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
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)