Code:
// Copyright 2023 Jorge Joaquin Pareja
//
// FileName: HC00.ino
// Purpose: Emulate OR Communicate with 74HC00 Quad 2 Input NAND Gate
//
// NOTE: Keep in mind that teensy 4.x are limited to 3.3v IO, the 74 series of ic's are higher so care should be taken.
// The 7400 series device datasheet will indicate (in Recomended Operating Conditions) if the real IC can operate
// at Teensy 4.x's voltage levels
//
// Mocrocontroller: Teensy 4.1
//
////////////
// Document formatting symbols (forums may mangle this)
////////////
//
// ─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ║ ╒ ╓ ╔ ╕╖ ╗ ╘ ╙ ╚ ╛╜╝╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬
//
////////////
// Documentation
////////////
//
// DocumentationSource : Nexperia 74HC00, This IC can operate at 3.3v of Teensy 4.x, other manufacturers may differ.
//
//
// Pinout DIP 14
//
// ┌──────┬──┬──────┐
// │ └──┘ │
// 1A ┤1 74HC00 14├ VCC
// 1B ┤2 13├ 4B
// 1Y ┤3 12├ 4A
// 2A ┤4 11├ 4Y
// 2B ┤5 10├ 3B
// 2Y ┤6 9├ 3A
// GND ┤7 8├ 3Y
// │ │
// └────────────────┘
//
// Truth Table (NAND)
//
// ┌───────────╥────────┐
// │ INPUTS ║ OUTPUT │
// ├─────┬─────╫────────┤
// │ A │ B ║ Y │
// ╞═════╪═════╬════════╡
// │ L │ L ║ H │
// ├─────┼─────╫────────┤
// │ L │ H ║ H │
// ├─────┼─────╫────────┤
// │ H │ L ║ H │
// ├─────┼─────╫────────┤
// │ H │ H ║ L │
// └─────┴─────╨────────┘
//
//
////////////////////
// define the some pins for teensy to act as a 7400 IC (Respecting Teensy's voltage limits)
#define PIN_1A 0
#define PIN_1B 1
#define PIN_1Y 2
#define PIN_2A 3
#define PIN_2B 4
#define PIN_2Y 5
#define PIN_3A 6
#define PIN_3B 7
#define PIN_3Y 8
#define PIN_4A 9
#define PIN_4B 10
#define PIN_4Y 11
#define PIN_ROLL 12 // teensy pin 12 will serve as the input to change the roll of the teensy at runtime
#define BIT0 0
#define BIT1 1
#define BIT2 2
#define BIT3 3
#define BIT4 4
#define BIT5 5
#define BIT6 6
#define BIT7 7
int lastRoll;
int currentRoll;
uint8_t inputs;
uint8_t outputs;
// constants can NOT be changed by setting them in code after programmed to the micro
const int TEENSY_ROLL_READ_IC = 0; // set the microcontroller to read an actual 74HC00 IC
const int TEENSY_ROLL_ACT_AS_IC = 1; // act as an 74HC00 IC for testing and learning
void setup() {
// set direction of roll pin
pinMode(PIN_ROLL, INPUT_PULLUP); // defaults to act as IC
// initialize serial communication:
Serial.begin(115200);
//wait 0.1 second
delayMicroseconds(100);
lastRoll = 1; // set to a known value, eg. default state
getROLL();
}
void loop() {
//getROLL();
// print out some data :TODO: check if changes are visible and set lastRole to currentRoll outside of the same function.
Serial.print("Current roll: ");
Serial.print(currentRoll, DEC);
Serial.print(" Last roll: ");
Serial.print(lastRoll, DEC);
readPins();
Serial.print(" --- Port Input bits: ");
printBin(inputs);
setOutputs();
Serial.print(" --- Port Output bits: ");
printBin(outputs);
Serial.println();
delayMicroseconds(250);
}
void setOutputs(){
outputs = 0b00000000;
//////////////////////////////////
// Port 1
if( (bitRead(inputs,BIT0) == 1) && (bitRead(inputs,BIT1) ==1) ){
digitalWrite(PIN_1Y, LOW);
bitWrite(outputs,BIT0,LOW);
}
else{
digitalWrite(PIN_1Y, HIGH);
bitWrite(outputs,BIT0,HIGH);
}
//////////////////////////////////
// Port 2
if( (bitRead(inputs,BIT2) == 1) && (bitRead(inputs,BIT3) ==1) ){
digitalWrite(PIN_2Y, LOW);
bitWrite(outputs,BIT1,LOW);
}
else{
digitalWrite(PIN_2Y, HIGH);
bitWrite(outputs,BIT1,HIGH);
}
//////////////////////////////////
// Port 3
if( (bitRead(inputs,BIT4) == 1) && (bitRead(inputs,BIT5) ==1) ){
digitalWrite(PIN_3Y, LOW);
bitWrite(outputs,BIT2,LOW);
}
else{
digitalWrite(PIN_3Y, HIGH);
bitWrite(outputs,BIT2,HIGH);
}
//////////////////////////////////
// Port 4
if( (bitRead(inputs,BIT6) == 1) && (bitRead(inputs,BIT7) ==1) ){
digitalWrite(PIN_4Y, LOW);
bitWrite(outputs,BIT3,LOW);
}
else{
digitalWrite(PIN_4Y, HIGH);
bitWrite(outputs,BIT3,HIGH);
}
}
void readPins(){
inputs = 0b00000000;
inputs |= digitalRead(PIN_1A) << BIT0;
delayMicroseconds(10);
inputs |= digitalRead(PIN_1B) << BIT1;
delayMicroseconds(10);
inputs |= digitalRead(PIN_2A) << BIT2;
delayMicroseconds(10);
inputs |= digitalRead(PIN_2B) << BIT3;
delayMicroseconds(10);
inputs |= digitalRead(PIN_3A) << BIT4;
delayMicroseconds(10);
inputs |= digitalRead(PIN_3B) << BIT5;
delayMicroseconds(10);
inputs |= digitalRead(PIN_4A) << BIT6;
delayMicroseconds(10);
inputs |= digitalRead(PIN_4B) << BIT7;
delayMicroseconds(10);
}
// Alters IO direction of the respective pins but does not read them
void setROLL_READ_IC(){
// we are reading an actual 7400, set pins appropriately
pinMode(PIN_1A, OUTPUT); // by default, digital pin 0 is used to send signals to 1A
pinMode(PIN_1B, OUTPUT); // by default, digital pin 1 is used to send signals to 1B
pinMode(PIN_1Y, INPUT); // read the result from the 7400 1Y output from digital pin 2
pinMode(PIN_2A, OUTPUT); // same as above with respect to pins for the remaining 7400 ports
pinMode(PIN_2B, OUTPUT);
pinMode(PIN_2Y, INPUT);
pinMode(PIN_3A, OUTPUT);
pinMode(PIN_3B, OUTPUT);
pinMode(PIN_3Y, INPUT);
pinMode(PIN_4A, OUTPUT);
pinMode(PIN_4B, OUTPUT);
pinMode(PIN_4Y, INPUT);
currentRoll = TEENSY_ROLL_READ_IC;
} // end setROLL_READ_IC
// Alters IO direction of the respective pins but does not read them
void setROLL_ACT_AS_IC(){
pinMode(PIN_1A, INPUT_PULLUP);
pinMode(PIN_1B, INPUT_PULLUP);
pinMode(PIN_1Y, OUTPUT);
pinMode(PIN_2A, INPUT_PULLUP);
pinMode(PIN_2B, INPUT_PULLUP);
pinMode(PIN_2Y, OUTPUT);
pinMode(PIN_3A, INPUT_PULLUP);
pinMode(PIN_3B, INPUT_PULLUP);
pinMode(PIN_3Y, OUTPUT);
pinMode(PIN_4A, INPUT_PULLUP);
pinMode(PIN_4B, INPUT_PULLUP);
pinMode(PIN_4Y, OUTPUT);
currentRoll = TEENSY_ROLL_ACT_AS_IC;
} // end setROLL_ACT_AS_IC
// checks to see if the controll pin (PIN_ROLL) has changed
void getROLL(){
//read ROLL pin
currentRoll = digitalRead(PIN_ROLL);
delayMicroseconds(10);
if(currentRoll != lastRoll)
{
switch(currentRoll){
case TEENSY_ROLL_READ_IC:
setROLL_READ_IC();
break;
case TEENSY_ROLL_ACT_AS_IC:
setROLL_ACT_AS_IC();
break;
default:
break;
}//end switch
lastRoll = currentRoll;
} // end if
} // end getROLL
// to print leading zero's in binary numbers.
// from https://forum.arduino.cc/t/how-can-i-serial-println-a-binary-output-that-will-give-all-the-leading-zeros-of-a-variable/962247
void printBin(byte aByte) {
for (int8_t aBit = 7; aBit >= 0; aBit--)
Serial.write(bitRead(aByte, aBit) ? '1' : '0');
}