Subversion Repositories group.electronics

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
130 pfowler 1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
#include <avr/interrupt.h>
4
#include <string.h>
5
#include <util/delay.h>
6
#include <stdlib.h>
7
 
8
#include "config.h"
9
#include "avrutil.h"
10
#include "hc595.h"
11
#include "twires.h"
12
 
13
 
14
#ifndef NULL
15
#define NULL    ((void *)0)
16
#endif
17
 
18
 
19
void writeSegment(uint8_t digit, uint8_t value);
20
void pcInterrupt(void);
21
void receiveEvent(uint8_t bytes);
22
 
23
/* ------------------------------------------------------------------------- */
24
 
25
 
26
#ifndef TWI_RX_BUFFER_SIZE
27
#define TWI_RX_BUFFER_SIZE ( 16 )
28
#endif
29
 
30
volatile uint8_t user_debug = 0;
31
volatile uint8_t tmr0_ovf = 0;
32
volatile struct {
33
        uint8_t current;
34
        uint8_t last;
35
        uint8_t mask;
36
} pcInt;
37
 
38
volatile struct {
39
	int8_t outer;
40
	int8_t inner;
41
} input;
42
 
43
//volatile uint8_t doInt = 0;
44
 
45
 
46
//uint8_t disVal[] = {8,8,8,8,8,8,8,8,8,8};
47
volatile uint8_t disVal[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
48
volatile uint8_t disPt[] = {0, 0};
49
 
50
int main(void) {
51
 
52
 
53
  /*
54
  DDR : 1 = Output, 0 = Input
55
  PORT: 1 = Pullup for Input, otherwise set output
56
  PIN : Read input pin
57
  */
58
 
59
 
60
  /*
61
		PA0	-	Output			- HC595 DS
62
		PA1	- 	Output			- HC595 ST
63
		PA2 -	Output			- HC595 SH
64
		PA3 -	Output			- 4511 blanking
65
		PA4 -	SCK
66
		PA5 -	Output			- Decimal Point
67
		PA6 -	SDA
68
		PA7 -	Input, Pullup			- Flip button
69
  */
70
  DDRA          = 0B00101111;
71
  PORTA         = 0B10001000;
72
  /*
73
        PB0     - Input, PCInt, Pullup	- Rot1a
74
        PB1     - Input, PCInt, Pullup	- Rot1b
75
        PB2     - Input, Pullup			- Swap button
76
        PB3     - N/A					- Reset (Future - I2C address select)
77
  */
78
  DDRB          = 0B00000000;
79
  PORTB         = 0B00000111;
80
 
81
    systime = 0;
82
    sysclockInit();
83
 
84
    PCMSK1 |= (( 1 << ROT_1A_PIN ) | ( 1 << ROT_1B_PIN ));
85
    GIMSK |= (1 << PCIE1);
86
 
87
    pcInt.last = ROT_1_PIN;
88
    pcInt.current = pcInt.last;
89
    pcInt.mask = 0;
90
 
91
    twires_begin(I2C_SLAVE_ADDR);
92
    twires_onReceive(receiveEvent);
93
 
94
    wdt_enable(WDTO_1S);	// Watchdog for 1 sec
95
    sei();					// Enable interrupts
96
 
97
    hc595_init();
98
    hc595_write(0x00);
99
 
100
    uint32_t refresh = systime;
101
    uint8_t disIdx = 0;
102
 
103
 
104
 
105
    for(;;){
106
    	 wdt_reset();
107
 
108
    	if (user_debug) {
109
    		disVal[9] = rbi(SB_INPUT, SB_PIN);
110
    		disVal[8] = rbi(FB_INPUT, FB_PIN);
111
    		disVal[0] = input.outer & 0x0f;
112
    		disVal[1] = input.outer >> 4;
113
    	}
114
 
115
		if (pcInt.current != pcInt.last) {
116
			pcInterrupt();
117
		}
118
 
119
		if (systime > refresh) {
120
			writeSegment(disIdx, disVal[disIdx]);
121
			refresh = systime + DISPLAY_REFRESH;
122
			disIdx++;
123
			if (disIdx > 10) disIdx = 0;
124
		}
125
 
126
		twires_stop_check();
127
    }
128
    return 0;
129
}
130
 
131
void receiveEvent(uint8_t bytes) {
132
	uint8_t cmd = twires_receive();
133
	bytes--;
134
	switch (cmd) {
135
		case (0x01): {
136
			twires_send(HW_VERSION);
137
			twires_send(SW_VERSION);
138
		}
139
			break;
140
		case (0x03): {
141
			user_debug = twires_receive();
142
		}
143
			break;
144
		case (0x05): {
145
			while (bytes--) {
146
				uint8_t data = twires_receive();
147
				disVal[(data >> 4)] = (data & 0x0f);
148
			}
149
		}
150
			break;
151
		case (0x08): {
152
			disPt[0] = twires_receive();
153
			disPt[1] = twires_receive();
154
		}
155
			break;
156
		case (0x09): {
157
			input.outer = 0;
158
			input.inner = 0;
159
		}
160
			break;
161
		case (0x0a): {
162
			twires_send(input.outer);
163
		}
164
			break;
165
		/* Not used in this version
166
		case (0x0b): {
167
			twires_send(input.inner);
168
		}
169
			break;
170
		*/
171
 
172
		case (0x0c): {
173
			uint8_t out = (!rbi(SB_INPUT, SB_PIN)) << 1;
174
			out |= (!rbi(FB_INPUT, FB_PIN));
175
			twires_send(out);
176
		}
177
		/* Comined into 0x0c
178
		case (0x0d): {
179
			twires_send(rbi(FB_INPUT, FB_PIN));
180
		}
181
			break;
182
		*/
183
		default: {
184
			while (twires_available())
185
				twires_receive();
186
		}
187
			break;
188
	}
189
}
190
 
191
void writeSegment(uint8_t digit, uint8_t value) {
192
	uint8_t dp = 0;
193
	if (digit <= 4 && rbi(disPt[0], digit)) dp = 1;
194
	if (digit > 4 && rbi(disPt[1], digit-5)) dp = 1;
195
 
196
	cbi(BL_PORT, BL_PIN);			// Blank the 4511
197
	cbi(DP_PORT, DP_PIN);			// Drop the DP before changing digit
198
	hc595_write((value << 4) | (digit & 0x0f)); //Write the value and digit
199
	if (dp) sbi(DP_PORT, DP_PIN);	// Add DP if required
200
	sbi(BL_PORT, BL_PIN);			// Enable the 4511
201
}
202
 
203
void pcInterrupt() {
204
		wdt_reset();
205
 
206
		pcInt.mask = pcInt.current ^ pcInt.last;
207
		pcInt.last = pcInt.current;
208
 
209
        if (!pcInt.mask)
210
        	return;
211
 
212
        // Check which pin caused the interrupt. If they both
213
        //  equal 0 || 1, the pin that interrupted is the direction
214
        if (((rbi(pcInt.current, ROT_1A_PIN) == 1 &&
215
             rbi(pcInt.current, ROT_1B_PIN) == 1) ||
216
             (rbi(pcInt.current, ROT_1A_PIN) == 0 &&
217
              rbi(pcInt.current, ROT_1B_PIN) == 0))) {
218
 
219
        	if (rbi(pcInt.mask, ROT_1A_PIN) ) {
220
        		input.outer += 1;
221
              } else if (rbi(pcInt.mask, ROT_1B_PIN) ) {
222
            	input.outer -= 1;
223
            }
224
 
225
        }
226
        // Clear the mask so we know we've dealt with it
227
        // Shouldn't be required now that 'doInt' has been removed
228
        //pcInt.mask = 0;
229
 
230
}
231
 
232
ISR(PCINT1_vect) {
233
	pcInt.current = ROT_1_PIN;
234
}
235
 
236
ISR(TIM0_OVF_vect) {
237
    tmr0_ovf++;
238
 
239
	// Clk/1 TCCR0B = (1<< CS00);
240
	//20.0Mhz, 1ms = 78ovf
241
	//16.5Mhz, 1ms = 64ovf
242
	//16.0Mhz, 1ms = 62ovf
243
	//12.0Mhz, 1ms = 46ovf
244
	// 8.0Mhz, 1ms = 31ovf
245
    // 8.0Mhz, .5ms = 15ovf, 160r
246
 
247
	if (tmr0_ovf>=15) {
248
			systime++;
249
			tmr0_ovf = 0;
250
	}
251
 
252
}