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

301 lines
8.7 KiB
Dart

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;
toListBoolbit() => [(this & 0x01)==0x01?true:false, (this &0x02)==0x02?true:false, (this &0x04)==0x04?true:false, (this &0x08)==0x08?true:false];
}
extension Ads1265ListBool on List<bool> {
toNibble() => (this[0]?0x01:0x00) | (this[1]?0x02:0x00) | (this[2]?0x04:0x00) | (this[3]?0x08:0x00);
}
class Ads1256 {
late SPI spi; //SPI
late GPIO drdy; //GPIO
late GPIO? rst;
late GPIO? cs; //GPIO
late Logger log;
bool isCSActiveHigh;
Ads1256({
required int spiBus,
required int spiChip,
required int gpioChip,
required int pinDrdy,
required this.isCSActiveHigh,
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(16)}>');
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);
skipClk();
csOff();
}
int get offsetCalibration {
csOn();
skipClk();
int x = readRegister(RADD_OFC0) | readRegister(RADD_OFC1) <<8 | readRegister(RADD_OFC2) <<16;
csOff();
return x;
}
int get fullscaleCalibration {
csOn();
skipClk();
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(isCSActiveHigh?true:false);
skipClk();
skipClk();
skipClk();
log.info(" > Start transfer");
}
void csOff(){
log.info(" > End transfer");
cs?.write(isCSActiveHigh?false:true);
skipClk();
skipClk();
skipClk();
}
void begin(int drate, int gain, bool buffen) {
log.info("begin() : <${drate.toRadixString(16)}> <${gain.toRadixString(8)}> <$buffen>");
doReset();
resetCommand();
skipClk();
skipClk();
csOn();
syncIt();
skipClk();
skipClk();
bufferNCS = buffen;
autoCalibrationNCS = true;
clockOutRateNCS = CLKOUT_1;
programmableGainNCS = gain;
dataRateNCS = drate;
var st = statusNCS.toRadixString(16);
var ac = controlRegisterNCS.toRadixString(16);
var dt = dataRateNCS.toRadixString(16);
csOff();
log.info(" status : $st");
log.info(" adcon : $ac");
log.info(" drate : $dt");
skipClk();
calibrateOffsetGain();
}
void syncIt(){
spi.transfer([CMD_SYNC], false);
skipClk();
skipClk();
skipClk();
spi.transfer([CMD_WAKEUP], false);
skipClk();
}
int get statusNCS => readRegister(RADD_STATUS);
set bufferNCS(bool isEnable){
isEnable ? writeRegister(RADD_STATUS, (statusNCS | (0x01 << 1))):
writeRegister(RADD_STATUS, (statusNCS & ~(0x01 << 1)));
}
set autoCalibrationNCS(bool isEnable){
isEnable ? writeRegister(RADD_STATUS, (statusNCS | (0x01 << 2))):
writeRegister(RADD_STATUS, (statusNCS & ~(0x01 << 2)));
}
int get controlRegisterNCS => readRegister(RADD_ADCON);
set clockOutRateNCS(int clk) => writeRegister(RADD_ADCON, controlRegisterNCS | (clk << 5 ));
set programmableGainNCS(int gain) => writeRegister(RADD_ADCON, controlRegisterNCS | gain);
int get dataRateNCS => readRegister(RADD_DRATE);
set dataRateNCS(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) <<4;
writeRegister(RADD_IO, d);
csOff();
}
List<bool> get dIO {
csOn();
int dio = readRegister(RADD_IO);
csOff();
return dio.toListBoolbit();
}
set dIO(List<bool> io){
csOn();
writeRegister(RADD_IO, io.toNibble() );
csOff();
}
set channelNCS(int c) => writeRegister(RADD_MUX, c);
int analogRead(int pChannel, int nChannel){
var nc = pChannel | nChannel;
log.info(" analogRead() <${pChannel.toRadixString(16)}> <${nChannel.toRadixString(16)}> = <${nc.toRadixString(16)}>");
csOn();
channelNCS = nc;
waitDRDY();
spi.transfer([CMD_RDATA], false);
skipClk();
var 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;
}