USB Code for the MZ
Here is some minimal USB code for the MZ processor written specifically for the hobbyist or developer
that does not want to, or just can't, invest in the time required to figure out how to use Harmony. My code uses Microsoft OS Descriptors to load a Winusb driver. The only requirement is a Windows or Linux based application that can interface with Winusb.
The Code
1 /*********************************************************************
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #pragma config DEBUG = OFF
20 #pragma config JTAGEN = OFF
21 #pragma config ICESEL = ICS_PGx2
22 #pragma config TRCEN = OFF
23 #pragma config BOOTISA = MIPS32
24 #pragma config FECCCON = OFF_UNLOCKED
25 #pragma config FSLEEP = OFF
26 #pragma config DBGPER = PG_ALL
27 #pragma config SMCLR = MCLR_NORM
28 #pragma config SOSCGAIN = GAIN_2X
29 #pragma config SOSCBOOST = ON
30 #pragma config POSCGAIN = GAIN_2X
31 #pragma config POSCBOOST = OFF
32 #pragma config EJTAGBEN = NORMAL
33 #pragma config CP = OFF
34
35
36 #pragma config FNOSC = SPLL
37 #pragma config DMTINTV = WIN_127_128
38 #pragma config FSOSCEN = OFF
39 #pragma config IESO = OFF
40 #pragma config POSCMOD = EC
41 #pragma config OSCIOFNC = ON
42 #pragma config FCKSM = CSECME
43 #pragma config WDTPS = PS1048576
44 #pragma config WDTSPGM = STOP
45 #pragma config FWDTEN = OFF
46 #pragma config WINDIS = NORMAL
47 #pragma config FWDTWINSZ = WINSZ_25
48 #pragma config DMTCNT = DMT31
49 #pragma config FDMTEN = OFF
50
51
52
53 #pragma config FPLLIDIV = DIV_3
54 #pragma config FPLLRNG = RANGE_5_10_MHZ
55 #pragma config FPLLICLK = PLL_POSC
56 #pragma config FPLLMULT = MUL_60
57 #pragma config FPLLODIV = DIV_2
58 #pragma config UPLLFSEL = FREQ_24MHZ
59
60
61 #pragma config USERID = 0xffff
62 #pragma config FMIIEN = ON
63 #pragma config FETHIO = ON
64 #pragma config PGL1WAY = OFF
65 #pragma config PMDL1WAY = OFF
66 #pragma config IOL1WAY = OFF
67 #pragma config FUSBIDIO = ON
68
69 #include <xc.h>
70 #include <p32xxxx.h>
71 #include <proc/p32mz0512efk100.h>
72 #include <sys/attribs.h>
73 #include <sys/kmem.h>
74 #include <stdint.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <stdbool.h>
79
80 void USB_init(void);
81 void SystemSetup(void);
82 void LED_Port(unsigned led_port_data);
83
84 int main(void)
85 {
86 while(CLKSTATbits.POSCRDY == 0);
87
88 SystemSetup();
89
90 LED_Port(0x0);
91
92 USB_init();
93
94 while(1)
95 {
96
97 PORTAbits.RA5 = !PORTAbits.RA5;
98 }
99 }
100
101
102 void __attribute__((vector(_TIMER_2_VECTOR), interrupt(ipl3srs), nomips16)) timer2_handler()
103 {
104
105 IFS0bits.T2IF = 0;
106 }
107
108 void SystemSetup(void)
109 {
110 unsigned int cp0;
111
112 ANSELA = 0;
113 ANSELD = 0;
114 ANSELF = 0;
115 ANSELG = 0;
116
117 TRISAbits.TRISA5 = 0;
118 TRISGbits.TRISG12 = 0;
119 TRISGbits.TRISG13 = 0;
120 TRISGbits.TRISG14 = 0;
121 TRISAbits.TRISA7 = 0;
122 TRISAbits.TRISA6 = 0;
123 TRISDbits.TRISD1 = 0;
124 TRISDbits.TRISD4 = 0;
125 TRISDbits.TRISD5 = 0;
126
127 TRISF = 1;
128
129
130 CNPUFbits.CNPUF3 = 1;
131
132 PRISS = 0x76543210;
133
134 __builtin_disable_interrupts();
135
136
137 SYSKEY = 0xAA996655;
138 SYSKEY = 0x556699AA;
139
140
141
142 PB1DIVbits.PBDIV = 1;
143
144
145 PB2DIVbits.ON = 1;
146 PB2DIVbits.PBDIV = 1;
147
148
149 PB3DIVbits.ON = 1;
150 PB3DIVbits.PBDIV = 1;
151
152
153 PB4DIVbits.ON = 1;
154 while (!PB4DIVbits.PBDIVRDY);
155 PB4DIVbits.PBDIV = 0;
156
157
158 PB5DIVbits.ON = 1;
159 PB5DIVbits.PBDIV = 1;
160
161
162 PB7DIVbits.ON = 1;
163 PB7DIVbits.PBDIV = 0;
164
165
166 PB8DIVbits.ON = 1;
167 PB8DIVbits.PBDIV = 1;
168
169
170 PRECONbits.PFMSECEN = 0;
171 PRECONbits.PREFEN = 0b11;
172 PRECONbits.PFMWS = 0b010;
173
174 CFGCONbits.USBSSEN = 1;
175
176
177 cp0 = _mfc0(16, 0);
178 cp0 &= ~0x07;
179 cp0 |= 0b011;
180 _mtc0(16, 0, cp0);
181
182 INTCONbits.MVEC = 1;
183
184
185 SYSKEY = 0x33333333;
186
187 __builtin_enable_interrupts();
188 }
189
190 void LED_Port(unsigned led_port_data)
191 {
192
193
194
195
196
197
198
199
200
201 uint32_t temp = led_port_data;
202
203
204 temp = led_port_data & 0x01;
205 PORTDbits.RD1 = temp;
206
207
208 temp = led_port_data & 0x02;
209 temp = temp >> 1;
210 PORTDbits.RD4 = temp;
211
212
213 temp = led_port_data & 0x04;
214 temp = temp >> 2;
215 PORTDbits.RD5 = temp;
216
217
218 temp = led_port_data & 0x08;
219 temp = temp >> 3;
220 PORTAbits.RA6 = temp;
221
222
223 temp = led_port_data & 0x10;
224 temp = temp >> 4;
225 PORTAbits.RA7 = temp;
226
227
228 temp = led_port_data & 0x20;
229 temp = temp >> 5;
230 PORTGbits.RG13 = temp;
231
232
233 temp = led_port_data & 0x40;
234 temp = temp >> 6;
235 PORTGbits.RG14 = temp;
236
237
238 temp = led_port_data & 0x80;
239 temp = temp >> 7;
240 PORTGbits.RG12 = temp;
241
242 }
243
244
245
1 /*********************************************************************
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 \SYSTEM\CurrentControlSet\Control\usbflags
28 \SYSTEM\CurrentControlSet\Enum\USB\VID_1209\MainBrain_MZ
29
30
31
32
33
34
35 #include <xc.h>
36 #include <p32xxxx.h>
37 #include <proc/p32mz0512efk100.h>
38 #include <sys/attribs.h>
39 #include <sys/kmem.h>
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdbool.h>
45
46 enum USB_State
47 {
48 POWERED,
49 DEFAULT,
50 ADDRESS,
51 CONFIGURED,
52 ATTACHED,
53 SUSPEND
54 };
55
56 enum USB_State DeviceState;
57
58 typedef struct
59 {
60 volatile unsigned char bmRequestType;
61 volatile unsigned char bRequest;
62 volatile unsigned short wValue;
63 volatile unsigned short wIndex;
64 volatile unsigned short wLength;
65 } USB_TRANSACTION;
66
67 USB_TRANSACTION USB_transaction;
68
69 typedef struct
70 {
71 volatile unsigned short rx_num_bytes;
72 volatile unsigned short tx_num_bytes;
73 volatile unsigned char tx_buffer[512];
74 volatile unsigned char rx_buffer[512];
75 } USB_ENDPOINT;
76
77 USB_ENDPOINT EP[3];
78
79 uint8_t device_descriptor[] =
80 {
81 0x12,
82 0x01,
83 0x00,0x02,
84 0x00,
85 0x00,
86 0x00,
87 0x40,
88 0x09,0x12,
89 0x01,0x00,
90 0x00,0x02,
91 0x01,
92 0x02,
93 0x02,
94 0x01
95 };
96
97 uint8_t config_descriptor[] =
98 {
99
100 0x09,
101 0x02,
102 0x20,0x00,
103 0x01,
104 0x01,
105 0x00,
106 0xc0,
107 0x32,
108
109
110 0x09,
111 0x04,
112 0x00,
113 0x00,
114 0x02,
115 0xff,
116 0xff,
117 0xff,
118 0x00,
119
120
121
122 0x07,
123 0x05,
124 0x01,
125 0x02,
126 0x40,0x00,
127 0x01,
128
129 0x07,
130 0x05,
131 0x82,
132 0x02,
133 0x40,0x00,
134 0x01
135 };
136
137 uint8_t device_qualifier[] =
138 {
139 0x0a,
140 0x06,
141 0x00, 0x02,
142 0xff,
143 0xff,
144 0xff,
145 0x40,
146 0x01,
147 0x00
148
149 };
150
151 uint8_t MSOSDescriptor[] =
152 {
153
154 0x0b,
155
156 0x03,
157
158 'M','S','F','T','1','0','0',
159
160 0xee,
161
162
163
164 0x00
165 };
166
167
168 uint8_t ExtCompatIDFeatureDescriptor[] =
169 {
170 0x28, 0x00, 0x00, 0x00,
171 0x00, 0x01,
172 0x04, 0x00,
173 0x01,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00,
176 0x01,
177 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
180 };
181
182 uint8_t ExtPropertyFeatureDescriptor[] =
183 {
184
185 0x8e, 0x00, 0x00, 0x00,
186 0x00, 0x01,
187 0x05, 0x00,
188 0x01, 0x00,
189
190 0x84, 0x00, 0x00, 0x00,
191 0x01,0x00, 0x00, 0x00,
192 0x28, 0x00,
193 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0,
194 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 0x00, 0x00,
195 0x4e, 0x00, 0x00, 0x00,
196
197
198 '{', 0, '2', 0, 'b', 0, '8', 0, 'a', 0, '8', 0, '2', 0, '1', 0, '6', 0, '-', 0, 'c', 0, '8', 0, '2', 0, 'a', 0,
199 '-', 0, '4', 0, 'a', 0, '9', 0, '1', 0, '-', 0, 'a', 0, '8', 0, 'b', 0, 'c', 0, '-', 0, 'a', 0, '1', 0, '2',
200 0, '1', 0, '2', 0, '9', 0, 'd', 0, '2', 0, 'd', 0, '7', 0, '0', 0, 'b', 0, '}', 0, 0x00, 0x00
201 };
202
203
204 uint8_t string0[] = {4, 0x03, 0x09, 0x04};
205
206
207 uint8_t string1[] = {26, 3, 'L', 0, 'a', 0, 'r', 0, 'r', 0, 'y', 0, ' ', 0, 'K', 0, 'n', 0, 'i', 0, 'g', 0, 'h', 0, 't', 0};
208
209
210 uint8_t string2[] = {26, 3, 'M', 0, 'a', 0, 'i', 0, 'n', 0, 'B', 0, 'r', 0, 'a', 0, 'i', 0, 'n', 0, ' ', 0, 'M', 0, 'Z', 0};
211
212
213 uint8_t string3[] = {10, 3, '0', 0, '0', 0, '0', 0, '1', 0};
214
215 void EP0_control_transaction(void);
216 void USB_queue_EP0(uint8_t *buffer, int size, int max_size);
217 void EP0_RX(int length);
218 void EP0_TX(void);
219 void Host_CMDs(void);
220 int EP1_RX(void);
221 int EP2_TX(volatile uint8_t *tx_buffer);
222 int EP0_Wait_TXRDY(void);
223 int EP2_Wait_TXRDY(void);
224
225 volatile uint8_t usbAddress;
226 volatile bool SetAddress = true;
227
228 void USB_init(void)
229 {
230
231 USBCSR0bits.SOFTCONN = 0;
232
233
234
235 USBCSR3bits.ENDPOINT = 1;
236
237
238 USBOTGbits.RXFIFOSZ = 0x06;
239 USBIENCSR1bits.RXMAXP = 64;
240 USBIENCSR3bits.RXFIFOSZ = 0x09;
241 USBFIFOAbits.RXFIFOAD = 0x0280;
242 USBIENCSR3bits.PROTOCOL = 0x02;
243 USBIENCSR3bits.TEP = 0x01;
244 USBIENCSR1bits.FLUSH = 1;
245
246
247
248 USBOTGbits.TXFIFOSZ = 0x06;
249 USBIENCSR0bits.TXMAXP = 64;
250 USBIENCSR3bits.TXFIFOSZ = 0x09;
251 USBFIFOAbits.TXFIFOAD = 0x0080;
252 USBIENCSR2bits.PROTOCOL = 0x02;
253 USBIENCSR2bits.TEP = 0x02;
254 USBIENCSR0bits.FLUSH = 1;
255
256
257 USBE1CSR0bits.MODE = 0;
258
259
260 USBE2CSR0bits.MODE = 1;
261
262
263 USBE0CSR0bits.TXMAXP = 64;
264
265
266 usbAddress = 0;
267 USBCSR0bits.FUNC = 0;
268
269
270 USBCSR2bits.RESETIE = 1;
271
272
273 IEC4bits.USBIE = 1;
274
275
276 USBCRCONbits.USBIE = 1;
277
278
279 IFS4bits.USBIF = 0;
280
281
282 IPC33bits.USBIP = 7;
283
284
285 IPC33bits.USBIS = 1;
286
287
288 USBE1CSR1bits.PIDERR = 1;
289
290
291 USBCSR0bits.HSEN = 1;
292
293 USBCSR0bits.SOFTCONN = 1;
294
295 DeviceState = ATTACHED;
296 }
297
298
299 void __attribute__((vector(_USB_VECTOR), interrupt(ipl7srs), nomips16)) USB_handler()
300 {
301
302 if(USBCSR2bits.RESETIF)
303 {
304
305 USBE1CSR0bits.MODE = 1;
306
307
308 USBE0CSR0bits.TXMAXP = 64;
309
310
311 USBE0CSR2bits.SPEED = 1;
312
313
314 USBE1CSR2bits.SPEED = 1;
315
316
317 USBE1CSR0bits.TXMAXP = 64;
318
319
320 USBE1CSR2bits.PROTOCOL = 2;
321
322 <1:0>
323
324
325
326
327
328 USBCSR1bits.EP1TXIE = 1;
329 USBCSR2bits.EP1RXIE = 1;
330
331 USBCSR2bits.RESETIF = 0;
332 }
333
334
335 if(USBCSR0bits.EP0IF == 1)
336 {
337
338 if (SetAddress == true)
339 {
340
341 USBCSR0bits.FUNC = usbAddress & 0x7F;
342 SetAddress = false;
343 }
344
345 if(USBE0CSR0bits.RXRDY)
346 {
347 EP0_RX(USBE0CSR2bits.RXCNT);
348
349 USB_transaction.bmRequestType = EP[0].rx_buffer[0];
350 USB_transaction.bRequest = EP[0].rx_buffer[1];
351 USB_transaction.wValue = (int)(EP[0].rx_buffer[3] << 8) | EP[0].rx_buffer[2];
352 USB_transaction.wIndex = (int)(EP[0].rx_buffer[5] << 8) | EP[0].rx_buffer[4];
353 USB_transaction.wLength = (int)(EP[0].rx_buffer[7] << 8) | EP[0].rx_buffer[6];
354
355 EP0_control_transaction();
356
357
358 if (USB_transaction.wLength == 0)
359 {
360 USBE0CSR0bits.DATAEND = 1;
361 }
362 }
363
364 if (USBE0CSR0bits.SETEND)
365 {
366 USBE0CSR0bits.SETENDC = 1;
367 }
368
369
370 USBCSR0bits.EP0IF = 0;
371 }
372
373
374 if(USBCSR1bits.EP1RXIF == 1)
375 {
376 EP1_RX();
377 Host_CMDs();
378 USBCSR1bits.EP1RXIF = 0;
379 }
380
381 IFS4bits.USBIF = 0;
382 }
383
384 void Host_CMDs()
385 {
386 switch (EP[1].rx_buffer[0])
387 {
388 case 0x00:
389 EP[2].tx_buffer[0] = 34;
390 EP2_TX(EP[2].tx_buffer);
391 break;
392 case 0x01:
393 EP[2].tx_buffer[0] = 87;
394 EP2_TX(EP[2].tx_buffer);
395 break;
396 }
397 }
398
399 int EP2_TX(volatile uint8_t* tx_buffer)
400 {
401 int cnt = 0;
402
403
404 EP[2].tx_num_bytes = 64;
405
406 for (cnt = 0; cnt < 64; cnt++)
407 {
408 EP[2].tx_buffer[cnt] = tx_buffer[cnt];
409 }
410
411
412 uint8_t *FIFO_buffer;
413
414
415 FIFO_buffer = (uint8_t *)&USBFIFO2;
416
417
418 if (EP2_Wait_TXRDY())
419 {
420 return 0;
421 }
422
423
424 cnt = 0;
425
426
427 while (cnt < EP[2].tx_num_bytes)
428 {
429 *FIFO_buffer = EP[2].tx_buffer[cnt];
430
431 cnt++;
432
433
434 if ((cnt > 0) && (cnt % 64 == 0))
435 {
436
437 USBE2CSR0bits.TXPKTRDY = 1;
438 if(EP2_Wait_TXRDY())
439 {
440 return 0;
441 }
442 }
443 }
444
445 USBE2CSR0bits.TXPKTRDY = 1;
446
447 }
448 int EP1_RX()
449 {
450 unsigned char *FIFO_buffer;
451 int cnt;
452 int rx_bytes;
453
454
455 rx_bytes = USBE1CSR2bits.RXCNT;
456
457
458 FIFO_buffer = (unsigned char *)&USBFIFO1;
459
460
461 for(cnt = 0; cnt < rx_bytes; cnt++)
462 {
463 EP[1].rx_buffer[cnt] = *(FIFO_buffer + (cnt & 3));
464 }
465
466
467 USBE1CSR1bits.RXPKTRDY = 0;
468
469 return rx_bytes;
470 }
471
472
473 void EP0_control_transaction()
474 {
475 uint16_t length;
476
477 if ((USB_transaction.bmRequestType == 0xC0) && (USB_transaction.wIndex == 0x04))
478 {
479 length = USB_transaction.wLength;
480 if (length > sizeof(ExtCompatIDFeatureDescriptor))
481 {
482 length = sizeof(ExtCompatIDFeatureDescriptor);
483 }
484
485 USB_queue_EP0(ExtCompatIDFeatureDescriptor, sizeof(ExtCompatIDFeatureDescriptor), length);
486
487 return;
488 }
489
490
491 if(USB_transaction.bmRequestType == 0xc1)
492 {
493
494 if(USB_transaction.bRequest == 0xee)
495 {
496
497 if(USB_transaction.wIndex == 0x05)
498 {
499
500
501 length = sizeof(ExtPropertyFeatureDescriptor);
502 if(USB_transaction.wLength < length)
503 {
504 length = USB_transaction.wLength;
505 }
506
507 USB_queue_EP0(ExtPropertyFeatureDescriptor, sizeof(ExtPropertyFeatureDescriptor), length);
508
509 USBE0CSR0bits.TXRDY = 1;
510
511 return;
512 }
513 }
514 }
515
516
517 switch (USB_transaction.bRequest)
518 {
519 case 0xC:
520 {
521 USBE0CSR0bits.STALL = 1;
522 break;
523
524 }
525 case 0x0:
526 {
527 if (USB_transaction.bmRequestType == 0x80)
528 USB_queue_EP0(device_descriptor, 0, 0);
529 if (USB_transaction.bmRequestType == 0x00)
530 USB_queue_EP0(device_descriptor, 0, 0);
531 break;
532 }
533
534
535 case 0x5:
536 {
537 USBE0CSR0bits.RXRDYC = 1;
538 usbAddress = EP[0].rx_buffer[2];
539
540 SetAddress = true;
541 break;
542 }
543
544
545 case 0x6:
546 {
547 switch (USB_transaction.wValue >> 8)
548 {
549
550 case 0x1:
551 {
552 USB_queue_EP0(device_descriptor, sizeof(device_descriptor), USB_transaction.wLength);
553 break;
554 }
555
556
557 case 0x2:
558 {
559 USB_queue_EP0(config_descriptor, sizeof(config_descriptor), USB_transaction.wLength);
560 break;
561 }
562
563
564 case 0x3:
565 {
566 switch (USB_transaction.wValue & 0xff)
567 {
568
569 case 0x0:
570 {
571 USB_queue_EP0(string0, sizeof(string0), USB_transaction.wLength);
572 break;
573 }
574
575 case 0x1:
576 {
577 USB_queue_EP0(string1, sizeof(string1), USB_transaction.wLength);
578 break;
579 }
580
581 case 0x2:
582 {
583 USB_queue_EP0(string2, sizeof(string2), USB_transaction.wLength);
584 break;
585 }
586
587 case 0x3:
588 {
589 USB_queue_EP0(string3, sizeof(string3), USB_transaction.wLength);
590 break;
591 }
592
593 case 0xee:
594 {
595 USB_queue_EP0(MSOSDescriptor, sizeof(MSOSDescriptor), USB_transaction.wLength);
596 break;
597 }
598 break;
599 }
600 break;
601 }
602
603
604 case 0x6:
605 {
606 USB_queue_EP0(device_qualifier, sizeof(device_qualifier), USB_transaction.wLength);
607 break;
608 }
609 }
610 break;
611 }
612
613
614 case 0x9:
615 {
616
617 break;
618 }
619
620 default:
621 {
622 USBE0CSR0bits.STALL = 1;
623 break;
624 }
625 }
626 }
627
628
629 void USB_queue_EP0(uint8_t *buffer, int size, int max_size)
630 {
631 int cnt;
632
633 if (max_size < size)
634 size = max_size;
635
636 EP[0].tx_num_bytes = size;
637
638 for (cnt = 0; cnt < size; cnt++)
639 {
640 EP[0].tx_buffer[cnt] = buffer[cnt];
641 }
642
643 EP0_TX();
644 }
645
646
647 void EP0_TX()
648 {
649 int cnt = 0;
650
651
652 uint8_t *FIFO_buffer;
653
654
655 FIFO_buffer = (uint8_t *)&USBFIFO0;
656
657
658 if (EP0_Wait_TXRDY())
659 {
660 return;
661 }
662
663
664 while (cnt < EP[0].tx_num_bytes)
665 {
666 *FIFO_buffer = EP[0].tx_buffer[cnt];
667
668 cnt++;
669
670
671 if ((cnt > 0) && (cnt % 64 == 0))
672 {
673
674 USBE0CSR0bits.TXRDY = 1;
675
676
677 while(!EP0_Wait_TXRDY());
678 }
679
680
681
682 if ((cnt > 0) && (cnt % 64 == 0))
683 {
684
685 USBE0CSR0bits.TXRDY = 1;
686 if(EP0_Wait_TXRDY())
687 {
688 return;
689 }
690 }
691 }
692
693 USBE0CSR0bits.TXRDY = 1;
694 }
695
696 void EP0_RX(int length)
697 {
698 int cnt;
699 uint8_t *FIFO_buffer;
700
701
702 EP[0].rx_num_bytes = USBE0CSR2bits.RXCNT;
703
704
705 FIFO_buffer = (uint8_t *)&USBFIFO0;
706
707 for(cnt = 0; cnt < length; cnt++)
708 {
709
710 EP[0].rx_buffer[cnt] = *(FIFO_buffer + (cnt & 3));
711 }
712
713 USBE0CSR0bits.RXRDYC = 1;
714 }
715
716 int EP0_Wait_TXRDY()
717 {
718 int timeout;
719
720 timeout = 0;
721
722 while (USBE0CSR0bits.TXRDY)
723 {
724 timeout++;
725
726 if (timeout > 5000)
727 {
728 return 1;
729 }
730 };
731
732 return 0;
733 }
734
735 int EP2_Wait_TXRDY()
736 {
737 int timeout;
738
739 timeout = 0;
740
741 while (USBE1CSR0bits.TXPKTRDY)
742 {
743 timeout++;
744
745 if (timeout > 5000)
746 {
747 return 1;
748 }
749 };
750
751 return 0;
752 }
753