Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • E3631A
  • InstekPST3202_addition
  • arduino-influx
  • blocking_com
  • calibrationEM
  • cgr_caen_dt5472N_500V
  • ci-format
  • devel
  • devel_isOn
  • dt5471
  • em_LXICom_and_TektronixLXI
  • generic_load
  • generic_multimeters
  • idatasink
  • ips-keithley
  • ips_RS_HMP4040
  • ips_texio
  • iv_curve
  • master
  • pbv2active
  • qaqc
  • rd53a_ivUpdate
  • rd53a_ivcurve
  • revert-70fe35dc
  • scpiPs
  • sp-autoconf
  • spi
  • RALIrradNov2018
  • v0.1
29 results

Target

Select target project
  • jiddon/labRemote
  • itk-strips-at-sr1/labRemote
  • kkrizka/labRemote
  • bbrueers/labRemote
  • usoldevi/labRemote
  • dsperlic/labRemote
  • eballabe/labRemote
  • yanght/labRemote
  • jgrosse/labRemote
  • scipp/pixels/labRemote
  • zhicaiz/labRemote
  • otoldaie/labRemote
  • bsmart/labRemote
  • scipp/labRemote
  • losojnak/labRemote
  • jdopke/labRemote
  • epianori/labRemote
  • berkeleylab/labRemote
18 results
Select Git revision
  • 2022-slac-testing
  • 24-handling-single-channel-ps
  • E3631A
  • InstekPST3202_addition
  • ad_adding_HYT221
  • addAgilentModel
  • addKeithley2230G
  • add_CAEN_R803x_PS
  • add_NGP804
  • add_generator
  • arduino-influx
  • bcm680
  • blocking_com
  • calibrationEM
  • cgr_caen_dt5472N_500V
  • ci-format
  • dantrim_ads1015_and_daq970a
  • dantrim_devcom_registry
  • dantrim_enforce_code_formatting
  • dantrim_filecalibration_filecheck
  • dantrim_fix_keithley_terminator
  • dantrim_multiftdi_get_strings
  • dantrim_update_ci_image
  • devel
  • dt54xxps-autorange
  • em_LXICom_and_TektronixLXI
  • fdti-bugfix
  • feat/CAENHVPS
  • feat/CAENHVPS_DT803x
  • ftdi_mpsse_context
  • generic_load
  • generic_multimeters
  • icomwait
  • iv_curve
  • jay_influxdbupdate
  • jgk_json_for_ClimateSensor
  • js_chiller_bug
  • juerg-dev
  • kk_DS10CP154A
  • kk_activeTB
  • kk_betsee
  • kk_betsee_dec2020
  • kk_climate
  • kk_fix
  • kk_fixgpibscan
  • kk_fixpca9548A
  • kk_littleredcaen_centos8
  • kk_lockps
  • kk_pcf8591
  • kk_spift232h
  • kk_waveformgen
  • kki2cdevcomuino
  • lxi_com
  • main
  • main_copy
  • monitoring_watch_dog
  • nz_climate
  • pbv2active
  • ps-documentation
  • psnaming
  • pythonbinding_registry
  • rd53a_ivUpdate
  • rd53a_ivcurve
  • release-v0.2
  • revert-78d4f7f6
  • revert-9dfbb40f
  • sp-autoconf
  • spi
  • testbeam
  • tmp_swint
  • tripletspmon
  • xray_devel
  • yanght_libMotion
  • 4.1.0
  • RALIrradNov2018
  • tag.4.devel
  • v0.1
  • v0.2
  • v1.0
  • v2.0
  • v3.0
  • v4.0
82 results
Show changes
Commits on Source (3)
Showing
with 1546 additions and 1 deletion
#include "AD5160.h"
#include <iostream>
#include <iomanip>
AD5160::AD5160(std::shared_ptr<DeviceCom> dev) : m_dev(dev){
this->setResistance(m_regMax);
}
AD5160::~AD5160(){
}
void AD5160::setResistance(float rOhm){
if(rOhm < m_R_W){
std::cout << "AD5160::setResistance ERROR rOhm is" << rOhm << ", but minimum is " << m_R_W << std::endl;
std::cout << "Exiting setResistance" << std::endl;
return;
}
else if(rOhm > m_R_AB){
std::cout << "AD5160::setResistance ERROR rOhm is" << rOhm << ", but maximum is " << m_R_AB << std::endl;
std::cout << "Exiting setResistance" << std::endl;
return;
}
// http://www.analog.com/media/en/technical-documentation/data-sheets/AD5160.pdf
// D = (R_WB - R_W) * (256 / R_AB)
// R_W = 50 Ohm (typically)
// R_AB = 100 kOhm (typically)
// R_WB = our value
uint8_t regValCounts = (rOhm - m_R_W) * (256. / m_R_AB);
setResistance(regValCounts);
}
void AD5160::setResistance(uint8_t regVal){
if(regVal > m_regMax){
std::cout << "AD5160::setResistance ERROR regVal is" << std::hex << regVal << ", but regMax is" << std::hex << m_regMax << std::endl;
std::cout << "Exiting setResistance" << std::endl;
return;
} else if(regVal < m_regMin){
std::cout << "AD5160::setResistance ERROR regVal is" << std::hex << regVal << ", but regMin is" << std::hex << m_regMin << std::endl;
std::cout << "Exiting setResistance" << std::endl;
return;
}
m_regVal = regVal;
m_dev->write_data(m_regVal);
}
uint8_t AD5160::getResistance(){
return m_regVal;
}
#ifndef AD5160_H
#define AD5160_H
#include "DeviceCom.h"
#include <memory>
class AD5160{
public:
AD5160(std::shared_ptr<DeviceCom> dev);
~AD5160();
// Configurable R_W and R_AB for calibration of the potentiometers
void set_R_W(float R_W){m_R_W = R_W;};
void set_R_AB(float R_AB){m_R_AB = R_AB;};
void setResistance(float rOhm);
void setResistance(uint8_t regVal);
uint8_t getResistance();
private:
std::shared_ptr<DeviceCom> m_dev;
// http://www.analog.com/media/en/technical-documentation/data-sheets/AD5160.pdf
// For the resistance float -> counts conversion
float m_R_W = 50;
float m_R_AB = 100e3;
uint8_t m_regVal;
// To limit the resistance range
uint8_t m_regMin = 0x00;
uint8_t m_regMax = 0xFF;
};
#endif //AD5160_H
#include "BME280.h"
#include <iostream>
#include <iomanip>
BME280::BME280(std::shared_ptr<SPICom> devcom)
: m_devcom(devcom)
{ }
BME280::~BME280()
{ }
void BME280::init()
{
load_calibration();
}
void BME280::reset()
{
m_devcom->write_reg(0x60, 0xB6);
}
float BME280::temperature()
{
uint8_t data[3];
m_devcom->read_reg(0xFA,data,3);
int adc_T=(data[0]<<16)|(data[1]<<8)|(data[2]);
adc_T>>=4;
int var1, var2, T;
var1 = (( ((adc_T>>3) - (m_dig_T1<<1)) ) * (m_dig_T2)) >> 11;
var2 = (((((adc_T>>4) - (m_dig_T1)) * ((adc_T>>4) - (m_dig_T1))) >> 12) * (m_dig_T3)) >> 14;
m_t_fine = var1 + var2;
T = (m_t_fine * 5 + 128) >> 8;
return T/100.;
}
float BME280::humidity()
{
temperature(); // must be done first to get t_fine
uint8_t data[2];
m_devcom->read_reg(0xFD,data,2);
int adc_H=(data[0]<<8)|(data[1]);
int32_t v_x1_u32r;
v_x1_u32r = (m_t_fine - ((int32_t)76800));
v_x1_u32r = (((((adc_H << 14) - (((int32_t)m_dig_H4) << 20) -
(((int32_t)m_dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
(((((((v_x1_u32r * ((int32_t)m_dig_H6)) >> 10) *
(((v_x1_u32r * ((int32_t)m_dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
((int32_t)2097152)) * ((int32_t)m_dig_H2) + 8192) >> 14));
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
((int32_t)m_dig_H1)) >> 4));
v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
float h = (v_x1_u32r>>12);
return h / 1024.0;
}
float BME280::pressure()
{
temperature(); // must be done first to get t_fine
uint8_t data[3];
m_devcom->read_reg(0xF7,data,3);
int adc_P=(data[0]<<16)|(data[1]<<8)|(data[2]);
adc_P>>=4;
int64_t var1, var2, p;
var1 = ((int64_t)m_t_fine) - 128000;
var2 = var1 * var1 * (int64_t)m_dig_P6;
var2 = var2 + ((var1*(int64_t)m_dig_P5)<<17);
var2 = var2 + (((int64_t)m_dig_P4)<<35);
var1 = ((var1 * var1 * (int64_t)m_dig_P3)>>8) +
((var1 * (int64_t)m_dig_P2)<<12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)m_dig_P1)>>33;
if (var1 == 0)
return 0; // avoid exception caused by division by zero
p = 1048576 - adc_P;
p = (((p<<31) - var2)*3125) / var1;
var1 = (((int64_t)m_dig_P9) * (p>>13) * (p>>13)) >> 25;
var2 = (((int64_t)m_dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)m_dig_P7)<<4);
return (float)p/256;
}
void BME280::load_calibration()
{
//
// Calibrate temperature
uint8_t calibTdata[6];
m_devcom->read_reg(0x88,calibTdata,6);
m_dig_T1=(calibTdata[1]<<8)|calibTdata[0];
m_dig_T2=(calibTdata[3]<<8)|calibTdata[2];
m_dig_T3=(calibTdata[5]<<8)|calibTdata[4];
//
// Calibrate pressure
uint8_t calibPdata[16];
m_devcom->read_reg(0x90,calibPdata,16);
m_dig_P1=(calibPdata[ 1]<<8)|calibPdata[ 0];
m_dig_P2=(calibPdata[ 3]<<8)|calibPdata[ 2];
m_dig_P3=(calibPdata[ 5]<<8)|calibPdata[ 4];
m_dig_P4=(calibPdata[ 7]<<8)|calibPdata[ 6];
m_dig_P5=(calibPdata[ 9]<<8)|calibPdata[ 8];
m_dig_P6=(calibPdata[11]<<8)|calibPdata[10];
m_dig_P7=(calibPdata[13]<<8)|calibPdata[12];
m_dig_P8=(calibPdata[15]<<8)|calibPdata[14];
m_dig_P9=(calibPdata[17]<<8)|calibPdata[16];
//
// Calibrate humidity
m_dig_H1=m_devcom->read_reg(0xA1);
uint8_t calibHdata[7];
m_devcom->read_reg(0xE1,calibHdata,7);
m_dig_H2=(calibHdata[ 1]<<8)|calibHdata[ 0];
m_dig_H3= calibHdata[ 2];
m_dig_H4=(calibHdata[ 3]<<4)|(calibHdata[ 4]&0xF);
m_dig_H5=(calibHdata[ 5]<<4)|(calibHdata[ 4]>>4 );
m_dig_H6= calibHdata[ 6];
}
void BME280::dump()
{
//
// Print device ID
std::cout << "device id = 0x" << std::hex << m_devcom->read_reg(0xD0) << std::dec << std::endl;
//
// Read the calibration
std::cout << std::endl << "calibration" << std::endl;
std::cout << "dig_T1 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_T1 << std::dec << std::endl;
std::cout << "dig_T2 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_T2 << std::dec << std::endl;
std::cout << "dig_T3 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_T3 << std::dec << std::endl;
std::cout << "dig_P1 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P1 << std::dec << std::endl;
std::cout << "dig_P2 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P2 << std::dec << std::endl;
std::cout << "dig_P3 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P3 << std::dec << std::endl;
std::cout << "dig_P4 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P4 << std::dec << std::endl;
std::cout << "dig_P5 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P5 << std::dec << std::endl;
std::cout << "dig_P6 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P6 << std::dec << std::endl;
std::cout << "dig_P7 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P7 << std::dec << std::endl;
std::cout << "dig_P8 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P8 << std::dec << std::endl;
std::cout << "dig_P9 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_P9 << std::dec << std::endl;
std::cout << "dig_H1 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H1 << std::dec << std::endl;
std::cout << "dig_H2 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H2 << std::dec << std::endl;
std::cout << "dig_H3 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H3 << std::dec << std::endl;
std::cout << "dig_H4 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H4 << std::dec << std::endl;
std::cout << "dig_H5 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H5 << std::dec << std::endl;
std::cout << "dig_H6 = 0x" << std::hex << std::setw(4) << std::setfill('0') << m_dig_H6 << std::dec << std::endl;
//
// Dump all registers
std::cout << std::endl << "all registers" << std::endl;
std::cout << std::hex;
for(uint i=0;i<8;i++)
{
uint8_t reg=0x80+(i<<4);
std::cout << "0x" << std::setw(2) << std::setfill('0') << (uint)reg << ":";
uint8_t regdata[16];
m_devcom->read_reg(reg,regdata,16);
for(uint j=0;j<16;j++)
std::cout << " " << std::setw(2) << std::setfill('0') << (uint)regdata[j];
std::cout << std::endl;
}
std::cout << std::dec;
}
#ifndef BME280_H
#define BME280_H
#include <memory>
#include "ClimateSensor.h"
#include "SPICom.h"
class BME280 : public ClimateSensor
{
public:
BME280(std::shared_ptr<SPICom> devcom);
virtual ~BME280();
virtual void init();
virtual void reset();
virtual float temperature();
virtual float humidity();
virtual float pressure();
void dump();
private:
std::shared_ptr<SPICom> m_devcom;
// Calibration constants
void load_calibration();
ushort m_dig_T1;
short m_dig_T2;
short m_dig_T3;
ushort m_dig_P1;
short m_dig_P2;
short m_dig_P3;
short m_dig_P4;
short m_dig_P5;
short m_dig_P6;
short m_dig_P7;
short m_dig_P8;
short m_dig_P9;
uint8_t m_dig_H1;
int16_t m_dig_H2;
uint8_t m_dig_H3;
int16_t m_dig_H4;
int16_t m_dig_H5;
int8_t m_dig_H6;
// Shared data
int m_t_fine;
};
#endif // BME280_H
......@@ -34,6 +34,7 @@ set(SrcFiles DeviceCom.cpp
DeviceCalibration.cpp
DummyCalibration.cpp
LinearCalibration.cpp
LineCalibration.cpp
FileCalibration.cpp
)
......
#include "DigitalIO.h"
#ifndef DIGITALIO_H
#define DIGITALIO_H
#endif //DIGITALIO_H
\ No newline at end of file
#include "EndeavourCom.h"
#include "EndeavourComException.h"
#include <iostream>
#include <unistd.h>
EndeavourCom::EndeavourCom(unsigned short amacid, std::shared_ptr<DeviceCom> fpgaCom)
: m_amacid(amacid&0x1F), m_fpgaCom(fpgaCom)
{
m_raw=std::unique_ptr<EndeavourRaw>(new EndeavourRaw(m_fpgaCom));
}
void EndeavourCom::enableSeqNum(bool enableSeqNum)
{ m_enableSeqNum=enableSeqNum; }
void EndeavourCom::reset()
{
m_raw->reset();
m_seqnum=0;
}
void EndeavourCom::setid(REFMODE mode, unsigned int refid)
{
m_raw->sendData(0, 10);
usleep(10);
unsigned long long int databits=0;
//{3'b110, 5'b11111, 3'b111, newamacid[4:0], 4'b1111, efuseid[19:0], 3'b111, idpads[4:0], crc[7:0]}
// SETID - 3'b110
databits<<=3;
databits|=0b110;
// 3'b11111
databits<<=5;
databits|=0b11111;
// 3'b111
databits<<=3;
databits|=0b111;
// newamacid[4:0]
databits<<=5;
databits|=(m_amacid&0x1F);
// 4'b1111
databits<<=4;
databits|=0b1111;
// efuseid[19:0]
databits<<=20;
if(mode==REFMODE::EfuseId)
databits|=(refid&0xFFFFF);
else
databits|=0xFFFFF;
// 3'b111
databits<<=3;
databits|=0b111;
// idpads[4:0]
databits<<=5;
if(mode==IDPads)
databits|=(refid&0x1F);
else
databits|=0x1F;
// crc[7:0]
unsigned int crc=calc_crc(databits);
databits<<=8;
databits|=(crc&0xFF);
// send data
m_raw->sendData(databits, 56);
m_seqnum++;
// wait for response ( poll :( )
uint tryidx=0;
for(tryidx=0;tryidx<10;tryidx++)
{
if(m_raw->isDataValid()) break;
usleep(10);
}
if(tryidx==10)
throw EndeavourComException("SETID timeout");
// Parse the response
unsigned long long int read_data;
unsigned int read_nbits;
m_raw->readData(read_data,read_nbits);
//std::cout << m_raw->isDataValid() << " " << read_nbits << " " << std::hex << read_data << std::dec << std::endl;
if(read_nbits!=8)
throw EndeavourComException("SETID recieved wrong number of bits: %d (expected 8)",read_nbits);
unsigned short int seqnum=read_data&0b111;
if(m_enableSeqNum && seqnum!=m_seqnum)
throw EndeavourComException("SETID recieved wrong sequence: %d (expected %d)",seqnum,m_seqnum);
unsigned short int amacid=(read_data>>3)&0b11111;
if(amacid!=m_amacid)
throw EndeavourComException("SETID recieved wrong amacid: %d (expected %d)",amacid,m_amacid);
}
void EndeavourCom::write_reg(unsigned int address, unsigned int data)
{
unsigned long long int databits=0;
//{3'b111, amacid[4:0], addr[7:0], data[31:0], crc[7:0]}
// WRITE - 3'b110
databits<<=3;
databits|=0b111;
// amacid[4:0]
databits<<=5;
databits|=(m_amacid&0x1F);
// addr[7:0]
databits<<=8;
databits|=(address&0xFF);
// data[31:0]
databits<<=32;
databits|=(data&0xFFFFFFFF);
// crc[7:0]
unsigned int crc=calc_crc(databits);
databits<<=8;
databits|=(crc&0xFF);
// send data
m_raw->sendData(databits, 56);
m_seqnum++;
// wait for response ( poll :( )
uint tryidx=0;
for(tryidx=0;tryidx<10;tryidx++)
{
if(m_raw->isDataValid()) break;
usleep(10);
}
if(tryidx==10)
throw EndeavourComException("SETID timeout");
// Parse the response
unsigned long long int read_data;
unsigned int read_nbits;
m_raw->readData(read_data,read_nbits);
//std::cout << m_raw->isDataValid() << " " << read_nbits << " " << std::hex << read_data << std::dec << std::endl;
if(read_nbits!=8)
throw EndeavourComException("WRITE recieved wrong number of bits: %d (expected 8)",read_nbits);
unsigned short int seqnum=read_data&0b111;
if(m_enableSeqNum && seqnum!=m_seqnum)
throw EndeavourComException("WRITE recieved wrong sequence: %d (expected %d)",seqnum,m_seqnum);
unsigned short int amacid=(read_data>>3)&0b11111;
if(amacid!=m_amacid)
throw EndeavourComException("WRITE recieved wrong amacid: %d (expected %d)",amacid,m_amacid);
}
unsigned int EndeavourCom::read_reg(unsigned int address)
{
unsigned long long int databits=0;
//{3'b101, amacid[4:0], addr[7:0]}
// READ - 3'b101
databits<<=3;
databits|=0b101;
// amacid[4:0]
databits<<=5;
databits|=(m_amacid&0x1F);
// addr[7:0]
databits<<=8;
databits|=(address&0xFF);
// send data
m_raw->sendData(databits, 16);
m_seqnum++;
// wait for response ( poll :( )
uint tryidx=0;
for(tryidx=0;tryidx<10;tryidx++)
{
if(m_raw->isDataValid()) break;
usleep(10);
}
if(tryidx==10)
throw EndeavourComException("READ timeout");
// Parse the response
unsigned long long int read_data;
unsigned int read_nbits;
m_raw->readData(read_data,read_nbits);
//std::cout << m_raw->isDataValid() << " " << read_nbits << " " << std::hex << read_data << std::dec << std::endl;
if(read_nbits!=48)
throw EndeavourComException("READ recieved wrong number of bits: %d (expected 48)",read_nbits);
unsigned int data=read_data&0xFFFFFFFF;
unsigned short int retaddress=(read_data>>32)&0xFF;
if(retaddress!=address)
throw EndeavourComException("READ recieved wrong address: 0x%08X (expected %08X)",retaddress,address);
unsigned short int seqnum=(read_data>>40)&0b111;
if(m_enableSeqNum && seqnum!=m_seqnum)
throw EndeavourComException("READ recieved wrong sequence: %d (expected %d)",seqnum,m_seqnum);
unsigned short int amacid=(read_data>>43)&0b11111;
if(amacid!=m_amacid)
throw EndeavourComException("READ recieved wrong amacid: %d (expected %d)",amacid,m_amacid);
return data;
}
unsigned int EndeavourCom::readnext_reg()
{
unsigned long long int databits=0;
//{3'b100, amacid[4:0]}
// READNEXT - 3'b100
databits<<=3;
databits|=0b100;
// amacid[4:0]
databits<<=5;
databits|=(m_amacid&0x1F);
// send data
m_raw->sendData(databits, 8);
m_seqnum++;
// wait for response ( poll :( )
uint tryidx=0;
for(tryidx=0;tryidx<10;tryidx++)
{
if(m_raw->isDataValid()) break;
usleep(10);
}
if(tryidx==10)
throw EndeavourComException("SETID timeout");
// Parse the response
unsigned long long int read_data;
unsigned int read_nbits;
m_raw->readData(read_data,read_nbits);
//std::cout << m_raw->isDataValid() << " " << read_nbits << " " << std::hex << read_data << std::dec << std::endl;
if(read_nbits!=48)
throw EndeavourComException("READ recieved wrong number of bits: %d (expected 48)",read_nbits);
unsigned int data=read_data&0xFFFFFFFF;
//unsigned short int retaddress=(read_data>>32)&0xFF;
unsigned short int seqnum=(read_data>>40)&0b111;
if(m_enableSeqNum && seqnum!=m_seqnum)
throw EndeavourComException("READ recieved wrong sequence: %d (expected %d)",seqnum,m_seqnum);
unsigned short int amacid=(read_data>>43)&0b11111;
if(amacid!=m_amacid)
throw EndeavourComException("READ recieved wrong amacid: %d (expected %d)",amacid,m_amacid);
return data;
}
unsigned int EndeavourCom::calc_crc(unsigned long long int data) const
{
unsigned crc=0;
for(unsigned int i=0;i<8;i++)
{
crc|=(( ((data>>(8*0+i))&1) ^
((data>>(8*1+i))&1) ^
((data>>(8*2+i))&1) ^
((data>>(8*3+i))&1) ^
((data>>(8*4+i))&1) ^
((data>>(8*5+i))&1) )<<i);
}
return crc;
}
#ifndef ENDEAVOURCOM_H
#define ENDEAVOURCOM_H
#include <memory>
#include "DeviceCom.h"
#include "EndeavourRaw.h"
class EndeavourCom : public DeviceCom
{
public:
enum REFMODE {IDPads, EfuseId};
EndeavourCom(unsigned short amacid, std::shared_ptr<DeviceCom> fpgaCom);
void enableSeqNum(bool enableSeqNum);
void reset();
void setid(REFMODE mode, unsigned int refid);
virtual void write_reg(unsigned int address, unsigned int data);
virtual unsigned int read_reg(unsigned int address);
virtual unsigned int readnext_reg();
//implemented in DeviceCom
virtual void write_reg(std::vector<unsigned int> data_vec){};
virtual void write_data(uint8_t data){};
virtual void read_reg(unsigned int address, uint8_t* data, unsigned int len){};
virtual void read_reg(uint8_t* data_in, uint8_t* data_out, unsigned int len){};
private:
unsigned short m_amacid;
bool m_enableSeqNum =false;
unsigned short m_seqnum =0;
std::unique_ptr<EndeavourRaw> m_raw;
std::shared_ptr<DeviceCom> m_fpgaCom;
unsigned int calc_crc(unsigned long long int data) const;
};
#endif //ENDEAVOURCOM_H
#include "EndeavourComException.h"
EndeavourComException::EndeavourComException(const std::string& msg)
: m_msg("EndeavourCom: "+msg)
{ }
EndeavourComException::EndeavourComException(const char *format, ...)
{
char buffer[256];
va_list args;
va_start( args, format );
vsnprintf( buffer, 256, format, args );
va_end( args );
m_msg=std::string("EndeavourCom: ")+buffer;
}
const char* EndeavourComException::what() const throw()
{ return m_msg.c_str(); }
#ifndef ENDEAVOURCOMEXCEPTION_H
#define ENDEAVOURCOMEXCEPTION_H
#include <stdarg.h>
#include <string>
#include "ComException.h"
class EndeavourComException : ComException
{
public:
EndeavourComException(const std::string& msg);
EndeavourComException(const char *format, ...);
virtual const char* what() const throw();
private:
std::string m_msg;
};
#endif // ENDEAVOURCOMEXCEPTION_H
#include "EndeavourRaw.h"
EndeavourRaw::EndeavourRaw(std::shared_ptr<DeviceCom> fpgaCom)
: m_fpgaCom(fpgaCom)
{ }
void EndeavourRaw::reset()
{ m_fpgaCom->write_reg32(0, 0x1); }
bool EndeavourRaw::isError()
{ return (m_fpgaCom->read_reg32(0)>>2)&1; }
bool EndeavourRaw::isDataValid()
{
return (m_fpgaCom->read_reg32(0)>>1)&1;
}
void EndeavourRaw::sendData(unsigned long long int data, unsigned int size)
{
m_fpgaCom->write_reg32(1, size);
m_fpgaCom->write_reg32(2, (data>>0 )&0xFFFFFFFF);
m_fpgaCom->write_reg32(3, (data>>32)&0xFFFFFFFF);
m_fpgaCom->write_reg32(0, 0x2);
}
void EndeavourRaw::readData(unsigned long long int& data, unsigned int& size)
{
if(isDataValid())
{
size=m_fpgaCom->read_reg32(4);
data=m_fpgaCom->read_reg32(6);
data<<=32;
data|=m_fpgaCom->read_reg32(5);
}
else
{
size=0;
data=0;
}
}
#ifndef ENDEAVOURRAW_H
#define ENDEAVOURRAW_H
#include <memory>
#include "DeviceCom.h"
class EndeavourRaw
{
public:
EndeavourRaw(std::shared_ptr<DeviceCom> fpgaCom);
void reset();
void sendData(unsigned long long int data, unsigned int size);
bool isError();
bool isDataValid();
void readData(unsigned long long int& data, unsigned int& size);
private:
std::shared_ptr<DeviceCom> m_fpgaCom;
};
#endif //ENDEAVOURRAW_H
......@@ -37,7 +37,7 @@ uint32_t FileCalibration::uncalibrate(double value)
for(uint32_t i=0; i<m_values.size()-1; i++)
{
if(m_values[i]<=value && value<m_values[i+1]) // Found interval
return m_counts[i]+(m_values[i]-value)/(m_values[i]-m_values[i+1])*(m_counts[i+1]-m_counts[i]);
return round(m_counts[i]+(m_values[i]-value)/(m_values[i]-m_values[i+1])*(m_counts[i+1]-m_counts[i]));
}
return 0;
}
#include "FreqMeas.h"
void FreqMeasInst::init_inst(std::shared_ptr<DeviceCom> dev, uint8_t id, uint32_t ts_cnt){
m_dev = dev;
m_id = id;
this->reset_inst();
this->freeze_inst();
this->set_ts_cnt_inst(ts_cnt);
this->start_inst();
}
void FreqMeasInst::reset_inst(bool active){
uint32_t data = m_dev->read_reg32(4*m_id);
data = (data & 0x7FFFFFFF) | ((uint32_t)~active << 31); //reset active low in FW
m_dev->write_reg32((4*m_id), data);
}
void FreqMeasInst::toggle_reset_inst(){
this->reset_inst(true);
this->reset_inst(false);
}
void FreqMeasInst::freeze_inst(bool active){
uint32_t data = m_dev->read_reg32(4*m_id);
data = (data & 0xBFFFFFFF) | ((uint32_t)active << 30);
m_dev->write_reg32((4*m_id), data);
}
void FreqMeasInst::start_inst(){
this->reset_inst(false);
this->freeze_inst(false);
}
void FreqMeasInst::set_ts_cnt_inst(uint32_t ts_cnt){
uint32_t data = m_dev->read_reg32(4*m_id);
data = (data & 0xC0000000) | (ts_cnt & 0x3FFFFFFF);
m_dev->write_reg32((4*m_id), data);
}
void FreqMeasInst::read_inst(){
m_hi_n = m_dev->read_reg32(4*m_id+1);
m_lo_n = m_dev->read_reg32(4*m_id+2);
m_hi_t = m_dev->read_reg32(4*m_id+3);
}
uint32_t FreqMeasInst::get_ts_cnt_inst(){
uint32_t data = m_dev->read_reg32(4*m_id);
return(data & 0x3FFFFFFF);
}
void FreqMeas::reset(FreqMeasInst FreqMeas::* ref, bool active){
(this->*ref).reset_inst(active);
}
void FreqMeas::reset(const std::string str, bool active){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).reset_inst(active);
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
void FreqMeas::toggle_reset(FreqMeasInst FreqMeas::* ref){
(this->*ref).toggle_reset_inst();
}
void FreqMeas::toggle_reset(const std::string str){
if(regMap.find(str) != regMap.end()){
toggle_reset(regMap.find(str)->second);
return;
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
void FreqMeas::toggle_reset_all(){
for(auto const& it : regMap)
toggle_reset(it.second);
}
void FreqMeas::freeze(FreqMeasInst FreqMeas::* ref, bool active){
(this->*ref).freeze_inst(active);
}
void FreqMeas::freeze(const std::string str, bool active){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).freeze_inst(active);
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
void FreqMeas::start(FreqMeasInst FreqMeas::* ref){
(this->*ref).start_inst();
}
void FreqMeas::start(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).start_inst();
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
void FreqMeas::set_ts_cnt(FreqMeasInst FreqMeas::* ref, uint32_t ts_cnt){
(this->*ref).set_ts_cnt_inst(ts_cnt);
}
void FreqMeas::set_ts_cnt(const std::string str, uint32_t ts_cnt){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).set_ts_cnt_inst(ts_cnt);
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
void FreqMeas::read(FreqMeasInst FreqMeas::* ref){
(this->*ref).read_inst();
}
void FreqMeas::read(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).read_inst();
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return;
}
uint32_t FreqMeas::get_ts_cnt(FreqMeasInst FreqMeas::* ref){
return (this->*ref).get_ts_cnt_inst();
}
uint32_t FreqMeas::get_ts_cnt(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).get_ts_cnt_inst();
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return 0;
}
uint32_t FreqMeas::get_hi_n(FreqMeasInst FreqMeas::* ref){
return (this->*ref).hi_n;
}
uint32_t FreqMeas::get_hi_n(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).hi_n;
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return 0;
}
uint32_t FreqMeas::get_lo_n(FreqMeasInst FreqMeas::* ref){
return (this->*ref).lo_n;
}
uint32_t FreqMeas::get_lo_n(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).lo_n;
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return 0;
}
uint32_t FreqMeas::get_hi_t(FreqMeasInst FreqMeas::* ref){
return (this->*ref).hi_t;
}
uint32_t FreqMeas::get_hi_t(const std::string str){
if(regMap.find(str) != regMap.end()){
return(this->*regMap[str]).hi_t;
} else {
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
}
return 0;
}
void FreqMeas::init(){
HVOSC0.init_inst(m_dev, 0); regMap["HVOSC0"] = &FreqMeas::HVOSC0;
HVOSC1.init_inst(m_dev, 1); regMap["HVOSC1"] = &FreqMeas::HVOSC1;
HVOSC2.init_inst(m_dev, 2); regMap["HVOSC2"] = &FreqMeas::HVOSC2;
HVOSC3.init_inst(m_dev, 3); regMap["HVOSC3"] = &FreqMeas::HVOSC3;
CLKOUT.init_inst(m_dev, 4); regMap["CLKOUT"] = &FreqMeas::CLKOUT;
}
float FreqMeas::get_frq(FreqMeasInst FreqMeas::* ref)
{
return ((float)get_hi_n(ref)/get_ts_cnt(ref))*m_bClkHz;
}
float FreqMeas::get_frq(const std::string& str)
{
if(regMap.find(str) != regMap.end())
return get_frq(regMap.find(str)->second);
else
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
return 0.0;
}
float FreqMeas::get_duty_cycle(FreqMeasInst FreqMeas::* ref){
return (float)get_hi_t(ref)/get_ts_cnt(ref);
}
float FreqMeas::get_duty_cycle(const std::string& str){
if(regMap.find(str) != regMap.end())
return get_duty_cycle(regMap.find(str)->second);
else
std::cerr << " --> Error: Could not find register \""<< str << "\"" << std::endl;
return 0.0;
}
#ifndef FREQ_MEAS_H
#define FREQ_MEAS_H
#include "UIOCom.h"
#include <memory>
#include <cstdint>
#include <iostream>
#include <map>
class FreqMeasInst{
public:
FreqMeasInst(){
m_id = 0;
m_hi_n = 0;
m_lo_n = 0;
m_hi_t = 0;
m_dev = NULL;
}
~FreqMeasInst(){};
void init_inst(std::shared_ptr<DeviceCom> dev, uint8_t id, uint32_t ts_cnt = 10000);
void reset_inst(bool active = true);
void toggle_reset_inst();
void freeze_inst(bool active = true);
void start_inst();
uint32_t get_ts_cnt_inst();
void set_ts_cnt_inst(uint32_t ts_cnt = 10000);
void read_inst();
const uint32_t& hi_n = m_hi_n;
const uint32_t& lo_n = m_lo_n;
const uint32_t& hi_t = m_hi_t;
private:
uint8_t m_id;
uint32_t m_hi_n;
uint32_t m_lo_n;
uint32_t m_hi_t;
std::shared_ptr<DeviceCom> m_dev;
};
class FreqMeas{
public:
FreqMeas(std::shared_ptr<DeviceCom> dev, uint32_t bClkHz = 100E6) : m_dev(dev), m_bClkHz(bClkHz){
this->init();
}
~FreqMeas(){};
void reset(FreqMeasInst FreqMeas::* ref, bool active = true);
void reset(const std::string str, bool active = true);
void toggle_reset(FreqMeasInst FreqMeas::* ref);
void toggle_reset(const std::string str);
void toggle_reset_all();
void freeze(FreqMeasInst FreqMeas::* ref, bool active = true);
void freeze(const std::string str, bool active = true);
void start(FreqMeasInst FreqMeas::* ref);
void start(const std::string str);
void set_ts_cnt(FreqMeasInst FreqMeas::* ref, uint32_t ts_cnt);
void set_ts_cnt(const std::string str, uint32_t ts_cnt);
void read(FreqMeasInst FreqMeas::* ref);
void read(const std::string str);
uint32_t get_ts_cnt(FreqMeasInst FreqMeas::* ref);
uint32_t get_ts_cnt(const std::string str);
uint32_t get_hi_n(FreqMeasInst FreqMeas::* ref);
uint32_t get_hi_n(const std::string str);
uint32_t get_lo_n(FreqMeasInst FreqMeas::* ref);
uint32_t get_lo_n(const std::string str);
uint32_t get_hi_t(FreqMeasInst FreqMeas::* ref);
uint32_t get_hi_t(const std::string str);
float get_frq(FreqMeasInst FreqMeas::* ref);
float get_frq(const std::string& str);
float get_duty_cycle(FreqMeasInst FreqMeas::* ref);
float get_duty_cycle(const std::string& str);
std::map<std::string, FreqMeasInst FreqMeas::*> regMap; //To control them all directly
FreqMeasInst HVOSC0;
FreqMeasInst HVOSC1;
FreqMeasInst HVOSC2;
FreqMeasInst HVOSC3;
FreqMeasInst CLKOUT;
private:
void init();
std::shared_ptr<DeviceCom> m_dev;
uint32_t m_bClkHz;
};
#endif //FREQ_MEAS_H
#include "LTC2333.h"
#include <unistd.h>
LTC2333::LTC2333(std::shared_ptr<DeviceCom> dev) : m_dev(dev){
init();
}
LTC2333::~LTC2333()
{
}
void LTC2333::init(){
reset();
}
void LTC2333::reset(){
// NOTE: we have seen on initial usage of the SPI bus that we sometimes have
// 24 clock edges instead of the expected 8 clock edges. If this persists, we should
// call setADC(vec) on each reset, and potentially similarly for the DAC and
// potentiometer code (if deemed to be needed / to be affecting anything).
// We expect that this just sends garbage which is never used, however.
}
bool LTC2333::checkValidInput(unsigned int chan, unsigned int span){
if(chan > m_chanMax){
std::cout << "LTC2333::checkValidInput ERROR chan is" << std::hex << chan << ", but chanMax is" << std::hex << m_chanMax << std::endl;
std::cout << "Exiting checkValidInput" << std::endl;
return false;
}
if(span > m_spanMax){
std::cout << "LTC2333::checkValidInput ERROR span is" << std::hex << span << ", but spanMax is" << std::hex << m_spanMax << std::endl;
std::cout << "Exiting checkValidInput" << std::endl;
return false;
}
return true;
}
unsigned int LTC2333::formatCommand(unsigned int chan, unsigned int span){
// cmd header for MUX control (10 in binary)
unsigned int cmd = 0x2;
chan = chan & m_chanMax;
span = span & m_spanMax;
// input is 8 bits, so shift the 2-bit header over by 6
// and the 3-bit middle part by 3
unsigned int input = (cmd << 6) | (chan << 3) | span;
return input;
}
std::vector<unsigned int> LTC2333::formatConversionResult(uint8_t* data){
// Here we parse the 8-bit data into a single unsigned int
unsigned int output = 0;
for(unsigned int index = 0; index < m_nBytesData; ++index){
output = (output << 8) | data[index];
}
// Now split output into its components
unsigned int output_span = output & m_spanMax;
unsigned int output_chan = (output >> 3) & m_chanMax;
// Here is the 18-bit result
unsigned int output_result = (output >> 6) & 0xFFFF; // 0xFFFF = 2^16-1
return {output_result, output_chan, output_span};
}
void LTC2333::setADC(std::vector<std::pair<uint8_t,uint8_t>> inputSettings){
uint8_t nBytesIn = inputSettings.size();
if(nBytesIn > 16){
std::cout << "LTC2333::setADC ERROR too many chan/span" << std::endl;
std::cout << "Exiting setADC" << std::endl;
return;
}
//std::cout << "nbytesIn: " << unsigned(nBytesIn) << std::endl;
uint8_t tx[nBytesIn] = {0, };
for(unsigned int i = 0; i < nBytesIn; ++i){
auto inputPair = inputSettings.at(i);
uint8_t chan = inputPair.first;
uint8_t span = inputPair.second;
// Check that chan and span are in range
if( !checkValidInput(chan, span) ){
// ERROR and maybe return
std::cout << "LTC2333::setADC ERROR invalid chan/span" << std::endl;
std::cout << "Exiting setADC" << std::endl;
return;
}
// Format our 8-bit word of cmd code, chan, and span
tx[i] = (uint8_t) formatCommand(chan, span);
//std::cout << "tx[" << i << "] is " << std::hex << unsigned(tx[i]) << std::endl;
}
m_inputSettings = inputSettings;
m_nBytesIn = nBytesIn;
m_dev->read_reg(tx, NULL, nBytesIn);
m_init = true;
usleep(m_nBytesIn); //sleep for tx
}
std::vector<LTC2333Outputs> LTC2333::getADC(){
if(!m_init){
std::cout << "LTC2333::getADC ERROR no previously initiated conversion to read!" << std::endl;
std::cout << "Exiting getADC" << std::endl;
return {};
}
//Set ADC_CNV pin FIXME remove hardcoding
uint32_t data = m_dio->read_reg(0x2);
uint32_t mask = (uint32_t)(1 << 7);
data = (data & ~mask) | (true << 7);
m_dio->write_reg(0x2, data);
//Reset ADC_CNV pin
data = m_dio->read_reg(0x2);
mask = (uint32_t)(1 << 7);
data = (data & ~mask) | (false << 7);
m_dio->write_reg(0x2, data);
usleep(1); //wait for conversion to finish
uint8_t rx[3*m_nBytesIn] = {0, };
uint8_t dummy [3*m_nBytesIn] = {0, };
m_dev->read_reg(dummy, NULL, 3*m_nBytesIn); //activate CS+clock for a 192 clock cycles
usleep(m_nBytesIn); //wait for rx buffer to fill
m_dev->read_reg(dummy, rx, 3*m_nBytesIn); //recover data in rx (clocks will also be activated...)
std::vector<LTC2333Outputs> outputs;
// Iterate 3-bytes at a time
for(unsigned int i = 0; i < 3*m_nBytesIn; i+=3){
LTC2333Outputs output_i;
// 16 bit conversion result
output_i.result = (rx[i] << 8) | (rx[i+1] );
output_i.chan = (rx[i+2] >> 3) & m_chanMax;
output_i.span = rx[i+2] & m_spanMax;
outputs.push_back(output_i);
}
return outputs;
}
LTC2333Outputs LTC2333::setAndReadChan(uint8_t chan, uint8_t span){
std::vector<std::pair<uint8_t,uint8_t>> vec;
vec.push_back( std::make_pair(chan, span) );
// initializes the conversion
setADC(vec);
//usleep(100); //for good measure
return getADC().at(0);
}
\ No newline at end of file
#ifndef LTC2333_H
#define LTC2333_H
#include "ADCDevice.h"
#include "DeviceCom.h"
#include "UIOCom.h"
#include <vector>
#include <iostream>
#include <memory>
#include <unistd.h>
struct LTC2333Outputs{
uint16_t result;
uint8_t chan;
uint8_t span;
};
class LTC2333 : public ADCDevice
{
public:
LTC2333(std::shared_ptr<DeviceCom> dev);
~LTC2333();
void init();
void reset();
// Sets next conversion result for specified channel and span, and
//
// Return value is a vector of length three, containing:
// index 0: 18-bit conversion result
// index 1: 3-bit channel ID
// index 2: 3-bit soft span value
//
// Valid channels are 0-7.
//
// Valid spans are:
//
// 0: 0V to 1.25*V_refbuf/1.024
// 1: 0V to 1.25*V_refbuf
// 2: +/-1.25*V_refbuf/1.024
// 3: +/-1.25*V_refbuf
// 4: 0V to 2.5*V_refbuf/1.024
// 5: 0V to 2.5*V_refbuf
// 6: +/-2.5*V_refbuf/1.024
// 7: +/-2.5*V_refbuf
//
// inputSettings is a pair of (channel, span)
void setADC(std::vector<std::pair<uint8_t,uint8_t>> inputSettings);
// Reads out previous conversion result
std::vector<LTC2333Outputs> getADC();
// Calls previous two functions for a single channel, with default span of 0
// (but can set it as an option).
//
// **Note that currently only a single channel works for setADC anyway!!
LTC2333Outputs setAndReadChan(uint8_t chan, uint8_t span = 0);
private:
std::shared_ptr<DeviceCom> m_dio = std::make_shared<UIOCom>("/dev/uio0", 0x10000);
std::shared_ptr<DeviceCom> m_dev;
bool m_init = false;
uint8_t m_nBytesIn;
std::vector<std::pair<uint8_t,uint8_t>> m_inputSettings;
const unsigned int m_chanMax = 0x7;
const unsigned int m_spanMax = 0x7;
// 3 bytes = 24 bits, which is enough for our ADC reads
const unsigned int m_nBytesData = 3;
bool checkValidInput(unsigned int chan, unsigned int span);
unsigned int formatCommand(unsigned int chan, unsigned int span);
std::vector<unsigned int> formatConversionResult(uint8_t* data);
};
#endif // LTC2333_H
#include "LTC2666.h"
LTC2666::LTC2666(std::shared_ptr<DeviceCom> dev) : m_dev(dev){
init();
}
LTC2666::~LTC2666()
{
}
void LTC2666::init(){
reset();
}
void LTC2666::reset(){
// originally did a power down and reset to DAC count = 0 here,
// but doesn't make sense to do this anymore if we want to use these on the fly
}
void LTC2666::writeUpdateAll(unsigned int counts){
// cmd header for write and update all DACs
unsigned int cmd = 0xA0;
unsigned int leadDigits = (counts >> 8) & 0xFF;
unsigned int subleadDigits = counts & 0xFF;
m_dev->write_reg({cmd, leadDigits, subleadDigits});
}
void LTC2666::writeUpdateChan(unsigned int chan, unsigned int counts){
if(chan > m_chanMax){
std::cout << "LTC2666::writeUpdateChan ERROR chan is" << std::hex << chan << ", but chanMax is" << std::hex << m_chanMax << std::endl;
std::cout << "Exiting writeUpdateChan" << std::endl;
return;
}
// cmd header for write and update channel
unsigned int cmd = 0x30;
// Add 0x30 + 0x0Y (for channel Y)
cmd += chan;
unsigned int leadDigits = (counts >> 8) & 0xFF;
unsigned int subleadDigits = counts & 0xFF;
m_dev->write_reg({cmd, leadDigits, subleadDigits});
}
void LTC2666::powerDownAll(){
// cmd header to turn off all DACs.
unsigned int cmd = 0x50;
// Other values don't matter.
m_dev->write_reg({cmd, 0x00, 0x00});
}
void LTC2666::powerDownChan(unsigned int chan){
if(chan > m_chanMax){
std::cout << "LTC2666::powerDownChan ERROR chan is" << std::hex << chan << ", but chanMax is" << std::hex << m_chanMax << std::endl;
std::cout << "Exiting powerDownChan" << std::endl;
return;
}
// cmd header for power down channel
unsigned int cmd = 0x40;
// Add 0x40 + 0x0Y (for channel Y)
cmd += chan;
// Other values don't matter.
m_dev->write_reg({cmd, 0x00, 0x00});
}
void LTC2666::changeSpanAll(unsigned int span){
if(span > m_spanMax){
std::cout << "LTC2666::changeSpanAll ERROR span is" << std::hex << span << ", but spanMax is" << std::hex << m_spanMax << std::endl;
std::cout << "Exiting changeSpanAll" << std::endl;
return;
}
// cmd header for change span for all
unsigned int cmd = 0xE0;
// Middle value doesn't matter
m_dev->write_reg({cmd, 0x00, span});
}
void LTC2666::changeSpanChan(unsigned int chan, unsigned int span){
if(chan > m_chanMax){
std::cout << "LTC2666::changeSpanChan ERROR chan is" << std::hex << chan << ", but chanMax is" << std::hex << m_chanMax << std::endl;
std::cout << "Exiting changeSpanChan" << std::endl;
return;
}
if(span > m_spanMax){
std::cout << "LTC2666::changeSpanChan ERROR span is" << std::hex << span << ", but spanMax is" << std::hex << m_spanMax << std::endl;
std::cout << "Exiting changeSpanChan" << std::endl;
return;
}
// cmd header for change span for channel
unsigned int cmd = 0x60;
// Add 0x60 + 0x0Y (for channel Y)
cmd += chan;
// Middle value doesn't matter
m_dev->write_reg({cmd, 0x00, span});
}
void LTC2666::pointMuxAtChan(unsigned int muxChan){
if(muxChan > m_muxChanMax){
std::cout << "LTC2666::pointMuxAtChan ERROR muxChan is" << std::hex << muxChan << ", but muxChanMax is" << std::hex << m_muxChanMax << std::endl;
std::cout << "Exiting pointMuxAtChan" << std::endl;
return;
}
// cmd header for MUX command
unsigned int cmd = 0xB0;
// to select particular channel
unsigned int chanSel = 0x10;
// Add 0x10 + 0x0Y (for mux chan Y)
chanSel += muxChan;
// Middle value doesn't matter
m_dev->write_reg({cmd, 0x00, chanSel});
}
void LTC2666::disableMux(){
// cmd header for MUX command
unsigned int cmd = 0xB0;
// to disable MUX
unsigned int chanSel = 0x00;
// Middle value doesn't matter
m_dev->write_reg({cmd, 0x00, chanSel});
}
#ifndef LTC2666_H
#define LTC2666_H
#include "DACDevice.h"
#include "SPICom.h"
#include <vector>
#include <iostream>
#include <memory>
class LTC2666 : public DACDevice
{
public:
LTC2666(std::shared_ptr<DeviceCom> dev);
~LTC2666();
void init();
void reset();
// Write and update all channels with given number of counts (as a 16 bit number).
void writeUpdateAll(unsigned int counts);
// Write and update channel with given number of counts (as a 16 bit number).
// Valid channels are 0-7
void writeUpdateChan(unsigned int chan, unsigned int counts);
// Turn off all DACs.
// Channel will automatically turn back on after an update signal.
void powerDownAll();
// Turn off DAC channel.
// Channel will automatically turn back on after an update signal.
// Valid channels are 0-7
void powerDownChan(unsigned int chan);
// Valid spans are:
//
// 0: 0V to 5V unipolar
// 1: 0V to 10V unipolar
// 2: -5V to 5V bipolar
// 3: -10V to 10V bipolar
// 4: -2.5V to 2.5V bipolar
void changeSpanAll(unsigned int span);
// Valid channels are 0-7
void changeSpanChan(unsigned int chan, unsigned int span);
// Route channel to the MUX; maybe not so useful for us.
// Valid channels are:
//
// 0-7: Vout_0 -> Vout_7
// 8: REFLO
// 9: REF
// A: Temperature monitor
// B: V+
// C: V-
void pointMuxAtChan(unsigned int chan);
// Disable the MUX
void disableMux();
private:
std::shared_ptr<DeviceCom> m_dev;
const unsigned int m_chanMax = 0x7;
const unsigned int m_muxChanMax = 0xC;
const unsigned int m_spanMax = 0x4;
};
#endif // LTC2666_H