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