
/**
 * AD567x.c
 * 
 * Function: Operating library of functions to manage a AD567(2/6) connected 
 * through SPI. These octal DACs have either 12 or 16-bit inputs, but 
 * communicate through a standard 24-bit width field. 
 * 
 * Required Definitions
 * @param AD567X_IS16BIT
 *  
 */

#include "AD567x.h"


/** Chip Definition
 * 
 * Select 1 for AD5676 and 0 for AD5672
 */
#define AD567X_IS16BIT 1

// Constants for DAC 
#define CSDAC _RG6
#define TCSDAC _TRISG6


/** Section: Data Type definitions */

typedef union {
    uint16_t value;
    uint8_t bytes[2];
} AD567x_DATABITS;

// typedef struct {
//     uint8_t * pDACRegister;
//     uint8_t * pAddresses;
// } AD567X_OBJ;
// 
// static AD567X_OBJ ad567x_obj;


#define AD567X_CONFIG_TXBYTEQLEN 3
#define AD567X_CONFIG_NUMCHAN 8

static uint8_t ad567x_txByteQ[AD567X_CONFIG_TXBYTEQLEN];
static uint8_t ad567x_rxByteQ[AD567X_CONFIG_TXBYTEQLEN];
// static uint8_t ad567x_DACRegister[AD567X_CONFIG_NUMCHAN];
// static uint8_t ad567x_DACAddresses[AD567X_CONFIG_NUMCHAN];

void AD567X_Initialize() {
    
    TCSDAC = 0; //Make the CSDAC PIN output
    CSDAC = 1;
    
    AD567X_SetupInternalRef(0x00); //Turn on (0) or off (1) internal ref.

}

void AD567X_TasksTransmit() {

}

void AD567X_AssembleDataRegister(uint8_t command, uint8_t address, uint16_t value) {
    //assemble the first byte which is the command code followed by the address
    //code
    uint8_t byte1, byte2, byte3;
    AD567x_DATABITS databits;

    // or the first byte to encode the command and address
    byte1 = (command << 4) | address;
    databits.value = value;

    byte2 = databits.bytes[1]; //MSB
    byte3 = databits.bytes[0]; //LSB

    ad567x_txByteQ[0] = byte1;
    ad567x_txByteQ[1] = byte2;
    ad567x_txByteQ[2] = byte3;

}

void AD567X_WriteQueue() {

    // just write out the queue for now.

    //if test for queue size
    CSDAC=0;
    SPI1_Exchange8bitBuffer(ad567x_txByteQ, 3, ad567x_rxByteQ);
    CSDAC=1;
    //set queue size to zero

}

void AD567X_WriteToAndUpdateChannel(AD567X_CHAN channel, uint16_t value) {
    AD567X_CMD command = DACCMD_WRITEREGNUPDATE;
    AD567X_AssembleDataRegister(command, channel, value);
    AD567X_WriteQueue();
}

void AD567X_UpdateAllChannels(uint16_t value){
    AD567X_CMD command = DACCMD_UPDALLDAC;
    AD567X_AssembleDataRegister(command,0x00,value);
    AD567X_WriteQueue();
}

uint16_t AD567X_ReadBackEnable(AD567X_CHAN channel){
    uint16_t retval = -1;
    AD567X_CMD command;
    AD567x_DATABITS databits;
    databits.value = 0;

    // SET READ BIT
    command = DACCMD_READBACKEN;
    AD567X_AssembleDataRegister(command, channel, 0);
    AD567X_WriteQueue();

    //SEND NOOP
    command = DACCMD_NOOP;
    AD567X_AssembleDataRegister(command, 0, 0);
    AD567X_WriteQueue();

    //NOW PROCCESS REPLY
    databits.bytes[0] = ad567x_rxByteQ[2];//LSB
    databits.bytes[1] = ad567x_rxByteQ[1];//MSB

    retval = databits.value;
    
    return retval;

}

void AD567X_SetupInternalRef(uint16_t on) {
       
    AD567X_CMD command;
    AD567X_CHAN channel = 0x00;
    
    command = DACCMD_INTREFREG;
    
    AD567X_AssembleDataRegister(command, channel, on);
    AD567X_WriteQueue();

    return;


}