/* * This project is a virtual implementation of the TTL coax continuity tester: * https://www.lloydm.net/Demos/logic-1.html * https://www.lloydm.net/Demos/Supplement-Coax_continuity_tester.pdf * * Rev-1 Encapsulate TTL functions in a user-defined library my_ttl.h * * Lloyd Milligan (WA4EFS) June 2025 * * © CC attribution - https://creativecommons.org/licenses/by/3.0/us/ */ #include // Location: D:\Projects\Arduino\libraries\Custom // Test buttons and coax #define A 2 // Test center #define B 3 // Test shield #define X 4 // Coax center #define Y 5 // Coax shield // Outputs #define L1 10 #define L2 11 #define L3 12 // Time intervals const unsigned long DEBOUNCE = 10; const unsigned long DEBUG_PRINT_WAIT = 5000; // Declare logic variables globally for analysis print boolean C, D, E, F, J, M, N, P, Q; // Input values (1 or 0) int A_value, B_value, X_value, Y_value; // Outputs 5 volts (1) or ground (0) // L1 is 0=ON while L2 and L3 are 1=ON int L1_state, L2_state, L3_state; // Time unsigned long ONE_SECOND = 1000; // Debug boolean debugPrintOK = true; boolean statusPrintOK = true; boolean LED_jig = true; void setup() { Serial.begin(9600); // Inputs and outputs pinMode(A, INPUT); pinMode(B, INPUT); pinMode(X, INPUT); pinMode(Y, INPUT); pinMode(L1, OUTPUT); pinMode(L2, OUTPUT); pinMode(L3, OUTPUT); // Serial.print("Setup complete!\n\n"); // Test /* L1_state = LOW; L2_state = HIGH; L3_state = HIGH; randomSeed(analogRead(0)); */ } void loop() { //exerciseLogic(); // Logic functions exerciseChips(); // TTL IC's (original circuit) //testLogicFridaySolution(); // TTL IC's (minimized circuit) } boolean isHigh(int button) { // Normally LOW button pressed = HIGH // No minimum button press duration if (digitalRead(button) == LOW) return false; while (digitalRead(button) == HIGH) delay(DEBOUNCE); return true; } // The following function simulates the coax tester logic gate by logic gate void exerciseLogic() { A_value = digitalRead(A); // TTL logic simulation B_value = digitalRead(B); X_value = digitalRead(X); Y_value = digitalRead(Y); // C = ic7400(A_value, X_value); D = ic7400(B_value, Y_value); E = ic7400(X_value, Y_value); // F = ic7408(C, D); Q = ic7486(A_value, B_value); // J = ic7400(E, F); P = ic7400(J, true); // NAND as inverter M = ic7400(P, Q); // N = ic7408(E, Q); // L1_state = ic7408(M, N); L2_state = M; L3_state = E; digitalWrite(L1, L1_state); // Invert output if ON = LOW (false) digitalWrite(L2, L2_state); digitalWrite(L3, L3_state); // } // The following function simulates the coax tester TTL chip by TTL chip void exerciseChips() { A_value = digitalRead(A); // TTL chip emulation B_value = digitalRead(B); X_value = digitalRead(X); Y_value = digitalRead(Y); uint16_t ic_1; // 7400 // NAND bitWrite(ic_1, pin2bit(1), A_value); bitWrite(ic_1, pin2bit(2), X_value); bitWrite(ic_1, pin2bit(4), Y_value); bitWrite(ic_1, pin2bit(5), B_value); bitWrite(ic_1, pin2bit(9), Y_value); bitWrite(ic_1, pin2bit(10), X_value); ic7400(ic_1); C = bitRead(ic_1, pin2bit(3)); D = bitRead(ic_1, pin2bit(6)); E = bitRead(ic_1, pin2bit(8)); uint16_t ic_4; // 7408 // AND bitWrite(ic_4, pin2bit(1), C); bitWrite(ic_4, pin2bit(2), D); ic7408(ic_4); F = bitRead(ic_4, pin2bit(3)); uint16_t ic_3; // 7486 // XOR bitWrite(ic_3, pin2bit(1), A_value); bitWrite(ic_3, pin2bit(2), B_value); ic7486(ic_3); Q = bitRead(ic_3, pin2bit(3)); uint16_t ic_2; // 7400 // NAND bitWrite(ic_2, pin2bit(1), F); bitWrite(ic_2, pin2bit(2), E); ic7400(ic_2); J = bitRead(ic_2, pin2bit(3)); bitWrite(ic_2, pin2bit(4), HIGH); // NAND as inverter (HIGH = true = '1') bitWrite(ic_2, pin2bit(5), J); ic7400(ic_2); P = bitRead(ic_2, pin2bit(6)); bitWrite(ic_2, pin2bit(9), P); bitWrite(ic_2, pin2bit(10), Q); ic7400(ic_2); M = bitRead(ic_2, pin2bit(8)); bitWrite(ic_4, pin2bit(4), E); bitWrite(ic_4, pin2bit(5), Q); ic7408(ic_4); N = bitRead(ic_4, pin2bit(6)); bitWrite(ic_4, pin2bit(10), M); bitWrite(ic_4, pin2bit(9), N); ic7408(ic_4); L1_state = bitRead(ic_4, pin2bit(8)); L2_state = M; L3_state = E; digitalWrite(L1, L1_state); // Invert output if ON = LOW (false) digitalWrite(L2, L2_state); digitalWrite(L3, L3_state); return; } void exerciseChipsAnnotated() { A_value = digitalRead(A); // TTL logic emulation B_value = digitalRead(B); X_value = digitalRead(X); Y_value = digitalRead(Y); /* C = ic7400(A_value, X_value); D = ic7400(B_value, Y_value); E = ic7400(X_value, Y_value); */ uint16_t ic_1; // 7400 bitWrite(ic_1, pin2bit(1), A_value); bitWrite(ic_1, pin2bit(2), X_value); bitWrite(ic_1, pin2bit(4), Y_value); bitWrite(ic_1, pin2bit(5), B_value); bitWrite(ic_1, pin2bit(9), Y_value); bitWrite(ic_1, pin2bit(10), X_value); // ic7400(ic_1); // C = bitRead(ic_1, pin2bit(3)); D = bitRead(ic_1, pin2bit(6)); E = bitRead(ic_1, pin2bit(8)); /* F = ic7408(C, D); Q = ic7486(A_value, B_value); */ uint16_t ic_4; // 7408 bitWrite(ic_4, pin2bit(1), C); bitWrite(ic_4, pin2bit(2), D); ic7408(ic_4); F = bitRead(ic_4, pin2bit(3)); // uint16_t ic_3; // 7486 bitWrite(ic_3, pin2bit(1), A_value); bitWrite(ic_3, pin2bit(2), B_value); ic7486(ic_3); Q = bitRead(ic_3, pin2bit(3)); /* J = ic7400(E, F); */ uint16_t ic_2; // 7400 bitWrite(ic_2, pin2bit(1), F); bitWrite(ic_2, pin2bit(2), E); ic7400(ic_2); J = bitRead(ic_2, pin2bit(3)); /* P = ic7400(J, true); */ // NAND as inverter bitWrite(ic_2, pin2bit(4), true); bitWrite(ic_2, pin2bit(5), J); ic7400(ic_2); P = bitRead(ic_2, pin2bit(6)); /* M = ic7400(P, Q); */ bitWrite(ic_2, pin2bit(9), P); bitWrite(ic_2, pin2bit(10), Q); ic7400(ic_2); M = bitRead(ic_2, pin2bit(8)); /* N = ic7408(E, Q); */ bitWrite(ic_4, pin2bit(4), E); bitWrite(ic_4, pin2bit(5), Q); ic7408(ic_4); N = bitRead(ic_4, pin2bit(6)); /* L1_state = ic7408(M, N); */ bitWrite(ic_4, pin2bit(10), M); bitWrite(ic_4, pin2bit(9), N); ic7408(ic_4); L1_state = bitRead(ic_4, pin2bit(8)); L2_state = M; L3_state = E; digitalWrite(L1, L1_state); // Invert output if ON = LOW (false) digitalWrite(L2, L2_state); digitalWrite(L3, L3_state); // } // Below this line exploratory simulations void testLogicFridaySolution() { // See annotated diagram of the Logic Friday 'minimized' circuit // Upper case letter variables are main inputs A, B, X, Y // and arbitrarily labeled outputs of logic gates. // Lower case letter variables stand for inverter outputs (this diagram/code only) // Logic Friday minimization uses 2, 3, and 4 input AND gates and 2-input OR gates, // Logic Friday minimization uses no negative logic except inverted inputs. A_value = digitalRead(A); // TTL logic emulation B_value = digitalRead(B); X_value = digitalRead(X); Y_value = digitalRead(Y); // uint16_t ic_1; // 7404 Hex inverter bitWrite(ic_1, pin2bit(1), X_value); bitWrite(ic_1, pin2bit(3), A_value); bitWrite(ic_1, pin2bit(5), Y_value); bitWrite(ic_1, pin2bit(13), B_value); ic7404(ic_1); boolean a, b, x, y; a = bitRead(ic_1, pin2bit(4)); b = bitRead(ic_1, pin2bit(12)); x = bitRead(ic_1, pin2bit(2)); y = bitRead(ic_1, pin2bit(6)); if (debugPrintOK) { Serial.println("IC-1 7404"); displayPins(ic_1); } // It is pointless to invert a, b, x, y redundantly using // a the last two inverters of ic_1 and a second 7404 (IC 2 in diagram) // Proceed to the AND gates ... // uint16_t ic_3; // 7421 Dual 4-input AND // Recall that lower case variable represent negations bitWrite(ic_3, pin2bit(1), x); bitWrite(ic_3, pin2bit(2), Y_value); bitWrite(ic_3, pin2bit(4), a); bitWrite(ic_3, pin2bit(5), B_value); // bitWrite(ic_3, pin2bit(9), X_value); bitWrite(ic_3, pin2bit(10), y); bitWrite(ic_3, pin2bit(12), A_value); bitWrite(ic_3, pin2bit(13), b); ic7421(ic_3); C = bitRead(ic_3, pin2bit(6)); D = bitRead(ic_3, pin2bit(8)); // if (debugPrintOK) { Serial.println("IC-3 7421"); displayPins(ic_3); } uint16_t ic_4; // 7411 Triple 3-input AND bitWrite(ic_4, pin2bit(3), y); bitWrite(ic_4, pin2bit(4), a); bitWrite(ic_4, pin2bit(5), B_value); // bitWrite(ic_4, pin2bit(9), x); bitWrite(ic_4, pin2bit(10), A_value); bitWrite(ic_4, pin2bit(11), b); ic7411(ic_4); E = bitRead(ic_4, pin2bit(6)); F = bitRead(ic_4, pin2bit(8)); // if (debugPrintOK) { Serial.println("IC-4 7411"); displayPins(ic_4); } // The following could use the third AND gate of the 7411 // Code as a separate 2-input gate for clarity // uint16_t ic_5; // 7408 Quad 2-input AND bitWrite(ic_5, pin2bit(1), Y_value); bitWrite(ic_5, pin2bit(2), X_value); ic7408(ic_5); // if (debugPrintOK) { Serial.println("IC-5 7408"); displayPins(ic_5); } // Fudge 'not' in next to respect common-high of original // // Debug using outputs D1, D2, D3 of L1_state, L2_state, and L3_state, respectively int D1, D2, D3; D3 = not(bitRead(ic_5, pin2bit(3))); // uint16_t ic_6; // 7432 Quad 2-input OR bitWrite(ic_6, pin2bit(1), C); bitWrite(ic_6, pin2bit(2), D); // bitWrite(ic_6, pin2bit(4), E); bitWrite(ic_6, pin2bit(5), F); ic7432(ic_6); D1 = bitRead(ic_6, pin2bit(3)); D2 = not (bitRead(ic_6, pin2bit(6))); // See note for L3_state (above) if (debugPrintOK) { Serial.print("Dummy outputs D1, D2, D3: "); Serial.print(D1); Serial.print(D2); Serial.print(D3); Serial.println(" (good, open, short)"); } debugPrintOK = false; if (statusPrintOK) { // Original TTL circuit output sense if (D1 == 1) Serial.println("Good!"); if (D2 == 0) Serial.println("Open!"); if (D3 == 0) Serial.println("Short!"); } if (LED_jig) { // Physical LEDs L1_state = D1; L2_state = not D2; // Double not to cancel it = Logic Friday output L3_state = not D3; // Ditto digitalWrite(L1, L1_state); // Invert output if ON = LOW (false) digitalWrite(L2, L2_state); digitalWrite(L3, L3_state); } return; } // Below this line DEBUG utilities only void displayOutput() { // Reserved // In place of LED's // Alternatively output text to an accessory display } void detailPrint() { Serial.print("A = "); Serial.println(A_value); // Internal logic circuit values (analysis) Serial.print("B = "); Serial.println(B_value); // Internal logic circuit values (analysis) Serial.print("C = nand(A, X) = "); Serial.println(C); Serial.print("D = nand(B, Y) = "); Serial.println(D); Serial.print("E = nand(X, Y) = "); Serial.println(E); Serial.print("F = and(C, D) = "); Serial.println(F); Serial.print("J = nand(E, F) = "); Serial.println(J); Serial.print("P = not(J) = "); Serial.println(P); Serial.print("Q = xor(A, B) = "); Serial.println(Q); Serial.print("M = nand(P, Q) = "); Serial.println(M); Serial.print("N = and(E, Q) = "); Serial.println(N); Serial.print("X = "); Serial.println(X_value); // Internal logic circuit values (analysis) Serial.print("Y = "); Serial.println(Y_value); // Internal logic circuit values (analysis) // Serial.print("L1= and(M, N) = "); Serial.print(L1_state); Serial.println(" (Good 1=ON)"); Serial.print("L2= not(M) = "); // LEDs L2 and L3 are sink = on (common +) Serial.print(L2_state); Serial.println(" (Open 0=ON)"); Serial.print("L3= not(E) = "); Serial.print(L3_state); Serial.println(" (Short 0=ON)"); } void testAny(uint16_t & testTTL) { unsigned int i; Serial.println("Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"); for (i=0; i<16; i++) bitWrite(testTTL, i, random(2)); // Power/Ground ignored in test for (i=0; i<16; i++) { Serial.print(" "); Serial.print(bitRead(testTTL, i)); // Before } Serial.println(); // Call TTL function to be tested here -> ic7400(testTTL); for (i=0; i<16; i++) { Serial.print(" "); Serial.print(bitRead(testTTL, i)); // After } Serial.println(); Serial.println(); } void displayPins(uint16_t testTTL) { unsigned int i; Serial.println("Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"); for (i=0; i<16; i++) { Serial.print(" "); Serial.print(bitRead(testTTL, i)); } Serial.println(); } void displayInputs() { Serial.println(); Serial.print("Coax center A: "); Serial.print(A_value); Serial.print(" Coax shield B: "); Serial.print(B_value); Serial.println(); Serial.print("Coax center X: "); Serial.print(X_value); Serial.print(" Coax shield Y: "); Serial.print(Y_value); Serial.println(); } void displayLEDs() { Serial.println(); Serial.print("LED 1: "); Serial.print(L1_state); Serial.println(" (Good 1=ON)"); Serial.print("LED 2: "); // LEDs L2 and L3 are sink = on (common +) Serial.print(L2_state); Serial.println(" (Open 0=ON)"); Serial.print("LED 3: "); Serial.print(L3_state); Serial.println(" (Short 0=ON)"); Serial.println(); }