From a1a68b4ad5471ff003ab1ed63bcc814340cd60b0 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Fri, 17 Jun 2022 09:43:48 +0200 Subject: [PATCH] Improve code style (constexpr + unions = avoid reinterpret_cast) --- src/application.cpp | 8 +++ src/application.h | 3 ++ src/registers.cpp | 118 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 109 insertions(+), 20 deletions(-) diff --git a/src/application.cpp b/src/application.cpp index 29464b5..28576d0 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -283,3 +283,11 @@ void Application::Step() { currentCommand->Step(); } + +uint8_t Application::CurrentProgressCode() { + return (uint8_t)currentCommand->State(); +} + +uint16_t Application::CurrentErrorCode() { + return (uint16_t)currentCommand->Error(); +} diff --git a/src/application.h b/src/application.h index 97ade21..aba5218 100644 --- a/src/application.h +++ b/src/application.h @@ -23,6 +23,9 @@ public: /// Perform one step of top level void Step(); + uint8_t CurrentProgressCode(); + uint16_t CurrentErrorCode(); + private: /// 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. diff --git a/src/registers.cpp b/src/registers.cpp index cdb708f..a84ae9f 100644 --- a/src/registers.cpp +++ b/src/registers.cpp @@ -1,38 +1,98 @@ #include "registers.h" #include "version.h" +#include "application.h" + +#include "modules/globals.h" +#include "modules/finda.h" +#include "modules/fsensor.h" struct RegisterFlags { 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 constexpr RegisterFlags(bool writable, uint8_t size) : writable(writable) - , eeprom(0) + , rwfuncs(0) , size(size) {} - constexpr RegisterFlags(bool writable, bool eeprom, uint8_t size) + constexpr RegisterFlags(bool writable, bool rwfuncs, uint8_t size) : writable(writable) - , eeprom(eeprom) + , rwfuncs(rwfuncs) , size(size) {} }; +using TReadFunc = uint16_t (*)(); +using TWriteFunc = void (*)(uint16_t); + struct RegisterRec { 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 constexpr RegisterRec(bool writable, T *address) : flags(RegisterFlags(writable, sizeof(T))) - , address((void *)address) {} - constexpr RegisterRec(bool writable, bool eeprom, void *eepromAddress, uint8_t bytes) - : flags(RegisterFlags(writable, eeprom, bytes)) - , address(eepromAddress) {} + , A1((void *)address) + , A2((void *)nullptr) {} + constexpr RegisterRec(TReadFunc readFunc, uint8_t bytes) + : 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[] = { 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); @@ -42,21 +102,30 @@ bool ReadRegister(uint8_t address, uint16_t &value) { return false; } value = 0; - if (!registers[address].flags.eeprom) { + if (!registers[address].flags.rwfuncs) { switch (registers[address].flags.size) { case 0: case 1: - value = *(uint8_t *)registers[address].address; + value = *(uint8_t *)registers[address].A1.addr; break; case 2: - value = *(uint16_t *)registers[address].address; + value = *(uint16_t *)registers[address].A1.addr; break; default: return false; } return true; } 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) { return false; } - if (!registers[address].flags.eeprom) { + if (!registers[address].flags.rwfuncs) { switch (registers[address].flags.size) { case 0: case 1: - *(uint8_t *)registers[address].address = value; + *(uint8_t *)registers[address].A1.addr = value; break; case 2: - *(uint16_t *)registers[address].address = value; + *(uint16_t *)registers[address].A1.addr = value; break; default: return false; } return true; } 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; } }