X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=main.c;h=9c368d5aa27b08f19da25d12c75249adc95f99ba;hb=3be0a345c40d7ef9b20e7749a0c73db14f2927e0;hp=5d449de1b11efa5669f804e0c648bfff391b194c;hpb=7550fa78c8354d1551266bb15e280d4dd6cefb50;p=protos%2Frc_servos.git diff --git a/main.c b/main.c index 5d449de..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; @@ -141,17 +198,17 @@ static void do_one_servo(struct servo *s) //portval = PORTC | (1 << s->bit); portval = (1 << s->bit); t = TCNT1; - load_timer_at(t + 150); + load_timer_at(t + 20); while (done == 0) - poll_spi(); + poll(); /* reset bit */ done = 0; portval = 0; //portval = PORTC & (~(1 << s->bit)); - load_timer_at(t + 150 + 8000 + s->command * 8); + load_timer_at(t + 20 + 1000 + s->command); while (done == 0) - poll_spi(); + poll(); } int main(void) @@ -160,6 +217,9 @@ int main(void) uint8_t t, diff; uint8_t tmp; + /* use pull-up for inputs */ + PORTC |= 0x3f; + /* LED */ DDRB = 0x02; @@ -175,9 +235,10 @@ int main(void) /* servo outputs PD2-PD7 */ DDRD = 0xfc; - /* start timer1 at clk/1 (8Mhz) */ + /* start timer1 at clk/8 (1Mhz), enable noise canceler on + * input capture, capture rising edge */ TCNT1 = 0; - TCCR1B = _BV(CS10); + TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1); /* start timer0 at clk/1024 (~8Khz) */ TCNT0 = 0; @@ -199,7 +260,7 @@ int main(void) diff = TCNT0 - t; if (diff >= 160) break; - poll_spi(); + poll(); } /* bypass mode */ if (bypass == 1) { @@ -210,7 +271,7 @@ int main(void) tmp &= 0x3f; tmp <<= 2; PORTD = tmp; - poll_spi(); + poll(); } LED_OFF(); }