2 #include <aversive/wait.h>
9 static struct servo servo_table[] = {
35 #define NB_SERVO (sizeof(servo_table)/sizeof(*servo_table))
37 static uint8_t bypass;
38 static volatile uint8_t done;
39 static uint8_t portval;
42 static uint8_t icp_idx = NB_SERVO;
43 static uint16_t icp_servos[NB_SERVO];
44 static uint16_t icp_prev;
46 static uint8_t spi_out_idx; /* current byte beeing sent */
48 #define BYPASS_ENABLE 14
49 #define BYPASS_DISABLE 15
51 #define LED_ON() do { PORTB |= 0x02; } while(0)
52 #define LED_OFF() do { PORTB &= ~0x02; } while(0)
57 * A command is stored on 2 bytes (except command 0). The first byte
58 * has its most significant bit to 0, and the second one to 1. The
59 * first received byte contains the command number, and the msb of the
60 * servo value. The second byte contains the lsb of the servo value.
62 * Command 0 is only one byte long, it means "I have nothing to say".
63 * Commands 1 to NB_SERVO+1 are to set the value of servo.
64 * Command 14 is to enable bypass mode.
65 * Command 15 is to disable bypass mode.
70 /* inverted: little endian */
80 /* inverted: little endian */
86 SIGNAL(TIMER1_COMPA_vect)
89 TIMSK1 &= ~_BV(OCIE1A);
93 static void poll_spi(void)
97 static union byte0 byte0_rx;
100 static union byte1 byte1_tx;
102 /* reception complete ? */
103 if (!(SPSR & (1<<SPIF)))
108 /* prepare next TX */
110 if ((spi_out_idx & 1) == 0) {
111 servo = icp_servos[spi_out_idx >> 1];
112 byte0_tx.val_msb = servo >> 7;
113 byte0_tx.cmd_num = (spi_out_idx >> 1) + 1;
115 byte1_tx.val_lsb = servo & 0x7f;
123 if (spi_out_idx >= NB_SERVO)
128 if ((rxidx == 0) && (c & 0x80)) {
132 if ((rxidx == 1) && ((c & 0x80) == 0)) {
140 /* command num 0 is ignored */
141 if (byte0_rx.cmd_num == 0)
149 /* process command */
151 if (byte0_rx.cmd_num < NB_SERVO+1) {
152 val = (uint16_t)byte0_rx.val_msb << 7;
153 val += byte1_rx.val_lsb;
154 servo_table[byte0_rx.cmd_num-1].command = val;
156 else if (byte0_rx.cmd_num == BYPASS_ENABLE) {
159 else if (byte0_rx.cmd_num == BYPASS_DISABLE) {
167 static void poll_input_capture(void)
172 /* no new sample, return */
173 if ((TIFR1 & _BV(ICF1)) == 0)
180 rising = TCCR1B & _BV(ICES1);
182 /* change the edge type */
183 TCCR1B ^= _BV(ICES1);
186 TIFR1 = TIFR1 | _BV(ICF1);
188 diff = icp - icp_prev;
191 /* a rising edge with at least 2ms of state 0 means that we
192 * get the first servo */
193 if (rising == 1 && diff > 2000) {
198 /* get the value for the servo */
199 if (rising == 0 && icp_idx < NB_SERVO) {
201 icp_servos[icp_idx] = 0;
203 icp_servos[icp_idx] = diff - 1000;
208 static void poll(void)
211 poll_input_capture();
214 static void load_timer_at(uint16_t t)
217 TIMSK1 |= _BV(OCIE1A);
220 static void do_one_servo(struct servo *s)
226 //portval = PORTC | (1 << s->bit);
227 portval = (1 << s->bit);
229 load_timer_at(t + 20);
236 //portval = PORTC & (~(1 << s->bit));
237 load_timer_at(t + 20 + 1000 + s->command);
248 /* use pull-up for inputs */
254 #if 0 /* LED debug */
263 /* servo outputs PD2-PD7 */
266 /* start timer1 at clk/8 (1Mhz), enable noise canceler on
267 * input capture, capture rising edge */
269 TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1);
271 /* start timer0 at clk/1024 (~8Khz) */
273 TCCR0B = _BV(CS02) | _BV(CS00);
275 /* enable spi (set MISO as output) */
285 for (i = 0; i < NB_SERVO; i++) {
286 do_one_servo(&servo_table[i]);
299 while (bypass == 1) {