Subversion Repositories group.electronics

Rev

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