diff --git a/Src/Application/mode_handler.c b/Src/Application/mode_handler.c index d798aa76..301fccfb 100644 --- a/Src/Application/mode_handler.c +++ b/Src/Application/mode_handler.c @@ -46,7 +46,7 @@ mode_handler_mode_t mode_handler_handle(imu_data_t *imu_data, remote_data_t *rem if (remote_timeout_counter >= REMOTE_TIMEOUT) { remote_timeout_counter = REMOTE_TIMEOUT; remote_active = false; - //error_handler_handle_warning(MODE_HANDLER, MODE_HANDLER_ERROR_NO_REMOTE_DATA); + // error_handler_handle_warning(MODE_HANDLER, MODE_HANDLER_ERROR_NO_REMOTE_DATA); } *remote_data = remote_get_data(); @@ -59,7 +59,7 @@ mode_handler_mode_t mode_handler_handle(imu_data_t *imu_data, remote_data_t *rem if (flightcomputer_timeout_counter >= FLIGHTCOMPUTER_TIMOUT) { flightcomputer_timeout_counter = FLIGHTCOMPUTER_TIMOUT; flightcomputer_active = false; - //error_handler_handle_warning(MODE_HANDLER, MODE_HANDLER_ERROR_NO_FCP_DATA); + // error_handler_handle_warning(MODE_HANDLER, MODE_HANDLER_ERROR_NO_FCP_DATA); } *flightcomputer_setpoint = flightcomputer_get_setpoint(); diff --git a/Src/Components/actuators.c b/Src/Components/actuators.c index 8e5b3072..5eca118d 100644 --- a/Src/Components/actuators.c +++ b/Src/Components/actuators.c @@ -5,10 +5,10 @@ * @brief Implementation of the actuators interface component. * @ingroup Components */ -#include - #include "actuators.h" +#include + enum { SERVO_CENTRE_POSITION = 500U }; void actuators_init(void) { diff --git a/Src/Components/imu.c b/Src/Components/imu.c index 769018b0..1adc3aa7 100644 --- a/Src/Components/imu.c +++ b/Src/Components/imu.c @@ -18,6 +18,9 @@ enum { MAG_CALIB_TRESH = 2 }; enum { GYR_CALIB_TRESH = 2 }; enum { SYS_CALIB_TRESH = 3 }; +/** + * State of the internal sampling state machine. + */ typedef enum { EUL, GYR, @@ -26,10 +29,12 @@ typedef enum { CALIB_STAT, } bno_sampling_state_t; -static volatile bno055_response_t init_response; -static volatile bool callback_ready; -static volatile bno_sampling_state_t bno_sampling_state; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) only read if callback ready, behaviour checked +static volatile bno055_response_t init_response = write_fail; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) clear interaction in init, always properly set +static volatile bool callback_ready = false; +static volatile bno_sampling_state_t bno_sampling_state = EUL; static volatile imu_data_t imu_datas[2]; static bno055_calib_status_t calib_status; static bno055_status_t bno_status; @@ -70,7 +75,7 @@ static void bno_sample_callback(bno055_response_t response) { case CALIB_STAT: current_sample_state_id = 1 - current_sample_state_id; if (calib_status.sys_status < SYS_CALIB_TRESH || calib_status.gyr_status < GYR_CALIB_TRESH || - calib_status.acc_status < GYR_CALIB_TRESH || calib_status.mag_status < MAG_CALIB_TRESH) { + calib_status.acc_status < ACC_CALIB_TRESH || calib_status.mag_status < MAG_CALIB_TRESH) { imu_data->imu_ok = false; } sampling_complete = true; diff --git a/Src/Drivers/CMakeLists.txt b/Src/Drivers/CMakeLists.txt index d54ddaca..ae1c5603 100644 --- a/Src/Drivers/CMakeLists.txt +++ b/Src/Drivers/CMakeLists.txt @@ -1,3 +1,3 @@ project(Drivers) -add_library(${PROJECT_NAME} STATIC bno055.c sbus.c bno055_uart.c ppm.c protobuf.c) +add_library(${PROJECT_NAME} STATIC bno055.c sbus.c bno055_uart.c ppm.c protobuf.c ring_buffer.c) target_link_libraries(${PROJECT_NAME} PUBLIC AvrHAL ToolboxPlaneMessages) diff --git a/Src/Drivers/protobuf.c b/Src/Drivers/protobuf.c index 5f30d9f5..2854c268 100644 --- a/Src/Drivers/protobuf.c +++ b/Src/Drivers/protobuf.c @@ -12,29 +12,25 @@ #include #include +#include "ring_buffer.h" + enum { UART_ID = 0 }; enum { UART_BAUD = 115200U }; -enum { RX_BUF_SIZE = 512 }; - -static volatile uint8_t rx_buf[RX_BUF_SIZE]; -static volatile uint8_t rx_head, rx_tail; +static ring_buffer_data_t ring_buffer_data; static message_decoding_data_t message_decoding_data; static setpoint_message_t setpoint_message; static void uart_callback(uint8_t data) { - rx_buf[rx_head] = data; - rx_head = (rx_head + 1) % RX_BUF_SIZE; - if (rx_tail == rx_head) { + if (!ring_buffer_put(&ring_buffer_data, data)) { // TODO error handling } } void protobuf_init(void) { - uart_init(UART_ID, UART_BAUD, NONE, 1, uart_callback); - rx_head = 0; - rx_tail = 0; message_decoding_init(&message_decoding_data, FC_SP_ID); + ring_buffer_data = ring_buffer_init(); + uart_init(UART_ID, UART_BAUD, NONE, 1, uart_callback); } void protobuf_send(const fc_message_t *message) { @@ -45,10 +41,8 @@ void protobuf_send(const fc_message_t *message) { bool protobuf_setpoint_available(void) { bool res = false; - while (rx_tail != rx_head) { - uint8_t data = rx_buf[rx_tail]; - rx_tail = (rx_tail + 1) % RX_BUF_SIZE; - + uint8_t data = 0; + while (ring_buffer_get(&ring_buffer_data, &data)) { if (message_decoding_decode(&message_decoding_data, data, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, &setpoint_message)) { res = true; diff --git a/Src/Drivers/ring_buffer.c b/Src/Drivers/ring_buffer.c new file mode 100644 index 00000000..76e10ef0 --- /dev/null +++ b/Src/Drivers/ring_buffer.c @@ -0,0 +1,33 @@ +/** + * @file ring_buffer.c + * @author Paul Nykiel + * @date 27.12.22 + * @brief Implemtation of the fixed-size, byte sized object ring-buffer utility module . + * @ingroup Drivers + */ +#include "ring_buffer.h" + +ring_buffer_data_t ring_buffer_init(void) { + ring_buffer_data_t uart_buffer_data = {.buf = {0}, .read_index = 0, .len = 0}; + return uart_buffer_data; +} + +bool ring_buffer_put(ring_buffer_data_t *ring_buffer_data, uint8_t data) { + if (ring_buffer_data->len == RING_BUFFER_SIZE) { + return false; + } + uint16_t index = (ring_buffer_data->read_index + ring_buffer_data->len) % RING_BUFFER_SIZE; + ring_buffer_data->buf[index] = data; + ring_buffer_data->len += 1; + return true; +} + +bool ring_buffer_get(ring_buffer_data_t *ring_buffer_data, uint8_t *out) { + if (ring_buffer_data->len > 0) { + *out = ring_buffer_data->buf[ring_buffer_data->read_index]; + ring_buffer_data->read_index = (ring_buffer_data->read_index + 1) % RING_BUFFER_SIZE; + ring_buffer_data->len -= 1; + return true; + } + return false; +} diff --git a/Src/Drivers/ring_buffer.h b/Src/Drivers/ring_buffer.h new file mode 100644 index 00000000..a32b19fa --- /dev/null +++ b/Src/Drivers/ring_buffer.h @@ -0,0 +1,50 @@ +/** + * @file ring_buffer.h + * @author Paul Nykiel + * @date 27.12.22 + * @brief Declaration of the fixed-size, byte sized object ring-buffer utility module . + * @ingroup Drivers + */ +#ifndef FLIGHTCONTROLLER_RING_BUFFER_H +#define FLIGHTCONTROLLER_RING_BUFFER_H + +#include +#include + +/** + * Size of the ring-buffer, i.e. number of elements/bytes. + */ +enum { RING_BUFFER_SIZE = 512 }; + +/** + * Internal data for the ring buffer + */ +typedef struct { + uint8_t buf[RING_BUFFER_SIZE]; ///< Buffer for the data + uint16_t read_index; ///< Index of the next data to read (i.e. oldest data) + uint16_t len; ///< Number of elements +} ring_buffer_data_t; + +/** + * Create a correctly initialized ring_buffer_data_t object. + * @return an ring_buffer_data_t for usage with the other functions. + */ +ring_buffer_data_t ring_buffer_init(void); + +/** + * Write a byte to the ring buffer. + * @param ring_buffer_data the internal data of the ring-buffer + * @param data the byte to add + * @return true if the object could be added, false if the buffer is already full + */ +bool ring_buffer_put(ring_buffer_data_t *ring_buffer_data, uint8_t data); + +/** + * Get a byte from the ring buffer if available. + * @param ring_buffer_data the internal data of the ring-buffer + * @param out the byte that got read + * @return true if a byte was available, otherwise false + */ +bool ring_buffer_get(ring_buffer_data_t *ring_buffer_data, uint8_t *out); + +#endif // FLIGHTCONTROLLER_RING_BUFFER_H diff --git a/Src/Drivers/sbus.c b/Src/Drivers/sbus.c index e6e4e008..4fc08b2d 100644 --- a/Src/Drivers/sbus.c +++ b/Src/Drivers/sbus.c @@ -10,25 +10,22 @@ #include +#include "ring_buffer.h" + enum { UART_ID = 2 }; enum { UART_BAUD = 100000 }; -enum { RX_BUF_SIZE = 512 }; - enum { SBUS_START_BYTE = 0x0F }; enum { SBUS_END_BYTE = 0x00 }; enum { SBUS_BITS_PER_CHANNEL = 11U }; -static volatile uint8_t rx_buf[RX_BUF_SIZE]; -static volatile uint8_t rx_head, rx_tail; -static volatile sbus_data_t latest_data; -static volatile sbus_data_t curr_decode_data; -static volatile uint8_t decode_byte_count; +static ring_buffer_data_t ring_buffer_data; +static sbus_data_t latest_data; +static sbus_data_t curr_decode_data; +static uint8_t decode_byte_count; static void uart_callback(uint8_t data) { - rx_buf[rx_head] = data; - rx_head = (rx_head + 1) % RX_BUF_SIZE; - if (rx_tail == rx_head) { + if (ring_buffer_put(&ring_buffer_data, data)) { // TODO error handling } } @@ -72,20 +69,15 @@ static bool sbus_decode(uint8_t data) { } void sbus_init(void) { - uart_init(UART_ID, UART_BAUD, EVEN, 2, uart_callback); - rx_head = 0; - rx_tail = 0; decode_byte_count = 0; - latest_data.failsafe = true; - latest_data.frame_lost = true; + ring_buffer_data = ring_buffer_init(); + uart_init(UART_ID, UART_BAUD, EVEN, 2, uart_callback); } bool sbus_data_available(void) { bool res = false; - while (rx_tail != rx_head) { - uint8_t data = rx_buf[rx_tail]; - rx_tail = (rx_tail + 1) % RX_BUF_SIZE; - + uint8_t data = 0; + while (ring_buffer_get(&ring_buffer_data, &data)) { if (sbus_decode(data)) { for (uint8_t index = 0U; index < SBUS_NUM_CHANNELS; ++index) { latest_data.channel[index] = curr_decode_data.channel[index]; diff --git a/Src/Drivers/sbus.h b/Src/Drivers/sbus.h index 69cc5fbe..c4a67ea5 100644 --- a/Src/Drivers/sbus.h +++ b/Src/Drivers/sbus.h @@ -22,8 +22,8 @@ enum { SBUS_NUM_CHANNELS = 16 }; */ typedef struct { uint16_t channel[SBUS_NUM_CHANNELS]; ///< The channel data, each channel is in [0, 2047] (11 bit) - bool failsafe; ///< Fail-safe bit of the package, set by the receiver - bool frame_lost; ///< Frame lost bit of the package set by the receiver + bool failsafe; ///< Fail-safe bit of the package, set by the receiver + bool frame_lost; ///< Frame lost bit of the package set by the receiver } sbus_data_t; /** diff --git a/Src/Messages b/Src/Messages index 67a56bb8..7b13ded2 160000 --- a/Src/Messages +++ b/Src/Messages @@ -1 +1 @@ -Subproject commit 67a56bb843c16aef8e1cf8743b4e85ee0e45b940 +Subproject commit 7b13ded2bc6a61b3c17aae0bd32a526105ae7904 diff --git a/Tests/LowLevel/CMakeLists.txt b/Tests/LowLevel/CMakeLists.txt index 5cc72914..94c19715 100644 --- a/Tests/LowLevel/CMakeLists.txt +++ b/Tests/LowLevel/CMakeLists.txt @@ -6,9 +6,6 @@ target_link_libraries(Test_Drivers_bno055_uart PRIVATE Mock_HAL_uart) make_test(Drivers/bno055) target_link_libraries(Test_Drivers_bno055 PRIVATE Mock_Drivers_bno055_uart) -make_test(Drivers/sbus) -target_link_libraries(Test_Drivers_sbus PRIVATE Mock_HAL_uart) - make_test(Drivers/ppm) target_link_libraries(Test_Drivers_ppm PRIVATE Mock_HAL_pwm16bit) target_link_libraries(Test_Drivers_ppm PRIVATE Mock_avr_io) @@ -17,6 +14,13 @@ make_test(Drivers/protobuf) target_link_libraries(Test_Drivers_protobuf PRIVATE Mock_HAL_uart) target_link_libraries(Test_Drivers_protobuf PRIVATE Mock_Messages_MessageDecoding) target_link_libraries(Test_Drivers_protobuf PRIVATE Mock_Messages_MessageEncoding) +target_link_libraries(Test_Drivers_protobuf PRIVATE Mock_Drivers_ring_buffer) + +make_test(Drivers/ring_buffer) + +make_test(Drivers/sbus) +target_link_libraries(Test_Drivers_sbus PRIVATE Mock_HAL_uart) +target_link_libraries(Test_Drivers_sbus PRIVATE Mock_Drivers_ring_buffer) make_test(Components/imu) target_link_libraries(Test_Components_imu PRIVATE Mock_Drivers_bno055) diff --git a/Tests/LowLevel/Components/imu.cpp b/Tests/LowLevel/Components/imu.cpp index a0f535db..f01423fe 100644 --- a/Tests/LowLevel/Components/imu.cpp +++ b/Tests/LowLevel/Components/imu.cpp @@ -54,7 +54,7 @@ TEST(TEST_NAME, init__config_mode_error) { [](auto /*op_mode*/, bno055_callback_t callback) { callback(write_fail); }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); EXPECT_FALSE(imu_data_available()); } @@ -75,7 +75,7 @@ TEST(TEST_NAME, init__self_test_error) { }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, read_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, read_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); EXPECT_FALSE(imu_data_available()); } @@ -185,7 +185,7 @@ TEST(TEST_NAME, init__unit_sel_error) { bno055_callback_t callback) { callback(write_fail); }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); EXPECT_FALSE(imu_data_available()); } @@ -214,7 +214,7 @@ TEST(TEST_NAME, init__remap_fail) { bno055_axis_remap_axis_t /*new_z*/, bno055_callback_t callback) { callback(write_fail); }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); EXPECT_FALSE(imu_data_available()); } @@ -246,7 +246,7 @@ TEST(TEST_NAME, init__remap_sign_fail) { bno055_axis_remap_sign_t /*new_z_sign*/, bno055_callback_t callback) { callback(write_fail); }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); } @@ -282,7 +282,7 @@ TEST(TEST_NAME, init__ndof_fail) { bno055_axis_remap_sign_t /*new_z_sign*/, bno055_callback_t callback) { callback(write_success); }); imu_init(); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, write_fail + 1)); EXPECT_FALSE(imu_get_latest_data().imu_ok); EXPECT_FALSE(imu_data_available()); } @@ -413,7 +413,7 @@ TEST(TEST_NAME, read__error_call_error_handler) { auto data = imu_get_latest_data(); EXPECT_EQ(data.imu_ok, false); - EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, read_fail+1)); + EXPECT_TRUE(errorHandlerHandle.functionGotCalled(BNO055, read_fail + 1)); } TEST(TEST_NAME, read__error_restart) { diff --git a/Tests/LowLevel/Components/system.cpp b/Tests/LowLevel/Components/system.cpp index 7ec4052b..80becdc5 100644 --- a/Tests/LowLevel/Components/system.cpp +++ b/Tests/LowLevel/Components/system.cpp @@ -111,7 +111,7 @@ TEST(TEST_NAME, timer_runtime_under_limit) { timer_8bit_callback_t internalCallback = nullptr; timerHandle.overrideFunc( [&internalCallback](timer_8bit_clock_option_t /*clock_option*/, system_timer_callback_t timerCallback) { - internalCallback = timerCallback; + internalCallback = timerCallback; }); // 12/16,384*255=186.767578125 timerHandle.overrideFunc([]() { return 186; }); @@ -134,7 +134,7 @@ TEST(TEST_NAME, timer_runtime_over_limit) { timer_8bit_callback_t internalCallback = nullptr; timerHandle.overrideFunc( [&internalCallback](timer_8bit_clock_option_t /*clock_option*/, system_timer_callback_t timerCallback) { - internalCallback = timerCallback; + internalCallback = timerCallback; }); // 12/16,384*255=186.767578125 timerHandle.overrideFunc([]() { return 187; }); diff --git a/Tests/LowLevel/Drivers/protobuf.cpp b/Tests/LowLevel/Drivers/protobuf.cpp index 88a4d087..fc256c80 100644 --- a/Tests/LowLevel/Drivers/protobuf.cpp +++ b/Tests/LowLevel/Drivers/protobuf.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -11,17 +12,21 @@ extern "C" { TEST(TEST_NAME, init) { auto uartHandle = mock::uart.getHandle(); auto decodeHandle = mock::MessageDecoding.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); protobuf_init(); EXPECT_TRUE(uartHandle.functionGotCalled(0, 115200U, NONE, 1, std::ignore)); - EXPECT_FALSE(protobuf_setpoint_available()); + EXPECT_TRUE(ringBufferHandle.functionGotCalled()); } TEST(TEST_NAME, send_fc) { auto uartHandle = mock::uart.getHandle(); auto encodingHandle = mock::MessageEncoding.getHandle(); auto decodeHandle = mock::MessageDecoding.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); protobuf_init(); @@ -59,110 +64,130 @@ TEST(TEST_NAME, send_fc) { EXPECT_TRUE(uartHandle.functionGotCalled()); } -TEST(TEST_NAME, receive_singler_buffer) { +TEST(TEST_NAME, rx_fill_buffer) { auto uartHandle = mock::uart.getHandle(); auto decodeHandle = mock::MessageDecoding.getHandle(); - uart_callback_t uartCallback; + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + ringBufferHandle.overrideFunc( + [](ring_buffer_data_t * /*ring_buffer_data*/, uint8_t /*data*/) { return true; }); + + uart_callback_t uartCallback = nullptr; uartHandle.overrideFunc([&uartCallback](uint8_t /*id*/, uint16_t /*baud*/, uart_parity_t /*parity*/, uint8_t /*stop_bits*/, uart_callback_t callback) { uartCallback = callback; }); + protobuf_init(); + + uartCallback(17); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 17)); + + uartCallback(38); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 38)); + + uartCallback(54); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 54)); +} + +TEST(TEST_NAME, available_read_buffer) { + auto uartHandle = mock::uart.getHandle(); + auto decodeHandle = mock::MessageDecoding.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + protobuf_init(); + + std::size_t count = 0; + ringBufferHandle.overrideFunc([&count](ring_buffer_data_t *ringBufferData, uint8_t *out) { + EXPECT_NE(ringBufferData, nullptr); + count += 1; + *out = count; + return count <= 4; + }); decodeHandle.overrideFunc([](message_decoding_data_t * /*messageDecodingData*/, uint8_t /*data*/, const pb_msgdesc_t * /*fields*/, void * /*message*/) -> bool { return false; }); + protobuf_setpoint_available(); + EXPECT_TRUE(decodeHandle.functionGotCalled( + std::ignore, 1, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, std::ignore)); + EXPECT_TRUE(decodeHandle.functionGotCalled( + std::ignore, 2, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, std::ignore)); + EXPECT_TRUE(decodeHandle.functionGotCalled( + std::ignore, 3, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, std::ignore)); + EXPECT_TRUE(decodeHandle.functionGotCalled( + std::ignore, 4, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, std::ignore)); +} + +TEST(TEST_NAME, receive_pb_no_decode) { + auto uartHandle = mock::uart.getHandle(); + auto decodeHandle = mock::MessageDecoding.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + protobuf_init(); - uint8_t bufData; + std::size_t count = 0; + ringBufferHandle.overrideFunc( + [&count](ring_buffer_data_t * /*ringBufferData*/, uint8_t * /*out*/) { + count += 1; + return count == 1; + }); - for (auto c = 0; c < 10; ++c) { - bufData = c * 11; - uartCallback(bufData); - protobuf_setpoint_available(); - EXPECT_TRUE(decodeHandle.functionGotCalled( - std::ignore, bufData, &ToolboxPlaneMessages_FlightControllerSetpoint_msg, std::ignore)); - } + decodeHandle.overrideFunc([](message_decoding_data_t * /*messageDecodingData*/, + uint8_t /*data*/, const pb_msgdesc_t * /*fields*/, + void * /*message*/) -> bool { return false; }); + + EXPECT_FALSE(protobuf_setpoint_available()); } -TEST(TEST_NAME, receive_200bytes) { +TEST(TEST_NAME, receive_pb_yes_decode) { auto uartHandle = mock::uart.getHandle(); auto decodeHandle = mock::MessageDecoding.getHandle(); - uart_callback_t uartCallback; - uartHandle.overrideFunc([&uartCallback](uint8_t /*id*/, uint16_t /*baud*/, uart_parity_t /*parity*/, - uint8_t /*stop_bits*/, - uart_callback_t callback) { uartCallback = callback; }); - int receiveIndex = 10U; - decodeHandle.overrideFunc( - [&receiveIndex](message_decoding_data_t * /*messageDecodingData*/, uint8_t data, - const pb_msgdesc_t * /*fields*/, void * /*message*/) -> bool { - EXPECT_EQ(receiveIndex, data); - receiveIndex += 1; - return false; - }); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); protobuf_init(); - for (auto c = 10U; c < 210U; ++c) { - uartCallback(c); - } - protobuf_setpoint_available(); - EXPECT_EQ(receiveIndex, 210U); + std::size_t count = 0; + ringBufferHandle.overrideFunc( + [&count](ring_buffer_data_t * /*ringBufferData*/, uint8_t * /*out*/) { + count += 1; + return count == 1; + }); + decodeHandle.overrideFunc([](message_decoding_data_t * /*messageDecodingData*/, + uint8_t /*data*/, const pb_msgdesc_t * /*fields*/, + void * /*message*/) -> bool { return true; }); - for (auto c = 20U; c < 220U; ++c) { - uartCallback(c); - } - receiveIndex = 20U; - protobuf_setpoint_available(); - EXPECT_EQ(receiveIndex, 220U); + EXPECT_TRUE(protobuf_setpoint_available()); } -TEST(TEST_NAME, receive_pb_decode) { +TEST(TEST_NAME, receive_pb_decode_data) { auto uartHandle = mock::uart.getHandle(); auto decodeHandle = mock::MessageDecoding.getHandle(); - uart_callback_t uartCallback; - uartHandle.overrideFunc([&uartCallback](uint8_t /*id*/, uint16_t /*baud*/, uart_parity_t /*parity*/, - uint8_t /*stop_bits*/, - uart_callback_t callback) { uartCallback = callback; }); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); protobuf_init(); - // echo "power: 1337, pitch: 17, roll: 34 | protoc - // --encode=ToolboxPlaneMessages.FlightControllerSetpoint Src/Messages/Definitions/FlightControllerSetpoint.proto - // | xxd - std::vector callbackData{{0x08, 0xb9, 0x0a, 0x10, 0x11, 0x18, 0x22}}; - std::size_t dataSendIndex = 0; - std::size_t dataDecodeIndex = 0; - - decodeHandle.overrideFunc( - [&callbackData, &dataDecodeIndex](message_decoding_data_t *messageDecodingData, uint8_t data, - const pb_msgdesc_t *fields, void *message) -> bool { - EXPECT_EQ(callbackData[dataDecodeIndex], data); - EXPECT_NE(messageDecodingData, nullptr); - EXPECT_EQ(fields, &ToolboxPlaneMessages_FlightControllerSetpoint_msg); - EXPECT_NE(message, nullptr); - dataDecodeIndex += 1; - if (dataDecodeIndex == callbackData.size()) { - auto fcData = static_cast(message); - fcData->motor = 1337; - fcData->pitch = 17; - fcData->roll = 34; - return true; - } - return false; + std::size_t count = 0; + ringBufferHandle.overrideFunc( + [&count](ring_buffer_data_t * /*ringBufferData*/, uint8_t * /*out*/) { + count += 1; + return count == 1; }); - for (; dataSendIndex < callbackData.size(); ++dataSendIndex) { - EXPECT_FALSE(protobuf_setpoint_available()); - uartCallback(callbackData[dataSendIndex]); - if (dataSendIndex == callbackData.size() - 1) { - EXPECT_TRUE(protobuf_setpoint_available()); - - auto setpoint = protobuf_get_setpoint(); - EXPECT_EQ(setpoint.motor, 1337); - EXPECT_EQ(setpoint.pitch, 17); - EXPECT_EQ(setpoint.roll, 34); - } else { - EXPECT_FALSE(protobuf_setpoint_available()); - } - } + decodeHandle.overrideFunc([](message_decoding_data_t * /*messageDecodingData*/, + uint8_t /*data*/, const pb_msgdesc_t * /*fields*/, + void *message) -> bool { + auto fcData = static_cast(message); + fcData->motor = 1337; + fcData->pitch = 17; + fcData->roll = 34; + return true; + }); + + EXPECT_TRUE(protobuf_setpoint_available()); + EXPECT_EQ(protobuf_get_setpoint().motor, 1337); + EXPECT_EQ(protobuf_get_setpoint().pitch, 17); + EXPECT_EQ(protobuf_get_setpoint().roll, 34); } diff --git a/Tests/LowLevel/Drivers/ring_buffer.cpp b/Tests/LowLevel/Drivers/ring_buffer.cpp new file mode 100644 index 00000000..48fd6743 --- /dev/null +++ b/Tests/LowLevel/Drivers/ring_buffer.cpp @@ -0,0 +1,77 @@ +#include + +extern "C" { +#include +} + +TEST(TEST_NAME, init) { + auto ringBufferData = ring_buffer_init(); + EXPECT_EQ(ringBufferData.len, 0); + uint8_t tmp = 255; + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); +} + +TEST(TEST_NAME, single) { + auto ringBufferData = ring_buffer_init(); + uint8_t tmp = 255; + + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 17)); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 17); + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); + + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 37)); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 37); + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); +} + +TEST(TEST_NAME, blockwise) { + auto ringBufferData = ring_buffer_init(); + uint8_t tmp = 255; + + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 17)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 18)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 19)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 20)); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 17); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 18); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 19); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 20); + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); + + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 37)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 38)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 39)); + EXPECT_TRUE(ring_buffer_put(&ringBufferData, 40)); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 37); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 38); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 39); + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, 40); + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); +} + +TEST(TEST_NAME, full) { + auto ringBufferData = ring_buffer_init(); + uint8_t tmp = 255; + + for (uint16_t c = 0; c < RING_BUFFER_SIZE; ++c) { + EXPECT_TRUE(ring_buffer_put(&ringBufferData, (c * 2) % 251)); + } + EXPECT_FALSE(ring_buffer_put(&ringBufferData, 1)); + + + for (uint16_t c = 0; c < RING_BUFFER_SIZE; ++c) { + EXPECT_TRUE(ring_buffer_get(&ringBufferData, &tmp)); + EXPECT_EQ(tmp, (c * 2) % 251); + } + EXPECT_FALSE(ring_buffer_get(&ringBufferData, &tmp)); +} diff --git a/Tests/LowLevel/Drivers/sbus.cpp b/Tests/LowLevel/Drivers/sbus.cpp index ed380e3e..06b0b19f 100644 --- a/Tests/LowLevel/Drivers/sbus.cpp +++ b/Tests/LowLevel/Drivers/sbus.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -7,6 +8,10 @@ extern "C" { TEST(TEST_NAME, init) { auto uartHandler = mock::uart.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + ringBufferHandle.overrideFunc( + [](ring_buffer_data_t * /*ring_buffer_data*/, uint8_t /*data*/) { return true; }); sbus_init(); /* * https://github.com/bolderflight/sbus/blob/main/README.md: @@ -14,17 +19,52 @@ TEST(TEST_NAME, init) { * bits */ EXPECT_TRUE(uartHandler.functionGotCalled(2, 100000U, EVEN, 2, std::ignore)); - EXPECT_FALSE(sbus_data_available()); + EXPECT_TRUE(ringBufferHandle.functionGotCalled()); } -TEST(TEST_NAME, decode) { - auto uartHandler = mock::uart.getHandle(); +TEST(TEST_NAME, rx_fill_buffer) { + auto uartHandle = mock::uart.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + ringBufferHandle.overrideFunc( + [](ring_buffer_data_t * /*ring_buffer_data*/, uint8_t /*data*/) { return true; }); + uart_callback_t uartCallback = nullptr; - uartHandler.overrideFunc([&uartCallback](uint8_t /*id*/, uint32_t /*baud*/, uart_parity_t /*parity*/, - uint8_t /*stop_bits*/, - uart_callback_t rx_callback) { uartCallback = rx_callback; }); + uartHandle.overrideFunc([&uartCallback](uint8_t /*id*/, uint16_t /*baud*/, uart_parity_t /*parity*/, + uint8_t /*stop_bits*/, + uart_callback_t callback) { uartCallback = callback; }); + sbus_init(); + + uartCallback(17); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 17)); + + uartCallback(38); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 38)); + + uartCallback(54); + EXPECT_TRUE(ringBufferHandle.functionGotCalled(std::ignore, 54)); +} + +TEST(TEST_NAME, available_read_buffer) { + auto uartHandle = mock::uart.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); sbus_init(); + std::size_t count = 0; + ringBufferHandle.overrideFunc([&count](ring_buffer_data_t *ringBufferData, uint8_t *out) { + EXPECT_NE(ringBufferData, nullptr); + count += 1; + *out = count; + return count <= 4; + }); +} + +TEST(TEST_NAME, decode) { + auto uartHandler = mock::uart.getHandle(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); + /* * https://github.com/bolderflight/sbus/blob/main/README.md: * @@ -38,38 +78,40 @@ TEST(TEST_NAME, decode) { * - Bit 3: failsafe activated (0x08) * - Byte[24]: SBUS footer */ - uint8_t data[] = {/* 0 */ 0x0F, - /* 1 */ (uint8_t) (1 << 0), - /* 2 */ (uint8_t) (2 << 3 | 1 >> 8), - /* 3 */ (uint8_t) (3 << 6 | 2 >> 5), - /* 4 */ (uint8_t) (3 >> 2), - /* 5 */ (uint8_t) (4 << 1 | 3 >> 10), - /* 6 */ (uint8_t) (5 << 4 | 4 >> 7), - /* 7 */ (uint8_t) (6 << 7 | 5 >> 4), - /* 8 */ (uint8_t) (6 >> 1), - /* 9 */ (uint8_t) (7 << 2 | 6 >> 9), - /* 10 */ (uint8_t) (8 << 5 | 7 >> 6), - /* 11 */ (uint8_t) (8 >> 3), - /* 12 */ (uint8_t) (9 << 0), - /* 13 */ (uint8_t) (10 << 3 | 9 >> 8), - /* 14 */ (uint8_t) (11 << 6 | 10 >> 5), - /* 15 */ (uint8_t) (11 >> 2), - /* 16 */ (uint8_t) (12 << 1 | 11 >> 10), - /* 17 */ (uint8_t) (13 << 4 | 12 >> 7), - /* 18 */ (uint8_t) (14 << 7 | 13 >> 4), - /* 19 */ (uint8_t) (14 >> 1), - /* 20 */ (uint8_t) (15 << 2 | 14 >> 9), - /* 21 */ (uint8_t) (16 << 5 | 15 >> 6), - /* 22 */ (uint8_t) (16 >> 3), - /* 23 */ 0b00, - /* 24 */ 0x00}; - - for (const uint8_t c : data) { - EXPECT_TRUE(sbus_get_latest_data().failsafe); - EXPECT_TRUE(sbus_get_latest_data().frame_lost); - EXPECT_FALSE(sbus_data_available()); - uartCallback(c); - } + std::vector data = {/* 0 */ 0x0F, + /* 1 */ (uint8_t) (1 << 0), + /* 2 */ (uint8_t) (2 << 3 | 1 >> 8), + /* 3 */ (uint8_t) (3 << 6 | 2 >> 5), + /* 4 */ (uint8_t) (3 >> 2), + /* 5 */ (uint8_t) (4 << 1 | 3 >> 10), + /* 6 */ (uint8_t) (5 << 4 | 4 >> 7), + /* 7 */ (uint8_t) (6 << 7 | 5 >> 4), + /* 8 */ (uint8_t) (6 >> 1), + /* 9 */ (uint8_t) (7 << 2 | 6 >> 9), + /* 10 */ (uint8_t) (8 << 5 | 7 >> 6), + /* 11 */ (uint8_t) (8 >> 3), + /* 12 */ (uint8_t) (9 << 0), + /* 13 */ (uint8_t) (10 << 3 | 9 >> 8), + /* 14 */ (uint8_t) (11 << 6 | 10 >> 5), + /* 15 */ (uint8_t) (11 >> 2), + /* 16 */ (uint8_t) (12 << 1 | 11 >> 10), + /* 17 */ (uint8_t) (13 << 4 | 12 >> 7), + /* 18 */ (uint8_t) (14 << 7 | 13 >> 4), + /* 19 */ (uint8_t) (14 >> 1), + /* 20 */ (uint8_t) (15 << 2 | 14 >> 9), + /* 21 */ (uint8_t) (16 << 5 | 15 >> 6), + /* 22 */ (uint8_t) (16 >> 3), + /* 23 */ 0b00, + /* 24 */ 0x00}; + std::size_t count = 0; + ringBufferHandle.overrideFunc([&count, data](ring_buffer_data_t *ringBufferData, uint8_t *out) { + EXPECT_NE(ringBufferData, nullptr); + *out = data[count]; + count += 1; + return count <= data.size(); + }); + + sbus_init(); EXPECT_TRUE(sbus_data_available()); EXPECT_FALSE(sbus_get_latest_data().failsafe); @@ -82,23 +124,23 @@ TEST(TEST_NAME, decode) { TEST(TEST_NAME, decode_failsave) { auto uartHandler = mock::uart.getHandle(); - uart_callback_t uartCallback = nullptr; - uartHandler.overrideFunc([&uartCallback](uint8_t /*id*/, uint32_t /*baud*/, uart_parity_t /*parity*/, - uint8_t /*stop_bits*/, - uart_callback_t rx_callback) { uartCallback = rx_callback; }); - sbus_init(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); - uint8_t data[25] = {0}; + std::vector data(25); data[0] = 0x0F; data[23] = 0x08; data[24] = 0; - for (const uint8_t c : data) { - EXPECT_TRUE(sbus_get_latest_data().failsafe); - EXPECT_TRUE(sbus_get_latest_data().frame_lost); - EXPECT_FALSE(sbus_data_available()); - uartCallback(c); - } + std::size_t count = 0; + ringBufferHandle.overrideFunc([&count, data](ring_buffer_data_t *ringBufferData, uint8_t *out) { + EXPECT_NE(ringBufferData, nullptr); + *out = data[count]; + count += 1; + return count <= data.size(); + }); + + sbus_init(); EXPECT_TRUE(sbus_data_available()); EXPECT_TRUE(sbus_get_latest_data().failsafe); @@ -111,23 +153,26 @@ TEST(TEST_NAME, decode_failsave) { TEST(TEST_NAME, decode_framelost) { auto uartHandler = mock::uart.getHandle(); - uart_callback_t uartCallback = nullptr; - uartHandler.overrideFunc([&uartCallback](uint8_t /*id*/, uint32_t /*baud*/, uart_parity_t /*parity*/, - uint8_t /*stop_bits*/, - uart_callback_t rx_callback) { uartCallback = rx_callback; }); - sbus_init(); + auto ringBufferHandle = mock::ring_buffer.getHandle(); + ringBufferHandle.overrideFunc([]() { return ring_buffer_data_t{}; }); - uint8_t data[25] = {0}; + std::vector data(25); data[0] = 0x0F; data[23] = 0x04; data[24] = 0; - for (const uint8_t c : data) { - EXPECT_TRUE(sbus_get_latest_data().failsafe); - EXPECT_TRUE(sbus_get_latest_data().frame_lost); - EXPECT_FALSE(sbus_data_available()); - uartCallback(c); - } + std::size_t count = 0; + ringBufferHandle.overrideFunc([&count, data](ring_buffer_data_t *ringBufferData, uint8_t *out) { + EXPECT_NE(ringBufferData, nullptr); + *out = data[count]; + count += 1; + return count <= data.size(); + }); + uart_callback_t uartCallback = nullptr; + uartHandler.overrideFunc([&uartCallback](uint8_t /*id*/, uint32_t /*baud*/, uart_parity_t /*parity*/, + uint8_t /*stop_bits*/, + uart_callback_t rx_callback) { uartCallback = rx_callback; }); + sbus_init(); EXPECT_TRUE(sbus_data_available()); EXPECT_FALSE(sbus_get_latest_data().failsafe); diff --git a/Tests/LowLevel/Mock/CMakeLists.txt b/Tests/LowLevel/Mock/CMakeLists.txt index 40c12b85..5912fec8 100644 --- a/Tests/LowLevel/Mock/CMakeLists.txt +++ b/Tests/LowLevel/Mock/CMakeLists.txt @@ -3,9 +3,10 @@ add_subdirectory(Lib) set(MockedModules Drivers/bno055 Drivers/bno055_uart + Drivers/ppm Drivers/protobuf + Drivers/ring_buffer Drivers/sbus - Drivers/ppm HAL/adc HAL/i2c HAL/pwm16bit