/***************************************************
*  TBIB_Slave.h
*
*  handles the Two-Bit-Interface-Bus protocol as a Slave
*
*  main program
*    in setup call
*      InitTBIBpins(); 
*
*    in main loop call
*      PollTBIB(); 
*      
*    to send a byte call
*      SendByteToMaster(b);
*
*  main program must include a declaration of
*    recvTBIB(byte b) {}
*  which will be called whenever a byte is received
*  
*****************************************************/

#ifndef TBIB_Slave_h
#define TBIB_Slave_h

const int pinMISOa = 6;
const int pinMOSIa = 7;
const int pinMCLK = 4;
const int pinSCLK = 5;
byte bOut = 0;
byte nOut = 0;

void SendByteToMaster(byte b);
void SetTBIBpins();
void PollTBIB();
void recvTBIB(byte b);
//void SendStrToSlave(char *s);

//-----------------------------------------------------------
// SendByteToMaster
//-----------------------------------------------------------
void SendByteToMaster(byte b) {
  bOut = b;
  nOut = 9;
  while (nOut > 0)
    PollTBIB();
}

//-----------------------------------------------------------
// SetTBIBpins() 
//-----------------------------------------------------------
void SetTBIBpins() {
  pinMode(pinMISOa, OUTPUT);    digitalWrite(pinMISOa, LOW);
  pinMode(pinSCLK, OUTPUT);     digitalWrite(pinSCLK, LOW);
  pinMode(pinMOSIa, INPUT);   
  pinMode(pinMCLK, INPUT);    
}

//-----------------------------------------------------------
// PollTBIB() 
//   on entry and exit, both CLKs are low 
//-----------------------------------------------------------
void PollTBIB() {
  static byte bIn = 0;
  static byte nIn = 0;
  bool bMOSI;
  static bool bWaitForCLKhigh = true;
  bool haveReceivedByte = false;

  if (bWaitForCLKhigh) {
    // wait for MCLK
    if (!digitalRead(pinMCLK)) 
      return;
  
    // can change MISO  
    if (nOut == 9) {
      digitalWrite(pinMISOa, true);
      nOut--;
    } else 
    if (nOut > 0) {
      digitalWrite(pinMISOa, bOut & 1);
      nOut--;
      bOut = (bOut >> 1) & 0x7F;
    } else 
      digitalWrite(pinMISOa, false);
    
    // read MOSI
    bMOSI = digitalRead(pinMOSIa);
    if ((nIn == 0) && bMOSI)
    { // start of incoming data
      nIn = 8;
    } else
    if (nIn > 0) {
      bIn = (bIn >> 1) & 0x7F;
      if (bMOSI)
        bIn += 0x80;
      nIn--;
      if (nIn == 0) 
        haveReceivedByte = true; 
    }
  
    // set SCLK = true
    digitalWrite(pinSCLK, true);

    bWaitForCLKhigh = false;
  } else {
    // wait for ! MCLK
    if (digitalRead(pinMCLK)) 
      return;
    
    // set SCLK = false  
    digitalWrite(pinSCLK, false);

    bWaitForCLKhigh = true;
  }

  if (haveReceivedByte) {
    haveReceivedByte = false;
    recvTBIB(bIn);
  }
}

//void PollTBIB() {
//  static byte bIn = 0;
//  static byte nIn = 0;
//  bool bMOSI;
//  bool bMCLK;
//  static bool bWaitForCLKhigh = true;
//  bool haveReceivedByte = false;
//
//  static bool prevMOSI = false;
//  static bool prevMCLK = false;
//
//  bMOSI = digitalRead(pinMOSIa);
//  bMCLK = digitalRead(pinMCLK);
//
////  if ((prevMOSI != bMOSI) || (prevMCLK != bMCLK)) {
////    Serial.print(bMCLK);
////    Serial.println(bMOSI);
////  }
////  prevMOSI = bMOSI;
////  prevMCLK = bMCLK;
//
//  if (bWaitForCLKhigh) {
//    // wait for MCLK
//    if (!bMCLK) 
//      return;
//  
//    // can change MISO  
//    if (nOut == 9) {
//      digitalWrite(pinMISOa, true);
//      nOut--;
//    } else 
//    if (nOut > 0) {
//      digitalWrite(pinMISOa, bOut & 1);
//      nOut--;
//      bOut = (bOut >> 1) & 0x7F;
//    } else 
//      digitalWrite(pinMISOa, false);
//    
//    // read MOSI
//    if ((nIn == 0) && bMOSI)
//    { // start of incoming data
//      nIn = 8;
//    } else
//    if (nIn > 0) {
//      bIn = (bIn >> 1) & 0x7F;
//      if (bMOSI)
//        bIn += 0x80;
//      nIn--;
//      if (nIn == 0) 
//        haveReceivedByte = true; 
//    }
//  
//    // set SCLK = true
//    digitalWrite(pinSCLK, true);
//
//    bWaitForCLKhigh = false;
//  } else {
//    // wait for ! MCLK
//    if (bMCLK)
//      return;
//    
//    // set SCLK = false  
//    digitalWrite(pinSCLK, false);
//
//    bWaitForCLKhigh = true;
//  }
//
//  if (haveReceivedByte) {
//    haveReceivedByte = false;
//    recvTBIB(bIn);
//  }
//}

#endif
