//----------------------------------------------------------------------------
// HACSOUND                                                   19950907 CHG
//
// HACBUS:
//   Device type: 0x04             ; HACSOUND type
//   Address    : 0x01..0x0F       ; Address 1..15
//   Commands   : 0x00             ; Poll
//          Resp: 0x80
//              : 0x01 CL CR       ; Set channel for left and right
//          Resp: 0x81
//              : 0x02 VL VR B T   ; Set sound parameters (Vol L/R, Bass, Treb)
//          Resp: 0x82
//              : 0x03 M           ; Mute=1, No mute=0
//          Resp: 0x83
//----------------------------------------------------------------------------
#include <reg2051.h>
#include <stdio.h>
#include "..\HACNET\HACNET.H"

//----------------------------------------------------------------------------
// Constants...
//----------------------------------------------------------------------------
#define TRUE   1
#define FALSE  0

#define Left   1
#define Right  0
#define I2CDELAY 0
#define MyDeviceType 0x04
#define RxSize 6+3             // Maximum size of RxBuffer

//----------------------------------------------------------------------------
// I/O definitions...
//----------------------------------------------------------------------------
#define MuxLA0  P34    // Analog Mux left channel, Address 0
#define MuxLA1  P35    // Analog Mux left channel, Address 1
#define MuxLA2  P37    // Analog Mux left channel, Address 2

#define MuxRA0  P10    // Analog Mux right channel, Address 0
#define MuxRA1  P12    // Analog Mux right channel, Address 1
#define MuxRA2  P11    // Analog Mux right channel, Address 2

#define SDA     P32    // I2C SDA pin for TEA6330T
#define SCL     P33    // I2C SCL pin for TEA6330T

//----------------------------------------------------------------------------
// Variables...
//----------------------------------------------------------------------------

unsigned char RxBuffer[RxSize];       // RxBuffer
extern bit RxAvail;                   // Message available in RX Buffer
extern bit Resend;                    // Resend last response

//----------------------------------------------------------------------------
// wait for a specific time in 10 mSec
// Based on a 11.059 MHz crystal
//----------------------------------------------------------------------------
void Delay(unsigned char t) {
  unsigned int i;
  if (t==0) return;
  while (t--) for(i=0;i<774; i++);
}


//----------------------------------------------------------------------------
// Send one byte out on I2C
// Returns: 0 if ack was ok
//          1 if no ack found
//----------------------------------------------------------------------------
unsigned char SendI2CByte(unsigned char Data) {
  unsigned char i;
  // Send byte...
  for (i=0; i<8; i++) {
    SDA=(Data & 0x80); // Send out the bit
    Data<<=1;          // Advance to next bit
    Delay(I2CDELAY);
    SCL=1;
    Delay(I2CDELAY);
    SCL=0;
    Delay(I2CDELAY);
  }
  SDA=1;
  SCL=1;
  // Check acknowledge...
  if (SDA) {
    SCL=0;
    return 1;
  } else {
    SCL=0;
    return 0;
  }
}

//----------------------------------------------------------------------------
// Send Start and Address and SubAddress
// Returns: 0 if ack was ok
//          1 if no ack found
//          2 bus fault
//----------------------------------------------------------------------------
unsigned char SendI2CStartAddress(unsigned char Address, unsigned char SubAddress) {
  // if either SDA or SCL isn't high, we have a bus fault...
  if ((SCL!=1) || (SDA!=1)) return 2;
  SDA=0;
  Delay(I2CDELAY);
  SCL=0;
  Delay(I2CDELAY);
  // Send address out, return if no ack...
  if (SendI2CByte(Address)) return 1;
  // Send SubAddress out, return if no ack...
  if (SendI2CByte(SubAddress)) return 1;
  return 0;
}

//----------------------------------------------------------------------------
// StopI2C communication
//----------------------------------------------------------------------------
void StopI2C(void) {
  SDA=0;
  Delay(I2CDELAY);
  SCL=1;
  Delay(I2CDELAY);
  SDA=1;
  Delay(I2CDELAY);
}

//----------------------------------------------------------------------------
// Send string out
// Returns: 0 if ack was ok
//          1 if no ack found
//          2 bus fault
//----------------------------------------------------------------------------
unsigned char SendI2CString(unsigned char Address, unsigned char SubAddress,
                            unsigned char *Data, unsigned char Length) {
  unsigned char rc;
  rc=SendI2CStartAddress(Address, SubAddress);
  if (rc) {
    StopI2C();
    return rc;
  }
  while (Length--) {
    // Send byte...
    rc=SendI2CByte(*Data++);
    // Check if error, and return if any...
    if (rc) {
      StopI2C();
      return rc;
    }
  }
  // Finished, stop communication...
  StopI2C();
  return 0;
}


//----------------------------------------------------------------------------
// Select channel 0..7 on Analog MUX for left or right side.
//----------------------------------------------------------------------------
void SetChannel(unsigned char side, unsigned char Channel) {
  if (side==Left) {
    MuxLA0=((Channel & 0x01)==0x01);
    MuxLA1=((Channel & 0x02)==0x02);
    MuxLA2=((Channel & 0x04)==0x04);
  } else {
    MuxRA0=((Channel & 0x01)==0x01);
    MuxRA1=((Channel & 0x02)==0x02);
    MuxRA2=((Channel & 0x04)==0x04);
  }
}

//----------------------------------------------------------------------------
// Set volume for left or right
// Input : 0 = mute, 1 = -66db, 44 = +20db, in 2db increments
//----------------------------------------------------------------------------
void SetVolume(unsigned char side, unsigned char value) {
  unsigned char rc, Data;
  Data=value+19;
  if (side==Left)
    rc=SendI2CString(0x80, 0x00, &Data, 1);
  else
    rc=SendI2CString(0x80, 0x01, &Data, 1);
}

//----------------------------------------------------------------------------
// Set Bass for left and right
// Input : 0 = -12db, 4 = 0db, 9 = +15db, in 3db increments
//----------------------------------------------------------------------------
void SetBass(unsigned char value) {
  unsigned char rc, Data;
  Data=value+3;
  rc=SendI2CString(0x80, 0x02, &Data, 1);
}

//----------------------------------------------------------------------------
// Set Treble for left and right
// Input : 0 = -12db, 4 = 0db, 8 = +12db, in 3db increments
//----------------------------------------------------------------------------
void SetTreble(unsigned char value) {
  unsigned char rc, Data;
  Data=value+3;
  rc=SendI2CString(0x80, 0x03, &Data, 1);
}

//----------------------------------------------------------------------------
// Set muting option
//----------------------------------------------------------------------------
void SetMute(unsigned char Mute) {
  unsigned char rc, Data;
  if (Mute)
    // Mute and No equalizer
    Data=0xC0;
  else
    // No Mute and No equalizer
    Data=0x40;
  rc=SendI2CString(0x80, 0x05, &Data, 1);
}

//----------------------------------------------------------------------------
// Main part
//----------------------------------------------------------------------------
void main() {
  unsigned char Data;
  unsigned char Rsp[1];                       // Buffer for responses
  unsigned char MyAddress;      // My assigned address on the Dip switches.

 //----------------------------------------------------------------------------
 // Initalize HACNET Driver
 //----------------------------------------------------------------------------
  MyAddress=InitHACNET(MyDeviceType, RxSize);

 //---------------------------------
 // Initialize outputs...
 //---------------------------------
  SetChannel(Left,0);     // Select channel 0
  SetChannel(Right,0);    // for both sides...
  SetVolume(Left,0);      // Set volume to mute
  SetVolume(Right,0);     // for both sides...
  SetBass(4);             // Set Bass to 0 db
  SetTreble(4);           // Set Treble to 0 db
  // Set fader to -84 db rear, 0 db front
  Data=0x00;
  SendI2CString(0x80, 0x04, &Data, 1);
  // No muting
  SetMute(FALSE);

 //------------------------------
 // Configure onchip resources...
 //------------------------------

  EA=1;        // Global int enable

  //----------------------------------------------------------------------------
  // Forever
  //----------------------------------------------------------------------------

  while(1) {
    //----------------------------------------------------------------------------
    // Diagnostic mode, Address is 0x00
    //----------------------------------------------------------------------------
    if (MyAddress==0) {
      Delay(255);
      SetVolume(Left,21);      // Set volume to -30db
      SetVolume(Right,21);     // for both sides...
    //  HacTransmit("DIAG\n\r",6);
    } else {
    //----------------------------------------------------------------------------
    // Normal mode
    //----------------------------------------------------------------------------
      // Check if we have to resend last response...
      if (Resend) {
        Resend=FALSE;
//        Delay(200);
        HacTransmit(Rsp, 0xFF);
      }
      if (RxAvail) {
//        Delay(200);
        switch (RxBuffer[0]) {
          case 0 :
            Rsp[0]=0x80; // Response code
            HacTransmit(Rsp, 1); // Empty response
            break;
          case 1 :
            SetChannel(Left, RxBuffer[1]);
            SetChannel(Right, RxBuffer[2]);
            Rsp[0]=0x81; // Response code
            HacTransmit(Rsp, 1); // Empty response
            break;
          case 2 :
            SetVolume(Left,RxBuffer[1]);
            SetVolume(Right,RxBuffer[2]);
            SetBass(RxBuffer[3]);
            SetTreble(RxBuffer[4]);
            Rsp[0]=0x82; // Response code
            HacTransmit(Rsp, 1); // Empty response
            break;
          case 3 :
            SetMute(RxBuffer[1]);
            Rsp[0]=0x83; // Response code
            HacTransmit(Rsp, 1); // Empty response
            break;
        }
        RxAvail=0;
      }
    }
  }
}
