Rev Author Line No. Line
1661 kaklik 1 /********************************************************************
2 FileName: main.c
3 Dependencies: See INCLUDES section
4 Processor: PIC18 or PIC24 USB Microcontrollers
5 Hardware: The code is natively intended to be used on the following
6 hardware platforms: PICDEM™ FS USB Demo Board,
7 PIC18F87J50 FS USB Plug-In Module, or
8 Explorer 16 + PIC24 USB PIM. The firmware may be
9 modified for use on other USB platforms by editing the
10 HardwareProfile.h file.
11 Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
12 Company: Microchip Technology, Inc.
13  
14 Software License Agreement:
15  
16 The software supplied herewith by Microchip Technology Incorporated
17 (the “Company”) for its PIC® Microcontroller is intended and
18 supplied to you, the Company’s customer, for use solely and
19 exclusively on Microchip PIC Microcontroller products. The
20 software is owned by the Company and/or its supplier, and is
21 protected under applicable copyright laws. All rights are reserved.
22 Any use in violation of the foregoing restrictions may subject the
23 user to criminal sanctions under applicable laws, as well as to
24 civil liability for the breach of the terms and conditions of this
25 license.
26  
27 THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
28 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
29 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
30 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
31 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
32 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33  
34 ********************************************************************
35 File Description:
36  
37 Change History:
38 Rev Date Description
39 1.0 11/19/2004 Initial release
40 2.1 02/26/2007 Updated for simplicity and to use common
41 coding style
42 ********************************************************************/
43  
44 /** INCLUDES *******************************************************/
45 #include "USB/usb.h"
46 #include "USB/usb_function_generic.h"
47 #include "user.h" // Modifiable
48 #include "HardwareProfile.h"
49  
50 /** CONFIGURATION **************************************************/
51 #if defined(PICDEM_FS_USB) // Configuration bits for PICDEM FS USB Demo Board (based on PIC18F4550)
52 #pragma config PLLDIV = 5 // (20 MHz crystal on PICDEM FS USB board)
53 #pragma config CPUDIV = OSC1_PLL2
54 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
55 #pragma config FOSC = HSPLL_HS
56 #pragma config FCMEN = OFF
57 #pragma config IESO = OFF
58 #pragma config PWRT = OFF
59 #pragma config BOR = ON
60 #pragma config BORV = 3
61 #pragma config VREGEN = ON //USB Voltage Regulator
62 #pragma config WDT = OFF
63 #pragma config WDTPS = 32768
64 #pragma config MCLRE = ON
65 #pragma config LPT1OSC = OFF
66 #pragma config PBADEN = OFF
67 // #pragma config CCP2MX = ON
68 #pragma config STVREN = ON
69 #pragma config LVP = OFF
70 // #pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming
71 #pragma config XINST = OFF // Extended Instruction Set
72 #pragma config CP0 = OFF
73 #pragma config CP1 = OFF
74 // #pragma config CP2 = OFF
75 // #pragma config CP3 = OFF
76 #pragma config CPB = OFF
77 // #pragma config CPD = OFF
78 #pragma config WRT0 = OFF
79 #pragma config WRT1 = OFF
80 // #pragma config WRT2 = OFF
81 // #pragma config WRT3 = OFF
82 #pragma config WRTB = OFF // Boot Block Write Protection
83 #pragma config WRTC = OFF
84 // #pragma config WRTD = OFF
85 #pragma config EBTR0 = OFF
86 #pragma config EBTR1 = OFF
87 // #pragma config EBTR2 = OFF
88 // #pragma config EBTR3 = OFF
89 #pragma config EBTRB = OFF
90  
91 #elif defined(PIC18F87J50_PIM) // Configuration bits for PIC18F87J50 FS USB Plug-In Module board
92 #pragma config XINST = OFF // Extended instruction set
93 #pragma config STVREN = ON // Stack overflow reset
94 #pragma config PLLDIV = 3 // (12 MHz crystal used on this board)
95 #pragma config WDTEN = OFF // Watch Dog Timer (WDT)
96 #pragma config CP0 = OFF // Code protect
97 #pragma config CPUDIV = OSC1 // OSC1 = divide by 1 mode
98 #pragma config IESO = OFF // Internal External (clock) Switchover
99 #pragma config FCMEN = OFF // Fail Safe Clock Monitor
100 #pragma config FOSC = HSPLL // Firmware must also set OSCTUNE<PLLEN> to start PLL!
101 #pragma config WDTPS = 32768
102 // #pragma config WAIT = OFF // Commented choices are
103 // #pragma config BW = 16 // only available on the
104 // #pragma config MODE = MM // 80 pin devices in the
105 // #pragma config EASHFT = OFF // family.
106 #pragma config MSSPMSK = MSK5
107 // #pragma config PMPMX = DEFAULT
108 // #pragma config ECCPMX = DEFAULT
109 #pragma config CCP2MX = DEFAULT
110  
111 #elif defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
112 #pragma config WDTEN = OFF //WDT disabled (enabled by SWDTEN bit)
113 #pragma config PLLDIV = 3 //Divide by 3 (12 MHz oscillator input)
114 #pragma config STVREN = ON //stack overflow/underflow reset enabled
115 #pragma config XINST = OFF //Extended instruction set disabled
116 #pragma config CPUDIV = OSC1 //No CPU system clock divide
117 #pragma config CP0 = OFF //Program memory is not code-protected
118 #pragma config OSC = HSPLL //HS oscillator, PLL enabled, HSPLL used by USB
119 #pragma config T1DIG = ON //Sec Osc clock source may be selected
120 #pragma config LPT1OSC = OFF //high power Timer1 mode
121 #pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
122 #pragma config IESO = OFF //Two-Speed Start-up disabled
123 #pragma config WDTPS = 32768 //1:32768
124 #pragma config DSWDTOSC = INTOSCREF //DSWDT uses INTOSC/INTRC as clock
125 #pragma config RTCOSC = T1OSCREF //RTCC uses T1OSC/T1CKI as clock
126 #pragma config DSBOREN = OFF //Zero-Power BOR disabled in Deep Sleep
127 #pragma config DSWDTEN = OFF //Disabled
128 #pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
129 #pragma config IOL1WAY = OFF //IOLOCK bit can be set and cleared
130 #pragma config MSSP7B_EN = MSK7 //7 Bit address masking
131 #pragma config WPFP = PAGE_1 //Write Protect Program Flash Page 0
132 #pragma config WPEND = PAGE_0 //Start protection at page 0
133 #pragma config WPCFG = OFF //Write/Erase last page protect Disabled
134 #pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
135  
136 #elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)
137 // PIC18F14K50
138 #pragma config CPUDIV = NOCLKDIV
139 #pragma config USBDIV = OFF
140 #pragma config FOSC = HS
141 #pragma config PLLEN = ON
142 #pragma config FCMEN = OFF
143 #pragma config IESO = OFF
144 #pragma config PWRTEN = OFF
145 #pragma config BOREN = OFF
146 #pragma config BORV = 30
147 #pragma config WDTEN = OFF
148 #pragma config WDTPS = 32768
149 #pragma config MCLRE = OFF
150 #pragma config HFOFST = OFF
151 #pragma config STVREN = ON
152 #pragma config LVP = OFF
153 #pragma config XINST = OFF
154 #pragma config BBSIZ = OFF
155 #pragma config CP0 = OFF
156 #pragma config CP1 = OFF
157 #pragma config CPB = OFF
158 #pragma config WRT0 = OFF
159 #pragma config WRT1 = OFF
160 #pragma config WRTB = OFF
161 #pragma config WRTC = OFF
162 #pragma config EBTR0 = OFF
163 #pragma config EBTR1 = OFF
164 #pragma config EBTRB = OFF
165  
166 #elif defined(EXPLORER_16)
167 #ifdef __PIC24FJ256GB110__ //Defined by MPLAB when using 24FJ256GB110 device
168 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
169 _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV2 & IOL1WAY_ON)
170 #elif defined(__PIC24FJ64GB004__)
171 _CONFIG1(WDTPS_PS1 & FWPSA_PR32 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
172 _CONFIG2(POSCMOD_HS & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_ON)
173 _CONFIG3(WPFP_WPFP0 & SOSCSEL_SOSC & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
174 _CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_LPRC & RTCOSC_SOSC & DSBOREN_OFF & DSWDTEN_OFF)
175 #elif defined(__32MX460F512L__) || defined(__32MX795F512L__)
176 #pragma config UPLLEN = ON // USB PLL Enabled
177 #pragma config FPLLMUL = MUL_15 // PLL Multiplier
178 #pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
179 #pragma config FPLLIDIV = DIV_2 // PLL Input Divider
180 #pragma config FPLLODIV = DIV_1 // PLL Output Divider
181 #pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
182 #pragma config FWDTEN = OFF // Watchdog Timer
183 #pragma config WDTPS = PS1 // Watchdog Timer Postscale
184 #pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
185 #pragma config OSCIOFNC = OFF // CLKO Enable
186 #pragma config POSCMOD = HS // Primary Oscillator
187 #pragma config IESO = OFF // Internal/External Switch-over
188 #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
189 #pragma config FNOSC = PRIPLL // Oscillator Selection
190 #pragma config CP = OFF // Code Protect
191 #pragma config BWP = OFF // Boot Flash Write Protect
192 #pragma config PWP = OFF // Program Flash Write Protect
193 #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
194 #pragma config DEBUG = ON // Background Debugger Enable
195 #else
196 #error No hardware board defined, see "HardwareProfile.h" and __FILE__
197 #endif
198 #elif defined(PIC24F_STARTER_KIT)
199 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
200 _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV3 & IOL1WAY_ON)
201 #elif defined(PIC24FJ256DA210_DEV_BOARD)
202 //_CONFIG1(FWDTEN_OFF & ICS_PGx2 & COE_OFF & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
203 //_CONFIG2(POSCMOD_HS & IOL1WAY_ON & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_OFF)
204 #elif defined(PIC32_USB_STARTER_KIT)
205 #pragma config UPLLEN = ON // USB PLL Enabled
206 #pragma config FPLLMUL = MUL_15 // PLL Multiplier
207 #pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
208 #pragma config FPLLIDIV = DIV_2 // PLL Input Divider
209 #pragma config FPLLODIV = DIV_1 // PLL Output Divider
210 #pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
211 #pragma config FWDTEN = OFF // Watchdog Timer
212 #pragma config WDTPS = PS1 // Watchdog Timer Postscale
213 #pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
214 #pragma config OSCIOFNC = OFF // CLKO Enable
215 #pragma config POSCMOD = HS // Primary Oscillator
216 #pragma config IESO = OFF // Internal/External Switch-over
217 #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
218 #pragma config FNOSC = PRIPLL // Oscillator Selection
219 #pragma config CP = OFF // Code Protect
220 #pragma config BWP = OFF // Boot Flash Write Protect
221 #pragma config PWP = OFF // Program Flash Write Protect
222 #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
223 #pragma config DEBUG = ON // Background Debugger Enable
224 #elif defined(UBW)
225 #elif defined(UBW32)
226 #else
227 #error No hardware board defined, see "HardwareProfile.h" and __FILE__
228 #endif
229  
230  
231  
232 /** VARIABLES ******************************************************/
233 #pragma udata
234  
235 /** PRIVATE PROTOTYPES *********************************************/
236 static void InitializeSystem(void);
237 void USBDeviceTasks(void);
238 void YourHighPriorityISRCode(void);
239 void YourLowPriorityISRCode(void);
240  
241  
242 /** VECTOR REMAPPING ***********************************************/
243 #if defined(__18CXX)
244 //On PIC18 devices, addresses 0x00, 0x08, and 0x18 are used for
245 //the reset, high priority interrupt, and low priority interrupt
246 //vectors. However, the current Microchip USB bootloader
247 //examples are intended to occupy addresses 0x00-0x7FF or
248 //0x00-0xFFF depending on which bootloader is used. Therefore,
249 //the bootloader code remaps these vectors to new locations
250 //as indicated below. This remapping is only necessary if you
251 //wish to program the hex file generated from this project with
252 //the USB bootloader. If no bootloader is used, edit the
253 //usb_config.h file and comment out the following defines:
254 //#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER
255 //#define PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER
256  
257 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
258 #define REMAPPED_RESET_VECTOR_ADDRESS 0x1000
259 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008
260 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018
261 #elif defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
262 #define REMAPPED_RESET_VECTOR_ADDRESS 0x800
263 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x808
264 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x818
265 #else
266 #define REMAPPED_RESET_VECTOR_ADDRESS 0x00
267 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x08
268 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x18
269 #endif
270  
271 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
272 extern void _startup (void); // See c018i.c in your C18 compiler dir
273 #pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
274 void _reset (void)
275 {
276 _asm goto _startup _endasm
277 }
278 #endif
279 #pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
280 void Remapped_High_ISR (void)
281 {
282 _asm goto YourHighPriorityISRCode _endasm
283 }
284 #pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
285 void Remapped_Low_ISR (void)
286 {
287 _asm goto YourLowPriorityISRCode _endasm
288 }
289  
290 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
291 //Note: If this project is built while one of the bootloaders has
292 //been defined, but then the output hex file is not programmed with
293 //the bootloader, addresses 0x08 and 0x18 would end up programmed with 0xFFFF.
294 //As a result, if an actual interrupt was enabled and occured, the PC would jump
295 //to 0x08 (or 0x18) and would begin executing "0xFFFF" (unprogrammed space). This
296 //executes as nop instructions, but the PC would eventually reach the REMAPPED_RESET_VECTOR_ADDRESS
297 //(0x1000 or 0x800, depending upon bootloader), and would execute the "goto _startup". This
298 //would effective reset the application.
299  
300 //To fix this situation, we should always deliberately place a
301 //"goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS" at address 0x08, and a
302 //"goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS" at address 0x18. When the output
303 //hex file of this project is programmed with the bootloader, these sections do not
304 //get bootloaded (as they overlap the bootloader space). If the output hex file is not
305 //programmed using the bootloader, then the below goto instructions do get programmed,
306 //and the hex file still works like normal. The below section is only required to fix this
307 //scenario.
308 #pragma code HIGH_INTERRUPT_VECTOR = 0x08
309 void High_ISR (void)
310 {
311 _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
312 }
313 #pragma code LOW_INTERRUPT_VECTOR = 0x18
314 void Low_ISR (void)
315 {
316 _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
317 }
318 #endif //end of "#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER)"
319  
320 #pragma code
321  
322  
323 //These are your actual interrupt handling routines.
324 #pragma interrupt YourHighPriorityISRCode
325 void YourHighPriorityISRCode()
326 {
327 //Check which interrupt flag caused the interrupt.
328 //Service the interrupt
329 //Clear the interrupt flag
330 //Etc.
331 #if defined(USB_INTERRUPT)
332 USBDeviceTasks();
333 #endif
334  
335 } //This return will be a "retfie fast", since this is in a #pragma interrupt section
336 #pragma interruptlow YourLowPriorityISRCode
337 void YourLowPriorityISRCode()
338 {
339 //Check which interrupt flag caused the interrupt.
340 //Service the interrupt
341 //Clear the interrupt flag
342 //Etc.
343  
344 } //This return will be a "retfie", since this is in a #pragma interruptlow section
345  
346 #elif defined(__C30__)
347 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
348 /*
349 * ISR JUMP TABLE
350 *
351 * It is necessary to define jump table as a function because C30 will
352 * not store 24-bit wide values in program memory as variables.
353 *
354 * This function should be stored at an address where the goto instructions
355 * line up with the remapped vectors from the bootloader's linker script.
356 *
357 * For more information about how to remap the interrupt vectors,
358 * please refer to AN1157. An example is provided below for the T2
359 * interrupt with a bootloader ending at address 0x1400
360 */
361 // void __attribute__ ((address(0x1404))) ISRTable(){
362 //
363 // asm("reset"); //reset instruction to prevent runaway code
364 // asm("goto %0"::"i"(&_T2Interrupt)); //T2Interrupt's address
365 // }
366 #endif
367 #endif
368  
369  
370  
371  
372 /** DECLARATIONS ***************************************************/
373 #pragma code
374  
375 /******************************************************************************
376 * Function: void main(void)
377 *
378 * PreCondition: None
379 *
380 * Input: None
381 *
382 * Output: None
383 *
384 * Side Effects: None
385 *
386 * Overview: Main program entry point.
387 *
388 * Note: None
389 *******************************************************************/
390  
391 #if defined(__18CXX)
392 void main(void)
393 #else
394 int main(void)
395 #endif
396 {
397 InitializeSystem();
398  
399 #if defined(USB_INTERRUPT)
400 USBDeviceAttach();
401 #endif
402  
403 while(1)
404 {
405 #if defined(USB_POLLING)
406 // Check bus status and service USB interrupts.
407 USBDeviceTasks(); // Interrupt or polling method. If using polling, must call
408 // this function periodically. This function will take care
409 // of processing and responding to SETUP transactions
410 // (such as during the enumeration process when you first
411 // plug in). USB hosts require that USB devices should accept
412 // and process SETUP packets in a timely fashion. Therefore,
413 // when using polling, this function should be called
414 // frequently (such as once about every 100 microseconds) at any
415 // time that a SETUP packet might reasonably be expected to
416 // be sent by the host to your device. In most cases, the
417 // USBDeviceTasks() function does not take very long to
418 // execute (~50 instruction cycles) before it returns.
419 #endif
420  
421  
422 // Application-specific tasks.
423 // Application related code may be added here, or in the ProcessIO() function.
424 ProcessIO();
425 }//end while
426 }//end main
427  
428  
429 /********************************************************************
430 * Function: static void InitializeSystem(void)
431 *
432 * PreCondition: None
433 *
434 * Input: None
435 *
436 * Output: None
437 *
438 * Side Effects: None
439 *
440 * Overview: InitializeSystem is a centralize initialization
441 * routine. All required USB initialization routines
442 * are called from here.
443 *
444 * User application initialization routine should
445 * also be called from here.
446 *
447 * Note: None
448 *******************************************************************/
449 static void InitializeSystem(void)
450 {
451 #if (defined(__18CXX) & !defined(PIC18F87J50_PIM))
452 ADCON1 |= 0x0F; // Default all pins to digital
453 #elif defined(__C30__)
454 #if defined(PIC24FJ256DA210_DEV_BOARD)
455 ANSA = 0x0000;
456 ANSB = 0x0000;
457 ANSC = 0x0000;
458 ANSD = 0x0000;
459 ANSE = 0x0000;
460 ANSF = 0x0000;
461 ANSG = 0x0000;
462 #else
463 AD1PCFGL = 0xFFFF;
464 #endif
465 #elif defined(__C32__)
466 AD1PCFG = 0xFFFF;
467 #endif
468  
469 #if defined(PIC18F87J50_PIM) || defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
470 //On the PIC18F87J50 Family of USB microcontrollers, the PLL will not power up and be enabled
471 //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
472 //This allows the device to power up at a lower initial operating frequency, which can be
473 //advantageous when powered from a source which is not gauranteed to be adequate for 48MHz
474 //operation. On these devices, user firmware needs to manually set the OSCTUNE<PLLEN> bit to
475 //power up the PLL.
476 {
477 unsigned int pll_startup_counter = 600;
478 OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
479 while(pll_startup_counter--);
480 }
481 //Device switches over automatically to PLL output after PLL is locked and ready.
482 #endif
483  
484 #if defined(PIC18F87J50_PIM)
485 //Configure all I/O pins to use digital input buffers. The PIC18F87J50 Family devices
486 //use the ANCONx registers to control this, which is different from other devices which
487 //use the ADCON1 register for this purpose.
488 WDTCONbits.ADSHR = 1; // Select alternate SFR location to access ANCONx registers
489 ANCON0 = 0xFF; // Default all pins to digital
490 ANCON1 = 0xFF; // Default all pins to digital
491 WDTCONbits.ADSHR = 0; // Select normal SFR locations
492 #endif
493  
494 #if defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
495 //Configure all I/O pins to use digital input buffers.
496 ANCON0 = 0x7F; // all pins to digital except AN7
497 ANCON1 = 0xBF; // Default all pins to digital. Bandgap on.
498 #endif
499  
500 #if defined(PIC24FJ64GB004_PIM) || defined(PIC24FJ256DA210_DEV_BOARD)
501 //On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
502 //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
503 //This allows the device to power up at a lower initial operating frequency, which can be
504 //advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
505 //operation. On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
506 //power up the PLL.
507 {
508 unsigned int pll_startup_counter = 600;
509 CLKDIVbits.PLLEN = 1;
510 while(pll_startup_counter--);
511 }
512  
513 //Device switches over automatically to PLL output after PLL is locked and ready.
514 #endif
515  
516  
517 // The USB specifications require that USB peripheral devices must never source
518 // current onto the Vbus pin. Additionally, USB peripherals should not source
519 // current on D+ or D- when the host/hub is not actively powering the Vbus line.
520 // When designing a self powered (as opposed to bus powered) USB peripheral
521 // device, the firmware should make sure not to turn on the USB module and D+
522 // or D- pull up resistor unless Vbus is actively powered. Therefore, the
523 // firmware needs some means to detect when Vbus is being powered by the host.
524 // A 5V tolerant I/O pin can be connected to Vbus (through a resistor), and
525 // can be used to detect when Vbus is high (host actively powering), or low
526 // (host is shut down or otherwise not supplying power). The USB firmware
527 // can then periodically poll this I/O pin to know when it is okay to turn on
528 // the USB module/D+/D- pull up resistor. When designing a purely bus powered
529 // peripheral device, it is not possible to source current on D+ or D- when the
530 // host is not actively providing power on Vbus. Therefore, implementing this
531 // bus sense feature is optional. This firmware can be made to use this bus
532 // sense feature by making sure "USE_USB_BUS_SENSE_IO" has been defined in the
533 // HardwareProfile.h file.
534 #if defined(USE_USB_BUS_SENSE_IO)
535 tris_usb_bus_sense = INPUT_PIN; // See HardwareProfile.h
536 #endif
537  
538 // If the host PC sends a GetStatus (device) request, the firmware must respond
539 // and let the host know if the USB peripheral device is currently bus powered
540 // or self powered. See chapter 9 in the official USB specifications for details
541 // regarding this request. If the peripheral device is capable of being both
542 // self and bus powered, it should not return a hard coded value for this request.
543 // Instead, firmware should check if it is currently self or bus powered, and
544 // respond accordingly. If the hardware has been configured like demonstrated
545 // on the PICDEM FS USB Demo Board, an I/O pin can be polled to determine the
546 // currently selected power source. On the PICDEM FS USB Demo Board, "RA2"
547 // is used for this purpose. If using this feature, make sure "USE_SELF_POWER_SENSE_IO"
548 // has been defined in HardwareProfile - (platform).h, and that an appropriate I/O pin
549 // has been mapped to it.
550 #if defined(USE_SELF_POWER_SENSE_IO)
551 tris_self_power = INPUT_PIN; // See HardwareProfile
552 #endif
553  
554 UserInit();
555  
556 USBDeviceInit(); //usb_device.c. Initializes USB module SFRs and firmware
557 //variables to known states.
558 }//end InitializeSystem
559  
560 // ******************************************************************************************************
561 // ************** USB Callback Functions ****************************************************************
562 // ******************************************************************************************************
563 // The USB firmware stack will call the callback functions USBCBxxx() in response to certain USB related
564 // events. For example, if the host PC is powering down, it will stop sending out Start of Frame (SOF)
565 // packets to your device. In response to this, all USB devices are supposed to decrease their power
566 // consumption from the USB Vbus to <2.5mA each. The USB module detects this condition (which according
567 // to the USB specifications is 3+ms of no bus activity/SOF packets) and then calls the USBCBSuspend()
568 // function. You should modify these callback functions to take appropriate actions for each of these
569 // conditions. For example, in the USBCBSuspend(), you may wish to add code that will decrease power
570 // consumption from Vbus to <2.5mA (such as by clock switching, turning off LEDs, putting the
571 // microcontroller to sleep, etc.). Then, in the USBCBWakeFromSuspend() function, you may then wish to
572 // add code that undoes the power saving things done in the USBCBSuspend() function.
573  
574 // The USBCBSendResume() function is special, in that the USB stack will not automatically call this
575 // function. This function is meant to be called from the application firmware instead. See the
576 // additional comments near the function.
577  
578 /******************************************************************************
579 * Function: void USBCBSuspend(void)
580 *
581 * PreCondition: None
582 *
583 * Input: None
584 *
585 * Output: None
586 *
587 * Side Effects: None
588 *
589 * Overview: Call back that is invoked when a USB suspend is detected
590 *
591 * Note: None
592 *****************************************************************************/
593 void USBCBSuspend(void)
594 {
595 //Example power saving code. Insert appropriate code here for the desired
596 //application behavior. If the microcontroller will be put to sleep, a
597 //process similar to that shown below may be used:
598  
599 //ConfigureIOPinsForLowPower();
600 //SaveStateOfAllInterruptEnableBits();
601 //DisableAllInterruptEnableBits();
602 //EnableOnlyTheInterruptsWhichWillBeUsedToWakeTheMicro(); //should enable at least USBActivityIF as a wake source
603 //Sleep();
604 //RestoreStateOfAllPreviouslySavedInterruptEnableBits(); //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
605 //RestoreIOPinsToNormal(); //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
606  
607 //IMPORTANT NOTE: Do not clear the USBActivityIF (ACTVIF) bit here. This bit is
608 //cleared inside the usb_device.c file. Clearing USBActivityIF here will cause
609 //things to not work as intended.
610  
611  
612 #if defined(__C30__)
613 #if 0
614 U1EIR = 0xFFFF;
615 U1IR = 0xFFFF;
616 U1OTGIR = 0xFFFF;
617 IFS5bits.USB1IF = 0;
618 IEC5bits.USB1IE = 1;
619 U1OTGIEbits.ACTVIE = 1;
620 U1OTGIRbits.ACTVIF = 1;
621 Sleep();
622 #endif
623 #endif
624 }
625  
626  
627 /******************************************************************************
628 * Function: void _USB1Interrupt(void)
629 *
630 * PreCondition: None
631 *
632 * Input: None
633 *
634 * Output: None
635 *
636 * Side Effects: None
637 *
638 * Overview: This function is called when the USB interrupt bit is set
639 * In this example the interrupt is only used when the device
640 * goes to sleep when it receives a USB suspend command
641 *
642 * Note: None
643 *****************************************************************************/
644 #if 0
645 void __attribute__ ((interrupt)) _USB1Interrupt(void)
646 {
647 #if !defined(self_powered)
648 if(U1OTGIRbits.ACTVIF)
649 {
650 IEC5bits.USB1IE = 0;
651 U1OTGIEbits.ACTVIE = 0;
652 IFS5bits.USB1IF = 0;
653  
654 //USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum);
655 USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum);
656 //USBSuspendControl = 0;
657 }
658 #endif
659 }
660 #endif
661  
662 /******************************************************************************
663 * Function: void USBCBWakeFromSuspend(void)
664 *
665 * PreCondition: None
666 *
667 * Input: None
668 *
669 * Output: None
670 *
671 * Side Effects: None
672 *
673 * Overview: The host may put USB peripheral devices in low power
674 * suspend mode (by "sending" 3+ms of idle). Once in suspend
675 * mode, the host may wake the device back up by sending non-
676 * idle state signalling.
677 *
678 * This call back is invoked when a wakeup from USB suspend
679 * is detected.
680 *
681 * Note: None
682 *****************************************************************************/
683 void USBCBWakeFromSuspend(void)
684 {
685 // If clock switching or other power savings measures were taken when
686 // executing the USBCBSuspend() function, now would be a good time to
687 // switch back to normal full power run mode conditions. The host allows
688 // a few milliseconds of wakeup time, after which the device must be
689 // fully back to normal, and capable of receiving and processing USB
690 // packets. In order to do this, the USB module must receive proper
691 // clocking (IE: 48MHz clock must be available to SIE for full speed USB
692 // operation).
693 }
694  
695 /********************************************************************
696 * Function: void USBCB_SOF_Handler(void)
697 *
698 * PreCondition: None
699 *
700 * Input: None
701 *
702 * Output: None
703 *
704 * Side Effects: None
705 *
706 * Overview: The USB host sends out a SOF packet to full-speed
707 * devices every 1 ms. This interrupt may be useful
708 * for isochronous pipes. End designers should
709 * implement callback routine as necessary.
710 *
711 * Note: None
712 *******************************************************************/
713 void USBCB_SOF_Handler(void)
714 {
715 // No need to clear UIRbits.SOFIF to 0 here.
716 // Callback caller is already doing that.
717 }
718  
719 /*******************************************************************
720 * Function: void USBCBErrorHandler(void)
721 *
722 * PreCondition: None
723 *
724 * Input: None
725 *
726 * Output: None
727 *
728 * Side Effects: None
729 *
730 * Overview: The purpose of this callback is mainly for
731 * debugging during development. Check UEIR to see
732 * which error causes the interrupt.
733 *
734 * Note: None
735 *******************************************************************/
736 void USBCBErrorHandler(void)
737 {
738 // No need to clear UEIR to 0 here.
739 // Callback caller is already doing that.
740  
741 // Typically, user firmware does not need to do anything special
742 // if a USB error occurs. For example, if the host sends an OUT
743 // packet to your device, but the packet gets corrupted (ex:
744 // because of a bad connection, or the user unplugs the
745 // USB cable during the transmission) this will typically set
746 // one or more USB error interrupt flags. Nothing specific
747 // needs to be done however, since the SIE will automatically
748 // send a "NAK" packet to the host. In response to this, the
749 // host will normally retry to send the packet again, and no
750 // data loss occurs. The system will typically recover
751 // automatically, without the need for application firmware
752 // intervention.
753  
754 // Nevertheless, this callback function is provided, such as
755 // for debugging purposes.
756 }
757  
758  
759 /*******************************************************************
760 * Function: void USBCBCheckOtherReq(void)
761 *
762 * PreCondition: None
763 *
764 * Input: None
765 *
766 * Output: None
767 *
768 * Side Effects: None
769 *
770 * Overview: When SETUP packets arrive from the host, some
771 * firmware must process the request and respond
772 * appropriately to fulfill the request. Some of
773 * the SETUP packets will be for standard
774 * USB "chapter 9" (as in, fulfilling chapter 9 of
775 * the official USB specifications) requests, while
776 * others may be specific to the USB device class
777 * that is being implemented. For example, a HID
778 * class device needs to be able to respond to
779 * "GET REPORT" type of requests. This
780 * is not a standard USB chapter 9 request, and
781 * therefore not handled by usb_device.c. Instead
782 * this request should be handled by class specific
783 * firmware, such as that contained in usb_function_hid.c.
784 *
785 * Note: None
786 *****************************************************************************/
787 void USBCBCheckOtherReq(void)
788 {
789 USBCheckUBWRequest();
790 }//end
791  
792  
793 /*******************************************************************
794 * Function: void USBCBStdSetDscHandler(void)
795 *
796 * PreCondition: None
797 *
798 * Input: None
799 *
800 * Output: None
801 *
802 * Side Effects: None
803 *
804 * Overview: The USBCBStdSetDscHandler() callback function is
805 * called when a SETUP, bRequest: SET_DESCRIPTOR request
806 * arrives. Typically SET_DESCRIPTOR requests are
807 * not used in most applications, and it is
808 * optional to support this type of request.
809 *
810 * Note: None
811 *****************************************************************************/
812 void USBCBStdSetDscHandler(void)
813 {
814 // Must claim session ownership if supporting this request
815 }//end
816  
817  
818 /******************************************************************************
819 * Function: void USBCBInitEP(void)
820 *
821 * PreCondition: None
822 *
823 * Input: None
824 *
825 * Output: None
826 *
827 * Side Effects: None
828 *
829 * Overview: This function is called when the device becomes
830 * initialized, which occurs after the host sends a
831 * SET_CONFIGURATION (wValue not = 0) request. This
832 * callback function should initialize the endpoints
833 * for the device's usage according to the current
834 * configuration.
835 *
836 * Note: None
837 *****************************************************************************/
838 void USBCBInitEP(void)
839 {
840 }
841  
842 /********************************************************************
843 * Function: void USBCBSendResume(void)
844 *
845 * PreCondition: None
846 *
847 * Input: None
848 *
849 * Output: None
850 *
851 * Side Effects: None
852 *
853 * Overview: The USB specifications allow some types of USB
854 * peripheral devices to wake up a host PC (such
855 * as if it is in a low power suspend to RAM state).
856 * This can be a very useful feature in some
857 * USB applications, such as an Infrared remote
858 * control receiver. If a user presses the "power"
859 * button on a remote control, it is nice that the
860 * IR receiver can detect this signalling, and then
861 * send a USB "command" to the PC to wake up.
862 *
863 * The USBCBSendResume() "callback" function is used
864 * to send this special USB signalling which wakes
865 * up the PC. This function may be called by
866 * application firmware to wake up the PC. This
867 * function should only be called when:
868 *
869 * 1. The USB driver used on the host PC supports
870 * the remote wakeup capability.
871 * 2. The USB configuration descriptor indicates
872 * the device is remote wakeup capable in the
873 * bmAttributes field.
874 * 3. The USB host PC is currently sleeping,
875 * and has previously sent your device a SET
876 * FEATURE setup packet which "armed" the
877 * remote wakeup capability.
878 *
879 * This callback should send a RESUME signal that
880 * has the period of 1-15ms.
881 *
882 * Note: Interrupt vs. Polling
883 * -Primary clock
884 * -Secondary clock ***** MAKE NOTES ABOUT THIS *******
885 * > Can switch to primary first by calling USBCBWakeFromSuspend()
886  
887 * The modifiable section in this routine should be changed
888 * to meet the application needs. Current implementation
889 * temporary blocks other functions from executing for a
890 * period of 1-13 ms depending on the core frequency.
891 *
892 * According to USB 2.0 specification section 7.1.7.7,
893 * "The remote wakeup device must hold the resume signaling
894 * for at lest 1 ms but for no more than 15 ms."
895 * The idea here is to use a delay counter loop, using a
896 * common value that would work over a wide range of core
897 * frequencies.
898 * That value selected is 1800. See table below:
899 * ==========================================================
900 * Core Freq(MHz) MIP RESUME Signal Period (ms)
901 * ==========================================================
902 * 48 12 1.05
903 * 4 1 12.6
904 * ==========================================================
905 * * These timing could be incorrect when using code
906 * optimization or extended instruction mode,
907 * or when having other interrupts enabled.
908 * Make sure to verify using the MPLAB SIM's Stopwatch
909 * and verify the actual signal on an oscilloscope.
910 *******************************************************************/
911 void USBCBSendResume(void)
912 {
913 static WORD delay_count;
914  
915 USBResumeControl = 1; // Start RESUME signaling
916  
917 delay_count = 1800U; // Set RESUME line for 1-13 ms
918 do
919 {
920 delay_count--;
921 }while(delay_count);
922 USBResumeControl = 0;
923 }
924  
925  
926 /*******************************************************************
927 * Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER(
928 * USB_EVENT event, void *pdata, WORD size)
929 *
930 * PreCondition: None
931 *
932 * Input: USB_EVENT event - the type of event
933 * void *pdata - pointer to the event data
934 * WORD size - size of the event data
935 *
936 * Output: None
937 *
938 * Side Effects: None
939 *
940 * Overview: This function is called from the USB stack to
941 * notify a user application that a USB event
942 * occured. This callback is in interrupt context
943 * when the USB_INTERRUPT option is selected.
944 *
945 * Note: None
946 *******************************************************************/
947 BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
948 {
949 switch(event)
950 {
951 case EVENT_CONFIGURED:
952 USBCBInitEP();
953 break;
954 case EVENT_SET_DESCRIPTOR:
955 USBCBStdSetDscHandler();
956 break;
957 case EVENT_EP0_REQUEST:
958 USBCBCheckOtherReq();
959 break;
960 case EVENT_SOF:
961 USBCB_SOF_Handler();
962 break;
963 case EVENT_SUSPEND:
964 USBCBSuspend();
965 break;
966 case EVENT_RESUME:
967 USBCBWakeFromSuspend();
968 break;
969 case EVENT_BUS_ERROR:
970 USBCBErrorHandler();
971 break;
972 case EVENT_TRANSFER:
973 Nop();
974 break;
975 default:
976 break;
977 }
978 return TRUE;
979 }
980 /** EOF main.c ***************************************************************/