/* rvb_sensor.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 "rvb_sensor.h" #include "io.h" #include "modules/utils/utils.h" /* regv */ #include "modules/uart/uart.h" /* */ #define S1RVB 7 #define S0RVB 6 /* Wait time between IO change in ns */ #define RVB_SENSOR_DELAY_IO 125 /** Internal counter */ static volatile uint16_t sensor_value_; /** Sensor state flag */ static volatile uint8_t sensor_state_; /** Sensor used actually */ volatile uint8_t sensor_number_; /** Color of the actual sensor */ volatile uint8_t sensor_color_; /** Number of overflow interruption since last edge change */ uint8_t sensor_overflow_count_; volatile uint16_t rvb_sensors_values [9][5]; uint8_t sensor_disable = 0; /** Update everything for you. */ static void rvb_sensors_update_state (void) { // uart0_putc ('u'); if (sensor_state_ == 1) { /* Disable sensors */ rvb_sensors_disable (); /* Wait a little */ utils_delay_ns (RVB_SENSOR_DELAY_IO); switch (++sensor_number_) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: // PORTC = ~_BV(sensor_number_); // break; case 8: // PORTD &= ~_BV(6); // break; case 9: // PORTC = ~_BV(0); // break; PORTD &= ~_BV(6); break; default: /* We are at the end */ sensor_state_ = 0; return; } /* Wait for output of sensor to be ready */ utils_delay_ns (RVB_SENSOR_DELAY_IO); /* Start with first color */ sensor_color_ = 0; } /* Select the color */ PORTF = (PORTF & ~0xC0) | (sensor_color_ << 6); /* Enable interrupt for IC1 */ TIMSK |= _BV (TICIE1); // uart0_putc ('e'); // XXX // TIMSK |= _BV (TOIE1); } /** Counter 1 overflow. */ SIGNAL (SIG_OVERFLOW1) { // XXX For the moment. if (++sensor_overflow_count_ == 2) { sensor_state_ = 1; rvb_sensors_update_state (); } } /** Interrupt on falling edge for Input Capture 1. */ SIGNAL (SIG_INPUT_CAPTURE1) { switch (sensor_state_) { case 1: /* Ignore this capture */ sensor_state_++; break; case 2: /* Save capture start */ sensor_value_ = ICR1; /* New capture */ sensor_overflow_count_ = 0; /* Enable interruption for overflow */ sensor_state_++; // TIMSK |= _BV (TOIE1); break; case 3: /* Disable this interruption */ TIMSK &= ~_BV (TICIE1); /* Disable interruption for overflow */ TIMSK &= ~_BV (TOIE1); /* Compute value */ //TODO sensor_value_ = ICR1 - sensor_value_; /* Save */ rvb_sensors_values[sensor_number_ - 1][sensor_color_] = sensor_value_; /* Next color */ sensor_color_++; /* If no more colour, next sensor */ if (sensor_color_ == 4) sensor_state_ = 1; rvb_sensors_update_state (); break; } } /** Start updating RVBC values for sensors. */ void rvb_sensors_start_update (void) { // uart0_putc ('i'); /* Are we already getting a sensor ? */ if (!sensor_state_ && !sensor_disable) { sensor_state_ = 1; /* Start with sensor one */ sensor_number_ = 0; /* Select it and launch capture */ rvb_sensors_update_state (); } } /** Initialisation. */ void rvb_sensors_init (void) { /* Disable sensors */ rvb_sensors_disable (); /* Put enable ports in output mode */ DDRC = 0xff; DDRD |= _BV(6); /* Put color selector mode in output mode */ DDRF |= _BV(S0RVB) | _BV(S1RVB); /* Initialisation of counter : * Noise canceler, 1 for prescaling and that's all */ TCCR1B |= _BV(ICNC1) | _BV(CS10); /* Nothing to do for the moment */ sensor_state_ = 0; } void rvb_sensor_watch (uint8_t sensor_num, uint8_t sensor_col) { /* Disable this interruption */ TIMSK &= ~_BV (TICIE1); /* Disable interruption for overflow */ TIMSK &= ~_BV (TOIE1); sensor_disable = 1; /* Disable sensors */ rvb_sensors_disable (); /* Wait a little */ utils_delay_ns (RVB_SENSOR_DELAY_IO); switch (++sensor_num) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: PORTC = ~_BV(sensor_num); break; case 8: PORTD &= ~_BV(6); break; case 9: PORTC = ~_BV(0); break; } /* Wait for output of sensor to be ready */ utils_delay_ns (RVB_SENSOR_DELAY_IO); /* Select the color */ PORTF = (PORTF & ~0xC0) | (sensor_col << 6); }