bicycle_odometer
changeset 0:0c1707508070
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 23 Aug 2011 19:01:11 +0300 |
parents | |
children | 5cbd47000b50 |
files | .hgignore Makefile odometer.c |
diffstat | 3 files changed, 176 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Aug 23 19:01:11 2011 +0300 1.3 @@ -0,0 +1,6 @@ 1.4 +\.d$ 1.5 +\.o$ 1.6 +\.swp$ 1.7 +^odometer.map$ 1.8 +^odometer.eep$ 1.9 +^odometer.hex$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Tue Aug 23 19:01:11 2011 +0300 2.3 @@ -0,0 +1,38 @@ 2.4 +src = $(wildcard *.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = odometer 2.7 +hex = $(bin).hex 2.8 +eep = $(bin).eep 2.9 + 2.10 +mcu_gcc = atmega168 2.11 +mcu_dude = m168 2.12 + 2.13 +CC = avr-gcc 2.14 +OBJCOPY = avr-objcopy 2.15 + 2.16 +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc) 2.17 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) 2.18 + 2.19 +.PHONY: all 2.20 +all: $(hex) $(eep) 2.21 + 2.22 +$(bin): $(obj) 2.23 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.24 + 2.25 +$(hex): $(bin) 2.26 + $(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@ 2.27 + 2.28 +$(eep): $(bin) 2.29 + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ 2.30 + 2.31 +.PHONY: fuses 2.32 +fuses: 2.33 + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0x66:m 2.34 + 2.35 +.PHONY: program 2.36 +program: $(hex) 2.37 + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) 2.38 + 2.39 +.PHONY: clean 2.40 +clean: 2.41 + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).$(map)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/odometer.c Tue Aug 23 19:01:11 2011 +0300 3.3 @@ -0,0 +1,132 @@ 3.4 +/* PORT USAGE 3.5 + * 3.6 + * D0-D3: data bus, connected to the D0-D3 pins of all the 4511 chips 3.7 + * C0-C5,D4,D5: directly driving the 8 speed graph LEDs 3.8 + * B0-B2: connected to the decoder controlling the 4511 latches as such: 3.9 + * 000 - speed most significant 3.10 + * 001 - speed least significant 3.11 + * 010 - dist most significant 3.12 + * 011 - dist middle 3.13 + * 100 - dist least significant 3.14 + * 101 - all latches are off (high) 3.15 + * B3-B5: ISP. B4 also acts as generic pushbutton input 3.16 + * B6,B7: XTAL 3.17 + * D6,D7: comparator, hall effect sensor input and threshold trimpot. 3.18 + */ 3.19 + 3.20 +/* 16mhz resonator */ 3.21 +#define F_CPU 2000000 3.22 + 3.23 +#include <avr/io.h> 3.24 +#include <avr/interrupt.h> 3.25 +#include <util/delay.h> 3.26 + 3.27 +void latch(int n); 3.28 +void update_display(void); 3.29 + 3.30 +int state; 3.31 +int debug_mode = 1; 3.32 + 3.33 +unsigned long nrot; 3.34 + 3.35 +/* wheel perimeter in centimeters */ 3.36 +#define WHEEL_PERIMETER 100 3.37 + 3.38 +int main(void) 3.39 +{ 3.40 + int i; 3.41 + 3.42 + DDRB = 0xf; /* only first four bits are outputs */ 3.43 + DDRC = 0xff; /* speed leds 6 bits */ 3.44 + DDRD = 0xff; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (don't care) */ 3.45 + 3.46 + /* zero-out the displays and disable all pullups except for the reset pin */ 3.47 + PORTB = 0; 3.48 + PORTC = 0x40; /* 6th bit set, C6 is reset */ 3.49 + PORTD = 0; 3.50 + 3.51 + for(i=0; i<5; i++) { 3.52 + latch(i); 3.53 + } 3.54 + 3.55 + /* read initial comparator state */ 3.56 + state = (ACSR >> ACO) & 1; 3.57 + 3.58 + if(debug_mode) { 3.59 + int i, j, leds, leds_val; 3.60 + 3.61 + for(i=0; ; i++) { 3.62 + for(j=0; j<5; j++) { 3.63 + /* set bits */ 3.64 + PORTD = (PORTD & 0xf0) | (((i + j) % 10) & 0xf); 3.65 + /* latch */ 3.66 + latch(j); 3.67 + } 3.68 + 3.69 + leds_val = 0; 3.70 + leds = i % 8; 3.71 + for(j=0; j<8; j++) { 3.72 + if(j <= leds) { 3.73 + leds_val |= (1 << j); 3.74 + } 3.75 + } 3.76 + PORTC = leds_val; 3.77 + PORTD = (PORTD & 0xf) | ((leds_val >> 2) & (3 << 4)); 3.78 + 3.79 + _delay_ms(1000); 3.80 + } 3.81 + } 3.82 + 3.83 + /* disable digital input buffer for the AINn pins */ 3.84 + /*DIDR1 = 0;*/ 3.85 + 3.86 + ACSR = (1 << ACIE); 3.87 + /* in debug mode we want an interrupt both on rising and falling edge 3.88 + * to be able to blink leds when the wheel goes past. otherwise we only need 3.89 + * a rising edge interrupt to increment the rotation counter. 3.90 + */ 3.91 + if(!debug_mode) { 3.92 + /* rising edge interrupt */ 3.93 + ACSR |= (3 << ACIS0); 3.94 + } 3.95 + 3.96 + sei(); 3.97 + 3.98 + for(;;); 3.99 + return 0; 3.100 +} 3.101 + 3.102 +void latch(int n) 3.103 +{ 3.104 + unsigned char upper = PORTB & 0xf0; 3.105 + /* pull latch low */ 3.106 + PORTB = upper | n; 3.107 + asm volatile("nop"); 3.108 + /* pull all latches high again */ 3.109 + PORTB = upper | 5; 3.110 +} 3.111 + 3.112 +ISR(ANALOG_COMP_vect) 3.113 +{ 3.114 + if(debug_mode) { 3.115 + int state = (ACSR >> ACO) & 1; 3.116 + 3.117 + if(state) { 3.118 + PORTB |= 1; 3.119 + nrot++; 3.120 + } else { 3.121 + PORTB &= ~1; 3.122 + } 3.123 + } else { 3.124 + nrot++; 3.125 + } 3.126 + 3.127 + update_display(); 3.128 +} 3.129 + 3.130 +void update_display(void) 3.131 +{ 3.132 + unsigned long dist_cm = (nrot * WHEEL_PERIMETER); 3.133 + 3.134 + /* TODO */ 3.135 +}