Improve code style (constexpr + unions = avoid reinterpret_cast)
parent
ad0b26c5ec
commit
48dacd57bd
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue