From 734dd6aa329098105a1a2a744ca73443dab44595 Mon Sep 17 00:00:00 2001 From: Jérémy Dufour Date: Sat, 14 Mar 2009 23:24:12 +0100 Subject: * digital/io: - clean main timer module, - update chrono module to rely on main timer (timer/counter 0). --- digital/io/src/chrono.c | 135 ++++++++++++++-------------------------- digital/io/src/chrono.h | 50 +++++++-------- digital/io/src/getsamples_cb.c | 2 +- digital/io/src/main_timer.avr.c | 14 +++-- digital/io/src/main_timer.h | 21 +++++-- digital/io/src/top_cb.c | 2 +- 6 files changed, 95 insertions(+), 129 deletions(-) (limited to 'digital') diff --git a/digital/io/src/chrono.c b/digital/io/src/chrono.c index 552232a3..6397f4f8 100644 --- a/digital/io/src/chrono.c +++ b/digital/io/src/chrono.c @@ -1,4 +1,4 @@ -/* chrono.avr.c */ +/* chrono.c */ /* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ * * Copyright (C) 2008 Dufour Jérémy @@ -23,115 +23,79 @@ * * }}} */ -#include "chrono.h" - -#include "modules/utils/utils.h" /* regv */ -#include "asserv.h" /* asserv_* */ +#include "common.h" -#include "io.h" /* Registers for timer/counter 1 */ +#include "aquajim.h" +#include "main_timer.h" +#include "asserv.h" -#ifdef HOST -#include -#include +#include "modules/utils/utils.h" #include "modules/host/mex.h" -#endif -/** - * Number of overflow of the timer/counter 1 before doing the last one. - */ -#define CHRONO_OVERFLOW_MAX 79 +#include "chrono.h" /** - * Number of TIC to restart from for the last overflow. - */ -#define CHRONO_RESTART_TIC 58982 -/** - * Duration of a loop to emulate from the original behaviour, in ms. + * Implementation notes. + * This module compute the number of tic of the main loop it should count + * before the match is over (chrono_init). Every tic of the main loop, it + * decrements the counter (chrono_update). When the counter is zero, the + * match is over (chrono_is_match_over, chrono_end_match). */ -#define CHRONO_LOOP_DURATION 4 + /** - * Time to wait before resetting asserv board, in ms. + * Number of overflows of the timer/counter 0 to wait before the match is + * over. + * Basically, it is match_duration / timer_counter_0_overflow_duration. */ -#define CHRONO_WAIT_BEFORE_RESET 1000 +#define CHRONO_MATCH_OVERFLOW_COUNT (MATCH_DURATION_MS / MT_TC0_PERIOD) /** - * Number of overflow to count before saying we are near the end of the match. - * You can compute it using the following formula: - * CHRONO_OVERFLOW_MAX * seconds / 90 + * Duration of a loop to emulate from the original behaviour, in ms. */ -#define CHRONO_OVERFLOW_COUNT_NEAR_END_MATCH \ - ((uint8_t) (CHRONO_OVERFLOW_MAX * 83 / 90)) +#define CHRONO_LOOP_DURATION_MS 4 /** - * Match is finished. - * This variable will be set to 1 when the match is over. + * Time to wait before resetting asserv board, in ms. */ -static volatile uint8_t chrono_match_over_ = 0; +#define CHRONO_WAIT_BEFORE_RESET_MS 1000 /** - * Overflow counter. + * Number of time to overflow before the end of the match. */ -static volatile uint8_t chrono_ov_count_; +static uint32_t chrono_ov_count_; -#ifdef HOST -/** SIGALRM handler. */ -void -signal_alarm (int signal); -#endif -/* Initialize the chrono timer/counter 1. */ void chrono_init (void) { -#ifndef HOST - /* Presaler = 256 */ - TCCR1B = regv (ICNC1, ICES1, 5, WGM13, WGM12, CS12, CS11, CS10, - 0, 0, 0, 0, 0, 1, 0, 0); - /* Enable overflow interrupt */ - set_bit (TIMSK, TOIE1); -#else - /* Set-up SIGALRM handler */ - signal (SIGALRM, &signal_alarm); - /* Alarm in 90 seconds */ -// alarm (90); -#endif + /* Set the overflow counter to the maximum of overflow before the end of + * the match. */ + chrono_ov_count_ = CHRONO_MATCH_OVERFLOW_COUNT; } -#ifndef HOST -/* Overflow of timer/counter 1 handler. */ -SIGNAL (SIG_OVERFLOW1) -{ - switch (++chrono_ov_count_) - { - case CHRONO_OVERFLOW_MAX: - /* Last but not complete overflow */ - TCNT1 = CHRONO_RESTART_TIC; - break; - case CHRONO_OVERFLOW_MAX + 1: - /* End of match! */ - chrono_match_over_ = 1; - break; - } -} -#else -/* SIGALRM handler */ void -signal_alarm (int signal) +chrono_update (void) { - /* End of match! */ - chrono_match_over_ = 1; + /* Decrement overflow counter if it is possible. */ + if (chrono_ov_count_) + chrono_ov_count_--; } -#endif - -/* Match over? */ uint8_t chrono_is_match_over (void) { - return chrono_match_over_; + if (chrono_ov_count_) + return 0; + else + return 1; +} + +uint32_t +chrono_remaining_time (void) +{ + return chrono_ov_count_ * MT_TC0_PERIOD; } -/* End the match. */ void chrono_end_match (uint8_t block) { @@ -144,7 +108,7 @@ chrono_end_match (uint8_t block) /* Manage retransmission */ asserv_retransmit (); /* Wait a little */ - utils_delay_ms (CHRONO_LOOP_DURATION); + utils_delay_ms (CHRONO_LOOP_DURATION_MS); } /* Make the bot stop moving */ @@ -161,7 +125,7 @@ chrono_end_match (uint8_t block) /* Retransmit if needed */ asserv_retransmit (); /* Wait a little */ - utils_delay_ms (CHRONO_LOOP_DURATION); + utils_delay_ms (CHRONO_LOOP_DURATION_MS); } else /* Exit loop */ @@ -169,7 +133,7 @@ chrono_end_match (uint8_t block) } /* Wait CHRONO_WAIT_BEFORE_RESET ms before reseting */ - utils_delay_ms (CHRONO_WAIT_BEFORE_RESET); + utils_delay_ms (CHRONO_WAIT_BEFORE_RESET_MS); /* Reset the asserv board */ asserv_reset (); /* Block indefinitely */ @@ -179,16 +143,7 @@ chrono_end_match (uint8_t block) { mex_node_wait (); } -#endif +#else ; -} - -/* Are we near the end of the match. */ -uint8_t -chrono_near_end_match (void) -{ - /* If we have overflow a certain number of time */ - if (chrono_ov_count_ >= CHRONO_OVERFLOW_COUNT_NEAR_END_MATCH) - return 1; - return 0; +#endif } diff --git a/digital/io/src/chrono.h b/digital/io/src/chrono.h index f8a5a308..5e1a378c 100644 --- a/digital/io/src/chrono.h +++ b/digital/io/src/chrono.h @@ -3,7 +3,7 @@ /* chrono.h */ /* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ * - * Copyright (C) 2008 Dufour Jérémy + * Copyright (C) 2008 Dufour Jérémy * * APBTeam: * Web: http://apbteam.org/ @@ -27,34 +27,44 @@ /** * @file Module to manage the chrono responsible to stop the bot after 90s. - * It uses the timer/counter 1 (16 bits), configured with a prescaler set to - * 256. - * This way, we need to overflow 79.10071 for a match of 90s: - * match_duration / (1 / (AC_FREQ / (Prescaler * (TOP + 1)))) - * It will overflow 79 times and them reset the timer/counter to 58982 - * (TOP - ((TOP + 1) / 10)). - * @todo add the ability to unblock the chrono_end_match with a flag that can - * be unset with an uart command. Maybe dangerous... + * + * It is based on the main timer (time/counter 0) to know when to stop the + * bot. + * + * The main loop should never last more than the 4.44ms defined, otherwise, + * this module will not be precise at all! */ -#include "common.h" - /** - * Initialize the chrono timer/counter 1. - * It starts it for a duration of 90s. + * Initialize the chrono module. + * It setups it for a duration of MATCH_DURATION_MS. */ void chrono_init (void); +/** + * Update chrono module. + * You must call this function every overflow of the main timer. + */ +void +chrono_update (void); + /** * Match over? * @return - * - 0 if the match is not finished yet - * - 1 if the match is over + * - 0 if the match is not finished yet. + * - 1 if the match is over. */ uint8_t chrono_is_match_over (void); +/** + * How much time remains before the end of the match. + * @return remaining time in ms. + */ +uint32_t +chrono_remaining_time (void); + /** * End the match. * This function is responsible of resetting the asserv board to stop the bot @@ -64,14 +74,4 @@ chrono_is_match_over (void); void chrono_end_match (uint8_t block); -/** - * Are we near the end of the match. - * This function tell you when there is not much time remaining. - * @return - * - 0 not near the end of the match - * - 1 near the end of the match - */ -uint8_t -chrono_near_end_match (void); - #endif /* chrono_h */ diff --git a/digital/io/src/getsamples_cb.c b/digital/io/src/getsamples_cb.c index 0990f4ae..86792887 100644 --- a/digital/io/src/getsamples_cb.c +++ b/digital/io/src/getsamples_cb.c @@ -273,7 +273,7 @@ getsamples__TAKE_SAMPLES__arm_pass_noted_position (void) /* Prepare classification */ getsamples_configure_classifier (); /* More samples? */ - if (getsamples_data_.sample_bitfield && !chrono_near_end_match ()) + if (getsamples_data_.sample_bitfield && !(chrono_remaining_time () > 83000)) { /* Compute notifier */ getsamples_data_.arm_noted_position += BOT_ARM_THIRD_ROUND; diff --git a/digital/io/src/main_timer.avr.c b/digital/io/src/main_timer.avr.c index 8f343403..bcb185b6 100644 --- a/digital/io/src/main_timer.avr.c +++ b/digital/io/src/main_timer.avr.c @@ -33,11 +33,13 @@ void main_timer_init (void) { - /* Fov = F_io / (prescaler * (TOP + 1)) - * TOP = 0xff - * prescaler = 256 - * Tov = 1 / Fov = 4.444 ms */ - /* Note: if you change this, update MT_TC0_*. */ + /* Configuration of the timer/counter 0: + * - top = 0xff, + * - prescaler = 256, + * -> Fov = F_io / (prescaler * (TOP + 1)) + * -> Tov = 1 / Fov = 4.444 ms. + * Note: if you change the TCCR0 register value, please also update + * MT_TC0_PRESCALER and MT_TC0_TOP. */ TCCR0 = regv (FOC0, WGM00, COM01, COM0, WGM01, CS02, CS01, CS00, 0, 0, 0, 0, 0, 1, 1, 0); } @@ -45,7 +47,7 @@ main_timer_init (void) uint8_t main_timer_wait (void) { - /* We have reached overflow. */ + /* Let's pretend we have reached overflow before calling this function. */ uint8_t count_before_ov = 1; /* Loop until an overflow of the timer occurs. */ while (!(TIFR & _BV (TOV0))) diff --git a/digital/io/src/main_timer.h b/digital/io/src/main_timer.h index 1b69a743..3f582f95 100644 --- a/digital/io/src/main_timer.h +++ b/digital/io/src/main_timer.h @@ -37,21 +37,26 @@ */ /** - * Configuration of prescaler of timer/counter 0. + * Prescaler configured for timer/counter 0. + * If you want to change this value, you also need to change the TCCR0 + * register. */ -#define MT_TC0_PRESCALER 256 +#define MT_TC0_PRESCALER 256L /** - * Configuration of the top of timer/counter 0. + * Top configured for timer/counter 0. + * If you want to change this value, you also need to change the TCCR0 + * register. */ #define MT_TC0_TOP 255 /** - * Configuration of the period timer/counter 0 (in millisecond). + * Period of timer/counter 0 (in millisecond). */ -#define MT_TC0_PERIOD ((1 / AC_FREQ / MT_TC0_PRESCALER * (MT_TC0_TOP + 1)) \ - * 1000) +#define MT_TC0_PERIOD \ + (1000 / (AC_FREQ / (MT_TC0_PRESCALER * (MT_TC0_TOP + 1)))) /** * Initialize the main timer to 4.444 ms. + * This function setup the timer/counter 0 configuration register. */ void main_timer_init (void); @@ -62,6 +67,10 @@ main_timer_init (void); * - 0 if we are on time (we have not reached overflow before calling this * function). * - 1 if we have already reached overflow. + * @warning if this function return 1, it means we are late and the main loop + * is lasting more than the time configured. Consequence, some important + * functions (like the chronometer for match duration) will not work + * correctly! */ uint8_t main_timer_wait (void); diff --git a/digital/io/src/top_cb.c b/digital/io/src/top_cb.c index 9383d887..83a6be5c 100644 --- a/digital/io/src/top_cb.c +++ b/digital/io/src/top_cb.c @@ -118,7 +118,7 @@ top__MOVE_AWAY_FROM_START_BORDER__move_fsm_finished (void) fsm_branch_t top__GET_SAMPLES_FROM_SAMPLES_DISTRIBUTOR__get_samples_fsm_finished (void) { - if (!chrono_near_end_match ()) + if (!(chrono_remaining_time ()> 83000)) { /* Start the move FSM to our ice distributor */ move_start (PG_DISTRIBUTOR_ICE_OUR_X, PG_DISTRIBUTOR_ICE_OUR_Y, 0); -- cgit v1.2.3