#include <vo_stdio.h>
#include <string.h>
#include <stdlib.h>
#include <aucommon.h>
#include <vsrv.h>
#include <clockspeed.h>
#include <exec.h>
#include "auiadc.h"

#define ADC_RATES 8

struct SetAdc {
  u_int32 nominalRateX256;
  u_int16 cfVal;
  u_int16 adIntF;
} const __mem_y setAdc[ADC_RATES] = {
  {  4000L*256, ADC_CF_ADFS_24K , INTF_MAC1},
  {  8000L*256, ADC_CF_ADFS_48K , INTF_MAC1},
  { 16000L*256, ADC_CF_ADFS_96K , INTF_MAC1},
  { 24000L*256, ADC_CF_ADFS_24K , INTF_MAC0},
  { 32000L*256, ADC_CF_ADFS_192K, INTF_MAC1},
  { 48000L*256, ADC_CF_ADFS_48K , INTF_MAC0},
  { 96000L*256, ADC_CF_ADFS_96K , INTF_MAC0},
  {192000L*256, ADC_CF_ADFS_192K, INTF_MAC0},
};




auto void AudioCloseInput(void) {
  /* Shut down old interrupt, if exists. */
  PERIP(INT_ENABLE0_HP) &= ~(INTF_MAC0|INTF_MAC1);
}


/*
  Find best hardware settings for the given A/D samplerate.
*/
auto ioresult AudioSetRate(register s_int32 sampleRateX256,
			   register s_int16 hiBits) {
  if (!sampleRateX256) {
    sampleRateX256 = 48000L*256;
  }

  if (hiBits >= 0) {
    Disable();
    audioIn.wr = audioIn.rd = audioIn.buf;
    audioIn.flags &= ~AIN_32BIT;
    if (hiBits) {
      audioIn.flags |= AIN_32BIT;
    }
    Enable();
  }

  {
    u_int32 smallestError = 0x7FFFFFFF;
    u_int32 thisRateX256;
    int bestIdx = 0, i;


#if 0
    printf("SetAdc(%ld), perip %ld\n", rate, clockSpeed.peripClkHz);
#endif
    for (i=0; i<ADC_RATES; i++) {
      u_int32 err;
      thisRateX256 = (u_int32)
	((double)setAdc[i].nominalRateX256 * clockSpeed.peripClkHz *
	 (1.0 / 12288000.0) + 0.5);
      err = labs(thisRateX256 - sampleRateX256);
      if (err < smallestError) {
	smallestError = err;
	bestIdx = i;
	audioIn.sampleRateX256 = thisRateX256;
      }
    }

    PERIP(INT_ENABLE0_HP) &= ~(INTF_MAC0|INTF_MAC1);
    PERIP(INT_ENABLE0_HP) |= setAdc[bestIdx].adIntF;
    PERIP(ADC_CF) = (ADC_CF_ENABLE | ADC_CF_DEC6ENA | ADC_CF_FILTENA) |
      setAdc[bestIdx].cfVal;
  }
  return S_OK;
}
