/**************************************************************************/
/*!
@file NelsonsLog_FDC2214.cpp
@author dlsc
*/
/**************************************************************************/
#include "Arduino.h"
#include <Wire.h>
#include "FDC2214.h"
FDC2214::FDC2214(uint8_t i2caddr) {
_i2caddr = i2caddr;
//_i2caddr = FDC2214_I2C_ADDRESS;
}
// Checking for chip ID, if OK, calls chip init
boolean FDC2214::begin(uint8_t chanMask, uint8_t autoscanSeq, uint8_t deglitchValue) {
Wire.begin();
int devId = read16FDC(FDC2214_DEVICE_ID);
if (devId != 0x3054) {
if (devId != 0x3055) {
//two valid device ids for FDC2214 0x3054 and 0x3055
return false;
}
}
loadSettings(chanMask, autoscanSeq, deglitchValue);
// setGain();
return true;
}
//Internal routine to do actual chip init
void FDC2214::loadSettings(uint8_t chanMask, uint8_t autoscanSeq, uint8_t deglitchValue) {
//Configuration register
// Active channel Select: b00 = ch0; b01 = ch1; b10 = ch2; b11 = ch3;
// |Sleep Mode: 0 - device active; 1 - device in sleep;
// ||Reserved, reserved, set to 1
// |||Sensor Activation Mode: 0 - drive sensor with full current. 1 - drive sensor with current set by DRIVE_CURRENT_CHn
// ||||Reserved, set to 1
// |||||Reference clock: 0 - use internal; 1 - use external clock
// ||||||Reserved, set to 0
// |||||||Disable interrupt. 0 - interrupt output on INTB pin; 1 - no interrupt output
// ||||||||High current sensor mode: 0 - 1.5mA max. 1 - > 1.5mA, not available if Autoscan is enabled
// ||||||||| Reserved, set to 000001
// ||||||||| |
// CCS1A1R0IH000000 -> 0001 1110 1000 0001 -> 0x1E81
write16FDC(FDC2214_CONFIG, 0x1E81); //set config
//If channel 1 selected, init it..
if (chanMask & 0x01) {
//settle count maximized, slow application
write16FDC(FDC2214_SETTLECOUNT_CH0, 0x64);
//rcount maximized for highest accuracy
write16FDC(FDC2214_RCOUNT_CH0, 0xFFFF);
//no offset
write16FDC(FDC2214_OFFSET_CH0, 0x0000);
// Set clock dividers
// Reserved
// | Sensor Frequency Select. b01 = /1 = sensor freq 0.01 to 8.75MHz; b10 = /2 = sensor freq 0.01 to 10 or 5 to 10 MHz
// | | Reserved
// | | | Reference divider. Must be > 1. fref = fclk / this register`
// | | | |
// 00FF00RRRRRRRRRR -> 0010000000000001 -> 0x2001
write16FDC(FDC2214_CLOCK_DIVIDERS_CH0, 0x2001);
//set drive register
write16FDC(FDC2214_DRIVE_CH0, 0xF800);
}
// Init chan2, if selected by channel init mask
if (chanMask & 0x02) {
write16FDC(FDC2214_SETTLECOUNT_CH1, 0x64);
write16FDC(FDC2214_RCOUNT_CH1, 0xFFFF);
write16FDC(FDC2214_OFFSET_CH1, 0x0000);
write16FDC(FDC2214_CLOCK_DIVIDERS_CH1, 0x2001);
write16FDC(FDC2214_DRIVE_CH1, 0xF800);
}
if (chanMask & 0x04) {
write16FDC(FDC2214_SETTLECOUNT_CH1, 0x64);
write16FDC(FDC2214_RCOUNT_CH1, 0xFFFF);
write16FDC(FDC2214_OFFSET_CH1, 0x0000);
write16FDC(FDC2214_CLOCK_DIVIDERS_CH1, 0x2001);
write16FDC(FDC2214_DRIVE_CH1, 0xF800);
}
if (chanMask & 0x08) {
write16FDC(FDC2214_SETTLECOUNT_CH1, 0x64);
write16FDC(FDC2214_RCOUNT_CH1, 0xFFFF);
write16FDC(FDC2214_OFFSET_CH1, 0x0000);
write16FDC(FDC2214_CLOCK_DIVIDERS_CH1, 0x2001);
write16FDC(FDC2214_DRIVE_CH1, 0xF800);
}
// Autoscan: 0 = single channel, selected by CONFIG.ACTIVE_CHAN
// | Autoscan sequence. b00 for chan 1-2, b01 for chan 1-2-3, b02 for chan 1-2-3-4
// | | Reserved - must be b0001000001
// | | | Deglitch frequency. b001 for 1 MHz, b100 for 3.3 MHz, b101 for 10 Mhz, b111 for 33 MHz
// | | | |
// ARR0001000001DDD -> b0000 0010 0000 1000 -> h0208
uint16_t muxVal = 0x0208 | ((uint16_t)autoscanSeq << 13) | deglitchValue;
//
write16FDC(FDC2214_MUX_CONFIG, muxVal); //set mux config for channels
}
///**************************************************************************/
///*!
// @brief Given a reading calculates the sensor frequency
//*/
///**************************************************************************/
//long long NelsonsLog_FDC2214::calculateFsensor(unsigned long reading){
//// Serial.println("reading: "+ String(reading));
// //fsensor = (CH_FIN_SEL * fref * data) / 2 ^ 28
// //should be mega hz so can truncate to long long
// Serial.println("FDC reading: " + String(reading));
// unsigned long long temp;
// temp = 1 * 40000000 * reading;
// temp = temp / (2^28);
//// Serial.println("frequency: " + String((long)temp));
// return temp;
//}
///**************************************************************************/
///*!
// @brief Given sensor frequency calculates capacitance
//*/
///**************************************************************************/
//double NelsonsLog_FDC2214::calculateCapacitance(long long fsensor){
// //differential configuration
// //c sensor = 1 - (Cboard + Cparacitic)
// // / (L * (2*pi * fsensor)^2)
//
// double pi = 3.14159265359;
// double L = 18; //uH
// double Cboard = 33; //pf
// double Cparacitic = 3; //pf
//
// double temp = 2 * pi * fsensor;
// temp = temp * temp;
//
// temp = temp / 1000000; //uH
// temp *= L;
//
//// Serial.println("capacitance: " + String(temp));
// return temp;
//
//}
// Gets 28bit reading for FDC2212 and FDC2214
// Takes in channel number, gives out the formatted 28 bit reading.
unsigned long FDC2214::getReading28(uint8_t channel) {
int timeout = 100;
unsigned long reading = 0;
long long fsensor = 0;
int status = read16FDC(FDC2214_STATUS);
uint8_t addressMSB;
uint8_t addressLSB;
uint8_t bitUnreadConv;
switch (channel){
case (0):
addressMSB = FDC2214_DATA_CH0_MSB;
addressLSB = FDC2214_DATA_CH0_LSB;
bitUnreadConv = FDC2214_CH0_UNREADCONV;
break;
case (1):
addressMSB = FDC2214_DATA_CH1_MSB;
addressLSB = FDC2214_DATA_CH1_LSB;
bitUnreadConv = FDC2214_CH1_UNREADCONV;
break;
case (2):
addressMSB = FDC2214_DATA_CH1_MSB;
addressLSB = FDC2214_DATA_CH1_LSB;
bitUnreadConv = FDC2214_CH1_UNREADCONV;
break;
case (3):
addressMSB = FDC2214_DATA_CH1_MSB;
addressLSB = FDC2214_DATA_CH1_LSB;
bitUnreadConv = FDC2214_CH1_UNREADCONV;
break;
default: return 0;
}
while (timeout && !(status & FDC2214_CH0_UNREADCONV)) {
status = read16FDC(FDC2214_STATUS);
timeout--;
}
if (timeout == 100) {
// #####################################################################################################
// There was this weird double read, as "first readout could be stale" in Nelsons file.
// I have not confirmed the existence of this silicon bug.
// I suspect that it might be due to crappy breadboard or rats nest wiring or lack of signal integrity for other reason
//
// On the other hand, I have done far too little testing to be sure, so I am leaving that bit in for now.
//
// #####################################################################################################
//could be stale grab another //could it really it? ?????
//read the 28 bit result
reading = (uint32_t)(read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
reading |= read16FDC(addressLSB);
while (timeout && !(status & FDC2214_CH0_UNREADCONV)) {
status = read16FDC(FDC2214_STATUS);
timeout--;
}
}
if (timeout) {
//read the 28 bit result
reading = (uint32_t)(read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
reading |= read16FDC(addressLSB);
return reading;
} else {
// Could not get data, chip readynes flag timeout
return 0;
}
}
// Gets 16bit reading for FDC2112 and FDC2114
// Takes in channel number, gives out the formatted 28 bit reading.
unsigned long FDC2214::getReading16(uint8_t channel) {
int timeout = 100;
unsigned long reading = 0;
long long fsensor = 0;
int status
评论0