version 0.1 written by Akiba, taken from here:
[chibi.git] / freakusb / hw / at90usbxx6_7 / isr.c
blob10c24ae6f2d411c018b603c333cc8af6c63d802f
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 *******************************************************************/
20 /*!
21 \file isr.c
22 \ingroup hw_at90usb
24 /*******************************************************************/
25 #include <avr/interrupt.h>
26 #include "freakusb.h"
27 #include "at90usb.h"
29 /**************************************************************************/
30 /*!
31 Clear all USB related interrupts.
33 /**************************************************************************/
34 void intp_clear_all()
36 U8 i;
38 USBINT = 0;
39 UDINT = 0;
41 for (i=0; i<MAX_EPS; i++)
43 ep_select(i);
44 UEINTX = 0;
48 /**************************************************************************/
49 /*!
50 VBUS Change interrupt handler.
52 /**************************************************************************/
53 void intp_vbus_change()
55 usb_pcb_t *pcb = usb_pcb_get();
57 VBUS_INT_CLR();
59 if (!pcb->connected)
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);
70 else
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);
80 PLLCSR = 0;
82 // disable the USB voltage regulator
83 UHWCON &= ~(1 << UVREGE);
85 pcb->connected = false;
86 pcb->flags = 0;
91 /**************************************************************************/
92 /*!
93 Suspend interrupt handler.
95 /**************************************************************************/
96 void intp_suspend()
98 SUSP_INT_CLR();
99 WAKEUP_INT_ENB();
100 WAKEUP_INT_CLR();
102 // freeze the clock and turn off the USB PLL
103 USBCON |= (1 << FRZCLK);
106 /**************************************************************************/
108 Resume interrupt handler.
110 /**************************************************************************/
111 void intp_resume()
113 WAKEUP_INT_DIS();
114 RESM_INT_CLR();
115 RESM_INT_DIS();
118 /**************************************************************************/
120 Wakeup interrupt handler.
122 /**************************************************************************/
123 void intp_wakeup()
125 // unfreeze the clock
126 USBCON &= ~(1 << FRZCLK);
128 WAKEUP_INT_CLR();
129 WAKEUP_INT_DIS();
131 // disable the wakeup until next time we go into suspend
132 WAKEUP_INT_DIS();
135 /**************************************************************************/
137 End of Reset interrupt handler. Gets triggered at the end of a bus reset.
139 /**************************************************************************/
140 void intp_eor()
142 EOR_INT_CLR();
143 ep_init();
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 /**************************************************************************/
152 ISR(USB_COM_vect)
154 U8 ep_intp_num, intp_src, ep_num;
155 usb_pcb_t *pcb;
157 cli();
159 // get the pcb for later use
160 pcb = usb_pcb_get();
162 // save off the ep number we just had
163 ep_num = UENUM;
165 if ((ep_intp_num= ep_intp_get_num()) == 0xFF)
167 // no intp number was found. restore the ep number and enable the interrupts
168 ep_select(ep_num);
169 sei();
170 return;
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
178 ep_select(ep_num);
179 sei();
180 return;
183 switch (intp_src)
185 case RXSTPI:
186 ep_read(ep_intp_num);
188 // clear the intp
189 RX_SETUP_INT_CLR();
190 break;
191 case RXOUTI:
192 ep_read(ep_intp_num);
194 // clear the intps
195 RX_OUT_INT_CLR();
196 FIFOCON_INT_CLR();
197 break;
198 case TXINI:
199 ep_write(ep_intp_num);
201 // clear the intps
202 TX_IN_INT_CLR();
203 break;
204 case STALLEDI:
205 break;
206 case NAKOUTI:
207 break;
208 case RWAL:
209 break;
210 case NAKINI:
211 break;
212 case FIFOCON:
213 break;
214 default:
215 break;
218 // restore the endpoint number
219 ep_select(ep_num);
221 sei();
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
229 and bus reset.
231 /**************************************************************************/
232 ISR(USB_GEN_vect)
234 U8 ep_num;
236 cli();
238 // save off the endpoint number we were just on. we'll restore it later
239 ep_num = UENUM;
241 // suspend detected
242 if (SUSP_INT && SUSP_INT_ENABLED)
244 intp_suspend();
247 // vbus status change
248 if (VBUS_INT && VBUS_INT_ENABLED)
250 intp_vbus_change();
253 if (RESM_INT && RESM_INT_ENABLED)
255 intp_resume();
258 // wakeup detected
259 if (WAKEUP_INT && WAKEUP_INT_ENABLED)
261 intp_wakeup();
264 // end of bus reset
265 if (EOR_INT && EOR_INT_ENABLED)
267 intp_eor();
270 // restore the endpoint number
271 ep_select(ep_num);
273 sei();
276 /**************************************************************************/
278 This ISR is only for the AT90USB16 since we need to use an IO as the VBUS sense
280 /**************************************************************************/
282 #ifdef AT90USB16
283 ISR(PCINT0_vect)
285 usb_pcb_t *pcb = usb_pcb_get();
287 cli();
288 if (PCMSK0 & (1<<VBUS_SENSE_IO))
290 PCMSK0 &= ~_BV(VBUS_SENSE_IO);
292 if (is_vbus_on)
294 pcb->connected = true;
296 // enable the 3.3V regulator for the USB pads
297 REGCR &= ~_BV(REGDIS);
299 // freeze the clock
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)));
309 // unfreeze clock
310 USBCON &= ~_BV(FRZCLK);
312 // attach USB
313 UDCON &= ~_BV(DETACH);
315 // reset CPU
316 UDCON |= _BV(RSTCPU);
318 else
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;
333 pcb->flags = 0;
336 sei();
338 #endif