// written by DedGzus [01/23/2024]
//
// send commands manually to an LCD using
// the switches
//
#include "CPU_S16.h"
#include <TinyDebug.h>
#define CPU_dataInPin PB3
#define CPU_dataOutPin PB0
#define CPU_IOSelectPin PB5
#define CPU_clockPin PB2
#define CPU_latchPin PB1
#define readDataBtn PB4
CPU_S16* pCPU;
char addr(0x0);
char ctrl(0x0);
char data(0x00);
void setup()
{
  // for debugging
  Debug.begin();
  // acquire a CPU_S16 with the pins
  pCPU = new CPU_S16(CPU_dataInPin,
                     CPU_dataOutPin,
                     CPU_IOSelectPin,
                     CPU_clockPin,
                     CPU_latchPin);
  // initialize the CPU
  pCPU->init();
  pinMode(readDataBtn, INPUT);
  // do initial setup of LCD
  pCPU->output(0x0,0x0,0x38);
  pCPU->output(0x0,0x0,0x0C);
  pCPU->output(0x0,0x0,0x06);
  pCPU->output(0x0,0x0,0x01);
  // display LCD splash screen
  pCPU->output(0x0,0x2,'1');
  pCPU->output(0x0,0x2,'6');
  pCPU->output(0x0,0x2,'-');
  pCPU->output(0x0,0x2,'b');
  pCPU->output(0x0,0x2,'i');
  pCPU->output(0x0,0x2,'t');
  pCPU->output(0x0,0x2,' ');
  pCPU->output(0x0,0x2,'S');
  pCPU->output(0x0,0x2,'e');
  pCPU->output(0x0,0x2,'r');
  pCPU->output(0x0,0x2,'i');
  pCPU->output(0x0,0x2,'a');
  pCPU->output(0x0,0x2,'l');
  pCPU->output(0x0,0x0,0xC6);
  pCPU->output(0x0,0x2,'P');
  pCPU->output(0x0,0x2,'r');
  pCPU->output(0x0,0x2,'o');
  pCPU->output(0x0,0x2,'c');
  pCPU->output(0x0,0x2,'e');
  pCPU->output(0x0,0x2,'s');
  pCPU->output(0x0,0x2,'s');
  pCPU->output(0x0,0x2,'o');
  pCPU->output(0x0,0x2,'r');
  delay(3000);
  // clear the LCD
  pCPU->output(0x0,0x0,0x01);
  
  // clear the output register
  pCPU->output(0x0,0x0,0x00);
  // read initial state of switches
  pCPU->input(&addr, &ctrl, &data);
}
void loop()
{
  static bool readBtnPressed = false;
  // if the button gets pressed read the switches
  if (!digitalRead(readDataBtn))
  {
    if (!readBtnPressed)
    {
      readBtnPressed = true;
      pCPU->input(&addr, &ctrl, &data);
      Debug.print(" IN: ");
      printBits(addr, ctrl, data);
    }
  }
  // output the bits when released
  else if (readBtnPressed)
  {
    readBtnPressed = false;
    pCPU->output(addr, ctrl, data);
    Debug.print("OUT: ");
    printBits(addr, ctrl, data);
  }
}
void printBits(byte addr, byte ctrl, byte data)
{
  Debug.print("addr[");
  // lower 4 bits of addr
  byte mask = 0b00001000;
  for (int i = 0; i != 4; i++)
  {
    Debug.print(addr & mask ? "1" : "0");
    mask >>= 1;
  }
  Debug.print("] ctrl[");
  // lower 4 bits of ctrl
  mask = 0b00001000;
  for (int i = 0; i != 4; i++)
  {
    Debug.print(ctrl & mask ? "1" : "0");
    mask >>= 1;
  }
  Debug.print("] data[");
  // 8 bits of data
  mask = 0b10000000;
  for (int i = 0; i != 8; i++)
  {
    Debug.print(data & mask ? "1" : "0");
    mask >>= 1;
  }
  Debug.println("]");
}address
address
control
control
data
data