Subversion Repositories group.electronics

Rev

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