diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 13a46a96..2de70932 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -2434,7 +2434,7 @@ bool EmotiBit::processThermopileData() size_t EmotiBit::getData(DataType type, float** data, uint32_t * timestamp) { #ifdef DEBUG Serial.print("getData: type="); - Serial.println((uint8_t) t); + Serial.println((uint8_t) type); #endif // DEBUG if ((uint8_t)type < (uint8_t)EmotiBit::DataType::length) { return dataDoubleBuffers[(uint8_t)type]->getData(data, timestamp, false); @@ -3363,6 +3363,50 @@ void EmotiBit::processHeartRate() //addPacket(timestamp, FIR_FILT_DATA, iirFiltData, dataSize, true); } +void EmotiBit::processSpO2() +{ + static uint8_t irDataIndex = 0; + static uint8_t redDataIndex = 0; + static float irDataBuffer[SPO2_PPG_BUFFER_SIZE]; + static float redDataBuffer[SPO2_PPG_BUFFER_SIZE]; + + float* ir_data; + float* red_data; + uint16_t irDataSize; + uint16_t redDataSize; + uint32_t timestamp; + const static size_t APERIODIC_DATA_LEN = 1; //used in packet header + const static float timePeriod = (1.f / _samplingRates.ppg) * 1000; // in mS + float spo2; + + irDataSize = dataDoubleBuffers[(uint8_t)DataType::PPG_INFRARED]->getData(&ir_data, ×tamp, false); + redDataSize = dataDoubleBuffers[(uint8_t)DataType::PPG_RED]->getData(&red_data, ×tamp, false); + + if (irDataIndex + irDataSize < SPO2_PPG_BUFFER_SIZE) { + for (int i = 0 ; i < irDataSize ; i++) { + irDataBuffer[irDataIndex + i] = ir_data[i]; + } + } + irDataIndex += irDataSize; + + if (redDataIndex + redDataSize < SPO2_PPG_BUFFER_SIZE) { + for (int i = 0 ; i < redDataSize ; i++) { + redDataBuffer[redDataIndex + i] = red_data[i]; + } + } + redDataIndex += redDataSize; + + if (irDataIndex >= SPO2_PPG_BUFFER_SIZE-15 && redDataIndex >= SPO2_PPG_BUFFER_SIZE-15) { + get_oxygen_level(irDataBuffer, redDataBuffer, min(irDataIndex, redDataIndex), &spo2); + + irDataIndex = 0; + redDataIndex = 0; + + // Add packets to output + addPacket(timestamp, EmotiBitPacket::TypeTag::SPO2, &spo2, APERIODIC_DATA_LEN); + } +} + void EmotiBit::processData() { // Perform all derivative calculations @@ -3412,6 +3456,10 @@ void EmotiBit::processData() { processHeartRate(); } + if (acquireData.spo2) + { + processSpO2(); + } if (acquireData.edrMetrics) { // Note: this may move to emotiBitEda.processData() in the future diff --git a/EmotiBit.h b/EmotiBit.h index 08c6f430..ca1a7544 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -35,6 +35,7 @@ #include "EmotiBitVariants.h" #include "EmotiBitNvmController.h" #include "heartRate.h" +#include "Emotibit_Brainflow_SpO2_Algorithm.h" #ifdef ARDUINO_FEATHER_ESP32 #include "FileTransferManager.h" #endif @@ -55,7 +56,7 @@ class EmotiBit { - String firmware_version = "1.14.0"; + String firmware_version = "1.14.0-feat-spo2.0"; @@ -331,6 +332,7 @@ class EmotiBit { #define IMU_SAMPLING_DIV 2 #define BATTERY_SAMPLING_DIV 50 #define DUMMY_ISR_DIV 10 +#define SPO2_PPG_BUFFER_SIZE 64 struct TimerLoopOffset { @@ -376,7 +378,8 @@ class EmotiBit { bool debug = false; bool battery = true; bool heartRate = true; // Note: we may want to move this to a separarte flag someday, for controlling derivative signals - bool edrMetrics = true; + bool spo2 = true; + bool edrMetrics = true; } acquireData; struct ChipBegun { @@ -453,6 +456,7 @@ class EmotiBit { void parseIncomingControlPackets(String &controlPackets, uint16_t &packetNumber); void readSensors(); void processHeartRate(); + void processSpO2(); void processData(); void sendData(); bool processThermopileData(); // placeholder until separate EmotiBitThermopile controller is implemented diff --git a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino index c9fbebe0..62b8dde2 100644 --- a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino +++ b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino @@ -1,8 +1,8 @@ -#include #include "EmotiBit.h" +#include #define SerialUSB SERIAL_PORT_USBVIRTUAL // Required to work in Visual Micro / Visual Studio IDE -const uint32_t SERIAL_BAUD = 2000000; //115200 +const uint32_t SERIAL_BAUD = 2000000; EmotiBit emotibit; const size_t dataSize = EmotiBit::MAX_DATA_BUFFER_SIZE; @@ -11,7 +11,7 @@ float data[dataSize]; void onShortButtonPress() { // toggle wifi on/off - if (emotibit.getPowerMode() == EmotiBit::PowerMode::NORMAL_POWER) + if (emotibit.getPowerMode() == EmotiBit::PowerMode::NORMAL_POWER) { emotibit.setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); Serial.println("PowerMode::WIRELESS_OFF"); diff --git a/EmotiBit_stock_firmware/partitions.csv b/EmotiBit_stock_firmware/partitions.csv new file mode 100644 index 00000000..94ed617d --- /dev/null +++ b/EmotiBit_stock_firmware/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, factory, 0x10000, 0x3E0000, +coredump, data, coredump, 0x3F0000, 0x10000, \ No newline at end of file diff --git a/EmotiBit_stock_firmware/platformio.ini b/EmotiBit_stock_firmware/platformio.ini index d8e9cbd7..3da5de4b 100644 --- a/EmotiBit_stock_firmware/platformio.ini +++ b/EmotiBit_stock_firmware/platformio.ini @@ -14,9 +14,9 @@ extra_configs = src_dir = ./ lib_dir = ../../ - [custom] variant_flags = -DSTOCK_FIRMWARE [env] -lib_ldf_mode = deep+ \ No newline at end of file +lib_ldf_mode = deep+ +board_build.partitions = partitions.csv diff --git a/library.properties b/library.properties index f3f76958..f4d536e5 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph= Requires dependent libraries as shown in the getting started document category=Sensors url=https://github.com/EmotiBit/EmotiBit_FeatherWing architectures=* -depends=EmotiBit BMI160, EmotiBit MAX30101, EmotiBit MLX90632, EmotiBit NCP5623, EmotiBit SI7013, EmotiBit XPlat Utils, EmotiBit ADS1X15, EmotiBit External EEPROM, EmotiBit EmojiLib, EmotiBit ArduinoFilters, EmotiBit SimpleFTPServer, EmotiBit KTD2026 +depends=EmotiBit BMI160, EmotiBit MAX30101, EmotiBit MLX90632, EmotiBit NCP5623, EmotiBit SI7013, EmotiBit XPlat Utils, EmotiBit ADS1X15, EmotiBit External EEPROM, EmotiBit EmojiLib, EmotiBit ArduinoFilters, EmotiBit SimpleFTPServer, EmotiBit KTD2026, EmotiBit Brainflow SpO2 Algorithm diff --git a/pio_scripts/removeBindingCPP.py b/pio_scripts/removeBindingCPP.py new file mode 100644 index 00000000..786b4527 --- /dev/null +++ b/pio_scripts/removeBindingCPP.py @@ -0,0 +1,6 @@ +Import("env") + +def skip_bindings_cpp(env, node): + return None + +env.AddBuildMiddleware(skip_bindings_cpp, "**/bindings.cpp") \ No newline at end of file