RISC-V/V203/usb/usart/main.cpp

77 lines
2.4 KiB
C++
Raw Normal View History

2024-10-15 19:26:19 +02:00
#include "cdc_class.h"
#include "usart.h"
#include "mirror.h"
2024-10-16 19:34:04 +02:00
static constexpr unsigned Timeout = 5000; // us
2024-10-15 19:26:19 +02:00
/** Převodník USB_CDC - USART
* Datový formát je pevný - 8 bit, 1 stop bit, bez parity.
* Změnu po USB by šlo dost jednoduše dodělat, ale nepovažoval jsem to za nutné.
* Baudová rychlost se po USB změnit na libovolnou hodnotu.
*
* Výhoda tohoto řešení je, že nad USARTem může běžet nějaký protokol
2024-10-16 15:46:34 +02:00
* přímo v tomto čipu. Jinak je to asi nejlevnější řešení.
*
* @class Middle
* Zkracuje obsluhu přerušení od USART1 čí podstatně zlepší činnost
* v plném duplexu. Je možné z řetězce vyhodit. Je to také ukázka
* jak přidat funkci (třeba vlastní protokol) do řetězce.
2024-10-15 19:26:19 +02:00
* */
2024-10-16 15:46:34 +02:00
class Middle : public BaseLayer {
static constexpr unsigned max = 128;
volatile unsigned index;
char buffer [max];
public:
explicit Middle () noexcept : BaseLayer(), index(0u) {}
/* Up() v původním řetězci volalo fakticky Down() v cdc_class.
* Vzhledem k tomu, že len je zde 1 a USB musí vyvolat odeslání
* paketu, zdržuje to a přerušení zde může být ignorováno.
* Tohle ho významně zkrátí, ale zase musí být v hlavní smyčce
* odeslání dat pomocí metody pass().
* */
uint32_t Up(const char * data, const uint32_t len) override {
for (unsigned n=0; n<len; n++) buffer [index++] = data [n];
return len;
}
// Down je průchozí, bylo by možné toto zcela vypustit.
uint32_t Down(const char * data, const uint32_t len) override {
return BaseLayer::Down(data, len);
}
/* Vlastní odeslání paketu na USB_CDC
* */
void pass () {
2024-10-16 19:34:04 +02:00
/* Je to dost zjednodušeno, odešle se 64 bytový paket,
* nebo po 5 ms to co zůstalo v bufferu.
2024-10-16 15:46:34 +02:00
* */
2024-10-16 19:34:04 +02:00
if ((is_timeout() and index) or (index >= 64)) {
block(buffer, index);
2024-10-16 15:46:34 +02:00
}
}
2024-10-16 19:34:04 +02:00
protected:
void block (const char * data, const uint32_t len) {
unsigned ofs = 0, rem = len;
while (rem) {
const unsigned n = BaseLayer::Up(data + ofs, rem);
rem -= n;
ofs += n;
}
index = 0;
set_timeout_us(Timeout);
}
2024-10-16 15:46:34 +02:00
};
2024-10-15 19:26:19 +02:00
static cdc_class cdc;
static Usart usart;
static Mirror top;
2024-10-16 15:46:34 +02:00
static Middle mid;
2024-10-15 19:26:19 +02:00
int main () {
cdc.init();
top += cdc;
2024-10-16 15:46:34 +02:00
top -= mid += usart;
2024-10-15 19:26:19 +02:00
cdc.attach(usart);
2024-10-16 19:34:04 +02:00
set_timeout_us(Timeout);
2024-10-15 19:26:19 +02:00
for (;;) {
2024-10-16 15:46:34 +02:00
mid.pass();
2024-10-15 19:26:19 +02:00
}
return 0;
}