/* chars data is which segments should be lit up when wanting to display a number for example:
* the number 0 needs "ABCDEF" segments to be lit
* the number 1 needs "BC" segments to be lit
* in the array there are two extra entries equating to numbers 10 and 11
* 10 is used for a blank display and 11 is used to display a negative symbol
*/
char chars[12][8] = {"ABCDEF", "BC", "ABDEG", "ABCDG", "BCFG", "ADCFG", "ACDEFG", "ABC", "ABCDEFG", "ABCFG", "X", "G"};
Ouch! :-) Simply make each segment a bit in a byte:
segment A = 0b00000001
segment B = 0b00000010
segment C = 0b00000100
To create a "1" OR the bitmaks:
segment B = 0b00000010
segment C = 0b00000100
"1" = 0b00000110 = 6
And you'll need just a single byte for each number.
Since the port pins don't match the order of the segments we change the bitmasks according to the wiring:
A segments connected to pin: PC1
B segments connected to pin: PC0
C segments connected to pin: PC3
D segments connected to pin: PB4
E segments connected to pin: PB5
F segments connected to pin: PB2
G segments connected to pin: PB3
P segments connected to pin: PC2 (P is decimal point)
We got 2 ports with 4 pins each. Port C is 0-3 and port B is 2-5. So we select following scheme for the bitmasks:
C3 C2 C1 C0 B5 B4 B3 B2
segment B = 0b00010000
segment C = 0b10000000
"1" = 0b1001000 = 72
For displaying a number we extract the segment pattern for each port. So we take the top 4 bits for port C, i.e. shifting the byte 4 times to the right:
output = chars[number] >> 4;
Then write that to the port and go to port B. For port B we take the lower 4 bits and shift them 2 times to the left to match the I/O pins:
output = chars[number] & 0b00001111;
output << 2;
Much better and more efficient, isn't it?