1
\$\begingroup\$

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?

asked Sep 19, 2014 at 8:18
\$\endgroup\$

4 Answers 4

3
\$\begingroup\$

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.
answered Sep 19, 2014 at 8:37
\$\endgroup\$
2
  • 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\$ Commented Sep 19, 2014 at 8:41
  • \$\begingroup\$ @gbulmer Good idea - code changed \$\endgroup\$ Commented Sep 19, 2014 at 9:50
2
\$\begingroup\$

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;
answered Sep 19, 2014 at 9:34
\$\endgroup\$
0
0
\$\begingroup\$

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
answered Sep 19, 2014 at 9:20
\$\endgroup\$
0
\$\begingroup\$

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 and 0x02 in ch (G, dot), we keep them
  • for 0x40 and 0x10 in ch (F, D), we shift them 3 bits to the right in rotch (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.

answered Sep 19, 2014 at 13:50
\$\endgroup\$
2
  • \$\begingroup\$ The compiler will generate equivalent code in either case. Which is clearer to read probably depends on the reader. \$\endgroup\$ Commented 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\$ Commented Sep 19, 2014 at 21:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.