bicycle_odometer

diff odometer.c @ 0:0c1707508070

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 23 Aug 2011 19:01:11 +0300
parents
children f74f4561e71c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/odometer.c	Tue Aug 23 19:01:11 2011 +0300
     1.3 @@ -0,0 +1,132 @@
     1.4 +/* PORT USAGE
     1.5 + *
     1.6 + * D0-D3: data bus, connected to the D0-D3 pins of all the 4511 chips
     1.7 + * C0-C5,D4,D5: directly driving the 8 speed graph LEDs
     1.8 + * B0-B2: connected to the decoder controlling the 4511 latches as such:
     1.9 + *        000 - speed most significant
    1.10 + *        001 - speed least significant
    1.11 + *        010 - dist most significant
    1.12 + *        011 - dist middle
    1.13 + *        100 - dist least significant
    1.14 + *        101 - all latches are off (high)
    1.15 + * B3-B5: ISP. B4 also acts as generic pushbutton input
    1.16 + * B6,B7: XTAL
    1.17 + * D6,D7: comparator, hall effect sensor input and threshold trimpot.
    1.18 + */
    1.19 +
    1.20 +/* 16mhz resonator */
    1.21 +#define F_CPU	2000000
    1.22 +
    1.23 +#include <avr/io.h>
    1.24 +#include <avr/interrupt.h>
    1.25 +#include <util/delay.h>
    1.26 +
    1.27 +void latch(int n);
    1.28 +void update_display(void);
    1.29 +
    1.30 +int state;
    1.31 +int debug_mode = 1;
    1.32 +
    1.33 +unsigned long nrot;
    1.34 +
    1.35 +/* wheel perimeter in centimeters */
    1.36 +#define WHEEL_PERIMETER		100
    1.37 +
    1.38 +int main(void)
    1.39 +{
    1.40 +	int i;
    1.41 +
    1.42 +	DDRB = 0xf;		/* only first four bits are outputs */
    1.43 +	DDRC = 0xff;	/* speed leds 6 bits */
    1.44 +	DDRD = 0xff;	/* 4bits data bus, 2 bits speed leds, 2 bits comparator (don't care) */
    1.45 +
    1.46 +	/* zero-out the displays and disable all pullups except for the reset pin */
    1.47 +	PORTB = 0;
    1.48 +	PORTC = 0x40;	/* 6th bit set, C6 is reset */
    1.49 +	PORTD = 0;
    1.50 +
    1.51 +	for(i=0; i<5; i++) {
    1.52 +		latch(i);
    1.53 +	}
    1.54 +
    1.55 +	/* read initial comparator state */
    1.56 +	state = (ACSR >> ACO) & 1;
    1.57 +
    1.58 +	if(debug_mode) {
    1.59 +		int i, j, leds, leds_val;
    1.60 +
    1.61 +		for(i=0; ; i++) {
    1.62 +			for(j=0; j<5; j++) {
    1.63 +				/* set bits */
    1.64 +				PORTD = (PORTD & 0xf0) | (((i + j) % 10) & 0xf);
    1.65 +				/* latch */
    1.66 +				latch(j);
    1.67 +			}
    1.68 +
    1.69 +			leds_val = 0;
    1.70 +			leds = i % 8;
    1.71 +			for(j=0; j<8; j++) {
    1.72 +				if(j <= leds) {
    1.73 +					leds_val |= (1 << j);
    1.74 +				}
    1.75 +			}
    1.76 +			PORTC = leds_val;
    1.77 +			PORTD = (PORTD & 0xf) | ((leds_val >> 2) & (3 << 4));
    1.78 +
    1.79 +			_delay_ms(1000);
    1.80 +		}
    1.81 +	}
    1.82 +
    1.83 +	/* disable digital input buffer for the AINn pins */
    1.84 +	/*DIDR1 = 0;*/
    1.85 +
    1.86 +	ACSR = (1 << ACIE);
    1.87 +	/* in debug mode we want an interrupt both on rising and falling edge
    1.88 +	 * to be able to blink leds when the wheel goes past. otherwise we only need
    1.89 +	 * a rising edge interrupt to increment the rotation counter.
    1.90 +	 */
    1.91 +	if(!debug_mode) {
    1.92 +		/* rising edge interrupt */
    1.93 +		ACSR |= (3 << ACIS0);
    1.94 +	}
    1.95 +
    1.96 +	sei();
    1.97 +
    1.98 +	for(;;);
    1.99 +	return 0;
   1.100 +}
   1.101 +
   1.102 +void latch(int n)
   1.103 +{
   1.104 +	unsigned char upper = PORTB & 0xf0;
   1.105 +	/* pull latch low */
   1.106 +	PORTB = upper | n;
   1.107 +	asm volatile("nop");
   1.108 +	/* pull all latches high again */
   1.109 +	PORTB = upper | 5;
   1.110 +}
   1.111 +
   1.112 +ISR(ANALOG_COMP_vect)
   1.113 +{
   1.114 +	if(debug_mode) {
   1.115 +		int state = (ACSR >> ACO) & 1;
   1.116 +
   1.117 +		if(state) {
   1.118 +			PORTB |= 1;
   1.119 +			nrot++;
   1.120 +		} else {
   1.121 +			PORTB &= ~1;
   1.122 +		}
   1.123 +	} else {
   1.124 +		nrot++;
   1.125 +	}
   1.126 +
   1.127 +	update_display();
   1.128 +}
   1.129 +
   1.130 +void update_display(void)
   1.131 +{
   1.132 +	unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
   1.133 +
   1.134 +	/* TODO */
   1.135 +}