Simulating a 7-segment display (pt1)
Tags: 7segment, simulation, javascript
Published: 2022-04-07 16:07:45

---
title: Simulating a 7-segment display (pt1)
published: true
description: A step-by-step development to simulate a 7-segment LCD/LED digit display and the logic behind a Binary-Coded-Decimal encoder using only HTML, CSS and JavaScript
series: A little computer science for the inquisitive developer
tags: 7segment, simulation, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwotn3g2ohnhx5kk5kwk.png   
---

##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](https://dev.to/tracygjg/simulating-a-7-segment-display-pt2-a-little-computer-science-for-the-inquisitive-developer-183g) 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  |
  +-----+--------------+-----------------------+
```

###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 |
+-----------------------+
```

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 |
+-----------------------+
```

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 |
+-----------------------+
```

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](https://jsfiddle.net/TGJGilmore/8wdghrop/).

####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).
```HTML
<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>
```

####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.
```CSS
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;
}
```

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.

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

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.

```CSS
#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;
}
```

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. 

```CSS
#seg_c, #seg_f, #seg_g {
  width: 56px;
  height: 0;
}
```

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.

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

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

#seg_d, #seg_e {
  left: 10px;
}
```

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

```CSS
#seg_g {
  top: 80px;
}

#seg_c {
  bottom: 10px;
}

#seg_f {
  top: 10px;
}
```

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

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

#seg_b, #seg_d {
  bottom: 32px;
}
```

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.

```JavaScript
const inputLines = [
  '0000', '0001', '0010', '0011', '0100', 
  '0101', '0110', '0111', '1000', '1001' 
];

const outputLines = [
  '1111110', '1100000', '1011011', '1110011', '1100101',
  '0110111', '0111111', '1100010', '1111111', '1110111' 
];
```

* Enable connections between the HTML Document Object Model (DOM) and the JavaScript engine.
```JavaScript
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]));
}
```

* Now we can simulate the wires connecting each of the seven segments of the display.

```JavaScript
const sevenSegmentDisplayWires = getSevenSegmentDisplayWires();
```

#####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.

```JavaScript
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]);
}
```

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.

```JavaScript
const decimalSelection = attachDecimalChangeEvent(
  simulatedBCD_Presentation, outputLines);
```

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.

```JavaScript
const decimalSelection = attachDecimalChangeEvent(
  simulatedMappedBCD, inputLines);

function simulatedMappedBCD(inputWires) {
  const outputWires = outputLines[inputLines.indexOf(inputWires)];
  simulatedBCD_Presentation(outputWires);
}
```

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](https://dev.to/tracygjg/simulating-a-7-segment-display-pt2-a-little-computer-science-for-the-inquisitive-developer-183g) in this two-part series.