
////////////////////////////////////////////////////////////////////////////
//// dac.c                                                              ////
////////////////////////////////////////////////////////////////////////////

void output_dac(float voltage) {

  long  i;

  int16 hexValue;
  float remedy;

  remedy = voltage;
  remedy *= 1024;
  remedy /= 5.0;

  hexValue = (int16) (remedy);
  // Anything above full scale should get full scale....
  if(hexValue > 0x3FF) {
    hexValue = 0x3FF;
  }

  output_high(DAC_SER_CLK);
  output_high(DAC_SER_LD);

  for(i = 1; i <= 10; i++) {
    output_low(DAC_SER_CLK);
    if(1 == bit_test(hexValue, (10 - i))) {
      output_high(DAC_SER_DATA);
    } else {
      output_low(DAC_SER_DATA);
    }
    output_high(DAC_SER_CLK);  
  }
  output_low(DAC_SER_CLK);
  output_low(DAC_SER_LD);

}


// Okay, so this doesn't have much to do with the DAC.
// It has more to do with the application.

// What we're trying to do here is set the DAC such that
// the differential mode ADC value will read 2.5 volts.
// This sets up the hyper-precise measurement mode.
// Note that the return value will be the initial value
// of the ADC.  This allows us to remember, PRECISELY, where
// we were when we started things.

// Note that it isn't super-important that we get to exactly
// 2.5 volts.  Something close is fine.  The remaining slop is
// subtracted out by remembering where we are when we start
// (hence the need to return adc[1] from this function).

float output_dac_zero(float target_voltage) {
  float dacVoltage;
  float dither = 0.0;
  float value;
  long  i;

  for(i = 0; i < 50; i++) {
    dacVoltage = d_adc_voltage[0] + (target_voltage / 4.7) + dither;
    output_dac(dacVoltage);
    delay_ms(50);
    refresh_adc(1);

    if((d_adc_voltage[1] - target_voltage) > 0.002) {
      dither -= 0.001;
    } else if((d_adc_voltage[1] - target_voltage) < -0.002) {
      dither += 0.001;
    } else {
      return(d_adc_voltage[1]);
    }
  }
  return(d_adc_voltage[1]);

}



void refresh_adc(long index) {
  long value;

  set_adc_channel(index);
  delay_us(20);
  value = read_adc();
  d_adc_voltage[index] = (float) value;
  d_adc_voltage[index] *= 0.004882813;  // Convert to Volts:  5V reference / 2^10
}


