X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=arducontrol%2Finterface.c;fp=arducontrol%2Finterface.c;h=9d21e9cbfe1ddf874d0e41b9807aa29a2164686e;hb=b47b38e9dd282c5f8fb1ded25ade805e64d0cf1a;hp=0000000000000000000000000000000000000000;hpb=817742862a867673e4cbdb85d274481f7482e1ae;p=model-railway-devices.git diff --git a/arducontrol/interface.c b/arducontrol/interface.c new file mode 100644 index 0000000..9d21e9c --- /dev/null +++ b/arducontrol/interface.c @@ -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=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)