BeRTOS
led_7seg.c
Go to the documentation of this file.
00001 
00041 #include "drv/led_7seg.h"
00042 #include "hw/hw_led_7seg.h"
00043 #include "cfg/cfg_arch.h"
00044 #include <drv/timer.h>
00045 #include <string.h>
00046 
00047 /*
00048  * Define the timer for the refreshing
00049  */
00050 static Timer sseg_trefresh;
00051 
00052 /*
00053  * FUNCTION: sseg_refresh
00054  *
00055  * This is the procedure that prints the seven_seg structure'string to the display.
00056  * It prints a single digit at time and does all the checks to a proper display.
00057  * It is called by the wrapper function fired by the timer set in the init procedure.
00058  * 
00059  * param SS The void pointer that holds the pointer to the data structure
00060  *
00061  */
00062 static void sseg_refresh(SevenSeg *SS)
00063 {
00064     /* First Check if the structure is being edited we do a silent exit*/
00065     if (SS->busyedit == true)
00066         return;
00067 
00068     /* If we have displayed all the digits */
00069     if (SS->curdigit == CONFIG_LED_7SEG_DIGIT)
00070     {
00071         sseg_off();
00072         /* And if we have to display again all the digit */
00073         if (SS->curspeed > 0)
00074         {
00075             SS->curspeed--;
00076             SS->curdigit = 0;
00077             SS->curpos -= CONFIG_LED_7SEG_DIGIT;
00078         }
00079         /* Else is time to scroll the text */
00080         else
00081         {
00082             /* If we aren't at the end of the string */
00083             if (SS->curpos < SS->string_len)
00084             {
00085                 SS->curpos -= CONFIG_LED_7SEG_DIGIT;
00086                 SS->curpos++;
00087                 SS->curdigit = 0;
00088                 SS->curspeed = SS->speed;
00089             }
00090             /* Else we are at the end of the string */
00091             else
00092             {
00093                 /* Set that the string was displayed at least one time and we can accept a new text*/
00094                 SS->firstrun = false;
00095                 /* If the string has to be displayed only one time we set an empty string
00096                  * to display till next print request*/
00097                 if (SS->runonce == true)
00098                     sevenseg_clear(SS);
00099                 /* Else we reset the text to it's first character ad do again the display */
00100                 else
00101                 {
00102                     SS->curdigit = 0;
00103                     SS->curpos = 0;
00104                     SS->curspeed = SS->speed;
00105                 }
00106             }
00107         }
00108     }
00109     /* Else We have to do a print*/
00110     else
00111     {
00112         /* If the text doesn't have to blink we write the character to the proper disply's digit */
00113         if (SS->blink == false)
00114             sseg_on(SS->string[SS->curpos], SS->curdigit);
00115         /* Else we do the blinking */
00116         else
00117         {
00118             /* If bdigit == 0 we have to blink all the digits */
00119             if (SS->bdigit == 0)
00120             {
00121                 if (SS->curspeed >= (SS->speed/2))
00122                     sseg_on(SS->string[SS->curpos], SS->curdigit);
00123                 else
00124                     sseg_off();
00125             }
00126             /* else we have to blink only one digit (bdigit -1) */
00127             else
00128                 /* is this the digit to blink? */
00129                 if (SS->curdigit == ((unsigned int)SS->bdigit-1))
00130                 {
00131                     if (SS->curspeed >= (SS->speed/2))
00132                         sseg_on(SS->string[SS->curpos], SS->curdigit);
00133                     else
00134                         sseg_off();
00135                 }
00136                 /* no, so let do a normal print */
00137                 else
00138                     sseg_on(SS->string[SS->curpos], SS->curdigit);
00139         }
00140         /* Ok, next time next char.... ;) */
00141         SS->curdigit++;
00142         SS->curpos++;
00143     }
00144 }
00145 
00146 /*
00147  * FUNCTION: sseg_refresh_wrapper
00148  *
00149  * This is a "wrapper" procedure that is called by the timer_setSoftint()
00150  * with the unique purpose to call the real sseg_refresh procedure without
00151  * the cast of the structure from void to SevenSeg.
00152  *
00153  * param VSS The void pointer that holds the pointer to the data structure
00154  *
00155  */
00156 static void sseg_refresh_wrapper(void *VSS)
00157 {
00158     /* Here we cast the Structure from void to proper type */
00159     SevenSeg *SS;
00160     SS = (SevenSeg *)VSS;
00161     /* now we call the right refresh routine */
00162     sseg_refresh(SS);
00163     /* ReStart the timer */
00164     timer_add(&sseg_trefresh);
00165 }
00166 
00167 /*
00168  * FUNCTION: sseg_tabcheck
00169  *
00170  * This function return the position of the ascii character in the hex
00171  * segstable.
00172  *
00173  * param source The ascii char to be positioned
00174  */
00175 INLINE uint8_t sseg_tabcheck(char source)
00176 {
00177     uint8_t hexchar=38;
00178 
00179     /* Numbers */
00180     if ((((int)source) > 47) && (((int)source) < 58))
00181         hexchar = source-48;
00182     else
00183         /* Capital Letters */
00184         if ((((int)source) > 64) && (((int)source) < 91))
00185             hexchar = source-53;
00186         else
00187             /* Letters */
00188             if ((((int)source) > 96) && (((int)source) < 123))
00189                 hexchar = source-85;
00190             else
00191                 /* Minus */
00192                 if (((int)source) == 45)
00193                     hexchar = 11;
00194                 else
00195                     /* Space */
00196                     if (((int)source) == 32)
00197                         hexchar = 38;
00198                     else
00199                         /* Dot */
00200                         if (((int)source) == 46)
00201                             hexchar = 10;
00202     return hexchar;
00203 }
00204 
00217 int sevenseg_print(SevenSeg *SS, const char *sstring)
00218 {
00219     size_t string_lenght;
00220     unsigned int x,y,dotnumber;
00221     bool dotjump = false;
00222     uint8_t hexchar;
00223 
00224     /* Check if the display is unlocked */
00225     if (SS->busyedit == false)
00226         return -1;
00227 
00228     /* Check if the string is too big */
00229     if (sizeof(&sstring) > (CONFIG_LED_7SEG_STRLEN-(2*CONFIG_LED_7SEG_DIGIT)))
00230         return -2;
00231 
00232     /* get the string length and set the number of dots in the string to 0 */
00233     string_lenght = strlen(sstring);
00234     dotnumber = 0;
00235 
00236     /* check if there are some dots in the string and report the number in dotnumber */
00237     for (x=0;x<(unsigned int)string_lenght;x++)
00238     {
00239         if (((int)sstring[x]) == 46)
00240             dotnumber++;
00241     }
00242 
00243     /* If the *REAL* lenght of the string is less or equal than the number of digits */
00244     if (((int)string_lenght-dotnumber) <= CONFIG_LED_7SEG_DIGIT)
00245     {
00246         /* If the *REAL* lenght of the string is less than number of digits */
00247         if (((int)string_lenght-dotnumber) < CONFIG_LED_7SEG_DIGIT)
00248         {
00249             /* Fill the left side of the string with blanks */
00250             for (x=0; x<(CONFIG_LED_7SEG_DIGIT-((int)string_lenght-dotnumber)); x++)
00251                 SS->string[x] = segstable[38];
00252             y = x;
00253         }
00254         else
00255         {
00256             /* Else we have the exact string length of the display */
00257             y = 0;
00258         }
00259     }
00260     else
00261     {
00262         /* Else we have the string length bigger than the display and we need to fill
00263          * the entire left side of the string with blanks to begin the scroll from the
00264          * rigthest side of the display */
00265         for (x=0; x<CONFIG_LED_7SEG_DIGIT; x++)
00266             SS->string[x] = segstable[38];
00267         y = CONFIG_LED_7SEG_DIGIT;
00268     }
00269     /* Here we start to fill the string with the Hex 7seg characters values */
00270     hexchar = 0;
00271     for (x=0; x<(unsigned int)string_lenght; x++)
00272     {
00273         hexchar = sseg_tabcheck(sstring[x]);
00274         /* do we have a dot? */
00275         if (hexchar == 10)
00276         {
00277             /* If we are at the first character of the string it has to be forced
00278              * as "lonly" dot ;) */
00279             if (x > 0)
00280             {
00281 #if CONFIG_LED_7SEG_CCAT
00282                 SS->string[y-1] = SS->string[y-1] | segstable[(int)hexchar];
00283 #else
00284                 SS->string[y-1] = SS->string[y-1] & segstable[(int)hexchar];
00285 #endif
00286                 dotjump = true;
00287             }
00288         }
00289         /* If the last character was a dot and we aren't at the first character of the string
00290          * we have just inserted it */
00291         if (dotjump)
00292             dotjump = false;
00293         /* Let's put the character in the structure's string */
00294         else
00295         {
00296             SS->string[y] = segstable[(int)hexchar];
00297             y++;
00298         }
00299     }
00300     /* If we have the string length bigger than the display we need to fill
00301      * the entire right side of the string with blanks to end the scroll
00302      * to the rigthest side of the display */
00303     if (((int)string_lenght-dotnumber) > CONFIG_LED_7SEG_DIGIT)
00304     {
00305         for (x=0; x<CONFIG_LED_7SEG_DIGIT; x++)
00306         {
00307             SS->string[y] = segstable[38];
00308             y++;
00309         }
00310     }
00311     /* Let's put the total string length to the structure */
00312     SS->string_len = y;
00313 
00314     return 0;
00315 }
00316 
00325 void sevenseg_init(SevenSeg *SS)
00326 {
00327     /*
00328      * Init the 7segments string structure
00329      */
00330     SS->busyedit = true;
00331     sevenseg_clear(SS);
00332     SS->busyedit = false;
00333 
00334     /*
00335      * Init the I/O ports and set the display OFF
00336      */
00337     sseg_init();
00338 
00339     /*
00340      * Define the timer for the refresh of the display
00341      * The timer calls the sevenseg_refresh function
00342      * every "CONFIG_LED_7SEG_RTIME" milliseconds for
00343      * an acceptable persistance of a single 7 segments
00344      * display.
00345      */
00346     // set the callback
00347     timer_setSoftint(&sseg_trefresh, sseg_refresh_wrapper, (void *)SS);
00348     // expire time: 1s
00349     timer_setDelay(&sseg_trefresh, ms_to_ticks(CONFIG_LED_7SEG_RTIME));
00350     // start the timer
00351     timer_add(&sseg_trefresh);
00352 }
00353 
00364 bool sevenseg_isReady(SevenSeg *SS)
00365 {
00366         return !SS->firstrun;
00367 }
00368 
00379 bool sevenseg_unlock(SevenSeg *SS)
00380 {
00381     if (SS->firstrun == false)
00382     {
00383         SS->busyedit = true;
00384         SS->firstrun = true;
00385         SS->curdigit = 0;
00386         SS->curpos = 0;
00387     }
00388     else
00389         return false;
00390     return true;
00391 }
00392 
00403 bool sevenseg_lock(SevenSeg *SS)
00404 {
00405     if (SS->busyedit == true)
00406     {
00407     /* If the string is longer than the number of the digit of the display we
00408      * reset the single digit blink to zero to be sure that the display of
00409      * the text is clean from previous single digit blinking settings */
00410         if (SS->string_len > CONFIG_LED_7SEG_DIGIT)
00411             SS->bdigit = 0;
00412         SS->busyedit = false;
00413     }
00414     else
00415         return false;
00416     return true;
00417 }
00418 
00432 bool sevenseg_setBlink(SevenSeg *SS, bool blink, uint8_t digit)
00433 {
00434     if (SS->busyedit == true)
00435     {
00436         if (blink == true)
00437         {
00438             if (digit == 0)
00439                 SS->bdigit = digit;
00440             else
00441                 if ((digit-1) <= CONFIG_LED_7SEG_DIGIT)
00442                     SS->bdigit = digit;
00443                 else
00444                     return false;
00445         }
00446         SS->blink = blink;
00447     }
00448     else
00449         return false;
00450     return true;
00451 }
00452 
00464 bool sevenseg_setRunonce(SevenSeg *SS, bool runonce)
00465 {
00466     if (SS->busyedit == true)
00467         SS->runonce = runonce;
00468     else
00469         return false;
00470     return true;
00471 }
00472 
00486 bool sevenseg_setRunspeed(SevenSeg *SS, unsigned int r_speed)
00487 {
00488     if (SS->busyedit == true)
00489     {
00490         SS->speed = r_speed;
00491         SS->curspeed = r_speed;
00492     }
00493     else
00494         return false;
00495     return true;
00496 }
00497 
00508 bool sevenseg_clear(SevenSeg *SS)
00509 {
00510     if (SS->busyedit == true)
00511     {
00512         memset(((void *)&SS->string),segstable[38],sizeof(SS->string));
00513         SS->string_len = CONFIG_LED_7SEG_DIGIT;
00514         SS->blink = false;
00515         SS->bdigit = 0;
00516         SS->runonce = false;
00517         SS->curdigit = 0;
00518         SS->curpos = 0;
00519         SS->speed = CONFIG_LED_7SEG_SSPEED;
00520         SS->curspeed = CONFIG_LED_7SEG_SSPEED;
00521         SS->firstrun = false;
00522     }
00523     else
00524         return false;
00525     return true;
00526 } //defgroup drivers