74 hundred Series logic IC emulation - Teensy 4.x

japreja

Active member
I've been working on this project again, this time for the Teensy 4.x. I am emulating the 74 hundred series of Logic IC's starting with the 74HC00 (NAND) and this is my code - working -. The roll section to read an actual IC is not completed yet, I think it will be much simpler than the emulation part.

I connected 8 switches and 4 LED's to the Teensy. The 8 switches represent the NAND IC inputs and the LED's are connected to emulate the outputs of the NAND.

Main question is: Is ther an easier method to code this? Not realy necessary because it works. I intend on emulating more logic and want to make corrections now before I get too much more involved.


Code:
[COLOR=#DAE3E3][FONT=Consolas][COLOR=#7f8c8d]//  Copyright 2023 Jorge Joaquin Pareja[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  FileName: HC00.ino[/COLOR]
[COLOR=#7f8c8d]//  Purpose:  Emulate OR Communicate with 74HC00 Quad 2 Input NAND Gate[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  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.[/COLOR]
[COLOR=#7f8c8d]//        The 7400 series device datasheet will indicate (in Recomended Operating Conditions) if the real IC can operate[/COLOR]
[COLOR=#7f8c8d]//        at Teensy 4.x's voltage levels[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  Mocrocontroller: Teensy 4.1[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]////////////[/COLOR]
[COLOR=#7f8c8d]//  Document formatting symbols (forums may mangle this)[/COLOR]
[COLOR=#7f8c8d]////////////[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  ─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ║ ╒ ╓ ╔ ╕╖ ╗ ╘ ╙ ╚ ╛╜╝╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]////////////[/COLOR]
[COLOR=#7f8c8d]// Documentation[/COLOR]
[COLOR=#7f8c8d]////////////[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  DocumentationSource : Nexperia 74HC00, This IC can operate at 3.3v of Teensy 4.x, other manufacturers may differ.[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//  Pinout DIP 14[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//                    ┌──────┬──┬──────┐[/COLOR]
[COLOR=#7f8c8d]//                    │      └──┘      │[/COLOR]
[COLOR=#7f8c8d]//                 1A ┤1   74HC00    14├ VCC[/COLOR]
[COLOR=#7f8c8d]//                 1B ┤2             13├ 4B[/COLOR]
[COLOR=#7f8c8d]//                 1Y ┤3             12├ 4A[/COLOR]
[COLOR=#7f8c8d]//                 2A ┤4             11├ 4Y[/COLOR]
[COLOR=#7f8c8d]//                 2B ┤5             10├ 3B[/COLOR]
[COLOR=#7f8c8d]//                 2Y ┤6              9├ 3A[/COLOR]
[COLOR=#7f8c8d]//                GND ┤7              8├ 3Y[/COLOR]
[COLOR=#7f8c8d]//                    │                │[/COLOR]
[COLOR=#7f8c8d]//                    └────────────────┘[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]// Truth Table (NAND)[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//                    ┌───────────╥────────┐[/COLOR]
[COLOR=#7f8c8d]//                    │   INPUTS  ║ OUTPUT │[/COLOR]
[COLOR=#7f8c8d]//                    ├─────┬─────╫────────┤[/COLOR]
[COLOR=#7f8c8d]//                    │  A  │  B  ║   Y    │[/COLOR]
[COLOR=#7f8c8d]//                    ╞═════╪═════╬════════╡[/COLOR]
[COLOR=#7f8c8d]//                    │  L  │  L  ║   H    │[/COLOR]
[COLOR=#7f8c8d]//                    ├─────┼─────╫────────┤[/COLOR]
[COLOR=#7f8c8d]//                    │  L  │  H  ║   H    │[/COLOR]
[COLOR=#7f8c8d]//                    ├─────┼─────╫────────┤[/COLOR]
[COLOR=#7f8c8d]//                    │  H  │  L  ║   H    │[/COLOR]
[COLOR=#7f8c8d]//                    ├─────┼─────╫────────┤[/COLOR]
[COLOR=#7f8c8d]//                    │  H  │  H  ║   L    │[/COLOR]
[COLOR=#7f8c8d]//                    └─────┴─────╨────────┘[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]//[/COLOR]
[COLOR=#7f8c8d]////////////////////[/COLOR]

[COLOR=#7f8c8d]// define the some pins for teensy to act as a 7400 IC (Respecting Teensy's voltage limits)[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_1A[/COLOR]  [COLOR=#7fcbcd]0[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_1B[/COLOR]  [COLOR=#7fcbcd]1[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_1Y[/COLOR]  [COLOR=#7fcbcd]2[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_2A[/COLOR]  [COLOR=#7fcbcd]3[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_2B[/COLOR]  [COLOR=#7fcbcd]4[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_2Y[/COLOR]  [COLOR=#7fcbcd]5[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_3A[/COLOR]  [COLOR=#7fcbcd]6[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_3B[/COLOR]  [COLOR=#7fcbcd]7[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_3Y[/COLOR]  [COLOR=#7fcbcd]8[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_4A[/COLOR]  [COLOR=#7fcbcd]9[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_4B[/COLOR] [COLOR=#7fcbcd]10[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_4Y[/COLOR] [COLOR=#7fcbcd]11[/COLOR]

[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]PIN_ROLL[/COLOR] [COLOR=#7fcbcd]12[/COLOR][COLOR=#7f8c8d] // teensy pin 12 will serve as the input to change the roll of the teensy at runtime[/COLOR]

[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT0[/COLOR] [COLOR=#7fcbcd]0[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT1[/COLOR] [COLOR=#7fcbcd]1[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT2[/COLOR] [COLOR=#7fcbcd]2[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT3[/COLOR] [COLOR=#7fcbcd]3[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT4[/COLOR] [COLOR=#7fcbcd]4[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT5[/COLOR] [COLOR=#7fcbcd]5[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT6[/COLOR] [COLOR=#7fcbcd]6[/COLOR]
[COLOR=#c586c0]#define[/COLOR] [COLOR=#f39c12]BIT7[/COLOR] [COLOR=#7fcbcd]7[/COLOR]

[COLOR=#0ca1a6]int[/COLOR] lastRoll;
[COLOR=#0ca1a6]int[/COLOR] currentRoll;

[COLOR=#0ca1a6]uint8_t[/COLOR] inputs;
[COLOR=#0ca1a6]uint8_t[/COLOR] outputs;


[COLOR=#7f8c8d]// constants can NOT be changed by setting them in code after programmed to the micro[/COLOR]
[COLOR=#0ca1a6]const[/COLOR] [COLOR=#0ca1a6]int[/COLOR] TEENSY_ROLL_READ_IC   = [COLOR=#7fcbcd]0[/COLOR];[COLOR=#7f8c8d] // set the microcontroller to read an actual 74HC00 IC[/COLOR]
[COLOR=#0ca1a6]const[/COLOR] [COLOR=#0ca1a6]int[/COLOR] TEENSY_ROLL_ACT_AS_IC = [COLOR=#7fcbcd]1[/COLOR];[COLOR=#7f8c8d] // act as an 74HC00 IC for testing and learning[/COLOR]

[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]setup[/COLOR]() {
[COLOR=#7f8c8d]  // set direction of roll pin[/COLOR]
  [COLOR=#f39c12]pinMode[/COLOR](PIN_ROLL, INPUT_PULLUP);[COLOR=#7f8c8d]  // defaults to act as IC[/COLOR]

[COLOR=#7f8c8d]  // initialize serial communication:[/COLOR]
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]begin[/COLOR]([COLOR=#7fcbcd]115200[/COLOR]);

[COLOR=#7f8c8d]  //wait 0.1 second[/COLOR]
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]100[/COLOR]);

  lastRoll = [COLOR=#7fcbcd]1[/COLOR];[COLOR=#7f8c8d]  // set to a known value, eg. default state[/COLOR]
  [COLOR=#f39c12]getROLL[/COLOR]();

}

[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]loop[/COLOR]() {
[COLOR=#7f8c8d]  //getROLL();[/COLOR]

  

[COLOR=#7f8c8d]  // print out some data :TODO: check if changes are visible and set lastRole to currentRoll outside of the same function.[/COLOR]
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR]([COLOR=#7fcbcd]"Current roll: "[/COLOR]);
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR](currentRoll, DEC);
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR]([COLOR=#7fcbcd]" Last roll: "[/COLOR]);
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR](lastRoll, DEC);

  [COLOR=#f39c12]readPins[/COLOR]();
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR]([COLOR=#7fcbcd]" --- Port Input bits: "[/COLOR]);
  [COLOR=#f39c12]printBin[/COLOR](inputs);

  [COLOR=#f39c12]setOutputs[/COLOR]();
  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]print[/COLOR]([COLOR=#7fcbcd]" --- Port Output bits: "[/COLOR]);
  [COLOR=#f39c12]printBin[/COLOR](outputs);

  [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]println[/COLOR]();
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]250[/COLOR]);
}

[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]setOutputs[/COLOR](){
  outputs = 0b[COLOR=#7fcbcd]00000000[/COLOR];
[COLOR=#7f8c8d]  //////////////////////////////////[/COLOR]
[COLOR=#7f8c8d]  // Port 1[/COLOR]
  [COLOR=#c586c0]if[/COLOR]( ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT0) == [COLOR=#7fcbcd]1[/COLOR]) && ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT1) ==[COLOR=#7fcbcd]1[/COLOR]) ){
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_1Y, LOW);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT0,LOW);
  }
  [COLOR=#c586c0]else[/COLOR]{
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_1Y, HIGH);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT0,HIGH);
  }

[COLOR=#7f8c8d]  //////////////////////////////////[/COLOR]
[COLOR=#7f8c8d]  // Port 2[/COLOR]
  [COLOR=#c586c0]if[/COLOR]( ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT2) == [COLOR=#7fcbcd]1[/COLOR]) && ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT3) ==[COLOR=#7fcbcd]1[/COLOR]) ){
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_2Y, LOW);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT1,LOW);
  }
  [COLOR=#c586c0]else[/COLOR]{
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_2Y, HIGH);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT1,HIGH);
  }

[COLOR=#7f8c8d]  //////////////////////////////////[/COLOR]
[COLOR=#7f8c8d]  // Port 3[/COLOR]
  [COLOR=#c586c0]if[/COLOR]( ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT4) == [COLOR=#7fcbcd]1[/COLOR]) && ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT5) ==[COLOR=#7fcbcd]1[/COLOR]) ){
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_3Y, LOW);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT2,LOW);
  }
  [COLOR=#c586c0]else[/COLOR]{
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_3Y, HIGH);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT2,HIGH);
  }

[COLOR=#7f8c8d]  //////////////////////////////////[/COLOR]
[COLOR=#7f8c8d]  // Port 4[/COLOR]
  [COLOR=#c586c0]if[/COLOR]( ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT6) == [COLOR=#7fcbcd]1[/COLOR]) && ([COLOR=#f39c12]bitRead[/COLOR](inputs,BIT7) ==[COLOR=#7fcbcd]1[/COLOR]) ){
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_4Y, LOW);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT3,LOW);
  }
  [COLOR=#c586c0]else[/COLOR]{
    [COLOR=#f39c12]digitalWrite[/COLOR](PIN_4Y, HIGH);
    [COLOR=#f39c12]bitWrite[/COLOR](outputs,BIT3,HIGH);
  }
}

[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]readPins[/COLOR](){
  inputs = 0b[COLOR=#7fcbcd]00000000[/COLOR];

  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_1A) << BIT0;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_1B) << BIT1;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);

  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_2A) << BIT2;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_2B) << BIT3;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_3A) << BIT4;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_3B) << BIT5;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_4A) << BIT6;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
  inputs |= [COLOR=#f39c12]digitalRead[/COLOR](PIN_4B) << BIT7;
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);
}

[COLOR=#7f8c8d]// Alters IO direction of the respective pins but does not read them[/COLOR]
[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]setROLL_READ_IC[/COLOR](){
[COLOR=#7f8c8d]  // we are reading an actual 7400, set pins appropriately[/COLOR]
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1A, OUTPUT);[COLOR=#7f8c8d]  // by default, digital pin 0 is used to send signals to 1A[/COLOR]
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1B, OUTPUT);[COLOR=#7f8c8d]  // by default, digital pin 1 is used to send signals to 1B[/COLOR]
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1Y, INPUT);[COLOR=#7f8c8d]   // read the result from the 7400 1Y output from digital pin 2[/COLOR]

  [COLOR=#f39c12]pinMode[/COLOR](PIN_2A, OUTPUT);[COLOR=#7f8c8d]  // same as above with respect to pins for the remaining 7400 ports[/COLOR]
  [COLOR=#f39c12]pinMode[/COLOR](PIN_2B, OUTPUT);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_2Y, INPUT);
  
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3A, OUTPUT);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3B, OUTPUT);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3Y, INPUT);
  
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4A, OUTPUT);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4B, OUTPUT);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4Y, INPUT);

  currentRoll = TEENSY_ROLL_READ_IC;
}[COLOR=#7f8c8d] // end setROLL_READ_IC[/COLOR]

[COLOR=#7f8c8d]// Alters IO direction of the respective pins but does not read them[/COLOR]
[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]setROLL_ACT_AS_IC[/COLOR](){
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1A, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1B, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_1Y, OUTPUT);

  [COLOR=#f39c12]pinMode[/COLOR](PIN_2A, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_2B, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_2Y, OUTPUT);
  
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3A, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3B, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_3Y, OUTPUT);
  
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4A, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4B, INPUT_PULLUP);
  [COLOR=#f39c12]pinMode[/COLOR](PIN_4Y, OUTPUT);

  currentRoll = TEENSY_ROLL_ACT_AS_IC;
}[COLOR=#7f8c8d] // end setROLL_ACT_AS_IC[/COLOR]

[COLOR=#7f8c8d]// checks to see if the controll pin (PIN_ROLL) has changed[/COLOR]
[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]getROLL[/COLOR](){
[COLOR=#7f8c8d]  //read ROLL pin[/COLOR]
  currentRoll = [COLOR=#f39c12]digitalRead[/COLOR](PIN_ROLL);
  [COLOR=#f39c12]delayMicroseconds[/COLOR]([COLOR=#7fcbcd]10[/COLOR]);

  [COLOR=#c586c0]if[/COLOR](currentRoll != lastRoll)
  {
    [COLOR=#c586c0]switch[/COLOR](currentRoll){
      [COLOR=#c586c0]case[/COLOR] TEENSY_ROLL_READ_IC:
        [COLOR=#f39c12]setROLL_READ_IC[/COLOR]();
        [COLOR=#c586c0]break[/COLOR];
      [COLOR=#c586c0]case[/COLOR] TEENSY_ROLL_ACT_AS_IC:
        [COLOR=#f39c12]setROLL_ACT_AS_IC[/COLOR]();
        [COLOR=#c586c0]break[/COLOR];
      [COLOR=#c586c0]default[/COLOR]:
        [COLOR=#c586c0]break[/COLOR];
    }[COLOR=#7f8c8d]//end switch[/COLOR]

    lastRoll = currentRoll;
  }[COLOR=#7f8c8d] // end if[/COLOR]
}[COLOR=#7f8c8d] // end getROLL[/COLOR]

[COLOR=#7f8c8d]// to print leading zero's in binary numbers.[/COLOR]
[COLOR=#7f8c8d]// 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[/COLOR]
[COLOR=#0ca1a6]void[/COLOR] [COLOR=#f39c12]printBin[/COLOR](byte aByte) {
  [COLOR=#c586c0]for[/COLOR] ([COLOR=#0ca1a6]int8_t[/COLOR] aBit = [COLOR=#7fcbcd]7[/COLOR]; aBit >= [COLOR=#7fcbcd]0[/COLOR]; aBit--)
    [COLOR=#f39c12]Serial[/COLOR].[COLOR=#f39c12]write[/COLOR]([COLOR=#f39c12]bitRead[/COLOR](aByte, aBit) ? '1' : '0');
}
[/FONT][/COLOR]
 
At first glance this project suggests one would use the C bitwise operators, &-AND, |-OR, ^-XOR but the way you have stored your data prevents this. But if all your inputs were kept in the BIT 0 position you could write functions like:

uint8_t fAND( uint8_t A, uint8_t B ){

return A & B;
}

uint8_t fNAND( uint8_t A, uint8_t B ){

return !( A & B );
}

And this would just simply work rather than implementing the truth table with IF ELSE type of statements.


Edit to add:

And if you wanted to cascade gates in the program for example the output of an AND gate feeding an XOR gate:

Code:
uint8_t in0 = digitalRead( 0 );
uint8_t in1 = digitalRead( 1 );
uint8_t in2 = digitalRead( 2 );

uint8_t node1 = fAND( in0, in1 );
uint8_t out0 = fXOR( node1, in2 );
 
Last edited:
Table lookup is one approach, combine the inputs into a single int and do the lookup, then expand for the outputs - the advantage is each logic function just needs a different table, not more coding, the disavantage is the amount of Flash memory consumed for the tables.
 
Personally I'd read all the values into one value (may as well use a uint32_t, it's a 32 bit processor) and then use bitwise operations to calculate all the outputs at the same time.
If you define the pin numbers as an array then it becomes simple to expand the logic to any number of gates (well up to 32 but that would be 96 IO pins which isn't going to happen anyway).

Code:
const int gates = 4;
const int InputA[] = {PIN_1A ,PIN_2A,PIN_3A,PIN_4A};
const int InputB[] = {PIN_1B ,PIN_2B,PIN_3B,PIN_4B};
const int Output[] = {PIN_1Y ,PIN_2Y,PIN_3Y,PIN_4Y};

uint32_t InputAAll = 0;
uint32_t InputBAll = 0;

// read inputs into single value
for (int i=0;i<gates;i++) {
  InputAAll |= digitalRead(InputA[i])<<i;
  InputBAll |= digitalRead(InputB[i])<<i;
}

//NAND
uint32_t OutputAll = ~(InputAAll & InputBAll);  // Output = Not (A and B)

//AND
// uint32_t OutputAll = InputAAll & InputBAll;
//NOR
// uint32_t OutputAll = ~(InputAAll | InputBAll);
//OR
// uint32_t OutputAll = InputAAll | InputBAll;
//XOR
// uint32_t OutputAll = InputAAll ^ InputBAll;

// set outputs
for (int i=0;i<gates;i++) {
  digitalWrite (Output[i], (OutputAll >> i)&0x01 );
}

Now if you wanted to get clever, if you defined the input and output pins correctly (1A, 1B and 1Y were all the same pin number on different logical GPIO ports) and used direct register reads and writes you could read all the inputs in 2 CPU instructions, 1 or 2 instructions for the logic operation and finally 1 instruction to write all the outputs at the same time. That's 32 gates of logic in 5 clock cycles.
But that's probably too restricting on pin choices and not worth the effort.
 
Back
Top