Norimasa Okamoto / Mbed 2 deprecated emuISP

Dependencies:   mbed

Revision:
3:ccc673a10485
Parent:
2:e3c085ac77f1
Child:
4:05f33cc747fd
--- a/BaseEmuISP.cpp	Sat Mar 12 09:34:38 2016 +0900
+++ b/BaseEmuISP.cpp	Tue Mar 22 16:25:41 2016 +0900
@@ -1,4 +1,4 @@
-// BaseEmuISP.cpp 2016/3/10
+// BaseEmuISP.cpp 2016/3/22
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -12,12 +12,13 @@
 void BaseEmuISP::Poll() {
     Mode_t prev_mode = mode;
     int result;
-    int c;
     char buf[32];
     switch(mode) {
         case M_RESET:
             echoFlag = true;
             lockFlag = true;
+            version.major = BootCodeVersion() >>8;
+            version.minor = BootCodeVersion() & 0xff;
             mode = M_SYNC;
             break;
         case M_SYNC:
@@ -34,25 +35,12 @@
             }
             break;
         case M_CMD_W_DATA:
-            if (count > 0) {
-                c = Getch();
-                if (c != (-1)) {
-                    if (echoFlag) {
-                        Putch(c);
-                    }
-                    WriteData(addr++, c);
-                    count--;
-                }
-            } else {
+            if (cmd_w_data()) {
                 mode = M_CMD;
             }
             break;
         case M_CMD_R_DATA:
-            if (count > 0) {
-                c = ReadData(addr++);
-                Putch(c);
-                count--;
-            } else {
+            if (cmd_r_data()) {
                 mode = M_CMD;
             }
             break;
@@ -62,8 +50,10 @@
             mode = M_CMD;
             break;
         case M_CMD_K:
-            putln("0");
-            putln("0");
+            snprintf(buf, sizeof(buf), "%d", version.major);
+            putln(buf);
+            snprintf(buf, sizeof(buf), "%d", version.minor);
+            putln(buf);
             mode = M_CMD;
             break;
         case M_CMD_N:
@@ -179,7 +169,7 @@
             return COUNT_ERROR;
         }
         addr = param[1];
-        count = param[2];
+        dataCount = param[2];
         mode = M_CMD_W_DATA;
         return CMD_SUCCESS;
     }
@@ -195,7 +185,7 @@
             return COUNT_ERROR;
         }
         addr = param[1];
-        count = param[2];
+        dataCount = param[2];
         mode = M_CMD_R_DATA;
         return CMD_SUCCESS;
     }
@@ -298,6 +288,126 @@
     return CMD_SUCCESS;
 }
 
+void uudecode(std::vector<uint8_t> &dst, const char* src) {
+    dst.clear();
+    int len = strlen(src);
+    if (len > 0) {
+        size_t size = (src[0]^0x20)&0x3f;
+        uint8_t b[4];
+        int k = 0;
+        for(int i = 1; i < len && dst.size() < size; i++) {
+            b[k] = (src[i]^0x20)&0x3f;
+            if (k == 0) {
+                k++;
+            } else if (k == 1) {
+                dst.push_back(b[0]<<2|b[1]>>4);
+                k++;
+            } else if (k == 2) {
+                dst.push_back(b[1]<<4|b[2]>>2);
+                k++;
+            } else {
+                dst.push_back(b[2]<<6|b[3]);
+                k = 0;
+            }
+        }
+    }
+}
+
+bool BaseEmuISP::cmd_w_data() {
+    int c;
+    switch(seq) {
+        case 0:
+            dataCurrent = 0;
+            if (UuencodeMode()) {
+                seq = 2;
+            } else {
+                seq = 1;
+            }
+            break;
+        case 1: // binary mode
+            if (dataCurrent >= dataCount) {
+                return true;
+            }
+            c = Getch();
+            if (c != (-1)) {
+                if (echoFlag) {
+                    Putch(c);
+                }
+                WriteData(addr++, c);
+                dataCurrent++;
+            }
+            break;
+        case 2: // uuencode mode
+            dataLine = 0;
+            dataCksum = 0;
+            line.clear();
+            seq++;
+            break;
+        case 3: // uu data start
+            if (line_proc()) {
+                vbyte_t data;
+                uudecode(data, line.c_str());
+                for(size_t i = 0; i < data.size(); i++) {
+                    int c = data[i];
+                    WriteData(addr++, c);
+                    dataCksum += c;
+                    dataCurrent++;
+                }
+                dataLine++;
+                if (dataLine >= 20 || dataCurrent>= dataCount) {
+                    seq++;
+                }
+                line.clear();
+            }
+            break;
+        case 4: // check sum
+            if (line_proc()) {
+                if (atoi(line.c_str()) == dataCksum) {
+                    putln("OK");
+                    if (dataCurrent >= dataCount) {
+                        mode = M_CMD;
+                    } else {
+                        seq = 2;
+                    }
+                } else {
+                    putln("RESEND");
+                    seq = 2;
+                }
+            }
+            break;
+    }
+    return false;
+}
+
+bool BaseEmuISP::cmd_r_data() {
+    int c;
+    switch(seq) {
+        case 0:
+            dataCurrent = 0;
+            if (UuencodeMode()) {
+                dataLine = 0;
+                dataCksum = 0;
+                line.clear();
+                seq = 2;
+            } else {
+                seq = 1;
+            }
+            break;
+        case 1: // binary mode
+            if (dataCurrent >= dataCount) {
+                return true;
+            }
+            c = ReadData(addr++);
+            Putch(c);
+            dataCurrent++;
+            break;
+        case 2:
+            break;
+    }
+    return false;
+}
+
+
 void BaseEmuISP::putln(const char *s) {
     debugPrintf("send: %s<CR><LF>\n", s);
     while(*s) {
@@ -311,7 +421,9 @@
     int c = Getch();
     if (c != (-1)) {
         if (echoFlag) {
-            Putch(c);
+            if (version.major >= 4 || c != '\n') {
+                Putch(c);
+            }
         }
         if (c == '\n') {
             debugPrintf("<LF>\n");