From e655a1568f4499a683026a6ba7b95ddb05e60741 Mon Sep 17 00:00:00 2001 From: lottaviano Date: Fri, 11 Nov 2011 16:58:36 +0000 Subject: [PATCH] Update the SevenSegment display driver. - Fixed a bug in the sevenseg_print() when a lonely dot is printed - Graphic print of a seven segment Digit Signed-off-by: Fabio Bizzi git-svn-id: https://src.develer.com/svnoss/bertos/trunk@5174 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/drv/led_7seg.c | 214 ++++++++++++++++++++++++++++++++++-------- bertos/drv/led_7seg.h | 47 +++++++--- 2 files changed, 209 insertions(+), 52 deletions(-) diff --git a/bertos/drv/led_7seg.c b/bertos/drv/led_7seg.c index d89ef377..96ff16dc 100644 --- a/bertos/drv/led_7seg.c +++ b/bertos/drv/led_7seg.c @@ -55,7 +55,7 @@ static Timer sseg_trefresh; * This is the procedure that prints the seven_seg structure'string to the display. * It prints a single digit at time and does all the checks to a proper display. * It is called by the wrapper function fired by the timer set in the init procedure. - * + * * param SS The void pointer that holds the pointer to the data structure * */ @@ -174,50 +174,125 @@ static void sseg_refresh_wrapper(void *VSS) */ INLINE uint8_t sseg_tabcheck(char source) { + /* If no legal character is recognized return a "space" */ uint8_t hexchar=38; /* Numbers */ - if ((((int)source) > 47) && (((int)source) < 58)) + if ((source > 47) && (source < 58)) hexchar = source-48; else /* Capital Letters */ - if ((((int)source) > 64) && (((int)source) < 91)) + if ((source > 64) && (source < 91)) hexchar = source-53; else /* Letters */ - if ((((int)source) > 96) && (((int)source) < 123)) + if ((source > 96) && (source < 123)) hexchar = source-85; else /* Minus */ - if (((int)source) == 45) + if (source == 45) hexchar = 11; else /* Space */ - if (((int)source) == 32) + if (source == 32) hexchar = 38; else /* Dot */ - if (((int)source) == 46) + if (source == 46) hexchar = 10; return hexchar; } +/* + * FUNCTION: sseg_digitbuild + * + * This function return the hex value of the graphic digit + * from a list of segments (ex. ACDP). + * + * param source The string of segments + */ +INLINE uint8_t sseg_digitbuild(const char *gstring, size_t start, size_t stop) +{ + /* the default "space" char returned if no "legal" segments recognized */ + uint8_t graphdigit = SEGMENT_EMPTY; + size_t x; + + /* Main cicle */ + for (x=start;x<=stop;x++) + { + switch (gstring[x]) + { + case 'A': + case 'a': + SET_SEGMENT(graphdigit, SEGMENT_A); + break; + case 'B': + case 'b': + SET_SEGMENT(graphdigit, SEGMENT_B); + break; + case 'C': + case 'c': + SET_SEGMENT(graphdigit, SEGMENT_C); + break; + case 'D': + case 'd': + SET_SEGMENT(graphdigit, SEGMENT_D); + break; + case 'E': + case 'e': + SET_SEGMENT(graphdigit, SEGMENT_E); + break; + case 'F': + case 'f': + SET_SEGMENT(graphdigit, SEGMENT_F); + break; + case 'G': + case 'g': + SET_SEGMENT(graphdigit, SEGMENT_G); + break; + case 'P': + case 'p': + SET_SEGMENT(graphdigit, SEGMENT_P); + break; + } + } + return graphdigit; +} + /** * \brief Print a string on the display * * This is the procedure that fills the seven_seg structure with the translated - * string to display. It swaps also the structures to display the new text when - * all the data is ready to display. + * string to display. + * + * To print a string simply call the procedure with a text string as the second parameter. + * Unrecognized characters are printed as a space + * + * To print "graphic" digits you have to enter them as a sequence of segments between "<>" + * for example: + * \code + * sevenseg_print(display,"Test Graphic"); + * \endcode + * This example will print "Test Graphic" + * + * This is the segments table: + * \code + * ___ + * F| A |B + * |___| + * | G | + * E|___|C oP + * D + * \endcode * * \param SS Pointer to the SevenSeg structure * \param sstring String to be displayed * - * \return 0 if all went well, -1 if the display is locked, -2 if the string too long. + * \return 0 if all went well, -1 if the display is locked, -2 if the string too long -3 if the string is malformed. */ int sevenseg_print(SevenSeg *SS, const char *sstring) { - size_t string_lenght; - unsigned int x,y,dotnumber; + size_t x,y,string_lenght,dotnumber,graph_digit_num,bracket_num,startgraph,stopgraph; bool dotjump = false; uint8_t hexchar; @@ -229,25 +304,58 @@ int sevenseg_print(SevenSeg *SS, const char *sstring) if (sizeof(&sstring) > (CONFIG_LED_7SEG_STRLEN-(2*CONFIG_LED_7SEG_DIGIT))) return -2; - /* get the string length and set the number of dots in the string to 0 */ + /* get the string length and set the number of dots and graphic in the string to 0 */ string_lenght = strlen(sstring); dotnumber = 0; + graph_digit_num = 0; + bracket_num = 0; - /* check if there are some dots in the string and report the number in dotnumber */ - for (x=0;x<(unsigned int)string_lenght;x++) + /* check if there are some dots an graphics in the string and report the number in dotnumber and graphnumber */ + for (x=0;x 0)) + { + /* If the previuos charachter is not a dot or a space we have a dot that + * has to be considered as a part of a previous character so we have to + * to count it */ + if ((sstring[x-1] != '.') & (sstring[x-1] != ' ')) + dotnumber++; + } + /* If we have a "<" or a ">" we have a graphic char */ + if (sstring[x] == '<') + { + bracket_num++; + x++; + while ((sstring[x] != '>') & (x 0 and is not pair we have a malformed string so exit with error */ + if (bracket_num > 0) + { + if (bracket_num & 1) + return -3; + else + /* Set the number of characters that compose the graphic + * to remove from the string, we subtract the "real" number + * of graphic character to display */ + graph_digit_num-=(bracket_num/2); + } /* If the *REAL* lenght of the string is less or equal than the number of digits */ - if (((int)string_lenght-dotnumber) <= CONFIG_LED_7SEG_DIGIT) + if ((string_lenght-dotnumber-graph_digit_num) <= CONFIG_LED_7SEG_DIGIT) { /* If the *REAL* lenght of the string is less than number of digits */ - if (((int)string_lenght-dotnumber) < CONFIG_LED_7SEG_DIGIT) + if ((string_lenght-dotnumber-graph_digit_num) < CONFIG_LED_7SEG_DIGIT) { /* Fill the left side of the string with blanks */ - for (x=0; x<(CONFIG_LED_7SEG_DIGIT-((int)string_lenght-dotnumber)); x++) + for (x=0; x<(CONFIG_LED_7SEG_DIGIT-(string_lenght-dotnumber-graph_digit_num)); x++) SS->string[x] = segstable[38]; y = x; } @@ -268,39 +376,63 @@ int sevenseg_print(SevenSeg *SS, const char *sstring) } /* Here we start to fill the string with the Hex 7seg characters values */ hexchar = 0; - for (x=0; x<(unsigned int)string_lenght; x++) + for (x=0; x 0) + x++; + /* set the first character of the graphic "string" to be passed to sseg_digitbuild */ + startgraph = x; + /* if we have an empty graphic char we return an error */ + if (sstring[x] == '>') + return -3; + while (sstring[x] != '>') + x++; + /* set the last character of the graphic "string" to be passed to sseg_digitbuild */ + stopgraph = x-1; + /* if we have a graphic char bigger than 8 (all the segments of the digit) we return an error */ + if (stopgraph-startgraph > 7) + return -3; + /* fill the destination string with the graphic digit returned by sseg_digitbuild */ + SS->string[y] = sseg_digitbuild(sstring,startgraph,stopgraph); + /* set next digit */ + y++; + } + else + { + hexchar = sseg_tabcheck(sstring[x]); + /* do we have a dot? */ + if (hexchar == 10) { + /* If we are at the first character of the string it has to be forced + * as "lonly" dot ;) */ + if ((x > 0) & ((sstring[x-1] != '.') & (sstring[x-1] != ' '))) + { #if CONFIG_LED_7SEG_CCAT - SS->string[y-1] = SS->string[y-1] | segstable[(int)hexchar]; + SS->string[y-1] = SS->string[y-1] | segstable[hexchar]; #else - SS->string[y-1] = SS->string[y-1] & segstable[(int)hexchar]; + SS->string[y-1] = SS->string[y-1] & segstable[hexchar]; #endif - dotjump = true; + dotjump = true; + } + } + /* If the last character was a dot and we aren't at the first character of the string + * we have just inserted it */ + if (dotjump) + dotjump = false; + /* Let's put the character in the structure's string */ + else + { + SS->string[y] = segstable[hexchar]; + y++; } - } - /* If the last character was a dot and we aren't at the first character of the string - * we have just inserted it */ - if (dotjump) - dotjump = false; - /* Let's put the character in the structure's string */ - else - { - SS->string[y] = segstable[(int)hexchar]; - y++; } } /* If we have the string length bigger than the display we need to fill * the entire right side of the string with blanks to end the scroll * to the rigthest side of the display */ - if (((int)string_lenght-dotnumber) > CONFIG_LED_7SEG_DIGIT) + if ((string_lenght-dotnumber-graph_digit_num) > CONFIG_LED_7SEG_DIGIT) { for (x=0; x #include -/** - * \name Numbers and Letters Table. - * \note These tables contain all the printable - * characters on a 7 segment digit encoded - * for common cathode and common anode - * display type. +/* + * Numbers and Letters Table + * Segments definitions + * Segments macro + * + * These tables contain all the printable + * characters on a 7 segment digit encoded + * for common cathode and common anode + * display type. * * 0, 1, 2, 3, 4, 5, 6, 7, 8, * 9, ., -, A, B, C, D, E, F, @@ -107,7 +109,11 @@ * P, Q, R, S, T, U, V, W, X, * Y, Z, SPACE * - * \{ + * Follows the Segments definitions for the + * graphic digits routines and the macro that + * set the graphic digit with the appropriate + * segment. + * */ #if CONFIG_LED_7SEG_CCAT static const uint8_t segstable[] = @@ -118,6 +124,16 @@ 0x73, 0x67, 0x50, 0x6d, 0x78, 0x3e, 0x2a, 0x6a, 0x76, 0x6e, 0x5b, 0x0 }; + #define SEGMENT_EMPTY (0x00) + #define SEGMENT_A (0x01) + #define SEGMENT_B (0x02) + #define SEGMENT_C (0x04) + #define SEGMENT_D (0x08) + #define SEGMENT_E (0x10) + #define SEGMENT_F (0x20) + #define SEGMENT_G (0x40) + #define SEGMENT_P (0x80) + #define SET_SEGMENT(var, segment) (var |= segment) #else static const uint8_t segstable[] = { @@ -127,8 +143,17 @@ 0x8c, 0x98, 0xaf, 0x92, 0x87, 0xc1, 0xd5, 0x95, 0x89, 0x91, 0xa4, 0xff }; + #define SEGMENT_EMPTY (0xFF) + #define SEGMENT_A (0xFE) + #define SEGMENT_B (0xFD) + #define SEGMENT_C (0xFB) + #define SEGMENT_D (0xF7) + #define SEGMENT_E (0xEF) + #define SEGMENT_F (0xDF) + #define SEGMENT_G (0xBF) + #define SEGMENT_P (0x7F) + #define SET_SEGMENT(var, segment) (var &= segment) #endif -/**\} */ /** * Context data for Display functions -- 2.25.1