I have a board with a 7-segment display controlled by an AVR. I need to rotate the display's characters in the firmware, so that the display is read correctly when physically rotated 180 degrees.
Currently, the display has an output defined by:
#define SEVEN_SEGMENT_PATTERN_0 0x7B
#define SEVEN_SEGMENT_PATTERN_1 0x09
#define SEVEN_SEGMENT_PATTERN_2 0xB3
#define SEVEN_SEGMENT_PATTERN_3 0x9B
#define SEVEN_SEGMENT_PATTERN_4 0xC9
#define SEVEN_SEGMENT_PATTERN_5 0xDA
#define SEVEN_SEGMENT_PATTERN_6 0xFa
#define SEVEN_SEGMENT_PATTERN_7 0x0B
#define SEVEN_SEGMENT_PATTERN_8 0xFB
#define SEVEN_SEGMENT_PATTERN_9 0xDB
#define SEVEN_SEGMENT_PATTERN_A 0xEB
#define SEVEN_SEGMENT_PATTERN_B 0xF8
#define SEVEN_SEGMENT_PATTERN_C 0x72
#define SEVEN_SEGMENT_PATTERN_D 0xB9
#define SEVEN_SEGMENT_PATTERN_E 0xF2
#define SEVEN_SEGMENT_PATTERN_F 0xE2
#define SEVEN_SEGMENT_PATTERN_G 0xdb
#define SEVEN_SEGMENT_PATTERN_H 0xE9
#define SEVEN_SEGMENT_PATTERN_I 0x09
#define SEVEN_SEGMENT_PATTERN_J 0x19
#define SEVEN_SEGMENT_PATTERN_L 0x70
#define SEVEN_SEGMENT_PATTERN_O 0x7b
#define SEVEN_SEGMENT_PATTERN_P 0xe3
#define SEVEN_SEGMENT_PATTERN_R 0xa0
#define SEVEN_SEGMENT_PATTERN_S 0xda
#define SEVEN_SEGMENT_PATTERN_U 0x79
#define SEVEN_SEGMENT_PATTERN_DOT 0x04
Of course, I could use this to extract the pinout of the display and manually figure out the new definitions for flipped characters. However, this would be time consuming and I'm thinking that there must be a smarter way.
Some would remain the same when flipped, such as SEVEN_SEGMENT_PATTERN_0
. Some will be easy to flip if I knew the pinout, such as SEVEN_SEGMENT_PATTERN_1
.
Is there some smart algorithm or whatever that can help me calculate the flipped values?
4 Answers 4
Looks like the pinout is, from most to least significant bit, G F E D C dot A B. enter image description here
You could write some code along the lines of
rotatedChar=0;
if (char & 0x01) rotatedChar|=0x20;
if (char & 0x02) rotatedChar|=0x10;
// six more lines here.
-
1\$\begingroup\$ While
rotatedChar += 0x20;
is correct, I think it would be more obvious to someone reading the code, for it to or the bits in, e.g.rotatedChar |= 0x20;
instead. Using+=
looks like counting or a calculation, while|=
looks like building a bit pattern. \$\endgroup\$gbulmer– gbulmer2014年09月19日 08:41:36 +00:00Commented Sep 19, 2014 at 8:41 -
\$\begingroup\$ @gbulmer Good idea - code changed \$\endgroup\$Chris Johnson– Chris Johnson2014年09月19日 09:50:37 +00:00Commented Sep 19, 2014 at 9:50
Initial order of segments is GFEDCPAB and it has to be changed to GCBAFPDE. G and P stay at their places. B,D,F are rotated three positions right. A,C,E are rotated three positions left. AVRs can not do circular shift easily, so data is nibble-swapped twice to avoid shifting between LSB and MSB.
unsigned char dataout;
asm volatile("swap %0" : "=r" (datain) : "0" (datain));
dataout = ((datain & 0x15)<<2)|(datain & 0xa2))>>1;
asm volatile("swap %0" : "=r" (datain) : "0" (datain));
dataout |= datain & 0x84;
The answer above solved this. The remap function looks like this in Python (for testing):
def rotate(char):
rotatedchar = 0
if (char & 0x01):
rotatedchar += 0x20
if (char & 0x02):
rotatedchar += 0x10
if (char & 0x04):
rotatedchar += 0x04
if (char & 0x08):
rotatedchar += 0x40
if (char & 0x10):
rotatedchar += 0x02
if (char & 0x20):
rotatedchar += 0x01
if (char & 0x40):
rotatedchar += 0x04
if (char & 0x80):
rotatedchar += 0x80
return rotatedchar
It may be unnecessary optimalization, but in general, &
is faster than if
, therefore, using the coding from Chris' answer, we can get:
rotch = ch&0x84 + (ch & 0x0a) << 3 + (ch & 0x50) >> 3 + (ch & 0x01) << 5 + (ch & 0x20) >> 5
This comes from the fact that:
- for
0x08
and0x02
inch
(G, dot), we keep them - for
0x40
and0x10
inch
(F, D), we shift them3
bits to the right inrotch
(to C, A) - etc.
This is faster and it's a one-liner. From the code itself, it's obvious that it's just some but shuffle, yet it may be wise to comment it well.
-
\$\begingroup\$ The compiler will generate equivalent code in either case. Which is clearer to read probably depends on the reader. \$\endgroup\$pericynthion– pericynthion2014年09月19日 16:35:30 +00:00Commented Sep 19, 2014 at 16:35
-
\$\begingroup\$ I was anticipating that the code would be used just to get new values to hardcode into the #defines - which would be even more optimised! \$\endgroup\$Chris Johnson– Chris Johnson2014年09月19日 21:23:42 +00:00Commented Sep 19, 2014 at 21:23