Subversion Repositories group.electronics

Rev

Rev 97 | Rev 99 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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