Subversion Repositories group.electronics

Rev

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

Rev Author Line No. Line
33 pfowler 1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
#include <avr/interrupt.h>
4
 
5
#include <util/delay.h>
6
#include <avr/wdt.h>
7
#include <usbdrv.h>
8
 
9
#include <stdlib.h>
10
#include <string.h>
11
 
63 pfowler 12
#include "lcd.h"
60 pfowler 13
#include "util.h"
40 pfowler 14
#include "wire.h"
33 pfowler 15
#include "config.h"
16
#include "hiddesc.h"
17
 
97 pfowler 18
 
39 pfowler 19
#define ROTS_ATTACHED	1
33 pfowler 20
#define STAT		0
21
#define SENT		1
22
 
97 pfowler 23
#define BUTTONS	1
39 pfowler 24
#define ON		1
25
#define OFF		0
26
 
27
#define DETECTED	0
28
#define TIMER		1
29
#define	DEBOUNCED	2
30
 
34 pfowler 31
/*
32
 * Keyboard modifier codes
33
 */
34
#define MOD_CONTROL_LEFT    (1<<0)
35
#define MOD_SHIFT_LEFT      (1<<1)
36
#define MOD_ALT_LEFT        (1<<2)
37
#define MOD_GUI_LEFT        (1<<3)
38
#define MOD_CONTROL_RIGHT   (1<<4)
39
#define MOD_SHIFT_RIGHT     (1<<5)
40
#define MOD_ALT_RIGHT       (1<<6)
41
#define MOD_GUI_RIGHT       (1<<7)
33 pfowler 42
 
97 pfowler 43
// CLOCK STUFF
44
// Clk/1 TCCR0B = (1<< CS00);
45
//20.0Mhz, 1ms = 78ovf
46
//16.5Mhz, 1ms = 64ovf
47
//12.0Mhz, 1ms = 46ovf
48
const uint8_t sys_ovf_tick = 78;
63 pfowler 49
volatile uint8_t tmr0_ovf = 0;
50
volatile uint32_t systime = 0;
97 pfowler 51
void millis_tick(void);
63 pfowler 52
 
53
 
62 pfowler 54
volatile struct {
55
	uint8_t current;
56
	uint8_t last;
57
	uint8_t mask;
58
} pcInt[3];
33 pfowler 59
 
97 pfowler 60
volatile struct {
61
	uint8_t detected;
62
	uint8_t timer;
63
	uint8_t debounced;
64
} buttons[BUTTONS];
39 pfowler 65
 
62 pfowler 66
volatile struct {
67
	union {
68
		uint8_t data;
69
		struct {
70
			uint8_t stat:4;
71
			uint8_t sent:4;
72
		};
73
	};
97 pfowler 74
} rotData[ROTS_ATTACHED];
62 pfowler 75
 
33 pfowler 76
struct {
77
	uint8_t report_id;
78
	uint8_t modifier;
39 pfowler 79
	uint8_t keycode;
33 pfowler 80
} reportKeyboard;
81
 
97 pfowler 82
struct {
33 pfowler 83
	uint8_t report_id;
97 pfowler 84
	union {
85
		uint8_t data1[2];
86
		struct {
87
		uint8_t rx:8;
88
		uint8_t ry:8;
89
		};
90
	};
33 pfowler 91
 
97 pfowler 92
	union {
93
		uint16_t data2;
94
		struct {
95
			uint16_t buttons:12;
96
			uint16_t rot2a:1;
97
			uint16_t rot2b:1;
98
			uint16_t rot1a:1;
99
			uint16_t rot1b:1;
100
		};
101
	};
33 pfowler 102
} reportJoystick;
103
 
97 pfowler 104
// * = 0x25, #=0x20
105
// F9 = 0x42, F12 = 0x45
106
 
107
uint8_t keyMap[] = { 	0x1E, 0x1F, 0x20,
108
						0x21, 0x22, 0x23,
109
						0x24, 0x25, 0x26,
110
						0x42, 0x27, 0x45 };
111
 
112
uint8_t keySelect = 1;
113
 
114
void doInt(uint8_t pcint);
115
uint8_t getKey(void);
116
 
117
uint8_t oldpotVal = 0;
118
volatile uint8_t lcdupdate = 1;
119
static uchar    idleRate;
120
 
121
 
122
uint8_t emblock[] = {   0B00011111,
123
                        0B00010001,
124
                        0B00010001,
125
                        0B00010001,
126
                        0B00010001,
127
                        0B00010001,
128
                        0B00010001,
129
                        0B00011111 };
130
 
39 pfowler 131
void usbSendHidReport(uchar * data, uchar len) {
132
	while(1)
133
	{
134
		usbPoll();
135
		if (usbInterruptIsReady())
136
		{
137
			usbSetInterrupt(data, len);
138
			break;
139
		}
140
	}
141
}
142
 
33 pfowler 143
usbMsgLen_t usbFunctionSetup(uchar data[8]) {
144
	usbRequest_t *rq = (void *)data;
145
 
146
	if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
147
		switch (rq->bRequest) {
148
			case USBRQ_HID_GET_REPORT:
149
				if (rq->wValue.bytes[0] == 1)
150
					return sizeof(reportKeyboard);
151
				else if (rq->wValue.bytes[0] == 2)
152
					return sizeof(reportJoystick);
153
				else
154
					return 0;
155
			case USBRQ_HID_GET_IDLE:
97 pfowler 156
				usbMsgPtr = &idleRate;
33 pfowler 157
				return 1;
97 pfowler 158
 
159
 
160
 
33 pfowler 161
			default:
162
				return 0;
163
		}
164
	}
165
	return 0;
166
}
167
 
168
void hadUsbReset(void) {
169
}
170
 
171
int main(void) {
62 pfowler 172
	analogInit();
97 pfowler 173
	sysclockInit();
33 pfowler 174
 
97 pfowler 175
	/*
176
		DDR : 1 = Output, 0 = Input
177
		PORT: 1 = Pullup for Input, otherwise set output
178
		PIN : Read input pin
179
	*/
33 pfowler 180
 
97 pfowler 181
	/*
182
		PB0	- Output 		- Keypad 2
183
		PB1	- Output 		- Keypad 7
184
		PB2	- Output 		- Keypad 6
185
		PB3	- Output 		- Keypad 4
186
		PB4	- Input, Pullup		- Function select
187
		PB5	- Input, Pullup		- Function select
188
	*/
189
	DDRB		= 0B00001111;
190
	PORTB 	= 0B00111111;
33 pfowler 191
 
97 pfowler 192
	/*
193
		PD0	- Input, Pullup, PCINT16	- Rotary 1a
194
		PD1	- Input, Pullup, PCINT17	- Rotary 1b
33 pfowler 195
 
196
 
97 pfowler 197
		PD4	- Output		- Keypad select status led
198
		PD5	- Input, Pullup		- Keypad 3
199
		PD6	- Input, Pullup		- Keypad 1
200
		PD7	- Input, Pullup		- Keypad 5
201
	*/
202
	DDRD		= 0B00010000;
203
	PORTD		= 0B11110011;
33 pfowler 204
 
97 pfowler 205
	PCMSK2 |= (( 1 << PCINT16 ) | ( 1 << PCINT17 )); //enable encoder pins interrupt sources
206
	PCICR |= ( 1 << PCIE2 ); //enable pin change interupts
207
 
33 pfowler 208
 
97 pfowler 209
	usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
210
	_delay_ms(500);
211
	usbDeviceConnect();
33 pfowler 212
 
97 pfowler 213
	wdt_enable(WDTO_1S);
214
	usbInit();
215
	usbPoll();
63 pfowler 216
 
64 pfowler 217
	sei();
40 pfowler 218
	i2c_master();
63 pfowler 219
	lcd_init();
220
	lcd_createChar(0x00, emblock);
97 pfowler 221
	usbPoll();
40 pfowler 222
 
63 pfowler 223
	char strTime[] = {'T', 'i', 'm', 'e', ':', 0x00};
97 pfowler 224
	lcd_setCursor(0, 1);
225
	lcd_print(strTime);	
33 pfowler 226
 
227
	reportKeyboard.report_id = 1;
228
	reportJoystick.report_id = 2;
229
 
64 pfowler 230
	cbi(PORTD, PD4);
33 pfowler 231
  for(;;) {
232
    wdt_reset();
233
    usbPoll();
234
 
39 pfowler 235
	/*
236
	 * This is some really bad deboucing code
237
	 */
238
 
239
	// Detect the button press, wait 100 timer cycles (1.7ms / cycle)
97 pfowler 240
	if (rbi(PINB, PB5) == 0 && buttons[0].detected==0) {
241
		buttons[0].detected = 1;
242
		buttons[0].timer = 100;
39 pfowler 243
	}
244
 
245
	// After timer is zero, check switch again.
246
	//  If switch still pressed, its debounced
247
	//  Otherwise, reset the debounce
97 pfowler 248
	if (buttons[0].detected == 1 && buttons[0].timer == 0 && buttons[0].debounced==0) {
39 pfowler 249
		if (rbi(PINB, PB5) == 0)	
97 pfowler 250
			buttons[0].debounced = 1;
39 pfowler 251
		else {
97 pfowler 252
			buttons[0].detected = 0;
253
			buttons[0].timer = 0;
39 pfowler 254
		}
255
	}
256
 
257
	// If the switch has come up, do another debounce
97 pfowler 258
	if (rbi(PINB, PB5) && buttons[0].detected==2) {
259
		buttons[0].timer = 100;
260
		buttons[0].detected = 3;
39 pfowler 261
	}
262
 
263
	// After the up switch timer is zero, do the debounce check
264
	// Otherwise, assume switch is still down
97 pfowler 265
	if (buttons[0].detected == 3 && buttons[0].timer == 0) {
39 pfowler 266
		if (rbi(PINB, PB5))
97 pfowler 267
			buttons[0].detected = 0;
39 pfowler 268
	}
269
 
270
	// Process the switch
97 pfowler 271
	if (buttons[0].debounced == 1) {
39 pfowler 272
		xbi(keySelect, 0);
273
 
274
		if (keySelect == 0)
275
			sbi(PORTD, PD4);
276
		else
277
			cbi(PORTD, PD4);
278
 
97 pfowler 279
		buttons[0].detected = 2;
280
		buttons[0].debounced = 0;
39 pfowler 281
	}
282
 
63 pfowler 283
	usbPoll();	
39 pfowler 284
 
33 pfowler 285
    if(usbInterruptIsReady()){
286
	reportJoystick.data1[0] = (-128 + analogRead(0));
287
	reportJoystick.data1[1] = (-128 + analogRead(1));
36 pfowler 288
	reportJoystick.data2 = 0x0000;				// Clear all the buttons
33 pfowler 289
 
36 pfowler 290
	reportKeyboard.modifier = 0x00;
39 pfowler 291
	reportKeyboard.keycode = 0x00;
33 pfowler 292
 
293
	uint8_t key = getKey();
39 pfowler 294
	if (rbi(keySelect, 0)) {
33 pfowler 295
		// Keypad is joystick
296
		if (key > 0)
39 pfowler 297
			reportJoystick.data2 |= (1 << (--key));
33 pfowler 298
	} else {
299
		// Keypad is keyboard
300
		if (key > 0) {
94 pfowler 301
			//if (key==10 || key==12) // Left shift, for *, #
302
			//	reportKeyboard.modifier |= (1<<1);
39 pfowler 303
			reportKeyboard.keycode = keyMap[--key];
33 pfowler 304
		}
305
	}
306
 
307
	// Now work out what rotary to send, if any
308
	// Also record if we sent a positive response, 
309
	//  so we can send a '0' next time (if selected on PD4)
62 pfowler 310
	// rotData = [rot#][(stat|sent)]
33 pfowler 311
	uint8_t rot = 0;
312
	for (rot=0; rot<=(ROTS_ATTACHED - 1); rot++) {
62 pfowler 313
	        if (rotData[rot].stat == 0x01 && rotData[rot].sent == 0) {
314
                	rotData[rot].sent = 1;
33 pfowler 315
			switch (rot) {
316
				case(0):	reportJoystick.rot1a = 1; break;
317
				case(1):	reportJoystick.rot2a = 1; break;
318
			}
62 pfowler 319
	        } else if (rotData[rot].stat == 0x02 && rotData[rot].sent == 0) {
320
                	rotData[rot].sent = 1;
33 pfowler 321
                        switch (rot) {
322
                                case(0):      reportJoystick.rot1b = 1; break;
323
                                case(1):      reportJoystick.rot2b = 1; break;
324
                        }
325
	        } else {
62 pfowler 326
        	        rotData[rot].sent = 0;
33 pfowler 327
	        }
62 pfowler 328
		rotData[rot].stat = 0;
33 pfowler 329
 
330
	        if (rbi(PINB, PB4))
62 pfowler 331
        	        rotData[rot].sent = 0;
33 pfowler 332
	}
333
 
334
      /* called after every poll of the interrupt endpoint */
39 pfowler 335
      //usbSetInterrupt(&reportKeyboard, sizeof(reportKeyboard));
336
      //usbSetInterrupt(&reportJoystick, sizeof(reportJoystick));
337
 
97 pfowler 338
	usbSendHidReport((uchar*)&reportKeyboard, sizeof(reportKeyboard));
339
	usbSendHidReport((uchar*)&reportJoystick, sizeof(reportJoystick));
39 pfowler 340
 
33 pfowler 341
    }
63 pfowler 342
 
343
	if (lcdupdate) {
64 pfowler 344
		usbPoll();
63 pfowler 345
		lcdupdate = 0;
346
 
97 pfowler 347
		char syschar[10];
348
		ultoa(systime, syschar, 10);
349
		lcd_overprint_right(syschar, 10, 5, 1);
63 pfowler 350
 
97 pfowler 351
		uint8_t potVal = map_8(analogRead(0), 0, 255, 0, 100);
352
		if (potVal != oldpotVal) {
353
				lcd_percent_graph(potVal, 0, 0);
354
				oldpotVal = potVal;
63 pfowler 355
 
97 pfowler 356
				char pot[3];
357
				utoa(potVal, pot, 10);
358
				lcd_overprint_right(pot, 3, 11, 0);
63 pfowler 359
 
97 pfowler 360
				// Set percentage
361
				lcd_setCursor(15, 0);
362
				lcd_char(0x25);
363
		}
63 pfowler 364
 
365
	}
366
 
33 pfowler 367
  }
368
}
369
 
370
uint8_t getKey() {
371
	uint8_t col, row = 0;
372
	uint8_t key = 0;
373
	uint8_t n = 1;
374
 
375
	for (row=0; row<=3; row++) {
376
		cbi(PORTB, row);
377
		_delay_us(10);				// Wait for the port to change
378
 
379
		for (col=5; col<=7; col++) {
380
			if (rbi(PIND, col) == 0)
381
				key = n;
382
			n++;
383
		}	
384
 
385
		sbi(PORTB, row);
386
	}
387
	return key;
388
}
389
 
390
/*
391
 *
392
 * Process the Pin Change Interrupt.
393
 * pcint provides what bank caused the interrupt
394
 *
395
 */
62 pfowler 396
void pcInterrupt(uint8_t pcint) {
33 pfowler 397
 
62 pfowler 398
	switch (pcint) {
399
		case 0:	pcInt[pcint].current = PINB; break;
400
		case 1:	pcInt[pcint].current = PIND; break;
401
		case 2:	pcInt[pcint].current = PINC; break;
402
	}
97 pfowler 403
	//pcInt[pcint].current = PIND;
62 pfowler 404
	pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
405
	pcInt[pcint].last = pcInt[pcint].current;
406
 
33 pfowler 407
	// Select what rotary we are dealing with
408
	//   based on the pc interrupt that fired.
409
	uint8_t rot = 0;
410
	if (pcint == 1) 
411
		rot = 1;
412
 
413
	// If rot stat is not 0, we havn't sent
414
	//  our last results yet. Skip this click.
62 pfowler 415
	if (rotData[rot].stat != 0) {
416
		pcInt[pcint].mask = 0;
33 pfowler 417
		return;
418
	}
419
	// Check which pin caused the interrupt. If they both
420
	//  equal 0, the pin that interrupted is the direction
62 pfowler 421
  	if (rbi(pcInt[pcint].current, PCINT17) == 0 
422
		&& rbi(pcInt[pcint].current, PCINT17) == 0 
423
		&& rbi(pcInt[pcint].mask, PCINT16) ) {
424
			rotData[rot].stat = 1;
425
  	} else if (rbi(pcInt[pcint].current, PCINT16) == 0 
426
		&& rbi(pcInt[pcint].current, PCINT17) == 0 
427
		&& rbi(pcInt[pcint].mask, PCINT17) ) {
428
			rotData[rot].stat = 2;
33 pfowler 429
  	}
430
 
431
	// Clear the mask so we know we've delth with it
62 pfowler 432
	pcInt[pcint].mask = 0;
33 pfowler 433
}
434
 
97 pfowler 435
void millis_tick() {
436
	if (buttons[0].detected && buttons[0].timer)
437
		buttons[0].timer--;
438
 
439
	lcdupdate = 1;
440
}
441
 
33 pfowler 442
ISR(TIMER0_OVF_vect) {
63 pfowler 443
	tmr0_ovf++;
97 pfowler 444
	if (tmr0_ovf>=sys_ovf_tick) {
63 pfowler 445
		systime++;
446
		tmr0_ovf = 0;
97 pfowler 447
		millis_tick();
63 pfowler 448
	}
33 pfowler 449
}
97 pfowler 450
/*
63 pfowler 451
ISR(TIMER2_OVF_vect) {
97 pfowler 452
	tmr2_ovf++;
453
	if (tmr2_ovf>=78) {}
63 pfowler 454
}
97 pfowler 455
*/
63 pfowler 456
 
62 pfowler 457
ISR(PCINT0_vect) {
458
	pcInterrupt(0);
33 pfowler 459
}
460
 
62 pfowler 461
ISR(PCINT1_vect) {
462
	pcInterrupt(1);
33 pfowler 463
}
464
 
62 pfowler 465
ISR(PCINT2_vect) {
466
	pcInterrupt(2);
467
}
468