/* ------------------------------------------------------
8 Bit ADC - ADS7830 device file
(C) Copyright 2008-2009 XJTAG Limited
Disclaimer: XJTAG makes no guarantees whatsoever
about this code.  You use it at your own risk.
This code requires XJTAG version 1.4.2 or later.
------------------------------------------------------
This device file has no test function, unlike most other 
device files, as there is no way to test a ADC on its own.
To use this file the ReadADC function should be called
from the CircuitTest.xje file after a stimulas has been
applied to the ADC.
The IIC_CheckPresent function can be used to test the
I2C interface without the need to stimulate the ADC inputs.
------------------------------------------------------ */
DEVICE NAME := "ADS7830"
  COMPAT_VERSION := 1;
  DESCRIPTION := "8 Bit 8 Channel ADC";

  PINS
    ADC_CH := 8, 7, 6, 5, 4, 3, 2, 1;
    VREF := 10;
    I2C_ADDR := 13, 12;
    GND := 9, 11;
    SCL := 14;
    SDA := 15;
    P3V3 := 16;
  END;

  DISABLE DEVICE
    SDA := Z;
  END;

  TEST COVERAGE
    SCL := OPEN LO HI;
    SDA := OPEN LO HI;
  END;

  // Additional files
  FILES
    "IIC.xje";
  END;
END;

//------------------------------------------------------------------
//I2C Constants
//------------------------------------------------------------------
CONST INT IIC_ADDRESS_BYTES := 1;
CONST INT IIC_WRITE_PAGE_SIZE := 1;
CONST INT IIC_READ_PAGE_SIZE := 1;
CONST INT IIC_ADDRESS := 0x90;

CONST INT ADC_BITS := 8;
CONST INT DEBUG := FALSE;

// Has the internal voltage reference been enabled?
INT InternalRefEnabled;

//------------------------------------------------------------------
EnableInternalRef(INT command)(INT result)
//------------------------------------------------------------------
  IIC_Write(command, 0, 0)(result);
  InternalRefEnabled := TRUE;
END;


//------------------------------------------------------------------
ReadADC(INT Channel, INT INTERNAL_REF_ON, INT REF_VOLTAGE)(INT mV, INT result)
//------------------------------------------------------------------
  INT byteRead, command WIDTH 8, chn_sel;

  ConvertChn(Channel)(chn_sel);
  command[7] := 1;                 // Single ended not differential read
  command[6..4] := chn_sel[2..0];  // The required channel
  command[3] := INTERNAL_REF_ON;   // 1 := Internal Ref ON, 0 := Use external Ref
  command[2] := 1;                 // A/D converter on
  command[1..0] := 0[1..0];        // Unused

  IF INTERNAL_REF_ON THEN
    REF_VOLTAGE := 2500;
    IF !InternalRefEnabled THEN
      EnableInternalRef(command)(result);
      IF result = RESULT_FAIL THEN
        PRINT("\nFailed to Enable ADC Internal Ref\n");
        RETURN;
      END;
    END;
  ELSE
    InternalRefEnabled := FALSE;
  END;

  IF DEBUG THEN PRINT("Command := 0b",BIN(command)," (0x",HEX(command),")\n"); END;
  IIC_Read(command, 1)(byteRead, result);  //IIC
  IF result THEN
    PRINT("\nFailed to read ADC Channel ",Channel,".\n");
    mV := 0;
    RETURN;
  END;
  mV := (REF_VOLTAGE * byteRead ) / ((1 << ADC_BITS)-1);
   
END;

//------------------------------------------------------------------
ConvertChn(INT Channel)(INT chn_sel)
//------------------------------------------------------------------
   IF (Channel = 0) THEN chn_sel := 0; END;
   IF (Channel = 1) THEN chn_sel := 4; END;
   IF (Channel = 2) THEN chn_sel := 1; END;
   IF (Channel = 3) THEN chn_sel := 5; END;
   IF (Channel = 4) THEN chn_sel := 2; END;
   IF (Channel = 5) THEN chn_sel := 6; END;
   IF (Channel = 6) THEN chn_sel := 3; END;
   IF (Channel = 7) THEN chn_sel := 7; END;
END;