zinnet yazıcı
/
Our_Code_copy
dszds
Revision 0:83277b73a1f8, committed 2019-07-28
- Comitter:
- zinnetyazicii53
- Date:
- Sun Jul 28 08:14:38 2019 +0000
- Commit message:
- commit
Changed in this revision
diff -r 000000000000 -r 83277b73a1f8 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,6 @@ +mbed-os +.build +/mdot/ +/mdot-library/ +/BUILD/ +/.git/
diff -r 000000000000 -r 83277b73a1f8 MAX30102/MAX30102.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX30102/MAX30102.cpp Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,759 @@ +/*************************************************** + This is a library written for the Maxim MAX30102 Optical Smoke Detector + It should also work with the MAX30102. However, the MAX30102 does not have a Green LED. + + These sensors use I2C to communicate, as well as a single (optional) + interrupt line that is not currently supported in this driver. + + Written by Peter Jansen and Nathan Seidle (SparkFun) + BSD license, all text above must be included in any redistribution. + *****************************************************/ +/* +#include "MAX30102.h" + +#ifdef TARGET_MAX32600MBED +I2C i2c(I2C1_SDA, I2C1_SCL); +#else +I2C i2c(I2C_SDA, I2C_SCL); +#endif + +// Status Registers +#define MAX30102_INTSTAT1 0x00; +#define MAX30102_INTSTAT2 0x01; +#define MAX30102_INTENABLE1 0x02; +#define MAX30102_INTENABLE2 0x03; + +// FIFO Registers +#define MAX30102_FIFOWRITEPTR 0x04; +#define MAX30102_FIFOOVERFLOW 0x05; +#define MAX30102_FIFOREADPTR 0x06; +#define MAX30102_FIFODATA 0x07; + +// Configuration Registers +#define MAX30102_FIFOCONFIG 0x08; +#define MAX30102_MODECONFIG 0x09; +#define MAX30102_PARTICLECONFIG 0x0A; // Note, sometimes listed as "SPO2" config in datasheet (pg. 11) +#define MAX30102_LED1_PULSEAMP 0x0C; +#define MAX30102_LED2_PULSEAMP 0x0D; +#define MAX30102_LED3_PULSEAMP 0x0E; +#define MAX30102_LED_PROX_AMP 0x10; +#define MAX30102_MULTILEDCONFIG1 0x11; +#define MAX30102_MULTILEDCONFIG2 0x12; + +// Die Temperature Registers +#define MAX30102_DIETEMPINT 0x1F; +#define MAX30102_DIETEMPFRAC 0x20; +#define MAX30102_DIETEMPCONFIG 0x21; + +// Proximity Function Registers +#define MAX30102_PROXINTTHRESH 0x30; + +// Part ID Registers +#define MAX30102_REVISIONID 0xFE; +#define MAX30102_PARTID 0xFF; // Should always be 0x15. Identical to MAX30102. + +// MAX30102 Commands +// Interrupt configuration (pg 13, 14) +#define MAX30102_INT_A_FULL_MASK (byte)~0b10000000; +#define MAX30102_INT_A_FULL_ENABLE 0x80; +#define MAX30102_INT_A_FULL_DISABLE 0x00; + +#define MAX30102_INT_DATA_RDY_MASK (byte)~0b01000000; +#define MAX30102_INT_DATA_RDY_ENABLE 0x40; +#define MAX30102_INT_DATA_RDY_DISABLE 0x00; + +#define MAX30102_INT_ALC_OVF_MASK (byte)~0b00100000; +#define MAX30102_INT_ALC_OVF_ENABLE 0x20; +#define MAX30102_INT_ALC_OVF_DISABLE 0x00; + +#define MAX30102_INT_PROX_INT_MASK (byte)~0b00010000; +#define MAX30102_INT_PROX_INT_ENABLE 0x10; +#define MAX30102_INT_PROX_INT_DISABLE 0x00; + +#define MAX30102_INT_DIE_TEMP_RDY_MASK (byte)~0b00000010; +#define MAX30102_INT_DIE_TEMP_RDY_ENABLE 0x02; +#define MAX30102_INT_DIE_TEMP_RDY_DISABLE 0x00; + +#define MAX30102_SAMPLEAVG_MASK (byte)~0b11100000; +#define MAX30102_SAMPLEAVG_1 0x00; +#define MAX30102_SAMPLEAVG_2 0x20; +#define MAX30102_SAMPLEAVG_4 0x40; +#define MAX30102_SAMPLEAVG_8 0x60; +#define MAX30102_SAMPLEAVG_16 0x80; +#define MAX30102_SAMPLEAVG_32 0xA0; + +#define MAX30102_ROLLOVER_MASK 0xEF; +#define MAX30102_ROLLOVER_ENABLE 0x10; +#define MAX30102_ROLLOVER_DISABLE 0x00; + +#define MAX30102_A_FULL_MASK 0xF0; + +// Mode configuration commands (page 19) +#define MAX30102_SHUTDOWN_MASK 0x7F; +#define MAX30102_SHUTDOWN 0x80; +#define MAX30102_WAKEUP 0x00; + +#define MAX30102_RESET_MASK 0xBF; +#define MAX30102_RESET 0x40; + +#define MAX30102_MODE_MASK 0xF8; +#define MAX30102_MODE_REDONLY 0x02; +#define MAX30102_MODE_REDIRONLY 0x03; +#define MAX30102_MODE_MULTILED 0x07; + +// Particle sensing configuration commands (pgs 19-20) +#define MAX30102_ADCRANGE_MASK 0x9F; +#define MAX30102_ADCRANGE_2048 0x00; +#define MAX30102_ADCRANGE_4096 0x20; +#define MAX30102_ADCRANGE_8192 0x40; +#define MAX30102_ADCRANGE_16384 0x60; + +#define MAX30102_SAMPLERATE_MASK 0xE3; +#define MAX30102_SAMPLERATE_50 0x00; +#define MAX30102_SAMPLERATE_100 0x04; +#define MAX30102_SAMPLERATE_200 0x08; +#define MAX30102_SAMPLERATE_400 0x0C; +#define MAX30102_SAMPLERATE_800 0x10; +#define MAX30102_SAMPLERATE_1000 0x14; +#define MAX30102_SAMPLERATE_1600 0x18; +#define MAX30102_SAMPLERATE_3200 0x1C; + +#define MAX30102_PULSEWIDTH_MASK 0xFC; +#define MAX30102_PULSEWIDTH_69 0x00; +#define MAX30102_PULSEWIDTH_118 0x01; +#define MAX30102_PULSEWIDTH_215 0x02; +#define MAX30102_PULSEWIDTH_411 0x03; + +//Multi-LED Mode configuration (pg 22) +#define MAX30102_SLOT1_MASK 0xF8; +#define MAX30102_SLOT2_MASK 0x8F; +#define MAX30102_SLOT3_MASK 0xF8; +#define MAX30102_SLOT4_MASK 0x8F; + +#define SLOT_NONE 0x00; +#define SLOT_RED_LED 0x01; +#define SLOT_IR_LED 0x02; +#define SLOT_GREEN_LED 0x03; +#define SLOT_NONE_PILOT 0x04; +#define SLOT_RED_PILOT 0x05; +#define SLOT_IR_PILOT 0x06; +#define SLOT_GREEN_PILOT 0x07; + + +#define MAX_30105_EXPECTEDPARTID 0x15; + +bool begin(TwoWire &wirePort, uint32_t i2cSpeed, uint8_t i2caddr) {//?? + + _i2cPort = &wirePort; //Grab which port the user wants us to use + + _i2cPort->begin(); + _i2cPort->setClock(i2cSpeed); + + _i2caddr = i2caddr; + + // Step 1: Initial Communication and Verification + // Check that a MAX30102 is connected + if (readPartID() != MAX_30105_EXPECTEDPARTID) { + // Error -- Part ID read from MAX30102 does not match expected part ID. + // This may mean there is a physical connectivity problem (broken wire, unpowered, etc). + return false; + } + + // Populate revision ID + readRevisionID(); + + return true; +} + +// +// Configuration +// + +//Begin Interrupt configuration +uint8_t MAX30102::getINT1(void) { + return (readRegister8(_i2caddr, MAX30102_INTSTAT1)); +} +uint8_t getINT2(void) { + return (readRegister8(_i2caddr, MAX30102_INTSTAT2)); +} + +void enableAFULL(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_A_FULL_MASK, MAX30102_INT_A_FULL_ENABLE); +} +void disableAFULL(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_A_FULL_MASK, MAX30102_INT_A_FULL_DISABLE); +} + +void enableDATARDY(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_DATA_RDY_MASK, MAX30102_INT_DATA_RDY_ENABLE); +} +void disableDATARDY(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_DATA_RDY_MASK, MAX30102_INT_DATA_RDY_DISABLE); +} + +void enableALCOVF(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_ALC_OVF_MASK, MAX30102_INT_ALC_OVF_ENABLE); +} +void disableALCOVF(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_ALC_OVF_MASK, MAX30102_INT_ALC_OVF_DISABLE); +} + +void enablePROXINT(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_PROX_INT_MASK, MAX30102_INT_PROX_INT_ENABLE); +} +void disablePROXINT(void) { + bitMask(MAX30102_INTENABLE1, MAX30102_INT_PROX_INT_MASK, MAX30102_INT_PROX_INT_DISABLE); +} + +void enableDIETEMPRDY(void) { + bitMask(MAX30102_INTENABLE2, MAX30102_INT_DIE_TEMP_RDY_MASK, MAX30102_INT_DIE_TEMP_RDY_ENABLE); +} +void disableDIETEMPRDY(void) { + bitMask(MAX30102_INTENABLE2, MAX30102_INT_DIE_TEMP_RDY_MASK, MAX30102_INT_DIE_TEMP_RDY_DISABLE); +} + +//End Interrupt configuration + +void softReset(void) { + bitMask(MAX30102_MODECONFIG, MAX30102_RESET_MASK, MAX30102_RESET); + + // Poll for bit to clear, reset is then complete + // Timeout after 100ms + unsigned long startTime = millis(); + while (millis() - startTime < 100) + { + uint8_t response = readRegister8(_i2caddr, MAX30102_MODECONFIG); + if ((response & MAX30102_RESET) == 0) break; //We're done! + delay(1); //Let's not over burden the I2C bus + } +} + +void shutDown(void) { + // Put IC into low power mode (datasheet pg. 19) + // During shutdown the IC will continue to respond to I2C commands but will + // not update with or take new readings (such as temperature) + bitMask(MAX30102_MODECONFIG, MAX30102_SHUTDOWN_MASK, MAX30102_SHUTDOWN); +} + +void wakeUp(void) { + // Pull IC out of low power mode (datasheet pg. 19) + bitMask(MAX30102_MODECONFIG, MAX30102_SHUTDOWN_MASK, MAX30102_WAKEUP); +} + +void setLEDMode(uint8_t mode) { + // Set which LEDs are used for sampling -- Red only, RED+IR only, or custom. + // See datasheet, page 19 + bitMask(MAX30102_MODECONFIG, MAX30102_MODE_MASK, mode); +} + +void setADCRange(uint8_t adcRange) { + // adcRange: one of MAX30102_ADCRANGE_2048, _4096, _8192, _16384 + bitMask(MAX30102_PARTICLECONFIG, MAX30102_ADCRANGE_MASK, adcRange); +} + +void setSampleRate(uint8_t sampleRate) { + // sampleRate: one of MAX30102_SAMPLERATE_50, _100, _200, _400, _800, _1000, _1600, _3200 + bitMask(MAX30102_PARTICLECONFIG, MAX30102_SAMPLERATE_MASK, sampleRate); +} + +void setPulseWidth(uint8_t pulseWidth) { + // pulseWidth: one of MAX30102_PULSEWIDTH_69, _188, _215, _411 + bitMask(MAX30102_PARTICLECONFIG, MAX30102_PULSEWIDTH_MASK, pulseWidth); +} + +// NOTE: Amplitude values: 0x00 = 0mA, 0x7F = 25.4mA, 0xFF = 50mA (typical) +// See datasheet, page 21 +void setPulseAmplitudeRed(uint8_t amplitude) { + writeRegister8(_i2caddr, MAX30102_LED1_PULSEAMP, amplitude); +} + +void setPulseAmplitudeIR(uint8_t amplitude) { + writeRegister8(_i2caddr, MAX30102_LED2_PULSEAMP, amplitude); +} + +void setPulseAmplitudeGreen(uint8_t amplitude) { + writeRegister8(_i2caddr, MAX30102_LED3_PULSEAMP, amplitude); +} + +void setPulseAmplitudeProximity(uint8_t amplitude) { + writeRegister8(_i2caddr, MAX30102_LED_PROX_AMP, amplitude); +} + +void setProximityThreshold(uint8_t threshMSB) { + // Set the IR ADC count that will trigger the beginning of particle-sensing mode. + // The threshMSB signifies only the 8 most significant-bits of the ADC count. + // See datasheet, page 24. + writeRegister8(_i2caddr, MAX30102_PROXINTTHRESH, threshMSB); +} + +//Given a slot number assign a thing to it +//Devices are SLOT_RED_LED or SLOT_RED_PILOT (proximity) +//Assigning a SLOT_RED_LED will pulse LED +//Assigning a SLOT_RED_PILOT will ?? +void enableSlot(uint8_t slotNumber, uint8_t device) { + + uint8_t originalContents; + + switch (slotNumber) { + case (1): + bitMask(MAX30102_MULTILEDCONFIG1, MAX30102_SLOT1_MASK, device); + break; + case (2): + bitMask(MAX30102_MULTILEDCONFIG1, MAX30102_SLOT2_MASK, device << 4); + break; + case (3): + bitMask(MAX30102_MULTILEDCONFIG2, MAX30102_SLOT3_MASK, device); + break; + case (4): + bitMask(MAX30102_MULTILEDCONFIG2, MAX30102_SLOT4_MASK, device << 4); + break; + default: + //Shouldn't be here! + break; + } +} + +//Clears all slot assignments +void disableSlots(void) { + writeRegister8(_i2caddr, MAX30102_MULTILEDCONFIG1, 0); + writeRegister8(_i2caddr, MAX30102_MULTILEDCONFIG2, 0); +} + +// +// FIFO Configuration +// + +//Set sample average (Table 3, Page 18) +void setFIFOAverage(uint8_t numberOfSamples) { + bitMask(MAX30102_FIFOCONFIG, MAX30102_SAMPLEAVG_MASK, numberOfSamples); +} + +//Resets all points to start in a known state +//Page 15 recommends clearing FIFO before beginning a read +void clearFIFO(void) { + writeRegister8(_i2caddr, MAX30102_FIFOWRITEPTR, 0); + writeRegister8(_i2caddr, MAX30102_FIFOOVERFLOW, 0); + writeRegister8(_i2caddr, MAX30102_FIFOREADPTR, 0); +} + +//Enable roll over if FIFO over flows +void enableFIFORollover(void) { + bitMask(MAX30102_FIFOCONFIG, MAX30102_ROLLOVER_MASK, MAX30102_ROLLOVER_ENABLE); +} + +//Disable roll over if FIFO over flows +void disableFIFORollover(void) { + bitMask(MAX30102_FIFOCONFIG, MAX30102_ROLLOVER_MASK, MAX30102_ROLLOVER_DISABLE); +} + +//Set number of samples to trigger the almost full interrupt (Page 18) +//Power on default is 32 samples +//Note it is reverse: 0x00 is 32 samples, 0x0F is 17 samples +void setFIFOAlmostFull(uint8_t numberOfSamples) { + bitMask(MAX30102_FIFOCONFIG, MAX30102_A_FULL_MASK, numberOfSamples); +} + +//Read the FIFO Write Pointer +uint8_t getWritePointer(void) { + return (readRegister8(_i2caddr, MAX30102_FIFOWRITEPTR)); +} + +//Read the FIFO Read Pointer +uint8_t getReadPointer(void) { + return (readRegister8(_i2caddr, MAX30102_FIFOREADPTR)); +} + + +// Die Temperature +// Returns temp in C +float readTemperature() { + + //DIE_TEMP_RDY interrupt must be enabled + //See issue 19: https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/19 + + // Step 1: Config die temperature register to take 1 temperature sample + writeRegister8(_i2caddr, MAX30102_DIETEMPCONFIG, 0x01); + + // Poll for bit to clear, reading is then complete + // Timeout after 100ms + unsigned long startTime = millis(); + while (millis() - startTime < 100) + { + //uint8_t response = readRegister8(_i2caddr, MAX30102_DIETEMPCONFIG); //Original way + //if ((response & 0x01) == 0) break; //We're done! + + //Check to see if DIE_TEMP_RDY interrupt is set + uint8_t response = readRegister8(_i2caddr, MAX30102_INTSTAT2); + if ((response & MAX30102_INT_DIE_TEMP_RDY_ENABLE) > 0) break; //We're done! + delay(1); //Let's not over burden the I2C bus + } + //TODO How do we want to fail? With what type of error? + //? if(millis() - startTime >= 100) return(-999.0); + + // Step 2: Read die temperature register (integer) + int8_t tempInt = readRegister8(_i2caddr, MAX30102_DIETEMPINT); + uint8_t tempFrac = readRegister8(_i2caddr, MAX30102_DIETEMPFRAC); //Causes the clearing of the DIE_TEMP_RDY interrupt + + // Step 3: Calculate temperature (datasheet pg. 23) + return (float)tempInt + ((float)tempFrac * 0.0625); +} + +// Returns die temp in F +float readTemperatureF() { + float temp = readTemperature(); + + if (temp != -999.0) temp = temp * 1.8 + 32.0; + + return (temp); +} + +// Set the PROX_INT_THRESHold +void setPROXINTTHRESH(uint8_t val) { + writeRegister8(_i2caddr, MAX30102_PROXINTTHRESH, val); +} + + +// +// Device ID and Revision +// +uint8_t readPartID() { + return readRegister8(_i2caddr, MAX30102_PARTID); +} + +void readRevisionID() { + revisionID = readRegister8(_i2caddr, MAX30102_REVISIONID); +} + +uint8_t getRevisionID() { + return revisionID; +} + + +//Setup the sensor +//The MAX30102 has many settings. By default we select: +// Sample Average = 4 +// Mode = MultiLED +// ADC Range = 16384 (62.5pA per LSB) +// Sample rate = 50 +//Use the default setup if you are just getting started with the MAX30102 sensor +void setup(byte powerLevel, byte sampleAverage, byte ledMode, int sampleRate, int pulseWidth, int adcRange) { + softReset(); //Reset all configuration, threshold, and data registers to POR values + + //FIFO Configuration + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + //The chip will average multiple samples of same type together if you wish + if (sampleAverage == 1) setFIFOAverage(MAX30102_SAMPLEAVG_1); //No averaging per FIFO record + else if (sampleAverage == 2) setFIFOAverage(MAX30102_SAMPLEAVG_2); + else if (sampleAverage == 4) setFIFOAverage(MAX30102_SAMPLEAVG_4); + else if (sampleAverage == 8) setFIFOAverage(MAX30102_SAMPLEAVG_8); + else if (sampleAverage == 16) setFIFOAverage(MAX30102_SAMPLEAVG_16); + else if (sampleAverage == 32) setFIFOAverage(MAX30102_SAMPLEAVG_32); + else setFIFOAverage(MAX30102_SAMPLEAVG_4); + + //setFIFOAlmostFull(2); //Set to 30 samples to trigger an 'Almost Full' interrupt + enableFIFORollover(); //Allow FIFO to wrap/roll over + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //Mode Configuration + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + if (ledMode == 3) setLEDMode(MAX30102_MODE_MULTILED); //Watch all three LED channels + else if (ledMode == 2) setLEDMode(MAX30102_MODE_REDIRONLY); //Red and IR + else setLEDMode(MAX30102_MODE_REDONLY); //Red only + activeLEDs = ledMode; //Used to control how many bytes to read from FIFO buffer + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //Particle Sensing Configuration + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + if(adcRange < 4096) setADCRange(MAX30102_ADCRANGE_2048); //7.81pA per LSB + else if(adcRange < 8192) setADCRange(MAX30102_ADCRANGE_4096); //15.63pA per LSB + else if(adcRange < 16384) setADCRange(MAX30102_ADCRANGE_8192); //31.25pA per LSB + else if(adcRange == 16384) setADCRange(MAX30102_ADCRANGE_16384); //62.5pA per LSB + else setADCRange(MAX30102_ADCRANGE_2048); + + if (sampleRate < 100) setSampleRate(MAX30102_SAMPLERATE_50); //Take 50 samples per second + else if (sampleRate < 200) setSampleRate(MAX30102_SAMPLERATE_100); + else if (sampleRate < 400) setSampleRate(MAX30102_SAMPLERATE_200); + else if (sampleRate < 800) setSampleRate(MAX30102_SAMPLERATE_400); + else if (sampleRate < 1000) setSampleRate(MAX30102_SAMPLERATE_800); + else if (sampleRate < 1600) setSampleRate(MAX30102_SAMPLERATE_1000); + else if (sampleRate < 3200) setSampleRate(MAX30102_SAMPLERATE_1600); + else if (sampleRate == 3200) setSampleRate(MAX30102_SAMPLERATE_3200); + else setSampleRate(MAX30102_SAMPLERATE_50); + + //The longer the pulse width the longer range of detection you'll have + //At 69us and 0.4mA it's about 2 inches + //At 411us and 0.4mA it's about 6 inches + if (pulseWidth < 118) setPulseWidth(MAX30102_PULSEWIDTH_69); //Page 26, Gets us 15 bit resolution + else if (pulseWidth < 215) setPulseWidth(MAX30102_PULSEWIDTH_118); //16 bit resolution + else if (pulseWidth < 411) setPulseWidth(MAX30102_PULSEWIDTH_215); //17 bit resolution + else if (pulseWidth == 411) setPulseWidth(MAX30102_PULSEWIDTH_411); //18 bit resolution + else setPulseWidth(MAX30102_PULSEWIDTH_69); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //LED Pulse Amplitude Configuration + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + //Default is 0x1F which gets us 6.4mA + //powerLevel = 0x02, 0.4mA - Presence detection of ~4 inch + //powerLevel = 0x1F, 6.4mA - Presence detection of ~8 inch + //powerLevel = 0x7F, 25.4mA - Presence detection of ~8 inch + //powerLevel = 0xFF, 50.0mA - Presence detection of ~12 inch + + setPulseAmplitudeRed(powerLevel); + setPulseAmplitudeIR(powerLevel); + setPulseAmplitudeGreen(powerLevel); + setPulseAmplitudeProximity(powerLevel); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //Multi-LED Mode Configuration, Enable the reading of the three LEDs + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + enableSlot(1, SLOT_RED_LED); + if (ledMode > 1) enableSlot(2, SLOT_IR_LED); + if (ledMode > 2) enableSlot(3, SLOT_GREEN_LED); + //enableSlot(1, SLOT_RED_PILOT); + //enableSlot(2, SLOT_IR_PILOT); + //enableSlot(3, SLOT_GREEN_PILOT); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + clearFIFO(); //Reset the FIFO before we begin checking the sensor +} + +// +// Data Collection +// + +//Tell caller how many samples are available +uint8_t available(void) +{ + int8_t numberOfSamples = sense.head - sense.tail; + if (numberOfSamples < 0) numberOfSamples += STORAGE_SIZE; + + return (numberOfSamples); +} + +//Report the most recent red value +uint32_t getRed(void) +{ + //Check the sensor for new data for 250ms + if(safeCheck(250)) + return (sense.red[sense.head]); + else + return(0); //Sensor failed to find new data +} + +//Report the most recent IR value +uint32_t getIR(void) +{ + //Check the sensor for new data for 250ms + if(safeCheck(250)) + return (sense.IR[sense.head]); + else + return(0); //Sensor failed to find new data +} + +//Report the most recent Green value +uint32_t getGreen(void) +{ + //Check the sensor for new data for 250ms + if(safeCheck(250)) + return (sense.green[sense.head]); + else + return(0); //Sensor failed to find new data +} + +//Report the next Red value in the FIFO +uint32_t getFIFORed(void) +{ + return (sense.red[sense.tail]); +} + +//Report the next IR value in the FIFO +uint32_t getFIFOIR(void) +{ + return (sense.IR[sense.tail]); +} + +//Report the next Green value in the FIFO +uint32_t getFIFOGreen(void) +{ + return (sense.green[sense.tail]); +} + +//Advance the tail +void nextSample(void) +{ + if(available()) //Only advance the tail if new data is available + { + sense.tail++; + sense.tail %= STORAGE_SIZE; //Wrap condition + } +} + +//Polls the sensor for new data +//Call regularly +//If new data is available, it updates the head and tail in the main struct +//Returns number of new samples obtained +uint16_t check(void) +{ + //Read register FIDO_DATA in (3-byte * number of active LED) chunks + //Until FIFO_RD_PTR = FIFO_WR_PTR + + byte readPointer = getReadPointer(); + byte writePointer = getWritePointer(); + + int numberOfSamples = 0; + + //Do we have new data? + if (readPointer != writePointer) + { + //Calculate the number of readings we need to get from sensor + numberOfSamples = writePointer - readPointer; + if (numberOfSamples < 0) numberOfSamples += 32; //Wrap condition + + //We now have the number of readings, now calc bytes to read + //For this example we are just doing Red and IR (3 bytes each) + int bytesLeftToRead = numberOfSamples * activeLEDs * 3; + + //Get ready to read a burst of data from the FIFO register + _i2cPort->beginTransmission(MAX30102_ADDRESS); + _i2cPort->write(MAX30102_FIFODATA); + _i2cPort->endTransmission(); + + //We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH + //I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno. + //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno + while (bytesLeftToRead > 0) + { + int toGet = bytesLeftToRead; + if (toGet > I2C_BUFFER_LENGTH) + { + //If toGet is 32 this is bad because we read 6 bytes (Red+IR * 3 = 6) at a time + //32 % 6 = 2 left over. We don't want to request 32 bytes, we want to request 30. + //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27. + + toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeLEDs * 3)); //Trim toGet to be a multiple of the samples we need to read + } + + bytesLeftToRead -= toGet; + + //Request toGet number of bytes from sensor + _i2cPort->requestFrom(MAX30102_ADDRESS, toGet); + + while (toGet > 0) + { + sense.head++; //Advance the head of the storage struct + sense.head %= STORAGE_SIZE; //Wrap condition + + byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long + uint32_t tempLong; + + //Burst read three bytes - RED + temp[3] = 0; + temp[2] = _i2cPort->read(); + temp[1] = _i2cPort->read(); + temp[0] = _i2cPort->read(); + + //Convert array to long + memcpy(&tempLong, temp, sizeof(tempLong)); + + tempLong &= 0x3FFFF; //Zero out all but 18 bits + + sense.red[sense.head] = tempLong; //Store this reading into the sense array + + if (activeLEDs > 1) + { + //Burst read three more bytes - IR + temp[3] = 0; + temp[2] = _i2cPort->read(); + temp[1] = _i2cPort->read(); + temp[0] = _i2cPort->read(); + + //Convert array to long + memcpy(&tempLong, temp, sizeof(tempLong)); + + tempLong &= 0x3FFFF; //Zero out all but 18 bits + + sense.IR[sense.head] = tempLong; + } + + if (activeLEDs > 2) + { + //Burst read three more bytes - Green + temp[3] = 0; + temp[2] = _i2cPort->read(); + temp[1] = _i2cPort->read(); + temp[0] = _i2cPort->read(); + + //Convert array to long + memcpy(&tempLong, temp, sizeof(tempLong)); + + tempLong &= 0x3FFFF; //Zero out all but 18 bits + + sense.green[sense.head] = tempLong; + } + + toGet -= activeLEDs * 3; + } + + } //End while (bytesLeftToRead > 0) + + } //End readPtr != writePtr + + return (numberOfSamples); //Let the world know how much new data we found +} + +//Check for new data but give up after a certain amount of time +//Returns true if new data was found +//Returns false if new data was not found +bool safeCheck(uint8_t maxTimeToCheck) +{ + uint32_t markTime = millis(); + + while(1) + { + if(millis() - markTime > maxTimeToCheck) return(false); + + if(check() == true) //We found new data! + return(true); + + delay(1); + } +} + +//Given a register, read it, mask it, and then set the thing +void bitMask(uint8_t reg, uint8_t mask, uint8_t thing) +{ + // Grab current register context + uint8_t originalContents = readRegister8(_i2caddr, reg); + + // Zero-out the portions of the register we're interested in + originalContents = originalContents & mask; + + // Change contents + writeRegister8(_i2caddr, reg, originalContents | thing); +} + +// +// Low-level I2C Communication +// +uint8_t readRegister8(uint8_t address, uint8_t reg) { + _i2cPort->beginTransmission(address); + _i2cPort->write(reg); + _i2cPort->endTransmission(false); + + _i2cPort->requestFrom((uint8_t)address, (uint8_t)1); // Request 1 byte + if (_i2cPort->available()) + { + return(_i2cPort->read()); + } + + return (0); //Fail + +} + +void writeRegister8(uint8_t address, uint8_t reg, uint8_t value) { + _i2cPort->beginTransmission(address); + _i2cPort->write(reg); + _i2cPort->write(value); + _i2cPort->endTransmission(); +} +*/ \ No newline at end of file
diff -r 000000000000 -r 83277b73a1f8 MAX30102/MAX30102.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX30102/MAX30102.h Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,138 @@ +/* +#define MAX30102_ADDRESS 0x57 //7-bit I2C Address +//Note that MAX30102 has the same I2C address and Part ID + +#define I2C_SPEED_STANDARD 100000 +#define I2C_SPEED_FAST 400000 + + +//Define the size of the I2C buffer based on the platform the user has +#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) + + //I2C_BUFFER_LENGTH is defined in Wire.H + #define I2C_BUFFER_LENGTH BUFFER_LENGTH + +#elif defined(__SAMD21G18A__) + + //SAMD21 uses RingBuffer.h + #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE + +#else + + //The catch-all default is 32 + #define I2C_BUFFER_LENGTH 32 + +#endif + +class MAX30102 { + public: + MAX30102(void); + + // bool begin(TwoWire &wirePort = Wire, uint32_t i2cSpeed = I2C_SPEED_STANDARD, uint8_t i2caddr = MAX30102_ADDRESS); + + uint32_t getRed(void); //Returns immediate red value + uint32_t getIR(void); //Returns immediate IR value + uint32_t getGreen(void); //Returns immediate green value + bool safeCheck(uint8_t maxTimeToCheck); //Given a max amount of time, check for new data + + // Configuration + void softReset(); + void shutDown(); + void wakeUp(); + + void setLEDMode(uint8_t mode); + + void setADCRange(uint8_t adcRange); + void setSampleRate(uint8_t sampleRate); + void setPulseWidth(uint8_t pulseWidth); + + void setPulseAmplitudeRed(uint8_t value); + void setPulseAmplitudeIR(uint8_t value); + void setPulseAmplitudeGreen(uint8_t value); + void setPulseAmplitudeProximity(uint8_t value); + + void setProximityThreshold(uint8_t threshMSB); + + //Multi-led configuration mode (page 22) + void enableSlot(uint8_t slotNumber, uint8_t device); //Given slot number, assign a device to slot + void disableSlots(void); + + // Data Collection + + //Interrupts (page 13, 14) + uint8_t getINT1(void); //Returns the main interrupt group + uint8_t getINT2(void); //Returns the temp ready interrupt + void enableAFULL(void); //Enable/disable individual interrupts + void disableAFULL(void); + void enableDATARDY(void); + void disableDATARDY(void); + void enableALCOVF(void); + void disableALCOVF(void); + void enablePROXINT(void); + void disablePROXINT(void); + void enableDIETEMPRDY(void); + void disableDIETEMPRDY(void); + + //FIFO Configuration (page 18) + void setFIFOAverage(uint8_t samples); + void enableFIFORollover(); + void disableFIFORollover(); + void setFIFOAlmostFull(uint8_t samples); + + //FIFO Reading + uint16_t check(void); //Checks for new data and fills FIFO + uint8_t available(void); //Tells caller how many new samples are available (head - tail) + void nextSample(void); //Advances the tail of the sense array + uint32_t getFIFORed(void); //Returns the FIFO sample pointed to by tail + uint32_t getFIFOIR(void); //Returns the FIFO sample pointed to by tail + uint32_t getFIFOGreen(void); //Returns the FIFO sample pointed to by tail + + uint8_t getWritePointer(void); + uint8_t getReadPointer(void); + void clearFIFO(void); //Sets the read/write pointers to zero + + //Proximity Mode Interrupt Threshold + void setPROXINTTHRESH(uint8_t val); + + // Die Temperature + float readTemperature(); + float readTemperatureF(); + + // Detecting ID/Revision + uint8_t getRevisionID(); + uint8_t readPartID(); + + // Setup the IC with user selectable settings + void setup(byte powerLevel = 0x1F, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 400, int pulseWidth = 411, int adcRange = 4096); + + // Low-level I2C communication + uint8_t readRegister8(uint8_t address, uint8_t reg); + void writeRegister8(uint8_t address, uint8_t reg, uint8_t value); + + private: + TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware + uint8_t _i2caddr; + + //activeLEDs is the number of channels turned on, and can be 1 to 3. 2 is common for Red+IR. + byte activeLEDs; //Gets set during setup. Allows check() to calculate how many bytes to read from FIFO + + uint8_t revisionID; + + void readRevisionID(); + + void bitMask(uint8_t reg, uint8_t mask, uint8_t thing); + + #define STORAGE_SIZE 4 //Each long is 4 bytes so limit this to fit on your micro + typedef struct Record + { + uint32_t red[STORAGE_SIZE]; + uint32_t IR[STORAGE_SIZE]; + uint32_t green[STORAGE_SIZE]; + byte head; + byte tail; + } sense_struct; //This is our circular buffer of readings from the sensor + + sense_struct sense; + +}; +*/
diff -r 000000000000 -r 83277b73a1f8 README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,22 @@ +Instructions for building Dot-Examples + +1. Import dot-examples +$ mbed import http://os.mbed.com/teams/MultiTech/code/Dot-Examples/ + +2. cd to the Dot-Examples/examples and import the dot library stack +Choose either the stable or dev library for your dot device +e.g. to get the latest development library for the xDot +$ mbed add http://os.mbed.com/teams/MultiTech/code/libxDot-dev-mbed5/ + +3. Update mbed-os revision to match that of the dot library you just imported. +This information can be found in the library's commit history. +e.g. +$ cd Dot-Examples/mbed-os +$ mbed update mbed-os-5.7.6 + +4. Modify the Dot-Examples/examples/example_config.h to select the channel plan and which example to build +By default, the OTA example is selected to build with the US channel plan + +5. Once the example is selected, modify the example source file to match the configuration of your gateway. +Make sure the network_name, network_passphrase, frequency_sub_band (US), public_network, and join_delay settings match that of your gateway +
diff -r 000000000000 -r 83277b73a1f8 heartRate/heartRate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/heartRate/heartRate.cpp Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,112 @@ + + +#include "heartRate.h" + +int32_t IR_AC_Max = 20; +int16_t IR_AC_Min = -20; + +int16_t IR_AC_Signal_Current = 0; +int16_t IR_AC_Signal_Previous; +int16_t IR_AC_Signal_min = 0; +int16_t IR_AC_Signal_max = 0; +int16_t IR_Average_Estimated; + +int16_t positiveEdge = 0; +int16_t negativeEdge = 0; +int32_t ir_avg_reg = 0; + +int16_t cbuf[32]; +uint8_t offset = 0; + +static const uint16_t FIRCoeffs[12] = {172, 321, 579, 927, 1360, 1858, 2390, 2916, 3391, 3768, 4012, 4096}; + +// Heart Rate Monitor functions takes a sample value and the sample number +// Returns true if a beat is detected +// A running average of four samples is recommended for display on the screen. +bool checkForBeat(int32_t sample) +{ + bool beatDetected = false; + + // Save current state + IR_AC_Signal_Previous = IR_AC_Signal_Current; + + //This is good to view for debugging + //Serial.print("Signal_Current: "); + //Serial.println(IR_AC_Signal_Current); + + // Process next data sample + IR_Average_Estimated = averageDCEstimator(&ir_avg_reg, sample); + IR_AC_Signal_Current = lowPassFIRFilter(sample - IR_Average_Estimated); + + // Detect positive zero crossing (rising edge) + if ((IR_AC_Signal_Previous < 0) & (IR_AC_Signal_Current >= 0)) + { + + IR_AC_Max = IR_AC_Signal_max; //Adjust our AC max and min + IR_AC_Min = IR_AC_Signal_min; + + positiveEdge = 1; + negativeEdge = 0; + IR_AC_Signal_max = 0; + + //if ((IR_AC_Max - IR_AC_Min) > 100 & (IR_AC_Max - IR_AC_Min) < 1000) + if ((IR_AC_Max - IR_AC_Min) > 20 & (IR_AC_Max - IR_AC_Min) < 1000) + { + //Heart beat!!! + beatDetected = true; + } + } + + // Detect negative zero crossing (falling edge) + if ((IR_AC_Signal_Previous > 0) & (IR_AC_Signal_Current <= 0)) + { + positiveEdge = 0; + negativeEdge = 1; + IR_AC_Signal_min = 0; + } + + // Find Maximum value in positive cycle + if (positiveEdge & (IR_AC_Signal_Current > IR_AC_Signal_Previous)) + { + IR_AC_Signal_max = IR_AC_Signal_Current; + } + + // Find Minimum value in negative cycle + if (negativeEdge & (IR_AC_Signal_Current < IR_AC_Signal_Previous)) + { + IR_AC_Signal_min = IR_AC_Signal_Current; + } + + return(beatDetected); +} + +// Average DC Estimator +int16_t averageDCEstimator(int32_t *p, uint16_t x) +{ + *p += ((((long) x << 15) - *p) >> 4); + return (*p >> 15); +} + +// Low Pass FIR Filter +int16_t lowPassFIRFilter(int16_t din) +{ + cbuf[offset] = din; + + int32_t z = mul16(FIRCoeffs[11], cbuf[(offset - 11) & 0x1F]); + + for (uint8_t i = 0 ; i < 11 ; i++) + { + z += mul16(FIRCoeffs[i], cbuf[(offset - i) & 0x1F] + cbuf[(offset - 22 + i) & 0x1F]); + } + + offset++; + offset %= 32; //Wrap condition + + return(z >> 15); +} + +// Integer multiplier +int32_t mul16(int16_t x, int16_t y) +{ + return((long)x * (long)y); +} \ No newline at end of file
diff -r 000000000000 -r 83277b73a1f8 heartRate/heartRate.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/heartRate/heartRate.h Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,12 @@ + +#ifndef HEARTRATE_H_ +#define HEARTRATE_H_ + +#include "mbed.h" + +bool checkForBeat(int32_t sample); +int16_t averageDCEstimator(int32_t *p, uint16_t x); +int16_t lowPassFIRFilter(int16_t din); +int32_t mul16(int16_t x, int16_t y); + +#endif \ No newline at end of file
diff -r 000000000000 -r 83277b73a1f8 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,131 @@ +//#include <Wire.h> +/*#include "MAX30102.h" + +#include "heartRate.h" + +//MAX30102 particleSensor; + + +void(* resetFunc) (void) = 0; + +bool nofinger=false; +bool programStarted=false; + +int RATE_SIZE=0; //Increase this for more averaging. 4 is good. +int rate[1000]; //Array of heart rates +long lastBeat = 0; //Time at which the last beat occurred + +float beatsPerMinute; +int beatAvg; + +long now=0; +int bpm = 0; +int mins=0; +int ten_secs=10; +int avg=0; + +long t=millis(); +void setup() +{ + pc.baud(9600); + pc.format(8,SerialBase::None,1); + wait(1); + pc.printf("Initializing..."); + + // Initialize sensor + if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed + { + pc.printf"MAX30105 was not found. Please check wiring/power. "); + while (1); + } + pc.printf("Place your index finger on the sensor with steady pressure."); + + particleSensor.setup(); //Configure sensor with default settings + particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running + particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED + + //particleSensor.enableDIETEMPRDY(); //Enable the temp ready interrupt. This is required. +} + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void measureTemp(){ + float temperature=0; + temperature = particleSensor.readTemperature(); + pc.printf(" temperatureC="); + pc.printf(temperature, 4); + return; +} + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +void check(){ + if(!programStarted && RATE_SIZE==4){ + programStarted=true; RATE_SIZE=0; + } + return; +} + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void measureBPM(){ + long irValue = particleSensor.getIR(); + + if (checkForBeat(irValue) == true) + { + //We sensed a beat! + long delta = millis() - lastBeat; + lastBeat = millis(); + + beatsPerMinute = 60 / (delta / 1000.0); + + if (beatsPerMinute < 255 && beatsPerMinute > 20) + { + check(); + rate[RATE_SIZE++]=(byte)beatsPerMinute; + } + } + + //Serial.print(ten_secs); + //Serial.println("seconds...."); + if(millis()-t>=10000){ + if(RATE_SIZE==0){ + nofinger=true; + return; + } + + beatAvg=0; + for(int i=0; i<RATE_SIZE; i++){ + beatAvg+=rate[i]; + } + pc.printf("Avg BPM="); + pc.printf("%i",beatAvg/RATE_SIZE); + t=millis(); + ten_secs+=10; + mins++; + if(mins%6==0){ + beatAvg=0; + for(int i=0; i<RATE_SIZE; i++){ + beatAvg+=rate[i]; + } + pc.printf(" Avg BPM after a min is="); + pc.printf(beatAvg/RATE_SIZE); + //measureTemp(); + mins=0; + } + } + + if (irValue < 50000){ + nofinger=true; + return; + } +} +int main() +{ + setup(); + if(nofinger){ + pc.printf(" No finger"); + long irValue = particleSensor.getIR(); + if (irValue > 50000){ + nofinger=false; + resetFunc(); + } + } + measureBPM(); + //Measure(); +}*/ \ No newline at end of file
diff -r 000000000000 -r 83277b73a1f8 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#c966348d3f9ca80843be7cdc9b748f06ea73ced0
diff -r 000000000000 -r 83277b73a1f8 setup.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.sh Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,3 @@ +if [ ! -d ISL29011 ]; then + hg clone https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/ +fi
diff -r 000000000000 -r 83277b73a1f8 spo2_algorithm/spo2_algorithm.cpp
diff -r 000000000000 -r 83277b73a1f8 spo2_algorithm/spo2_algorithm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spo2_algorithm/spo2_algorithm.h Sun Jul 28 08:14:38 2019 +0000 @@ -0,0 +1,40 @@ +#ifndef SPO2_ALGORITHM_H_ +#define SPO2_ALGORITHM_H_ +/* +#include "mbed.h" + +#define FreqS 25 //sampling frequency +#define BUFFER_SIZE (FreqS * 4) +#define MA4_SIZE 4 // DONOT CHANGE +//#define min(x,y) ((x) < (y) ? (x) : (y)) //Defined in Arduino.h + +//uch_spo2_table is approximated as -45.060*ratioAverage* ratioAverage + 30.354 *ratioAverage + 94.845 ; +const uint8_t uch_spo2_table[184]={ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99, + 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, + 90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81, + 80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67, + 66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29, + 28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, + 3, 2, 1 } ; +static int32_t an_x[ BUFFER_SIZE]; //ir +static int32_t an_y[ BUFFER_SIZE]; //red + + +#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) +//Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format +//To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data. +void maxim_heart_rate_and_oxygen_saturation(uint16_t *pun_ir_buffer, int32_t n_ir_buffer_length, uint16_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, int32_t *pn_heart_rate, int8_t *pch_hr_valid); +#else +void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer, int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, int32_t *pn_heart_rate, int8_t *pch_hr_valid); +#endif + +void maxim_find_peaks(int32_t *pn_locs, int32_t *n_npks, int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num); +void maxim_peaks_above_min_height(int32_t *pn_locs, int32_t *n_npks, int32_t *pn_x, int32_t n_size, int32_t n_min_height); +void maxim_remove_close_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_min_distance); +void maxim_sort_ascend(int32_t *pn_x, int32_t n_size); +void maxim_sort_indices_descend(int32_t *pn_x, int32_t *pn_indx, int32_t n_size); + +#endif*/ /* ALGORITHM_H_ */