Subversion Repositories group.electronics

Rev

Rev 103 | Rev 105 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
98 pfowler 1
/*
2
 * atcpad.c
3
 *
4
 * Created: 7/06/2013 10:15:34 PM
5
 *  Author: pfowler
6
 */ 
7
 
8
 
33 pfowler 9
#include <avr/io.h>
10
#include <avr/pgmspace.h>
11
#include <avr/interrupt.h>
12
 
13
#include <util/delay.h>
14
#include <avr/wdt.h>
100 pfowler 15
#include <stdlib.h>
16
#include <string.h>
17
 
98 pfowler 18
#include "usbdrv.h"
19
#include "atcpad.h"
20
#include "avrutil.h"
63 pfowler 21
#include "lcd.h"
40 pfowler 22
#include "wire.h"
33 pfowler 23
#include "hiddesc.h"
24
 
101 pfowler 25
#define BUTTONS	 		1
26
#define ROTARYS			1
39 pfowler 27
 
101 pfowler 28
#define LCD_UPDATE		11
29
#define	ROTARY_UPDATE	5
100 pfowler 30
 
102 pfowler 31
void pcInterrupt(uint8_t);
100 pfowler 32
uint8_t getKey(void);
33
void updateLcd();
101 pfowler 34
void checkRotarys();
35
void checkButtons(void);
100 pfowler 36
 
101 pfowler 37
 
97 pfowler 38
// * = 0x25, #=0x20
39
// F9 = 0x42, F12 = 0x45
40
uint8_t keyMap[] = { 	0x1E, 0x1F, 0x20,
41
						0x21, 0x22, 0x23,
42
						0x24, 0x25, 0x26,
43
						0x42, 0x27, 0x45 };
100 pfowler 44
 
98 pfowler 45
uint8_t lcdRectangle[] = {   
46
	0B00011111,
47
	0B00010001,
48
	0B00010001,
49
	0B00010001,
50
	0B00010001,
51
	0B00010001,
52
	0B00010001,
53
	0B00011111 };
97 pfowler 54
 
55
 
100 pfowler 56
uint8_t oldpotVal = 0;
57
uint8_t keySelect = 1;
58
 
101 pfowler 59
// Start these of at different times, so they
60
//  don't kick of it the same loop run
61
volatile uint8_t lcdTimer = 8;
62
volatile uint8_t rotaryTimer = 5;
63
 
98 pfowler 64
volatile struct {
102 pfowler 65
        uint8_t current;
66
        uint8_t last;
67
        uint8_t mask;
68
} pcInt[3];
69
 
70
volatile struct {
98 pfowler 71
	uint8_t detected;
72
	uint8_t timer;
99 pfowler 73
	uint8_t waitup;
98 pfowler 74
} buttons[BUTTONS];
97 pfowler 75
 
101 pfowler 76
volatile struct {
77
	union {
78
		uint8_t data;
79
		struct {
80
			uint8_t stat:4;
81
			uint8_t sent:4;
82
		};
83
	};
84
} rotary[ROTARYS];
85
 
104 pfowler 86
int main(void) {
98 pfowler 87
 
88
	setup();
89
 
90
    while(1)
91
    {
100 pfowler 92
		wdt_reset();
98 pfowler 93
        loop(); 
94
    }
39 pfowler 95
}
96
 
98 pfowler 97
void setup() {
97 pfowler 98
	/*
99
		DDR : 1 = Output, 0 = Input
100
		PORT: 1 = Pullup for Input, otherwise set output
101
		PIN : Read input pin
102
	*/
33 pfowler 103
 
97 pfowler 104
	/*
105
		PB0	- Output 		- Keypad 2
106
		PB1	- Output 		- Keypad 7
107
		PB2	- Output 		- Keypad 6
108
		PB3	- Output 		- Keypad 4
109
		PB4	- Input, Pullup		- Function select
110
		PB5	- Input, Pullup		- Function select
111
	*/
101 pfowler 112
	DDRB	= 0B00001111;
97 pfowler 113
	PORTB 	= 0B00111111;
33 pfowler 114
 
97 pfowler 115
	/*
116
		PD0	- Input, Pullup, PCINT16	- Rotary 1a
117
		PD1	- Input, Pullup, PCINT17	- Rotary 1b
33 pfowler 118
 
119
 
97 pfowler 120
		PD4	- Output		- Keypad select status led
121
		PD5	- Input, Pullup		- Keypad 3
122
		PD6	- Input, Pullup		- Keypad 1
123
		PD7	- Input, Pullup		- Keypad 5
124
	*/
101 pfowler 125
	DDRD	= 0B00010000;
126
	PORTD	= 0B11110011;
33 pfowler 127
 
97 pfowler 128
	PCMSK2 |= (( 1 << PCINT16 ) | ( 1 << PCINT17 )); //enable encoder pins interrupt sources
98 pfowler 129
	PCICR |= ( 1 << PCIE2 ); //enable pin change interrupts
130
 
131
	analogInit();
132
	sysclockInit();
133
 
134
	reportKeyboard.report_id = 1;
135
	reportJoystick.report_id = 2;	
136
 
97 pfowler 137
	usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
138
	_delay_ms(500);
139
	usbDeviceConnect();
33 pfowler 140
 
99 pfowler 141
	sei();
97 pfowler 142
	wdt_enable(WDTO_1S);
143
	usbInit();
63 pfowler 144
 
40 pfowler 145
	i2c_master();
63 pfowler 146
	lcd_init();
98 pfowler 147
	lcd_createChar(0x00, lcdRectangle);
40 pfowler 148
 
63 pfowler 149
	char strTime[] = {'T', 'i', 'm', 'e', ':', 0x00};
97 pfowler 150
	lcd_setCursor(0, 1);
98 pfowler 151
	lcd_print(strTime);
99 pfowler 152
 
153
	buttons[0].detected = 0;
154
	buttons[0].timer = 0;
155
	buttons[0].waitup = 0;
156
 
157
	cbi(PORTD, 4);
98 pfowler 158
 
159
}
33 pfowler 160
 
98 pfowler 161
void loop() {
99 pfowler 162
 
100 pfowler 163
   	usbPoll();
164
 
101 pfowler 165
	if (lcdTimer==0) {
100 pfowler 166
		updateLcd();
101 pfowler 167
		lcdTimer = LCD_UPDATE;
100 pfowler 168
	}
101 pfowler 169
 
103 pfowler 170
	reportJoystick.data1[0] = (-128 + analogRead(0));
171
	reportJoystick.data1[1] = (-128 + analogRead(1));
172
	reportJoystick.data2 = 0x0000;		// Clear all the buttons
173
 
174
	reportKeyboard.modifier = 0x00;
175
	reportKeyboard.keycode = 0x00;	
101 pfowler 176
 
177
 
103 pfowler 178
	checkButtons();
179
	checkRotarys();
102 pfowler 180
 
100 pfowler 181
 
98 pfowler 182
	if(usbInterruptIsReady()){
183
	    usbSendHidReport((uchar*)&reportKeyboard, sizeof(reportKeyboard));
184
	    usbSendHidReport((uchar*)&reportJoystick, sizeof(reportJoystick));
100 pfowler 185
    }	
33 pfowler 186
}
187
 
188
uint8_t getKey() {
189
	uint8_t col, row = 0;
190
	uint8_t key = 0;
191
	uint8_t n = 1;
192
 
193
	for (row=0; row<=3; row++) {
194
		cbi(PORTB, row);
195
		_delay_us(10);				// Wait for the port to change
196
 
197
		for (col=5; col<=7; col++) {
198
			if (rbi(PIND, col) == 0)
98 pfowler 199
			key = n;
33 pfowler 200
			n++;
98 pfowler 201
		}
33 pfowler 202
 
203
		sbi(PORTB, row);
204
	}
205
	return key;
206
}
207
 
101 pfowler 208
void checkRotarys() {
209
	uint8_t rot = 0;
103 pfowler 210
	//for (rot=0; rot<=(ROTARYS - 1); rot++) {
101 pfowler 211
		if (rotary[rot].stat == 0x01 && rotary[rot].sent == 0) {
212
			rotary[rot].sent = 1;
213
			switch (rot) {
214
				case(0):        reportJoystick.rot1a = 1; break;
103 pfowler 215
				//case(1):        reportJoystick.rot2a = 1; break;
101 pfowler 216
			}
217
		} else if (rotary[rot].stat == 0x02 && rotary[rot].sent == 0) {
218
			rotary[rot].sent = 1;
219
			switch (rot) {
220
				case(0):      reportJoystick.rot1b = 1; break;
103 pfowler 221
				//case(1):      reportJoystick.rot2b = 1; break;
101 pfowler 222
			}
223
		} else {
224
			rotary[rot].sent = 0;
225
		}
226
		rotary[rot].stat = 0;
227
 
103 pfowler 228
		// Config setting for a pause between sending
102 pfowler 229
		//if (rbi(PINB, PB4))
103 pfowler 230
			rotary[rot].sent = 0;
231
	//}
101 pfowler 232
}
233
 
234
void checkButtons() {
235
 
236
	uint8_t key = getKey();
237
	if (rbi(keySelect, 0)) {
238
		// Keypad is joystick
239
		if (key > 0)
240
			reportJoystick.data2 |= (1 << (--key));
241
		} else {
242
		// Keypad is keyboard
243
		if (key > 0) {
244
			//if (key==10 || key==12) // Left shift, for *, #
245
			//	reportKeyboard.modifier |= (1<<1);
246
			reportKeyboard.keycode = keyMap[--key];
247
		}
248
	}
249
 
250
	// Only one button for now
251
	if (rbi(PINB, 5) == 0 && buttons[0].detected == 0 && buttons[0].timer == 0) {
252
		buttons[0].detected = 1;
253
		buttons[0].timer = 5;
102 pfowler 254
		buttons[0].waitup = 0;
101 pfowler 255
	}
256
 
257
	if (rbi(PINB, 5) == 1 && buttons[0].waitup == 1) {
258
		buttons[0].detected = 0;
259
		buttons[0].timer = 0;
260
		buttons[0].waitup = 0;
261
	}
262
 
263
	if (buttons[0].detected == 1 && buttons[0].timer == 0 && buttons[0].waitup == 0 ) {
264
 
265
		xbi(keySelect, 0);
266
 
267
		if (keySelect == 0)
268
			sbi(PORTD, PD4);
269
		else
270
			cbi(PORTD, PD4);	
271
 
272
		buttons[0].waitup = 1;
273
	}
274
}
275
 
100 pfowler 276
void updateLcd() {
277
	usbPoll();
278
 
279
 
280
	char syschar[10];
281
	ultoa(systime, syschar, 10);
282
	lcd_overprint_right(syschar, 10, 5, 1);
283
 
284
	uint8_t potVal = map_8(analogRead(0), 0, 255, 0, 100);
285
	if (potVal != oldpotVal) {
286
		lcd_percent_graph(potVal, 0, 0);
287
		oldpotVal = potVal;
288
 
289
		char pot[3];
290
		utoa(potVal, pot, 10);
291
		lcd_overprint_right(pot, 3, 11, 0);
292
 
293
		// Set percentage
294
		lcd_setCursor(15, 0);
295
		lcd_char(0x25);
296
	}
297
}
298
 
97 pfowler 299
void millis_tick() {
98 pfowler 300
 
97 pfowler 301
}
302
 
102 pfowler 303
/*
304
 *
305
 * Process the Pin Change Interrupt.
306
 * pcint provides what bank caused the interrupt
307
 *
308
 */
309
void pcInterrupt(uint8_t pcint) {
103 pfowler 310
		pcint = 1;
311
        /*switch (pcint) {
102 pfowler 312
                case 0: pcInt[pcint].current = PINB; break;
313
                case 1: pcInt[pcint].current = PIND; break;
314
                case 2: pcInt[pcint].current = PINC; break;
103 pfowler 315
        }*/
316
        pcInt[pcint].current = PIND;
102 pfowler 317
        pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
318
        pcInt[pcint].last = pcInt[pcint].current;
319
 
320
        // Select what rotary we are dealing with
321
        //   based on the pc interrupt that fired.
322
        uint8_t rot = 0;
103 pfowler 323
        //if (pcint == 1) 
324
        //        rot = 1;
102 pfowler 325
 
326
        // If rot stat is not 0, we havn't sent
327
        //  our last results yet. Skip this click.
328
        if (rotary[rot].stat != 0) {
329
                pcInt[pcint].mask = 0;
330
                return;
331
        }
332
        // Check which pin caused the interrupt. If they both
333
        //  equal 0, the pin that interrupted is the direction
334
        if (rbi(pcInt[pcint].current, PCINT17) == 0 
335
                && rbi(pcInt[pcint].current, PCINT17) == 0 
336
                && rbi(pcInt[pcint].mask, PCINT16) ) {
337
                        rotary[rot].stat = 1;
338
        } else if (rbi(pcInt[pcint].current, PCINT16) == 0 
339
                && rbi(pcInt[pcint].current, PCINT17) == 0 
340
                && rbi(pcInt[pcint].mask, PCINT17) ) {
341
                        rotary[rot].stat = 2;
342
        }
343
 
344
        // Clear the mask so we know we've delth with it
345
        pcInt[pcint].mask = 0;
346
}
347
 
33 pfowler 348
ISR(TIMER0_OVF_vect) {
63 pfowler 349
	tmr0_ovf++;
99 pfowler 350
	if (tmr0_ovf >= sys_ovf_tick) {
63 pfowler 351
		systime++;
352
		tmr0_ovf = 0;
99 pfowler 353
		//millis_tick();	// Not working, taking too long to call?
354
 
101 pfowler 355
		if (buttons[0].timer)
99 pfowler 356
			buttons[0].timer--;
100 pfowler 357
 
101 pfowler 358
		if (lcdTimer)
359
			lcdTimer--;
360
 
103 pfowler 361
		//if (rotaryTimer)
362
		//	rotaryTimer--;
101 pfowler 363
 
63 pfowler 364
	}
33 pfowler 365
}
102 pfowler 366
 
367
ISR(PCINT0_vect) {
368
        pcInterrupt(0);
369
}
370
 
371
ISR(PCINT1_vect) {
372
        pcInterrupt(1);
373
}
374
 
375
ISR(PCINT2_vect) {
376
        pcInterrupt(2);
377
}
378
 
379
 
98 pfowler 380
void usbSendHidReport(uchar * data, uchar len) {
381
	while(1)
382
	{
383
		usbPoll();
384
		if (usbInterruptIsReady())
385
		{
386
			usbSetInterrupt(data, len);
387
			break;
388
		}
389
	}
33 pfowler 390
}
391
 
98 pfowler 392
usbMsgLen_t usbFunctionSetup(uchar data[8]) {
393
	usbRequest_t *rq = (void *)data;
33 pfowler 394
 
98 pfowler 395
	if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
396
		switch (rq->bRequest) {
397
			case USBRQ_HID_GET_REPORT:
100 pfowler 398
				if (rq->wValue.bytes[0] == 1)
399
					return sizeof(reportKeyboard);
400
				else if (rq->wValue.bytes[0] == 2)
401
					return sizeof(reportJoystick);
402
				else
403
					return 0;
98 pfowler 404
			case USBRQ_HID_GET_IDLE:
100 pfowler 405
				usbMsgPtr = &idleRate;
101 pfowler 406
				return 1;
98 pfowler 407
 
408
 
409
 
410
			default:
101 pfowler 411
				return 0;
98 pfowler 412
		}
413
	}
414
	return 0;
62 pfowler 415
}
416
 
98 pfowler 417
void hadUsbReset(void) {
99 pfowler 418
}