1 /*******************************************************************
2 Copyright (C) 2008 FreakLabs
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 Please post support questions to the FreakLabs forum.
19 *******************************************************************/
24 /*******************************************************************/
25 #include <avr/interrupt.h>
29 /**************************************************************************/
31 Clear all USB related interrupts.
33 /**************************************************************************/
41 for (i
=0; i
<MAX_EPS
; i
++)
48 /**************************************************************************/
50 VBUS Change interrupt handler.
52 /**************************************************************************/
53 void intp_vbus_change()
55 usb_pcb_t
*pcb
= usb_pcb_get();
61 pcb
->connected
= true;
63 // enabled the USB voltage regulator
64 UHWCON
|= (1 << UVREGE
);
66 // unfreeze the clock and attach to the bus
67 USBCON
&= ~(1 << FRZCLK
);
68 UDCON
&= ~(1 << DETACH
);
72 // if we're connected, but VBUS is gone, then detach
73 if (!(USBSTA
& (1<<VBUS
)))
75 // detach from the bus
76 UDCON
|= (1 << DETACH
);
78 // freeze the clock and turn off the USB PLL
79 USBCON
|= (1 << FRZCLK
);
82 // disable the USB voltage regulator
83 UHWCON
&= ~(1 << UVREGE
);
85 pcb
->connected
= false;
91 /**************************************************************************/
93 Suspend interrupt handler.
95 /**************************************************************************/
102 // freeze the clock and turn off the USB PLL
103 USBCON
|= (1 << FRZCLK
);
106 /**************************************************************************/
108 Resume interrupt handler.
110 /**************************************************************************/
118 /**************************************************************************/
120 Wakeup interrupt handler.
122 /**************************************************************************/
125 // unfreeze the clock
126 USBCON
&= ~(1 << FRZCLK
);
131 // disable the wakeup until next time we go into suspend
135 /**************************************************************************/
137 End of Reset interrupt handler. Gets triggered at the end of a bus reset.
139 /**************************************************************************/
146 /**************************************************************************/
148 This is the ISR that handles communications for the AT90USB. These interrupts
149 are endpoint specific and are mostly used for data transfers and communications.
151 /**************************************************************************/
154 U8 ep_intp_num
, intp_src
, ep_num
;
159 // get the pcb for later use
162 // save off the ep number we just had
165 if ((ep_intp_num
= ep_intp_get_num()) == 0xFF)
167 // no intp number was found. restore the ep number and enable the interrupts
173 // select the endpoint number and get the intp src
174 ep_select(ep_intp_num
);
175 if ((intp_src
= ep_intp_get_src()) == 0xFF)
177 // no intp source was found. restore the ep number and enable the interrupts
186 ep_read(ep_intp_num
);
192 ep_read(ep_intp_num
);
199 ep_write(ep_intp_num
);
218 // restore the endpoint number
224 /**************************************************************************/
226 This ISR handles general USB functions on the AT90USB. The interrupts
227 are sepearated into a general and communications interrupt. The general
228 interrupt handles global USB features such as VBUS detection, suspend, resume
231 /**************************************************************************/
238 // save off the endpoint number we were just on. we'll restore it later
242 if (SUSP_INT
&& SUSP_INT_ENABLED
)
247 // vbus status change
248 if (VBUS_INT
&& VBUS_INT_ENABLED
)
253 if (RESM_INT
&& RESM_INT_ENABLED
)
259 if (WAKEUP_INT
&& WAKEUP_INT_ENABLED
)
265 if (EOR_INT
&& EOR_INT_ENABLED
)
270 // restore the endpoint number
276 /**************************************************************************/
278 This ISR is only for the AT90USB16 since we need to use an IO as the VBUS sense
280 /**************************************************************************/
285 usb_pcb_t
*pcb
= usb_pcb_get();
288 if (PCMSK0
& (1<<VBUS_SENSE_IO
))
290 PCMSK0
&= ~_BV(VBUS_SENSE_IO
);
294 pcb
->connected
= true;
296 // enable the 3.3V regulator for the USB pads
297 REGCR
&= ~_BV(REGDIS
);
300 USBCON
|= _BV(FRZCLK
);
302 // enable the 48 MHz PLL
303 PLLCSR
&= ~(_BV(PLLP2
) | _BV(PLLP1
) | _BV(PLLP0
));
304 PLLCSR
|= _BV(1<<PLLE
);
306 // busy wait until the PLL is locked
307 while (!(PLLCSR
& _BV(PLOCK
)));
310 USBCON
&= ~_BV(FRZCLK
);
313 UDCON
&= ~_BV(DETACH
);
316 UDCON
|= _BV(RSTCPU
);
320 // if we're connected, but VBUS is gone, then detach
322 // detach from the bus
323 UDCON
|= _BV(DETACH
);
325 // freeze the clock and turn off the USB PLL
326 USBCON
|= _BV(FRZCLK
);
327 PLLCSR
&= ~_BV(PLLE
);
329 // disable the USB voltage regulator
330 REGCR
|= _BV(REGDIS
);
332 pcb
->connected
= false;