Open
Description
I have a suggestion to add to EmIL:
struct SerialCommunicationBufferedReceive: hal::SerialCommunication
{
SerialCommunicationBufferedReceive(hal::SerialCommunication& sercom)
: sercom{sercom}
, queue{[this]() {
while (!queue.Empty())
{
const auto range = queue.ContiguousRange();
dataReceived(range);
queue.Consume(range.size());
}
}}
{
sercom.ReceiveData([this](infra::ConstByteRange range) { queue.AddFromInterrupt(range); });
}
void SendData(infra::ConstByteRange data, infra::Function<void()> actionOnCompletion) override
{
sercom.SendData(data, actionOnCompletion);
}
void ReceiveData(infra::Function<void(infra::ConstByteRange data)> dataReceived) override
{
this->dataReceived = dataReceived;
}
hal::SerialCommunication& sercom;
infra::QueueForOneReaderOneIrqWriter<std::uint8_t>::WithStorage<128> queue;
infra::Function<void(infra::ConstByteRange data)> dataReceived;
};
queue size could be made configurable or as a ::WithSize
type of implementation.
Some modules (EchoOnSerial for instance) perform all the handling on interrupt. In a "normal" situation where CPU speed is high and baudrate is slow this is fine. However, once your baudrate is high enough bytes will be missed.
There are two ways to tackle such situation. Adapt EchoOnSerial to not process the bytes on interrupt and do the receive queue manually. Or by adding a decorater like the above. The latter having my preference as this class is versatile enough that it could be used for other situations as well.