Implement serial interaction
This commit is contained in:
parent
d1f9e3d88c
commit
e2a64ac231
4 changed files with 124 additions and 0 deletions
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <FreeRTOS/Queue.h>
|
||||||
|
#include <FreeRTOS/Task.h>
|
||||||
|
#include <FreeRTOS/Util.h>
|
||||||
|
#include <Messages/Message.h>
|
||||||
|
#include <Util/CircularBuffer.h>
|
||||||
|
#include <etl/string.h>
|
||||||
|
|
||||||
|
namespace comm {
|
||||||
|
namespace serial {
|
||||||
|
template <size_t bufferSize = 20> class SerialReceiver {
|
||||||
|
public:
|
||||||
|
SerialReceiver(HardwareSerial &port,
|
||||||
|
freertos::Queue<message::Message *> &messageQueue,
|
||||||
|
UBaseType_t priority, BaseType_t coreID)
|
||||||
|
: port{port}, messageQueue{messageQueue},
|
||||||
|
serialReceiverTask{
|
||||||
|
exec, "receive serial data", stackDepth, this, priority, coreID} {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void exec(void *receiverPtr) {
|
||||||
|
freertos::sleep(20); // wait until Serial port has been initialized
|
||||||
|
SerialReceiver<bufferSize> *receiver =
|
||||||
|
static_cast<SerialReceiver<bufferSize> *>(receiverPtr);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
receiver->magicNumberBuf.clear();
|
||||||
|
receiver->magicNumberBuf.resize(receiver->magicNumber.length());
|
||||||
|
size_t availableBytes = receiver->port.available();
|
||||||
|
if (availableBytes >= receiver->magicNumber.length() + 1) {
|
||||||
|
receiver->port.readBytes(receiver->magicNumberBuf.data(),
|
||||||
|
receiver->magicNumber.length());
|
||||||
|
receiver->port.println(receiver->magicNumberBuf ==
|
||||||
|
receiver->magicNumber);
|
||||||
|
|
||||||
|
uint8_t size;
|
||||||
|
receiver->port.readBytes(&size, sizeof(size));
|
||||||
|
if (receiver->port.available() >= size) {
|
||||||
|
message::Message &msg = receiver->buffer.pop();
|
||||||
|
msg.second.lock();
|
||||||
|
msg.first.clear();
|
||||||
|
msg.first.resize(size);
|
||||||
|
receiver->port.readBytes(msg.first.data(), size);
|
||||||
|
msg.second.unlock();
|
||||||
|
receiver->messageQueue.push(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HardwareSerial &port;
|
||||||
|
freertos::Queue<message::Message *> &messageQueue;
|
||||||
|
etl::string<4> magicNumberBuf;
|
||||||
|
const etl::string<2> magicNumber{"HX"};
|
||||||
|
util::CircularBuffer<message::Message, bufferSize> buffer;
|
||||||
|
freertos::Task serialReceiverTask;
|
||||||
|
static const uint32_t stackDepth = 2048;
|
||||||
|
};
|
||||||
|
} // namespace serial
|
||||||
|
} // namespace comm
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <Communication/Serial/SerialSender.h>
|
||||||
|
|
||||||
|
comm::serial::SerialSender::SerialSender(HardwareSerial &port,
|
||||||
|
UBaseType_t queueCapacity,
|
||||||
|
UBaseType_t priority,
|
||||||
|
BaseType_t coreID)
|
||||||
|
: port{port}, messages{queueCapacity}, SerialSenderTask{
|
||||||
|
exec, "send serial data",
|
||||||
|
stackDepth, this,
|
||||||
|
priority, coreID} {}
|
||||||
|
|
||||||
|
void comm::serial::SerialSender::exec(void *senderPtr) {
|
||||||
|
SerialSender *sender = static_cast<SerialSender *>(senderPtr);
|
||||||
|
freertos::sleep(20); // wait until Serial port has been initialized
|
||||||
|
while (true) {
|
||||||
|
if (!sender->port.availableForWrite()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto message = sender->messages.pop();
|
||||||
|
if (message.has_value()) {
|
||||||
|
sender->port.write(message.value().data(), message.value().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <FreeRTOS/Queue.h>
|
||||||
|
#include <FreeRTOS/Task.h>
|
||||||
|
#include <FreeRTOS/Util.h>
|
||||||
|
#include <Messages/Message.h>
|
||||||
|
#include <Util/CircularBuffer.h>
|
||||||
|
#include <etl/span.h>
|
||||||
|
#include <etl/string.h>
|
||||||
|
|
||||||
|
namespace comm {
|
||||||
|
namespace serial {
|
||||||
|
class SerialSender {
|
||||||
|
public:
|
||||||
|
SerialSender(HardwareSerial &port, UBaseType_t queueCapacity,
|
||||||
|
UBaseType_t priority, BaseType_t coreID);
|
||||||
|
freertos::Queue<etl::span<uint8_t>> &getMessageQueue() { return messages; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void exec(void *senderPtr);
|
||||||
|
HardwareSerial &port;
|
||||||
|
freertos::Queue<etl::span<uint8_t>> messages;
|
||||||
|
freertos::Task SerialSenderTask;
|
||||||
|
static const uint32_t stackDepth = 2048;
|
||||||
|
};
|
||||||
|
} // namespace serial
|
||||||
|
} // namespace comm
|
12
modules/control/Firmware/src/Messages/Message.h
Normal file
12
modules/control/Firmware/src/Messages/Message.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <FreeRTOS/Mutex.h>
|
||||||
|
#include <Messages/Protocol.h>
|
||||||
|
#include <etl/utility.h>
|
||||||
|
#include <etl/vector.h>
|
||||||
|
|
||||||
|
namespace message {
|
||||||
|
using Message =
|
||||||
|
etl::pair<etl::vector<uint8_t, message::protocol::MAX_PAYLOAD_LEN>,
|
||||||
|
freertos::Mutex>;
|
||||||
|
} // namespace message
|
Reference in a new issue