Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Simulating a seven-segment display (http://www.velocityreviews.com/forums/t689694-simulating-a-seven-segment-display.html)

Felipe Ribeiro 07-01-2009 03:11 AM

Simulating a seven-segment display
 
Hi everybody,

I wrote a small program that simulates the effect of a seven-segment
display and would like to know if I can do anything to improve it.
Here's the code:

====================================
#include <stdio.h>

#define MAX_DIGITS 10
#define HEIGHT_DIGIT 3

/* External variables */
/*
* 'segments' stores the seven-segment representaion of each number.
* The representation is done in the following way:
*
* 1__2__3
* | |
* 4 6
* |__5__|
* | |
* 7 9
* |__8__|
*
* '*' determines that a segment is necessary in a given position
while
* ' ' detrmines that no segment should be printed and a blank is
* printed instead.
*/
const char segments[10][9] =
{{' ', '*', ' ', '*', ' ', '*', '*', '*', '*'},
{' ', ' ', ' ', ' ', ' ', '*', ' ', ' ', '*'},
{' ', '*', ' ', ' ', '*', '*', '*', '*', ' '},
{' ', '*', ' ', ' ', '*', '*', ' ', '*', '*'},
{' ', ' ', ' ', '*', '*', '*', ' ', ' ', '*'},
{' ', '*', ' ', '*', '*', ' ', ' ', '*', '*'},
{' ', '*', ' ', '*', '*', ' ', '*', '*', '*'},
{' ', '*', ' ', ' ', ' ', '*', ' ', ' ', '*'},
{' ', '*', ' ', '*', '*', '*', '*', '*', '*'},
{' ', '*', ' ', '*', '*', '*', ' ', '*', '*'}};
/*
* 'digits' will store only the seven-segment representation of the
* digits entered by the user. Each digit is 3 characters high and 3
* characters wide.
*/
char digits[HEIGHT_DIGIT][MAX_DIGITS * 4];

/* Prototypes */
void process_digit(int digit, int position);
void print_digits_array(void);

/*
* Calls 'process_digit' and 'print_digits_array' repeatedly.
*/
int main(void)
{
char digit_ch;
int digit, i = 0;

printf("Enter a number: ");
do {
/*
* The user may enter a non-numerical character but it's gonna
* be ignored.
*/
digit_ch = getchar();
digit = digit_ch - '0';

if (0 <= digit && digit <= 9) {
process_digit(digit, i);
i++;
}
} while (i < MAX_DIGITS && digit_ch != '\n');

print_digits_array();

return 0;
}

/*
* Treats the digit entered by the user. 'digits' will receive the
data
* stored in 'segments' according to the number entered by the user.
* For instance; if the number one is entered, then all the
information
* in row one of the 'segments' array will be passed to the 'digits'
* array.
*/
void process_digit(int digit, int position)
{
int start, end;
int i, j = 0;

start = position * 4;
end = start + 3;
for (i = 0; i < HEIGHT_DIGIT; i++)
for (start = position * 4; start < end; start++) {
digits[i][start] = segments[digit][j];
j++;
}
}

/*
* Surprisingly, it prints the 'digits' array.
*/
void print_digits_array(void)
{
int i, j;

for (i = 0; i < HEIGHT_DIGIT; i++) {
for (j = 0; j < MAX_DIGITS * 4; j++)
if (digits[i][j] == '*' && j % 2 == 0)
printf("|");
else if (digits[i][j] == '*')
printf("_");
else
printf(" ");
printf("\n");
}
}
====================================

I don't know if I chose the best way to do it. Problably not, since
I'm just learning. :)
My segments array specially causes me some doubts. Each row stores
information about a digit and it does so using 9 positions instead of
7. I wasn't able to figure out a way to solve the problem using just 7
segments.

I'd appreciate any advice. :)
Thank in advance.

Felipe

Peter Nilsson 07-01-2009 04:28 AM

Re: Simulating a seven-segment display
 
Felipe Ribeiro <feliper.gra...@gmail.com> wrote:
> I wrote a small program that simulates the effect of a
> seven-segment display and would like to know if I can
> do anything to improve it.
> Here's the code:

<snip>
> * * * * char digit_ch;
> ...
> * * * * * * * * digit_ch = getchar();


There is a FAQ discussing why digit_ch should be an int.
....And why you should check the return value.

> * * * * * * * * digit = digit_ch - '0';

<snip>

You seemed to have over complicated things a little.

% type 7seg.c
#include <stdio.h>

const char seg_row[3][10][3] =
{
{ " _ "," "," _ "," _ "," "," _ "," _ "," _ "," _ "," _ " },
{ "| |"," |"," _|"," _|","|_|","|_ ","|_ "," |","|_|","|_|" },
{ "|_|"," |","|_ "," _|"," |"," _|","|_|"," |","|_|"," _|" }
};

#define countof(x) ((size_t) (sizeof(x) / sizeof *(x)))

int main(int argc, char **argv)
{
size_t r;
const char *s;

if (argc)
while (argv++, --argc)
for (r = 0; r < countof(seg_row); r++, puts(""))
for (s = *argv; *s; s++)
if ('0' <= *s && *s <= '9')
printf("%.*s", (int) countof(seg_row[0][0]),
seg_row[r][*s - '0']);

return 0;
}

% acc 7seg.c -o 7seg.exe

% 7seg 1234567890 "2009/07/01"
_ _ _ _ _ _ _ _
| _| _||_||_ |_ ||_||_|| |
||_ _| | _||_| ||_| _||_|
_ _ _ _ _ _ _
_|| || ||_|| | || | |
|_ |_||_| _||_| ||_| |

%

--
Peter

luserXtrog 07-01-2009 08:47 AM

Re: Simulating a seven-segment display
 
On Jun 30, 10:11*pm, Felipe Ribeiro <feliper.gra...@gmail.com> wrote:
> Hi everybody,
>
> I wrote a small program that simulates the effect of a seven-segment
> display and would like to know if I can do anything to improve it.
> Here's the code:
>


<snipped longish code, though I am one to say so>

> I don't know if I chose the best way to do it. Problably not, since
> I'm just learning. :)
> My segments array specially causes me some doubts. Each row stores
> information about a digit and it does so using 9 positions instead of
> 7. I wasn't able to figure out a way to solve the problem using just 7
> segments.
>
> I'd appreciate any advice. :)
> Thank in advance.


As another nother way, here's my go:

#include <ctype.h>
#include <stdio.h>
int main(int c, char **v) {
for (;c>1; c--, v++) {
/* _
|_|
|_| bits 0-7 :: segs a-g */
int segs[] = { 077, 006, 0133, 0117, 0146, 0155, 0175, 007,
0177, 0147 };
int mask[] = { 01, 0142, 034 };
int lbar = 060;
int rbar = 006;
int und = 0111;
int i;
for (i=0; i < sizeof(mask)/sizeof(*mask) /*3*/; i++) {
int j;
for (j=0; v[1][j]; j++) {
int c;
c = v[1][j];
if (!isdigit(c)) fprintf(stderr, "bogus input\n");
c -= '0';
if (i == 0) {
putchar(' ');
if (segs[c] & mask[i] & und) putchar('_');
else putchar(' ');
putchar(' ');
} else {
if (segs[c] & mask[i] & lbar) putchar('|');
else putchar(' ');
if (segs[c] & mask[i] & und) putchar('_');
else putchar(' ');
if (segs[c] & mask[i] & rbar) putchar('|');
else putchar(' ');
}
}
putchar('\n');
}
}
return 0;
}

After a glance at Peter's output and a skim through the wikipedia
entry, octal seems perfect for this size ascii rendition.
For your bigger dimensions, it might still be straightforward
to pack it into hex numbers.

I wasn't entirely happy with the result once I got to the middle
of the loop. And the error behavior is nothing to write home about.

I plead insomnia.

fwiw

--
lxt

Felipe Ribeiro 07-01-2009 04:26 PM

Re: Simulating a seven-segment display
 
On Jul 1, 5:47*am, luserXtrog <mijo...@yahoo.com> wrote:

<snip>
>
> As another nother way, here's my go:
>
> #include <ctype.h>
> #include <stdio.h>
> int main(int c, char **v) {
> * * for (;c>1; c--, v++) {
> * * * * /* _
> * * * * * |_|
> * * * * * |_| bits 0-7 :: segs a-g */
> * * * * int segs[] = { 077, 006, 0133, 0117, 0146, 0155, 0175, 007,
> 0177, 0147 };
> * * * * int mask[] = { 01, 0142, 034 };
> * * * * int lbar = 060;
> * * * * int rbar = 006;
> * * * * int und = 0111;
> * * * * int i;
> * * * * for (i=0; i < sizeof(mask)/sizeof(*mask) /*3*/; i++) {
> * * * * * * int j;
> * * * * * * for (j=0; v[1][j]; j++) {
> * * * * * * * * int c;
> * * * * * * * * c = v[1][j];
> * * * * * * * * if (!isdigit(c)) fprintf(stderr, "bogus input\n");
> * * * * * * * * c -= '0';
> * * * * * * * * if (i == 0) {
> * * * * * * * * * * putchar(' ');
> * * * * * * * * * * if (segs[c] & mask[i] & und) putchar('_');
> * * * * * * * * * * else putchar(' ');
> * * * * * * * * * * putchar(' ');
> * * * * * * * * } else {
> * * * * * * * * * * if (segs[c] & mask[i] & lbar) putchar('|');
> * * * * * * * * * * else putchar(' ');
> * * * * * * * * * * if (segs[c] & mask[i] & und) putchar('_');
> * * * * * * * * * * else putchar(' ');
> * * * * * * * * * * if (segs[c] & mask[i] & rbar) putchar('|');
> * * * * * * * * * * else putchar(' ');
> * * * * * * * * }
> * * * * * * }
> * * * * * * putchar('\n');
> * * * * }
> * * }
> * * return 0;
>
> }
>

I'm sorry but I can't really understand your program since I haven't
seen pointers yet.

<snip>

As for the way I used to represent the digits, I simply couldn't
figure out a way to store the 'segments' array into 'digits' properly
using just 7 segments.

Peter Nilsson 07-01-2009 11:21 PM

Re: Simulating a seven-segment display
 
Felipe Ribeiro <feliper.gra...@gmail.com> wrote:
> luserXtrog <mijo...@yahoo.com> wrote:
> > As another nother way, here's my go:

<snip>
> I'm sorry but I can't really understand your program
> since I haven't seen pointers yet.
>
> <snip>
>
> As for the way I used to represent the digits, I simply
> couldn't figure out a way to store the 'segments' array
> into 'digits' properly using just 7 segments.


% type 7seg_2.c
#include <stdio.h>

#define countof(x) ((size_t) (sizeof(x) / sizeof *(x)))

typedef unsigned char mask_t;

enum segments
{
S1,
S2, S3,
S4,
S5, S6,
S7, S8,

M1 = 1 << S1,
M2 = 1 << S2,
M3 = 1 << S3,
M4 = 1 << S4,
M5 = 1 << S5,
M6 = 1 << S6,
M7 = 1 << S7,
M8 = 1 << S8
};

struct display_char
{
mask_t mask;
char out;
};

#define BLANK ' '

#if 0
const struct display_char font[3][3] =
{
{ { 0, 0 }, { M1, '_' }, { 0, 0 } },
{ { M2, '|' }, { M4, '_' }, { M3, '|' } },
{ { M5, '|' }, { M7, '_' }, { M6, '|' } }
};
#else
const struct display_char font[5][5] =
{
{ { 0, 0 }, {M1,'_'}, {M1, '_'}, { 0, 0 }, { 0, 0 } },
{ {M2,'|'}, { 0, 0 }, { 0, 0 }, {M3, '|'}, { 0, 0 } },
{ {M2,'|'}, {M4,'_'}, {M4, '_'}, {M3, '|'}, { 0, 0 } },
{ {M5,'|'}, { 0, 0 }, { 0, 0 }, {M6, '|'}, { 0, 0 } },
{ {M5,'|'}, {M7,'_'}, {M7, '_'}, {M6, '|'}, {M8,'.'} }
};
#endif

const mask_t digit[10] =
{
/* 0 */ M1 + M2 + M3 + M5 + M6 + M7,
/* 1 */ M3 + M6 ,
/* 2 */ M1 + M3 + M4 + M5 + M7,
/* 3 */ M1 + M3 + M4 + M6 + M7,
/* 4 */ M2 + M3 + M4 + M6 ,
/* 5 */ M1 + M2 + M4 + M6 + M7,
/* 6 */ M1 + M2 + M4 + M5 + M6 + M7,
/* 7 */ M1 + M3 + M6 ,
/* 8 */ M1 + M2 + M3 + M4 + M5 + M6 + M7,
/* 9 */ M1 + M2 + M3 + M4 + M6 + M7,
};

int main(int argc, char *argv[])
{
int i;
size_t j, r, c;
mask_t m;

for (i = 1; i < argc; i++)
for (r = 0; r < countof(font); r++, puts(""))
for (j = 0; argv[i][j] != 0; j++)
if ('0' <= argv[i][j] && argv[i][j] <= '9')
for (c = 0; c < countof(font[r]); c++)
{
m = digit[argv[i][j] - '0'];
if (argv[i][j + 1] == '.') m |= M8;

if (font[r][c].mask & m)
putchar(font[r][c].out);
else
putchar(BLANK);
}

return 0;
}

% acc 7seg_2.c -o 7seg_2.exe

% 7seg_2.exe 3.14159265 "2009.07.02"
__ __ __ __ __ __
| | | | | | | | | | |
__| | |__| | |__ |__| __| |__ |__
| | | | | | | | | |
__|. | | | __| __| |__ |__| __|
__ __ __ __ __ __ __ __
| | | | | | | | | | | | |
__| | | | | |__| | | | | | __|
| | | | | | | | | | | |
|__ |__| |__| __|.|__| |.|__| |__

%

--
Peter

luserXtrog 07-02-2009 04:22 AM

Re: Simulating a seven-segment display
 
On Jul 1, 11:26*am, Felipe Ribeiro <feliper.gra...@gmail.com> wrote:
> On Jul 1, 5:47*am, luserXtrog <mijo...@yahoo.com> wrote:
>
> <snip>
>
>
>
> > As another nother way, here's my go:

>
> > #include <ctype.h>
> > #include <stdio.h>
> > int main(int c, char **v) {
> > * * for (;c>1; c--, v++) {
> > * * * * /* _
> > * * * * * |_|
> > * * * * * |_| bits 0-7 :: segs a-g */
> > * * * * int segs[] = { 077, 006, 0133, 0117, 0146, 0155, 0175, 007,
> > 0177, 0147 };
> > * * * * int mask[] = { 01, 0142, 034 };
> > * * * * int lbar = 060;
> > * * * * int rbar = 006;
> > * * * * int und = 0111;
> > * * * * int i;
> > * * * * for (i=0; i < sizeof(mask)/sizeof(*mask) /*3*/; i++) {
> > * * * * * * int j;
> > * * * * * * for (j=0; v[1][j]; j++) {
> > * * * * * * * * int c;
> > * * * * * * * * c = v[1][j];
> > * * * * * * * * if (!isdigit(c)) fprintf(stderr, "bogus input\n");
> > * * * * * * * * c -= '0';
> > * * * * * * * * if (i == 0) {
> > * * * * * * * * * * putchar(' ');
> > * * * * * * * * * * if (segs[c] & mask[i] & und) putchar('_');
> > * * * * * * * * * * else putchar(' ');
> > * * * * * * * * * * putchar(' ');
> > * * * * * * * * } else {
> > * * * * * * * * * * if (segs[c] & mask[i] & lbar) putchar('|');
> > * * * * * * * * * * else putchar(' ');
> > * * * * * * * * * * if (segs[c] & mask[i] & und) putchar('_');
> > * * * * * * * * * * else putchar(' ');
> > * * * * * * * * * * if (segs[c] & mask[i] & rbar) putchar('|');
> > * * * * * * * * * * else putchar(' ');
> > * * * * * * * * }
> > * * * * * * }
> > * * * * * * putchar('\n');
> > * * * * }
> > * * }
> > * * return 0;

>
> > }

>
> I'm sorry but I can't really understand your program since I haven't
> seen pointers yet.


I think I'm not using any pointers. Ok, I see it.
sizeof(*mask) is the same as sizeof(mask[0]) or sizeof(int).
That's just to get the number of elements in the mask array
to avoid using constants all over the place (there were enough
of them in the arrays).

It loops over the three elements of mask (which select the bits
from the segs relevant to the three output lines) and within that,
it loops over the string to be displayed. On the first line
it prints space, underscore (if the digit has one), space.
On the other two lines it prints a bar (if the digit has one),
an underscore (if...), and another bar (if...).

To understand the segs array, you have to imagine the template:

_ a . .
..| b f |.. ._. g
..| c e |_. ...
d

where the bits are laid out in ascending order.
So an octal number nicely encodes the abc def g, but backwards
g fed cba. So '0' having abcdef but no g, is 077. '8' is 0177
to add the g. '7' ends up being 07! I obfuscated that to 007
for obvious reasons.

> <snip>
>
> As for the way I used to represent the digits, I simply couldn't
> figure out a way to store the 'segments' array into 'digits' properly
> using just 7 segments


Perhaps because of the size you've chosen. If you have a try
at the smaller sized version, it may help that each segment
only controls one character.

I now think it might be fun to do it by allocating a multi-line
buffer and bitblt the shapes into it.

--
lxt

lovecreatesbeauty@gmail.c0m 07-02-2009 04:24 AM

Re: Simulating a seven-segment display
 
On Jul 1, 12:28 pm, Peter Nilsson <ai...@acay.com.au> wrote:
> const char seg_row[3][10][3] =
> {
> { " _ "," "," _ "," _ "," "," _ "," _ "," _ "," _ "," _ " },
> { "| |"," |"," _|"," _|","|_|","|_ ","|_ "," |","|_|","|_|" },
> { "|_|"," |","|_ "," _|"," |"," _|","|_|"," |","|_|"," _|" }
> };
>


The microsoft c++ compiler doesn't recognise this piece unless it's
changed to this:

const char *seg_row[3][10]

luserXtrog 07-02-2009 04:36 AM

Re: Simulating a seven-segment display
 
On Jul 1, 6:21*pm, Peter Nilsson <ai...@acay.com.au> wrote:
> Felipe Ribeiro <feliper.gra...@gmail.com> wrote:
> > luserXtrog <mijo...@yahoo.com> wrote:
> > > As another nother way, here's my go:

> <snip>
> > I'm sorry but I can't really understand your program
> > since I haven't seen pointers yet.

>
> > <snip>

>
> > As for the way I used to represent the digits, I simply
> > couldn't figure out a way to store the 'segments' array
> > into 'digits' properly using just 7 segments.

>
> * % type 7seg_2.c
> * #include <stdio.h>
>

<cut>

Genius!

--
lxt

lovecreatesbeauty@gmail.c0m 07-02-2009 05:30 AM

Re: Simulating a seven-segment display
 
On Jul 2, 12:24*pm, "lovecreatesbea...@gmail.c0m"
<lovecreatesbea...@gmail.com> wrote:
> On Jul 1, 12:28 pm, Peter Nilsson <ai...@acay.com.au> wrote:
>
> > * const char seg_row[3][10][3] =
> > * {
> > * * { " _ "," * "," _ "," _ "," * "," _ "," _ "," _ "," _ "," _ " },
> > * * { "| |"," *|"," _|"," _|","|_|","|_ ","|_ "," *|","|_|","|_|" },
> > * * { "|_|"," *|","|_ "," _|"," *|"," _|","|_|"," *|","|_|"," _|" }
> > * };

>
> The microsoft c++ compiler doesn't recognise this piece unless it's
> changed to this:
>
> * * const char *seg_row[3][10]


sorry, c++ is off-topic here.

lovecreatesbeauty@gmail.c0m 07-02-2009 09:31 AM

Re: Simulating a seven-segment display
 
On Jul 2, 1:30*pm, "lovecreatesbea...@gmail.c0m"
<lovecreatesbea...@gmail.com> wrote:
> On Jul 2, 12:24*pm, "lovecreatesbea...@gmail.c0m"
>
> <lovecreatesbea...@gmail.com> wrote:
> > On Jul 1, 12:28 pm, Peter Nilsson <ai...@acay.com.au> wrote:

>
> > > * const char seg_row[3][10][3] =
> > > * {
> > > * * { " _ "," * "," _ "," _ "," * "," _ "," _ "," _ "," _ "," _ " },
> > > * * { "| |"," *|"," _|"," _|","|_|","|_ ","|_ "," *|","|_|","|_|" },
> > > * * { "|_|"," *|","|_ "," _|"," *|"," _|","|_|"," *|","|_|"," _|" }
> > > * };

>
> > The microsoft c++ compiler doesn't recognise this piece unless it's
> > changed to this:

>
> > * * const char *seg_row[3][10]

>
> sorry, c++ is off-topic here.


$ cat a.c
/* a.c */

static const char segs[16][7 + 1] =
{
"ABCDEF ", /* 0 */
" BC ", /* 1 */
"AB DE G", /* 2 */
"ABCD G", /* 3 */
" BC FG", /* 4 */
"A CD FG", /* 5 */
"A CDEFG", /* 6 */
"ABC ", /* 7 */
"ABCDEFG", /* 8 */
"ABC FG", /* 9 */
"ABC EFG", /* 0xA */
" CDEFG", /* 0xB */
"A DEF ", /* 0xC */
" BCDE G", /* 0xD */
"A DEFG", /* 0xE */
"A EFG", /* 0xF */
};

void lightup(char seg[5][3], const char c)
{
char i, *p;

if (c >= '0' && c <= '9') i = c - '0';
else if (c >= 'A' && c <= 'Z') i = c - 'A' + 10;
else if (c >= 'a' && c <= 'z') i = c - 'a' + 10;
p = segs[i];
while (*p){
switch(*p++){
case 'A':
seg[0][1] = '_';
break;
case 'B':
seg[1][2] = '|';
break;
case 'C':
seg[3][2] = '|';
break;
case 'D':
seg[4][1] = '_';
break;
case 'E':
seg[3][0] = '|';
break;
case 'F':
seg[1][0] = '|';
break;
case 'G':
seg[2][1] = '_';
break;
}
}
}

void showup(char seg[5][3], int lncnt, int clcnt)
{
int i, j;
for (i = 0; i != lncnt; i++){
for (j = 0; j != clcnt; j++){
printf("%c", seg[i][j]);
}
printf("\n");
}
}

void cleanup(char seg[5][3], int lncnt, int clcnt)
{
int i, j;
for (i = 0; i != lncnt; i++){
for (j = 0; j != clcnt; j++){
seg[i][j] = ' ';
}
}
}

#include <stdio.h>
int main(void)
{
char seg[5][3] =
{
" ",
" ",
" ",
" ",
" "
};

lightup(seg, '8');
showup(seg, 5, 3);
cleanup(seg, 5, 3);
printf("\n");
lightup(seg, 'b');
showup(seg, 5, 3);

return 0;
}
$
$ make && ./a.out 123
make: `a.out' is up to date.
_
| |
_
| |
_


|
_
| |
_
$


All times are GMT. The time now is 10:56 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.