]> git.tdb.fi Git - model-railway-devices.git/blob - arducontrol/output.c
Add a function and command to find out if power is applied to the output
[model-railway-devices.git] / arducontrol / output.c
1 #include <avr/io.h>
2 #include "interface.h"
3 #include "output.h"
4 #include "timer.h"
5
6 #define POLARITY PORTD2
7 #define ENABLE PORTD3
8 #define BIT(x) (1<<(x))
9
10 OutputPacket packet;
11 static uint8_t out_bit;
12 static uint8_t out_time;
13 static uint8_t out_data;
14 static uint8_t delay_time;
15
16 void output_init(void)
17 {
18         DDRD = (DDRD&0xF3)|0x0C;
19         PORTD &= ~BIT(ENABLE);
20
21         timer_start_hz(2, 80000, 1);
22 }
23
24 void clear_packet(void)
25 {
26         packet.ready = 0;
27         packet.sending = 0;
28         packet.done = 0;
29 }
30
31 void output_set_power(uint8_t p)
32 {
33         if(p==POWER_ON)
34                 PORTD |= BIT(ENABLE);
35         else
36                 PORTD &= ~BIT(ENABLE);
37 }
38
39 uint8_t output_is_power_on()
40 {
41         return (PORTD&BIT(ENABLE))!=0;
42 }
43
44 uint8_t output_command(const uint8_t *cmd_buf, uint8_t cmd_length)
45 {
46         if(cmd_buf[0]==POWER_ON || cmd_buf[0]==POWER_OFF)
47         {
48                 if(cmd_length!=1)
49                         return LENGTH_ERROR;
50
51                 output_set_power(cmd_buf[0]==POWER_ON);
52         }
53         else if(cmd_buf[0]==READ_POWER_STATE)
54         {
55                 if(cmd_length!=1)
56                         return LENGTH_ERROR;
57
58                 uint8_t reply[2];
59                 reply[0] = POWER_STATE;
60                 reply[1] = output_is_power_on();
61                 interface_send(reply, 2);
62         }
63         else
64                 return INVALID_COMMAND;
65
66         return COMMAND_OK;
67 }
68
69 static inline void output_tick(void)
70 {
71         if(delay_time && --delay_time)
72                 return;
73
74         if(out_time && !--out_time)
75         {
76                 ++out_bit;
77                 if(out_bit>=packet.length)
78                 {
79                         PORTD &= ~BIT(POLARITY);
80                         if(packet.repeat_count>1)
81                         {
82                                 if(packet.repeat_count<0xFF)
83                                         --packet.repeat_count;
84                                 delay_time = packet.repeat_delay;
85                                 packet.sending = 0;
86                         }
87                         else
88                         {
89                                 delay_time = packet.final_delay;
90                                 packet.done = 1;
91                         }
92                 }
93                 else
94                 {
95                         if((out_bit&7)==0)
96                                 out_data = packet.data[out_bit>>3];
97                         else
98                                 out_data >>= 1;
99
100                         if(out_data&1)
101                                 PORTD |= BIT(POLARITY);
102                         else
103                                 PORTD &= ~BIT(POLARITY);
104
105                         out_time = packet.bit_duration;
106                 }
107
108                 return;
109         }
110
111         if(packet.ready && !packet.sending)
112         {
113                 packet.sending = 1;
114                 out_bit = 0;
115                 out_time = packet.bit_duration;
116                 out_data = packet.data[0];
117                 if(out_data&1)
118                         PORTD |= BIT(POLARITY);
119                 else
120                         PORTD &= ~BIT(POLARITY);
121         }
122 }
123
124 TIMER_SET_CALLBACK(2, output_tick)