HeartBeatRate/Software/dashboard/lib/hal/ads1256.dart

279 lines
8.1 KiB
Dart
Raw Normal View History

2024-09-15 18:06:05 +07:00
import 'package:dart_periphery/dart_periphery.dart';
import 'package:logging/logging.dart';
import 'dart:io';
extension Ads1265Int on int {
double toMicroVolt(){
int newThis = this;
if ((newThis >> 23) == 1) {
newThis = this - 16777216;
}
// 5000000.0 microVolt = Vref; 8388608 = 2^{23} -1
// (5000000.0 / 8388608) = 0.5960464477539062;
return 0.5960464477539062 * newThis;
}
double toMilliVolt() => toMicroVolt() / 1000.0;
double toVolt() => toMicroVolt() / 1000000.0;
}
class Ads1256 {
late SPI spi; //SPI
late GPIO drdy; //GPIO
late GPIO? rst;
late GPIO? cs; //GPIO
late Logger log;
Ads1256({
required int spiBus,
required int spiChip,
required int gpioChip,
required int pinDrdy,
String? tag,
int? pinReset,
int? pinCS }){
spi = SPI(spiBus, spiChip, SPImode.mode1, 50000);
drdy = GPIO(pinDrdy, GPIOdirection.gpioDirIn, gpioChip);
cs = pinCS != null ? GPIO(pinCS, GPIOdirection.gpioDirOutHigh, gpioChip): null;
rst = pinReset != null ? GPIO(pinReset, GPIOdirection.gpioDirOutHigh, gpioChip): null;
log = Logger("[Ads1256][$tag]");
}
void skipClk()=>sleep(const Duration(microseconds: 1 ));
void writeRegister(int reg, int wdata) {
log.info(' writeRegistere() <${reg.toRadixString(16)}> <${wdata.toRadixString(8)}>');
waitDRDY();
spi.transfer([CMD_WREG | reg, 0, wdata], false);
skipClk();
}
int readRegister(int reg) {
waitDRDY();
spi.transfer([CMD_RREG | reg], true);
skipClk();
List<int> val= spi.transfer([CMD_WAKEUP, CMD_WAKEUP], true);
log.info(' readRegister() <${reg.toRadixString(16)}>');
log.info(' > ${val[1].toRadixString(16)}');
skipClk();
return val[1];
}
void sendCommand(int cmd){
log.info(' sendCommand() <${cmd.toRadixString(16)}>');
csOn();
waitDRDY();
spi.transfer([cmd], false);
csOff();
}
int get offsetCalibration {
csOn();
int x = readRegister(RADD_OFC0) | readRegister(RADD_OFC1) <<8 | readRegister(RADD_OFC2) <<16;
csOff();
return x;
}
int get fullscaleCalibration {
csOn();
int x = readRegister(RADD_FSC0) | readRegister(RADD_FSC1) <<8 | readRegister(RADD_FSC2) <<16;
csOff();
return x;
}
void calibrateOffsetGain()=>sendCommand(CMD_SELFCAL);
void calibrateOffset()=>sendCommand(CMD_SELFOCAL);
void calibrateGain()=>sendCommand(CMD_SELFGCAL);
void calibrateSystemOffset()=>sendCommand(CMD_SYSOCAL);
void calibrateSystemGain()=>sendCommand(CMD_SYSGCAL);
void stopContinueRead()=>sendCommand(CMD_SDATAC);
void resetCommand()=>sendCommand(CMD_RESET);
void doReset(){
waitDRDY();
rst?.write(false);
skipClk();
skipClk();
skipClk();
rst?.write(true);
}
void waitDRDY() {
while (drdy.read()){}
}
void csOn(){
cs?.write(false);
log.info("============== Start transfer");
}
void csOff(){
log.info("============== End transfer");
cs?.write(true);
}
void begin(int drate, int gain, bool buffen) {
log.info("begin() : <${drate.toRadixString(16)}> <${gain.toRadixString(8)}> <$buffen>");
doReset();
csOn();
resetCommand();
syncIt();
buffer = buffen;
autoCalibration = true;
clockOutRate = CLKOUT_1;
programmableGain = gain;
dataRate = drate;
log.info(" status : ${status.toRadixString(16)}");
log.info(" adcon : ${controlRegister.toRadixString(16)}");
log.info(" drate : ${dataRate.toRadixString(16)}");
csOff();
calibrateOffsetGain();
}
void syncIt(){
spi.transfer([CMD_SYNC], false);
skipClk();
skipClk();
skipClk();
spi.transfer([CMD_WAKEUP], false);
skipClk();
}
int get status => readRegister(RADD_STATUS);
set buffer(bool isEnable){
isEnable ? writeRegister(RADD_STATUS, (status | (0x01 << 1))):
writeRegister(RADD_STATUS, (status & ~(0x01 << 1)));
}
set autoCalibration(bool isEnable){
isEnable ? writeRegister(RADD_STATUS, (status | (0x01 << 2))):
writeRegister(RADD_STATUS, (status & ~(0x01 << 2)));
}
int get controlRegister => readRegister(RADD_ADCON);
set clockOutRate(int clk)=>writeRegister(RADD_ADCON, controlRegister | (clk << 5 ));
set programmableGain(int gain)=>writeRegister(RADD_ADCON, controlRegister | gain);
int get dataRate =>readRegister(RADD_DRATE);
set dataRate(int rate) => writeRegister(RADD_DRATE, rate);
set ioDir(List<int> dir){
csOn();
int d = dir[0] | dir[1]<<1 | dir[2]<<2 | dir[3]<<3;
writeRegister(RADD_IO, d <<4);
csOff();
}
List<bool> get dIO {
csOn();
int dio = readRegister(RADD_IO);
csOff();
return [(dio & 0x01)==0x01?true:false, (dio &0x02)==0x02?true:false, (dio &0x04)==0x04?true:false, (dio &0x08)==0x08?true:false];
}
set dIO(List<bool> io){
csOn();
writeRegister(RADD_IO, (io[0]?0x01:0x00) | (io[1]?0x02:0x00) | (io[2]?0x04:0x00) | (io[3]?0x08:0x00) );
csOff();
}
set channel(int c) => writeRegister(RADD_MUX, c<<4);
int analogRead(int channel){
log.info(" analogRead() <${channel.toRadixString(16)}>");
csOn();
waitDRDY();
this.channel = channel;
waitDRDY();
spi.transfer([CMD_RDATA], false);
skipClk();
List<int> d = spi.transfer([0, 0, 0], true);
csOff();
int v = d[0] << 16 | d[1] << 8 | d[2];
log.info(" > $v");
return v;
}
void dispose(){
spi.dispose(); //SPI
drdy.dispose(); //GPIO
cs?.dispose(); //GPIO
rst?.dispose(); //GPIO
}
static const int RADD_STATUS = 0x00;
static const int RADD_MUX = 0x01;
static const int RADD_ADCON = 0x02;
static const int RADD_DRATE = 0x03;
static const int RADD_IO = 0x04;
static const int RADD_OFC0 = 0x05;
static const int RADD_OFC1 = 0x06;
static const int RADD_OFC2 = 0x07;
static const int RADD_FSC0 = 0x08;
static const int RADD_FSC1 = 0x09;
static const int RADD_FSC2 = 0x0A;
static const int CMD_WAKEUP = 0x00;
static const int CMD_RDATA = 0x01;
static const int CMD_RDATAC = 0x03;
static const int CMD_SDATAC = 0x0f;
static const int CMD_RREG = 0x10;
static const int CMD_WREG = 0x50;
static const int CMD_SELFCAL = 0xF0;
static const int CMD_SELFOCAL = 0xF1;
static const int CMD_SELFGCAL = 0xF2;
static const int CMD_SYSOCAL = 0xF3;
static const int CMD_SYSGCAL = 0xF4;
static const int CMD_SYNC = 0xFC;
static const int CMD_STANDBY = 0xFD;
static const int CMD_RESET = 0xFE;
static const int MUXP_AIN0 = 0x00;
static const int MUXP_AIN1 = 0x10;
static const int MUXP_AIN2 = 0x20;
static const int MUXP_AIN3 = 0x30;
static const int MUXP_AIN4 = 0x40;
static const int MUXP_AIN5 = 0x50;
static const int MUXP_AIN6 = 0x60;
static const int MUXP_AIN7 = 0x70;
static const int MUXP_AINCOM = 0x80;
static const int MUXN_AIN0 = 0x00;
static const int MUXN_AIN1 = 0x01;
static const int MUXN_AIN2 = 0x02;
static const int MUXN_AIN3 = 0x03;
static const int MUXN_AIN4 = 0x04;
static const int MUXN_AIN5 = 0x05;
static const int MUXN_AIN6 = 0x06;
static const int MUXN_AIN7 = 0x07;
static const int MUXN_AINCOM = 0x08;
static const int GAIN_1 = 0x00;
static const int GAIN_2 = 0x01;
static const int GAIN_4 = 0x02;
static const int GAIN_8 = 0x03;
static const int GAIN_16 = 0x04;
static const int GAIN_32 = 0x05;
static const int GAIN_64 = 0x06;
static const int DRATE_30000SPS = 0xF0;
static const int DRATE_15000SPS = 0xE0;
static const int DRATE_7500SPS = 0xD0;
static const int DRATE_3750SPS = 0xC0;
static const int DRATE_2000SPS = 0xB0;
static const int DRATE_1000SPS = 0xA1;
static const int DRATE_500SPS = 0x92;
static const int DRATE_100SPS = 0x82;
static const int DRATE_60SPS = 0x72;
static const int DRATE_50SPS = 0x63;
static const int DRATE_30SPS = 0x53;
static const int DRATE_25SPS = 0x43;
static const int DRATE_15SPS = 0x33;
static const int DRATE_10SPS = 0x23;
static const int DRATE_5SPS = 0x13;
static const int DRATE_2_5SPS = 0x03;
static const int CLKOUT_OFF = 0x00;
static const int CLKOUT_1 = 0x20;
static const int CLKOUT_HALF = 0x40;
static const int CLKOUT_QUARTER = 0x60;
static const int IO_DIR_OUT = 0x00;
static const int IO_DIR_IN = 0x10;
}