// The implementation file for DDSDualModule.h
// These functions provide the interface to both the modules through a single object.

#include "DDSDualModule.h"

DDSDualModule::DDSDualModule(int resetPin, int freqUpdatePin, int dataPin, int clockPinA, int clockPinB) {
    PIN_RESET = resetPin;
    PIN_FREQUENCY_UPDATE = freqUpdatePin;
    PIN_DATA_IN = dataPin;
    
    OneHzPhaseWord = 34.35973837;
    
    _ddsA = new DDSModule(clockPinA);
    _ddsB = new DDSModule(clockPinB); 
  
    pinMode(PIN_RESET, OUTPUT);  
    pinMode(PIN_FREQUENCY_UPDATE, OUTPUT); 
    pinMode(PIN_DATA_IN, OUTPUT); 
    
    digitalWrite(PIN_RESET, LOW);
    digitalWrite(PIN_FREQUENCY_UPDATE, LOW);
    digitalWrite(PIN_DATA_IN, LOW);
    
    SetFreq(10000000); // 10 MHz
    SetBSin();
    //SetBSin();
    SetACos();
    WriteControlBits();
  
}

void DDSDualModule::SetFreq(long freqHz) { 
  Serial.print("Freq Set: ");
  Serial.print(freqHz);
  Serial.println("Hz");
  _freq = floor(freqHz * OneHzPhaseWord);
  //Serial.print("Freq calculated:");
  //Serial.println(_freq);
  WriteControlBits();

}

void DDSDualModule::SetASin() {
    Serial.println("Set A sin");
    _ddsA->SetStartAtSin(true);
    WriteControlBits();
}

void DDSDualModule::SetACos() {
     Serial.println("Set A cos");
    _ddsA->SetStartAtSin(false);
    WriteControlBits();
}

void DDSDualModule::SetBSin() {
     Serial.println("Set b sin");
     _ddsB->SetStartAtSin(true);
     WriteControlBits();
}

void DDSDualModule::SetBCos() {
     Serial.println("Set b cos");
    _ddsB->SetStartAtSin(false);
    WriteControlBits();
}

void DDSDualModule::InitDDS() {
   ResetPulse();
   PulseWriteClockA();
   PulseWriteClockB();
   FreqUpdatePulse();
}

// Send all control bits, frequency and control byte. (40 bits)
void DDSDualModule::WriteControlBits() {
    //Serial.println("Writing control bits");
  
    // This is performing :void  InitialiseDDS()  from JCcode
    InitDDS();
   
    // Clear DDS A
    SerialiseToPin(0, 32, _ddsA->GetClockPin());
    SerialiseToPin(0, 8, _ddsA->GetClockPin());

    // Clear DDS B    
    SerialiseToPin(0, 32, _ddsB->GetClockPin());
    SerialiseToPin(0, 8, _ddsB->GetClockPin());
  
    FreqUpdatePulse();
    
    InitDDS();
        
     // DDS A actual values
    SerialiseToPin(_freq, 32, _ddsA->GetClockPin());
    SerialiseToPin(_ddsA->GetControlByte(), 8, _ddsA->GetClockPin());
 
    // DDS B actual values
    SerialiseToPin(_freq, 32, _ddsB->GetClockPin());
    SerialiseToPin(_ddsB->GetControlByte(), 8, _ddsB->GetClockPin());
       
    FreqUpdatePulse();
}


void DDSDualModule::PulseWriteClockA() {
  // Send 0,1,0 to 
  digitalWrite(_ddsA->GetClockPin(), LOW);
  digitalWrite(_ddsA->GetClockPin(), HIGH);
  digitalWrite(_ddsA->GetClockPin(), LOW);
}

void DDSDualModule::PulseWriteClockB() {
  // Send 0,1,0 to 
  digitalWrite(_ddsB->GetClockPin(), LOW);
  digitalWrite(_ddsB->GetClockPin(), HIGH);
  digitalWrite(_ddsB->GetClockPin(), LOW);
}


void DDSDualModule::SerialiseToPin(long bits, int numberOfBitsToSend, int clockPin) {
  digitalWrite(clockPin, LOW);
  
  for(int i = 0; i < numberOfBitsToSend; i++) {
      if (bitRead(bits, i)) {
         digitalWrite(PIN_DATA_IN, HIGH);
      } else {
         digitalWrite(PIN_DATA_IN, LOW);
      }
      digitalWrite(clockPin, HIGH);
      digitalWrite(clockPin, LOW);    
  }
    
}


void DDSDualModule::FreqUpdatePulse() {
    digitalWrite(PIN_FREQUENCY_UPDATE, LOW);
    digitalWrite(PIN_FREQUENCY_UPDATE, HIGH);
    digitalWrite(PIN_FREQUENCY_UPDATE, LOW);
}

void DDSDualModule::ResetPulse() {
    digitalWrite(PIN_RESET, LOW);
    digitalWrite(PIN_RESET, HIGH);
    digitalWrite(PIN_RESET, LOW);
}

