diff --git a/CMakeLists.txt b/CMakeLists.txt index 326a896..239ae85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,7 +184,7 @@ target_include_directories(firmware PRIVATE include src) target_compile_options(firmware PRIVATE -Wdouble-promotion) target_sources( firmware PRIVATE src/main.cpp src/hal/avr/cpu.cpp src/hal/avr/usart.cpp src/modules/protocol.cpp - src/modules/buttons.cpp + src/modules/buttons.cpp src/modules/leds.cpp ) set_property( diff --git a/src/hal/adc.h b/src/hal/adc.h index 61a0f26..cd9cef6 100644 --- a/src/hal/adc.h +++ b/src/hal/adc.h @@ -4,10 +4,10 @@ /// Hardware Abstraction Layer for the ADC's namespace hal { -namespace ADC { +namespace adc { /// ADC access routines uint16_t ReadADC(uint8_t adc); -} // namespace ADC +} // namespace adc } // namespace hal diff --git a/src/hal/avr/cpu.cpp b/src/hal/avr/cpu.cpp index de23c60..991342c 100644 --- a/src/hal/avr/cpu.cpp +++ b/src/hal/avr/cpu.cpp @@ -1,7 +1,7 @@ #include "../cpu.h" namespace hal { -namespace CPU { +namespace cpu { void Init() { } diff --git a/src/hal/cpu.h b/src/hal/cpu.h index 1f7e2c0..880cc79 100644 --- a/src/hal/cpu.h +++ b/src/hal/cpu.h @@ -3,10 +3,10 @@ /// Hardware Abstraction Layer for the CPU namespace hal { -namespace CPU { +namespace cpu { /// CPU init routines (not really necessary for the AVR) void Init(); -} // namespace CPU +} // namespace cpu } // namespace hal diff --git a/src/main.cpp b/src/main.cpp index 9ccaf8a..cb72bca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,65 +1,135 @@ -#include "logic/mm_control.h" +#include "hal/cpu.h" +#include "hal/adc.h" #include "hal/gpio.h" #include "hal/spi.h" #include "hal/usart.h" + #include "pins.h" #include +#include "modules/buttons.h" +#include "modules/leds.h" +#include "modules/protocol.h" + +#include "logic/mm_control.h" + +static hal::UART uart; + +static modules::protocol::Protocol protocol; +static modules::buttons::Buttons buttons; +static modules::leds::LEDs leds; + +// examples and test code shall be located here +void TmpPlayground() { + using namespace hal; + + // SPI example + gpio::Init(gpio::GPIO_pin(GPIOC, 6), gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high)); + uint8_t dat[5]; + gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::low); + spi::TxRx(SPI0, 0x01); + spi::TxRx(SPI0, 0x00); + spi::TxRx(SPI0, 0x00); + spi::TxRx(SPI0, 0x00); + spi::TxRx(SPI0, 0x00); + gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::high); + gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::low); + dat[0] = spi::TxRx(SPI0, 0x00); + dat[1] = spi::TxRx(SPI0, 0x00); + dat[2] = spi::TxRx(SPI0, 0x00); + dat[3] = spi::TxRx(SPI0, 0x00); + dat[4] = spi::TxRx(SPI0, 0x00); + gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::high); + (void)dat; + + // using namespace hal::gpio; + // WritePin(GPIO_pin(GPIOB, 5), Level::low); + // TogglePin(GPIO_pin(GPIOB, 6)); + // if (hal::gpio::ReadPin(GPIO_pin(GPIOB, 7)) == hal::gpio::Level::low) + // break; + + sei(); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); + usart1.puts("1234567890\n"); +} + /// One-time setup of HW and SW components /// Called before entering the loop() function +/// Green LEDs signalize the progress of initialization. If anything goes wrong we shall turn on a red LED void setup() { using namespace hal; - // spi::SPI_InitTypeDef spi_conf = { - // .miso_pin = gpio::GPIO_pin(TMC2130_SPI_MISO_PIN), - // .mosi_pin = gpio::GPIO_pin(TMC2130_SPI_MOSI_PIN), - // .sck_pin = gpio::GPIO_pin(TMC2130_SPI_SCK_PIN), - // .ss_pin = gpio::GPIO_pin(TMC2130_SPI_SS_PIN), - // .prescaler = 2, //4mhz - // .cpha = 1, - // .cpol = 1, - // }; - // spi::Init(SPI0, &spi_conf); + cpu::Init(); - // // SPI example - // gpio::Init(gpio::GPIO_pin(GPIOC, 6), gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high)); - // uint8_t dat[5]; - // gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::low); - // spi::TxRx(SPI0, 0x01); - // spi::TxRx(SPI0, 0x00); - // spi::TxRx(SPI0, 0x00); - // spi::TxRx(SPI0, 0x00); - // spi::TxRx(SPI0, 0x00); - // gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::high); - // gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::low); - // dat[0] = spi::TxRx(SPI0, 0x00); - // dat[1] = spi::TxRx(SPI0, 0x00); - // dat[2] = spi::TxRx(SPI0, 0x00); - // dat[3] = spi::TxRx(SPI0, 0x00); - // dat[4] = spi::TxRx(SPI0, 0x00); - // gpio::WritePin(gpio::GPIO_pin(GPIOC, 6), gpio::Level::high); - // (void)dat; + // shr::Init() + leds.SetMode(4, false, modules::leds::Mode::blink0); + // shr::Send(leds.Step(0)); - USART::USART_InitTypeDef usart_conf = { + // @@TODO if the shift register doesn't work we really can't signalize anything, only internal variables will be accessible if the UART works + + USART::USART_InitTypeDef usart_conf = { .rx_pin = gpio::GPIO_pin(GPIOD, 2), .tx_pin = gpio::GPIO_pin(GPIOD, 3), .baudrate = 115200, - }; - usart1.Init(&usart_conf); - sei(); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - usart1.puts("1234567890\n"); - // usart1.Flush(); + + leds.SetMode(3, false, modules::leds::Mode::on); + // shr::Send(leds.Step(0)); + + // @@TODO if both shift register and the UART are dead, we are sitting ducks :( + + spi::SPI_InitTypeDef spi_conf = { + .miso_pin = gpio::GPIO_pin(TMC2130_SPI_MISO_PIN), + .mosi_pin = gpio::GPIO_pin(TMC2130_SPI_MOSI_PIN), + .sck_pin = gpio::GPIO_pin(TMC2130_SPI_SCK_PIN), + .ss_pin = gpio::GPIO_pin(TMC2130_SPI_SS_PIN), + .prescaler = 2, //4mhz + .cpha = 1, + .cpol = 1, + }; + spi::Init(SPI0, &spi_conf); + leds.SetMode(2, false, modules::leds::Mode::on); + //shr::Send(leds.Step(0)); + + // tmc::Init() + leds.SetMode(1, false, modules::leds::Mode::on); + //shr::Send(leds.Step(0)); + + // adc::Init(); + leds.SetMode(0, false, modules::leds::Mode::on); + //shr::Send(leds.Step(0)); +} + +void ProcessRequestMsg(const modules::protocol::RequestMsg &rq) { +} + +/// @returns true if a request was successfully finished +bool CheckMsgs() { + using mpd = modules::protocol::DecodeStatus; + while (!uart.ReadEmpty()) { + switch (protocol.DecodeRequest(uart.Read())) { + case mpd::MessageCompleted: + // process the input message + return true; + break; + case mpd::NeedMoreData: + // just continue reading + break; + case mpd::Error: + // what shall we do? Start some watchdog? + break; + } + } + return false; } /// Main loop of the firmware @@ -77,13 +147,16 @@ void setup() { /// The idea behind the Step* routines is to keep each automaton non-blocking allowing for some “concurrency”. /// Some FW components will leverage ISR to do their stuff (UART, motor stepping?, etc.) void loop() { + if (CheckMsgs()) { + ProcessRequestMsg(protocol.GetRequestMsg()); + } + buttons.Step(hal::adc::ReadADC(0)); + // shr.Send(leds.Step(0)); } int main() { setup(); for (;;) { - if (!usart1.ReadEmpty()) - usart1.Write(usart1.Read()); loop(); } return 0; diff --git a/src/modules/buttons.cpp b/src/modules/buttons.cpp index 70d726c..7ce76e1 100644 --- a/src/modules/buttons.cpp +++ b/src/modules/buttons.cpp @@ -1,72 +1,71 @@ #include "buttons.h" -#include "../hal/adc.h" namespace modules { +namespace buttons { -uint16_t Buttons::tmpTiming = 0; + uint16_t Buttons::tmpTiming = 0; -// original idea from: https://www.eeweb.com/debouncing-push-buttons-using-a-state-machine-approach -void Button::Step(uint16_t time, bool press) { - switch (f.state) { - case State::Waiting: - if (press) { - f.state = State::Detected; - timeLastChange = time; - f.tmp = press; - } - break; - case State::Detected: - if (f.tmp == press) { - if (time - timeLastChange > debounce) { - f.state = State::WaitForRelease; + // original idea from: https://www.eeweb.com/debouncing-push-buttons-using-a-state-machine-approach + void Button::Step(uint16_t time, bool press) { + switch (f.state) { + case State::Waiting: + if (press) { + f.state = State::Detected; + timeLastChange = time; + f.tmp = press; } - } else { + break; + case State::Detected: + if (f.tmp == press) { + if (time - timeLastChange > debounce) { + f.state = State::WaitForRelease; + } + } else { + f.state = State::Waiting; + } + break; + case State::WaitForRelease: + if (!press) { + f.state = State::Update; + } + break; + case State::Update: f.state = State::Waiting; + timeLastChange = time; + f.tmp = false; + break; + default: + f.state = State::Waiting; + timeLastChange = time; + f.tmp = false; } - break; - case State::WaitForRelease: - if (!press) { - f.state = State::Update; + } + + int8_t Buttons::Sample(uint16_t rawADC) { + // decode 3 buttons' levels from one ADC + // Button 1 - 0 + // Button 2 - 344 + // Button 3 - 516 + // Doesn't handle multiple pressed buttons at once + + if (rawADC < 10) + return 0; + else if (rawADC > 320 && rawADC < 360) + return 1; + else if (rawADC > 500 && rawADC < 530) + return 2; + return -1; + } + + void Buttons::Step(uint16_t rawADC) { + // @@TODO temporary timing + ++tmpTiming; + int8_t currentState = Sample(rawADC); + for (uint_fast8_t b = 0; b < N; ++b) { + // this button was pressed if b == currentState, released otherwise + buttons[b].Step(tmpTiming, b == currentState); } - break; - case State::Update: - f.state = State::Waiting; - timeLastChange = time; - f.tmp = false; - break; - default: - f.state = State::Waiting; - timeLastChange = time; - f.tmp = false; } -} - -int8_t Buttons::Sample() { - // decode 3 buttons' levels from one ADC - uint16_t raw = hal::ADC::ReadADC(0); - - // Button 1 - 0 - // Button 2 - 344 - // Button 3 - 516 - // Doesn't handle multiple pressed buttons at once - - if (raw < 10) - return 0; - else if (raw > 320 && raw < 360) - return 1; - else if (raw > 500 && raw < 530) - return 2; - return -1; -} - -void Buttons::Step() { - // @@TODO temporary timing - ++tmpTiming; - int8_t currentState = Sample(); - for (uint_fast8_t b = 0; b < N; ++b) { - // this button was pressed if b == currentState, released otherwise - buttons[b].Step(tmpTiming, b == currentState); - } -} +} // namespace buttons } // namespace modules diff --git a/src/modules/buttons.h b/src/modules/buttons.h index c3a3ea3..d20260e 100644 --- a/src/modules/buttons.h +++ b/src/modules/buttons.h @@ -7,67 +7,69 @@ /// This layer should contain debouncing of buttons and their logical interpretation namespace modules { +namespace buttons { -struct Button { - inline constexpr Button() - : timeLastChange(0) {} + struct Button { + inline constexpr Button() + : timeLastChange(0) {} - /// @returns true if button is currently considered as pressed - inline bool Pressed() const { return f.state == State::WaitForRelease; } + /// @returns true if button is currently considered as pressed + inline bool Pressed() const { return f.state == State::WaitForRelease; } - /// State machine stepping routine - void Step(uint16_t time, bool press); + /// State machine stepping routine + void Step(uint16_t time, bool press); -private: - /// time interval for debouncing @@TODO specify units - constexpr static const uint16_t debounce = 100; + private: + /// time interval for debouncing @@TODO specify units + constexpr static const uint16_t debounce = 100; - /// States of the debouncing automaton - /// Intentionally not modeled as an enum class - /// as it would impose additional casts which do not play well with the struct Flags - /// and would make the code less readable - enum State { Waiting = 0, - Detected, - WaitForRelease, - Update }; + /// States of the debouncing automaton + /// Intentionally not modeled as an enum class + /// as it would impose additional casts which do not play well with the struct Flags + /// and would make the code less readable + enum State { Waiting = 0, + Detected, + WaitForRelease, + Update }; - /// The sole purpose of this data struct is to save RAM by compressing several flags into one byte on the AVR - struct Flags { - uint8_t state : 2; ///< state of the button - uint8_t tmp : 1; ///< temporary state of button before the debouncing state machine finishes - inline constexpr Flags() - : state(State::Waiting) - , tmp(false) {} + /// The sole purpose of this data struct is to save RAM by compressing several flags into one byte on the AVR + struct Flags { + uint8_t state : 2; ///< state of the button + uint8_t tmp : 1; ///< temporary state of button before the debouncing state machine finishes + inline constexpr Flags() + : state(State::Waiting) + , tmp(false) {} + }; + + /// Flags and state of the debouncing automaton + Flags f; + + /// Timestamp of the last change of ADC state for this button + uint16_t timeLastChange; }; - /// Flags and state of the debouncing automaton - Flags f; + class Buttons { + constexpr static const uint8_t N = 3; ///< number of buttons currently supported + constexpr static const uint8_t adc = 1; ///< ADC index - will be some define or other constant later on + static uint16_t tmpTiming; ///< subject to removal when we have timers implemented - now used for the unit tests - /// Timestamp of the last change of ADC state for this button - uint16_t timeLastChange; -}; + public: + inline constexpr Buttons() = default; -class Buttons { - constexpr static const uint8_t N = 3; ///< number of buttons currently supported - constexpr static const uint8_t adc = 1; ///< ADC index - will be some define or other constant later on - static uint16_t tmpTiming; ///< subject to removal when we have timers implemented - now used for the unit tests + /// State machine step - reads the ADC, processes debouncing, updates states of individual buttons + void Step(uint16_t rawADC); -public: - inline constexpr Buttons() = default; + /// @return true if button at index is pressed + /// @@TODO add range checking if necessary + inline bool ButtonPressed(uint8_t index) const { return buttons[index].Pressed(); } - /// State machine step - reads the ADC, processes debouncing, updates states of individual buttons - void Step(); + private: + Button buttons[N]; - /// @return true if button at index is pressed - /// @@TODO add range checking if necessary - inline bool ButtonPressed(uint8_t index) const { return buttons[index].Pressed(); } - -private: - Button buttons[N]; - - /// Call to the ADC and decode its output into a button index - /// @returns index of the button pressed or -1 in case no button is pressed - static int8_t Sample(); -}; + /// Call to the ADC and decode its output into a button index + /// @returns index of the button pressed or -1 in case no button is pressed + static int8_t Sample(uint16_t rawADC); + }; +} // namespace buttons } // namespace modules diff --git a/src/modules/leds.cpp b/src/modules/leds.cpp new file mode 100644 index 0000000..c994d42 --- /dev/null +++ b/src/modules/leds.cpp @@ -0,0 +1,50 @@ +#include "leds.h" + +namespace modules { +namespace leds { + + void LED::SetMode(Mode mode) { + state.mode = mode; + // set initial state of LEDs correctly - transition from one mode to another + switch (state.mode) { + case Mode::blink1: + case Mode::off: + state.on = 0; + break; + + case Mode::blink0: + case Mode::on: + state.on = 1; + break; + default: + break; + } + } + + bool LED::Step(bool oddPeriod) { + switch (state.mode) { + // on and off don't change while stepping + case Mode::blink0: + state.on = oddPeriod; + break; + case Mode::blink1: + state.on = !oddPeriod; + break; + default: // do nothing + break; + } + } + + uint16_t LEDs::Step(uint8_t delta_ms) { + ms += delta_ms; + bool oddPeriod = ((ms / 1000U) & 0x01U) != 0; + uint16_t result = 0; + for (uint8_t i = 0; i < ledPairs * 2; ++i) { + result <<= 1; + result |= leds[i].Step(oddPeriod); + } + return result; + } + +} // namespace leds +} // namespace modules diff --git a/src/modules/leds.h b/src/modules/leds.h index 54041c7..d3168b4 100644 --- a/src/modules/leds.h +++ b/src/modules/leds.h @@ -1,3 +1,119 @@ #pragma once -/// @@TODO @leptun design some nice API ;) +#include + +/// We have 5 pairs of LEDs +/// In each pair there is a green and a red LED +/// +/// A typical scenario in the past was visualization of error states. +/// The combination of colors with blinking frequency had a specific meaning. +/// +/// We'd like to drive each pair? separately, which includes: +/// - blinking (none/slow/fast) +/// - what shall blink (red/green/both-at-once/both-interlaced) +/// +/// The physical connection is not important on this level (i.e. how and what shall be sent into the shift registers) + +namespace modules { +namespace leds { + + /// Mode of LED + /// blink0 and blink1 allow for interlaced blinking of LEDs (one is on and the other off) + enum Mode { + off, + on, + blink0, ///< start blinking at even periods + blink1 ///< start blinking at odd periods + }; + + /// a single LED + class LED { + public: + constexpr inline LED() = default; + void SetMode(Mode mode); + + /// @returns true if the LED shines + bool Step(bool oddPeriod); + inline bool On() const { return state.on; } + + private: + struct State { + uint8_t on : 1; + uint8_t mode : 2; + constexpr inline State() + : on(0) + , mode(Mode::off) {} + }; + + State state; + }; + + /// main LED API + class LEDs { + public: + constexpr inline LEDs() + : ms(0) {}; + + /// step LED automaton + /// @returns statuses of LEDs - one bit per LED and 1 = on, 0 = off + uint16_t Step(uint8_t delta_ms); + + inline constexpr uint8_t LedPairsCount() const { return ledPairs; } + + inline void SetMode(uint8_t slot, bool red, Mode mode) { + SetMode(slot * 2 + red, mode); + } + inline void SetMode(uint8_t index, Mode mode) { + leds[index].SetMode(mode); + } + + inline bool LedOn(uint8_t index) const { + return leds[index].On(); + } + inline bool LedOn(uint8_t slot, bool red) const { + return leds[slot * 2 + red].On(); + } + + private: + constexpr static const uint8_t ledPairs = 5; + LED leds[ledPairs * 2]; + uint16_t ms; + }; + + //// asi nechame moznost jednu blikat rychle a druhou pomalu + + //// tohle ale nevyresi, ze jedna LED ma blikat a druha svitit + + //// problem je, ze zapnuti/vypnuti led je blink none ... mozna by to chtelo blink none-on a none-off + //// jaka bude mnozina rezimu? + //// green-off green-on green-blink-slow green-blink-fast + //// red-off + + + + + //// red-on + + + + + //// red-blink-slow + + 2 x + //// red-blink-fast + + x 2 + //// + //// rezim 2 muze mit jeste varianty - blink-sync, blink-interlaced, coz v podstate znamena rezimy: + //// blink-slow1, blink-slow2, blink-fast1, blink-fast2, pricemz nemaji smysl kombinace: + //// blink-slow + blink-fast + + //// revize + //// v aktualnim FW led jen blikaji jednou rychlosti + //// takze to spis udelam jako pole LED, pricemz cervene budou na sudych a zelene na lichych indexech + //// stav ledky bude: off, on, blink0 a blink1 + //// blink0 znamena zacni pocitat blikaci interval od sude periody + //// blink1 od liche + //// tim pujde zmodelovat jak sync tak async blikani + //// Dale je otazka, jestli chceme rychle a pomale blikani... asi ne, kdyz bude report na LCD tiskarny + + //// Dale castecne souvisejici + //// Start MMU by mel reportovat progress, pricemz aktualni stav je takovy, ze nabihaji LED a kazda neco znamena + //// Tiskarna by klidne mohla posilat Q a dostavat odpoved ve stylu "starting" a progress/state code + //// + //// Mozna taky budeme potrebovat nastavovat ruzne vnitrni promenne (treba use slots 1-3 namisto 0-4), takze operace SetVar a k tomu obracena GetVar + //// Dava mi smysl modifikovat protokol V jako getvar (zamerne ne G, aby to nekolidovalo s gcodes) a S jako setvar + //// cislo je index variable a odpovi se A_hodnota, cili accepted a hodnota odpovedi + + //void SetLEDs(uint8_t slot0, uint8_t slot1, uint8_t slot2, uint8_t slot3, uint8_t slot4); + +} // namespace LEDs +} // namespace modules diff --git a/src/modules/protocol.cpp b/src/modules/protocol.cpp index 893e039..356a30e 100644 --- a/src/modules/protocol.cpp +++ b/src/modules/protocol.cpp @@ -11,198 +11,178 @@ // F : operation finished - will be repeated to "Q" messages until a new command is issued namespace modules { +namespace protocol { -// decoding automaton -// states: input -> transition into state -// Code QTLMUXPSBEWK -> msgcode -// \n ->start -// * ->error -// error \n ->start -// * ->error -// msgcode 0-9 ->msgvalue -// * ->error -// msgvalue 0-9 ->msgvalue -// \n ->start successfully accepted command + // decoding automaton + // states: input -> transition into state + // Code QTLMUXPSBEWK -> msgcode + // \n ->start + // * ->error + // error \n ->start + // * ->error + // msgcode 0-9 ->msgvalue + // * ->error + // msgvalue 0-9 ->msgvalue + // \n ->start successfully accepted command -Protocol::DecodeStatus Protocol::DecodeRequest(uint8_t c) { - switch (rqState) { - case RequestStates::Code: - switch (c) { - case 'Q': - case 'T': - case 'L': - case 'M': - case 'U': - case 'X': - case 'P': - case 'S': - case 'B': - case 'E': - case 'W': - case 'K': - requestMsg.code = (RequestMsgCodes)c; - requestMsg.value = 0; - rqState = RequestStates::Value; - return DecodeStatus::NeedMoreData; - default: - requestMsg.code = RequestMsgCodes::unknown; - rqState = RequestStates::Error; - return DecodeStatus::Error; - } - case RequestStates::Value: - if (c >= '0' && c <= '9') { - requestMsg.value *= 10; - requestMsg.value += c - '0'; - return DecodeStatus::NeedMoreData; - } else if (c == '\n') { - rqState = RequestStates::Code; - return DecodeStatus::MessageCompleted; - } else { - requestMsg.code = RequestMsgCodes::unknown; - rqState = RequestStates::Error; - return DecodeStatus::Error; - } - default: //case error: - if (c == '\n') { - rqState = RequestStates::Code; - return DecodeStatus::MessageCompleted; - } else { - requestMsg.code = RequestMsgCodes::unknown; - rqState = RequestStates::Error; - return DecodeStatus::Error; + DecodeStatus Protocol::DecodeRequest(uint8_t c) { + switch (rqState) { + case RequestStates::Code: + switch (c) { + case 'Q': + case 'T': + case 'L': + case 'M': + case 'U': + case 'X': + case 'P': + case 'S': + case 'B': + case 'E': + case 'W': + case 'K': + requestMsg.code = (RequestMsgCodes)c; + requestMsg.value = 0; + rqState = RequestStates::Value; + return DecodeStatus::NeedMoreData; + default: + requestMsg.code = RequestMsgCodes::unknown; + rqState = RequestStates::Error; + return DecodeStatus::Error; + } + case RequestStates::Value: + if (c >= '0' && c <= '9') { + requestMsg.value *= 10; + requestMsg.value += c - '0'; + return DecodeStatus::NeedMoreData; + } else if (c == '\n') { + rqState = RequestStates::Code; + return DecodeStatus::MessageCompleted; + } else { + requestMsg.code = RequestMsgCodes::unknown; + rqState = RequestStates::Error; + return DecodeStatus::Error; + } + default: //case error: + if (c == '\n') { + rqState = RequestStates::Code; + return DecodeStatus::MessageCompleted; + } else { + requestMsg.code = RequestMsgCodes::unknown; + rqState = RequestStates::Error; + return DecodeStatus::Error; + } } } -} -uint8_t Protocol::EncodeRequest(const RequestMsg &msg, uint8_t *txbuff) { - txbuff[0] = (uint8_t)msg.code; - txbuff[1] = msg.value + '0'; - txbuff[2] = '\n'; - return 3; -} + uint8_t Protocol::EncodeRequest(const RequestMsg &msg, uint8_t *txbuff) { + txbuff[0] = (uint8_t)msg.code; + txbuff[1] = msg.value + '0'; + txbuff[2] = '\n'; + return 3; + } -Protocol::DecodeStatus Protocol::DecodeResponse(uint8_t c) { - switch (rspState) { - case ResponseStates::RequestCode: - switch (c) { - case 'Q': - case 'T': - case 'L': - case 'M': - case 'U': - case 'X': - case 'P': - case 'S': - case 'B': - case 'E': - case 'W': - case 'K': - responseMsg.request.code = (RequestMsgCodes)c; - responseMsg.request.value = 0; - rspState = ResponseStates::RequestValue; - return DecodeStatus::NeedMoreData; - default: - rspState = ResponseStates::Error; - return DecodeStatus::Error; - } - case ResponseStates::RequestValue: - if (c >= '0' && c <= '9') { - responseMsg.request.value *= 10; - responseMsg.request.value += c - '0'; - return DecodeStatus::NeedMoreData; - } else if (c == ' ') { - rspState = ResponseStates::ParamCode; - return DecodeStatus::NeedMoreData; - } else { - rspState = ResponseStates::Error; - return DecodeStatus::Error; - } - case ResponseStates::ParamCode: - switch (c) { - case 'P': - case 'E': - case 'F': - case 'A': - case 'R': - rspState = ResponseStates::ParamValue; - responseMsg.paramCode = (ResponseMsgParamCodes)c; - responseMsg.paramValue = 0; - return DecodeStatus::NeedMoreData; - default: - responseMsg.paramCode = ResponseMsgParamCodes::unknown; - rspState = ResponseStates::Error; - return DecodeStatus::Error; - } - case ResponseStates::ParamValue: - if (c >= '0' && c <= '9') { - responseMsg.paramValue *= 10; - responseMsg.paramValue += c - '0'; - return DecodeStatus::NeedMoreData; - } else if (c == '\n') { - rspState = ResponseStates::RequestCode; - return DecodeStatus::MessageCompleted; - } else { - responseMsg.paramCode = ResponseMsgParamCodes::unknown; - rspState = ResponseStates::Error; - return DecodeStatus::Error; - } - default: //case error: - if (c == '\n') { - rspState = ResponseStates::RequestCode; - return DecodeStatus::MessageCompleted; - } else { - responseMsg.paramCode = ResponseMsgParamCodes::unknown; - return DecodeStatus::Error; + DecodeStatus Protocol::DecodeResponse(uint8_t c) { + switch (rspState) { + case ResponseStates::RequestCode: + switch (c) { + case 'Q': + case 'T': + case 'L': + case 'M': + case 'U': + case 'X': + case 'P': + case 'S': + case 'B': + case 'E': + case 'W': + case 'K': + responseMsg.request.code = (RequestMsgCodes)c; + responseMsg.request.value = 0; + rspState = ResponseStates::RequestValue; + return DecodeStatus::NeedMoreData; + default: + rspState = ResponseStates::Error; + return DecodeStatus::Error; + } + case ResponseStates::RequestValue: + if (c >= '0' && c <= '9') { + responseMsg.request.value *= 10; + responseMsg.request.value += c - '0'; + return DecodeStatus::NeedMoreData; + } else if (c == ' ') { + rspState = ResponseStates::ParamCode; + return DecodeStatus::NeedMoreData; + } else { + rspState = ResponseStates::Error; + return DecodeStatus::Error; + } + case ResponseStates::ParamCode: + switch (c) { + case 'P': + case 'E': + case 'F': + case 'A': + case 'R': + rspState = ResponseStates::ParamValue; + responseMsg.paramCode = (ResponseMsgParamCodes)c; + responseMsg.paramValue = 0; + return DecodeStatus::NeedMoreData; + default: + responseMsg.paramCode = ResponseMsgParamCodes::unknown; + rspState = ResponseStates::Error; + return DecodeStatus::Error; + } + case ResponseStates::ParamValue: + if (c >= '0' && c <= '9') { + responseMsg.paramValue *= 10; + responseMsg.paramValue += c - '0'; + return DecodeStatus::NeedMoreData; + } else if (c == '\n') { + rspState = ResponseStates::RequestCode; + return DecodeStatus::MessageCompleted; + } else { + responseMsg.paramCode = ResponseMsgParamCodes::unknown; + rspState = ResponseStates::Error; + return DecodeStatus::Error; + } + default: //case error: + if (c == '\n') { + rspState = ResponseStates::RequestCode; + return DecodeStatus::MessageCompleted; + } else { + responseMsg.paramCode = ResponseMsgParamCodes::unknown; + return DecodeStatus::Error; + } } } -} -uint8_t Protocol::EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff) { - txbuff[0] = (uint8_t)msg.code; - txbuff[1] = msg.value + '0'; - txbuff[2] = ' '; - txbuff[3] = (uint8_t)ar; - txbuff[4] = '\n'; - return 5; -} - -uint8_t Protocol::EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff) { - txbuff[0] = (uint8_t)msg.code; - txbuff[1] = msg.value + '0'; - txbuff[2] = ' '; - txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted; - txbuff[4] = findaValue + '0'; - txbuff[5] = '\n'; - return 6; -} - -uint8_t Protocol::EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff) { - txbuff[0] = (uint8_t)msg.code; - txbuff[1] = msg.value + '0'; - txbuff[2] = ' '; - txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted; - uint8_t *dst = txbuff + 4; - if (value < 10) { - *dst++ = value + '0'; - } else if (value < 100) { - *dst++ = value / 10 + '0'; - *dst++ = value % 10 + '0'; - } else { - *dst++ = value / 100 + '0'; - *dst++ = (value / 10) % 10 + '0'; - *dst++ = value % 10 + '0'; + uint8_t Protocol::EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff) { + txbuff[0] = (uint8_t)msg.code; + txbuff[1] = msg.value + '0'; + txbuff[2] = ' '; + txbuff[3] = (uint8_t)ar; + txbuff[4] = '\n'; + return 5; } - *dst = '\n'; - return dst - txbuff + 1; -} -uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff) { - txbuff[0] = (uint8_t)msg.code; - txbuff[1] = msg.value + '0'; - txbuff[2] = ' '; - txbuff[3] = (uint8_t)code; - uint8_t *dst = txbuff + 4; - if (code != ResponseMsgParamCodes::Finished) { + uint8_t Protocol::EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff) { + txbuff[0] = (uint8_t)msg.code; + txbuff[1] = msg.value + '0'; + txbuff[2] = ' '; + txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted; + txbuff[4] = findaValue + '0'; + txbuff[5] = '\n'; + return 6; + } + + uint8_t Protocol::EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff) { + txbuff[0] = (uint8_t)msg.code; + txbuff[1] = msg.value + '0'; + txbuff[2] = ' '; + txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted; + uint8_t *dst = txbuff + 4; if (value < 10) { *dst++ = value + '0'; } else if (value < 100) { @@ -213,9 +193,31 @@ uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMs *dst++ = (value / 10) % 10 + '0'; *dst++ = value % 10 + '0'; } + *dst = '\n'; + return dst - txbuff + 1; } - *dst = '\n'; - return dst - txbuff + 1; -} + uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff) { + txbuff[0] = (uint8_t)msg.code; + txbuff[1] = msg.value + '0'; + txbuff[2] = ' '; + txbuff[3] = (uint8_t)code; + uint8_t *dst = txbuff + 4; + if (code != ResponseMsgParamCodes::Finished) { + if (value < 10) { + *dst++ = value + '0'; + } else if (value < 100) { + *dst++ = value / 10 + '0'; + *dst++ = value % 10 + '0'; + } else { + *dst++ = value / 100 + '0'; + *dst++ = (value / 10) % 10 + '0'; + *dst++ = value % 10 + '0'; + } + } + *dst = '\n'; + return dst - txbuff + 1; + } + +} // namespace protocol } // namespace modules diff --git a/src/modules/protocol.h b/src/modules/protocol.h index 0f01a76..98a8d61 100644 --- a/src/modules/protocol.h +++ b/src/modules/protocol.h @@ -7,60 +7,56 @@ /// @@TODO possibly add some checksum to verify the correctness of messages namespace modules { +namespace protocol { -enum class RequestMsgCodes : uint8_t { - unknown = 0, - Query = 'Q', - Tool = 'T', - Load = 'L', - Mode = 'M', - Unload = 'U', - Reset = 'X', - Finda = 'P', - Version = 'S', - Button = 'B', - Eject = 'E', - Wait = 'W', - Cut = 'K' -}; + enum class RequestMsgCodes : uint8_t { + unknown = 0, + Query = 'Q', + Tool = 'T', + Load = 'L', + Mode = 'M', + Unload = 'U', + Reset = 'X', + Finda = 'P', + Version = 'S', + Button = 'B', + Eject = 'E', + Wait = 'W', + Cut = 'K' + }; -enum class ResponseMsgParamCodes : uint8_t { - unknown = 0, - Processing = 'P', - Error = 'E', - Finished = 'F', - Accepted = 'A', - Rejected = 'R' -}; + enum class ResponseMsgParamCodes : uint8_t { + unknown = 0, + Processing = 'P', + Error = 'E', + Finished = 'F', + Accepted = 'A', + Rejected = 'R' + }; -/// A request message -/// Requests are being sent by the printer into the MMU -/// It is the same structure as the generic Msg -struct RequestMsg { - RequestMsgCodes code; - uint8_t value; - inline RequestMsg(RequestMsgCodes code, uint8_t value) - : code(code) - , value(value) {} -}; + /// A request message + /// Requests are being sent by the printer into the MMU + /// It is the same structure as the generic Msg + struct RequestMsg { + RequestMsgCodes code; + uint8_t value; + inline RequestMsg(RequestMsgCodes code, uint8_t value) + : code(code) + , value(value) {} + }; -/// A response message -/// Responses are being sent from the MMU into the printer as a response to a request message -struct ResponseMsg { - RequestMsg request; ///< response is always preceeded by the request message - ResponseMsgParamCodes paramCode; ///< parameters of reply - uint8_t paramValue; ///< parameters of reply - inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue) - : request(request) - , paramCode(paramCode) - , paramValue(paramValue) {} -}; + /// A response message + /// Responses are being sent from the MMU into the printer as a response to a request message + struct ResponseMsg { + RequestMsg request; ///< response is always preceeded by the request message + ResponseMsgParamCodes paramCode; ///< parameters of reply + uint8_t paramValue; ///< parameters of reply + inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue) + : request(request) + , paramCode(paramCode) + , paramValue(paramValue) {} + }; -/// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer -/// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods -/// processing one input byte per call -class Protocol { -public: /// Message decoding return value enum class DecodeStatus : uint_fast8_t { MessageCompleted, ///< message completed and successfully lexed @@ -68,76 +64,82 @@ public: Error, ///< input character broke message decoding }; - inline Protocol() - : rqState(RequestStates::Code) - , requestMsg(RequestMsgCodes::unknown, 0) - , rspState(ResponseStates::RequestCode) - , responseMsg(RequestMsg(RequestMsgCodes::unknown, 0), ResponseMsgParamCodes::unknown, 0) { - } + /// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer + /// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods + /// processing one input byte per call + class Protocol { + public: + inline Protocol() + : rqState(RequestStates::Code) + , requestMsg(RequestMsgCodes::unknown, 0) + , rspState(ResponseStates::RequestCode) + , responseMsg(RequestMsg(RequestMsgCodes::unknown, 0), ResponseMsgParamCodes::unknown, 0) { + } - /// Takes the input byte c and steps one step through the state machine - /// @returns state of the message being decoded - DecodeStatus DecodeRequest(uint8_t c); + /// Takes the input byte c and steps one step through the state machine + /// @returns state of the message being decoded + DecodeStatus DecodeRequest(uint8_t c); - /// Decodes response message in rxbuff - /// @returns decoded response message structure - DecodeStatus DecodeResponse(uint8_t c); + /// Decodes response message in rxbuff + /// @returns decoded response message structure + DecodeStatus DecodeResponse(uint8_t c); - /// Encodes request message msg into txbuff memory - /// It is expected the txbuff is large enough to fit the message - /// @returns number of bytes written into txbuff - static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff); + /// Encodes request message msg into txbuff memory + /// It is expected the txbuff is large enough to fit the message + /// @returns number of bytes written into txbuff + static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff); - /// Encode generic response Command Accepted or Rejected - /// @param msg source request message for this response - /// @returns number of bytes written into txbuff - static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff); + /// Encode generic response Command Accepted or Rejected + /// @param msg source request message for this response + /// @returns number of bytes written into txbuff + static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff); - /// Encode response to Read FINDA query - /// @param msg source request message for this response - /// @param findaValue 1/0 (on/off) status of FINDA - /// @returns number of bytes written into txbuff - static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff); + /// Encode response to Read FINDA query + /// @param msg source request message for this response + /// @param findaValue 1/0 (on/off) status of FINDA + /// @returns number of bytes written into txbuff + static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff); - /// Encode response to Version query - /// @param msg source request message for this response - /// @param value version number (0-255) - /// @returns number of bytes written into txbuff - static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff); + /// Encode response to Version query + /// @param msg source request message for this response + /// @param value version number (0-255) + /// @returns number of bytes written into txbuff + static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff); - /// Encode response to Query operation status - /// @param msg source request message for this response - /// @param code status of operation (Processing, Error, Finished) - /// @param value related to status of operation(e.g. error code or progress) - /// @returns number of bytes written into txbuff - static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff); + /// Encode response to Query operation status + /// @param msg source request message for this response + /// @param code status of operation (Processing, Error, Finished) + /// @param value related to status of operation(e.g. error code or progress) + /// @returns number of bytes written into txbuff + static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff); - /// @returns the most recently lexed request message - inline const RequestMsg GetRequestMsg() const { return requestMsg; } + /// @returns the most recently lexed request message + inline const RequestMsg GetRequestMsg() const { return requestMsg; } - /// @returns the most recently lexed response message - inline const ResponseMsg GetResponseMsg() const { return responseMsg; } + /// @returns the most recently lexed response message + inline const ResponseMsg GetResponseMsg() const { return responseMsg; } -private: - enum class RequestStates : uint8_t { - Code, ///< starting state - expects message code - Value, ///< expecting code value - Error ///< automaton in error state + private: + enum class RequestStates : uint8_t { + Code, ///< starting state - expects message code + Value, ///< expecting code value + Error ///< automaton in error state + }; + + RequestStates rqState; + RequestMsg requestMsg; + + enum class ResponseStates : uint8_t { + RequestCode, ///< starting state - expects message code + RequestValue, ///< expecting code value + ParamCode, ///< expecting param code + ParamValue, ///< expecting param value + Error ///< automaton in error state + }; + + ResponseStates rspState; + ResponseMsg responseMsg; }; - RequestStates rqState; - RequestMsg requestMsg; - - enum class ResponseStates : uint8_t { - RequestCode, ///< starting state - expects message code - RequestValue, ///< expecting code value - ParamCode, ///< expecting param code - ParamValue, ///< expecting param value - Error ///< automaton in error state - }; - - ResponseStates rspState; - ResponseMsg responseMsg; -}; - +} // namespace protocol } // namespace modules diff --git a/tests/unit/modules/buttons/stub_adc.cpp b/tests/unit/modules/buttons/stub_adc.cpp index c6edfa3..5006f68 100644 --- a/tests/unit/modules/buttons/stub_adc.cpp +++ b/tests/unit/modules/buttons/stub_adc.cpp @@ -3,7 +3,7 @@ #include namespace hal { -namespace ADC { +namespace adc { static TADCData values2Return; static TADCData::const_iterator rdptr = values2Return.cbegin(); @@ -28,5 +28,5 @@ namespace ADC { return rdptr != values2Return.end() ? *rdptr : 1023; } -} // namespace ADC +} // namespace adc } // namespace hal diff --git a/tests/unit/modules/buttons/stub_adc.h b/tests/unit/modules/buttons/stub_adc.h index 7105f01..ae3b658 100644 --- a/tests/unit/modules/buttons/stub_adc.h +++ b/tests/unit/modules/buttons/stub_adc.h @@ -4,11 +4,11 @@ #include namespace hal { -namespace ADC { +namespace adc { using TADCData = std::vector; void ReinitADC(TADCData &&d, uint8_t ovsmpl); -} // namespace ADC +} // namespace adc } // namespace hal diff --git a/tests/unit/modules/buttons/test_buttons.cpp b/tests/unit/modules/buttons/test_buttons.cpp index ded5db0..261edf9 100644 --- a/tests/unit/modules/buttons/test_buttons.cpp +++ b/tests/unit/modules/buttons/test_buttons.cpp @@ -4,21 +4,21 @@ using Catch::Matchers::Equals; -bool Step_Basic_One_Button_Test(modules::Buttons &b, uint8_t oversampleFactor, uint8_t testedButtonIndex, uint8_t otherButton1, uint8_t otherButton2) { +bool Step_Basic_One_Button_Test(modules::buttons::Buttons &b, uint8_t oversampleFactor, uint8_t testedButtonIndex, uint8_t otherButton1, uint8_t otherButton2) { for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // should detect the press but remain in detected state - wait for debounce + b.Step(hal::adc::ReadADC(0)); // should detect the press but remain in detected state - wait for debounce CHECK(!b.ButtonPressed(testedButtonIndex)); CHECK(!b.ButtonPressed(otherButton1)); CHECK(!b.ButtonPressed(otherButton2)); for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // reset to waiting + b.Step(hal::adc::ReadADC(0)); // reset to waiting CHECK(b.ButtonPressed(testedButtonIndex)); CHECK(!b.ButtonPressed(otherButton1)); CHECK(!b.ButtonPressed(otherButton2)); for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // pressed again, still in debouncing state + b.Step(hal::adc::ReadADC(0)); // pressed again, still in debouncing state CHECK(!b.ButtonPressed(testedButtonIndex)); CHECK(!b.ButtonPressed(otherButton1)); CHECK(!b.ButtonPressed(otherButton2)); @@ -27,14 +27,14 @@ bool Step_Basic_One_Button_Test(modules::Buttons &b, uint8_t oversampleFactor, u } /// This test verifies the behaviour of a single button. The other buttons must remain intact. -bool Step_Basic_One_Button(hal::ADC::TADCData &&d, uint8_t testedButtonIndex) { - using namespace modules; +bool Step_Basic_One_Button(hal::adc::TADCData &&d, uint8_t testedButtonIndex) { + using namespace modules::buttons; Buttons b; // need to oversample the data as debouncing takes 100 cycles to accept a pressed button constexpr uint8_t oversampleFactor = 100; - hal::ADC::ReinitADC(std::move(d), oversampleFactor); + hal::adc::ReinitADC(std::move(d), oversampleFactor); uint8_t otherButton1 = 1, otherButton2 = 2; switch (testedButtonIndex) { @@ -53,15 +53,15 @@ bool Step_Basic_One_Button(hal::ADC::TADCData &&d, uint8_t testedButtonIndex) { TEST_CASE("buttons::Step-basic-button", "[buttons]") { { - hal::ADC::TADCData d({ 5, 6, 1023 }); + hal::adc::TADCData d({ 5, 6, 1023 }); CHECK(Step_Basic_One_Button(std::move(d), 0)); } { - hal::ADC::TADCData d({ 321, 359, 1023 }); + hal::adc::TADCData d({ 321, 359, 1023 }); CHECK(Step_Basic_One_Button(std::move(d), 1)); } { - hal::ADC::TADCData d({ 501, 529, 1023 }); + hal::adc::TADCData d({ 501, 529, 1023 }); CHECK(Step_Basic_One_Button(std::move(d), 2)); } } @@ -70,13 +70,13 @@ TEST_CASE("buttons::Step-basic-button", "[buttons]") { /// and the Buttons class should press first button and release, then the second one and then the third one /// without being reinitialized. TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") { - using namespace modules; - hal::ADC::TADCData d({ 5, 6, 1023, 321, 359, 1023, 501, 529, 1023 }); + using namespace modules::buttons; + hal::adc::TADCData d({ 5, 6, 1023, 321, 359, 1023, 501, 529, 1023 }); Buttons b; // need to oversample the data as debouncing takes 100 cycles to accept a pressed button constexpr uint8_t oversampleFactor = 100; - hal::ADC::ReinitADC(std::move(d), oversampleFactor); + hal::adc::ReinitADC(std::move(d), oversampleFactor); CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 0, 1, 2)); CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 1, 0, 2)); @@ -85,76 +85,76 @@ TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") { /// This test tries to simulate a bouncing effect on data from ADC on the first button TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") { - using namespace modules; + using namespace modules::buttons; // make a bounce event on the first press - hal::ADC::TADCData d({ 5, 1023, 5, 9, 6, 7, 8, 1023, 1023 }); + hal::adc::TADCData d({ 5, 1023, 5, 9, 6, 7, 8, 1023, 1023 }); // need to oversample the data as debouncing takes 100 cycles to accept a pressed button constexpr uint8_t oversampleFactor = 25; - hal::ADC::ReinitADC(std::move(d), oversampleFactor); + hal::adc::ReinitADC(std::move(d), oversampleFactor); Buttons b; // 5 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // should detect the press but remain in detected state - wait for debounce + b.Step(hal::adc::ReadADC(0)); // should detect the press but remain in detected state - wait for debounce CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 1023 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // reset to waiting + b.Step(hal::adc::ReadADC(0)); // reset to waiting CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 5 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // pressed again, still in debouncing state + b.Step(hal::adc::ReadADC(0)); // pressed again, still in debouncing state CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 9 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // no change + b.Step(hal::adc::ReadADC(0)); // no change CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 6 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // no change + b.Step(hal::adc::ReadADC(0)); // no change CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 7 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // one step from "pressed" + b.Step(hal::adc::ReadADC(0)); // one step from "pressed" CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 8 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // fifth set of samples - should report "pressed" finally + b.Step(hal::adc::ReadADC(0)); // fifth set of samples - should report "pressed" finally CHECK(b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 1023 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // sixth set of samples - button released (no debouncing on release) + b.Step(hal::adc::ReadADC(0)); // sixth set of samples - button released (no debouncing on release) CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); // 1023 for (uint8_t i = 0; i < oversampleFactor; ++i) - b.Step(); // seventh set of samples - still released + b.Step(hal::adc::ReadADC(0)); // seventh set of samples - still released CHECK(!b.ButtonPressed(0)); CHECK(!b.ButtonPressed(1)); CHECK(!b.ButtonPressed(2)); diff --git a/tests/unit/modules/protocol/test_protocol.cpp b/tests/unit/modules/protocol/test_protocol.cpp index a134428..a2e461d 100644 --- a/tests/unit/modules/protocol/test_protocol.cpp +++ b/tests/unit/modules/protocol/test_protocol.cpp @@ -4,7 +4,7 @@ using Catch::Matchers::Equals; TEST_CASE("protocol::EncodeRequests", "[protocol]") { - using namespace modules; + using namespace modules::protocol; RequestMsgCodes code; uint8_t value; @@ -45,7 +45,7 @@ TEST_CASE("protocol::EncodeRequests", "[protocol]") { } TEST_CASE("protocol::EncodeResponseCmdAR", "[protocol]") { - using namespace modules; + using namespace modules::protocol; auto requestMsg = GENERATE( RequestMsg(RequestMsgCodes::Button, 0), @@ -93,7 +93,7 @@ TEST_CASE("protocol::EncodeResponseCmdAR", "[protocol]") { } TEST_CASE("protocol::EncodeResponseReadFINDA", "[protocol]") { - using namespace modules; + using namespace modules::protocol; auto requestMsg = RequestMsg(RequestMsgCodes::Finda, 0); uint8_t findaStatus = GENERATE(0, 1); @@ -111,7 +111,7 @@ TEST_CASE("protocol::EncodeResponseReadFINDA", "[protocol]") { } TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") { - using namespace modules; + using namespace modules::protocol; std::uint8_t versionQueryType = GENERATE(0, 1, 2, 3); auto requestMsg = RequestMsg(RequestMsgCodes::Version, versionQueryType); @@ -142,7 +142,7 @@ TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") { } TEST_CASE("protocol::EncodeResponseQueryOperation", "[protocol]") { - using namespace modules; + using namespace modules::protocol; auto requestMsg = GENERATE( RequestMsg(RequestMsgCodes::Cut, 0), @@ -202,7 +202,7 @@ TEST_CASE("protocol::EncodeResponseQueryOperation", "[protocol]") { } TEST_CASE("protocol::DecodeRequest", "[protocol]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char *rxbuff = GENERATE( "B0\n", "B1\n", "B2\n", @@ -226,9 +226,9 @@ TEST_CASE("protocol::DecodeRequest", "[protocol]") { break; } else if (c == '\n') { // regular end of message line - CHECK(p.DecodeRequest(c) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest(c) == DecodeStatus::MessageCompleted); } else { - CHECK(p.DecodeRequest(c) == Protocol::DecodeStatus::NeedMoreData); + CHECK(p.DecodeRequest(c) == DecodeStatus::NeedMoreData); } } @@ -239,7 +239,7 @@ TEST_CASE("protocol::DecodeRequest", "[protocol]") { } TEST_CASE("protocol::DecodeResponseReadFinda", "[protocol]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char *rxbuff = GENERATE( "P0 A0\n", @@ -253,9 +253,9 @@ TEST_CASE("protocol::DecodeResponseReadFinda", "[protocol]") { break; } else if (c == '\n') { // regular end of message line - CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeResponse(c) == DecodeStatus::MessageCompleted); } else { - CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::NeedMoreData); + CHECK(p.DecodeResponse(c) == DecodeStatus::NeedMoreData); } } @@ -268,7 +268,7 @@ TEST_CASE("protocol::DecodeResponseReadFinda", "[protocol]") { } TEST_CASE("protocol::DecodeResponseQueryOperation", "[protocol]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char *cmdReference = GENERATE( "E0", "E1", "E2", "E3", "E4", @@ -294,9 +294,9 @@ TEST_CASE("protocol::DecodeResponseQueryOperation", "[protocol]") { break; } else if (c == '\n') { // regular end of message line - CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeResponse(c) == DecodeStatus::MessageCompleted); } else { - CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::NeedMoreData); + CHECK(p.DecodeResponse(c) == DecodeStatus::NeedMoreData); } } @@ -311,81 +311,81 @@ TEST_CASE("protocol::DecodeResponseQueryOperation", "[protocol]") { } TEST_CASE("protocol::DecodeRequestErrors", "[protocol]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char b0[] = "b0"; - CHECK(p.DecodeRequest(b0[0]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[0]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b0[1]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[1]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); // reset protokol decoder - CHECK(p.DecodeRequest('\n') == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest('\n') == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); const char B1_[] = "B1 \n"; - CHECK(p.DecodeRequest(B1_[0]) == Protocol::DecodeStatus::NeedMoreData); - CHECK(p.DecodeRequest(B1_[1]) == Protocol::DecodeStatus::NeedMoreData); - CHECK(p.DecodeRequest(B1_[2]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(B1_[0]) == DecodeStatus::NeedMoreData); + CHECK(p.DecodeRequest(B1_[1]) == DecodeStatus::NeedMoreData); + CHECK(p.DecodeRequest(B1_[2]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(B1_[3]) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest(B1_[3]) == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); const char _B2[] = " B2\n"; - CHECK(p.DecodeRequest(_B2[0]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B2[0]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B2[1]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B2[1]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B2[2]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B2[2]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B2[3]) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest(_B2[3]) == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); const char _B0_[] = " B0 "; - CHECK(p.DecodeRequest(_B0_[0]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B0_[0]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B0_[1]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B0_[1]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B0_[2]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B0_[2]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(_B0_[3]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(_B0_[3]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest('\n') == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest('\n') == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); } TEST_CASE("protocol::DecodeResponseErrors", "[protocol]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char b0[] = "b0 A\n"; - CHECK(p.DecodeRequest(b0[0]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[0]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b0[1]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[1]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b0[2]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[2]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b0[3]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b0[3]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b0[4]) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest(b0[4]) == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); const char b1[] = "b0A\n"; - CHECK(p.DecodeRequest(b1[0]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b1[0]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b1[1]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b1[1]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b1[2]) == Protocol::DecodeStatus::Error); + CHECK(p.DecodeRequest(b1[2]) == DecodeStatus::Error); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); - CHECK(p.DecodeRequest(b1[3]) == Protocol::DecodeStatus::MessageCompleted); + CHECK(p.DecodeRequest(b1[3]) == DecodeStatus::MessageCompleted); CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown); } // Beware - this test makes 18M+ combinations, run only when changing the implementation of the codec // Therefore it is disabled [.] by default TEST_CASE("protocol::DecodeResponseErrorsCross", "[protocol][.]") { - using namespace modules; + using namespace modules::protocol; Protocol p; const char *validInitialSpaces = ""; @@ -434,7 +434,7 @@ TEST_CASE("protocol::DecodeResponseErrorsCross", "[protocol][.]") { bool shouldPass = viInitialSpace && viReqCode && /*viReqValue && */ viSpace && viRspCode && viTerminatingSpaces; bool failed = false; std::for_each(msg.cbegin(), msg.cend(), [&](uint8_t c) { - if (p.DecodeResponse(c) == Protocol::DecodeStatus::Error) { + if (p.DecodeResponse(c) == DecodeStatus::Error) { failed = true; } });