]> git.tdb.fi Git - model-railway-devices.git/blobdiff - arducontrol/output.c
Support chaining packets to create a larger packet
[model-railway-devices.git] / arducontrol / output.c
index 3c94f7091c39072939829e45adff5ff1cde6d5ad..e017560c5cf6e12930f3b65003b4eae1823868b0 100644 (file)
@@ -1,5 +1,5 @@
 #include <avr/io.h>
-#include "commands.h"
+#include "interface.h"
 #include "output.h"
 #include "timer.h"
 
@@ -7,7 +7,17 @@
 #define ENABLE PORTD3
 #define BIT(x) (1<<(x))
 
-OutputPacket packet;
+enum State
+{
+       IDLE,
+       READY,
+       SENDING
+};
+
+OutputPacket packets[4];
+uint8_t chain_length;
+uint8_t current_packet;
+volatile uint8_t packet_state = IDLE;
 static uint8_t out_bit;
 static uint8_t out_time;
 static uint8_t out_data;
@@ -21,11 +31,26 @@ void output_init(void)
        timer_start_hz(2, 80000, 1);
 }
 
-void clear_packet(void)
+OutputPacket *output_create_packet(void)
 {
-       packet.ready = 0;
-       packet.sending = 0;
-       packet.done = 0;
+       while(packet_state!=IDLE) ;
+       chain_length = 1;
+       return &packets[0];
+}
+
+OutputPacket *output_create_chained_packet(void)
+{
+       ++chain_length;
+       return &packets[chain_length-1];
+}
+
+void output_send_packet(void)
+{
+       if(packet_state!=IDLE)
+               return;
+
+       current_packet = 0;
+       packet_state = READY;
 }
 
 void output_set_power(uint8_t p)
@@ -36,6 +61,11 @@ void output_set_power(uint8_t p)
                PORTD &= ~BIT(ENABLE);
 }
 
+uint8_t output_is_power_on()
+{
+       return (PORTD&BIT(ENABLE))!=0;
+}
+
 uint8_t output_command(const uint8_t *cmd_buf, uint8_t cmd_length)
 {
        if(cmd_buf[0]==POWER_ON || cmd_buf[0]==POWER_OFF)
@@ -45,6 +75,16 @@ uint8_t output_command(const uint8_t *cmd_buf, uint8_t cmd_length)
 
                output_set_power(cmd_buf[0]==POWER_ON);
        }
+       else if(cmd_buf[0]==READ_POWER_STATE)
+       {
+               if(cmd_length!=1)
+                       return LENGTH_ERROR;
+
+               uint8_t reply[2];
+               reply[0] = POWER_STATE;
+               reply[1] = output_is_power_on();
+               interface_send(reply, 2);
+       }
        else
                return INVALID_COMMAND;
 
@@ -58,27 +98,29 @@ static inline void output_tick(void)
 
        if(out_time && !--out_time)
        {
+               OutputPacket *packet = &packets[current_packet];
                ++out_bit;
-               if(out_bit>=packet.length)
+               if(out_bit>=packet->length)
                {
                        PORTD &= ~BIT(POLARITY);
-                       if(packet.repeat_count>1)
+                       if(--packet->repeat_count)
                        {
-                               if(packet.repeat_count<0xFF)
-                                       --packet.repeat_count;
-                               delay_time = packet.repeat_delay;
-                               packet.sending = 0;
+                               delay_time = packet->repeat_delay;
+                               packet_state = READY;
                        }
                        else
                        {
-                               delay_time = packet.final_delay;
-                               packet.done = 1;
+                               delay_time = packet->final_delay;
+                               if(++current_packet<chain_length)
+                                       packet_state = READY;
+                               else
+                                       packet_state = IDLE;
                        }
                }
                else
                {
                        if((out_bit&7)==0)
-                               out_data = packet.data[out_bit>>3];
+                               out_data = packet->data[out_bit>>3];
                        else
                                out_data >>= 1;
 
@@ -87,18 +129,19 @@ static inline void output_tick(void)
                        else
                                PORTD &= ~BIT(POLARITY);
 
-                       out_time = packet.bit_duration;
+                       out_time = packet->bit_duration;
                }
 
                return;
        }
 
-       if(packet.ready && !packet.sending)
+       if(packet_state==READY)
        {
-               packet.sending = 1;
+               OutputPacket *packet = &packets[current_packet];
+               packet_state = SENDING;
                out_bit = 0;
-               out_time = packet.bit_duration;
-               out_data = packet.data[0];
+               out_time = packet->bit_duration;
+               out_data = packet->data[0];
                if(out_data&1)
                        PORTD |= BIT(POLARITY);
                else