From 4b6e85ca26ac9cacf578862688f3c2a77a9090a1 Mon Sep 17 00:00:00 2001
From: Damien <damien.p.george@gmail.com>
Date: Mon, 21 Oct 2013 09:56:56 +0100
Subject: [PATCH] Try to get REPL working, but bug with CDC VCP...

---
 stm/lib/usb_dcd_int.c   | 10 ++++++
 stm/lib/usbd_cdc_vcp.c  |  3 +-
 stm/lib/usbd_pyb_core.c |  3 +-
 stm/main.c              | 79 ++++++++++++++++++++++++++++++++++++++++-
 stm/printf.c            |  2 +-
 stm/usb.c               | 51 ++++++++++++++++++++++++--
 stm/usb.h               |  5 ++-
 7 files changed, 146 insertions(+), 7 deletions(-)

diff --git a/stm/lib/usb_dcd_int.c b/stm/lib/usb_dcd_int.c
index 32984e610c..abdb686c6a 100644
--- a/stm/lib/usb_dcd_int.c
+++ b/stm/lib/usb_dcd_int.c
@@ -675,6 +675,16 @@ static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
     ep->xfer_buff  += len;
     ep->xfer_count += len;
     
+    // this code turns off the "empty interrupt"
+    // without it the USB is subject to perpetual interrupts
+    // see my.st.com, "Yet another STM32F105/7 USB OTG driver issue (VCP device)"
+    // this code might also work if put in DCD_HandleInEP_ISR
+    if (ep->xfer_count >= ep->xfer_len) {
+      uint32_t fifoemptymsk = 1 << ep->num;
+      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
+      break;
+    }
+
     txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
   }
   
diff --git a/stm/lib/usbd_cdc_vcp.c b/stm/lib/usbd_cdc_vcp.c
index b7330d9f6a..985b0b4fd9 100644
--- a/stm/lib/usbd_cdc_vcp.c
+++ b/stm/lib/usbd_cdc_vcp.c
@@ -212,7 +212,8 @@ static uint16_t VCP_DataTx (const uint8_t* Buf, uint32_t Len)
   * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
   */
 static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len) {
-    //printf("%.*s", (int)Len, Buf);
+    extern void usb_vcp_receive(uint8_t *buf, uint32_t len);
+    usb_vcp_receive(Buf, Len);
     return USBD_OK;
 }
 
diff --git a/stm/lib/usbd_pyb_core.c b/stm/lib/usbd_pyb_core.c
index 5d6e6d9b95..f388361aa0 100644
--- a/stm/lib/usbd_pyb_core.c
+++ b/stm/lib/usbd_pyb_core.c
@@ -73,7 +73,8 @@
 #include "usbd_msc_bot.h"
 #include "usbd_msc_mem.h"
 
-#define USB_PYB_CONFIG_DESC_SIZ (98)
+#define USB_PYB_CONFIG_DESC_SIZ (98) // for both CDC VCP and MSC interfaces
+//#define USB_PYB_CONFIG_DESC_SIZ (67) // for only CDC VCP interfaces
 
 #define MSC_EPIN_SIZE                MSC_MAX_PACKET
 #define MSC_EPOUT_SIZE               MSC_MAX_PACKET
diff --git a/stm/main.c b/stm/main.c
index 90421d5989..660f42cb31 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <stm32f4xx.h>
 #include <stm32f4xx_rcc.h>
 #include <stm32f4xx_gpio.h>
@@ -182,6 +183,80 @@ static void board_info() {
     }
 }
 
+char *readline(const char *prompt) {
+    printf("a\n");
+    led_state(PYB_LED_R1, 1);
+    printf("b\n");
+    usb_vcp_send_str(prompt);
+    for (;;) {
+        printf("c\n");
+        led_state(PYB_LED_R2, 1);
+        char c = usb_vcp_rx_get();
+        led_state(PYB_LED_R2, 0);
+        usb_vcp_send_strn(&c, 1);
+        led_state(PYB_LED_G1, 1);
+        sys_tick_delay_ms(100);
+        led_state(PYB_LED_G1, 0);
+    }
+    return NULL;
+}
+
+extern char rx_buf[];
+extern int rx_buf_out;
+void do_repl() {
+    int i = 0;
+    for (;;) {
+    usb_vcp_send_str("Micro Python\r\n");
+    printf("%d %d %c\n", i++, usb_vcp_rx_any(), rx_buf[rx_buf_out]);
+    sys_tick_delay_ms(1000);
+    }
+
+    for (;;) {
+        char *line = readline(">>> ");
+        if (line == NULL) {
+            // EOF
+            return;
+        }
+        /*
+        if (is_compound_stmt(line)) {
+            for (;;) {
+                char *line2 = readline("... ");
+                if (line2 == NULL || strlen(line2) == 0) {
+                    break;
+                }
+                char *line3 = str_join(line, '\n', line2);
+                m_free(line);
+                m_free(line2);
+                line = line3;
+            }
+        }
+        */
+
+        py_lexer_str_buf_t sb;
+        py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", line, strlen(line), false, &sb);
+        py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
+        py_lexer_free(lex);
+
+        if (pn != PY_PARSE_NODE_NULL) {
+            bool comp_ok = py_compile(pn, true);
+            if (comp_ok) {
+                py_obj_t module_fun = rt_make_function_from_id(1);
+                if (module_fun != py_const_none) {
+                    nlr_buf_t nlr;
+                    if (nlr_push(&nlr) == 0) {
+                        rt_call_function_0(module_fun);
+                        nlr_pop();
+                    } else {
+                        // uncaught exception
+                        py_obj_print((py_obj_t)nlr.ret_val);
+                        printf("\n");
+                    }
+                }
+            }
+        }
+    }
+}
+
 int main() {
     // TODO disable JTAG
 
@@ -294,7 +369,7 @@ int main() {
     //sys_tick_delay_ms(1000);
 
     // Python!
-    if (1) {
+    if (0) {
         //const char *pysrc = "def f():\n  x=x+1\nprint(42)\n";
         const char *pysrc =
             // impl01.py
@@ -441,6 +516,8 @@ int main() {
         }
     }
 
+    do_repl();
+
     // benchmark C version of impl02.py
     if (0) {
         led_state(PYB_LED_G1, 1);
diff --git a/stm/printf.c b/stm/printf.c
index cec7c3e5c3..39d902d21b 100644
--- a/stm/printf.c
+++ b/stm/printf.c
@@ -214,7 +214,7 @@ void usb_vcp_send(const char* str, int len);
 void stdout_print_strn(void *data, const char *str, unsigned int len) {
     // send stdout to LCD and USB CDC VCP
     lcd_print_strn(str, len);
-    usb_vcp_send(str, len);
+    //usb_vcp_send(str, len);
 }
 
 static const pfenv_t pfenv_stdout = {0, stdout_print_strn};
diff --git a/stm/usb.c b/stm/usb.c
index fd32c8425f..6ac2392a1f 100644
--- a/stm/usb.c
+++ b/stm/usb.c
@@ -1,23 +1,70 @@
+#include <string.h>
+
 #include "usb_core.h"
 #include "usbd_core.h"
 #include "usbd_cdc_core.h"
 #include "usbd_pyb_core.h"
 #include "usbd_usr.h"
 #include "usbd_desc.h"
+
+#include "misc.h"
 #include "usb.h"
 
 extern CDC_IF_Prop_TypeDef VCP_fops;
 
 int is_enabled = 0;
 USB_OTG_CORE_HANDLE USB_OTG_dev;
+char rx_buf[64];
+int rx_buf_in;
+int rx_buf_out;
 
 void usb_init() {
     USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
+    rx_buf_in = 0;
+    rx_buf_out = 0;
     is_enabled = 1;
 }
 
-void usb_vcp_send(const char* str, int len) {
+void usb_vcp_receive(const char *buf, uint32_t len) {
+    for (int i = 0; i < len; i++) {
+        rx_buf[rx_buf_in++] = buf[i];
+        if (rx_buf_in >= sizeof(rx_buf)) {
+            rx_buf_in = 0;
+        }
+        if (rx_buf_in == rx_buf_out) {
+            rx_buf_out = rx_buf_in + 1;
+            if (rx_buf_out >= sizeof(rx_buf)) {
+                rx_buf_out = 0;
+            }
+        }
+    }
+}
+
+int usb_vcp_rx_any() {
+    if (rx_buf_in >= rx_buf_out) {
+        return rx_buf_in - rx_buf_out;
+    } else {
+        return rx_buf_in + sizeof(rx_buf) - rx_buf_out;
+    }
+}
+
+char usb_vcp_rx_get() {
+    while (rx_buf_out == rx_buf_in) {
+    }
+    char c = rx_buf[rx_buf_out];
+    rx_buf_out += 1;
+    if (rx_buf_out >= sizeof(rx_buf)) {
+        rx_buf_out = 0;
+    }
+    return c;
+}
+
+void usb_vcp_send_str(const char *str) {
+    usb_vcp_send_strn(str, strlen(str));
+}
+
+void usb_vcp_send_strn(const char *str, int len) {
     if (is_enabled) {
-        //VCP_fops.pIf_DataTx((const uint8_t*)str, len);
+        VCP_fops.pIf_DataTx((const uint8_t*)str, len);
     }
 }
diff --git a/stm/usb.h b/stm/usb.h
index c5060a0107..14a0345c17 100644
--- a/stm/usb.h
+++ b/stm/usb.h
@@ -1,2 +1,5 @@
 void usb_init();
-void usb_vcp_send(const char* str, int len);
+int usb_vcp_rx_any();
+char usb_vcp_rx_get();
+void usb_vcp_send_str(const char* str);
+void usb_vcp_send_strn(const char* str, int len);
-- 
GitLab