2018-12-12 11:20:27 +01:00

232 lines
9.2 KiB
C
Executable File

#pragma once
#include "commonServerFunctions.h" // blackfin.h, ansi.h
/* AD7689 ADC DEFINES */
/** Read back CFG Register */
#define AD7689_CFG_RB_OFST (0)
#define AD7689_CFG_RB_MSK (0x00000001 << AD7689_CFG_RB_OFST)
/** Channel sequencer */
#define AD7689_CFG_SEQ_OFST (1)
#define AD7689_CFG_SEQ_MSK (0x00000003 << AD7689_CFG_SEQ_OFST)
#define AD7689_CFG_SEQ_DSBLE_VAL ((0x0 << AD7689_CFG_SEQ_OFST) & AD7689_CFG_SEQ_MSK)
#define AD7689_CFG_SEQ_UPDTE_DRNG_SQNCE_VAL ((0x1 << AD7689_CFG_SEQ_OFST) & AD7689_CFG_SEQ_MSK)
#define AD7689_CFG_SEQ_SCN_WTH_TMP_VAL ((0x2 << AD7689_CFG_SEQ_OFST) & AD7689_CFG_SEQ_MSK)
#define AD7689_CFG_SEQ_SCN_WTHT_TMP_VAL ((0x3 << AD7689_CFG_SEQ_OFST) & AD7689_CFG_SEQ_MSK)
/** Reference/ buffer selection */
#define AD7689_CFG_REF_OFST (3)
#define AD7689_CFG_REF_MSK (0x00000007 << AD7689_CFG_REF_OFST)
/** Internal reference. REF = 2.5V buffered output. Temperature sensor enabled. */
#define AD7689_CFG_REF_INT_2500MV_VAL ((0x0 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_OFST)
/** Internal reference. REF = 4.096V buffered output. Temperature sensor enabled. */
#define AD7689_CFG_REF_INT_4096MV_VAL ((0x1 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_MSK)
/** External reference. Temperature sensor enabled. Internal buffer disabled. */
#define AD7689_CFG_REF_EXT_TMP_VAL ((0x2 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_MSK)
/** External reference. Temperature sensor enabled. Internal buffer enabled. */
#define AD7689_CFG_REF_EXT_TMP_INTBUF_VAL ((0x3 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_MSK)
/** External reference. Temperature sensor disabled. Internal buffer disabled. */
#define AD7689_CFG_REF_EXT_VAL ((0x6 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_MSK)
/** External reference. Temperature sensor disabled. Internal buffer enabled. */
#define AD7689_CFG_REF_EXT_INTBUF_VAL ((0x7 << AD7689_CFG_REF_OFST) & AD7689_CFG_REF_MSK)
/** bandwidth of low pass filter */
#define AD7689_CFG_BW_OFST (6)
#define AD7689_CFG_BW_MSK (0x00000001 << AD7689_CFG_REF_OFST)
#define AD7689_CFG_BW_ONE_FOURTH_VAL ((0x0 << AD7689_CFG_BW_OFST) & AD7689_CFG_BW_MSK)
#define AD7689_CFG_BW_FULL_VAL ((0x1 << AD7689_CFG_BW_OFST) & AD7689_CFG_BW_MSK)
/** input channel selection IN0 - IN7 */
#define AD7689_CFG_IN_OFST (7)
#define AD7689_CFG_IN_MSK (0x00000007 << AD7689_CFG_IN_OFST)
/** input channel configuration */
#define AD7689_CFG_INCC_OFST (10)
#define AD7689_CFG_INCC_MSK (0x00000007 << AD7689_CFG_INCC_OFST)
#define AD7689_CFG_INCC_BPLR_DFFRNTL_PRS_VAL ((0x0 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
#define AD7689_CFG_INCC_BPLR_IN_COM_VAL ((0x2 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
#define AD7689_CFG_INCC_TMP_VAL ((0x3 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
#define AD7689_CFG_INCC_UNPLR_DFFRNTL_PRS_VAL ((0x4 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
#define AD7689_CFG_INCC_UNPLR_IN_COM_VAL ((0x6 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
#define AD7689_CFG_INCC_UNPLR_IN_GND_VAL ((0x7 << AD7689_CFG_INCC_OFST) & AD7689_CFG_INCC_MSK)
/** configuration update */
#define AD7689_CFG_CFG_OFST (13)
#define AD7689_CFG_CFG_MSK (0x00000001 << AD7689_CFG_CFG_OFST)
#define AD7689_CFG_CFG_NO_UPDATE_VAL ((0x0 << AD7689_CFG_CFG_OFST) & AD7689_CFG_CFG_MSK)
#define AD7689_CFG_CFG_OVRWRTE_VAL ((0x1 << AD7689_CFG_CFG_OFST) & AD7689_CFG_CFG_MSK)
#define AD7689_ADC_CFG_NUMBITS (14)
#define AD7689_ADC_DATA_NUMBITS (16)
#define AD7689_NUM_CHANNELS (7)
#define AD7689_NUM_INVALID_CONVERSIONS (3)
#define AD7689_INT_REF_MAX_MV (2500) // chosen using reference buffer selection in config reg
#define AD7689_INT_REF_MIN_MV (0)
#define AD7689_TMP_C_FOR_1_MV (25.00 / 283)
uint32_t AD7689_Reg = 0x0;
uint32_t AD7689_ROReg = 0x0;
uint32_t AD7689_CnvMask = 0x0;
uint32_t AD7689_ClkMask = 0x0;
uint32_t AD7689_DigMask = 0x0;
int AD7689_DigOffset = 0x0;
/**
* Set Defines
* @param reg spi register
* @param roreg spi readout register
* @param cmsk conversion mask
* @param clkmsk clock output mask
* @param dmsk digital output mask
* @param dofst digital output offset
*/
void AD7689_SetDefines(uint32_t reg, uint32_t roreg, uint32_t cmsk, uint32_t clkmsk, uint32_t dmsk, int dofst) {
AD7689_Reg = reg;
AD7689_ROReg = roreg;
AD7689_CnvMask = cmsk;
AD7689_ClkMask = clkmsk;
AD7689_DigMask = dmsk;
AD7689_DigOffset = dofst;
}
/**
* Disable SPI
*/
void AD7689_Disable() {
bus_w(AD7689_Reg, bus_r(AD7689_Reg)
| AD7689_CnvMask
| AD7689_ClkMask
&~(AD7689_DigMask));
}
/**
* Set SPI reg value
* @param codata value to be set
*/
void AD7689_Set(u_int32_t codata) {
FILE_LOG(logINFO, ("\tSetting ADC SPI Register. Writing 0x%08x to Config Reg\n", codata));
serializeToSPI(AD7689_Reg, codata, AD7689_CnvMask, AD7689_ADC_CFG_NUMBITS,
AD7689_ClkMask, AD7689_DigMask, AD7689_DigOffset);
}
/**
* Get SPI reg value
* @returns SPI reg value
*/
uint16_t AD7689_Get() {
FILE_LOG(logINFO, ("\tGetting ADC SPI Register.\n"));
return (uint16_t)serializeFromSPI(AD7689_ROReg, AD7689_Reg, AD7689_CnvMask, AD7689_ADC_DATA_NUMBITS,
AD7689_ClkMask, AD7689_DigMask);
}
/**
* Get temperature
* @returns temperature in °C
*/
int AD7689_GetTemperature() {
AD7689_Set(
// read back
AD7689_CFG_RB_MSK |
// disable sequencer (different from config)
AD7689_CFG_SEQ_DSBLE_VAL |
// Internal reference. REF = 2.5V buffered output. Temperature sensor enabled.
AD7689_CFG_REF_INT_2500MV_VAL |
// full bandwidth of low pass filter
AD7689_CFG_BW_FULL_VAL |
// all channel (different from config)
AD7689_CFG_IN_MSK |
// temperature sensor (different from config)
AD7689_CFG_INCC_TMP_VAL |
// overwrite configuration
AD7689_CFG_CFG_OVRWRTE_VAL);
// FIXME: do we have to read it 8 times?? (sequencer is disabled anyway) or are we sequencing, then we read only last channel
uint16_t regval = AD7689_Get();
// value in mV FIXME: page 17? reference voltage temperature coefficient or t do with -40 to 85 °C
uint16_t vmin = AD7689_INT_REF_MIN_MV;
uint16_t vmax = AD7689_INT_REF_MAX_MV;
uint16_t nsteps = (2 ^ AD7689_ADC_DATA_NUMBITS);
uint16_t retval = (vmin + (vmax - vmin) * regval / (nsteps - 1));
FILE_LOG(logDEBUG1, ("\tvoltage read for temp: 0x%d mV\n", retval));
// value in °C
uint16_t temp = AD7689_TMP_C_FOR_1_MV * retval;
FILE_LOG(logDEBUG1, ("\ttemp read: 0x%d °C\n", temp));
return temp;
}
/**
* Reads channels voltage
* @param ichan channel number from 0 to 7
* @returns channel voltage in mV
*/
int AD7689_GetChannel(int ichan) {
// filter channels val
if (ichan < 0 || ichan >= AD7689_NUM_CHANNELS) {
FILE_LOG(logERROR, ("Cannot get slow adc channel. "
"%d out of bounds (0 to %d)\n", ichan, AD7689_NUM_CHANNELS - 1));
return -1;
}
AD7689_Set(
// read back
AD7689_CFG_RB_MSK |
// disable sequencer (different from config)
AD7689_CFG_SEQ_DSBLE_VAL |
// Internal reference. REF = 2.5V buffered output. Temperature sensor enabled.
AD7689_CFG_REF_INT_2500MV_VAL |
// full bandwidth of low pass filter
AD7689_CFG_BW_FULL_VAL |
// specific channel (different from config)
((ichan << AD7689_CFG_IN_OFST) & AD7689_CFG_IN_MSK) |
// input channel configuration (unipolar. inx to gnd)
AD7689_CFG_INCC_UNPLR_IN_GND_VAL |
// overwrite configuration
AD7689_CFG_CFG_OVRWRTE_VAL);
// FIXME: do we have to read it 8 times?? (sequencer is disabled anyway) or are we sequencing, then we read only last channel
uint16_t regval = AD7689_Get();
// value in mV
uint16_t vmin = AD7689_INT_REF_MIN_MV;
uint16_t vmax = AD7689_INT_REF_MAX_MV;
uint16_t nsteps = (2 ^ AD7689_ADC_DATA_NUMBITS);
uint16_t retval = (vmin + (vmax - vmin) * regval / (nsteps - 1));
FILE_LOG(logINFO, ("\tvoltage read for chan %d: 0x%d mV\n", retval));
return retval;
}
/**
* Configure
*/
void AD7689_Configure(){
FILE_LOG(logINFOBLUE, ("Configuring AD7689 (Slow ADCs):\n"));
// from power up, 3 invalid conversions
int i = 0;
for (i = 0; i < AD7689_NUM_INVALID_CONVERSIONS; ++i) {
AD7689_Set(
// read back
AD7689_CFG_RB_MSK |
// scan sequence IN0-IN7 then temperature sensor
AD7689_CFG_SEQ_SCN_WTH_TMP_VAL |
// Internal reference. REF = 2.5V buffered output. Temperature sensor enabled.
AD7689_CFG_REF_INT_2500MV_VAL |
// full bandwidth of low pass filter
AD7689_CFG_BW_FULL_VAL |
// scan upto channel 7
AD7689_CFG_IN_MSK |
// input channel configuration (unipolar. inx to gnd)
AD7689_CFG_INCC_UNPLR_IN_GND_VAL |
// overwrite configuration
AD7689_CFG_CFG_OVRWRTE_VAL);
}
}