AnsweredAssumed Answered

BF518 TWI (AD7998) issue (sequence mode)

Question asked by BlueIceScream on Oct 27, 2014
Latest reply on Dec 10, 2014 by Suraj

Hi to all.

 

I have some issue with AD7998 ADC.

 

AD7998 adc supports several modes and use twi for data transfering.

 

When i use single conversion mode (conversion by command) all works fine.

When i use sequence mode (conversion all channels one by one) i get same values for all channels.

 

this is my code:

 

 

#include <adi_types.h>

#include <stdio.h>

#include "adi_ssl_Init.h"

#include "AD7998.h"

 

void Callback(void *ClientHandle, u32 Event, void *pArg);

 

const adi_twi_bit_rate rate = { .frequency = 100, .duty_cycle = 50 };

 

static bool prepareReadyStatus = false;

static bool readSingleReadyStatus = false;

static bool readMultiReadyStatus = false;

 

u8 OutboundData[10];

u8 InboundData[22];

 

//Table of configuration    

ADI_DEV_CMD_VALUE_PAIR TWIConfigurationTable[] = { // configuration table for the TWI driver

            {ADI_DEV_CMD_SET_DATAFLOW_METHOD,        (void *)ADI_DEV_MODE_SEQ_CHAINED},

            {ADI_TWI_CMD_SET_FIFO,                    (void *)0x0000},

            {ADI_TWI_CMD_SET_RATE,                    (void *)(&rate)},

            {ADI_TWI_CMD_SET_LOSTARB,                (void *)1},

            {ADI_TWI_CMD_SET_ANAK,                    (void *)0},

            {ADI_TWI_CMD_SET_DNAK,                    (void *)0},

            {ADI_DEV_CMD_END,                        NULL}

};

 

ADI_DEV_DEVICE_HANDLE     TWIDeviceHandle;   

ADI_DEV_SEQ_1D_BUFFER    OutboundBuffer;

ADI_DEV_SEQ_1D_BUFFER    InboundBuffer;   

   

// init AD7998 device and twi system

int AD7998_init(void)

{

    u32 result;

   

    result = adi_dev_Open(

                adi_dev_ManagerHandle,

                &ADITWIEntryPoint,

                0,  // TWI Device Number

                NULL, // Client Handle ( passed to call back function )

                &TWIDeviceHandle,

                ADI_DEV_DIRECTION_BIDIRECTIONAL,

                NULL, // DMA Handle (TWI has no DMA)

                NULL, //Handle to the deferred callback service deferred.

                Callback // Call Back Function.

          );

         

    if (result) {

        printf("AD7998 says:\tCan't open twi device\n");

        return -1;

    }         

 

    // output buffer common setup

    OutboundBuffer.Buffer.Data = &OutboundData[0];

    OutboundBuffer.Buffer.ElementWidth = 1;

    OutboundBuffer.Buffer.ProcessedFlag = NULL;   

    OutboundBuffer.Buffer.ProcessedElementCount = NULL;

    OutboundBuffer.Direction = ADI_DEV_DIRECTION_OUTBOUND;

   

    // input buffer common setup

    InboundBuffer.Buffer.Data = &InboundData[0];

    InboundBuffer.Buffer.ElementWidth = 1;

    InboundBuffer.Buffer.ProcessedFlag = NULL;   

    InboundBuffer.Buffer.ProcessedElementCount = NULL;

    InboundBuffer.Direction = ADI_DEV_DIRECTION_INBOUND;

 

    // configure twi device

    result = adi_dev_Control(TWIDeviceHandle, ADI_DEV_CMD_TABLE, TWIConfigurationTable);

 

    if (result) {

        printf("AD7998 says:\tCan't configure twi device\n");

        return -1;

    }         

   

    // start dataflow

    adi_dev_Control(TWIDeviceHandle, ADI_DEV_CMD_SET_DATAFLOW, (void *)TRUE);                                   

   

    return 0;

}

 

// Prepare device to work in sequence mode

// function blocks thread

void AD7998_prepare()

{

    prepareReadyStatus = false;

   

    // set value for configuration register

    // all channels set to 1; fltr set to 1

    OutboundData[0] = CONFIGURATION_REG;

    OutboundData[1] = 0x03;

    OutboundData[2] = 0xFA;

 

    // setup output buffer

    OutboundBuffer.Buffer.ElementCount = 3;

    OutboundBuffer.Buffer.CallbackParameter = (void *)CMD_PREPARE_PARAM;

    OutboundBuffer.Buffer.pNext = NULL;

    OutboundBuffer.Buffer.pAdditionalInfo = (void *)AD7998_ADDR;

 

    adi_dev_SequentialIO(TWIDeviceHandle, ADI_DEV_SEQ_1D,

                        (ADI_DEV_BUFFER *)&OutboundBuffer);

   

    // wait before data will be sent                                   

    while (!prepareReadyStatus);

}

 

// read data from AD7998 channel

// return reading data

// this function block thread!!!

u32 AD7998_readSingle(u8 channel)

{

    // set channel for reading

    OutboundData[0] = channel;

   

    // send data to address point register

    // (4MSB is channel num) (4LSB is conversation register address)

    OutboundBuffer.Buffer.ElementCount = 1;

    OutboundBuffer.Buffer.CallbackParameter = (void *)0;

    OutboundBuffer.Buffer.pNext = &InboundBuffer.Buffer;   

    OutboundBuffer.Buffer.pAdditionalInfo = (void *)AD7998_ADDR;

 

    // we receive 2 bytes (12 bit ADC)

    InboundBuffer.Buffer.ElementCount = 2;

    InboundBuffer.Buffer.CallbackParameter = (void *)CMD_READSINGLE_PARAM;

    InboundBuffer.Buffer.pNext = NULL;   

    InboundBuffer.Buffer.pAdditionalInfo = (void *)AD7998_ADDR;

 

    readSingleReadyStatus = false;

   

    adi_dev_SequentialIO(TWIDeviceHandle, ADI_DEV_SEQ_1D,

                        (ADI_DEV_BUFFER *)&OutboundBuffer);

 

    // wait before operations complete

    while (!readSingleReadyStatus);

   

    // pack result

    return (((InboundData[0] & 0x0F)<<8) | InboundData[1]);                       

}

 

// read sequense data from AD7998 channels

// return pointer to readed data

// this function block thread!!!

void AD7998_readMulti(u32 *ADCResultsData)

{

    u32 i;

    readMultiReadyStatus = false;

   

    // set value for sequence convert

    // this value will be stored in address point register

    OutboundData[0] = 0x70;//SEQUENCE_CONVERT;

       

    OutboundBuffer.Buffer.ElementCount = 1;

    OutboundBuffer.Buffer.CallbackParameter = (void *)0;

    OutboundBuffer.Buffer.pNext = &InboundBuffer.Buffer;   

    OutboundBuffer.Buffer.pAdditionalInfo = (void *)AD7998_ADDR;

   

    // we have to receive 12 bytes (12 bit from conversion register x 6 channels)

    InboundBuffer.Buffer.ElementCount = 12;

    InboundBuffer.Buffer.CallbackParameter = (void *)CMD_READMULTI_PARAM;

    InboundBuffer.Buffer.pNext = NULL;   

    InboundBuffer.Buffer.pAdditionalInfo = (void *)AD7998_ADDR;

 

    adi_dev_SequentialIO(TWIDeviceHandle, ADI_DEV_SEQ_1D,

                        (ADI_DEV_BUFFER *)&OutboundBuffer);

   

    // wait before all data will be received

    while (!readMultiReadyStatus);

   

    // prepare results

    for (i=0; i<12; i+=2)

        ADCResultsData[i/2] = ((InboundData[i] & 0x0F)<<8) | InboundData[i+1];

}

 

void Callback(void *ClientHandle, u32 Event, void *pArg)

{

    char param = (char)pArg;

   

    if (param == CMD_PREPARE_PARAM && Event==ADI_DEV_EVENT_BUFFER_PROCESSED) {

        prepareReadyStatus = true;

    }

    else if (param == CMD_READMULTI_PARAM && Event==ADI_DEV_EVENT_BUFFER_PROCESSED) {

        readMultiReadyStatus = true;

    }

    else if (param == CMD_READSINGLE_PARAM && Event==ADI_DEV_EVENT_BUFFER_PROCESSED) {

        readSingleReadyStatus = true;

    }

}

 

====================================================================

 

I know that for every channel AD7998 starts conversion because some values (that i got) sometimes different. For example:

 

Vin1 = 0x0489

Vin2 = 0x0489

Vin3 = 0x0489

Vin4 = 0x0489

Vin5 = 0x048A !!!!!  (this is because i change Vin1 input during sequence conversation)

Vin6 = 0x048A !!!!!

Vin7 = 0x048A !!!!!

 

Seems that AD7998 do conversion in one channel, but must do conversion for all channels (for channels thats have logical 1 in Configuration register).

 

Single read method works fine. But i want know where i has error or may be this is AD7998 issue.

Outcomes