Nut/OS  4.10.3
API Reference
led.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 by Rittal GmbH & Co. KG,
00003  * Ulrich Prinz <prinz.u@rittal.de> All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EMBEDDED IT AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EMBEDDED IT
00022  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 
00056 #include <cfg/os.h>
00057 
00058 #include <compiler.h>
00059 #include <dev/board.h>
00060 #include <dev/gpio.h>
00061 
00062 #include <stdlib.h>
00063 #include <string.h>
00064 #include <sys/heap.h>
00065 #include <sys/event.h>
00066 #include <sys/timer.h>
00067 #include <sys/atom.h>
00068 
00069 #include <sys/nutdebug.h>
00070 
00071 #include <cfg/pca9555.h>
00072 #ifdef LED_SUPPORT_IOEXP
00073 #include <dev/pca9555.h>
00074 #endif
00075 #include "cfg/led.h"
00076 #include "dev/led.h"
00077 
00082 
00083 /* define inverted LED states as LEDs are driven by low side switching */
00084 
00085 #ifdef LED_ON_HIGH
00086 #define LED_IS_ON  1
00087 #define LED_IS_OFF 0
00088 #else
00089 #define LED_IS_ON  0
00090 #define LED_IS_OFF 1
00091 #endif
00092 
00093 typedef struct
00094 {
00095     void         *next;     
00096         uint32_t     timOn;     
00097     uint32_t     timOff;    
00098         uint32_t     tim;           
00099     int          bank;      
00100     int          pin;       
00101         int          state;             
00102     uint_fast8_t fx;        
00103 } LEDEventT;
00104 
00105 /* Pointer to first led registered */
00106 LEDEventT *first_led = NULL;
00107 
00108 /* Timer- and Timer-Event-Handler */
00109 HANDLE led_tmr = NULL;
00110 HANDLE led_evt = NULL;
00111 
00117 int InitLED(LEDEventT *led)
00118 {
00119 #ifdef LED_SUPPORT_IOEXP
00120     if( led->bank >= IOXP_PORT0) {
00121         IOExpPinConfigSet(led->bank, led->pin, GPIO_CFG_OUTPUT);
00122         IOExpSetBitHigh( led->bank, led->pin);
00123         return 0;
00124     }
00125     else
00126 #else
00127     {
00128         GpioPinConfigSet( led->bank, led->pin, GPIO_CFG_OUTPUT);
00129         GpioPinSetHigh( led->bank, led->pin);
00130         return 0;
00131     }
00132 #endif
00133     return -1;
00134 }
00135 
00146 static void LedTimerCb(HANDLE timer, void *arg)
00147 {
00148     NutEventPostAsync( arg);
00149 }
00150 
00164 /****************************************************************************/
00165 THREAD( sys_led, arg)
00166 /****************************************************************************/
00167 {
00168     LEDEventT *led;
00169     uint32_t now, last, dur;
00170 
00171     NUTASSERT( arg != NULL);
00172 
00173     last = NutGetMillis();
00174     NutThreadSetPriority(16);
00175     for(;;) {
00176         if (NutEventWait(arg, NUT_WAIT_INFINITE)==0) {
00177             now = NutGetMillis();
00178             dur = now-last;
00179             last = now;
00180             led = first_led;
00181 
00182             while( led)
00183             {
00184                 switch( led->fx) {
00185                     case LED_ON:
00186                         if( led->timOn > 0) {
00187                             if( led->tim >= dur) led->tim -= dur;
00188                             else
00189                                 NutSetLed( led, LED_OFF, 0, 0);
00190                         }
00191                         break;
00192                     case LED_OFF:
00193                         if( led->timOff > 0) {
00194                             if( led->tim >= dur) led->tim -= dur;
00195                             else
00196                                 NutSetLed( led, LED_ON, 0, 0);
00197                         }
00198                         break;
00199                     case LED_BLINK:
00200                         if( led->tim >= dur) led->tim -= dur;
00201                         else {
00202                             NutSetLed( led, LED_FLIP, 0, 0);
00203                             led->fx = LED_BLINK;
00204                             if( led->state)
00205                                 led->tim = led->timOff;
00206                             else
00207                                 led->tim = led->timOn;
00208                         }
00209                         break;
00210                 }
00211 
00212                 led = led->next;
00213             }
00214         }
00215     }
00216 }
00217 
00228 void NutSetLed( HANDLE ledh, uint_fast8_t fxin, uint32_t timOn, uint32_t timOff)
00229 {
00230     LEDEventT *led = (LEDEventT *)ledh;
00231 
00232     NUTASSERT( ledh != NULL);
00233 
00234     led->fx = fxin;
00235 
00236     switch( fxin) {
00237         case LED_BLINK:
00238             led->state ^= 1;
00239             led->timOn = timOn;
00240             led->timOff = timOff;
00241             if( led->state==LED_IS_ON)
00242                 led->tim = timOff;
00243             else
00244                 led->tim = timOn;
00245             break;
00246         case LED_FLIP:
00247             led->state ^= 1;
00248             break;
00249         case LED_ON:
00250             led->state = LED_IS_ON;
00251             led->timOn = led->tim = timOn;
00252             break;
00253         case LED_OFF:
00254         default:
00255             led->state = LED_IS_OFF;
00256             led->timOff = led->tim = timOff;
00257             break;
00258     }
00259 
00260 #ifdef LED_SUPPORT_IOEXP
00261     if( led->bank < IOXP_PORT0)
00262         GpioPinSet( led->bank, led->pin, led->state);
00263     else
00264         IOExpSetBit( led->bank, led->pin, led->state);
00265 #else
00266         GpioPinSet( led->bank, led->pin, led->state);
00267 #endif
00268 
00269 }
00270 
00288 int NutRegisterLed( HANDLE * ledh, int bank, int pin)
00289 {
00290     LEDEventT *led;
00291 
00292     /* Check memory constraints and assign memory to new led struct */
00293     led = malloc(sizeof( LEDEventT));
00294     *ledh = (void*)led;
00295 
00296     if( led == NULL) {
00297         return -1;
00298     }
00299 
00300     /* Preset new led struct */
00301     memset( led, 0, sizeof( LEDEventT));
00302     led->bank = bank;
00303     led->pin = pin;
00304     led->state = LED_IS_OFF;
00305 
00306     /* Assign the led to the chain */
00307     NutEnterCritical();
00308     if( first_led == NULL) {
00309         /* it is the first led */
00310         first_led = led;
00311     }
00312     else {
00313         /* if not first, put it into the chain at first position */
00314         led->next = first_led;
00315         first_led = led;
00316     }
00317     NutExitCritical();
00318 
00319     /* Start timer for LED effects, but only one timer for all */
00320     if( led_tmr == NULL) {
00321         NutThreadCreate("sys_led", sys_led, &led_evt, 192);
00322         led_tmr = NutTimerStart(10, LedTimerCb, &led_evt, 0);
00323     }
00324 
00325     return InitLED( led);
00326 }
00327