rc_servos: implement bypass mode
[protos/rc_servos.git] / main.c
1 #include <aversive.h>
2
3 struct servo {
4         uint8_t bit;
5         uint16_t command;
6 };
7
8 static struct servo servo_table[] = {
9         {
10                 .bit = 0,
11                 .command = 0,
12         },
13         {
14                 .bit = 1,
15                 .command = 512,
16         },
17         {
18                 .bit = 2,
19                 .command = 1023,
20         },
21 };
22
23 static volatile uint8_t rxbuf[16];
24 register uint8_t rxlen asm("r2");
25 register uint8_t done asm("r3");
26 register uint8_t portval asm("r4");
27 register uint8_t bypass asm("r5");
28
29 SIGNAL(TIMER1_COMPA_vect)
30 {
31         PORTC = portval;
32         TIMSK1 &= ~_BV(OCIE1A);
33         done = 1;
34 }
35
36 static void poll_spi(void)
37 {
38 }
39
40 static void load_timer_at(uint16_t t)
41 {
42         OCR1A = t;
43         TIMSK1 |= _BV(OCIE1A);
44 }
45
46 static void do_one_servo(struct servo *s)
47 {
48         uint16_t t;
49
50         /* set bit */
51         done = 0;
52         //portval = PORTC | (1 << s->bit);
53         portval = (1 << s->bit);
54         t = TCNT1;
55         load_timer_at(t + 150);
56         while (done == 0)
57                 poll_spi();
58
59         /* reset bit */
60         done = 0;
61         portval = 0;
62         //portval = PORTC & (~(1 << s->bit));
63         load_timer_at(t + 150 + 8000 + s->command * 8);
64         while (done == 0)
65                 poll_spi();
66 }
67
68 int main(void)
69 {
70         uint8_t i;
71         uint8_t t, diff;
72
73         DDRB = 0x20;
74         DDRC = 0x7;
75
76         /* start timer1 at clk/1 (8Mhz) */
77         TCNT1 = 0;
78         TCCR1B = _BV(CS10);
79
80         /* start timer0 at clk/1024 (~8Khz) */
81         TCNT0 = 0;
82         TCCR0B = _BV(CS02) | _BV(CS00);
83
84         sei();
85
86         while (1) {
87                 t = TCNT0;
88                 for (i = 0; i < sizeof(servo_table)/sizeof(*servo_table); i++) {
89                         do_one_servo(&servo_table[i]);
90                 }
91                 /* wait 20 ms */
92                 while (1) {
93                         diff = TCNT0 - t;
94                         if (diff >= 160)
95                                 break;
96                         poll_spi();
97                 }
98                 /* bypass mode */
99                 while (bypass == 1) {
100                         PORTC = PORTB;
101                 }
102         }
103
104         return 0;
105 }