]> git.tdb.fi Git - model-railway-devices.git/commitdiff
Organize arducontrol code by functionality
authorMikko Rasa <tdb@tdb.fi>
Mon, 21 Oct 2013 20:10:35 +0000 (23:10 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 21 Oct 2013 23:14:56 +0000 (02:14 +0300)
13 files changed:
arducontrol/Makefile
arducontrol/arducontrol.c
arducontrol/commands.h
arducontrol/interface.c [new file with mode: 0644]
arducontrol/interface.h [new file with mode: 0644]
arducontrol/monitor.c [new file with mode: 0644]
arducontrol/monitor.h [new file with mode: 0644]
arducontrol/motorola.c
arducontrol/motorola.h
arducontrol/output.c [new file with mode: 0644]
arducontrol/output.h [new file with mode: 0644]
arducontrol/packet.c [deleted file]
arducontrol/packet.h [deleted file]

index 22864ff148a78227b3e4b8671b2ea31be4466c54..b520eb767b1a05eabcd7d88d9442ae621321c73f 100644 (file)
@@ -1,3 +1,3 @@
 include ../common/build.mk
 
-arducontrol.elf: adc.o motorola.o packet.o serial.o timer.o
+arducontrol.elf: adc.o interface.o monitor.o motorola.o output.o serial.o timer.o
index d09fc09c3766e3dca9d41dbbd0125e250dae8c28..882f280b9e432b3dd3399f0230a011b4404d34d4 100644 (file)
@@ -34,361 +34,24 @@ blocks until the operation completes.  The command returns as soon as sending
 its data to the track can start.
 */
 #include <avr/io.h>
-#include "adc.h"
-#include "commands.h"
-#include "motorola.h"
-#include "packet.h"
-#include "serial.h"
-#include "timer.h"
-
-Packet packet;
-uint8_t out_bit;
-uint8_t out_time;
-uint8_t out_data;
-uint8_t delay_time;
-
-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;
-
-uint16_t track_current_samples[16] = { 0 };
-uint8_t track_current_head = 0;
-volatile uint16_t track_current_sum = 0;
-uint16_t overcurrent_limit = 1000<<4;
-uint8_t overcurrent_sent = 0;
-
-uint16_t input_voltage_samples[16] = { 0 };
-uint8_t input_voltage_head = 0;
-volatile uint16_t input_voltage_sum = 0;
-
-volatile uint8_t adc_state = 0;
-
-void process_commands();
-uint8_t process_command();
+#include <avr/interrupt.h>
+#include "interface.h"
+#include "monitor.h"
+#include "output.h"
 
 int main()
 {
-       DDRD = 0x0E;
-       PORTD = 0;
-
-       serial_init(9600);
-       timer_start_hz(0, 80000, 1);
-       adc_init();
+       output_init();
+       interface_init();
+       monitor_init();
 
        sei();
 
        while(1)
        {
-               if(recv_overrun)
-               {
-                       serial_write(0xFE);
-                       serial_write(RECEIVE_OVERRUN);
-                       recv_overrun = 0;
-               }
-               if(recv_fill>0)
-                       process_commands();
-               if(!(adc_state&1))
-               {
-                       ++adc_state;
-                       adc_read_async(adc_state>>1);
-               }
-               if(track_current_sum>overcurrent_limit)
-               {
-                       PORTD &= ~0x08;
-                       if(!overcurrent_sent)
-                       {
-                               overcurrent_sent = 1;
-                               serial_write(0xFE);
-                               serial_write(OVERCURRENT);
-                       }
-               }
-               else
-                       overcurrent_sent = 0;
+               interface_check();
+               monitor_check();
        }
 
        return 0;
 }
-
-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)
-
-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()
-{
-       if(cmd_buf[0]==POWER_ON || cmd_buf[0]==POWER_OFF)
-       {
-               if(cmd_length!=1)
-                       return LENGTH_ERROR;
-
-               if(cmd_buf[0]==POWER_ON)
-                       PORTD |= 0x08;
-               else
-                       PORTD &= ~0x08;
-       }
-       else if(cmd_buf[0]==READ_TRACK_CURRENT)
-       {
-               if(cmd_length!=1)
-                       return LENGTH_ERROR;
-
-               serial_write(0xFC);
-               serial_write(TRACK_CURRENT);
-               uint16_t value = track_current_sum>>4;
-               serial_write(value>>8);
-               serial_write(value);
-       }
-       else if(cmd_buf[0]==SET_OVERCURRENT_LIMIT)
-       {
-               if(cmd_length!=3)
-                       return LENGTH_ERROR;
-
-               if(cmd_buf[1]&0xF0)
-                       return INVALID_VALUE;
-
-               overcurrent_limit = (cmd_buf[1]<<12) | (cmd_buf[2]<<4);
-       }
-       else if(cmd_buf[0]==READ_INPUT_VOLTAGE)
-       {
-               if(cmd_length!=1)
-                       return LENGTH_ERROR;
-
-               serial_write(0xFC);
-               serial_write(INPUT_VOLTAGE);
-               uint16_t value = (input_voltage_sum>>3)*5;
-               serial_write(value>>8);
-               serial_write(value);
-       }
-       else if(cmd_buf[0]==MOTOROLA_SPEED || cmd_buf[0]==MOTOROLA_SPEED_DIRECTION || cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
-       {
-               if(cmd_length!=4)
-                       return LENGTH_ERROR;
-
-               uint8_t addr = cmd_buf[1];
-               if(addr>80)
-                       return INVALID_VALUE;
-
-               if(cmd_buf[2]&0x0E)
-                       return INVALID_VALUE;
-               uint8_t aux = cmd_buf[2]&0x01;
-
-               uint8_t func = (cmd_buf[2]&0xF0)>>4;
-               if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
-               {
-                       if(func<1 || func>4)
-                               return INVALID_VALUE;
-               }
-               else if(cmd_buf[2]&0xFE)
-                       return INVALID_VALUE;
-               uint8_t state = cmd_buf[2]&0x02;
-
-               uint8_t speed = cmd_buf[3]&0x7F;
-               if(speed>14)
-                       return INVALID_VALUE;
-
-               uint8_t dir = !(cmd_buf[3]&0x80);
-
-               while(packet.ready && !packet.done) ;
-
-               if(cmd_buf[0]==MOTOROLA_SPEED)
-                       motorola_locomotive_speed_packet(addr, aux, speed);
-               else if(cmd_buf[0]==MOTOROLA_SPEED_DIRECTION)
-                       motorola_locomotive_speed_direction_packet(addr, aux, speed, dir);
-               else if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
-                       motorola_locomotive_speed_function_packet(addr, aux, speed, func, state);
-       }
-       else if(cmd_buf[0]==MOTOROLA_REVERSE)
-       {
-               if(cmd_length!=3)
-                       return LENGTH_ERROR;
-
-               uint8_t addr = cmd_buf[1];
-               if(addr>80)
-                       return INVALID_VALUE;
-
-               if(cmd_buf[2]&0xFE)
-                       return INVALID_VALUE;
-               uint8_t aux = cmd_buf[2]&0x01;
-
-               while(packet.ready && !packet.done) ;
-
-               motorola_locomotive_reverse_packet(addr, aux);
-       }
-       else if(cmd_buf[0]==MOTOROLA_SOLENOID)
-       {
-               if(cmd_length!=3)
-                       return LENGTH_ERROR;
-
-               uint8_t addr = cmd_buf[1];
-               if(addr>80)
-                       return INVALID_VALUE;
-
-               if(cmd_buf[2]&0x8E)
-                       return INVALID_VALUE;
-               uint8_t output = (cmd_buf[2]&0x70)>>4;
-               uint8_t state = cmd_buf[2]&1;
-
-               while(packet.ready && !packet.done) ;
-
-               motorola_solenoid_packet(addr, output, state);
-       }
-       else
-               return INVALID_COMMAND;
-
-       return COMMAND_OK;
-}
-
-static inline void tick()
-{
-       if(delay_time && --delay_time)
-               return;
-
-       if(out_time && !--out_time)
-       {
-               ++out_bit;
-               if(out_bit>=packet.length)
-               {
-                       PORTD &= ~0x04;
-                       if(packet.repeat_count>1)
-                       {
-                               if(packet.repeat_count<0xFF)
-                                       --packet.repeat_count;
-                               delay_time = packet.repeat_delay;
-                               packet.sending = 0;
-                       }
-                       else
-                       {
-                               delay_time = packet.final_delay;
-                               packet.done = 1;
-                       }
-               }
-               else
-               {
-                       if((out_bit&7)==0)
-                               out_data = packet.data[out_bit>>3];
-                       else
-                               out_data >>= 1;
-
-                       if(out_data&1)
-                               PORTD |= 0x04;
-                       else
-                               PORTD &= ~0x04;
-
-                       out_time = packet.bit_duration;
-               }
-
-               return;
-       }
-
-       if(packet.ready && !packet.sending)
-       {
-               packet.sending = 1;
-               out_bit = 0;
-               out_time = packet.bit_duration;
-               out_data = packet.data[0];
-               if(out_data&1)
-                       PORTD |= 0x04;
-               else
-                       PORTD &= ~0x04;
-       }
-}
-
-TIMER_SET_CALLBACK(0, tick)
-
-static inline void adc_complete(uint16_t value)
-{
-       if(adc_state==1)
-       {
-               // Convert to milliamps: (v*5/1024-2.5)*1000/0.185
-               if(value<512)  // Ignore negative current readings
-                       value = 0;
-               else if(value>663)  // Limit range so averaging won't overflow
-                       value = 4000;
-               else
-                       value = (value-512)*132/5;
-
-               uint8_t i = track_current_head;
-               track_current_sum -= track_current_samples[i];
-               track_current_samples[i] = value;
-               track_current_sum += value;
-               track_current_head = (i+1)&15;
-       }
-       else if(adc_state==3)
-       {
-               // Convert to centivolts: (v*5/1024)*100*11
-               if(value>744) // Limit range so averaging won't overflow
-                       value = 4000;
-               else
-                       value = value*43/8;
-
-               uint8_t i = input_voltage_head;
-               input_voltage_sum -= input_voltage_samples[i];
-               input_voltage_samples[i] = value;
-               input_voltage_sum += value;
-               input_voltage_head = (i+1)&15;
-       }
-
-       ++adc_state;
-}
-
-ADC_SET_CALLBACK(adc_complete)
index 64cbe54a22190eb39a310d4fcc0d0241fd091a63..865405d6f9957a6173869d54702abf7617d4ba9b 100644 (file)
@@ -5,9 +5,9 @@ enum Command
 {
        POWER_ON = 0x01,
        POWER_OFF = 0x02,
-       READ_TRACK_CURRENT = 0x03,
-       SET_OVERCURRENT_LIMIT = 0x04,
-       READ_INPUT_VOLTAGE = 0x05,
+       READ_TRACK_CURRENT = 0x08,
+       SET_OVERCURRENT_LIMIT = 0x09,
+       READ_INPUT_VOLTAGE = 0x0A,
        MOTOROLA_SPEED = 0x11,
        MOTOROLA_REVERSE = 0x12,
        MOTOROLA_SPEED_DIRECTION = 0x13,
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)
diff --git a/arducontrol/interface.h b/arducontrol/interface.h
new file mode 100644 (file)
index 0000000..f95244f
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef COMMAND_H_
+#define COMMAND_H_
+
+#include <stdint.h>
+#include "commands.h"
+
+extern uint8_t cmd_buf[];
+extern uint8_t cmd_length;
+
+void interface_init();
+void interface_check();
+
+#endif
diff --git a/arducontrol/monitor.c b/arducontrol/monitor.c
new file mode 100644 (file)
index 0000000..c88a071
--- /dev/null
@@ -0,0 +1,122 @@
+#include "adc.h"
+#include "interface.h"
+#include "monitor.h"
+#include "output.h"
+#include "serial.h"
+
+uint16_t track_current_samples[16] = { 0 };
+uint8_t track_current_head = 0;
+volatile uint16_t track_current_sum = 0;
+uint16_t overcurrent_limit = 1000<<4;
+uint8_t overcurrent_sent = 0;
+
+uint16_t input_voltage_samples[16] = { 0 };
+uint8_t input_voltage_head = 0;
+volatile uint16_t input_voltage_sum = 0;
+
+volatile uint8_t adc_state = 0;
+
+void monitor_init()
+{
+       adc_init();
+}
+
+void monitor_check()
+{
+       if(!(adc_state&1))
+       {
+               ++adc_state;
+               adc_read_async(adc_state>>1);
+       }
+
+       if(track_current_sum>overcurrent_limit)
+       {
+               output_set_power(0);
+               if(!overcurrent_sent)
+               {
+                       overcurrent_sent = 1;
+                       serial_write(0xFE);
+                       serial_write(OVERCURRENT);
+               }
+       }
+       else
+               overcurrent_sent = 0;
+}
+
+uint8_t monitor_command()
+{
+       if(cmd_buf[0]==READ_TRACK_CURRENT)
+       {
+               if(cmd_length!=1)
+                       return LENGTH_ERROR;
+
+               serial_write(0xFC);
+               serial_write(TRACK_CURRENT);
+               uint16_t value = track_current_sum>>4;
+               serial_write(value>>8);
+               serial_write(value);
+       }
+       else if(cmd_buf[0]==SET_OVERCURRENT_LIMIT)
+       {
+               if(cmd_length!=3)
+                       return LENGTH_ERROR;
+
+               if(cmd_buf[1]&0xF0)
+                       return INVALID_VALUE;
+
+               overcurrent_limit = (cmd_buf[1]<<12) | (cmd_buf[2]<<4);
+       }
+       else if(cmd_buf[0]==READ_INPUT_VOLTAGE)
+       {
+               if(cmd_length!=1)
+                       return LENGTH_ERROR;
+
+               serial_write(0xFC);
+               serial_write(INPUT_VOLTAGE);
+               uint16_t value = (input_voltage_sum>>3)*5;
+               serial_write(value>>8);
+               serial_write(value);
+       }
+       else
+               return INVALID_COMMAND;
+
+       return COMMAND_OK;
+}
+
+static inline void adc_complete(uint16_t value)
+{
+       if(adc_state==1)
+       {
+               // Convert to milliamps: (v*5/1024-2.5)*1000/0.185
+               if(value<512)  // Ignore negative current readings
+                       value = 0;
+               else if(value>663)  // Limit range so averaging won't overflow
+                       value = 4000;
+               else
+                       value = (value-512)*132/5;
+
+               uint8_t i = track_current_head;
+               track_current_sum -= track_current_samples[i];
+               track_current_samples[i] = value;
+               track_current_sum += value;
+               track_current_head = (i+1)&15;
+       }
+       else if(adc_state==3)
+       {
+               // Convert to centivolts: (v*5/1024)*100*11
+               if(value>744) // Limit range so averaging won't overflow
+                       value = 4000;
+               else
+                       value = value*43/8;
+
+               uint8_t i = input_voltage_head;
+               input_voltage_sum -= input_voltage_samples[i];
+               input_voltage_samples[i] = value;
+               input_voltage_sum += value;
+               input_voltage_head = (i+1)&15;
+       }
+
+       ++adc_state;
+}
+
+ADC_SET_CALLBACK(adc_complete)
diff --git a/arducontrol/monitor.h b/arducontrol/monitor.h
new file mode 100644 (file)
index 0000000..d5761e3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef MONITOR_H_
+#define MONITOR_H_
+
+#include <stdint.h>
+
+void monitor_init();
+void monitor_check();
+uint8_t monitor_command();
+
+#endif
index e78ebfc34bbe6a0b1de6a939452aca3d96577f66..5bf15ad9e37ed8422cd93f063d128d34c0beada9 100644 (file)
@@ -1,4 +1,6 @@
-#include "packet.h"
+#include "interface.h"
+#include "motorola.h"
+#include "output.h"
 
 static uint8_t motorola_speed_to_value(uint8_t speed)
 {
@@ -122,3 +124,84 @@ void motorola_solenoid_packet(uint8_t addr, uint8_t output, uint8_t state)
 
        packet.ready = 1;
 }
+
+uint8_t motorola_command()
+{
+       if(cmd_buf[0]==MOTOROLA_SPEED || cmd_buf[0]==MOTOROLA_SPEED_DIRECTION || cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
+       {
+               if(cmd_length!=4)
+                       return LENGTH_ERROR;
+
+               uint8_t addr = cmd_buf[1];
+               if(addr>80)
+                       return INVALID_VALUE;
+
+               if(cmd_buf[2]&0x0E)
+                       return INVALID_VALUE;
+               uint8_t aux = cmd_buf[2]&0x01;
+
+               uint8_t func = (cmd_buf[2]&0xF0)>>4;
+               if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
+               {
+                       if(func<1 || func>4)
+                               return INVALID_VALUE;
+               }
+               else if(cmd_buf[2]&0xFE)
+                       return INVALID_VALUE;
+               uint8_t state = cmd_buf[2]&0x02;
+
+               uint8_t speed = cmd_buf[3]&0x7F;
+               if(speed>14)
+                       return INVALID_VALUE;
+
+               uint8_t dir = !(cmd_buf[3]&0x80);
+
+               while(packet.ready && !packet.done) ;
+
+               if(cmd_buf[0]==MOTOROLA_SPEED)
+                       motorola_locomotive_speed_packet(addr, aux, speed);
+               else if(cmd_buf[0]==MOTOROLA_SPEED_DIRECTION)
+                       motorola_locomotive_speed_direction_packet(addr, aux, speed, dir);
+               else if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION)
+                       motorola_locomotive_speed_function_packet(addr, aux, speed, func, state);
+       }
+       else if(cmd_buf[0]==MOTOROLA_REVERSE)
+       {
+               if(cmd_length!=3)
+                       return LENGTH_ERROR;
+
+               uint8_t addr = cmd_buf[1];
+               if(addr>80)
+                       return INVALID_VALUE;
+
+               if(cmd_buf[2]&0xFE)
+                       return INVALID_VALUE;
+               uint8_t aux = cmd_buf[2]&0x01;
+
+               while(packet.ready && !packet.done) ;
+
+               motorola_locomotive_reverse_packet(addr, aux);
+       }
+       else if(cmd_buf[0]==MOTOROLA_SOLENOID)
+       {
+               if(cmd_length!=3)
+                       return LENGTH_ERROR;
+
+               uint8_t addr = cmd_buf[1];
+               if(addr>80)
+                       return INVALID_VALUE;
+
+               if(cmd_buf[2]&0x8E)
+                       return INVALID_VALUE;
+               uint8_t output = (cmd_buf[2]&0x70)>>4;
+               uint8_t state = cmd_buf[2]&1;
+
+               while(packet.ready && !packet.done) ;
+
+               motorola_solenoid_packet(addr, output, state);
+       }
+       else
+               return INVALID_COMMAND;
+
+       return COMMAND_OK;
+}
index 8b0bccf48173135dfad2c545359ca556322d04ad..5a3057a9fb3432d39d0f74aadad83a9b36fc7be7 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef MOTOROLA_H_
 #define MOTOROLA_H_
 
+#include <stdint.h>
+
 void motorola_locomotive_speed_packet(uint8_t, uint8_t, uint8_t);
 void motorola_locomotive_reverse_packet(uint8_t, uint8_t);
 void motorola_locomotive_speed_direction_packet(uint8_t, uint8_t, uint8_t, uint8_t);
 void motorola_locomotive_speed_function_packet(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);
 void motorola_solenoid_packet(uint8_t, uint8_t, uint8_t);
 void motorola_set_repeat_count(uint8_t);
+uint8_t motorola_command();
 
 #endif
diff --git a/arducontrol/output.c b/arducontrol/output.c
new file mode 100644 (file)
index 0000000..c1d5148
--- /dev/null
@@ -0,0 +1,105 @@
+#include <avr/io.h>
+#include "interface.h"
+#include "output.h"
+#include "timer.h"
+
+OutputPacket packet;
+uint8_t out_bit;
+uint8_t out_time;
+uint8_t out_data;
+uint8_t delay_time;
+
+void output_init()
+{
+       DDRD = (DDRD&0xF3)|0x0C;
+       PORTD &= ~0x08;
+
+       timer_start_hz(0, 80000, 1);
+}
+
+void clear_packet()
+{
+       packet.ready = 0;
+       packet.sending = 0;
+       packet.done = 0;
+}
+
+void output_set_power(uint8_t p)
+{
+       if(p==POWER_ON)
+               PORTD |= 0x08;
+       else
+               PORTD &= ~0x08;
+}
+
+uint8_t output_command()
+{
+       if(cmd_buf[0]==POWER_ON || cmd_buf[0]==POWER_OFF)
+       {
+               if(cmd_length!=1)
+                       return LENGTH_ERROR;
+
+               output_set_power(cmd_buf[0]==POWER_ON);
+       }
+       else
+               return INVALID_COMMAND;
+
+       return COMMAND_OK;
+}
+
+static inline void output_tick()
+{
+       if(delay_time && --delay_time)
+               return;
+
+       if(out_time && !--out_time)
+       {
+               ++out_bit;
+               if(out_bit>=packet.length)
+               {
+                       PORTD &= ~0x04;
+                       if(packet.repeat_count>1)
+                       {
+                               if(packet.repeat_count<0xFF)
+                                       --packet.repeat_count;
+                               delay_time = packet.repeat_delay;
+                               packet.sending = 0;
+                       }
+                       else
+                       {
+                               delay_time = packet.final_delay;
+                               packet.done = 1;
+                       }
+               }
+               else
+               {
+                       if((out_bit&7)==0)
+                               out_data = packet.data[out_bit>>3];
+                       else
+                               out_data >>= 1;
+
+                       if(out_data&1)
+                               PORTD |= 0x04;
+                       else
+                               PORTD &= ~0x04;
+
+                       out_time = packet.bit_duration;
+               }
+
+               return;
+       }
+
+       if(packet.ready && !packet.sending)
+       {
+               packet.sending = 1;
+               out_bit = 0;
+               out_time = packet.bit_duration;
+               out_data = packet.data[0];
+               if(out_data&1)
+                       PORTD |= 0x04;
+               else
+                       PORTD &= ~0x04;
+       }
+}
+
+TIMER_SET_CALLBACK(0, output_tick)
diff --git a/arducontrol/output.h b/arducontrol/output.h
new file mode 100644 (file)
index 0000000..b4498ad
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef PACKET_H_
+#define PACKET_H_
+
+#include <stdint.h>
+
+typedef struct
+{
+       uint8_t bit_duration:5;
+       uint8_t ready:1;
+       uint8_t sending:1;
+       volatile uint8_t done:1;
+       uint8_t length;
+       uint8_t data[32];
+       uint8_t repeat_count;
+       uint8_t repeat_delay;
+       uint8_t final_delay;
+} OutputPacket;
+
+extern OutputPacket packet;
+
+void output_init();
+void clear_packet();
+void output_set_power(uint8_t);
+uint8_t output_command();
+
+#endif
diff --git a/arducontrol/packet.c b/arducontrol/packet.c
deleted file mode 100644 (file)
index 2b20fc2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "packet.h"
-
-void clear_packet()
-{
-       packet.ready = 0;
-       packet.sending = 0;
-       packet.done = 0;
-}
diff --git a/arducontrol/packet.h b/arducontrol/packet.h
deleted file mode 100644 (file)
index fdd10ce..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef PACKET_H_
-#define PACKET_H_
-
-#include <stdint.h>
-
-typedef struct
-{
-       uint8_t bit_duration:5;
-       uint8_t ready:1;
-       uint8_t sending:1;
-       volatile uint8_t done:1;
-       uint8_t length;
-       uint8_t data[32];
-       uint8_t repeat_count;
-       uint8_t repeat_delay;
-       uint8_t final_delay;
-} Packet;
-
-extern Packet packet;
-
-void clear_packet();
-
-#endif