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 +}