Subversion Repositories group.electronics

Rev

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