Implement virtual com port receiver

This commit is contained in:
BlackMark 2020-06-28 21:22:17 +02:00
parent 3d0cce0db4
commit e0bb399415
5 changed files with 79 additions and 3 deletions

View File

@ -0,0 +1,53 @@
#pragma once
#include <algorithm>
#include <cstdint>
#include <cstring>
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<size_t Size>
struct RingBuffer {
size_t head = 0;
size_t tail = 0;
uint8_t data[Size];
};
static volatile RingBuffer<detail::VCP_RECEIVE_BUFFER_SIZE> 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
}
}
};

View File

@ -74,7 +74,8 @@ Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
# C++ sources # C++ sources
CXX_SOURCES = \ CXX_SOURCES = \
Src/main.cpp Src/main.cpp \
Src/vcp_receiver.cpp
# ASM sources # ASM sources
ASM_SOURCES = \ ASM_SOURCES = \

View File

@ -7,6 +7,7 @@
#include "init.h" #include "init.h"
#include "usbd_cdc_if.h" #include "usbd_cdc_if.h"
#include "utils.hpp" #include "utils.hpp"
#include "vcp_receiver.hpp"
std::array<uint16_t, 3> sampleLightSensors() std::array<uint16_t, 3> sampleLightSensors()
{ {
@ -31,6 +32,8 @@ int main()
{ {
init(); init();
VcpReceiver vcpReceiver;
HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET); 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(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_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(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_SET);
uint8_t data = 0;
while(true) { while(true) {
if(vcpReceiver.rxByte(data)) {
CDC_Transmit_FS(&data, 1);
}
const auto ldrValues = sampleLightSensors(); const auto ldrValues = sampleLightSensors();
HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_RESET); 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) { for(uint8_t i = 0; i < ldrValues.size(); ++i) {
const auto ldrID = i + 1; const auto ldrID = i + 1;
const auto percentage = ldrValues[i] * 100 / 0xFFF; const auto percentage = ldrValues[i] * 100 / 0xFFF;
const auto bufLen = const auto bufLen = std::sprintf(reinterpret_cast<char*>(printBuffer.data()), "LDR%d: %04hu - %03d%%\r\n%s", ldrID, ldrValues[i], percentage,
std::sprintf(reinterpret_cast<char*>(printBuffer.data()), "LDR%d: %04hu - %03d%%\r\n%s", ldrID, ldrValues[i], percentage, (i == 2) ? "\r\n" : ""); (i == 2) ? "\r\n" : "");
if(bufLen > 0) { if(bufLen > 0) {
while(CDC_Transmit_FS(printBuffer.data(), bufLen) == USBD_BUSY) while(CDC_Transmit_FS(printBuffer.data(), bufLen) == USBD_BUSY)
; ;

View File

@ -246,6 +246,8 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
/* USER CODE END 5 */ /* 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 * @brief Data received over USB OUT endpoint are sent over CDC interface
* through this function. * through this function.
@ -265,6 +267,7 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
/* USER CODE BEGIN 6 */ /* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS); USBD_CDC_ReceivePacket(&hUsbDeviceFS);
vcpReceiveCallback(Buf, *Len);
return (USBD_OK); return (USBD_OK);
/* USER CODE END 6 */ /* USER CODE END 6 */
} }

View File

@ -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<detail::VCP_RECEIVE_BUFFER_SIZE> VcpReceiver::m_receiveBuffer;