X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=main.c;h=9c368d5aa27b08f19da25d12c75249adc95f99ba;hb=3be0a345c40d7ef9b20e7749a0c73db14f2927e0;hp=35098746f4563207d3510a44a96dd3d00b59e417;hpb=e8dc3448b547f715e33f62ae690a9408b4e90a70;p=protos%2Frc_servos.git diff --git a/main.c b/main.c index 3509874..9c368d5 100644 --- a/main.c +++ b/main.c @@ -39,6 +39,10 @@ static volatile uint8_t done; static uint8_t portval; static uint8_t rxidx; +static uint8_t icp_idx = NB_SERVO; +static uint16_t icp_servos[NB_SERVO]; +static uint16_t icp_prev; + #define BYPASS_ENABLE 14 #define BYPASS_DISABLE 15 @@ -48,11 +52,13 @@ static uint8_t rxidx; /* * SPI protocol: * - * A command is stored on 2 bytes. The first one has its msb to 0, and the - * second one to 1. The first received byte contains the command number, and the - * msb of the servo value. The second byte contains the lsb of the servo value. + * A command is stored on 2 bytes (except command 0). The first byte + * has its most significant bit to 0, and the second one to 1. The + * first received byte contains the command number, and the msb of the + * servo value. The second byte contains the lsb of the servo value. * - * Commands 0 to NB_SERVO are to set the value of servo. + * Command 0 is only one byte long, it means "I have nothing to say". + * Commands 1 to NB_SERVO+1 are to set the value of servo. * Command 14 is to enable bypass mode. * Command 15 is to disable bypass mode. */ @@ -102,6 +108,10 @@ static void poll_spi(void) if (rxidx == 0) { byte0.u8 = c; + + /* command num 0 is ignored */ + if (byte0.cmd_num == 0) + return; } else { uint16_t val; @@ -110,10 +120,10 @@ static void poll_spi(void) /* process command */ - if (byte0.cmd_num < NB_SERVO) { + if (byte0.cmd_num < NB_SERVO+1) { val = (uint16_t)byte0.val_msb << 7; val += byte1.val_lsb; - servo_table[byte0.cmd_num].command = val; + servo_table[byte0.cmd_num-1].command = val; } else if (byte0.cmd_num == BYPASS_ENABLE) { bypass = 1; @@ -126,6 +136,53 @@ static void poll_spi(void) rxidx ^= 1; } +static void poll_input_capture(void) +{ + uint16_t icp, diff; + uint8_t rising; + + /* no new sample, return */ + if ((TIFR1 & _BV(ICF1)) == 0) + return; + + sei(); + icp = ICR1; + cli(); + + rising = TCCR1B & _BV(ICES1); + + /* change the edge type */ + TCCR1B ^= _BV(ICES1); + + /* clear the flag */ + TIFR1 = TIFR1 | _BV(ICF1); + + diff = icp - icp_prev; + icp_prev = icp; + + /* a rising edge with at least 2ms of state 0 means that we + * get the first servo */ + if (rising == 1 && diff > 2000) { + icp_idx = 0; + return; + } + + /* get the value for the servo */ + if (rising == 0 && icp_idx < NB_SERVO) { + if (diff < 1000) + icp_servos[icp_idx] = 0; + else + icp_servos[icp_idx] = diff - 1000; + icp_idx++; + } +} + +static void poll(void) +{ + poll_spi(); + poll_input_capture(); +} + static void load_timer_at(uint16_t t) { OCR1A = t; @@ -143,7 +200,7 @@ static void do_one_servo(struct servo *s) t = TCNT1; load_timer_at(t + 20); while (done == 0) - poll_spi(); + poll(); /* reset bit */ done = 0; @@ -151,7 +208,7 @@ static void do_one_servo(struct servo *s) //portval = PORTC & (~(1 << s->bit)); load_timer_at(t + 20 + 1000 + s->command); while (done == 0) - poll_spi(); + poll(); } int main(void) @@ -178,9 +235,10 @@ int main(void) /* servo outputs PD2-PD7 */ DDRD = 0xfc; - /* start timer1 at clk/8 (1Mhz) */ + /* start timer1 at clk/8 (1Mhz), enable noise canceler on + * input capture, capture rising edge */ TCNT1 = 0; - TCCR1B = _BV(CS11); + TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1); /* start timer0 at clk/1024 (~8Khz) */ TCNT0 = 0; @@ -202,7 +260,7 @@ int main(void) diff = TCNT0 - t; if (diff >= 160) break; - poll_spi(); + poll(); } /* bypass mode */ if (bypass == 1) { @@ -213,7 +271,7 @@ int main(void) tmp &= 0x3f; tmp <<= 2; PORTD = tmp; - poll_spi(); + poll(); } LED_OFF(); }