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