Subversion Repositories group.electronics

Rev

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