Subversion Repositories group.electronics

Rev

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