Subversion Repositories group.electronics

Rev

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