// variable managing clock sate
int clockState = LOW;
// Pins for the Output Register
int datapin = A15;
int clockpin = A13;
int latchpin = A14;
// This variable is used for the output register
byte data = 0;
int cycleCount = 0;
// ram of the SAP-1
int ram[16][8] = {
//****************************
// 1001 = one after another
// 1111 = binary Counter
// 1101 = one at a time
// 0001 = load
// 0010 = add
// 0011 = subtract
// 0000 = halt
//************************
// First 4 from left are Op codes
// Next 4 are address
{1, 0, 0, 1, 0, 1, 1, 0}, // Calls one after another
{1, 1, 1, 1, 0, 1, 1, 1}, // Calls 0-255 binary Counter
{1, 1, 0, 1, 1, 0, 1, 0}, // Calls one at a time
{0, 0, 0, 1, 1, 1, 0, 1}, // loads [13] = 16 decimal
{0, 0, 1, 0, 1, 1, 1, 0}, // loads [14] = 15 decimal and calls add
// 5 leds should light up here at output as 16 + 15 = 31
{0, 0, 0, 1, 1, 1, 1, 1}, // Loads null in accumulator
{0, 0, 1, 0, 1, 1, 1, 1}, // loads null in B register
// All leds should be off here as we are resetting registers
{0, 0, 0, 1, 1, 0, 1, 0}, // loads [10] = 5 decimal
{0, 0, 1, 1, 1, 0, 1, 1}, // loads [11] = 8 decimal and subtracts
// 2 leds should light as 8-5 = 3
{0, 0, 0, 0, 0, 0, 0, 0}, // Halts
// Program ends
{0, 0, 0, 0, 0, 1, 0, 1}, //[10] = 5 in decimal
{0, 0, 0, 0, 1, 0, 0, 0}, // [11] = 8 in decimal
{0, 0, 0, 0, 0, 0, 0, 0}, // [12] used as null
{0, 0, 0, 1, 0, 0, 0, 0}, // [13] =16 in decimal
{0, 0, 0, 0, 1, 1, 1, 1}, // [14] = 15 in decimal
{0, 0, 0, 0, 0, 0, 0, 0} // [15] used as null
};
void setup() {
Serial.begin(115200);
// initializing output pins
for(int i=0; i<34; i++){
pinMode(i, OUTPUT);
}
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A4, OUTPUT);
pinMode(A5, OUTPUT);
pinMode(A6, OUTPUT);
pinMode(A7, OUTPUT);
pinMode(A8, OUTPUT);
pinMode(A9, OUTPUT);
pinMode(A10, OUTPUT);
pinMode(A11, OUTPUT);
pinMode(A12, OUTPUT);
// initializing address pins
for(int i=34; i<54; i++){
pinMode(i, INPUT);
}
// DS A15
// Stcp 14
// Sthp 13
// Setting up Output Register Pins
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
// resetting the IR's flip flops to 0.
digitalWrite(A8, HIGH);
digitalWrite(A1, HIGH);
digitalWrite(A1, LOW);
digitalWrite(A8, LOW);
digitalWrite(A1, HIGH);
digitalWrite(A1, LOW);
// resetting the accumulator's flip flops to 0.
digitalWrite(A9, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A9, LOW);
digitalWrite(A2, LOW);
//resetting the b-register's flip flops to 0.
digitalWrite(A10, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A3, LOW);
digitalWrite(A10, LOW);
digitalWrite(A3, HIGH);
digitalWrite(A3, LOW);
// set enable pin high of the pc
digitalWrite(A4, HIGH);
//select line, active low
// config for program counter
// setting pc to zero
digitalWrite(30, LOW);
digitalWrite(31, LOW);
digitalWrite(32, LOW);
digitalWrite(33, LOW);
delay(50);
digitalWrite(A0, LOW);
delay(50);
digitalWrite(A0, HIGH);
digitalWrite(A12, LOW);
digitalWrite(A12, HIGH);
}
void loop() {
clockState = !clockState; // Toggle the clockState
digitalWrite(A0, clockState); // Output the clock state on the clockPin
delay(1000);
Serial.println("****************************************");
Serial.print("Current Count Cycle = ");
Serial.println(cycleCount++);
clockState = !clockState; // Toggle the clockState again
digitalWrite(A0, clockState);
// The pc counters value is taken and converted to decimal
// The value tells us which location of RAM is loaded to the IR
int address [4] = {};
address[0] = digitalRead(42);
address[1] = digitalRead(43);
address[2] = digitalRead(44);
address[3] = digitalRead(45);
int addressDecimal = 8*address[3] + 4*address[2] + 2*address[1] + 1*address[0];
// Address from the PC is loaded to the IR
digitalWrite(A5, HIGH);
digitalWrite(29, ram[addressDecimal][0]);
digitalWrite(28, ram[addressDecimal][1]);
digitalWrite(27, ram[addressDecimal][2]);
digitalWrite(26, ram[addressDecimal][3]);
digitalWrite(25, ram[addressDecimal][4]);
digitalWrite(24, ram[addressDecimal][5]);
digitalWrite(23, ram[addressDecimal][6]);
digitalWrite(22, ram[addressDecimal][7]);
digitalWrite(A1, HIGH);
digitalWrite(A1, LOW);
// IRs contents is READ and opcode and operand is determined
int opcodeBit1 = digitalRead(41);
int opcodeBit2 = digitalRead(40);
int opcodeBit3 = digitalRead(39);
int opcodeBit4 = digitalRead(38);
int operandBit1 = digitalRead(37);
int operandBit2 = digitalRead(36);
int operandBit3 = digitalRead(35);
int operandBit4 = digitalRead(34);
int addressExecution = 8*operandBit1 + 4*operandBit2 + 2*operandBit3+ 1*operandBit4;
// An array of if and else if determine which function
// This is determined by the Op code
if(opcodeBit1 == 0 && opcodeBit2 == 0 && opcodeBit3 == 0 && opcodeBit4 == 1 )
{
loadSequence(addressExecution);
Serial.print("Loading To ACCUMULATOR CONTENTS OF ADDRESS = ");
Serial.println(addressExecution);
}
else if(opcodeBit1 == 0 && opcodeBit2 == 0 && opcodeBit3 == 1 && opcodeBit4 == 0 )
{
additionSequence(addressExecution);
Serial.print("Loading To B-REGISTER CONTENTS OF ADDRESS = ");
Serial.println(addressExecution);
Serial.println("ADDITION DISPLAYED ON OUTPUT REGISTER");
}
// if opcode is of subtraction
else if(opcodeBit1 == 0 && opcodeBit2 == 0 && opcodeBit3 == 1 && opcodeBit4 == 1)
{
subtractionSequence(addressExecution);
Serial.print("Loading To B-REGISTER CONTENTS OF ADDRESS = ");
Serial.println(addressExecution);
Serial.println("SUBTRACTION DISPLAYED ON OUTPUT REGISTER");
}
else if(opcodeBit1 == 0 && opcodeBit2 == 0 && opcodeBit3 == 0 && opcodeBit4 == 0 )
{
haltSequence();
}
else if(opcodeBit1 == 1 && opcodeBit2 == 0 && opcodeBit3 == 0 && opcodeBit4 == 1 )
{
for (int i = 0; i < 3; ++i) {
Serial.println("Initiating One After Another on Output Register");
oneAfterAnother();
delay(100);
}
}
else if(opcodeBit1 == 1 && opcodeBit2 == 1 && opcodeBit3 == 0 && opcodeBit4 == 1 )
{
for (int i = 0; i < 3; ++i) {
Serial.println("Initiating One At A Time on Output Register");
oneOnAtATime();
delay(100);
}
}
else if(opcodeBit1 == 1 && opcodeBit2 == 1 && opcodeBit3 == 1 && opcodeBit4 == 1 )
{
Serial.println("Initiating Binary Count 0-255 on Output Register");
binaryCount();
delay(100);
}
}
void loadSequence(int addressExecution) {
// set the select line of accumulator low
digitalWrite(A6, LOW);
// store the instruction in the accumulator
digitalWrite(14, ram[addressExecution][0]);
digitalWrite(15, ram[addressExecution][1]);
digitalWrite(16, ram[addressExecution][2]);
digitalWrite(17, ram[addressExecution][3]);
digitalWrite(18, ram[addressExecution][4]);
digitalWrite(19, ram[addressExecution][5]);
digitalWrite(20, ram[addressExecution][6]);
digitalWrite(21, ram[addressExecution][7]);
// set the select line of accumulator high
digitalWrite(A6, HIGH);
// provide active high edge of the clock to accumulator
digitalWrite(A2, HIGH);
digitalWrite(A2, LOW);
}
void additionSequence(int addressExecution) {
// set selector pin low to add
digitalWrite(A11, LOW);
// set the select line of B-register high
digitalWrite(A7, HIGH);
// store the instruction in the b-register
digitalWrite(13, ram[addressExecution][0]);
digitalWrite(12, ram[addressExecution][1]);
digitalWrite(11, ram[addressExecution][2]);
digitalWrite(10, ram[addressExecution][3]);
digitalWrite(9, ram[addressExecution][4]);
digitalWrite(8, ram[addressExecution][5]);
digitalWrite(7, ram[addressExecution][6]);
digitalWrite(6, ram[addressExecution][7]);
// provide active high edge of the clock to b-register
digitalWrite(A3, HIGH);
digitalWrite(A3, LOW);
Serial.println("Loaded the instruction in b-register and added.");
}
// Subtracts Accumulators and B registers value and displays ANs on output register
// IMP NOTE *** 9th Output LED lights up when answer is positive
void subtractionSequence(int addressExecution) {
// set selector pin high to subtract
digitalWrite(A11, HIGH);
// set the select line of B-register high
digitalWrite(A7, HIGH);
// store the instruction in the b-register
digitalWrite(13, ram[addressExecution][0]);
digitalWrite(12, ram[addressExecution][1]);
digitalWrite(11, ram[addressExecution][2]);
digitalWrite(10, ram[addressExecution][3]);
digitalWrite(9, ram[addressExecution][4]);
digitalWrite(8, ram[addressExecution][5]);
digitalWrite(7, ram[addressExecution][6]);
digitalWrite(6, ram[addressExecution][7]);
// provide active high edge of the clock to b-register
digitalWrite(A3, HIGH);
digitalWrite(A3, LOW);
Serial.println("Loaded the instruction in b-register and subtracted.");
}
// ENDS the Program by going into an infinite loop
void haltSequence() {
Serial.println("SAP-1 entering HALT State.");
while (true) {
// Infinite Loop
}
}
// STarts counting from 0-255
void binaryCount() {
// Delay between Successive Counts
int delayTime = 50;
for (int count = 0; count <= 255; ++count) {
// Send the data byte to the shift register:
shiftOut(datapin, clockpin, MSBFIRST, count);
// Toggle the latch pin to make the data appear at the outputs:
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
// Delay so you can see what's going on:
delay(delayTime);
}
}
// USED in other functions
void shiftWrite(int pin, boolean onOff){
//Change desired bit to 0 or 1
bitWrite(data,pin,onOff);
//Send "data" to the shift register
shiftOut(datapin, clockpin, MSBFIRST, data);
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
}
// This function will turn on all the LEDs, one-by-one,
// and then turn them off all off, one-by-one.
void oneAfterAnother()
{
int index;
int delayTime = 100; // Time (milliseconds) to pause between LEDs
for(index = 0; index <= 7; index++)
{
// To turns the LEDS on
shiftWrite(index, HIGH);
delay(delayTime);
}
for(index = 7; index >= 0; index--)
{
// To Turn the LEDS off
shiftWrite(index, LOW);
delay(delayTime);
}
}
// This function will turn the LEDs on and off, one-by-one.
void oneOnAtATime()
{
int index;
int delayTime = 100; // Time (milliseconds) to pause between LEDs
// step through the LEDs, from 0 to 7
for(index = 0; index <= 7; index++)
{
// This turns the lights on
shiftWrite(index, HIGH);
delay(delayTime);
// This turns the lights off
shiftWrite(index, LOW);
}
}
// The program counter (PC) configuration:
// IS LOCATED NEAR RED LEDS
// IS of 4 bits to account for 16 ram addresses
// COUNTER STARTS FROM ZERO HENCE THE FIRST CYCLE NOT DISPLAYED ON LEDS
// - A12 serves as the enable pin for the PC.
// - The addresses for the PC are determined by pins 33, 32, 31, and 30.
// - A4 is the select line for the PC multiplexer.
// - The clock signal for the PC is provided through pin A0.
// - The PC reads addresses from pins 42, 43, 44, and 45.
// Instruction Register (IR) Configuration:
// IS LOCATED NEAR THE PINK LEDS
// Is a simple 8 bit register which hold current instruction
// - The IR utilizes address pins 29, 28, 27, 26, 25, 24, 23, and 22.
// - A5 serves as the select line for the IR multiplexer.
// - Addresses from the IR are read through pins 34, 35, 36, 37, 38, 39, 40, and 41.
// - The clock signal for addressing is received via pin A1.
// - The reset output is controlled by pin A8.
// Configuration for the Accumulator:
// LOCATED NEAR THE YELLOW LEDS
// FOR THE FIRST FEW INSTRUCTIONS NOTHING IS ADDED TO ACC HENCE ITS LEDS DONT LIGHT UP
// - Utilizes address pins 21, 20, 19, 18, 17, 16, 15, 14
// - Mux select line: A6
// - Clock signal: A2
// - Reset control: A9
//B-Register Configuration
// LOCATED NEAR BLUE LEDS
// Simple 8 bit register using D-flipflops
// ALU (Arithmetic Logic Unit) Configuration:
// IS A basic 8 bit adder and subtractor with a select line which decides whether to add or subtract
// - Selector for addition or subtraction: A11
// - B-register Configuration:
// - Reset: A10
// - Clock: A3
// - Address pins: 13, 12, 11, 10, 9, 8, 7, 6
// - Select line: A7
// Output Register
// IS LOCATED NEAR THE GREEN LEDS
// Prebuilt IC 74HC595 is used
// Is a 8 bit parallel SHift register
// Q0-Q7 connected to LEDS to display Output
// VCC of IC connect to 5V of controller
// OE of IC connected to ground
// 3 additional pins to control register functions
// datapin = A15;
// clockpin = A13;
// latchpin = A14;
ERC Warnings
flop1:S: Input pin not driven
flop1:R: Input pin not driven
flop2:S: Input pin not driven
flop2:R: Input pin not driven
flop3:S: Input pin not driven
flop3:R: Input pin not driven
flop4:S: Input pin not driven
flop4:R: Input pin not driven
flop13:S: Input pin not driven
flop14:S: Input pin not driven
50 additional warning(s) hidden