summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--digital/io/src/chrono.c135
-rw-r--r--digital/io/src/chrono.h50
-rw-r--r--digital/io/src/getsamples_cb.c2
-rw-r--r--digital/io/src/main_timer.avr.c14
-rw-r--r--digital/io/src/main_timer.h21
-rw-r--r--digital/io/src/top_cb.c2
6 files changed, 95 insertions, 129 deletions
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 <unistd.h>
-#include <signal.h>
+#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,35 +27,45 @@
/**
* @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
* from moving and put the io board in a state where it will not do something.
@@ -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);