A decoder/driver for 1½ digit 7-segment LED


Actually, at the time when TVs never had more than 16 channels, there was an integrated circuit SN29764AN2 , produced by Texas Instruments© to display the channel currently received. Google will still find the data sheet for it but shops would charge you a fortune.

So, why not take a cheap microcontroller to do that job? When you count the segments you find even an ATtiny 2313 (or 4313) offers enough pins.

And even better: the μC has a serial input so you need only one data line.

In case you are using more than one display you can make use of the EEPROM to give each μC its own address; just send a sequence of "adress, data" to the RX pin of all the chips.

The code can be compiled with the Arduino IDE after installing the attiny library. There are several ways to upload the hex file to the ATtiny. (Due to the small size of its FLASH memory there is no boot loader and no USB.) And you better do not use the digitalWrite() command.

If you want to make your chips addressable, first program the EESAVE fuse before writing the chip's address to the EEPROM. If you don't, the EEPROM will be cleared each time you upload a new sketch.

Two displays are mounted next to each other, supplied with Vcc, GND and serial data.

The ATtinys are mounted to the Soldering Strips Grid Board back to back with the LED displays. As the μCs have 20 pins whereas the displays have only 18 pins, they do not match exactly. If you place pin-1 of the μC to pin-18 of the display the eight segment pins match perfect to the pins of the μC and you do not need any wires.

Just one more thing: the left "1" consists of two separate segments (A1, pin 14 and B1, pin 3). In order to switch both of them with pin-5 of the μC, you need a short wire to connect them.
Don't forget to cut the strips in the middle and solder the resistors below the IC socket.

And: it is a good idea to place a label on top of the μC once you have written its address to its EEPROM.

// compiled for ATtiny2313 @ 1 MHz
/* receives char via Serial 
   read, decode, store and display
   commands:
   B001xxxxx: address select of display
   B010xxxxx: data to display
   B01100000: clear display
   adress = -1 is invalid
   ATtiny 2313 SRAM = 128 bytes
   ATtiny 4313 SRAM = 256 bytes
   Serial library uses 186 bytes!!
*/

#include <EEPROM.h>
/* The EESAVE fuse bit in hfuse has to be programmed (set to zero)
in order to keep the chip's address when updating the software. */
byte myAdr;

void setup() {
  DDRA = B00000001;
  DDRB = B00001110;
  DDRD = B00111100;
  // so all the remaining pins are INPUTs 
  // and can be connected to HIGH or LOW at random.
  Serial.begin(9600);
  // these test  can be deleted
  // lamp test:
  for (byte i = 0; i < 20; i++) displayAndPause(i);
  // show the chip's address:
  myAdr = EEPROM.read(0);
  for (byte i = 1; i < 10; i++) displayAndPause(myAdr); 
}

void loop() {
  if (Serial.available() == 0) return;
  char c = Serial.read();
  char mode = c & B11100000;
  static int8_t adr;
  int8_t data;
  switch (mode) {
    case B00100000 : adr  = c & B00011111; break; // address 
    case B01000000 : data = c & B00011111; break; // data
    case B01100000 : data = -1; break; // clear
  }
  // is it for me?
  if (adr == myAdr) {
    display(data);  
    adr = -1; // mark this address as invalid until new adr command
  }
}

void displayAndPause(byte x) {
  display(x);
  delay(300);
  display(-1);
  delay(300);
}

void display(int x) { 
  if (x < 0) {PORTA = 0; PORTB = 0; PORTD = 0; return; }
  const byte segs4digit[10][2] = {
  /* how to connect
  ATtiny    VQE21
  PA0  5    14 A1
  PD2  6    13 B2
  PD3  7    12 F2
  PD4  8    11 A2
  PD5  9    10 G2
  PB1 13     8 C2
  PB2 14     7 E2
  PB3 15     6 D2
             5 ----- 22 ohms --- GND
             4 ----- 22 ohm2 --- GND
             
                              --a--
                       /    /     /
                     10    f     b
                     /    /     /
                          --g--
                   /    /     /
                 10    e     c
                 /    /     /
                       --d--               */
    //  PORT B     PORT D   
    // ----dec-   --gafb--
    { B00001110, B00011100 }, //   0
    { B00000010, B00000100 }, //   1
    { B00001100, B00110100 }, //   2
    { B00001010, B00110100 }, //   3
    { B00000010, B00101100 }, //   4
    { B00001010, B00111000 }, //   5
    { B00001110, B00111000 }, //   6 
    { B00000010, B00010100 }, //   7
    { B00001110, B00111100 }, //   8 
    { B00001010, B00111100 }, //   9
  };
  PORTA = (x > 9) ? 1 : 0;
  PORTB = segs4digit[x % 10][0];
  PORTD = segs4digit[x % 10][1];
}



contact: nji(at)gmx.de