#include <MD_Parola.h>
#include <MD_MAX72xx.h>

#include <MATRIX7219.h>

const byte latchPin = 19;// to latch the inputs into the registers
const byte clockPin = 22; // I choose the SCK pin
const byte dataPin  = 5; // I choose the MISO pin
uint32_t oldOptionSwitch = 0; // previous state of all the inputs
const int pulseWidth = 10; // pulse width in microseconds

#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 12 
#define CLK_PIN    18 //b
#define Data_PIN   23 //y
#define CS_PIN     15 //g
#define MAX_ZONES 8
MATRIX7219 mx(Data_PIN, CS_PIN, CLK_PIN, MAX_ZONES);
byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};
uint8_t  curText;
uint8_t zone = 0;
const char *pc[] =
{
  "y",
  "n",
  "M3",
  "M4",
  "M5",
  "M6",
  "M7",
  "M8",
  "M9",
  "M10",
  "M11",
  "M12",
};

typedef struct
{
  int id;
  int zone;
} buttonData;

#define NUM_BUTTONS 32
buttonData buttons[NUM_BUTTONS];

void setup() {
  for (int i=0; i< NUM_BUTTONS;i++){
    buttons[i].zone = i%3;
    buttons[i].id = i;
  }

  Serial.begin(9600);


  //init mux
  pinMode(clockPin, OUTPUT); // clock signal, idle LOW
  pinMode(latchPin, OUTPUT); // latch (copy input into registers), idle HIGH
  digitalWrite(latchPin, HIGH);

  mx.begin();
  mx.clear();
  mx.setBrightness(3);
}

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
  uint32_t optionSwitch = 0;
  for (int i = 24; i >= 0; i -= 8) {
    optionSwitch |= ((uint32_t)ReadOne165()) << i;
  }


  for (int i = 0; i < 32; i++) {
    if (bitRead(optionSwitch, i) != bitRead(oldOptionSwitch, i)) {
       Serial.print("Switch ");
       Serial.print(i);
       Serial.print(" is now ");
       Serial.println(bitRead(optionSwitch, i) == 0 ? "down ↓" : "up   ↑"); 
       if (bitRead(optionSwitch, i) == 1){
        onButtonPress(i);
       }    
    }
  }
  oldOptionSwitch = optionSwitch;
  mx.clear();
  mx.setRow(0, 255, zone);
  zone = (zone+1)%MAX_ZONES;
    
  delay(25);      // slow down the sketch to avoid switch bounce
}

void onButtonPress(int idx){
//mx.setRow(1, (255), idx);
 // mx.setRow(1, 1, idx);
  /*
  Serial.println("displaying ");
  Serial.print(buttons[idx].zone);
  Serial.print(' ');
  Serial.print(pc[0]);
  P.displayZoneText(buttons[idx].zone, pc[0] , PA_LEFT, 0, 0, PA_NO_EFFECT, PA_NO_EFFECT);*/
}

// 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);
}

74HC165
74HC165
74HC165
74HC165