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 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 dir){ csOn(); int d = dir[0] | dir[1]<<1 | dir[2]<<2 | dir[3]<<3; writeRegister(RADD_IO, d <<4); csOff(); } List 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 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 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; }