CesareBrizio
Published © GPL3+

DIP/DIL Switch-Based 8-Byte ROM via Daisy-Chained 4051 MUXs

Switches as bits, a 4051 daisy chain as bytes, and a small 8-byte ROM for Arduino is made! A tribute to AGC's core rope memory of 1960s!

IntermediateShowcase (no instructions)3,643
DIP/DIL Switch-Based 8-Byte ROM via Daisy-Chained 4051 MUXs

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
4051 multiplexer 8-channel IC
×9
Dip Switch package (4 lines)
×16
10 kOhm bussed resistive network (4 or 5 lines + common)
×16

Story

Read more

Schematics

Fritzing schematics (with only one 4051 attached to its 8 switches)

A full overview of the project, but with many obvious connections omitted for clarity

Code

Arduino sketch to read the 8-Byte ROM and show its content on an LCD display

Arduino
/*
 
DIP/DIL Switch-based 8-Byte ROM via daisy-chained 4051 multiplexers and Arduino

Circuit and comments: 
See http://www.cesarebrizio.it/Arduino/DIP_Switch_ROM.html
Circuit is as illustrated here:http://www.cesarebrizio.it/Arduino/Final%20Fritzing%20Schema.jpg
 
 created 03 Feb 2019
 by Cesare Brizio
 modified ----

This example code is in the public domain.

Originally conceived as a tribute to the hand-sewn Core Rope memories of the Apollo Guidance Computer, 
my idea was successively simplified to “find a way to store a short character string in a series of 
DIP switches, then retrieve and display that text via an Arduino UNO”.

I was inspired by (or better: I plagiarized) the schematics by PaulRB and the project described here: 
https://forum.arduino.cc/index.php?topic=446780.0 

I have 64 DIP switches, each one capable of storing a bit of information, in eaght groups of eight switches
(closed = non-null voltage reading = binary 1 - opened = null voltage reading = binary 0) 

Each group of eight switches, that I will call a "Byte", is connected to the eight I/O channels of a 
separate "slave" 4051. 

The three address lines S0/S1/S2 of all the slave multiplexers are common: one S0, one S1, and one S2 address all
the slave multiplexers simultaneously

I am using a master multiplexer 4051 whose I/O channels are connected to the com out/in of each slave multiplexer
Thus, by a two-step process:
a) select the "byte" (=slave multiplexer) to read via the S0/S1/S2 of the master 4051
b) select which "bit" to read from each slave via the common S0/S1/S2 of the slave 4051's
I can access one switch at a time and make individual reading.

As each byte is meant to store an 8-bit ASCII character, I compose the bytes by the successive readings from
their bits, and translate them into ASCII values, that are added to the string.

The string obtained is displayed on an LCD display driven by Arduino.

By changing the open/closed DIP switch configuration, I can vary the displayed string in real time.


  ==========================
  The circuit for LCD board:
  ==========================
 * LCD RS pin to digital pin 15
 * LCD Enable pin to digital pin 14
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

*/
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// "Slave" 4051 ADDRESS PINS :
int slave_S0 = 2;
int slave_S1 = 3;
int slave_S2 = 4;

// "Master" 4051 ADDRESS PINS :
int master_S0 = 5;
int master_S1 = 6;
int master_S2 = 7;

//
int analogPin = A0;

int ReadVolt = 0;

int bitValue;

int asciiCode;

char asciiChar ="";

int powerOfTwo = 0;

char asciiString[8];



void setup() {
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print("8-bit ROM says: ");
    // CONFIGURE ADDRESS PINS
    pinMode(master_S0, OUTPUT);
    pinMode(master_S1, OUTPUT);
    pinMode(master_S2, OUTPUT);
    pinMode(slave_S0, OUTPUT);
    pinMode(slave_S1, OUTPUT);
    pinMode(slave_S2, OUTPUT);
    
  Serial.begin(9600);   
  
}


void loop() {

    for( int x = 0; x < 8;  ++x )
          asciiString[x] = (char)0;

 
    // For each "Byte" 
    for (int i = 0; i < 8; i++) {
        
        // Select current Byte
        cycle4051('M',i);
        
        delay(5);
        
        //Serial.print("Byte ");
        //Serial.print(i);
        //Serial.println(" readings:");
        //Serial.print(">"); 

        asciiCode=0;

        for (int j = 7; j >=0; j--) {
        
            // Select current bit  
            cycle4051('S',j);   

            delay(5);
    
            ReadVolt = analogRead(analogPin); 
            
            if(ReadVolt>500) // check if current is running
            {
                bitValue=1; // Switch closed, bit high
                asciiCode = asciiCode + powerOfTwo;
            }
            else
            {
                bitValue=0; // Switch open, bit low
            }  
            
            //Serial.print(bitValue); 
            //Serial.print(ReadVolt); 
            //Serial.print("|"); 

        }

        //Serial.print(asciiCode); 
        //Serial.println("|");
        asciiString[i]=asciiCode;

    
    }
    //Serial.println("--- End series");    
    //Serial.println(asciiString);   

    for( int z = 0; z < 8;  ++z )
        {
        // (note: line 1 is the second row, since counting begins with 0):
        lcd.setCursor(z, 1);
        // print on the LCD the current character from the string:
        lcd.print(asciiString[z]);
        // print it also on the Serial Monitor
        Serial.print(asciiString[z]);
        }      
    Serial.println("");
    delay(10);
}


void cycle4051(char master_slave, int stepNumber) {
     // It's very obvious that this subprogram could have been written in
     // a much more compact form. I prefer to use a more verbose style
     // for clarity, readability and ease of maintenance.
     // I do know that there are may valid alternatives to the stratagem of 
     // using the powerOfTwo variable - the native POW() exponentiation function
     // that I could well have used has its drawbacks.
     switch (master_slave) {
        case 'M':
            //Next "Byte" (= next slave 4051)
            //Select the next slave 4051, connected to one of the channels of the master 4051 
            switch (stepNumber) {
               case 0:
                   //Select Channel 0 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, LOW);
                   break;
               case 1:
                   //Select Channel 1 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 2:
                   //Select Channel 2 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, LOW);
                   break;
               case 3:
                   //Select Channel 3 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 4:
                   //Select Channel 4 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, LOW);
                   break;
               case 5:
                   //Select Channel 5 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 6:
                   //Select Channel 6 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, LOW);
                   break;
               case 7:
                   //Select Channel 7 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, HIGH);
                   break;
            }
            break;
        case 'S':
            //Next "bit" (= next channel in the currently selected slave 4051)
            //Select the next channel of the slave 4051, connected to one of the dip switches 
            switch (stepNumber) {
               case 0:
                   //Select Channel 0 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=1;
                   break;
               case 1:
                   //Select Channel 1 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=2;                   
                   break;
               case 2:
                   //Select Channel 2 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=4;                   
                   break;
               case 3:
                   //Select Channel 3 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=8;                   
                   break;
               case 4:
                   //Select Channel 4 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=16;                   
                   break;
               case 5:
                   //Select Channel 5 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=32;                   
                   break;
               case 6:
                   //Select Channel 6 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=64;                   
                   break;
               case 7:
                   //Select Channel 7 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=128;                   
                   break;
            }
            break;
    }


}

Credits

CesareBrizio
1 project • 12 followers
Retired, formerly software developer and database administrator
Contact

Comments

Please log in or sign up to comment.