/*
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;
}
}
Comments
Please log in or sign up to comment.