From e7fb4f1b6b94fbcbaf56bbd350e4d45c1d7eef39 Mon Sep 17 00:00:00 2001 From: dufourj Date: Mon, 8 May 2006 13:36:09 +0000 Subject: ES : - début d'intégration avec la futur PWM de marcel ; - meilleur gestion des interruptions qui pourraient se "chevaucher". TODO : - améliorer un if pour le décallage de bits ; - calculer le nombre d'overflow de manière dynamique. --- n/es-2006/src/Makefile | 2 +- n/es-2006/src/es_config.c | 50 ++++++++++++++++++++++++++ n/es-2006/src/es_config.h | 41 +++++++++++++++++++++ n/es-2006/src/main.c | 61 ++++++++++++++++++++++--------- n/es-2006/src/sensor_rvb.c | 90 ++++++++++++++++++++++++++++------------------ n/es-2006/src/sensor_rvb.h | 42 ++++++++++++---------- n/es-2006/src/timer.h | 51 -------------------------- n/es-2006/src/timer_main.h | 51 ++++++++++++++++++++++++++ 8 files changed, 267 insertions(+), 121 deletions(-) create mode 100644 n/es-2006/src/es_config.c create mode 100644 n/es-2006/src/es_config.h delete mode 100644 n/es-2006/src/timer.h create mode 100644 n/es-2006/src/timer_main.h diff --git a/n/es-2006/src/Makefile b/n/es-2006/src/Makefile index 0d16f6a..444347b 100644 --- a/n/es-2006/src/Makefile +++ b/n/es-2006/src/Makefile @@ -1,6 +1,6 @@ BASE = ../../avr PROGS = es -es_SOURCES = main.c sensor_rvb.c +es_SOURCES = main.c sensor_rvb.c es_config.c MODULES = proto uart utils CONFIGFILE = avrconfig.h # atmega8, atmega8535, atmega128... diff --git a/n/es-2006/src/es_config.c b/n/es-2006/src/es_config.c new file mode 100644 index 0000000..1342bea --- /dev/null +++ b/n/es-2006/src/es_config.c @@ -0,0 +1,50 @@ +/* es_config.c */ +/* es - Input/Output general purpose board. {{{ + * + * Copyright (C) 2006 Dufour Jérémy + * + * Robot APB Team/Efrei 2004. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "es_config.h" + +/** Initialisation of the shared register for the timer/counter 1. */ +inline void +timer1_init (void) +{ + /* Initialisation of timer/counter 1 control register A : + * - pwm : TODO Fast PWM 10 bits. + */ + TCCR1A = + regv (COM1A1, COM1A0, COM1B1, COM1B0, COM1C1, COM1C0, WGM11, WGM10, + 0, 0, 0, 0, 0, 0, 1, 1 ); + /* Initialisation of timer/counter 1 control register B : + * - shared : 1 for prescaling ; + * - rvb : noise canceler, IC on falling edge ; + * - pwm : TODO Fast PWM 10 bits. + */ + TCCR1B = regv (ICNC1, ICES1, 5, WGM13, WGM12, CS12, CS11, CS10, + 1, 0, 0, 0, 1, 0, 0, 1 ); + /* Initialisation of timer/counter 1 control register C : + * - pwm : TODO. + */ +// TCCR1C = regv (F0C1A, FOC1B, FOC1C, 4, 3, 2, 1, 0, +// 0, 0, 0, 0, 0, 0, 0, 0); +} + diff --git a/n/es-2006/src/es_config.h b/n/es-2006/src/es_config.h new file mode 100644 index 0000000..5a94c84 --- /dev/null +++ b/n/es-2006/src/es_config.h @@ -0,0 +1,41 @@ +#ifndef es_config_h +#define es_config_h +// es_config.h +// es - Input/Output general purpose board. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "modules/utils/utils.h" /* regv */ +#include "common.h" /* TCCR1*... */ + +/** Common defines shared between differents modules inside the ES program. */ + +/** The TOP of the timer/counter 1. + * This define has to be update by hand every time you change the + * configuration of the timer/counter 1. */ +#define TC1_TOP 0x03FF + +/** Initialisation of the shared register for the timer/counter 1. */ +extern void timer1_init (void); + +#endif // es_config_h diff --git a/n/es-2006/src/main.c b/n/es-2006/src/main.c index a269dfe..f5e15a8 100644 --- a/n/es-2006/src/main.c +++ b/n/es-2006/src/main.c @@ -29,18 +29,20 @@ #include "modules/proto/proto.h" #include "modules/utils/utils.h" -#include "timer.h" /* main timer */ +#include "timer_main.h" /* main timer */ #include "sensor_rvb.h" /* RVB sensors management */ +#include "es_config.h" /* timer/counter 1 */ -/* Statistics for sensors */ -uint8_t sensor_rvb_stat_enable = 0; -uint8_t sensor_rvb_stats = 0; +/* Statistics for RVB sensors */ +uint8_t sensor_rvb_stat_enable[RVB_MAX_SENSOR] = { 0 }; +uint8_t sensor_rvb_stats[RVB_MAX_SENSOR] = { 0 }; /** Call when we receive some data from proto (uart) */ void proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) { + uint8_t compt; /* This macro combine command and size in one integer. */ #define c(cmd, size) (cmd << 8 | size) switch (c (cmd, size)) @@ -49,13 +51,21 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) case c ('z', 0): utils_reset (); break; - case c ('S', 1): - sensor_rvb_stats = sensor_rvb_stat_enable = args[0]; + /* RVB sensors stats */ + case c ('S', 3): + for (compt = 0; compt < RVB_MAX_SENSOR; compt++) + // TODO improve this ! + if ( ((compt >= 8) && (args[0] & _BV(compt))) + || ((compt < 8) && (args[1] & _BV(compt))) ) + { + sensor_rvb_stat_enable[compt] = sensor_rvb_stats[compt] = + args[2]; + } break; - case c ('s', 2): - sensor_rvb_watch (args[0], args[1]); - break; - /* Unknown command */ +// case c ('s', 2): +// sensor_rvb_watch (args[0], args[1]); +// break; + /* Unknown commands */ default: proto_send0 ('?'); return; @@ -68,26 +78,43 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) int main (void) { - int compt; + uint8_t compt; + /* Serial port */ uart0_init (); - timer_init (); + /* Main timer init */ + timer_main_init (); + /* Init timer/counter 1 for RVB & PWM + * /!\ Must be called before RVB/PWM init ! */ + timer1_init (); + /* Init RVB sensors system */ sensor_rvb_init (); + + /* Enable interrupts */ sei (); + + /* We are ready ! */ proto_send0 ('z'); while (1) { - timer_wait (); - if (sensor_rvb_stat_enable && !--sensor_rvb_stats) + /* Wait 4.44 ms */ + timer_main_wait (); + + /* RVB Sensors stats */ + for (compt = 0; compt < RVB_MAX_SENSOR; compt++) + if (sensor_rvb_stat_enable[compt] && !--sensor_rvb_stats[compt]) { - sensor_rvb_stats = sensor_rvb_stat_enable; - for (compt = 0; compt < RVB_MAX_SENSOR; compt++) - proto_send4w ('S', sensor_rvb_values[compt][0], + /* Re init stats system for this sensor */ + sensor_rvb_stats[compt] = sensor_rvb_stat_enable[compt]; + proto_send4w ('S', sensor_rvb_values[compt][0], sensor_rvb_values[compt][1], sensor_rvb_values[compt][2], sensor_rvb_values[compt][3]); } + /* Update RVB sensors data. */ sensor_rvb_start_capture (); + + /* Get data for serial port */ while (uart0_poll ()) proto_accept (uart0_getc ()); } diff --git a/n/es-2006/src/sensor_rvb.c b/n/es-2006/src/sensor_rvb.c index ac8b0aa..a354c53 100644 --- a/n/es-2006/src/sensor_rvb.c +++ b/n/es-2006/src/sensor_rvb.c @@ -23,26 +23,32 @@ * * }}} */ #include "sensor_rvb.h" +#include "es_config.h" #include "io.h" #include "modules/utils/utils.h" /* regv */ #include "modules/uart/uart.h" +#include "modules/proto/proto.h" /** * Somes defines. **/ -/** Color pins. */ +/** Colors selection pins. */ #define S1RVB 7 #define S0RVB 6 /** Max input capture before considering we can start the real capture. */ -#define RVB_MAX_FALSE_IC 3 +#define RVB_MAX_FALSE_IC 4 +/** Max overflow of the timer 1 before thinking the sensor is HS. */ +/* TODO Find a way to compute this value */ +#define RVB_MAX_OVERFLOW 250 /** Wait time between IO change in ns. */ #define RVB_SENSOR_DELAY_IO 125 -/** All the possible states */ +/** All the possible states. */ #define RVB_STATE_SLEEP 0 /* Doing nothing */ #define RVB_STATE_NEXT_SENSOR 1 /* Selecting a sensor */ #define RVB_STATE_WAIT_IC 20 /* Waiting for the first input capture */ -#define RVB_STATE_WAIT_IC2 (RVB_STATE_WAIT_IC + 1) /* 2nd input capture */ +#define RVB_STATE_WAIT_IC2 (RVB_STATE_WAIT_IC + 1) /* 2nd and more false + input captures */ #define RVB_STATE_START_CAPTURE 2 /* After waiting enough IC, starting capture */ #define RVB_STATE_STOP_CAPTURE 3 /* We can compute a value */ #define RVB_STATE_NEXT_COLOR 4 /* Selecting another color */ @@ -57,7 +63,7 @@ volatile uint8_t sensor_rvb_number_; /** Color of the actual sensor. */ volatile uint8_t sensor_rvb_color_; /** Number of overflow interruption since last edge change. */ -uint8_t sensor_rvb_overflow_count_; +volatile uint8_t sensor_rvb_overflow_count_; /** Results table for 9 RVB sensors (RVCB) */ volatile uint16_t sensor_rvb_values[RVB_MAX_SENSOR][4]; /** Geting stats only for one sensors and disabling computing the others. */ @@ -65,6 +71,9 @@ uint8_t sensor_rvb_enable; /** Count the number of IC before starting a good capture. */ uint8_t sensor_rvb_ic_count_; +/** Update everything for you. */ +void sensor_rvb_update (void); + /** Select a color : * 0 : red ; * 1 : blue ; @@ -73,14 +82,22 @@ uint8_t sensor_rvb_ic_count_; inline uint8_t sensor_rvb_color_select (uint8_t sensor_rvb_color) { - /* Check */ - if (sensor_rvb_color > 3) + switch (sensor_rvb_color) + { + case RVB_INDEX_RED: + case RVB_INDEX_BLUE: + case RVB_INDEX_CLEAR: + case RVB_INDEX_GREEN: + /* Select the color */ + PORTF = (PORTF & ~0xC0) | (sensor_rvb_color << 6); + /* Wait a little */ + utils_delay_ns (RVB_SENSOR_DELAY_IO); + /* Color exists */ + return 1; + default: + /* Error */ return 0; - /* Select the color */ - PORTF = (PORTF & ~0xC0) | (sensor_rvb_color << 6); - /* Wait a little */ - utils_delay_ns (RVB_SENSOR_DELAY_IO); - return 1; + } } /** Enable a RVB sensor. */ @@ -117,9 +134,6 @@ sensor_rvb_sensor_select (uint8_t sensor_rvb_num) return 1; } -/** Update everything for you. */ -void sensor_rvb_update (void); - /** Initialisation of the RVB sensors module. */ void sensor_rvb_init (void) @@ -133,14 +147,6 @@ sensor_rvb_init (void) DDRD |= _BV(6); /* Put color selector pins in output */ DDRF |= _BV(S0RVB) | _BV(S1RVB); - /* Initialisation of counter : - * Noise canceler, 1 for prescaling */ - TCCR1B |= _BV(ICNC1) | _BV(CS10); - /* XXX Fast PWM 10-bit */ - TCCR1B |= _BV(WGM12); - TCCR1A |= _BV(WGM11) | _BV(WGM10); - /* XXX Overflow IR */ - TIMSK |= _BV (TOIE1); /* Nothing to do for the moment */ sensor_rvb_state_ = RVB_STATE_SLEEP; } @@ -150,7 +156,7 @@ void sensor_rvb_start_capture (void) { /* Are we already getting a sensor ? */ - if (!sensor_rvb_state_ && sensor_rvb_enable) + if ((sensor_rvb_state_ == RVB_STATE_SLEEP) && sensor_rvb_enable) { sensor_rvb_state_ = RVB_STATE_NEXT_SENSOR; /* Start with sensor one */ @@ -165,6 +171,7 @@ void sensor_rvb_watch (uint8_t sensor_num, uint8_t sensor_col) { // XXX Better approach. + return; /* Disable all interrupt that could be enabled */ TIMSK &= ~_BV (TICIE1); TIMSK &= ~_BV (TOIE1); @@ -199,7 +206,7 @@ sensor_rvb_update (void) else { sensor_rvb_state_ = RVB_STATE_WAIT_IC; - /* Enable interrupt for IC1 and counter overflow */ + /* Enable interrupt for IC1 */ TIMSK |= _BV (TICIE1); } } @@ -210,30 +217,43 @@ sensor_rvb_update (void) /* Select sensor */ if (!sensor_rvb_sensor_select (++sensor_rvb_number_)) { - /* Disable IC interrupt */ + /* Disable IC1 and TC1 overflow interrupts */ TIMSK &= ~_BV (TICIE1); + TIMSK &= ~_BV (TOIE1); sensor_rvb_state_ = RVB_STATE_SLEEP; return; } /* Start with first color */ sensor_rvb_color_select (sensor_rvb_color_ = 0); sensor_rvb_state_ = RVB_STATE_WAIT_IC; + sensor_rvb_overflow_count_ = 0; /* Enable interrupt for IC1 and counter overflow */ TIMSK |= _BV (TICIE1); + TIMSK |= _BV (TOIE1); } } /** Timer 1 overflow. */ SIGNAL (SIG_OVERFLOW1) { - if ((sensor_rvb_state_ == RVB_STATE_STOP_CAPTURE) && - (++sensor_rvb_overflow_count_ == 4)) + switch (sensor_rvb_state_) { - /* Disable IC interrupt */ - TIMSK &= ~_BV (TICIE1); - /* Ask for next sensor */ - sensor_rvb_state_ = RVB_STATE_NEXT_SENSOR; - sensor_rvb_update (); + case RVB_STATE_START_CAPTURE: + ++sensor_rvb_overflow_count_; + break; + case RVB_STATE_WAIT_IC: + case RVB_STATE_WAIT_IC2: + // XXX >= Sucks ! + // TODO : check this >= and the IC2 used + if (++sensor_rvb_overflow_count_ >= RVB_MAX_OVERFLOW) + { + /* Disable IC interrupt */ + TIMSK &= ~_BV (TICIE1); + /* Ask for next sensor */ + sensor_rvb_state_ = RVB_STATE_NEXT_SENSOR; + sensor_rvb_update (); + } + break; } } @@ -251,15 +271,17 @@ SIGNAL (SIG_INPUT_CAPTURE1) sensor_rvb_state_ = RVB_STATE_START_CAPTURE; break; case RVB_STATE_START_CAPTURE: + sensor_rvb_overflow_count_ = 0; /* Save capture start */ sensor_rvb_value_ = ICR1; /* New capture */ - sensor_rvb_overflow_count_ = 0; sensor_rvb_state_ = RVB_STATE_STOP_CAPTURE; break; case RVB_STATE_STOP_CAPTURE: /* Disable IC interrupt */ TIMSK &= ~_BV (TICIE1); + /* Ensure we have no pending interrupt for IC1. */ + TIFR = _BV (ICF1); /* Compute value */ sensor_rvb_value_ = ICR1 + sensor_rvb_overflow_count_ * TC1_TOP - sensor_rvb_value_; diff --git a/n/es-2006/src/sensor_rvb.h b/n/es-2006/src/sensor_rvb.h index c060f68..d138311 100644 --- a/n/es-2006/src/sensor_rvb.h +++ b/n/es-2006/src/sensor_rvb.h @@ -29,28 +29,33 @@ #include "io.h" /** Manage all the RVB sensors. -Connectors : - ENARVB7 PORTC7 - ENARVB6 PORTC6 - ENARVB5 PORTC5 - ENARVB4 PORTC4 - ENARVB3 PORTC3 - ENARVB2 PORTC2 - ENARVB1 PORTC1 - ENANB1 PORTD6 - ENANB2 PORTC0 - OUTRVB PORTD7/PORTD4(IC1) - S0RVB PORTF6 - S1RVB PORTF7 + * Connectors used : + ENARVB7 PORTC7 + ENARVB6 PORTC6 + ENARVB5 PORTC5 + ENARVB4 PORTC4 + ENARVB3 PORTC3 + ENARVB2 PORTC2 + ENARVB1 PORTC1 + ENANB1 PORTD6 + ENANB2 PORTC0 + OUTRVB PORTD7/PORTD4(IC1) + S0RVB PORTF6 + S1RVB PORTF7 - Sensor actualy send us a frequency for a specific color. We have pins for - selecting. + Sensors actualy send us a frequency for a specific color. We have pins + (ENA*) for selecting the sensor we want to use, some (S[01]RVB) for the + color we want to watch and one (OUTRVB) for the output frequency. + It uses the Input Capture and the Overflow interrupts. */ -/** Define of the TOP of the timer 1. */ -#define TC1_TOP 0x03FF /** Maximum number of sensors we manage. */ #define RVB_MAX_SENSOR 9 +/** Define the colors indexes. */ +#define RVB_INDEX_RED 0 +#define RVB_INDEX_BLUE 1 +#define RVB_INDEX_CLEAR 2 +#define RVB_INDEX_GREEN 3 /** Results table for 9 RVB sensors (RVCB) : * Values are in the folowing order : Red, Blue, Clear, Green. */ @@ -64,7 +69,8 @@ void sensor_rvb_init (void); /** Start a capture RVBC values for sensors if we are not already doing one. */ void sensor_rvb_start_capture (void); -/** Watch only one sensor. Usefull for debugging. */ +/** Watch only one sensor. Usefull for debugging. + * Does not work ! XXX */ void sensor_rvb_watch (uint8_t sensor_num, uint8_t color_num); #endif // sensor_rvb_h diff --git a/n/es-2006/src/timer.h b/n/es-2006/src/timer.h deleted file mode 100644 index 70f2de6..0000000 --- a/n/es-2006/src/timer.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef timer_h -#define timer_h -// timer.h -// es - Input/Output general purpose board. {{{ -// -// Copyright (C) 2006 Dufour Jérémy -// From Ni. -// -// Robot APB Team/Efrei 2004. -// Web: http://assos.efrei.fr/robot/ -// Email: robot AT efrei DOT fr -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// }}} - -/** Initialise the timer. */ -inline void -timer_init (void) -{ - TCCR0 = regv (FOC0, WGM00, COM01, COM0, WGM01, CS02, CS01, CS00, - 0, 0, 0, 0, 0, 1, 1, 0); - /* Fov = F_io / (prescaler * (TOP + 1)) - * TOP = 0xff - * prescaler = 256 - * Tov = 1 / Fov = 4.444 ms */ -} - -/** Wait for timer overflow. */ -inline void -timer_wait (void) -{ - while (!(TIFR & _BV (TOV0))) - ; - /* Write 1 to clear. */ - TIFR = _BV (TOV0); -} - -#endif // timer_h diff --git a/n/es-2006/src/timer_main.h b/n/es-2006/src/timer_main.h new file mode 100644 index 0000000..458db2e --- /dev/null +++ b/n/es-2006/src/timer_main.h @@ -0,0 +1,51 @@ +#ifndef timer_main_h +#define timer_main_h +// timer_main.h +// es - Input/Output general purpose board. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// From Ni. +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/** Initialise the main timer. */ +inline void +timer_main_init (void) +{ + TCCR0 = regv (FOC0, WGM00, COM01, COM0, WGM01, CS02, CS01, CS00, + 0, 0, 0, 0, 0, 1, 1, 0); + /* Fov = F_io / (prescaler * (TOP + 1)) + * TOP = 0xff + * prescaler = 256 + * Tov = 1 / Fov = 4.444 ms */ +} + +/** Wait for main timer overflow. */ +inline void +timer_main_wait (void) +{ + while (!(TIFR & _BV (TOV0))) + ; + /* Write 1 to clear. */ + TIFR = _BV (TOV0); +} + +#endif // timer_main_h -- cgit v1.2.3