bicycle_odometer

changeset 2:f74f4561e71c

first version almost done
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 24 Aug 2011 07:51:12 +0300
parents 5cbd47000b50
children c0c68988bcdf
files Makefile odometer.c
diffstat 2 files changed, 156 insertions(+), 50 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Tue Aug 23 19:01:38 2011 +0300
     1.2 +++ b/Makefile	Wed Aug 24 07:51:12 2011 +0300
     1.3 @@ -27,7 +27,7 @@
     1.4  
     1.5  .PHONY: fuses
     1.6  fuses:
     1.7 -	avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0x66:m
     1.8 +	avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xe6:m
     1.9  
    1.10  .PHONY: program
    1.11  program: $(hex)
     2.1 --- a/odometer.c	Tue Aug 23 19:01:38 2011 +0300
     2.2 +++ b/odometer.c	Wed Aug 24 07:51:12 2011 +0300
     2.3 @@ -15,22 +15,49 @@
     2.4   */
     2.5  
     2.6  /* 16mhz resonator */
     2.7 -#define F_CPU	2000000
     2.8 +#define F_CPU		16000000
     2.9  
    2.10  #include <avr/io.h>
    2.11  #include <avr/interrupt.h>
    2.12 +#include <avr/power.h>
    2.13  #include <util/delay.h>
    2.14  
    2.15 +#define SEC_TICKS	(F_CPU / 256 / 256)
    2.16 +
    2.17 +#define PRESCL_1		1
    2.18 +#define PRESCL_8		2
    2.19 +#define PRESCL_64		3
    2.20 +#define PRESCL_256		4
    2.21 +#define PRESCL_1024		5
    2.22 +
    2.23 +
    2.24 +#define PB_CSEL_MASK	0x7
    2.25 +#define PD_DATA_MASK	0xf
    2.26 +#define PD_LEDS_MASK	0xc0
    2.27 +
    2.28 +#define RPS_TO_KMH(x)	((36 * WHEEL_PERIMETER * (x)) / 1000)
    2.29 +
    2.30 +#define DEBOUNCE_TICKS	1
    2.31 +
    2.32 +#define nop()	asm volatile("nop")
    2.33 +
    2.34 +void init_timer(void);
    2.35  void latch(int n);
    2.36  void update_display(void);
    2.37 +void disp_speed(int n);
    2.38 +void disp_dist(int n);
    2.39 +void disp_leds(int n);
    2.40  
    2.41  int state;
    2.42 -int debug_mode = 1;
    2.43 +int debug_mode = 0;
    2.44 +
    2.45 +volatile long ticks;
    2.46  
    2.47  unsigned long nrot;
    2.48 +unsigned long speed_rps;
    2.49  
    2.50  /* wheel perimeter in centimeters */
    2.51 -#define WHEEL_PERIMETER		100
    2.52 +#define WHEEL_PERIMETER		220
    2.53  
    2.54  int main(void)
    2.55  {
    2.56 @@ -38,7 +65,7 @@
    2.57  
    2.58  	DDRB = 0xf;		/* only first four bits are outputs */
    2.59  	DDRC = 0xff;	/* speed leds 6 bits */
    2.60 -	DDRD = 0xff;	/* 4bits data bus, 2 bits speed leds, 2 bits comparator (don't care) */
    2.61 +	DDRD = 0x3f;	/* 4bits data bus, 2 bits speed leds, 2 bits comparator (input) */
    2.62  
    2.63  	/* zero-out the displays and disable all pullups except for the reset pin */
    2.64  	PORTB = 0;
    2.65 @@ -49,56 +76,51 @@
    2.66  		latch(i);
    2.67  	}
    2.68  
    2.69 +	/* if the button at B4 is pressed during startup, enter debug mode */
    2.70 +	if((PINB >> 4) & 1) {
    2.71 +		debug_mode = 1;
    2.72 +		PORTC |= 3 << 4;
    2.73 +	}
    2.74 +
    2.75 +	init_timer();
    2.76 +
    2.77 +	/* disable digital input buffer for the AINn pins */
    2.78 +	DIDR1 = 0;
    2.79 +
    2.80  	/* read initial comparator state */
    2.81  	state = (ACSR >> ACO) & 1;
    2.82  
    2.83 -	if(debug_mode) {
    2.84 -		int i, j, leds, leds_val;
    2.85 -
    2.86 -		for(i=0; ; i++) {
    2.87 -			for(j=0; j<5; j++) {
    2.88 -				/* set bits */
    2.89 -				PORTD = (PORTD & 0xf0) | (((i + j) % 10) & 0xf);
    2.90 -				/* latch */
    2.91 -				latch(j);
    2.92 -			}
    2.93 -
    2.94 -			leds_val = 0;
    2.95 -			leds = i % 8;
    2.96 -			for(j=0; j<8; j++) {
    2.97 -				if(j <= leds) {
    2.98 -					leds_val |= (1 << j);
    2.99 -				}
   2.100 -			}
   2.101 -			PORTC = leds_val;
   2.102 -			PORTD = (PORTD & 0xf) | ((leds_val >> 2) & (3 << 4));
   2.103 -
   2.104 -			_delay_ms(1000);
   2.105 -		}
   2.106 -	}
   2.107 -
   2.108 -	/* disable digital input buffer for the AINn pins */
   2.109 -	/*DIDR1 = 0;*/
   2.110 -
   2.111 -	ACSR = (1 << ACIE);
   2.112  	/* in debug mode we want an interrupt both on rising and falling edge
   2.113  	 * to be able to blink leds when the wheel goes past. otherwise we only need
   2.114  	 * a rising edge interrupt to increment the rotation counter.
   2.115  	 */
   2.116 -	if(!debug_mode) {
   2.117 -		/* rising edge interrupt */
   2.118 -		ACSR |= (3 << ACIS0);
   2.119 -	}
   2.120 +	/* rising edge interrupt */
   2.121 +	/*ACSR |= (2 << ACIS0);*/
   2.122 +
   2.123 +	/* comparator interrupt enable */
   2.124 +	ACSR |= (1 << ACIE);
   2.125  
   2.126  	sei();
   2.127  
   2.128 -	for(;;);
   2.129 +	for(;;) {
   2.130 +	}
   2.131  	return 0;
   2.132  }
   2.133  
   2.134 +void init_timer(void)
   2.135 +{
   2.136 +	power_timer0_enable();
   2.137 +
   2.138 +	TCCR0A = 0;
   2.139 +	TCCR0B = PRESCL_256;
   2.140 +
   2.141 +	/* enable timer overflow interrupt */
   2.142 +	TIMSK0 = 1;
   2.143 +}
   2.144 +
   2.145  void latch(int n)
   2.146  {
   2.147 -	unsigned char upper = PORTB & 0xf0;
   2.148 +	unsigned char upper = PORTB & ~PB_CSEL_MASK;
   2.149  	/* pull latch low */
   2.150  	PORTB = upper | n;
   2.151  	asm volatile("nop");
   2.152 @@ -108,25 +130,109 @@
   2.153  
   2.154  ISR(ANALOG_COMP_vect)
   2.155  {
   2.156 -	if(debug_mode) {
   2.157 -		int state = (ACSR >> ACO) & 1;
   2.158 +	volatile static long prev_time;
   2.159 +	unsigned char aco;
   2.160 +
   2.161 +	nop();
   2.162 +	nop();
   2.163 +	nop();
   2.164 +
   2.165 +	aco = (ACSR >> ACO) & 1;
   2.166 +
   2.167 +	if(aco != state && (ticks - prev_time) > DEBOUNCE_TICKS) {
   2.168 +		state = aco;
   2.169  
   2.170  		if(state) {
   2.171 -			PORTB |= 1;
   2.172  			nrot++;
   2.173 -		} else {
   2.174 -			PORTB &= ~1;
   2.175 +
   2.176 +			update_display();
   2.177  		}
   2.178 -	} else {
   2.179 -		nrot++;
   2.180  	}
   2.181  
   2.182 -	update_display();
   2.183 +	prev_time = ticks;
   2.184 +}
   2.185 +
   2.186 +ISR(TIMER0_OVF_vect)
   2.187 +{
   2.188 +	volatile static int sec_ticks;
   2.189 +	volatile static unsigned long last_rot;
   2.190 +
   2.191 +	ticks++;
   2.192 +	sec_ticks++;
   2.193 +
   2.194 +	if(sec_ticks >= SEC_TICKS) {
   2.195 +		speed_rps = nrot - last_rot;
   2.196 +
   2.197 +		update_display();
   2.198 +
   2.199 +		sec_ticks = 0;
   2.200 +		last_rot = nrot;
   2.201 +	}
   2.202 +
   2.203 +
   2.204 +	if(debug_mode) {
   2.205 +		unsigned char state = (ACSR >> ACO) & 1;
   2.206 +		if(state) {
   2.207 +			PORTD |= (1 << 5);
   2.208 +		} else {
   2.209 +			PORTD &= ~(1 << 5);
   2.210 +		}
   2.211 +	}
   2.212  }
   2.213  
   2.214  void update_display(void)
   2.215  {
   2.216 -	unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
   2.217 +	if(debug_mode) {
   2.218 +		disp_dist(nrot);
   2.219 +		disp_speed(speed_rps);
   2.220  
   2.221 -	/* TODO */
   2.222 +		if(state) {
   2.223 +			PORTD |= (1 << 5);
   2.224 +		} else {
   2.225 +			PORTD &= ~(1 << 5);
   2.226 +		}
   2.227 +	} else {
   2.228 +		unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
   2.229 +		int speed_kmh = RPS_TO_KMH(speed_rps);
   2.230 +
   2.231 +		disp_dist(dist_cm / 10000);
   2.232 +		disp_speed(speed_kmh);
   2.233 +		disp_leds(speed_kmh * 8);
   2.234 +	}
   2.235  }
   2.236 +
   2.237 +void disp_speed(int n)
   2.238 +{
   2.239 +	PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
   2.240 +	latch(1);
   2.241 +	n /= 10;
   2.242 +	PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
   2.243 +	latch(0);
   2.244 +}
   2.245 +
   2.246 +void disp_dist(int n)
   2.247 +{
   2.248 +	PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
   2.249 +	latch(4);
   2.250 +	n /= 10;
   2.251 +	PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
   2.252 +	latch(3);
   2.253 +	n /= 10;
   2.254 +	PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
   2.255 +	latch(2);
   2.256 +}
   2.257 +
   2.258 +void disp_leds(int n)
   2.259 +{
   2.260 +	int i, count, bits;
   2.261 +
   2.262 +	count = (n + 4) >> 5;
   2.263 +	bits = 0;
   2.264 +
   2.265 +	for(i=0; i<count; i++) {
   2.266 +		bits |= (1 << i);
   2.267 +	}
   2.268 +
   2.269 +	PORTC = bits;
   2.270 +	PORTD = (PORTD & PD_DATA_MASK) | ((bits & PD_LEDS_MASK) >> 2);
   2.271 +}