summaryrefslogtreecommitdiffhomepage
path: root/digital/io/src/chrono.c
blob: 95384455864d5a1762986c45804647494eacb9af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* chrono.avr.c */
/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
 *
 * Copyright (C) 2008 Dufour Jérémy
 *
 * APBTeam:
 *        Web: http://apbteam.org/
 *      Email: team AT apbteam DOT org
 *
 * 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 "chrono.h"

#include "modules/utils/utils.h"	/* regv */
#include "asserv.h"			/* asserv_* */

#include "io.h"				/* Registers for timer/counter 1 */

/**
 * Number of overflow of the timer/counter 1 before doing the last one.
 */
#define CHRONO_OVERFLOW_MAX 70

/**
 * 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.
 */
#define CHRONO_LOOP_DURATION 4
/**
 * Time to wait before resetting asserv board, in ms.
 */
#define CHRONO_WAIT_BEFORE_RESET 1000

/**
 * Match is finished.
 * This variable will be set to 1 when the match is over.
 */
static volatile uint8_t chrono_match_over_ = 0;

/**
 * Overflow counter.
 */
static volatile uint8_t chrono_ov_count_;

/* 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,     1, 0,     0,     0,    1,    0,    0);
    /* Enable overflow interrupt */
    set_bit (TIMSK, TOIE1);
#endif
}

#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;
      }
}
#endif

/* Match over? */
uint8_t
chrono_is_match_over (void)
{
    return chrono_match_over_;
}

/* End the match. */
void
chrono_end_match (uint8_t block)
{
    /* Make sure previous command has been acknowledged. If not, retransmit
     * until acknowledged */
    while (asserv_last_cmd_ack () == 0)
      {
	/* Update status */
	asserv_update_status ();
	/* Manage retransmission */
	asserv_retransmit ();
	/* Wait a little */
	utils_delay_ms (CHRONO_LOOP_DURATION);
      }

    /* Make the bot stop moving */
    asserv_stop_motor ();

    /* Wait until complete */
    while (42)
      {
	/* Update the asserv board */
	asserv_update_status ();
	/* Stop acknowledged ? */
	if (asserv_last_cmd_ack () == 0)
	  {
	    /* Retransmit if needed */
	    asserv_retransmit ();
	    /* Wait a little */
	    utils_delay_ms (CHRONO_LOOP_DURATION);
	  }
	else
	    /* Exit loop */
	    break;
      }

    /* Wait CHRONO_WAIT_BEFORE_RESET ms before reseting */
    utils_delay_ms (CHRONO_WAIT_BEFORE_RESET);
    /* Reset the asserv board */
    asserv_reset ();
    /* Block indefinitely */
    if (block)
	while (42);
}