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     /* If no legal character is recognized return a "space" */
00178     uint8_t hexchar=38;
00179
00180     /* Numbers */
00181     if ((source > 47) && (source < 58))
00182         hexchar = source-48;
00183     else
00184         /* Capital Letters */
00185         if ((source > 64) && (source < 91))
00186             hexchar = source-53;
00187         else
00188             /* Letters */
00189             if ((source > 96) && (source < 123))
00190                 hexchar = source-85;
00191             else
00192                 /* Minus */
00193                 if (source == 45)
00194                     hexchar = 11;
00195                 else
00196                     /* Space */
00197                     if (source == 32)
00198                         hexchar = 38;
00199                     else
00200                         /* Dot */
00201                         if (source == 46)
00202                             hexchar = 10;
00203     return hexchar;
00204 }
00205
00206 /*
00207  * FUNCTION: sseg_digitbuild
00208  *
00209  * This function return the hex value of the graphic digit
00210  * from a list of segments (ex. ACDP).
00211  *
00212  * param source The string of segments
00213  */
00214 INLINE uint8_t sseg_digitbuild(const char *gstring, size_t start, size_t stop)
00215 {
00216     /* the default "space" char returned if no "legal" segments recognized */
00217     uint8_t graphdigit = SEGMENT_EMPTY;
00218     size_t x;
00219
00220     /* Main cicle */
00221     for (x=start;x<=stop;x++)
00222     {
00223         switch (gstring[x])
00224         {
00225             case 'A':
00226             case 'a':
00227                         SET_SEGMENT(graphdigit, SEGMENT_A);
00228                         break;
00229             case 'B':
00230             case 'b':
00231                         SET_SEGMENT(graphdigit, SEGMENT_B);
00232                         break;
00233             case 'C':
00234             case 'c':
00235                         SET_SEGMENT(graphdigit, SEGMENT_C);
00236                         break;
00237             case 'D':
00238             case 'd':
00239                         SET_SEGMENT(graphdigit, SEGMENT_D);
00240                         break;
00241             case 'E':
00242             case 'e':
00243                         SET_SEGMENT(graphdigit, SEGMENT_E);
00244                         break;
00245             case 'F':
00246             case 'f':
00247                         SET_SEGMENT(graphdigit, SEGMENT_F);
00248                         break;
00249             case 'G':
00250             case 'g':
00251                         SET_SEGMENT(graphdigit, SEGMENT_G);
00252                         break;
00253             case 'P':
00254             case 'p':
00255                         SET_SEGMENT(graphdigit, SEGMENT_P);
00256                         break;
00257         }
00258     }
00259     return graphdigit;
00260 }
00261
00293 int sevenseg_print(SevenSeg *SS, const char *sstring)
00294 {
00295     size_t x,y,string_lenght,dotnumber,graph_digit_num,bracket_num,startgraph,stopgraph;
00296     bool dotjump = false;
00297     uint8_t hexchar;
00298
00299     /* Check if the display is unlocked */
00300     if (SS->busyedit == false)
00301         return -1;
00302
00303     /* Check if the string is too big */
00304     if (sizeof(&sstring) > (CONFIG_LED_7SEG_STRLEN-(2*CONFIG_LED_7SEG_DIGIT)))
00305         return -2;
00306
00307     /* get the string length and set the number of dots and graphic in the string to 0 */
00308     string_lenght = strlen(sstring);
00309     dotnumber = 0;
00310     graph_digit_num = 0;
00311     bracket_num = 0;
00312
00313     /* check if there are some dots an graphics in the string and report the number in dotnumber and graphnumber */
00314     for (x=0;x<string_lenght;x++)
00315     {
00316         /* If the first char is a "lonely" dot it has to be counted as a character */
00317         if ((sstring[x] == '.') & (x > 0))
00318         {
00319             /* If the previuos charachter is not a dot or a space we have a dot that
00320              * has to be considered as a part of a previous character so we have to
00321              * to count it */
00322             if ((sstring[x-1] != '.') & (sstring[x-1] != ' '))
00323                 dotnumber++;
00324         }
00325         /* If we have a "<" or a ">" we have a graphic char */
00326         if (sstring[x] == '<')
00327         {
00328             bracket_num++;
00329             x++;
00330             while ((sstring[x] != '>') & (x<string_lenght))
00331             {
00332                 x++;
00333                 graph_digit_num++;
00334             }
00335                 bracket_num++;
00336         }
00337     }
00338     graph_digit_num+=bracket_num;
00339     /* if graphoc is > 0 and is not pair we have a malformed string so exit with error */
00340         if (bracket_num > 0)
00341         {
00342             if (bracket_num & 1)
00343                 return -3;
00344             else
00345                 /* Set the number of characters that compose the graphic
00346                  * to remove from the string, we subtract the "real" number
00347                  * of graphic character to display */
00348                 graph_digit_num-=(bracket_num/2);
00349         }
00350
00351     /* If the *REAL* lenght of the string is less or equal than the number of digits */
00352     if ((string_lenght-dotnumber-graph_digit_num) <= CONFIG_LED_7SEG_DIGIT)
00353     {
00354         /* If the *REAL* lenght of the string is less than number of digits */
00355         if ((string_lenght-dotnumber-graph_digit_num) < CONFIG_LED_7SEG_DIGIT)
00356         {
00357             /* Fill the left side of the string with blanks */
00358             for (x=0; x<(CONFIG_LED_7SEG_DIGIT-(string_lenght-dotnumber-graph_digit_num)); x++)
00359                 SS->string[x] = segstable[38];
00360             y = x;
00361         }
00362         else
00363         {
00364             /* Else we have the exact string length of the display */
00365             y = 0;
00366         }
00367     }
00368     else
00369     {
00370         /* Else we have the string length bigger than the display and we need to fill
00371          * the entire left side of the string with blanks to begin the scroll from the
00372          * rigthest side of the display */
00373         for (x=0; x<CONFIG_LED_7SEG_DIGIT; x++)
00374             SS->string[x] = segstable[38];
00375         y = CONFIG_LED_7SEG_DIGIT;
00376     }
00377     /* Here we start to fill the string with the Hex 7seg characters values */
00378     hexchar = 0;
00379     for (x=0; x<string_lenght; x++)
00380     {
00381         /* check if the charcter is a graphic character delimiter */
00382         if (sstring[x] == '<')
00383         {
00384             x++;
00385             /* set the first character of the graphic "string" to be passed to sseg_digitbuild */
00386             startgraph = x;
00387             /* if we have an empty graphic char we return an error */
00388             if (sstring[x] == '>')
00389                 return -3;
00390             while (sstring[x] != '>')
00391                 x++;
00392             /* set the last character of the graphic "string" to be passed to sseg_digitbuild */
00393             stopgraph = x-1;
00394             /* if we have a graphic char bigger than 8 (all the segments of the digit) we return an error */
00395             if (stopgraph-startgraph > 7)
00396                 return -3;
00397             /* fill the destination string with the graphic digit returned by sseg_digitbuild */
00398             SS->string[y] = sseg_digitbuild(sstring,startgraph,stopgraph);
00399             /* set next digit */
00400             y++;
00401         }
00402         else
00403         {
00404             hexchar = sseg_tabcheck(sstring[x]);
00405             /* do we have a dot? */
00406             if (hexchar == 10)
00407             {
00408                 /* If we are at the first character of the string it has to be forced
00409                 * as "lonly" dot ;) */
00410                 if ((x > 0) & ((sstring[x-1] != '.') & (sstring[x-1] != ' ')))
00411                 {
00412 #if CONFIG_LED_7SEG_CCAT
00413                     SS->string[y-1] = SS->string[y-1] | segstable[hexchar];
00414 #else
00415                     SS->string[y-1] = SS->string[y-1] & segstable[hexchar];
00416 #endif
00417                     dotjump = true;
00418                 }
00419             }
00420             /* If the last character was a dot and we aren't at the first character of the string
00421             * we have just inserted it */
00422             if (dotjump)
00423                 dotjump = false;
00424             /* Let's put the character in the structure's string */
00425             else
00426             {
00427                 SS->string[y] = segstable[hexchar];
00428                 y++;
00429             }
00430         }
00431     }
00432     /* If we have the string length bigger than the display we need to fill
00433      * the entire right side of the string with blanks to end the scroll
00434      * to the rigthest side of the display */
00435     if ((string_lenght-dotnumber-graph_digit_num) > CONFIG_LED_7SEG_DIGIT)
00436     {
00437         for (x=0; x<CONFIG_LED_7SEG_DIGIT; x++)
00438         {
00439             SS->string[y] = segstable[38];
00440             y++;
00441         }
00442     }
00443     /* Let's put the total string length to the structure */
00444     SS->string_len = y;
00445
00446     return 0;
00447 }
00448
00457 void sevenseg_init(SevenSeg *SS)
00458 {
00459     /*
00460      * Init the 7segments string structure
00461      */
00462     SS->busyedit = true;
00463     sevenseg_clear(SS);
00464     SS->busyedit = false;
00465
00466     /*
00467      * Init the I/O ports and set the display OFF
00468      */
00469     sseg_init();
00470
00471     /*
00472      * Define the timer for the refresh of the display
00473      * The timer calls the sevenseg_refresh function
00474      * every "CONFIG_LED_7SEG_RTIME" milliseconds for
00475      * an acceptable persistance of a single 7 segments
00476      * display.
00477      */
00478     // set the callback
00479     timer_setSoftint(&sseg_trefresh, sseg_refresh_wrapper, (void *)SS);
00480     // expire time: 1s
00481     timer_setDelay(&sseg_trefresh, ms_to_ticks(CONFIG_LED_7SEG_RTIME));
00482     // start the timer
00483     timer_add(&sseg_trefresh);
00484 }
00485
00496 bool sevenseg_isReady(SevenSeg *SS)
00497 {
00498         return !SS->firstrun;
00499 }
00500
00511 bool sevenseg_unlock(SevenSeg *SS)
00512 {
00513     if (SS->firstrun == false)
00514     {
00515         SS->busyedit = true;
00516         SS->firstrun = true;
00517         SS->curdigit = 0;
00518         SS->curpos = 0;
00519     }
00520     else
00521         return false;
00522     return true;
00523 }
00524
00535 bool sevenseg_lock(SevenSeg *SS)
00536 {
00537     if (SS->busyedit == true)
00538     {
00539     /* If the string is longer than the number of the digit of the display we
00540      * reset the single digit blink to zero to be sure that the display of
00541      * the text is clean from previous single digit blinking settings */
00542         if (SS->string_len > CONFIG_LED_7SEG_DIGIT)
00543             SS->bdigit = 0;
00544         SS->busyedit = false;
00545     }
00546     else
00547         return false;
00548     return true;
00549 }
00550
00564 bool sevenseg_setBlink(SevenSeg *SS, bool blink, uint8_t digit)
00565 {
00566     if (SS->busyedit == true)
00567     {
00568         if (blink == true)
00569         {
00570             if (digit == 0)
00571                 SS->bdigit = digit;
00572             else
00573                 if ((digit-1) <= CONFIG_LED_7SEG_DIGIT)
00574                     SS->bdigit = digit;
00575                 else
00576                     return false;
00577         }
00578         SS->blink = blink;
00579     }
00580     else
00581         return false;
00582     return true;
00583 }
00584
00596 bool sevenseg_setRunonce(SevenSeg *SS, bool runonce)
00597 {
00598     if (SS->busyedit == true)
00599         SS->runonce = runonce;
00600     else
00601         return false;
00602     return true;
00603 }
00604
00618 bool sevenseg_setRunspeed(SevenSeg *SS, unsigned int r_speed)
00619 {
00620     if (SS->busyedit == true)
00621     {
00622         SS->speed = r_speed;
00623         SS->curspeed = r_speed;
00624     }
00625     else
00626         return false;
00627     return true;
00628 }
00629
00640 bool sevenseg_clear(SevenSeg *SS)
00641 {
00642     if (SS->busyedit == true)
00643     {
00644         memset(((void *)&SS->string),segstable[38],sizeof(SS->string));
00645         SS->string_len = CONFIG_LED_7SEG_DIGIT;
00646         SS->blink = false;
00647         SS->bdigit = 0;
00648         SS->runonce = false;
00649         SS->curdigit = 0;
00650         SS->curpos = 0;
00651         SS->speed = CONFIG_LED_7SEG_SSPEED;
00652         SS->curspeed = CONFIG_LED_7SEG_SSPEED;
00653         SS->firstrun = false;
00654     }
00655     else
00656         return false;
00657     return true;
00658 } //defgroup drivers