Improve code style (constexpr + unions = avoid reinterpret_cast)

pull/196/head
D.R.racer 2022-06-17 09:43:48 +02:00 committed by DRracer
parent ad0b26c5ec
commit 48dacd57bd
3 changed files with 109 additions and 20 deletions

View File

@ -283,3 +283,11 @@ void Application::Step() {
currentCommand->Step(); currentCommand->Step();
} }
uint8_t Application::CurrentProgressCode() {
return (uint8_t)currentCommand->State();
}
uint16_t Application::CurrentErrorCode() {
return (uint16_t)currentCommand->Error();
}

View File

@ -23,6 +23,9 @@ public:
/// Perform one step of top level /// Perform one step of top level
void Step(); void Step();
uint8_t CurrentProgressCode();
uint16_t CurrentErrorCode();
private: private:
/// Checks if the MMU can enter manual mode (user can move the selector with buttons) /// Checks if the MMU can enter manual mode (user can move the selector with buttons)
/// The MMU enters idle mode after 5s from the last command finished and there must be no filament present in the selector. /// The MMU enters idle mode after 5s from the last command finished and there must be no filament present in the selector.

View File

@ -1,38 +1,98 @@
#include "registers.h" #include "registers.h"
#include "version.h" #include "version.h"
#include "application.h"
#include "modules/globals.h"
#include "modules/finda.h"
#include "modules/fsensor.h"
struct RegisterFlags { struct RegisterFlags {
uint8_t writable : 1; uint8_t writable : 1;
uint8_t eeprom : 1; // 1: register is located in eeprom uint8_t rwfuncs : 1; // 1: register needs special read and write functions
uint8_t size : 2; // 0: 1 bit, 1: 1 byte, 2: 2 bytes uint8_t size : 2; // 0: 1 bit, 1: 1 byte, 2: 2 bytes
constexpr RegisterFlags(bool writable, uint8_t size) constexpr RegisterFlags(bool writable, uint8_t size)
: writable(writable) : writable(writable)
, eeprom(0) , rwfuncs(0)
, size(size) {} , size(size) {}
constexpr RegisterFlags(bool writable, bool eeprom, uint8_t size) constexpr RegisterFlags(bool writable, bool rwfuncs, uint8_t size)
: writable(writable) : writable(writable)
, eeprom(eeprom) , rwfuncs(rwfuncs)
, size(size) {} , size(size) {}
}; };
using TReadFunc = uint16_t (*)();
using TWriteFunc = void (*)(uint16_t);
struct RegisterRec { struct RegisterRec {
RegisterFlags flags; RegisterFlags flags;
void *address; union U1 {
void *addr;
TReadFunc readFunc;
constexpr explicit U1(TReadFunc r)
: readFunc(r) {}
constexpr explicit U1(void *a)
: addr(a) {}
} A1;
union U2 {
void *addr;
TWriteFunc writeFunc;
constexpr explicit U2(TWriteFunc w)
: writeFunc(w) {}
constexpr explicit U2(void *a)
: addr(a) {}
} A2;
template <typename T> template <typename T>
constexpr RegisterRec(bool writable, T *address) constexpr RegisterRec(bool writable, T *address)
: flags(RegisterFlags(writable, sizeof(T))) : flags(RegisterFlags(writable, sizeof(T)))
, address((void *)address) {} , A1((void *)address)
constexpr RegisterRec(bool writable, bool eeprom, void *eepromAddress, uint8_t bytes) , A2((void *)nullptr) {}
: flags(RegisterFlags(writable, eeprom, bytes)) constexpr RegisterRec(TReadFunc readFunc, uint8_t bytes)
, address(eepromAddress) {} : flags(RegisterFlags(false, true, bytes))
, A1(readFunc)
, A2((void *)nullptr) {}
constexpr RegisterRec(TReadFunc readFunc, TWriteFunc writeFunc, uint8_t bytes)
: flags(RegisterFlags(true, true, bytes))
, A1(readFunc)
, A2(writeFunc) {}
}; };
// @@TODO it is nice to see all the supported registers at one spot,
// however it requires including all bunch of dependencies
// which makes unit testing and separation of modules much harder.
static const RegisterRec registers[] = { static const RegisterRec registers[] = {
RegisterRec(false, &project_major), RegisterRec(false, &project_major),
RegisterRec(false, &project_minor),
RegisterRec(false, &project_build_number),
RegisterRec(false, true, (void *)0, 2), // @@TODO needs improvement
RegisterRec(false, &project_minor),
RegisterRec(false, &project_build_number),
RegisterRec( // MMU errors
[]() -> uint16_t { return mg::globals.DriveErrors(); },
[](uint16_t) {}, // @@TODO think about setting/clearing the error counter from the outside
2),
RegisterRec([]() -> uint16_t { return application.CurrentProgressCode(); }, 1),
RegisterRec([]() -> uint16_t { return application.CurrentErrorCode(); }, 2),
RegisterRec( // filamentState
[]() -> uint16_t { return mg::globals.FilamentLoaded(); },
[](uint16_t v) { return mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), (mg::FilamentLoadState)v); },
1),
RegisterRec( // FINDA
[]() -> uint16_t { return mf::finda.Pressed(); },
1),
RegisterRec( // fsensor
[]() -> uint16_t { return mfs::fsensor.Pressed(); },
[](uint16_t v) { return mfs::fsensor.ProcessMessage(v); },
1),
RegisterRec([]() -> uint16_t { return mg::globals.MotorsStealth(); }, 1), // mode (stealth = 1/normal = 0)
}; };
static constexpr uint8_t registersSize = sizeof(registers) / sizeof(RegisterRec); static constexpr uint8_t registersSize = sizeof(registers) / sizeof(RegisterRec);
@ -42,21 +102,30 @@ bool ReadRegister(uint8_t address, uint16_t &value) {
return false; return false;
} }
value = 0; value = 0;
if (!registers[address].flags.eeprom) { if (!registers[address].flags.rwfuncs) {
switch (registers[address].flags.size) { switch (registers[address].flags.size) {
case 0: case 0:
case 1: case 1:
value = *(uint8_t *)registers[address].address; value = *(uint8_t *)registers[address].A1.addr;
break; break;
case 2: case 2:
value = *(uint16_t *)registers[address].address; value = *(uint16_t *)registers[address].A1.addr;
break; break;
default: default:
return false; return false;
} }
return true; return true;
} else { } else {
return false; // @@TODO switch (registers[address].flags.size) {
case 0:
case 1:
case 2:
value = registers[address].A1.readFunc();
break;
default:
return false;
}
return true;
} }
} }
@ -67,20 +136,29 @@ bool WriteRegister(uint8_t address, uint16_t value) {
if (!registers[address].flags.writable) { if (!registers[address].flags.writable) {
return false; return false;
} }
if (!registers[address].flags.eeprom) { if (!registers[address].flags.rwfuncs) {
switch (registers[address].flags.size) { switch (registers[address].flags.size) {
case 0: case 0:
case 1: case 1:
*(uint8_t *)registers[address].address = value; *(uint8_t *)registers[address].A1.addr = value;
break; break;
case 2: case 2:
*(uint16_t *)registers[address].address = value; *(uint16_t *)registers[address].A1.addr = value;
break; break;
default: default:
return false; return false;
} }
return true; return true;
} else { } else {
return false; // @@TODO switch (registers[address].flags.size) {
case 0:
case 1:
case 2:
registers[address].A2.writeFunc(value);
break;
default:
return false;
}
return true;
} }
} }