Subversion Repositories group.electronics

Rev

Rev 131 | Details | Compare with Previous | 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
  /*
131 pfowler 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
130 pfowler 69
  */
70
  DDRA          = 0B00101111;
71
  PORTA         = 0B10001000;
72
  /*
131 pfowler 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)
130 pfowler 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
131 pfowler 95
    sei();			// Enable interrupts
130 pfowler 96
 
131 pfowler 97
 
98
    // Init and clear the displays
130 pfowler 99
    hc595_init();
100
    hc595_write(0x00);
101
 
102
    uint32_t refresh = systime;
103
    uint8_t disIdx = 0;
104
 
105
 
106
 
107
    for(;;){
108
    	 wdt_reset();
109
 
110
    	if (user_debug) {
111
    		disVal[9] = rbi(SB_INPUT, SB_PIN);
112
    		disVal[8] = rbi(FB_INPUT, FB_PIN);
113
    		disVal[0] = input.outer & 0x0f;
114
    		disVal[1] = input.outer >> 4;
115
    	}
116
 
117
		if (pcInt.current != pcInt.last) {
131 pfowler 118
			cei(); 		// Dont process interrupts for a bit
130 pfowler 119
			pcInterrupt();
131 pfowler 120
			sei();
130 pfowler 121
		}
122
 
123
		if (systime > refresh) {
124
			writeSegment(disIdx, disVal[disIdx]);
125
			refresh = systime + DISPLAY_REFRESH;
126
			disIdx++;
127
			if (disIdx > 10) disIdx = 0;
128
		}
129
 
130
		twires_stop_check();
131
    }
132
    return 0;
133
}
134
 
135
void receiveEvent(uint8_t bytes) {
136
	uint8_t cmd = twires_receive();
137
	bytes--;
138
	switch (cmd) {
139
		case (0x01): {
131 pfowler 140
			// Send 2 bytes with version details
130 pfowler 141
			twires_send(HW_VERSION);
142
			twires_send(SW_VERSION);
143
		}
144
			break;
145
		case (0x03): {
131 pfowler 146
			// Enable debugging mode
130 pfowler 147
			user_debug = twires_receive();
148
		}
149
			break;
150
		case (0x05): {
131 pfowler 151
			// Receive n numbers of digits to DISPLAY_REFRESH
152
			// High nibble = segment number
153
			// Low nibble = digit to display
130 pfowler 154
			while (bytes--) {
155
				uint8_t data = twires_receive();
156
				disVal[(data >> 4)] = (data & 0x0f);
157
			}
158
		}
159
			break;
160
		case (0x08): {
131 pfowler 161
			// Recieve 2 bytes, for the decimal points
162
			//  5 bits used in eac byte
130 pfowler 163
			disPt[0] = twires_receive();
164
			disPt[1] = twires_receive();
165
		}
166
			break;
167
		case (0x09): {
131 pfowler 168
			// Reset the rotary
130 pfowler 169
			input.outer = 0;
170
			input.inner = 0;
171
		}
172
			break;
173
		case (0x0a): {
131 pfowler 174
			// Send the value of the rotary count
130 pfowler 175
			twires_send(input.outer);
176
		}
177
			break;
178
		/* Not used in this version
179
		case (0x0b): {
180
			twires_send(input.inner);
181
		}
182
			break;
183
		*/
184
 
185
		case (0x0c): {
131 pfowler 186
			// Send that status of the buttons
130 pfowler 187
			uint8_t out = (!rbi(SB_INPUT, SB_PIN)) << 1;
188
			out |= (!rbi(FB_INPUT, FB_PIN));
189
			twires_send(out);
190
		}
191
		/* Comined into 0x0c
192
		case (0x0d): {
193
			twires_send(rbi(FB_INPUT, FB_PIN));
194
		}
195
			break;
196
		*/
197
		default: {
131 pfowler 198
			// Don't know what it is, empty buffer
130 pfowler 199
			while (twires_available())
200
				twires_receive();
201
		}
202
			break;
203
	}
204
}
205
 
206
void writeSegment(uint8_t digit, uint8_t value) {
207
	uint8_t dp = 0;
208
	if (digit <= 4 && rbi(disPt[0], digit)) dp = 1;
209
	if (digit > 4 && rbi(disPt[1], digit-5)) dp = 1;
210
 
211
	cbi(BL_PORT, BL_PIN);			// Blank the 4511
212
	cbi(DP_PORT, DP_PIN);			// Drop the DP before changing digit
213
	hc595_write((value << 4) | (digit & 0x0f)); //Write the value and digit
131 pfowler 214
	if (dp) sbi(DP_PORT, DP_PIN);		// Add DP if required
130 pfowler 215
	sbi(BL_PORT, BL_PIN);			// Enable the 4511
216
}
217
 
218
void pcInterrupt() {
131 pfowler 219
	pcInt.mask = pcInt.current ^ pcInt.last;
220
	pcInt.last = pcInt.current;
130 pfowler 221
 
222
        if (!pcInt.mask)
223
        	return;
224
 
225
        // Check which pin caused the interrupt. If they both
226
        //  equal 0 || 1, the pin that interrupted is the direction
227
        if (((rbi(pcInt.current, ROT_1A_PIN) == 1 &&
228
             rbi(pcInt.current, ROT_1B_PIN) == 1) ||
229
             (rbi(pcInt.current, ROT_1A_PIN) == 0 &&
230
              rbi(pcInt.current, ROT_1B_PIN) == 0))) {
231
 
232
        	if (rbi(pcInt.mask, ROT_1A_PIN) ) {
233
        		input.outer += 1;
234
              } else if (rbi(pcInt.mask, ROT_1B_PIN) ) {
235
            	input.outer -= 1;
236
            }
237
 
238
        }
239
        // Clear the mask so we know we've dealt with it
240
        // Shouldn't be required now that 'doInt' has been removed
241
        //pcInt.mask = 0;
242
 
243
}
244
 
245
ISR(PCINT1_vect) {
246
	pcInt.current = ROT_1_PIN;
247
}
248
 
249
ISR(TIM0_OVF_vect) {
250
    tmr0_ovf++;
251
 
252
	// Clk/1 TCCR0B = (1<< CS00);
253
	//20.0Mhz, 1ms = 78ovf
254
	//16.5Mhz, 1ms = 64ovf
255
	//16.0Mhz, 1ms = 62ovf
256
	//12.0Mhz, 1ms = 46ovf
257
	// 8.0Mhz, 1ms = 31ovf
131 pfowler 258
	// 8.0Mhz, .5ms = 15ovf, 160r
130 pfowler 259
 
260
	if (tmr0_ovf>=15) {
261
			systime++;
262
			tmr0_ovf = 0;
263
	}
264
 
265
}