--- /dev/null
+#include "interface.h"
+#include "monitor.h"
+#include "motorola.h"
+#include "output.h"
+#include "serial.h"
+
+volatile uint8_t recv_buf[32];
+uint8_t recv_head = 0;
+uint8_t recv_tail = 0;
+volatile uint8_t recv_fill = 0;
+volatile uint8_t recv_overrun = 0;
+uint8_t cmd_buf[15];
+uint8_t cmd_length;
+
+void process_commands();
+uint8_t process_command();
+
+void interface_init()
+{
+ DDRD = (DDRD&0xFC)|0x02;
+
+ serial_init(9600);
+}
+
+void interface_check()
+{
+ if(recv_overrun)
+ {
+ serial_write(0xFE);
+ serial_write(RECEIVE_OVERRUN);
+ recv_overrun = 0;
+ }
+ if(recv_fill>0)
+ process_commands();
+}
+
+void process_commands()
+{
+ while(recv_fill>0)
+ {
+ uint8_t consumed;
+ uint8_t c = recv_buf[recv_tail];
+
+ cmd_length = 0;
+
+ if(c>=0xF0)
+ {
+ cmd_length = ~c;
+ if(recv_fill<=cmd_length)
+ break;
+
+ uint8_t i, j;
+ for(i=0, j=recv_tail+1; i<cmd_length; ++i, ++j)
+ {
+ if(j>=sizeof(recv_buf))
+ j = 0;
+ cmd_buf[i] = recv_buf[j];
+ }
+
+ consumed = 1+cmd_length;
+ }
+ else
+ {
+ serial_write(0xFE);
+ serial_write(FRAMING_ERROR);
+ consumed = 1;
+ }
+
+ recv_tail += consumed;
+ if(recv_tail>=sizeof(recv_buf))
+ recv_tail -= sizeof(recv_buf);
+ recv_fill -= consumed;
+
+ if(cmd_length>0)
+ {
+ uint8_t result = process_command();
+ serial_write(0xFE);
+ serial_write(result);
+ }
+ }
+}
+
+uint8_t process_command()
+{
+ uint8_t type = cmd_buf[0]>>4;
+ if(type==0)
+ {
+ uint8_t subtype = (cmd_buf[0]>>3)&1;
+ if(subtype==0)
+ return output_command();
+ else
+ return monitor_command();
+ }
+ else if(type==1)
+ return motorola_command();
+ else
+ return INVALID_COMMAND;
+}
+
+static inline void receive(uint8_t c)
+{
+ if(recv_fill>=sizeof(recv_buf))
+ {
+ recv_overrun = 1;
+ return;
+ }
+
+ recv_buf[recv_head++] = c;
+ if(recv_head>=sizeof(recv_buf))
+ recv_head = 0;
+ ++recv_fill;
+}
+
+SERIAL_SET_CALLBACK(receive)