From 71e602397826026f332e7a11b6c7f6ec9ac95713 Mon Sep 17 00:00:00 2001
From: Kizarm <mrazik@volny.cz>
Date: Wed, 16 Oct 2024 15:46:34 +0200
Subject: [PATCH] test cdc-usart

---
 V203/usb/usart/main.cpp       | 47 ++++++++++++++++++++++++++++++++---
 V203/usb/usart/test/main.cpp  |  2 +-
 V203/usb/usart/test/usart.cpp |  3 ++-
 3 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/V203/usb/usart/main.cpp b/V203/usb/usart/main.cpp
index 57dd43f..59d7cfb 100644
--- a/V203/usb/usart/main.cpp
+++ b/V203/usb/usart/main.cpp
@@ -7,19 +7,58 @@
  * Baudová rychlost se dá po USB změnit na libovolnou hodnotu.
  * 
  * Výhoda tohoto řešení je, že nad USARTem může běžet nějaký protokol
- * přímo v tomto čipu. Jinak je to asi nejlevnější řešení. Zřejmě to
- * nebude snášet velké rychlosti (nad 115200 Bd).
+ * přímo v tomto čipu. Jinak je to asi nejlevnější řešení.
+ * 
+ * @class Middle
+ * Zkracuje obsluhu přerušení od USART1 čímž podstatně zlepší činnost
+ * v plném duplexu. Je možné jí z řetězce vyhodit. Je to také ukázka
+ * jak přidat funkci (třeba vlastní protokol) do řetězce.
  * */
+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 () {
+    /* Je to velmi zjednodušeno, odešle se 32 bytový paket, přímo.
+     * Pro test to stačí (testováno pro 1 MBd, full duplex), ale jinak by
+     * zde musela být kontrola přetečení, odeslání, časování timeout atd.
+     * Nechci to zaplevelit nečitelnými hovadinami jako ten číňan.
+     * */
+    if (index >= 32) { // 32 je vhodný kompromis mezi 1 a 64
+      BaseLayer::Up (buffer, index);
+      index = 0;
+    }
+  }
+};
 static cdc_class cdc;
 static Usart     usart;
 static Mirror    top;
+static Middle    mid;
 int main () {
   cdc.init();
   top += cdc;
-  top -= usart;
+  top -= mid += usart;
   cdc.attach(usart);
   for (;;) {
-    /* Vše probíhá v přerušení */
+    mid.pass();
   }
   return 0;
 }
diff --git a/V203/usb/usart/test/main.cpp b/V203/usb/usart/test/main.cpp
index 91f80ca..3dd3644 100644
--- a/V203/usb/usart/test/main.cpp
+++ b/V203/usb/usart/test/main.cpp
@@ -35,7 +35,7 @@ static void Handler (int) {
 int main (void) {
   loop = true;
   signal (SIGINT, Handler);
-  UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._USB__=__USART_0002-if00", 9600);
+  UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._USB__=__USART_0002-if00", 1'000'000);
   Top top;
   top += usart;
   while (loop) {
diff --git a/V203/usb/usart/test/usart.cpp b/V203/usb/usart/test/usart.cpp
index 640ab80..8e095b9 100644
--- a/V203/usb/usart/test/usart.cpp
+++ b/V203/usb/usart/test/usart.cpp
@@ -14,7 +14,7 @@ UsartClass::UsartClass (const char * name, const int baudrate) : BaseLayer() {
   fd = ::open (id, O_RDWR);
   if (fd < 0) return;
   
-  timeout = 12'000'000 / baudrate; // cca pro 1 byte
+  timeout = 20'000'000 / baudrate; // cca 2 násobek pro 1 byte
   
   struct termios LineFlags;
   int attr = tcgetattr (fd, &LineFlags);
@@ -66,6 +66,7 @@ uint32_t UsartClass::Down (const char * data, uint32_t len) {
   while (remain) {
     const unsigned chunk = remain > maxchunk ? maxchunk : remain;
     const unsigned writn = ::write (fd, data + offset, chunk);
+    // Počkat je nejjednodušší prevence zahlcení USB (USART má omezenou rychlost)
     usleep (timeout * writn); // závisí na baud rate
     offset += writn;
     remain -= writn;