bicycle_odometer

annotate 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
rev   line source
nuclear@0 1 /* PORT USAGE
nuclear@0 2 *
nuclear@0 3 * D0-D3: data bus, connected to the D0-D3 pins of all the 4511 chips
nuclear@0 4 * C0-C5,D4,D5: directly driving the 8 speed graph LEDs
nuclear@0 5 * B0-B2: connected to the decoder controlling the 4511 latches as such:
nuclear@0 6 * 000 - speed most significant
nuclear@0 7 * 001 - speed least significant
nuclear@0 8 * 010 - dist most significant
nuclear@0 9 * 011 - dist middle
nuclear@0 10 * 100 - dist least significant
nuclear@0 11 * 101 - all latches are off (high)
nuclear@0 12 * B3-B5: ISP. B4 also acts as generic pushbutton input
nuclear@0 13 * B6,B7: XTAL
nuclear@0 14 * D6,D7: comparator, hall effect sensor input and threshold trimpot.
nuclear@0 15 */
nuclear@0 16
nuclear@0 17 /* 16mhz resonator */
nuclear@0 18 #define F_CPU 2000000
nuclear@0 19
nuclear@0 20 #include <avr/io.h>
nuclear@0 21 #include <avr/interrupt.h>
nuclear@0 22 #include <util/delay.h>
nuclear@0 23
nuclear@0 24 void latch(int n);
nuclear@0 25 void update_display(void);
nuclear@0 26
nuclear@0 27 int state;
nuclear@0 28 int debug_mode = 1;
nuclear@0 29
nuclear@0 30 unsigned long nrot;
nuclear@0 31
nuclear@0 32 /* wheel perimeter in centimeters */
nuclear@0 33 #define WHEEL_PERIMETER 100
nuclear@0 34
nuclear@0 35 int main(void)
nuclear@0 36 {
nuclear@0 37 int i;
nuclear@0 38
nuclear@0 39 DDRB = 0xf; /* only first four bits are outputs */
nuclear@0 40 DDRC = 0xff; /* speed leds 6 bits */
nuclear@0 41 DDRD = 0xff; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (don't care) */
nuclear@0 42
nuclear@0 43 /* zero-out the displays and disable all pullups except for the reset pin */
nuclear@0 44 PORTB = 0;
nuclear@0 45 PORTC = 0x40; /* 6th bit set, C6 is reset */
nuclear@0 46 PORTD = 0;
nuclear@0 47
nuclear@0 48 for(i=0; i<5; i++) {
nuclear@0 49 latch(i);
nuclear@0 50 }
nuclear@0 51
nuclear@0 52 /* read initial comparator state */
nuclear@0 53 state = (ACSR >> ACO) & 1;
nuclear@0 54
nuclear@0 55 if(debug_mode) {
nuclear@0 56 int i, j, leds, leds_val;
nuclear@0 57
nuclear@0 58 for(i=0; ; i++) {
nuclear@0 59 for(j=0; j<5; j++) {
nuclear@0 60 /* set bits */
nuclear@0 61 PORTD = (PORTD & 0xf0) | (((i + j) % 10) & 0xf);
nuclear@0 62 /* latch */
nuclear@0 63 latch(j);
nuclear@0 64 }
nuclear@0 65
nuclear@0 66 leds_val = 0;
nuclear@0 67 leds = i % 8;
nuclear@0 68 for(j=0; j<8; j++) {
nuclear@0 69 if(j <= leds) {
nuclear@0 70 leds_val |= (1 << j);
nuclear@0 71 }
nuclear@0 72 }
nuclear@0 73 PORTC = leds_val;
nuclear@0 74 PORTD = (PORTD & 0xf) | ((leds_val >> 2) & (3 << 4));
nuclear@0 75
nuclear@0 76 _delay_ms(1000);
nuclear@0 77 }
nuclear@0 78 }
nuclear@0 79
nuclear@0 80 /* disable digital input buffer for the AINn pins */
nuclear@0 81 /*DIDR1 = 0;*/
nuclear@0 82
nuclear@0 83 ACSR = (1 << ACIE);
nuclear@0 84 /* in debug mode we want an interrupt both on rising and falling edge
nuclear@0 85 * to be able to blink leds when the wheel goes past. otherwise we only need
nuclear@0 86 * a rising edge interrupt to increment the rotation counter.
nuclear@0 87 */
nuclear@0 88 if(!debug_mode) {
nuclear@0 89 /* rising edge interrupt */
nuclear@0 90 ACSR |= (3 << ACIS0);
nuclear@0 91 }
nuclear@0 92
nuclear@0 93 sei();
nuclear@0 94
nuclear@0 95 for(;;);
nuclear@0 96 return 0;
nuclear@0 97 }
nuclear@0 98
nuclear@0 99 void latch(int n)
nuclear@0 100 {
nuclear@0 101 unsigned char upper = PORTB & 0xf0;
nuclear@0 102 /* pull latch low */
nuclear@0 103 PORTB = upper | n;
nuclear@0 104 asm volatile("nop");
nuclear@0 105 /* pull all latches high again */
nuclear@0 106 PORTB = upper | 5;
nuclear@0 107 }
nuclear@0 108
nuclear@0 109 ISR(ANALOG_COMP_vect)
nuclear@0 110 {
nuclear@0 111 if(debug_mode) {
nuclear@0 112 int state = (ACSR >> ACO) & 1;
nuclear@0 113
nuclear@0 114 if(state) {
nuclear@0 115 PORTB |= 1;
nuclear@0 116 nrot++;
nuclear@0 117 } else {
nuclear@0 118 PORTB &= ~1;
nuclear@0 119 }
nuclear@0 120 } else {
nuclear@0 121 nrot++;
nuclear@0 122 }
nuclear@0 123
nuclear@0 124 update_display();
nuclear@0 125 }
nuclear@0 126
nuclear@0 127 void update_display(void)
nuclear@0 128 {
nuclear@0 129 unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
nuclear@0 130
nuclear@0 131 /* TODO */
nuclear@0 132 }