// File : Cascade165.ino
//
// Version 1, 5 August 2021, by Koepel
// Initial version.
// Version 2, 5 August 2021, by Koepel
// Layout of the wiring made better.
// Version 3, 13 August 2021, by Koepel
// Changed 'SCK' to 'clockPin'.
//
// Cascade of four 74HC165 shift-in registers.
// Only three pins are used on the Arduino board, to read 32 switches.
//
// Using the 74HC165 is safe, because a pulse to the Latch pin
// ('PL' on the 74HC165) will make a new start every time.
// In case of an error or a wrong clock pulse by noise,
// it synchronizes the data when inputs are read the next time.
//
// Based on:
// (1)
// Demo sketch to read from a 74HC165 input shift register
// by Nick Gammon, https://www.gammon.com.au/forum/?id=11979
// (2)
// 74HC165 Shift register input example
// by Uri Shaked, https://wokwi.com/arduino/projects/306031380875182657
//
//
#include <EncButton.h>
#define reg 8 // количество регистров
const byte latchPin = 9; // to latch the inputs into the registers
const byte clockPin = 13; // I choose the SCK pin
const byte dataPin = 12; // I choose the MISO pin
uint64_t oldOptionSwitch = 0; // previous state of all the inputs
const int pulseWidth = 10; // pulse width in microseconds
VirtButton btn1;
VirtButton btn2;
VirtButton btn3;
VirtButton btn4;
VirtButton btn5;
VirtButton btn6;
VirtButton btn7;
VirtButton btn8;
VirtButton btn9;
VirtButton btn10;
VirtButton btn11;
VirtButton btn12;
VirtButton btn13;
VirtButton btn14;
VirtButton btn15;
VirtButton btn16;
VirtButton btn17;
VirtButton btn18;
VirtButton btn19;
VirtButton btn20;
VirtButton btn21;
VirtButton btn22;
VirtButton btn23;
VirtButton btn24;
VirtButton btn25;
VirtButton btn26;
VirtButton btn27;
VirtButton btn28;
VirtButton btn29;
VirtButton btn30;
VirtButton btn31;
VirtButton btn32;
VirtButton btn33;
VirtButton btn34;
VirtButton btn35;
VirtButton btn36;
VirtButton btn37;
VirtButton btn38;
VirtButton btn39;
VirtButton btn40;
VirtButton btn41;
VirtButton btn42;
VirtButton btn43;
VirtButton btn44;
VirtButton btn45;
VirtButton btn46;
VirtButton btn47;
VirtButton btn48;
VirtButton btn49;
VirtButton btn50;
VirtButton btn51;
VirtButton btn52;
VirtButton btn53;
VirtButton btn54;
VirtButton btn55;
VirtButton btn56;
VirtButton btn57;
VirtButton btn58;
VirtButton btn59;
VirtButton btn60;
VirtButton btn61;
VirtButton btn62;
VirtButton btn63;
VirtButton btn64;
void setup ()
{
Serial.begin( 115200);
Serial.println( "Запуск мк с кнопками 56");
Serial.println( "Битрейт 115200");
pinMode( clockPin, OUTPUT); // clock signal, idle LOW
pinMode( latchPin, OUTPUT); // latch (copy input into registers), idle HIGH
digitalWrite( latchPin, HIGH);
Serial.println( "Инициализация сдвиговых регистров");
}
void loop ()
{
// Give a pulse to the parallel load latch of all 74HC165
digitalWrite( latchPin, LOW);
delayMicroseconds( pulseWidth);
digitalWrite( latchPin, HIGH);
// Reading one 74HC165 at a time and combining them into a 32 bit variable
// The last 74HC165 is at the bottom, but the switches start numbering
// at the top. So the first byte has to be shifted into the highest place.
uint64_t optionSwitch = 0;
for( int i=reg*8-8; i>=0; i-=8)
{
optionSwitch |= ((uint64_t) ReadOne165()) << i;
}
/*
for( int i = 0; i<reg*8; i++)
{
if( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch,i))
{
Serial.print( "Switch ");
if( i < 10)
Serial.print( " ");
Serial.print( i);
Serial.print( " is now ");
Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up ↑");
}
}
*/
oldOptionSwitch = optionSwitch;
btn1.tick(bitRead(optionSwitch, 0));
btn2.tick(bitRead(optionSwitch, 1));
btn3.tick(bitRead(optionSwitch, 2));
btn4.tick(bitRead(optionSwitch, 3));
btn5.tick(bitRead(optionSwitch, 4));
btn6.tick(bitRead(optionSwitch, 5));
btn7.tick(bitRead(optionSwitch, 6));
btn8.tick(bitRead(optionSwitch, 7));
btn9.tick(bitRead(optionSwitch, 8));
btn10.tick(bitRead(optionSwitch, 9));
btn11.tick(bitRead(optionSwitch, 10));
btn12.tick(bitRead(optionSwitch, 11));
btn13.tick(bitRead(optionSwitch, 12));
btn14.tick(bitRead(optionSwitch, 13));
btn15.tick(bitRead(optionSwitch, 14));
btn16.tick(bitRead(optionSwitch, 15));
btn17.tick(bitRead(optionSwitch, 16));
btn18.tick(bitRead(optionSwitch, 17));
btn19.tick(bitRead(optionSwitch, 18));
btn20.tick(bitRead(optionSwitch, 19));
btn21.tick(bitRead(optionSwitch, 20));
btn22.tick(bitRead(optionSwitch, 21));
btn23.tick(bitRead(optionSwitch, 22));
btn24.tick(bitRead(optionSwitch, 23));
btn25.tick(bitRead(optionSwitch, 24));
btn26.tick(bitRead(optionSwitch, 25));
btn27.tick(bitRead(optionSwitch, 26));
btn28.tick(bitRead(optionSwitch, 27));
btn29.tick(bitRead(optionSwitch, 28));
btn30.tick(bitRead(optionSwitch, 29));
btn31.tick(bitRead(optionSwitch, 30));
btn32.tick(bitRead(optionSwitch, 31));
btn33.tick(bitRead(optionSwitch, 32));
btn34.tick(bitRead(optionSwitch, 33));
btn35.tick(bitRead(optionSwitch, 34));
btn36.tick(bitRead(optionSwitch, 35));
btn37.tick(bitRead(optionSwitch, 36));
btn38.tick(bitRead(optionSwitch, 37));
btn39.tick(bitRead(optionSwitch, 38));
btn40.tick(bitRead(optionSwitch, 39));
btn41.tick(bitRead(optionSwitch, 40));
btn42.tick(bitRead(optionSwitch, 41));
btn43.tick(bitRead(optionSwitch, 42));
btn44.tick(bitRead(optionSwitch, 43));
btn45.tick(bitRead(optionSwitch, 44));
btn46.tick(bitRead(optionSwitch, 45));
btn47.tick(bitRead(optionSwitch, 46));
btn48.tick(bitRead(optionSwitch, 47));
btn49.tick(bitRead(optionSwitch, 48));
btn50.tick(bitRead(optionSwitch, 49));
btn51.tick(bitRead(optionSwitch, 50));
btn52.tick(bitRead(optionSwitch, 51));
btn53.tick(bitRead(optionSwitch, 52));
btn54.tick(bitRead(optionSwitch, 53));
btn55.tick(bitRead(optionSwitch, 54));
btn56.tick(bitRead(optionSwitch, 55));
btn57.tick(bitRead(optionSwitch, 56));
btn58.tick(bitRead(optionSwitch, 57));
btn59.tick(bitRead(optionSwitch, 58));
btn60.tick(bitRead(optionSwitch, 59));
btn61.tick(bitRead(optionSwitch, 60));
btn62.tick(bitRead(optionSwitch, 61));
btn63.tick(bitRead(optionSwitch, 62));
btn64.tick(bitRead(optionSwitch, 63));
if (btn1.press()) Serial.println ("Press btn1");
if (btn2.press()) Serial.println ("Press btn2");
if (btn3.press()) Serial.println ("Press btn3");
if (btn4.press()) Serial.println ("Press btn4");
if (btn5.press()) Serial.println ("Press btn5");
if (btn6.press()) Serial.println ("Press btn6");
if (btn7.press()) Serial.println ("Press btn7");
if (btn8.press()) Serial.println ("Press btn8");
if (btn9.press()) Serial.println ("Press btn9");
if (btn10.press()) Serial.println ("Press btn10");
if (btn11.press()) Serial.println ("Press btn11");
if (btn12.press()) Serial.println ("Press btn12");
if (btn13.press()) Serial.println ("Press btn13");
if (btn14.press()) Serial.println ("Press btn14");
if (btn15.press()) Serial.println ("Press btn15");
if (btn16.press()) Serial.println ("Press btn16");
if (btn17.press()) Serial.println ("Press btn17");
if (btn18.press()) Serial.println ("Press btn18");
if (btn19.press()) Serial.println ("Press btn19");
if (btn20.press()) Serial.println ("Press btn20");
if (btn21.press()) Serial.println ("Press btn21");
if (btn22.press()) Serial.println ("Press btn22");
if (btn23.press()) Serial.println ("Press btn23");
if (btn24.press()) Serial.println ("Press btn24");
if (btn25.press()) Serial.println ("Press btn25");
if (btn26.press()) Serial.println ("Press btn26");
if (btn27.press()) Serial.println ("Press btn27");
if (btn28.press()) Serial.println ("Press btn28");
if (btn29.press()) Serial.println ("Press btn29");
if (btn30.press()) Serial.println ("Press btn30");
if (btn31.press()) Serial.println ("Press btn31");
if (btn32.press()) Serial.println ("Press btn32");
if (btn33.press()) Serial.println ("Press btn33");
if (btn34.press()) Serial.println ("Press btn34");
if (btn35.press()) Serial.println ("Press btn35");
if (btn36.press()) Serial.println ("Press btn36");
if (btn37.press()) Serial.println ("Press btn37");
if (btn38.press()) Serial.println ("Press btn38");
if (btn39.press()) Serial.println ("Press btn39");
if (btn40.press()) Serial.println ("Press btn40");
if (btn41.press()) Serial.println ("Press btn41");
if (btn42.press()) Serial.println ("Press btn42");
if (btn43.press()) Serial.println ("Press btn43");
if (btn44.press()) Serial.println ("Press btn44");
if (btn45.press()) Serial.println ("Press btn45");
if (btn46.press()) Serial.println ("Press btn46");
if (btn47.press()) Serial.println ("Press btn47");
if (btn48.press()) Serial.println ("Press btn48");
if (btn49.press()) Serial.println ("Press btn49");
if (btn50.press()) Serial.println ("Press btn50");
if (btn51.press()) Serial.println ("Press btn51");
if (btn52.press()) Serial.println ("Press btn52");
if (btn53.press()) Serial.println ("Press btn53");
if (btn54.press()) Serial.println ("Press btn54");
if (btn55.press()) Serial.println ("Press btn55");
if (btn56.press()) Serial.println ("Press btn56");
if (btn57.press()) Serial.println ("Press btn57");
if (btn58.press()) Serial.println ("Press btn58");
if (btn59.press()) Serial.println ("Press btn59");
if (btn60.press()) Serial.println ("Press btn60");
if (btn61.press()) Serial.println ("Press btn61");
if (btn62.press()) Serial.println ("Press btn62");
if (btn63.press()) Serial.println ("Press btn63");
if (btn64.press()) Serial.println ("Press btn64");
delay( 25); // slow down the sketch to avoid switch bounce
}
// The ReadOne165() function reads only 8 bits,
// because of the similar functions shiftIn() and SPI.transfer()
// which both use 8 bits.
//
// The shiftIn() can not be used here, because the clock is set idle low
// and the shiftIn() makes the clock high to read a bit.
// The 74HC165 require to read the bit first and then give a clock pulse.
//
byte ReadOne165()
{
byte ret = 0x00;
// The first one that is read is the highest bit (input D7 of the 74HC165).
for( int i=7; i>=0; i--)
{
if( digitalRead( dataPin) == HIGH)
bitSet( ret, i);
digitalWrite( clockPin, HIGH);
delayMicroseconds( pulseWidth);
digitalWrite( clockPin, LOW);
}
return( ret);
}