1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2 
3 /*This file is prepared for Doxygen automatic documentation generation.*/
4 /*! \file *********************************************************************
5  *
6  * \brief AT32UC3A EVK1100 board LEDs support package.
7  *
8  * This file contains definitions and services related to the LED features of
9  * the EVK1100 board.
10  *
11  * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
12  * - Supported devices:  All AVR32 AT32UC3A devices can be used.
13  * - AppNote:
14  *
15  * \author               Atmel Corporation: http://www.atmel.com \n
16  *                       Support and FAQ: http://support.atmel.no/
17  *
18  ******************************************************************************/
19 
20 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions are met:
24  *
25  * 1. Redistributions of source code must retain the above copyright notice, this
26  * list of conditions and the following disclaimer.
27  *
28  * 2. Redistributions in binary form must reproduce the above copyright notice,
29  * this list of conditions and the following disclaimer in the documentation
30  * and/or other materials provided with the distribution.
31  *
32  * 3. The name of Atmel may not be used to endorse or promote products derived
33  * from this software without specific prior written permission.
34  *
35  * 4. This software may only be redistributed and used in connection with an Atmel
36  * AVR product.
37  *
38  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
41  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
42  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
48  *
49  */
50 
51 #include <avr32/io.h>
52 #include "preprocessor.h"
53 #include "compiler.h"
54 #include "arduino.h"
55 #include "led.h"
56 
57 
58 //! Structure describing LED hardware connections.
59 typedef const struct
60 {
61   struct
62   {
63     U32 PORT;     //!< LED GPIO port.
64     U32 PIN_MASK; //!< Bit-mask of LED pin in GPIO port.
65   } GPIO; //!< LED GPIO descriptor.
66   struct
67   {
68     S32 CHANNEL;  //!< LED PWM channel (< 0 if N/A).
69     S32 FUNCTION; //!< LED pin PWM function (< 0 if N/A).
70   } PWM;  //!< LED PWM descriptor.
71 } tLED_DESCRIPTOR;
72 
73 
74 //! Hardware descriptors of all LEDs.
75 static tLED_DESCRIPTOR LED_DESCRIPTOR[LED_COUNT] =
76 {
77 #define INSERT_LED_DESCRIPTOR(LED_NO, unused)                 \
78   {                                                           \
79     {LED##LED_NO##_GPIO / 32, 1 << (LED##LED_NO##_GPIO % 32)},\
80     {LED##LED_NO##_PWM,       LED##LED_NO##_PWM_FUNCTION    } \
81   },
82   MREPEAT(LED_COUNT, INSERT_LED_DESCRIPTOR, ~)
83 #undef INSERT_LED_DESCRIPTOR
84 };
85 
86 
87 //! Saved state of all LEDs.
88 static volatile U32 LED_State = (1 << LED_COUNT) - 1;
89 
90 
LED_Read_Display(void)91 U32 LED_Read_Display(void)
92 {
93   return LED_State;
94 }
95 
96 
LED_Display(U32 leds)97 void LED_Display(U32 leds)
98 {
99   // Use the LED descriptors to get the connections of a given LED to the MCU.
100   tLED_DESCRIPTOR *led_descriptor;
101   volatile avr32_gpio_port_t *led_gpio_port;
102 
103   // Make sure only existing LEDs are specified.
104   leds &= (1 << LED_COUNT) - 1;
105 
106   // Update the saved state of all LEDs with the requested changes.
107   LED_State = leds;
108 
109   // For all LEDs...
110   for (led_descriptor = &LED_DESCRIPTOR[0];
111        led_descriptor < LED_DESCRIPTOR + LED_COUNT;
112        led_descriptor++)
113   {
114     // Set the LED to the requested state.
115     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
116     if (leds & 1)
117     {
118       led_gpio_port->ovrc  = led_descriptor->GPIO.PIN_MASK;
119     }
120     else
121     {
122       led_gpio_port->ovrs  = led_descriptor->GPIO.PIN_MASK;
123     }
124     led_gpio_port->oders = led_descriptor->GPIO.PIN_MASK;
125     led_gpio_port->gpers = led_descriptor->GPIO.PIN_MASK;
126     leds >>= 1;
127   }
128 }
129 
130 
LED_Read_Display_Mask(U32 mask)131 U32 LED_Read_Display_Mask(U32 mask)
132 {
133   return Rd_bits(LED_State, mask);
134 }
135 
136 
LED_Display_Mask(U32 mask,U32 leds)137 void LED_Display_Mask(U32 mask, U32 leds)
138 {
139   // Use the LED descriptors to get the connections of a given LED to the MCU.
140   tLED_DESCRIPTOR *led_descriptor = &LED_DESCRIPTOR[0] - 1;
141   volatile avr32_gpio_port_t *led_gpio_port;
142   U8 led_shift;
143 
144   // Make sure only existing LEDs are specified.
145   mask &= (1 << LED_COUNT) - 1;
146 
147   // Update the saved state of all LEDs with the requested changes.
148   Wr_bits(LED_State, mask, leds);
149 
150   // While there are specified LEDs left to manage...
151   while (mask)
152   {
153     // Select the next specified LED and set it to the requested state.
154     led_shift = 1 + ctz(mask);
155     led_descriptor += led_shift;
156     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
157     leds >>= led_shift - 1;
158     if (leds & 1)
159     {
160       led_gpio_port->ovrc  = led_descriptor->GPIO.PIN_MASK;
161     }
162     else
163     {
164       led_gpio_port->ovrs  = led_descriptor->GPIO.PIN_MASK;
165     }
166     led_gpio_port->oders = led_descriptor->GPIO.PIN_MASK;
167     led_gpio_port->gpers = led_descriptor->GPIO.PIN_MASK;
168     leds >>= 1;
169     mask >>= led_shift;
170   }
171 }
172 
173 
LED_Test(U32 leds)174 Bool LED_Test(U32 leds)
175 {
176   return Tst_bits(LED_State, leds);
177 }
178 
179 
LED_Off(U32 leds)180 void LED_Off(U32 leds)
181 {
182   // Use the LED descriptors to get the connections of a given LED to the MCU.
183   tLED_DESCRIPTOR *led_descriptor = &LED_DESCRIPTOR[0] - 1;
184   volatile avr32_gpio_port_t *led_gpio_port;
185   U8 led_shift;
186 
187   // Make sure only existing LEDs are specified.
188   leds &= (1 << LED_COUNT) - 1;
189 
190   // Update the saved state of all LEDs with the requested changes.
191   Clr_bits(LED_State, leds);
192 
193   // While there are specified LEDs left to manage...
194   while (leds)
195   {
196     // Select the next specified LED and turn it off.
197     led_shift = 1 + ctz(leds);
198     led_descriptor += led_shift;
199     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
200     led_gpio_port->ovrs  = led_descriptor->GPIO.PIN_MASK;
201     led_gpio_port->oders = led_descriptor->GPIO.PIN_MASK;
202     led_gpio_port->gpers = led_descriptor->GPIO.PIN_MASK;
203     leds >>= led_shift;
204   }
205 }
206 
207 
LED_On(U32 leds)208 void LED_On(U32 leds)
209 {
210   // Use the LED descriptors to get the connections of a given LED to the MCU.
211   tLED_DESCRIPTOR *led_descriptor = &LED_DESCRIPTOR[0] - 1;
212   volatile avr32_gpio_port_t *led_gpio_port;
213   U8 led_shift;
214 
215   // Make sure only existing LEDs are specified.
216   leds &= (1 << LED_COUNT) - 1;
217 
218   // Update the saved state of all LEDs with the requested changes.
219   Set_bits(LED_State, leds);
220 
221   // While there are specified LEDs left to manage...
222   while (leds)
223   {
224     // Select the next specified LED and turn it on.
225     led_shift = 1 + ctz(leds);
226     led_descriptor += led_shift;
227     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
228     led_gpio_port->ovrc  = led_descriptor->GPIO.PIN_MASK;
229     led_gpio_port->oders = led_descriptor->GPIO.PIN_MASK;
230     led_gpio_port->gpers = led_descriptor->GPIO.PIN_MASK;
231     leds >>= led_shift;
232   }
233 }
234 
235 
LED_Toggle(U32 leds)236 void LED_Toggle(U32 leds)
237 {
238   // Use the LED descriptors to get the connections of a given LED to the MCU.
239   tLED_DESCRIPTOR *led_descriptor = &LED_DESCRIPTOR[0] - 1;
240   volatile avr32_gpio_port_t *led_gpio_port;
241   U8 led_shift;
242 
243   // Make sure only existing LEDs are specified.
244   leds &= (1 << LED_COUNT) - 1;
245 
246   // Update the saved state of all LEDs with the requested changes.
247   Tgl_bits(LED_State, leds);
248 
249   // While there are specified LEDs left to manage...
250   while (leds)
251   {
252     // Select the next specified LED and toggle it.
253     led_shift = 1 + ctz(leds);
254     led_descriptor += led_shift;
255     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
256     led_gpio_port->ovrt  = led_descriptor->GPIO.PIN_MASK;
257     led_gpio_port->oders = led_descriptor->GPIO.PIN_MASK;
258     led_gpio_port->gpers = led_descriptor->GPIO.PIN_MASK;
259     leds >>= led_shift;
260   }
261 }
262 
263 
LED_Read_Display_Field(U32 field)264 U32 LED_Read_Display_Field(U32 field)
265 {
266   return Rd_bitfield(LED_State, field);
267 }
268 
269 
LED_Display_Field(U32 field,U32 leds)270 void LED_Display_Field(U32 field, U32 leds)
271 {
272   // Move the bit-field to the appropriate position for the bit-mask.
273   LED_Display_Mask(field, leds << ctz(field));
274 }
275 
276 
LED_Get_Intensity(U32 led)277 U8 LED_Get_Intensity(U32 led)
278 {
279   tLED_DESCRIPTOR *led_descriptor;
280 
281   // Check that the argument value is valid.
282   led = ctz(led);
283   led_descriptor = &LED_DESCRIPTOR[led];
284   if (led >= LED_COUNT || led_descriptor->PWM.CHANNEL < 0) return 0;
285 
286   // Return the duty cycle value if the LED PWM channel is enabled, else 0.
287   return (AVR32_PWM.sr & (1 << led_descriptor->PWM.CHANNEL)) ?
288            AVR32_PWM.channel[led_descriptor->PWM.CHANNEL].cdty : 0;
289 }
290 
291 
LED_Set_Intensity(U32 leds,U8 intensity)292 void LED_Set_Intensity(U32 leds, U8 intensity)
293 {
294   tLED_DESCRIPTOR *led_descriptor = &LED_DESCRIPTOR[0] - 1;
295   volatile avr32_pwm_channel_t *led_pwm_channel;
296   volatile avr32_gpio_port_t *led_gpio_port;
297   U8 led_shift;
298 
299   // For each specified LED...
300   for (leds &= (1 << LED_COUNT) - 1; leds; leds >>= led_shift)
301   {
302     // Select the next specified LED and check that it has a PWM channel.
303     led_shift = 1 + ctz(leds);
304     led_descriptor += led_shift;
305     if (led_descriptor->PWM.CHANNEL < 0) continue;
306 
307     // Initialize or update the LED PWM channel.
308     led_pwm_channel = &AVR32_PWM.channel[led_descriptor->PWM.CHANNEL];
309     if (!(AVR32_PWM.sr & (1 << led_descriptor->PWM.CHANNEL)))
310     {
311       led_pwm_channel->cmr = (AVR32_PWM_CPRE_MCK << AVR32_PWM_CPRE_OFFSET) &
312                              ~(AVR32_PWM_CALG_MASK |
313                                AVR32_PWM_CPOL_MASK |
314                                AVR32_PWM_CPD_MASK);
315       led_pwm_channel->cprd = 0x000000FF;
316       led_pwm_channel->cdty = intensity;
317       AVR32_PWM.ena = 1 << led_descriptor->PWM.CHANNEL;
318     }
319     else
320     {
321       AVR32_PWM.isr;
322       while (!(AVR32_PWM.isr & (1 << led_descriptor->PWM.CHANNEL)));
323       led_pwm_channel->cupd = intensity;
324     }
325 
326     // Switch the LED pin to its PWM function.
327     led_gpio_port = &AVR32_GPIO.port[led_descriptor->GPIO.PORT];
328     if (led_descriptor->PWM.FUNCTION & 0x1)
329     {
330       led_gpio_port->pmr0s = led_descriptor->GPIO.PIN_MASK;
331     }
332     else
333     {
334       led_gpio_port->pmr0c = led_descriptor->GPIO.PIN_MASK;
335     }
336     if (led_descriptor->PWM.FUNCTION & 0x2)
337     {
338       led_gpio_port->pmr1s = led_descriptor->GPIO.PIN_MASK;
339     }
340     else
341     {
342       led_gpio_port->pmr1c = led_descriptor->GPIO.PIN_MASK;
343     }
344     led_gpio_port->gperc = led_descriptor->GPIO.PIN_MASK;
345   }
346 }
347