]> git.tdb.fi Git - model-railway-devices.git/blobdiff - arducontrol/interface.c
Organize arducontrol code by functionality
[model-railway-devices.git] / arducontrol / interface.c
diff --git a/arducontrol/interface.c b/arducontrol/interface.c
new file mode 100644 (file)
index 0000000..9d21e9c
--- /dev/null
@@ -0,0 +1,114 @@
+#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)