From e0bb3994151960b90db58499c0c41fc8c614122e Mon Sep 17 00:00:00 2001 From: BlackMark Date: Sun, 28 Jun 2020 21:22:17 +0200 Subject: [PATCH] Implement virtual com port receiver --- .../Inc/vcp_receiver.hpp | 53 +++++++++++++++++++ AdaptiveBrightnessFirmware/Makefile | 3 +- AdaptiveBrightnessFirmware/Src/main.cpp | 13 ++++- AdaptiveBrightnessFirmware/Src/usbd_cdc_if.c | 3 ++ .../Src/vcp_receiver.cpp | 10 ++++ 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 AdaptiveBrightnessFirmware/Inc/vcp_receiver.hpp create mode 100644 AdaptiveBrightnessFirmware/Src/vcp_receiver.cpp diff --git a/AdaptiveBrightnessFirmware/Inc/vcp_receiver.hpp b/AdaptiveBrightnessFirmware/Inc/vcp_receiver.hpp new file mode 100644 index 0000000..a410473 --- /dev/null +++ b/AdaptiveBrightnessFirmware/Inc/vcp_receiver.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include + +extern "C" void vcpReceiveCallback(uint8_t*, uint32_t); + +namespace detail { + +constexpr auto VCP_RECEIVE_BUFFER_SIZE = 64; + +} // namespace detail + +class VcpReceiver { + public: + static inline bool rxByte(uint8_t& data) + { + if(m_receiveBuffer.head == m_receiveBuffer.tail) + return false; + + const uint8_t newTail = (m_receiveBuffer.tail + 1) % detail::VCP_RECEIVE_BUFFER_SIZE; + data = m_receiveBuffer.data[newTail]; + m_receiveBuffer.tail = newTail; + + return true; + } + + private: + friend void vcpReceiveCallback(uint8_t*, uint32_t); + + template + struct RingBuffer { + size_t head = 0; + size_t tail = 0; + uint8_t data[Size]; + }; + + static volatile RingBuffer m_receiveBuffer; + + static inline void rxHandler(const uint8_t& data) + { + const uint8_t newHead = (m_receiveBuffer.head + 1) % detail::VCP_RECEIVE_BUFFER_SIZE; + + if(newHead != m_receiveBuffer.tail) { + m_receiveBuffer.head = newHead; + m_receiveBuffer.data[newHead] = data; + } + else { + // TODO: Handle overflow + } + } +}; diff --git a/AdaptiveBrightnessFirmware/Makefile b/AdaptiveBrightnessFirmware/Makefile index 1edeefd..c08a4e4 100644 --- a/AdaptiveBrightnessFirmware/Makefile +++ b/AdaptiveBrightnessFirmware/Makefile @@ -74,7 +74,8 @@ Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c # C++ sources CXX_SOURCES = \ -Src/main.cpp +Src/main.cpp \ +Src/vcp_receiver.cpp # ASM sources ASM_SOURCES = \ diff --git a/AdaptiveBrightnessFirmware/Src/main.cpp b/AdaptiveBrightnessFirmware/Src/main.cpp index ccda663..c42d4f7 100644 --- a/AdaptiveBrightnessFirmware/Src/main.cpp +++ b/AdaptiveBrightnessFirmware/Src/main.cpp @@ -7,6 +7,7 @@ #include "init.h" #include "usbd_cdc_if.h" #include "utils.hpp" +#include "vcp_receiver.hpp" std::array sampleLightSensors() { @@ -31,6 +32,8 @@ int main() { init(); + VcpReceiver vcpReceiver; + HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_RESET); @@ -41,7 +44,13 @@ int main() HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_SET); + uint8_t data = 0; + while(true) { + if(vcpReceiver.rxByte(data)) { + CDC_Transmit_FS(&data, 1); + } + const auto ldrValues = sampleLightSensors(); HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_RESET); @@ -51,8 +60,8 @@ int main() for(uint8_t i = 0; i < ldrValues.size(); ++i) { const auto ldrID = i + 1; const auto percentage = ldrValues[i] * 100 / 0xFFF; - const auto bufLen = - std::sprintf(reinterpret_cast(printBuffer.data()), "LDR%d: %04hu - %03d%%\r\n%s", ldrID, ldrValues[i], percentage, (i == 2) ? "\r\n" : ""); + const auto bufLen = std::sprintf(reinterpret_cast(printBuffer.data()), "LDR%d: %04hu - %03d%%\r\n%s", ldrID, ldrValues[i], percentage, + (i == 2) ? "\r\n" : ""); if(bufLen > 0) { while(CDC_Transmit_FS(printBuffer.data(), bufLen) == USBD_BUSY) ; diff --git a/AdaptiveBrightnessFirmware/Src/usbd_cdc_if.c b/AdaptiveBrightnessFirmware/Src/usbd_cdc_if.c index cff2042..fbd2585 100644 --- a/AdaptiveBrightnessFirmware/Src/usbd_cdc_if.c +++ b/AdaptiveBrightnessFirmware/Src/usbd_cdc_if.c @@ -246,6 +246,8 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) /* USER CODE END 5 */ } +extern void vcpReceiveCallback(uint8_t* buf, uint32_t len); + /** * @brief Data received over USB OUT endpoint are sent over CDC interface * through this function. @@ -265,6 +267,7 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hUsbDeviceFS); + vcpReceiveCallback(Buf, *Len); return (USBD_OK); /* USER CODE END 6 */ } diff --git a/AdaptiveBrightnessFirmware/Src/vcp_receiver.cpp b/AdaptiveBrightnessFirmware/Src/vcp_receiver.cpp new file mode 100644 index 0000000..d56bada --- /dev/null +++ b/AdaptiveBrightnessFirmware/Src/vcp_receiver.cpp @@ -0,0 +1,10 @@ +#include "vcp_receiver.hpp" + +extern "C" void vcpReceiveCallback(uint8_t* buf, uint32_t len) +{ + for(uint32_t i = 0; i < len; ++i) { + VcpReceiver::rxHandler(buf[i]); + } +} + +volatile VcpReceiver::RingBuffer VcpReceiver::m_receiveBuffer;