bicycle_odometer

view odometer.c @ 2:f74f4561e71c

first version almost done
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 24 Aug 2011 07:51:12 +0300
parents 0c1707508070
children c0c68988bcdf
line source
1 /* PORT USAGE
2 *
3 * D0-D3: data bus, connected to the D0-D3 pins of all the 4511 chips
4 * C0-C5,D4,D5: directly driving the 8 speed graph LEDs
5 * B0-B2: connected to the decoder controlling the 4511 latches as such:
6 * 000 - speed most significant
7 * 001 - speed least significant
8 * 010 - dist most significant
9 * 011 - dist middle
10 * 100 - dist least significant
11 * 101 - all latches are off (high)
12 * B3-B5: ISP. B4 also acts as generic pushbutton input
13 * B6,B7: XTAL
14 * D6,D7: comparator, hall effect sensor input and threshold trimpot.
15 */
17 /* 16mhz resonator */
18 #define F_CPU 16000000
20 #include <avr/io.h>
21 #include <avr/interrupt.h>
22 #include <avr/power.h>
23 #include <util/delay.h>
25 #define SEC_TICKS (F_CPU / 256 / 256)
27 #define PRESCL_1 1
28 #define PRESCL_8 2
29 #define PRESCL_64 3
30 #define PRESCL_256 4
31 #define PRESCL_1024 5
34 #define PB_CSEL_MASK 0x7
35 #define PD_DATA_MASK 0xf
36 #define PD_LEDS_MASK 0xc0
38 #define RPS_TO_KMH(x) ((36 * WHEEL_PERIMETER * (x)) / 1000)
40 #define DEBOUNCE_TICKS 1
42 #define nop() asm volatile("nop")
44 void init_timer(void);
45 void latch(int n);
46 void update_display(void);
47 void disp_speed(int n);
48 void disp_dist(int n);
49 void disp_leds(int n);
51 int state;
52 int debug_mode = 0;
54 volatile long ticks;
56 unsigned long nrot;
57 unsigned long speed_rps;
59 /* wheel perimeter in centimeters */
60 #define WHEEL_PERIMETER 220
62 int main(void)
63 {
64 int i;
66 DDRB = 0xf; /* only first four bits are outputs */
67 DDRC = 0xff; /* speed leds 6 bits */
68 DDRD = 0x3f; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (input) */
70 /* zero-out the displays and disable all pullups except for the reset pin */
71 PORTB = 0;
72 PORTC = 0x40; /* 6th bit set, C6 is reset */
73 PORTD = 0;
75 for(i=0; i<5; i++) {
76 latch(i);
77 }
79 /* if the button at B4 is pressed during startup, enter debug mode */
80 if((PINB >> 4) & 1) {
81 debug_mode = 1;
82 PORTC |= 3 << 4;
83 }
85 init_timer();
87 /* disable digital input buffer for the AINn pins */
88 DIDR1 = 0;
90 /* read initial comparator state */
91 state = (ACSR >> ACO) & 1;
93 /* in debug mode we want an interrupt both on rising and falling edge
94 * to be able to blink leds when the wheel goes past. otherwise we only need
95 * a rising edge interrupt to increment the rotation counter.
96 */
97 /* rising edge interrupt */
98 /*ACSR |= (2 << ACIS0);*/
100 /* comparator interrupt enable */
101 ACSR |= (1 << ACIE);
103 sei();
105 for(;;) {
106 }
107 return 0;
108 }
110 void init_timer(void)
111 {
112 power_timer0_enable();
114 TCCR0A = 0;
115 TCCR0B = PRESCL_256;
117 /* enable timer overflow interrupt */
118 TIMSK0 = 1;
119 }
121 void latch(int n)
122 {
123 unsigned char upper = PORTB & ~PB_CSEL_MASK;
124 /* pull latch low */
125 PORTB = upper | n;
126 asm volatile("nop");
127 /* pull all latches high again */
128 PORTB = upper | 5;
129 }
131 ISR(ANALOG_COMP_vect)
132 {
133 volatile static long prev_time;
134 unsigned char aco;
136 nop();
137 nop();
138 nop();
140 aco = (ACSR >> ACO) & 1;
142 if(aco != state && (ticks - prev_time) > DEBOUNCE_TICKS) {
143 state = aco;
145 if(state) {
146 nrot++;
148 update_display();
149 }
150 }
152 prev_time = ticks;
153 }
155 ISR(TIMER0_OVF_vect)
156 {
157 volatile static int sec_ticks;
158 volatile static unsigned long last_rot;
160 ticks++;
161 sec_ticks++;
163 if(sec_ticks >= SEC_TICKS) {
164 speed_rps = nrot - last_rot;
166 update_display();
168 sec_ticks = 0;
169 last_rot = nrot;
170 }
173 if(debug_mode) {
174 unsigned char state = (ACSR >> ACO) & 1;
175 if(state) {
176 PORTD |= (1 << 5);
177 } else {
178 PORTD &= ~(1 << 5);
179 }
180 }
181 }
183 void update_display(void)
184 {
185 if(debug_mode) {
186 disp_dist(nrot);
187 disp_speed(speed_rps);
189 if(state) {
190 PORTD |= (1 << 5);
191 } else {
192 PORTD &= ~(1 << 5);
193 }
194 } else {
195 unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
196 int speed_kmh = RPS_TO_KMH(speed_rps);
198 disp_dist(dist_cm / 10000);
199 disp_speed(speed_kmh);
200 disp_leds(speed_kmh * 8);
201 }
202 }
204 void disp_speed(int n)
205 {
206 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
207 latch(1);
208 n /= 10;
209 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
210 latch(0);
211 }
213 void disp_dist(int n)
214 {
215 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
216 latch(4);
217 n /= 10;
218 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
219 latch(3);
220 n /= 10;
221 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
222 latch(2);
223 }
225 void disp_leds(int n)
226 {
227 int i, count, bits;
229 count = (n + 4) >> 5;
230 bits = 0;
232 for(i=0; i<count; i++) {
233 bits |= (1 << i);
234 }
236 PORTC = bits;
237 PORTD = (PORTD & PD_DATA_MASK) | ((bits & PD_LEDS_MASK) >> 2);
238 }