diff --git a/Software/ALL-H3-CC-V1.0A Headers.ods b/Software/ALL-H3-CC-V1.0A Headers.ods new file mode 100644 index 0000000..369c907 Binary files /dev/null and b/Software/ALL-H3-CC-V1.0A Headers.ods differ diff --git a/Software/dashboard/Makefile b/Software/dashboard/Makefile index 5f7bd05..366a386 100644 --- a/Software/dashboard/Makefile +++ b/Software/dashboard/Makefile @@ -1,20 +1,27 @@ TARGET_USER := a2nr -TARGET_HOST := 10.4.106.103 +TARGET_HOST := tritium-h5 TARGET_PATH := /home/$(TARGET_USER)/Documents/dashboard TARGET_PASS := 'a2nr' +PROBE_USER := a2nr +PROBE_HOST := mekatronika +PROBE_PATH := /home/$(PROBE_USER)/ +PROBE_PASS := 'Bismillah...' all: comp up run debug: comp_debug up run_debug init: install_dep install_flutter_pi +up: comp copy_target +clean: + rm -rf ./build/* && sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S rm -rf $(TARGET_PATH)/*' comp_debug: flutterpi_tool build --arch=arm64 comp: flutterpi_tool build --arch=arm64 --release -up: +copy_target: sshpass -p $(TARGET_PASS) rsync -a --info=progress2 ./build/flutter_assets $(TARGET_USER)@$(TARGET_HOST):$(TARGET_PATH) run: - sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -o landscape_left --release $(TARGET_PATH)/flutter_assets' + sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -r 90 --release $(TARGET_PATH)/flutter_assets' run_debug: sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -o landscape_left $(TARGET_PATH)/flutter_assets' install_dep: @@ -22,3 +29,8 @@ install_dep: libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad gstreamer1.0-libav gstreamer1.0-alsa' install_flutter_pi: sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'cd ~/Documents && git clone --recursive https://github.com/ardera/flutter-pi || cd flutter-pi && mkdir build || cd build && cmake .. && make -j`nproc` && echo $(TARGET_PASS) | sudo -S make install' +# -C D0=CS1,D6=CS2,D1=MISO,D2=MOSI,D3=CLK,D4=DRDY1,D5=DRDY2 +probe: + sshpass -p $(PROBE_PASS) ssh -t $(PROBE_USER)@$(PROBE_HOST) 'echo $(PROBE_PASS) | sudo -S sigrok-cli -d fx2lafw:conn=2.4 -o $(PROBE_PATH)/test.sr -w -t D0=f -M spi --config samplerate=100k --samples 500k --time 1s' \ + && sshpass -p $(PROBE_PASS) rsync -a --info=progress2 $(PROBE_USER)@$(PROBE_HOST):$(PROBE_PATH)/test.sr ./build/ + diff --git a/Software/dashboard/lib/hal/X9C10X.dart b/Software/dashboard/lib/hal/X9C10X.dart new file mode 100644 index 0000000..69ddf88 --- /dev/null +++ b/Software/dashboard/lib/hal/X9C10X.dart @@ -0,0 +1,54 @@ +import 'package:dart_periphery/dart_periphery.dart'; +import 'package:logging/logging.dart'; + +class X9c10x { + int ohm; + late GPIO inc; + late GPIO ud; + late GPIO? ss; + final log = Logger("X9C10X"); + late Function() onSelect; + late Function() onRelease; + + X9c10x({ + required this.ohm, + required int gpioChip, + required int pinInc, + required int pinUd, + int? pinSs}){ + inc = GPIO(pinInc, GPIOdirection.gpioDirOutHigh, gpioChip); + ud = GPIO(pinUd, GPIOdirection.gpioDirOutHigh, gpioChip); + ss = pinSs != null ? GPIO(pinSs, GPIOdirection.gpioDirOutHigh, gpioChip) : null; + onSelect = selectChip; + onRelease = releaseChip; + } + + void setCallBack(Function() onSelect, Function() onRelease){ + this.onSelect = onSelect; + this.onRelease = onRelease; + } + + void selectChip()=>ss?.write(false); + void releaseChip()=>ss?.write(true); + + void wipeUp(){ + onSelect.call(); + ud.write(true); + const Duration(microseconds: 3); + inc.write(false); + const Duration(microseconds: 1); + inc.write(true); + onRelease.call(); + } + + void wipeDown(){ + onSelect.call(); + ud.write(false); + const Duration(microseconds: 3); + inc.write(false); + const Duration(microseconds: 1); + inc.write(true); + onRelease.call(); + } + +} diff --git a/Software/dashboard/lib/hal/adc1256.dart b/Software/dashboard/lib/hal/adc1256.dart deleted file mode 100644 index 71f21cd..0000000 --- a/Software/dashboard/lib/hal/adc1256.dart +++ /dev/null @@ -1,167 +0,0 @@ -import 'package:dart_periphery/dart_periphery.dart'; - -class Ads1256 { - 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; - - final SPI _spi; //SPI - final GPIO _drdy; //GPIO - final GPIO? _cs; //GPIO - - Ads1256(this._spi, this._drdy, this._cs) {} - - void _sendCommand(int reg) { - _CSON(); - _waitDRDY(); - _spi.transfer([reg], false); - _CSON(); - } - - void _writeRegister(int reg, int wdata) { - _CSON(); - _spi.transfer([CMD_WREG, reg, 0, wdata], false); - _CSOFF(); - } - - int _readRegister(int reg) { - var val = _spi.transfer([CMD_RREG, 0, 0], true); - return val[2]; - } - - void _waitDRDY() { - while (_drdy.read()){} - } - - void _CSON() { - //PORT_CS &= ~(1 << PINDEX_CS); - _cs?.write(false); - } - - void _CSOFF() { - //PORT_CS |= (1 << PINDEX_CS); - _cs?.write(true); - } - - void begin(int drate, int gain, bool buffen) { - _sendCommand( - CMD_SDATAC); // send out ADS1256_CMD_SDATAC command to stop continous reading mode. - _writeRegister(RADD_DRATE, drate); // write data rate register - int bytemask = 7; - int adcon = _readRegister(RADD_ADCON); - int byte2send = (adcon & ~bytemask) | gain; - _writeRegister(RADD_ADCON, byte2send); - if (buffen) { - setBufferEnable(_readRegister(RADD_STATUS)); - } - _sendCommand(CMD_SELFCAL); // perform self calibration - _waitDRDY(); - } - - /* STATUS : STATUS REGISTER (ADDRESS 00h) - Reset Value = x1h - Bit 3 ORDER: Data Output Bit Order - 0 = Most Significant Bit First (default) - 1 = Least Significant Bit First - Bit 2 ACAL: Auto-Calibration - 0 = Auto-Calibration Disabled (default) - 1 = Auto-Calibration Enabled - Bit 1 BUFEN: Analog Input Buffer Enable - 0 = Buffer Disabled (default) - 1 = Buffer Enabled - Bit 0 DRDY: Data Ready (Read Only) - */ - int getStatus() { - _sendCommand(CMD_SDATAC); - return _readRegister(RADD_STATUS); - } - - void setBufferEnable(int status) { - _writeRegister(RADD_STATUS, (status | (0x01 << 1))); - } - - void resetBufferEnable(int status) { - _writeRegister(RADD_STATUS, (status & ~(0x01 << 1))); - } - - void readTest() { - _CSON(); - var _hml = - _spi.transfer([CMD_RDATA, CMD_WAKEUP, CMD_WAKEUP, CMD_WAKEUP], false); - print(_hml); - _CSOFF(); - } - void dispose(){ - _spi.dispose(); //SPI - _drdy.dispose(); //GPIO - _cs?.dispose(); //GPIO - } -} diff --git a/Software/dashboard/lib/hal/ads1256.dart b/Software/dashboard/lib/hal/ads1256.dart new file mode 100644 index 0000000..d92a0cf --- /dev/null +++ b/Software/dashboard/lib/hal/ads1256.dart @@ -0,0 +1,278 @@ +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; + +} diff --git a/Software/dashboard/lib/hardware/heartbeatmice.dart b/Software/dashboard/lib/hardware/heartbeatmice.dart index cff6cc7..45e6348 100644 --- a/Software/dashboard/lib/hardware/heartbeatmice.dart +++ b/Software/dashboard/lib/hardware/heartbeatmice.dart @@ -1,13 +1,30 @@ -import '../hal/adc1256.dart'; -import 'package:dart_periphery/dart_periphery.dart'; +import 'package:dashboard/hal/X9C10X.dart'; + +import '../hal/ads1256.dart'; class HeartBeatMice { - Ads1256 adc = Ads1256( - SPI(1, 0, SPImode.mode1, 50000), - GPIO(2, GPIOdirection.gpioDirIn, 1), - null - ); + Ads1256 adc1 = Ads1256(tag: "adc1", spiBus: 1, spiChip: 0, gpioChip: 1, pinDrdy: 202, pinCS: 13, pinReset: 20); + Ads1256 adc2 = Ads1256(tag: "adc2", spiBus: 1, spiChip: 0, gpioChip: 1, pinDrdy: 6, pinCS: 21); + X9c10x pot = X9c10x(ohm: 104000, gpioChip: 1, pinUd: 204, pinInc: 205); + + void potSelect(){ + + } + void potRelease(){ + + } + void init(){ + adc1.begin(Ads1256.DRATE_500SPS, Ads1256.GAIN_1, false); + adc2.begin(Ads1256.DRATE_500SPS, Ads1256.GAIN_1, false); + adc1.ioDir = [Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT]; + adc2.ioDir = [Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT]; + print('adc = ${adc1.analogRead(0).toVolt()}'); + } + void test(){ + print('adc = ${adc1.analogRead(0).toVolt()}'); + } void dispose(){ - adc.dispose(); + adc1.dispose(); + adc2.dispose(); } } diff --git a/Software/dashboard/lib/main.dart b/Software/dashboard/lib/main.dart index cc44ec4..843b12b 100644 --- a/Software/dashboard/lib/main.dart +++ b/Software/dashboard/lib/main.dart @@ -1,8 +1,15 @@ import 'package:dashboard/hardware/heartbeatmice.dart'; import 'package:flutter/material.dart'; import 'util/mouse_cursor.dart'; +import 'package:logging/logging.dart'; +import 'ui/plot.dart'; void main() { + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((record){ + + print('[${record.level.name}:${record.loggerName}][${record.time.hour}:${record.time.minute}:${record.time.second}] ${record.message}'); + }); runApp(const MyApp()); } @@ -12,16 +19,16 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { - return SoftwareMouseCursor( - child : MaterialApp( + //return SoftwareMouseCursor( + /*child :*/ return MaterialApp( title: 'Heart Beat Mice', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), - home: const MyHomePage(title: 'Heart Beat Mice'), - ) - ); + home: const MyHomePage(title: 'Heart Beat Mice Coba'), + ); + //); } } @@ -41,6 +48,7 @@ class _MyHomePageState extends State { @override void initState(){ super.initState(); + drive.init(); } @override @@ -53,6 +61,7 @@ class _MyHomePageState extends State { setState(() { _counter++; }); + drive.test(); } @override @@ -63,9 +72,8 @@ class _MyHomePageState extends State { title: Text(widget.title), ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ + child: Column ( + children: [ const Text( 'You have pushed the button this many times:', ), @@ -73,8 +81,9 @@ class _MyHomePageState extends State { '$_counter', style: Theme.of(context).textTheme.headlineMedium, ), + Container ( width: 350, child : const LineChartSample10()) ], - ), + ) ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, diff --git a/Software/dashboard/lib/ui/plot.dart b/Software/dashboard/lib/ui/plot.dart new file mode 100644 index 0000000..0f0c0a4 --- /dev/null +++ b/Software/dashboard/lib/ui/plot.dart @@ -0,0 +1,171 @@ +import 'dart:async'; +import 'dart:math' as math; + +import 'package:fl_chart/fl_chart.dart'; +//import 'package:fl_chart_app/presentation/resources/app_resources.dart'; +import 'package:flutter/material.dart'; + +class AppColors { + static const Color primary = contentColorCyan; + static const Color menuBackground = Color(0xFF090912); + static const Color itemsBackground = Color(0xFF1B2339); + static const Color pageBackground = Color(0xFF282E45); + static const Color mainTextColor1 = Colors.white; + static const Color mainTextColor2 = Colors.white70; + static const Color mainTextColor3 = Colors.white38; + static const Color mainGridLineColor = Colors.white10; + static const Color borderColor = Colors.white54; + static const Color gridLinesColor = Color(0x11FFFFFF); + + static const Color contentColorBlack = Colors.black; + static const Color contentColorWhite = Colors.white; + static const Color contentColorBlue = Color(0xFF2196F3); + static const Color contentColorYellow = Color(0xFFFFC300); + static const Color contentColorOrange = Color(0xFFFF683B); + static const Color contentColorGreen = Color(0xFF3BFF49); + static const Color contentColorPurple = Color(0xFF6E1BFF); + static const Color contentColorPink = Color(0xFFFF3AF2); + static const Color contentColorRed = Color(0xFFE80054); + static const Color contentColorCyan = Color(0xFF50E4FF); +} + +class LineChartSample10 extends StatefulWidget { + const LineChartSample10({super.key}); + + final Color sinColor = AppColors.contentColorBlue; + final Color cosColor = AppColors.contentColorPink; + + @override + State createState() => _LineChartSample10State(); +} + +class _LineChartSample10State extends State { + final limitCount = 100; + final sinPoints = []; + final cosPoints = []; + + double xValue = 0; + double step = 0.05; + + late Timer timer; + + @override + void initState() { + super.initState(); + timer = Timer.periodic(const Duration(milliseconds: 40), (timer) { + while (sinPoints.length > limitCount) { + sinPoints.removeAt(0); + cosPoints.removeAt(0); + } + setState(() { + sinPoints.add(FlSpot(xValue, math.sin(xValue))); + cosPoints.add(FlSpot(xValue, math.cos(xValue))); + }); + xValue += step; + }); + } + + @override + Widget build(BuildContext context) { + return cosPoints.isNotEmpty + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 12), + Text( + 'x: ${xValue.toStringAsFixed(1)}', + style: const TextStyle( + color: AppColors.mainTextColor2, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'sin: ${sinPoints.last.y.toStringAsFixed(1)}', + style: TextStyle( + color: widget.sinColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'cos: ${cosPoints.last.y.toStringAsFixed(1)}', + style: TextStyle( + color: widget.cosColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 12, + ), + AspectRatio( + aspectRatio: 1.5, + child: Padding( + padding: const EdgeInsets.only(bottom: 24.0), + child: LineChart( + LineChartData( + minY: -1, + maxY: 1, + minX: sinPoints.first.x, + maxX: sinPoints.last.x, + lineTouchData: const LineTouchData(enabled: false), + clipData: const FlClipData.all(), + gridData: const FlGridData( + show: true, + drawVerticalLine: false, + ), + borderData: FlBorderData(show: false), + lineBarsData: [ + sinLine(sinPoints), + cosLine(cosPoints), + ], + titlesData: const FlTitlesData( + show: false, + ), + ), + ), + ), + ) + ], + ) + : Container(); + } + + LineChartBarData sinLine(List points) { + return LineChartBarData( + spots: points, + dotData: const FlDotData( + show: false, + ), + gradient: LinearGradient( + colors: [widget.sinColor.withOpacity(0), widget.sinColor], + stops: const [0.1, 1.0], + ), + barWidth: 4, + isCurved: false, + ); + } + + LineChartBarData cosLine(List points) { + return LineChartBarData( + spots: points, + dotData: const FlDotData( + show: false, + ), + gradient: LinearGradient( + colors: [widget.cosColor.withOpacity(0), widget.cosColor], + stops: const [0.1, 1.0], + ), + barWidth: 4, + isCurved: false, + ); + } + + @override + void dispose() { + timer.cancel(); + super.dispose(); + } +} + diff --git a/Software/dashboard/pubspec.lock b/Software/dashboard/pubspec.lock index 75d7ab4..799b261 100644 --- a/Software/dashboard/pubspec.lock +++ b/Software/dashboard/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.6" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -81,6 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef" + url: "https://pub.dev" + source: hosted + version: "0.69.0" flutter: dependency: "direct main" description: flutter @@ -131,6 +147,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + logging: + dependency: "direct main" + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" matcher: dependency: transitive description: diff --git a/Software/dashboard/pubspec.yaml b/Software/dashboard/pubspec.yaml index 2217de6..829e2f7 100644 --- a/Software/dashboard/pubspec.yaml +++ b/Software/dashboard/pubspec.yaml @@ -31,6 +31,8 @@ dependencies: flutter: sdk: flutter dart_periphery: ^0.9.6 + logging: ^1.2.0 + fl_chart: ^0.69.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.