* 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
*
*/
*/
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,"<bf>Test Graphic<bf>");
+ * \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;
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<string_lenght;x++)
{
- if (((int)sstring[x]) == 46)
- dotnumber++;
+ /* If the first char is a "lonely" dot it has to be counted as a character */
+ if ((sstring[x] == '.') & (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<string_lenght))
+ {
+ x++;
+ graph_digit_num++;
+ }
+ bracket_num++;
+ }
}
+ graph_digit_num+=bracket_num;
+ /* if graphoc is > 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;
}
}
/* 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<string_lenght; x++)
{
- hexchar = sseg_tabcheck(sstring[x]);
- /* do we have a dot? */
- if (hexchar == 10)
+ /* check if the charcter is a graphic character delimiter */
+ if (sstring[x] == '<')
{
- /* If we are at the first character of the string it has to be forced
- * as "lonly" dot ;) */
- if (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<CONFIG_LED_7SEG_DIGIT; x++)
{
* \ingroup drivers
* \{
*
- * \brief 7 segments LED displays (headers)
+ * \brief 7 segments LED displays Driver
*
* Here you find the prototypes and the data structures that
* format and holds the text that has to be displayed by the
* static Seven_Seg display;
* // ...
* sevenseg_init(&display);
- * while (!sevenseg_isReady(&display))
- * ;
+ * while (!sevenseg_isReady(&display));
* sevenseg_unlock(&display);
* sevenseg_setBlink(&display,false,0);
* sevenseg_setRunonce(&display,false);
#include <drv/timer.h>
#include <mware/event.h>
-/**
- * \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,
* 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[] =
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[] =
{
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