Interface module for driving LEDs
+ start shaping up main.cpp + make the usage of namespaces and class names more consistent throughout the whole project + refactor related unit tests accordinglypull/13/head
parent
7611b98830
commit
fce2195558
|
|
@ -184,7 +184,7 @@ target_include_directories(firmware PRIVATE include src)
|
||||||
target_compile_options(firmware PRIVATE -Wdouble-promotion)
|
target_compile_options(firmware PRIVATE -Wdouble-promotion)
|
||||||
target_sources(
|
target_sources(
|
||||||
firmware PRIVATE src/main.cpp src/hal/avr/cpu.cpp src/hal/avr/usart.cpp src/modules/protocol.cpp
|
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(
|
set_property(
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
/// Hardware Abstraction Layer for the ADC's
|
/// Hardware Abstraction Layer for the ADC's
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace ADC {
|
namespace adc {
|
||||||
|
|
||||||
/// ADC access routines
|
/// ADC access routines
|
||||||
uint16_t ReadADC(uint8_t adc);
|
uint16_t ReadADC(uint8_t adc);
|
||||||
|
|
||||||
} // namespace ADC
|
} // namespace adc
|
||||||
} // namespace hal
|
} // namespace hal
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "../cpu.h"
|
#include "../cpu.h"
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace CPU {
|
namespace cpu {
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
/// Hardware Abstraction Layer for the CPU
|
/// Hardware Abstraction Layer for the CPU
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace CPU {
|
namespace cpu {
|
||||||
|
|
||||||
/// CPU init routines (not really necessary for the AVR)
|
/// CPU init routines (not really necessary for the AVR)
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
} // namespace CPU
|
} // namespace cpu
|
||||||
} // namespace hal
|
} // namespace hal
|
||||||
|
|
|
||||||
167
src/main.cpp
167
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/gpio.h"
|
||||||
#include "hal/spi.h"
|
#include "hal/spi.h"
|
||||||
#include "hal/usart.h"
|
#include "hal/usart.h"
|
||||||
|
|
||||||
#include "pins.h"
|
#include "pins.h"
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#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
|
/// One-time setup of HW and SW components
|
||||||
/// Called before entering the loop() function
|
/// 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() {
|
void setup() {
|
||||||
using namespace hal;
|
using namespace hal;
|
||||||
|
|
||||||
// spi::SPI_InitTypeDef spi_conf = {
|
cpu::Init();
|
||||||
// .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);
|
|
||||||
|
|
||||||
// // SPI example
|
// shr::Init()
|
||||||
// gpio::Init(gpio::GPIO_pin(GPIOC, 6), gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high));
|
leds.SetMode(4, false, modules::leds::Mode::blink0);
|
||||||
// uint8_t dat[5];
|
// shr::Send(leds.Step(0));
|
||||||
// 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;
|
|
||||||
|
|
||||||
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),
|
.rx_pin = gpio::GPIO_pin(GPIOD, 2),
|
||||||
.tx_pin = gpio::GPIO_pin(GPIOD, 3),
|
.tx_pin = gpio::GPIO_pin(GPIOD, 3),
|
||||||
.baudrate = 115200,
|
.baudrate = 115200,
|
||||||
};
|
|
||||||
|
|
||||||
usart1.Init(&usart_conf);
|
usart1.Init(&usart_conf);
|
||||||
sei();
|
|
||||||
usart1.puts("1234567890\n");
|
leds.SetMode(3, false, modules::leds::Mode::on);
|
||||||
usart1.puts("1234567890\n");
|
// shr::Send(leds.Step(0));
|
||||||
usart1.puts("1234567890\n");
|
|
||||||
usart1.puts("1234567890\n");
|
// @@TODO if both shift register and the UART are dead, we are sitting ducks :(
|
||||||
usart1.puts("1234567890\n");
|
|
||||||
usart1.puts("1234567890\n");
|
spi::SPI_InitTypeDef spi_conf = {
|
||||||
usart1.puts("1234567890\n");
|
.miso_pin = gpio::GPIO_pin(TMC2130_SPI_MISO_PIN),
|
||||||
usart1.puts("1234567890\n");
|
.mosi_pin = gpio::GPIO_pin(TMC2130_SPI_MOSI_PIN),
|
||||||
usart1.puts("1234567890\n");
|
.sck_pin = gpio::GPIO_pin(TMC2130_SPI_SCK_PIN),
|
||||||
usart1.puts("1234567890\n");
|
.ss_pin = gpio::GPIO_pin(TMC2130_SPI_SS_PIN),
|
||||||
usart1.puts("1234567890\n");
|
.prescaler = 2, //4mhz
|
||||||
// usart1.Flush();
|
.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
|
/// 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”.
|
/// 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.)
|
/// Some FW components will leverage ISR to do their stuff (UART, motor stepping?, etc.)
|
||||||
void loop() {
|
void loop() {
|
||||||
|
if (CheckMsgs()) {
|
||||||
|
ProcessRequestMsg(protocol.GetRequestMsg());
|
||||||
|
}
|
||||||
|
buttons.Step(hal::adc::ReadADC(0));
|
||||||
|
// shr.Send(leds.Step(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
setup();
|
setup();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!usart1.ReadEmpty())
|
|
||||||
usart1.Write(usart1.Read());
|
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,71 @@
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "../hal/adc.h"
|
|
||||||
|
|
||||||
namespace modules {
|
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
|
// original idea from: https://www.eeweb.com/debouncing-push-buttons-using-a-state-machine-approach
|
||||||
void Button::Step(uint16_t time, bool press) {
|
void Button::Step(uint16_t time, bool press) {
|
||||||
switch (f.state) {
|
switch (f.state) {
|
||||||
case State::Waiting:
|
case State::Waiting:
|
||||||
if (press) {
|
if (press) {
|
||||||
f.state = State::Detected;
|
f.state = State::Detected;
|
||||||
timeLastChange = time;
|
timeLastChange = time;
|
||||||
f.tmp = press;
|
f.tmp = press;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case State::Detected:
|
|
||||||
if (f.tmp == press) {
|
|
||||||
if (time - timeLastChange > debounce) {
|
|
||||||
f.state = State::WaitForRelease;
|
|
||||||
}
|
}
|
||||||
} 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;
|
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) {
|
int8_t Buttons::Sample(uint16_t rawADC) {
|
||||||
f.state = State::Update;
|
// 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
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -7,67 +7,69 @@
|
||||||
/// This layer should contain debouncing of buttons and their logical interpretation
|
/// This layer should contain debouncing of buttons and their logical interpretation
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
namespace buttons {
|
||||||
|
|
||||||
struct Button {
|
struct Button {
|
||||||
inline constexpr Button()
|
inline constexpr Button()
|
||||||
: timeLastChange(0) {}
|
: timeLastChange(0) {}
|
||||||
|
|
||||||
/// @returns true if button is currently considered as pressed
|
/// @returns true if button is currently considered as pressed
|
||||||
inline bool Pressed() const { return f.state == State::WaitForRelease; }
|
inline bool Pressed() const { return f.state == State::WaitForRelease; }
|
||||||
|
|
||||||
/// State machine stepping routine
|
/// State machine stepping routine
|
||||||
void Step(uint16_t time, bool press);
|
void Step(uint16_t time, bool press);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// time interval for debouncing @@TODO specify units
|
/// time interval for debouncing @@TODO specify units
|
||||||
constexpr static const uint16_t debounce = 100;
|
constexpr static const uint16_t debounce = 100;
|
||||||
|
|
||||||
/// States of the debouncing automaton
|
/// States of the debouncing automaton
|
||||||
/// Intentionally not modeled as an enum class
|
/// Intentionally not modeled as an enum class
|
||||||
/// as it would impose additional casts which do not play well with the struct Flags
|
/// as it would impose additional casts which do not play well with the struct Flags
|
||||||
/// and would make the code less readable
|
/// and would make the code less readable
|
||||||
enum State { Waiting = 0,
|
enum State { Waiting = 0,
|
||||||
Detected,
|
Detected,
|
||||||
WaitForRelease,
|
WaitForRelease,
|
||||||
Update };
|
Update };
|
||||||
|
|
||||||
/// The sole purpose of this data struct is to save RAM by compressing several flags into one byte on the AVR
|
/// The sole purpose of this data struct is to save RAM by compressing several flags into one byte on the AVR
|
||||||
struct Flags {
|
struct Flags {
|
||||||
uint8_t state : 2; ///< state of the button
|
uint8_t state : 2; ///< state of the button
|
||||||
uint8_t tmp : 1; ///< temporary state of button before the debouncing state machine finishes
|
uint8_t tmp : 1; ///< temporary state of button before the debouncing state machine finishes
|
||||||
inline constexpr Flags()
|
inline constexpr Flags()
|
||||||
: state(State::Waiting)
|
: state(State::Waiting)
|
||||||
, tmp(false) {}
|
, 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
|
class Buttons {
|
||||||
Flags f;
|
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
|
public:
|
||||||
uint16_t timeLastChange;
|
inline constexpr Buttons() = default;
|
||||||
};
|
|
||||||
|
|
||||||
class Buttons {
|
/// State machine step - reads the ADC, processes debouncing, updates states of individual buttons
|
||||||
constexpr static const uint8_t N = 3; ///< number of buttons currently supported
|
void Step(uint16_t rawADC);
|
||||||
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
|
|
||||||
|
|
||||||
public:
|
/// @return true if button at index is pressed
|
||||||
inline constexpr Buttons() = default;
|
/// @@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
|
private:
|
||||||
void Step();
|
Button buttons[N];
|
||||||
|
|
||||||
/// @return true if button at index is pressed
|
/// Call to the ADC and decode its output into a button index
|
||||||
/// @@TODO add range checking if necessary
|
/// @returns index of the button pressed or -1 in case no button is pressed
|
||||||
inline bool ButtonPressed(uint8_t index) const { return buttons[index].Pressed(); }
|
static int8_t Sample(uint16_t rawADC);
|
||||||
|
};
|
||||||
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();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
} // namespace buttons
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,3 +1,119 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/// @@TODO @leptun design some nice API ;)
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
|
|
||||||
|
|
@ -11,198 +11,178 @@
|
||||||
// <OID> F : operation finished - will be repeated to "Q" messages until a new command is issued
|
// <OID> F : operation finished - will be repeated to "Q" messages until a new command is issued
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
namespace protocol {
|
||||||
|
|
||||||
// decoding automaton
|
// decoding automaton
|
||||||
// states: input -> transition into state
|
// states: input -> transition into state
|
||||||
// Code QTLMUXPSBEWK -> msgcode
|
// Code QTLMUXPSBEWK -> msgcode
|
||||||
// \n ->start
|
// \n ->start
|
||||||
// * ->error
|
// * ->error
|
||||||
// error \n ->start
|
// error \n ->start
|
||||||
// * ->error
|
// * ->error
|
||||||
// msgcode 0-9 ->msgvalue
|
// msgcode 0-9 ->msgvalue
|
||||||
// * ->error
|
// * ->error
|
||||||
// msgvalue 0-9 ->msgvalue
|
// msgvalue 0-9 ->msgvalue
|
||||||
// \n ->start successfully accepted command
|
// \n ->start successfully accepted command
|
||||||
|
|
||||||
Protocol::DecodeStatus Protocol::DecodeRequest(uint8_t c) {
|
DecodeStatus Protocol::DecodeRequest(uint8_t c) {
|
||||||
switch (rqState) {
|
switch (rqState) {
|
||||||
case RequestStates::Code:
|
case RequestStates::Code:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'Q':
|
case 'Q':
|
||||||
case 'T':
|
case 'T':
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'U':
|
case 'U':
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'W':
|
case 'W':
|
||||||
case 'K':
|
case 'K':
|
||||||
requestMsg.code = (RequestMsgCodes)c;
|
requestMsg.code = (RequestMsgCodes)c;
|
||||||
requestMsg.value = 0;
|
requestMsg.value = 0;
|
||||||
rqState = RequestStates::Value;
|
rqState = RequestStates::Value;
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
default:
|
default:
|
||||||
requestMsg.code = RequestMsgCodes::unknown;
|
requestMsg.code = RequestMsgCodes::unknown;
|
||||||
rqState = RequestStates::Error;
|
rqState = RequestStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
case RequestStates::Value:
|
case RequestStates::Value:
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
requestMsg.value *= 10;
|
requestMsg.value *= 10;
|
||||||
requestMsg.value += c - '0';
|
requestMsg.value += c - '0';
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
rqState = RequestStates::Code;
|
rqState = RequestStates::Code;
|
||||||
return DecodeStatus::MessageCompleted;
|
return DecodeStatus::MessageCompleted;
|
||||||
} else {
|
} else {
|
||||||
requestMsg.code = RequestMsgCodes::unknown;
|
requestMsg.code = RequestMsgCodes::unknown;
|
||||||
rqState = RequestStates::Error;
|
rqState = RequestStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
default: //case error:
|
default: //case error:
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
rqState = RequestStates::Code;
|
rqState = RequestStates::Code;
|
||||||
return DecodeStatus::MessageCompleted;
|
return DecodeStatus::MessageCompleted;
|
||||||
} else {
|
} else {
|
||||||
requestMsg.code = RequestMsgCodes::unknown;
|
requestMsg.code = RequestMsgCodes::unknown;
|
||||||
rqState = RequestStates::Error;
|
rqState = RequestStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Protocol::EncodeRequest(const RequestMsg &msg, uint8_t *txbuff) {
|
uint8_t Protocol::EncodeRequest(const RequestMsg &msg, uint8_t *txbuff) {
|
||||||
txbuff[0] = (uint8_t)msg.code;
|
txbuff[0] = (uint8_t)msg.code;
|
||||||
txbuff[1] = msg.value + '0';
|
txbuff[1] = msg.value + '0';
|
||||||
txbuff[2] = '\n';
|
txbuff[2] = '\n';
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
Protocol::DecodeStatus Protocol::DecodeResponse(uint8_t c) {
|
DecodeStatus Protocol::DecodeResponse(uint8_t c) {
|
||||||
switch (rspState) {
|
switch (rspState) {
|
||||||
case ResponseStates::RequestCode:
|
case ResponseStates::RequestCode:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'Q':
|
case 'Q':
|
||||||
case 'T':
|
case 'T':
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'U':
|
case 'U':
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'W':
|
case 'W':
|
||||||
case 'K':
|
case 'K':
|
||||||
responseMsg.request.code = (RequestMsgCodes)c;
|
responseMsg.request.code = (RequestMsgCodes)c;
|
||||||
responseMsg.request.value = 0;
|
responseMsg.request.value = 0;
|
||||||
rspState = ResponseStates::RequestValue;
|
rspState = ResponseStates::RequestValue;
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
default:
|
default:
|
||||||
rspState = ResponseStates::Error;
|
rspState = ResponseStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
case ResponseStates::RequestValue:
|
case ResponseStates::RequestValue:
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
responseMsg.request.value *= 10;
|
responseMsg.request.value *= 10;
|
||||||
responseMsg.request.value += c - '0';
|
responseMsg.request.value += c - '0';
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
} else if (c == ' ') {
|
} else if (c == ' ') {
|
||||||
rspState = ResponseStates::ParamCode;
|
rspState = ResponseStates::ParamCode;
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
} else {
|
} else {
|
||||||
rspState = ResponseStates::Error;
|
rspState = ResponseStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
case ResponseStates::ParamCode:
|
case ResponseStates::ParamCode:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'R':
|
case 'R':
|
||||||
rspState = ResponseStates::ParamValue;
|
rspState = ResponseStates::ParamValue;
|
||||||
responseMsg.paramCode = (ResponseMsgParamCodes)c;
|
responseMsg.paramCode = (ResponseMsgParamCodes)c;
|
||||||
responseMsg.paramValue = 0;
|
responseMsg.paramValue = 0;
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
default:
|
default:
|
||||||
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
||||||
rspState = ResponseStates::Error;
|
rspState = ResponseStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
case ResponseStates::ParamValue:
|
case ResponseStates::ParamValue:
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
responseMsg.paramValue *= 10;
|
responseMsg.paramValue *= 10;
|
||||||
responseMsg.paramValue += c - '0';
|
responseMsg.paramValue += c - '0';
|
||||||
return DecodeStatus::NeedMoreData;
|
return DecodeStatus::NeedMoreData;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
rspState = ResponseStates::RequestCode;
|
rspState = ResponseStates::RequestCode;
|
||||||
return DecodeStatus::MessageCompleted;
|
return DecodeStatus::MessageCompleted;
|
||||||
} else {
|
} else {
|
||||||
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
||||||
rspState = ResponseStates::Error;
|
rspState = ResponseStates::Error;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
}
|
}
|
||||||
default: //case error:
|
default: //case error:
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
rspState = ResponseStates::RequestCode;
|
rspState = ResponseStates::RequestCode;
|
||||||
return DecodeStatus::MessageCompleted;
|
return DecodeStatus::MessageCompleted;
|
||||||
} else {
|
} else {
|
||||||
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
responseMsg.paramCode = ResponseMsgParamCodes::unknown;
|
||||||
return DecodeStatus::Error;
|
return DecodeStatus::Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Protocol::EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff) {
|
uint8_t Protocol::EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff) {
|
||||||
txbuff[0] = (uint8_t)msg.code;
|
txbuff[0] = (uint8_t)msg.code;
|
||||||
txbuff[1] = msg.value + '0';
|
txbuff[1] = msg.value + '0';
|
||||||
txbuff[2] = ' ';
|
txbuff[2] = ' ';
|
||||||
txbuff[3] = (uint8_t)ar;
|
txbuff[3] = (uint8_t)ar;
|
||||||
txbuff[4] = '\n';
|
txbuff[4] = '\n';
|
||||||
return 5;
|
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';
|
|
||||||
}
|
}
|
||||||
*dst = '\n';
|
|
||||||
return dst - txbuff + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff) {
|
uint8_t Protocol::EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff) {
|
||||||
txbuff[0] = (uint8_t)msg.code;
|
txbuff[0] = (uint8_t)msg.code;
|
||||||
txbuff[1] = msg.value + '0';
|
txbuff[1] = msg.value + '0';
|
||||||
txbuff[2] = ' ';
|
txbuff[2] = ' ';
|
||||||
txbuff[3] = (uint8_t)code;
|
txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted;
|
||||||
uint8_t *dst = txbuff + 4;
|
txbuff[4] = findaValue + '0';
|
||||||
if (code != ResponseMsgParamCodes::Finished) {
|
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) {
|
if (value < 10) {
|
||||||
*dst++ = value + '0';
|
*dst++ = value + '0';
|
||||||
} else if (value < 100) {
|
} else if (value < 100) {
|
||||||
|
|
@ -213,9 +193,31 @@ uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMs
|
||||||
*dst++ = (value / 10) % 10 + '0';
|
*dst++ = (value / 10) % 10 + '0';
|
||||||
*dst++ = value % 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
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -7,60 +7,56 @@
|
||||||
/// @@TODO possibly add some checksum to verify the correctness of messages
|
/// @@TODO possibly add some checksum to verify the correctness of messages
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
namespace protocol {
|
||||||
|
|
||||||
enum class RequestMsgCodes : uint8_t {
|
enum class RequestMsgCodes : uint8_t {
|
||||||
unknown = 0,
|
unknown = 0,
|
||||||
Query = 'Q',
|
Query = 'Q',
|
||||||
Tool = 'T',
|
Tool = 'T',
|
||||||
Load = 'L',
|
Load = 'L',
|
||||||
Mode = 'M',
|
Mode = 'M',
|
||||||
Unload = 'U',
|
Unload = 'U',
|
||||||
Reset = 'X',
|
Reset = 'X',
|
||||||
Finda = 'P',
|
Finda = 'P',
|
||||||
Version = 'S',
|
Version = 'S',
|
||||||
Button = 'B',
|
Button = 'B',
|
||||||
Eject = 'E',
|
Eject = 'E',
|
||||||
Wait = 'W',
|
Wait = 'W',
|
||||||
Cut = 'K'
|
Cut = 'K'
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ResponseMsgParamCodes : uint8_t {
|
enum class ResponseMsgParamCodes : uint8_t {
|
||||||
unknown = 0,
|
unknown = 0,
|
||||||
Processing = 'P',
|
Processing = 'P',
|
||||||
Error = 'E',
|
Error = 'E',
|
||||||
Finished = 'F',
|
Finished = 'F',
|
||||||
Accepted = 'A',
|
Accepted = 'A',
|
||||||
Rejected = 'R'
|
Rejected = 'R'
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A request message
|
/// A request message
|
||||||
/// Requests are being sent by the printer into the MMU
|
/// Requests are being sent by the printer into the MMU
|
||||||
/// It is the same structure as the generic Msg
|
/// It is the same structure as the generic Msg
|
||||||
struct RequestMsg {
|
struct RequestMsg {
|
||||||
RequestMsgCodes code;
|
RequestMsgCodes code;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
inline RequestMsg(RequestMsgCodes code, uint8_t value)
|
inline RequestMsg(RequestMsgCodes code, uint8_t value)
|
||||||
: code(code)
|
: code(code)
|
||||||
, value(value) {}
|
, value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A response message
|
/// A response message
|
||||||
/// Responses are being sent from the MMU into the printer as a response to a request message
|
/// Responses are being sent from the MMU into the printer as a response to a request message
|
||||||
struct ResponseMsg {
|
struct ResponseMsg {
|
||||||
RequestMsg request; ///< response is always preceeded by the request message
|
RequestMsg request; ///< response is always preceeded by the request message
|
||||||
ResponseMsgParamCodes paramCode; ///< parameters of reply
|
ResponseMsgParamCodes paramCode; ///< parameters of reply
|
||||||
uint8_t paramValue; ///< parameters of reply
|
uint8_t paramValue; ///< parameters of reply
|
||||||
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue)
|
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue)
|
||||||
: request(request)
|
: request(request)
|
||||||
, paramCode(paramCode)
|
, paramCode(paramCode)
|
||||||
, paramValue(paramValue) {}
|
, 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
|
/// Message decoding return value
|
||||||
enum class DecodeStatus : uint_fast8_t {
|
enum class DecodeStatus : uint_fast8_t {
|
||||||
MessageCompleted, ///< message completed and successfully lexed
|
MessageCompleted, ///< message completed and successfully lexed
|
||||||
|
|
@ -68,76 +64,82 @@ public:
|
||||||
Error, ///< input character broke message decoding
|
Error, ///< input character broke message decoding
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Protocol()
|
/// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer
|
||||||
: rqState(RequestStates::Code)
|
/// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods
|
||||||
, requestMsg(RequestMsgCodes::unknown, 0)
|
/// processing one input byte per call
|
||||||
, rspState(ResponseStates::RequestCode)
|
class Protocol {
|
||||||
, responseMsg(RequestMsg(RequestMsgCodes::unknown, 0), ResponseMsgParamCodes::unknown, 0) {
|
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
|
/// Takes the input byte c and steps one step through the state machine
|
||||||
/// @returns state of the message being decoded
|
/// @returns state of the message being decoded
|
||||||
DecodeStatus DecodeRequest(uint8_t c);
|
DecodeStatus DecodeRequest(uint8_t c);
|
||||||
|
|
||||||
/// Decodes response message in rxbuff
|
/// Decodes response message in rxbuff
|
||||||
/// @returns decoded response message structure
|
/// @returns decoded response message structure
|
||||||
DecodeStatus DecodeResponse(uint8_t c);
|
DecodeStatus DecodeResponse(uint8_t c);
|
||||||
|
|
||||||
/// Encodes request message msg into txbuff memory
|
/// Encodes request message msg into txbuff memory
|
||||||
/// It is expected the txbuff is large enough to fit the message
|
/// It is expected the txbuff is large enough to fit the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff);
|
static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode generic response Command Accepted or Rejected
|
/// Encode generic response Command Accepted or Rejected
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
|
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode response to Read FINDA query
|
/// Encode response to Read FINDA query
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param findaValue 1/0 (on/off) status of FINDA
|
/// @param findaValue 1/0 (on/off) status of FINDA
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode response to Version query
|
/// Encode response to Version query
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param value version number (0-255)
|
/// @param value version number (0-255)
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff);
|
static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode response to Query operation status
|
/// Encode response to Query operation status
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param code status of operation (Processing, Error, Finished)
|
/// @param code status of operation (Processing, Error, Finished)
|
||||||
/// @param value related to status of operation(e.g. error code or progress)
|
/// @param value related to status of operation(e.g. error code or progress)
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
||||||
|
|
||||||
/// @returns the most recently lexed request message
|
/// @returns the most recently lexed request message
|
||||||
inline const RequestMsg GetRequestMsg() const { return requestMsg; }
|
inline const RequestMsg GetRequestMsg() const { return requestMsg; }
|
||||||
|
|
||||||
/// @returns the most recently lexed response message
|
/// @returns the most recently lexed response message
|
||||||
inline const ResponseMsg GetResponseMsg() const { return responseMsg; }
|
inline const ResponseMsg GetResponseMsg() const { return responseMsg; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class RequestStates : uint8_t {
|
enum class RequestStates : uint8_t {
|
||||||
Code, ///< starting state - expects message code
|
Code, ///< starting state - expects message code
|
||||||
Value, ///< expecting code value
|
Value, ///< expecting code value
|
||||||
Error ///< automaton in error state
|
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;
|
} // namespace protocol
|
||||||
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 modules
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace ADC {
|
namespace adc {
|
||||||
|
|
||||||
static TADCData values2Return;
|
static TADCData values2Return;
|
||||||
static TADCData::const_iterator rdptr = values2Return.cbegin();
|
static TADCData::const_iterator rdptr = values2Return.cbegin();
|
||||||
|
|
@ -28,5 +28,5 @@ namespace ADC {
|
||||||
return rdptr != values2Return.end() ? *rdptr : 1023;
|
return rdptr != values2Return.end() ? *rdptr : 1023;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ADC
|
} // namespace adc
|
||||||
} // namespace hal
|
} // namespace hal
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace ADC {
|
namespace adc {
|
||||||
|
|
||||||
using TADCData = std::vector<uint16_t>;
|
using TADCData = std::vector<uint16_t>;
|
||||||
|
|
||||||
void ReinitADC(TADCData &&d, uint8_t ovsmpl);
|
void ReinitADC(TADCData &&d, uint8_t ovsmpl);
|
||||||
|
|
||||||
} // namespace ADC
|
} // namespace adc
|
||||||
} // namespace hal
|
} // namespace hal
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,21 @@
|
||||||
|
|
||||||
using Catch::Matchers::Equals;
|
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)
|
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(testedButtonIndex));
|
||||||
CHECK(!b.ButtonPressed(otherButton1));
|
CHECK(!b.ButtonPressed(otherButton1));
|
||||||
CHECK(!b.ButtonPressed(otherButton2));
|
CHECK(!b.ButtonPressed(otherButton2));
|
||||||
|
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(testedButtonIndex));
|
||||||
CHECK(!b.ButtonPressed(otherButton1));
|
CHECK(!b.ButtonPressed(otherButton1));
|
||||||
CHECK(!b.ButtonPressed(otherButton2));
|
CHECK(!b.ButtonPressed(otherButton2));
|
||||||
|
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(testedButtonIndex));
|
||||||
CHECK(!b.ButtonPressed(otherButton1));
|
CHECK(!b.ButtonPressed(otherButton1));
|
||||||
CHECK(!b.ButtonPressed(otherButton2));
|
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.
|
/// 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) {
|
bool Step_Basic_One_Button(hal::adc::TADCData &&d, uint8_t testedButtonIndex) {
|
||||||
using namespace modules;
|
using namespace modules::buttons;
|
||||||
|
|
||||||
Buttons b;
|
Buttons b;
|
||||||
|
|
||||||
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||||
constexpr uint8_t oversampleFactor = 100;
|
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;
|
uint8_t otherButton1 = 1, otherButton2 = 2;
|
||||||
switch (testedButtonIndex) {
|
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]") {
|
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));
|
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));
|
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));
|
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
|
/// and the Buttons class should press first button and release, then the second one and then the third one
|
||||||
/// without being reinitialized.
|
/// without being reinitialized.
|
||||||
TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") {
|
TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") {
|
||||||
using namespace modules;
|
using namespace modules::buttons;
|
||||||
hal::ADC::TADCData d({ 5, 6, 1023, 321, 359, 1023, 501, 529, 1023 });
|
hal::adc::TADCData d({ 5, 6, 1023, 321, 359, 1023, 501, 529, 1023 });
|
||||||
Buttons b;
|
Buttons b;
|
||||||
|
|
||||||
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||||
constexpr uint8_t oversampleFactor = 100;
|
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, 0, 1, 2));
|
||||||
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 1, 0, 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
|
/// This test tries to simulate a bouncing effect on data from ADC on the first button
|
||||||
TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") {
|
TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") {
|
||||||
using namespace modules;
|
using namespace modules::buttons;
|
||||||
|
|
||||||
// make a bounce event on the first press
|
// 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
|
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||||
constexpr uint8_t oversampleFactor = 25;
|
constexpr uint8_t oversampleFactor = 25;
|
||||||
hal::ADC::ReinitADC(std::move(d), oversampleFactor);
|
hal::adc::ReinitADC(std::move(d), oversampleFactor);
|
||||||
|
|
||||||
Buttons b;
|
Buttons b;
|
||||||
|
|
||||||
// 5
|
// 5
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 1023
|
// 1023
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 5
|
// 5
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 9
|
// 9
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 6
|
// 6
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 7
|
// 7
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 8
|
// 8
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 1023
|
// 1023
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
||||||
// 1023
|
// 1023
|
||||||
for (uint8_t i = 0; i < oversampleFactor; ++i)
|
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(0));
|
||||||
CHECK(!b.ButtonPressed(1));
|
CHECK(!b.ButtonPressed(1));
|
||||||
CHECK(!b.ButtonPressed(2));
|
CHECK(!b.ButtonPressed(2));
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using Catch::Matchers::Equals;
|
using Catch::Matchers::Equals;
|
||||||
|
|
||||||
TEST_CASE("protocol::EncodeRequests", "[protocol]") {
|
TEST_CASE("protocol::EncodeRequests", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
|
|
||||||
RequestMsgCodes code;
|
RequestMsgCodes code;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
@ -45,7 +45,7 @@ TEST_CASE("protocol::EncodeRequests", "[protocol]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::EncodeResponseCmdAR", "[protocol]") {
|
TEST_CASE("protocol::EncodeResponseCmdAR", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
|
|
||||||
auto requestMsg = GENERATE(
|
auto requestMsg = GENERATE(
|
||||||
RequestMsg(RequestMsgCodes::Button, 0),
|
RequestMsg(RequestMsgCodes::Button, 0),
|
||||||
|
|
@ -93,7 +93,7 @@ TEST_CASE("protocol::EncodeResponseCmdAR", "[protocol]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::EncodeResponseReadFINDA", "[protocol]") {
|
TEST_CASE("protocol::EncodeResponseReadFINDA", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
auto requestMsg = RequestMsg(RequestMsgCodes::Finda, 0);
|
auto requestMsg = RequestMsg(RequestMsgCodes::Finda, 0);
|
||||||
|
|
||||||
uint8_t findaStatus = GENERATE(0, 1);
|
uint8_t findaStatus = GENERATE(0, 1);
|
||||||
|
|
@ -111,7 +111,7 @@ TEST_CASE("protocol::EncodeResponseReadFINDA", "[protocol]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") {
|
TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
|
|
||||||
std::uint8_t versionQueryType = GENERATE(0, 1, 2, 3);
|
std::uint8_t versionQueryType = GENERATE(0, 1, 2, 3);
|
||||||
auto requestMsg = RequestMsg(RequestMsgCodes::Version, versionQueryType);
|
auto requestMsg = RequestMsg(RequestMsgCodes::Version, versionQueryType);
|
||||||
|
|
@ -142,7 +142,7 @@ TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::EncodeResponseQueryOperation", "[protocol]") {
|
TEST_CASE("protocol::EncodeResponseQueryOperation", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
|
|
||||||
auto requestMsg = GENERATE(
|
auto requestMsg = GENERATE(
|
||||||
RequestMsg(RequestMsgCodes::Cut, 0),
|
RequestMsg(RequestMsgCodes::Cut, 0),
|
||||||
|
|
@ -202,7 +202,7 @@ TEST_CASE("protocol::EncodeResponseQueryOperation", "[protocol]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::DecodeRequest", "[protocol]") {
|
TEST_CASE("protocol::DecodeRequest", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
const char *rxbuff = GENERATE(
|
const char *rxbuff = GENERATE(
|
||||||
"B0\n", "B1\n", "B2\n",
|
"B0\n", "B1\n", "B2\n",
|
||||||
|
|
@ -226,9 +226,9 @@ TEST_CASE("protocol::DecodeRequest", "[protocol]") {
|
||||||
break;
|
break;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
// regular end of message line
|
// regular end of message line
|
||||||
CHECK(p.DecodeRequest(c) == Protocol::DecodeStatus::MessageCompleted);
|
CHECK(p.DecodeRequest(c) == DecodeStatus::MessageCompleted);
|
||||||
} else {
|
} 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]") {
|
TEST_CASE("protocol::DecodeResponseReadFinda", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
const char *rxbuff = GENERATE(
|
const char *rxbuff = GENERATE(
|
||||||
"P0 A0\n",
|
"P0 A0\n",
|
||||||
|
|
@ -253,9 +253,9 @@ TEST_CASE("protocol::DecodeResponseReadFinda", "[protocol]") {
|
||||||
break;
|
break;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
// regular end of message line
|
// regular end of message line
|
||||||
CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::MessageCompleted);
|
CHECK(p.DecodeResponse(c) == DecodeStatus::MessageCompleted);
|
||||||
} else {
|
} 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]") {
|
TEST_CASE("protocol::DecodeResponseQueryOperation", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
const char *cmdReference = GENERATE(
|
const char *cmdReference = GENERATE(
|
||||||
"E0", "E1", "E2", "E3", "E4",
|
"E0", "E1", "E2", "E3", "E4",
|
||||||
|
|
@ -294,9 +294,9 @@ TEST_CASE("protocol::DecodeResponseQueryOperation", "[protocol]") {
|
||||||
break;
|
break;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n') {
|
||||||
// regular end of message line
|
// regular end of message line
|
||||||
CHECK(p.DecodeResponse(c) == Protocol::DecodeStatus::MessageCompleted);
|
CHECK(p.DecodeResponse(c) == DecodeStatus::MessageCompleted);
|
||||||
} else {
|
} 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]") {
|
TEST_CASE("protocol::DecodeRequestErrors", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
const char b0[] = "b0";
|
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.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.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
|
|
||||||
// reset protokol decoder
|
// reset protokol decoder
|
||||||
CHECK(p.DecodeRequest('\n') == Protocol::DecodeStatus::MessageCompleted);
|
CHECK(p.DecodeRequest('\n') == DecodeStatus::MessageCompleted);
|
||||||
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
|
|
||||||
const char B1_[] = "B1 \n";
|
const char B1_[] = "B1 \n";
|
||||||
CHECK(p.DecodeRequest(B1_[0]) == Protocol::DecodeStatus::NeedMoreData);
|
CHECK(p.DecodeRequest(B1_[0]) == DecodeStatus::NeedMoreData);
|
||||||
CHECK(p.DecodeRequest(B1_[1]) == Protocol::DecodeStatus::NeedMoreData);
|
CHECK(p.DecodeRequest(B1_[1]) == DecodeStatus::NeedMoreData);
|
||||||
CHECK(p.DecodeRequest(B1_[2]) == Protocol::DecodeStatus::Error);
|
CHECK(p.DecodeRequest(B1_[2]) == DecodeStatus::Error);
|
||||||
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
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);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
|
|
||||||
const char _B2[] = " B2\n";
|
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.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.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.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);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
|
|
||||||
const char _B0_[] = " B0 ";
|
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.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.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.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.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
CHECK(p.DecodeRequest('\n') == Protocol::DecodeStatus::MessageCompleted);
|
CHECK(p.DecodeRequest('\n') == DecodeStatus::MessageCompleted);
|
||||||
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("protocol::DecodeResponseErrors", "[protocol]") {
|
TEST_CASE("protocol::DecodeResponseErrors", "[protocol]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
|
|
||||||
const char b0[] = "b0 A\n";
|
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.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.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.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.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);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
|
|
||||||
const char b1[] = "b0A\n";
|
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.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.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.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);
|
CHECK(p.GetRequestMsg().code == RequestMsgCodes::unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beware - this test makes 18M+ combinations, run only when changing the implementation of the codec
|
// Beware - this test makes 18M+ combinations, run only when changing the implementation of the codec
|
||||||
// Therefore it is disabled [.] by default
|
// Therefore it is disabled [.] by default
|
||||||
TEST_CASE("protocol::DecodeResponseErrorsCross", "[protocol][.]") {
|
TEST_CASE("protocol::DecodeResponseErrorsCross", "[protocol][.]") {
|
||||||
using namespace modules;
|
using namespace modules::protocol;
|
||||||
Protocol p;
|
Protocol p;
|
||||||
|
|
||||||
const char *validInitialSpaces = "";
|
const char *validInitialSpaces = "";
|
||||||
|
|
@ -434,7 +434,7 @@ TEST_CASE("protocol::DecodeResponseErrorsCross", "[protocol][.]") {
|
||||||
bool shouldPass = viInitialSpace && viReqCode && /*viReqValue && */ viSpace && viRspCode && viTerminatingSpaces;
|
bool shouldPass = viInitialSpace && viReqCode && /*viReqValue && */ viSpace && viRspCode && viTerminatingSpaces;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
std::for_each(msg.cbegin(), msg.cend(), [&](uint8_t c) {
|
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;
|
failed = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue