--- /dev/null
+/* 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();
+}
+