DEV Community

Cover image for Simulating a 7-segment display (pt1)
Tracy Gilmore
Tracy Gilmore

Posted on • Edited on

Simulating a 7-segment display (pt1)

The Project - Part One

We are going to simulate a 7-segment display and Binary-Coded-Decimal (BCD) encoder in vanilla HTML, CSS and JS. The step-by-step process will commence by preparing the HTML page to exercise the simulation.

Next we will create and locate the segments using CSS and finally we will use JS to map a selected digit to the display segments but this will itself be done in several stages. The last stage, being the most academic of the three, will be covered by part two of this post.

Data

During the project we will need to reference the following Truth table several times. The first section (left) refers to the digit that user can select from a dropdown (select) for presentation as a 7-segment display (7SD.)

The middle section documents the binary encoded value of the decimal using first bits (binary digits) that will be used as input (lines/wires) into the BCD (Binary-Coded-Decimal) modules.

The right side of the table documents the seven output lines from the BCD module that align to each of the segments of the 7SD.

  +--------------------------------------------+
  | Truth Table                                |
  +-----+--------------+-----------------------+
  |     | Input lines  | Output lines          |
  | Dec |  A  B  C  D  |  a  b  c  d  e  f  g  |
  +-----+--------------+-----------------------+
  |  0  |  0  0  0  0  |  1  1  1  1  1  1  0  |
  |  1  |  0  0  0  1  |  1  1  0  0  0  0  0  |
  |  2  |  0  0  1  0  |  1  0  1  1  0  1  0  |
  |  3  |  0  0  1  1  |  1  1  1  0  0  1  1  |
  |  4  |  0  1  0  0  |  1  1  0  0  1  0  1  |
  |  5  |  0  1  0  1  |  0  1  1  0  1  1  1  |
  |  6  |  0  1  1  0  |  0  1  1  1  1  1  1  |
  |  7  |  0  1  1  1  |  1  1  0  0  0  1  0  |
  |  8  |  1  0  0  0  |  1  1  1  1  1  1  1  |
  |  9  |  1  0  0  1  |  1  1  1  0  1  1  1  |
  +-----+--------------+-----------------------+
Enter fullscreen mode Exit fullscreen mode

Steps Overview

Step One - Direct representation of the digit as input to the 7SD

We will initially ignore the BCD encoder and map the selected digit directly to energise the 'wires' required in order to get the 7-segment display to represent the digit appropriately.

  +---------------+---+
  | Decimal digit | V |
  +------+--------+---+
         | Decimal (string)
         |
   +--+--+--+--+--+--+
   |a |b |c |d |e |f |g    7 Binary digits (bits)
   |  |  |  |  |  |  |       (string)
+--+--+--+--+--+--+--+--+
| Seven-segment display |
+-----------------------+
Enter fullscreen mode Exit fullscreen mode

Going by truth table above, this stage will map the selected Decimal digit directly to the Output lines to light up the appropriate segments of the display. The HTML Select element value will be mapped to a 7-bit binary pattern as a string.

Step Two - Simulated BCD (mapping Input lines to Output lines)

We will convert the selected digit (in decimal) to a 4-bit binary value (string) representing of the Input lines. This will be passing in to the simulated BCD that will convert the binary value to 7 Output lines used to energise the 7-segment display.

  +---------------+---+
  | Decimal digit | V |
  +------+--------+---+
         | Decimal (string)
         |
    +----+----+----+
    |A   |B   |C   |D      4 Binary digits
    |    |    |    |         (string)
+---+----+----+----+---+
| Binary Coded Decimal |
|   (Mapping object)   |
+--+--+--+--+--+--+--+-+
   |  |  |  |  |  |  |       
   |a |b |c |d |e |f |g    7 Binary digits
   |  |  |  |  |  |  |       (string)
+--+--+--+--+--+--+--+--+
| Seven-segment display |
+-----------------------+
Enter fullscreen mode Exit fullscreen mode

Again with reference to the Truth table above, this stage has the select element issuing a decimal value for encoding by a simulated BCD component. The output from the BCD will be the 7-bit binary value required by the 7-segment display.

Step Three - Simulated BCD with logic circuits

Finally we will replace the mapping of the Input lines to Output lines in the BCD module. Instead we will use logical expressions required to simulate the operation of the BCD module.

  +---------------+---+
  | Decimal digit | V |
  +------+--------+---+
         | Decimal (string)
         |
    +----+----+----+
    |A   |B   |C   |D      4 Binary digits
    |    |    |    |         (string)
+---+----+----+----+---+
| Binary Coded Decimal |
|   (Boolean  Logic)   |
+--+--+--+--+--+--+--+-+
   |  |  |  |  |  |  |       
   |a |b |c |d |e |f |g    7 Binary digits
   |  |  |  |  |  |  |       (string)
+--+--+--+--+--+--+--+--+
| Seven-segment display |
+-----------------------+
Enter fullscreen mode Exit fullscreen mode

In this final stage the select element will issue a 4-bit binary (string) representing the user-selected decimal value. The 4-bit value will be translated into 7 bits via the BCD using Boolean logic before it is sent to the 7SD.

Let's get started

A physical 7-segment display has 7 LED (Light Emitting Diodes) or LCD (Liquid Crystal Display) areas arranged so each represents a single segment of a digit. Each segment has a wire that is energised to switch the segment on or off and is often labelled a-g illustrated in the diagram at the top of this post.

The source code for this post can be found in this JSFiddle.

Structuring the screen with HTML

To begin with we need the HTML to present the decimal selection (section 1) and the segments of the 7-segment display (section 2).

<main>
  <section>
    <label for="decimal">Decimal</label>
    <select id="decimal">
      <option>0</option>
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option>
      <option>5</option>
      <option>6</option>
      <option>7</option>
      <option>8</option>
      <option>9</option>
    </select> 
  </section>
  <section class="seven-segment">
    <div class="segment" id="seg_a"></div>
    <div class="segment" id="seg_b"></div>
    <div class="segment" id="seg_c"></div>
    <div class="segment" id="seg_d"></div>
    <div class="segment" id="seg_e"></div>
    <div class="segment" id="seg_f"></div>
    <div class="segment" id="seg_g"></div>
  </section>
</main>
Enter fullscreen mode Exit fullscreen mode

Styling the content with CSS

The 7-segment display will need quite a bit of styling so we will apply the styling gradually.

  1. We will style the section element as the container for the seven segments with a grey (#777) background, width of 100px and height 160px. We also need to set the positioning to relative so we can position the div segments absolutely.
  2. Segments will have a basic styling and a specific styling. The default (off) colour will be a light-grey (#AAA) orientated vertically (20px wide by 66px long) and positioned absolutely.
  3. Segment-specific styling will apply the orientation, position and hexagonal shape using pseudo elements. To keep things simple we will delay shaping the segments so the initial CSS looks like this.
section {
  width: 50%;
  float: left;
}

.seven-segment {
  background-color: #777;
  width: 120px;
  height: 180px;
  position: relative;
}

.segment {
  border: 10px solid #999;
  width: 0;
  height: 46px;
  position: absolute;
  box-sizing: border-box;
}

.segLit {
  border-color: yellow;
}
Enter fullscreen mode Exit fullscreen mode

The segments will be 'energised' by applying a segLit class that changes the border-color property to yellow.

The segment-specific styling uses pseudo-elements for the 'pointy' ends of each segment to for the narrow-hexagonal shape. This is achieved using an element with no width or height but a solid transparent border of 10px wide. The pointy-ends are positioned just outside of the segment as assumes the same colour through the inherit value.

.segment::before,
.segment::after {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 10px;
  border-color: transparent;
  position: absolute;
  content: '';
}
Enter fullscreen mode Exit fullscreen mode

Quite rightly, it is not considered good practice to use Id's in CSS given the specificity and access limitations it produces. However, in this learning project we will to uniquely reference each segment of the display. First we append the appropriate 'pointy' ends to each segment.

#seg_c::before, #seg_f::before, #seg_g::before {
  border-left-width: 0;
  border-right-color: inherit;
  top: -10px;
  left: -20px;
}

#seg_c::after, #seg_f::after, #seg_g::after {
  border-right-width: 0;
  border-left-color: inherit;
  top: -10px;
  right: -20px;
}

#seg_a::before, #seg_b::before, #seg_d::before, #seg_e::before {
  border-top-width: 0;
  border-bottom-color: inherit;
  top: -20px;
  left: -10px;
}

#seg_a::after, #seg_b::after, #seg_d::after, #seg_e::after {
  border-bottom-width: 0;
  border-top-color: inherit;
  bottom: -20px;
  left: -10px;
}
Enter fullscreen mode Exit fullscreen mode

Finally we resize and position the segments absolutely within the seven-segment element. Segments c, f and g are horizontal (short and wide) so need to be resized as follows and will be slightly wider purely for personal preference.

#seg_c, #seg_f, #seg_g {
  width: 56px;
  height: 0;
}
Enter fullscreen mode Exit fullscreen mode

Segments a and b are aligned to the right, segments c, f and g are inset from the left, as are d and e but not by as much.

#seg_a, #seg_b {
  right: 10px;
}

#seg_c, #seg_f, #seg_g {
  left: 32px;
}

#seg_d, #seg_e {
  left: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Segment g is vertically centred whilst segment c is clamped to the bottom and f to the top.

#seg_g {
  top: 80px;
}

#seg_c {
  bottom: 10px;
}

#seg_f {
  top: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Lastly, segments a and e are inset from the top whilst b and d are inset from the bottom.

#seg_a, #seg_e {
  top: 32px;
}

#seg_b, #seg_d {
  bottom: 32px;
}
Enter fullscreen mode Exit fullscreen mode

That is the styling done. Next we start wiring up using JavaScript.

Enabling the simulation with JavaScript

As stated at the beginning of this post we will be simulating the 7SD and BCD in three stages:

  1. Simulate the 7-segment display
  2. Simulate the output of the Binary-Converted-Decimal module by mapping the input
  3. Simulate the internal wiring of the logic gates within the BCD module

But before we do that (stage 0) we need to establish some infrastructure such as:

  • Define arrays containing the (4-bit) input lines and (7-bit) output lines as binary strings.
const inputLines = [
  '0000', '0001', '0010', '0011', '0100', 
  '0101', '0110', '0111', '1000', '1001' 
];

const outputLines = [
  '1111110', '1100000', '1011011', '1110011', '1100101',
  '0110111', '0111111', '1100010', '1111111', '1110111' 
];
Enter fullscreen mode Exit fullscreen mode
  • Enable connections between the HTML Document Object Model (DOM) and the JavaScript engine.
function getSevenSegmentDisplayWires() {
  return [...document.getElementsByClassName('segment')]
    .reduce((interface, domSeg) => 
      ({
        ...interface,
        [domSeg.id.replace('seg_', '')]: (isLit) => 
          domSeg.classList[isLit === '1' ? 'add' : 'remove'] 
            ('segLit')
      }),
      {});
}

function attachDecimalChangeEvent(changeEventHandler, wires) {
  document.getElementById('decimal').
    addEventListener('change', (evt) => 
      changeEventHandler(wires[+evt.target.value]));
}
Enter fullscreen mode Exit fullscreen mode
  • Now we can simulate the wires connecting each of the seven segments of the display.
const sevenSegmentDisplayWires = getSevenSegmentDisplayWires();
Enter fullscreen mode Exit fullscreen mode
Stage One - Simulate the 7-segment display

We have the mechanism to illuminate the individual segments of the display according to the state of each wire, now we need a mechanism to the take a specific Output lines argument and display and entire digit.

function simulatedBCD_Presentation(outputWires) {
  sevenSegmentDisplayWires.a(outputWires[0]);
  sevenSegmentDisplayWires.b(outputWires[1]);
  sevenSegmentDisplayWires.c(outputWires[2]);
  sevenSegmentDisplayWires.d(outputWires[3]);
  sevenSegmentDisplayWires.e(outputWires[4]);
  sevenSegmentDisplayWires.f(outputWires[5]);
  sevenSegmentDisplayWires.g(outputWires[6]);
}
Enter fullscreen mode Exit fullscreen mode

The simulatedBCD_Presentation function can be used in conjunction with the outputLines array to link the decimal output from the select element to the display.

const decimalSelection = attachDecimalChangeEvent(
  simulatedBCD_Presentation, outputLines);
Enter fullscreen mode Exit fullscreen mode

This decimalSelection function connects the simulatedBCD_Presentation function to change event of the dropdown component so the outputLines can be selected and sent to the simulated 7SD via the simulatedBCD_Presentation function.

Stage Two - Simulate the BCD by mapping input to output lines

In the next two states we still use the simulatedBCD_Presentation function but we wrap it in another function so the that takes the inputLines data, passes it through a simulated BCD and the output is sent to the 7SD.

const decimalSelection = attachDecimalChangeEvent(
  simulatedMappedBCD, inputLines);

function simulatedMappedBCD(inputWires) {
  const outputWires = outputLines[inputLines.indexOf(inputWires)];
  simulatedBCD_Presentation(outputWires);
}
Enter fullscreen mode Exit fullscreen mode

The above simulatedMappedBCD function, as the name suggests, just does a mapping operation between the inputLines to outputLines.

Stage Three - Simulate the BCD to include the Boolean logic

The third stage of simulating the BCD will be covered by the next post in this two-part series.

Top comments (0)