avr: initial commit
[z80.git] / avr / monitor / ihex.c
diff --git a/avr/monitor/ihex.c b/avr/monitor/ihex.c
new file mode 100644 (file)
index 0000000..675804f
--- /dev/null
@@ -0,0 +1,95 @@
+/* IHEX loader */
+
+#include <avr/pgmspace.h>
+
+#include <stdio.h>
+
+#include "../mem.h"
+#include "../uart.h"
+#include "../monitor.h"
+
+static uint8_t get_hex(char c)
+{
+       switch(c) {
+       case '0': return 0;
+       case '1': return 1;
+       case '2': return 2;
+       case '3': return 3;
+       case '4': return 4;
+       case '5': return 5;
+       case '6': return 6;
+       case '7': return 7;
+       case '8': return 8;
+       case '9': return 9;
+       case 'A': case 'a': return 10;
+       case 'B': case 'b': return 11;
+       case 'C': case 'c': return 12;
+       case 'D': case 'd': return 13;
+       case 'E': case 'e': return 14;
+       case 'F': case 'f': return 15;
+       }
+}
+
+void menu_ihex(void)
+{
+       char c;
+
+       uint8_t  state = 0;
+       uint8_t  len, count, sum, type = 0;
+       uint16_t addr;
+       uint8_t  byte;
+       uint8_t  echo = uart_echo;
+
+       mem_start();
+       uart_echo = 0;
+       printf_P(PSTR("Please send IHEX file now.\n"));
+
+       while(type != 0x01) {
+               /* wait for RECORD START */
+               sum = 0;
+               while(c != ':') c = uart_getc(NULL);
+
+               /* read RECORD LENGTH */
+               c=uart_getc(NULL); len  = get_hex(c) << 4;
+               c=uart_getc(NULL); len |= get_hex(c);
+               sum += len;
+
+               /* read LOAD OFFSET */
+               c=uart_getc(NULL); addr  = get_hex(c) << 12;
+               c=uart_getc(NULL); addr |= get_hex(c) <<  8;
+               c=uart_getc(NULL); addr |= get_hex(c) <<  4;
+               c=uart_getc(NULL); addr |= get_hex(c);
+               sum += (addr >> 8);
+               sum += (addr & 0xFF);
+
+               /* read RECORD TYPE */
+               c=uart_getc(NULL); type  = get_hex(c) << 4;
+               c=uart_getc(NULL); type |= get_hex(c);
+               sum += type;
+
+               /* read DATA */
+               for(uint8_t i = 0; i < len; i++) {
+                       c = uart_getc(NULL); byte  = get_hex(c) << 4;
+                       c = uart_getc(NULL); byte |= get_hex(c);
+                       sum += byte;
+
+                       mem_write(addr + i, byte);
+               }
+
+               /* read CHKSUM */
+               c = uart_getc(NULL); byte  = get_hex(c) << 4;
+               c = uart_getc(NULL); byte |= get_hex(c);
+               sum += byte;
+
+               if(sum) printf_P(PSTR("\nFAIL:0x%02x"), sum);
+               else    printf_P(PSTR("\r0x%04x"), addr);
+       }
+
+       /* read last CRLF */
+       if((char)(uart_getc(NULL)) == '\r') uart_getc(NULL);
+
+       printf_P(PSTR("\nReading IHEX file finished.\n"));
+       uart_echo = echo;
+       mem_stop();
+}
+