Chanel's edits
Dependencies: max32630fthr USBDevice
max86150.cpp@4:4233f5538abf, 2020-02-23 (annotated)
- Committer:
- saleiferis
- Date:
- Sun Feb 23 12:04:01 2020 +0000
- Revision:
- 4:4233f5538abf
- Parent:
- 1:6e6f7e3cc1e1
- Child:
- 8:2005014df05c
BT example streaming works
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
saleiferis | 0:89ec48e52250 | 1 | /*************************************************** |
saleiferis | 0:89ec48e52250 | 2 | Arduino library written for the Maxim MAX86150 ECG and PPG integrated sensor |
saleiferis | 0:89ec48e52250 | 3 | |
saleiferis | 0:89ec48e52250 | 4 | Written by Ashwin Whitchurch, ProtoCentral Electronics (www.protocentral.com) |
saleiferis | 0:89ec48e52250 | 5 | |
saleiferis | 0:89ec48e52250 | 6 | Based on code written by Peter Jansen and Nathan Seidle (SparkFun) for the MAX30105 sensor |
saleiferis | 0:89ec48e52250 | 7 | BSD license, all text above must be included in any redistribution. |
saleiferis | 0:89ec48e52250 | 8 | *****************************************************/ |
saleiferis | 0:89ec48e52250 | 9 | |
saleiferis | 0:89ec48e52250 | 10 | #include "max86150.h" |
saleiferis | 0:89ec48e52250 | 11 | |
saleiferis | 0:89ec48e52250 | 12 | |
saleiferis | 0:89ec48e52250 | 13 | static const uint8_t MAX86150_INTSTAT1 = 0x00; |
saleiferis | 0:89ec48e52250 | 14 | static const uint8_t MAX86150_INTSTAT2 = 0x01; |
saleiferis | 0:89ec48e52250 | 15 | static const uint8_t MAX86150_INTENABLE1 = 0x02; |
saleiferis | 0:89ec48e52250 | 16 | static const uint8_t MAX86150_INTENABLE2 = 0x03; |
saleiferis | 0:89ec48e52250 | 17 | |
saleiferis | 0:89ec48e52250 | 18 | static const uint8_t MAX86150_FIFOWRITEPTR = 0x04; |
saleiferis | 0:89ec48e52250 | 19 | static const uint8_t MAX86150_FIFOOVERFLOW = 0x05; |
saleiferis | 0:89ec48e52250 | 20 | static const uint8_t MAX86150_FIFOREADPTR = 0x06; |
saleiferis | 0:89ec48e52250 | 21 | static const uint8_t MAX86150_FIFODATA = 0x07; |
saleiferis | 0:89ec48e52250 | 22 | |
saleiferis | 0:89ec48e52250 | 23 | static const uint8_t MAX86150_FIFOCONFIG = 0x08; |
saleiferis | 0:89ec48e52250 | 24 | static const uint8_t MAX86150_FIFOCONTROL1= 0x09; |
saleiferis | 0:89ec48e52250 | 25 | static const uint8_t MAX86150_FIFOCONTROL2 = 0x0A; |
saleiferis | 0:89ec48e52250 | 26 | |
saleiferis | 0:89ec48e52250 | 27 | static const uint8_t MAX86150_SYSCONTROL = 0x0D; |
saleiferis | 0:89ec48e52250 | 28 | static const uint8_t MAX86150_PPGCONFIG1 = 0x0E; |
saleiferis | 0:89ec48e52250 | 29 | static const uint8_t MAX86150_PPGCONFIG2 = 0x0F; |
saleiferis | 0:89ec48e52250 | 30 | static const uint8_t MAX86150_LED_PROX_AMP = 0x10; |
saleiferis | 0:89ec48e52250 | 31 | |
saleiferis | 0:89ec48e52250 | 32 | static const uint8_t MAX86150_LED1_PULSEAMP = 0x11; |
saleiferis | 0:89ec48e52250 | 33 | static const uint8_t MAX86150_LED2_PULSEAMP = 0x12; |
saleiferis | 0:89ec48e52250 | 34 | static const uint8_t MAX86150_LED_RANGE = 0x14; |
saleiferis | 0:89ec48e52250 | 35 | static const uint8_t MAX86150_LED_PILOT_PA = 0x15; |
saleiferis | 0:89ec48e52250 | 36 | |
saleiferis | 0:89ec48e52250 | 37 | static const uint8_t MAX86150_ECG_CONFIG1 = 0x3C; |
saleiferis | 0:89ec48e52250 | 38 | static const uint8_t MAX86150_ECG_CONFIG3 = 0x3E; |
saleiferis | 0:89ec48e52250 | 39 | static const uint8_t MAX86150_PROXINTTHRESH = 0x10; |
saleiferis | 0:89ec48e52250 | 40 | |
saleiferis | 0:89ec48e52250 | 41 | static const uint8_t MAX86150_PARTID = 0xFF; |
saleiferis | 0:89ec48e52250 | 42 | |
saleiferis | 0:89ec48e52250 | 43 | // MAX86150 Commands |
saleiferis | 0:89ec48e52250 | 44 | static const uint8_t MAX86150_INT_A_FULL_MASK = (uint8_t)~0b10000000; |
saleiferis | 0:89ec48e52250 | 45 | static const uint8_t MAX86150_INT_A_FULL_ENABLE = 0x80; |
saleiferis | 0:89ec48e52250 | 46 | static const uint8_t MAX86150_INT_A_FULL_DISABLE = 0x00; |
saleiferis | 0:89ec48e52250 | 47 | |
saleiferis | 0:89ec48e52250 | 48 | static const uint8_t MAX86150_INT_DATA_RDY_MASK = (uint8_t)~0b01000000; |
saleiferis | 0:89ec48e52250 | 49 | static const uint8_t MAX86150_INT_DATA_RDY_ENABLE = 0x40; |
saleiferis | 0:89ec48e52250 | 50 | static const uint8_t MAX86150_INT_DATA_RDY_DISABLE = 0x00; |
saleiferis | 0:89ec48e52250 | 51 | |
saleiferis | 0:89ec48e52250 | 52 | static const uint8_t MAX86150_INT_ALC_OVF_MASK = (uint8_t)~0b00100000; |
saleiferis | 0:89ec48e52250 | 53 | static const uint8_t MAX86150_INT_ALC_OVF_ENABLE = 0x20; |
saleiferis | 0:89ec48e52250 | 54 | static const uint8_t MAX86150_INT_ALC_OVF_DISABLE = 0x00; |
saleiferis | 0:89ec48e52250 | 55 | |
saleiferis | 0:89ec48e52250 | 56 | static const uint8_t MAX86150_INT_PROX_INT_MASK = (uint8_t)~0b00010000; |
saleiferis | 0:89ec48e52250 | 57 | static const uint8_t MAX86150_INT_PROX_INT_ENABLE = 0x10; |
saleiferis | 0:89ec48e52250 | 58 | static const uint8_t MAX86150_INT_PROX_INT_DISABLE = 0x00; |
saleiferis | 0:89ec48e52250 | 59 | |
saleiferis | 0:89ec48e52250 | 60 | static const uint8_t MAX86150_SAMPLEAVG_MASK = (uint8_t)~0b11100000; |
saleiferis | 0:89ec48e52250 | 61 | static const uint8_t MAX86150_SAMPLEAVG_1 = 0x00; |
saleiferis | 0:89ec48e52250 | 62 | static const uint8_t MAX86150_SAMPLEAVG_2 = 0x20; |
saleiferis | 0:89ec48e52250 | 63 | static const uint8_t MAX86150_SAMPLEAVG_4 = 0x40; |
saleiferis | 0:89ec48e52250 | 64 | static const uint8_t MAX86150_SAMPLEAVG_8 = 0x60; |
saleiferis | 0:89ec48e52250 | 65 | static const uint8_t MAX86150_SAMPLEAVG_16 = 0x80; |
saleiferis | 0:89ec48e52250 | 66 | static const uint8_t MAX86150_SAMPLEAVG_32 = 0xA0; |
saleiferis | 0:89ec48e52250 | 67 | |
saleiferis | 0:89ec48e52250 | 68 | static const uint8_t MAX86150_ROLLOVER_MASK = 0xEF; |
saleiferis | 0:89ec48e52250 | 69 | static const uint8_t MAX86150_ROLLOVER_ENABLE = 0x10; |
saleiferis | 0:89ec48e52250 | 70 | static const uint8_t MAX86150_ROLLOVER_DISABLE = 0x00; |
saleiferis | 0:89ec48e52250 | 71 | |
saleiferis | 0:89ec48e52250 | 72 | static const uint8_t MAX86150_A_FULL_MASK = 0xF0; |
saleiferis | 0:89ec48e52250 | 73 | |
saleiferis | 0:89ec48e52250 | 74 | static const uint8_t MAX86150_SHUTDOWN_MASK = 0x7F; |
saleiferis | 0:89ec48e52250 | 75 | static const uint8_t MAX86150_SHUTDOWN = 0x80; |
saleiferis | 0:89ec48e52250 | 76 | static const uint8_t MAX86150_WAKEUP = 0x00; |
saleiferis | 0:89ec48e52250 | 77 | |
saleiferis | 0:89ec48e52250 | 78 | static const uint8_t MAX86150_RESET_MASK = 0xFE; |
saleiferis | 0:89ec48e52250 | 79 | static const uint8_t MAX86150_RESET = 0x01; |
saleiferis | 0:89ec48e52250 | 80 | |
saleiferis | 0:89ec48e52250 | 81 | static const uint8_t MAX86150_MODE_MASK = 0xF8; |
saleiferis | 0:89ec48e52250 | 82 | static const uint8_t MAX86150_MODE_REDONLY = 0x02; |
saleiferis | 0:89ec48e52250 | 83 | static const uint8_t MAX86150_MODE_REDIRONLY = 0x03; |
saleiferis | 0:89ec48e52250 | 84 | static const uint8_t MAX86150_MODE_MULTILED = 0x07; |
saleiferis | 0:89ec48e52250 | 85 | |
saleiferis | 0:89ec48e52250 | 86 | static const uint8_t MAX86150_ADCRANGE_MASK = 0x9F; |
saleiferis | 0:89ec48e52250 | 87 | static const uint8_t MAX86150_ADCRANGE_2048 = 0x00; |
saleiferis | 0:89ec48e52250 | 88 | static const uint8_t MAX86150_ADCRANGE_4096 = 0x20; |
saleiferis | 0:89ec48e52250 | 89 | static const uint8_t MAX86150_ADCRANGE_8192 = 0x40; |
saleiferis | 0:89ec48e52250 | 90 | static const uint8_t MAX86150_ADCRANGE_16384 = 0x60; |
saleiferis | 0:89ec48e52250 | 91 | |
saleiferis | 0:89ec48e52250 | 92 | static const uint8_t MAX86150_SAMPLERATE_MASK = 0xE3; |
saleiferis | 0:89ec48e52250 | 93 | static const uint8_t MAX86150_SAMPLERATE_50 = 0x00; |
saleiferis | 0:89ec48e52250 | 94 | static const uint8_t MAX86150_SAMPLERATE_100 = 0x04; |
saleiferis | 0:89ec48e52250 | 95 | static const uint8_t MAX86150_SAMPLERATE_200 = 0x08; |
saleiferis | 0:89ec48e52250 | 96 | static const uint8_t MAX86150_SAMPLERATE_400 = 0x0C; |
saleiferis | 0:89ec48e52250 | 97 | static const uint8_t MAX86150_SAMPLERATE_800 = 0x10; |
saleiferis | 0:89ec48e52250 | 98 | static const uint8_t MAX86150_SAMPLERATE_1000 = 0x14; |
saleiferis | 0:89ec48e52250 | 99 | static const uint8_t MAX86150_SAMPLERATE_1600 = 0x18; |
saleiferis | 0:89ec48e52250 | 100 | static const uint8_t MAX86150_SAMPLERATE_3200 = 0x1C; |
saleiferis | 0:89ec48e52250 | 101 | |
saleiferis | 0:89ec48e52250 | 102 | static const uint8_t MAX86150_PULSEWIDTH_MASK = 0xFC; |
saleiferis | 0:89ec48e52250 | 103 | static const uint8_t MAX86150_PULSEWIDTH_69 = 0x00; |
saleiferis | 0:89ec48e52250 | 104 | static const uint8_t MAX86150_PULSEWIDTH_118 = 0x01; |
saleiferis | 0:89ec48e52250 | 105 | static const uint8_t MAX86150_PULSEWIDTH_215 = 0x02; |
saleiferis | 0:89ec48e52250 | 106 | static const uint8_t MAX86150_PULSEWIDTH_411 = 0x03; |
saleiferis | 0:89ec48e52250 | 107 | |
saleiferis | 0:89ec48e52250 | 108 | static const uint8_t MAX86150_SLOT1_MASK = 0xF0; |
saleiferis | 0:89ec48e52250 | 109 | static const uint8_t MAX86150_SLOT2_MASK = 0x0F; |
saleiferis | 0:89ec48e52250 | 110 | static const uint8_t MAX86150_SLOT3_MASK = 0xF0; |
saleiferis | 0:89ec48e52250 | 111 | static const uint8_t MAX86150_SLOT4_MASK = 0x0F; |
saleiferis | 0:89ec48e52250 | 112 | |
saleiferis | 0:89ec48e52250 | 113 | static const uint8_t SLOT_NONE = 0x00; |
saleiferis | 0:89ec48e52250 | 114 | static const uint8_t SLOT_RED_LED = 0x01; |
saleiferis | 0:89ec48e52250 | 115 | static const uint8_t SLOT_IR_LED = 0x02; |
saleiferis | 0:89ec48e52250 | 116 | static const uint8_t SLOT_RED_PILOT = 0x09; |
saleiferis | 0:89ec48e52250 | 117 | static const uint8_t SLOT_IR_PILOT = 0x0A; |
saleiferis | 0:89ec48e52250 | 118 | static const uint8_t SLOT_ECG = 0x0D; |
saleiferis | 0:89ec48e52250 | 119 | |
saleiferis | 0:89ec48e52250 | 120 | static const uint8_t MAX_30105_EXPECTEDPARTID = 0x1E; |
saleiferis | 0:89ec48e52250 | 121 | //static const uint8_t MAX_30105_EXPECTEDPARTID = 0x00; |
saleiferis | 0:89ec48e52250 | 122 | |
saleiferis | 0:89ec48e52250 | 123 | extern Serial pc; |
saleiferis | 0:89ec48e52250 | 124 | |
saleiferis | 0:89ec48e52250 | 125 | MAX86150::MAX86150() { |
saleiferis | 0:89ec48e52250 | 126 | // Constructor |
saleiferis | 0:89ec48e52250 | 127 | } |
saleiferis | 0:89ec48e52250 | 128 | |
saleiferis | 0:89ec48e52250 | 129 | //boolean MAX86150::begin(TwoWire &wirePort, uint32_t i2cSpeed, uint8_t i2caddr) |
saleiferis | 0:89ec48e52250 | 130 | bool MAX86150::begin(I2C &wirePort, uint32_t i2cSpeed, uint8_t i2caddr) |
saleiferis | 0:89ec48e52250 | 131 | { |
saleiferis | 0:89ec48e52250 | 132 | |
saleiferis | 0:89ec48e52250 | 133 | _i2cPort = &wirePort; |
saleiferis | 0:89ec48e52250 | 134 | _i2cPort->frequency(i2cSpeed); |
saleiferis | 0:89ec48e52250 | 135 | _i2caddr = i2caddr; |
saleiferis | 0:89ec48e52250 | 136 | /* |
saleiferis | 0:89ec48e52250 | 137 | // Step 1: Initial Communication and Verification |
saleiferis | 0:89ec48e52250 | 138 | // Check that a MAX86150 is connected |
saleiferis | 0:89ec48e52250 | 139 | //Serial.println(readPartID()); |
saleiferis | 0:89ec48e52250 | 140 | //Serial.println(MAX_30105_EXPECTEDPARTID); |
saleiferis | 0:89ec48e52250 | 141 | if (readPartID() != MAX_30105_EXPECTEDPARTID) { |
saleiferis | 0:89ec48e52250 | 142 | // Error -- Part ID read from MAX86150 does not match expected part ID. |
saleiferis | 0:89ec48e52250 | 143 | // This may mean there is a physical connectivity problem (broken wire, unpowered, etc). |
saleiferis | 0:89ec48e52250 | 144 | return false; |
saleiferis | 0:89ec48e52250 | 145 | } |
saleiferis | 0:89ec48e52250 | 146 | return true;*/ |
saleiferis | 0:89ec48e52250 | 147 | |
saleiferis | 0:89ec48e52250 | 148 | |
saleiferis | 0:89ec48e52250 | 149 | |
saleiferis | 0:89ec48e52250 | 150 | return true; |
saleiferis | 0:89ec48e52250 | 151 | |
saleiferis | 0:89ec48e52250 | 152 | |
saleiferis | 0:89ec48e52250 | 153 | } |
saleiferis | 0:89ec48e52250 | 154 | |
saleiferis | 0:89ec48e52250 | 155 | // |
saleiferis | 0:89ec48e52250 | 156 | // Configuration |
saleiferis | 0:89ec48e52250 | 157 | // |
saleiferis | 0:89ec48e52250 | 158 | |
saleiferis | 0:89ec48e52250 | 159 | //Begin Interrupt configuration |
saleiferis | 0:89ec48e52250 | 160 | uint8_t MAX86150::getINT1(void) |
saleiferis | 0:89ec48e52250 | 161 | { |
saleiferis | 0:89ec48e52250 | 162 | return (readRegister8(_i2caddr, MAX86150_INTSTAT1)); |
saleiferis | 0:89ec48e52250 | 163 | } |
saleiferis | 0:89ec48e52250 | 164 | uint8_t MAX86150::getINT2(void) { |
saleiferis | 0:89ec48e52250 | 165 | return (readRegister8(_i2caddr, MAX86150_INTSTAT2)); |
saleiferis | 0:89ec48e52250 | 166 | } |
saleiferis | 0:89ec48e52250 | 167 | |
saleiferis | 0:89ec48e52250 | 168 | void MAX86150::enableAFULL(void) { |
saleiferis | 0:89ec48e52250 | 169 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_ENABLE); |
saleiferis | 0:89ec48e52250 | 170 | } |
saleiferis | 0:89ec48e52250 | 171 | void MAX86150::disableAFULL(void) { |
saleiferis | 0:89ec48e52250 | 172 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_DISABLE); |
saleiferis | 0:89ec48e52250 | 173 | } |
saleiferis | 0:89ec48e52250 | 174 | |
saleiferis | 0:89ec48e52250 | 175 | void MAX86150::enableDATARDY(void) { |
saleiferis | 0:89ec48e52250 | 176 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_ENABLE); |
saleiferis | 0:89ec48e52250 | 177 | } |
saleiferis | 0:89ec48e52250 | 178 | void MAX86150::disableDATARDY(void) { |
saleiferis | 0:89ec48e52250 | 179 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_DISABLE); |
saleiferis | 0:89ec48e52250 | 180 | } |
saleiferis | 0:89ec48e52250 | 181 | |
saleiferis | 0:89ec48e52250 | 182 | void MAX86150::enableALCOVF(void) { |
saleiferis | 0:89ec48e52250 | 183 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_ENABLE); |
saleiferis | 0:89ec48e52250 | 184 | } |
saleiferis | 0:89ec48e52250 | 185 | void MAX86150::disableALCOVF(void) { |
saleiferis | 0:89ec48e52250 | 186 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_DISABLE); |
saleiferis | 0:89ec48e52250 | 187 | } |
saleiferis | 0:89ec48e52250 | 188 | |
saleiferis | 0:89ec48e52250 | 189 | void MAX86150::enablePROXINT(void) { |
saleiferis | 0:89ec48e52250 | 190 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_ENABLE); |
saleiferis | 0:89ec48e52250 | 191 | } |
saleiferis | 0:89ec48e52250 | 192 | void MAX86150::disablePROXINT(void) { |
saleiferis | 0:89ec48e52250 | 193 | bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_DISABLE); |
saleiferis | 0:89ec48e52250 | 194 | } |
saleiferis | 0:89ec48e52250 | 195 | //End Interrupt configuration |
saleiferis | 0:89ec48e52250 | 196 | |
saleiferis | 0:89ec48e52250 | 197 | void MAX86150::softReset(void) { |
saleiferis | 0:89ec48e52250 | 198 | |
saleiferis | 0:89ec48e52250 | 199 | Timer t; |
saleiferis | 0:89ec48e52250 | 200 | t.start(); |
saleiferis | 0:89ec48e52250 | 201 | bitMask(MAX86150_SYSCONTROL, MAX86150_RESET_MASK, MAX86150_RESET); |
saleiferis | 0:89ec48e52250 | 202 | |
saleiferis | 0:89ec48e52250 | 203 | // Poll for bit to clear, reset is then complete |
saleiferis | 0:89ec48e52250 | 204 | // Timeout after 100ms |
saleiferis | 0:89ec48e52250 | 205 | |
saleiferis | 0:89ec48e52250 | 206 | unsigned long startTime = t.read(); //TODO: double check t.read() returns milliseconds |
saleiferis | 0:89ec48e52250 | 207 | while (t.read() - startTime < 100) |
saleiferis | 0:89ec48e52250 | 208 | { |
saleiferis | 0:89ec48e52250 | 209 | uint8_t response = readRegister8(_i2caddr, MAX86150_SYSCONTROL); |
saleiferis | 0:89ec48e52250 | 210 | if ((response & MAX86150_RESET) == 0) break; //We're done! |
saleiferis | 0:89ec48e52250 | 211 | wait_ms(1); //Let's not over burden the I2C bus |
saleiferis | 0:89ec48e52250 | 212 | } |
saleiferis | 0:89ec48e52250 | 213 | } |
saleiferis | 0:89ec48e52250 | 214 | |
saleiferis | 0:89ec48e52250 | 215 | void MAX86150::shutDown(void) { |
saleiferis | 0:89ec48e52250 | 216 | // Put IC into low power mode (datasheet pg. 19) |
saleiferis | 0:89ec48e52250 | 217 | // During shutdown the IC will continue to respond to I2C commands but will |
saleiferis | 0:89ec48e52250 | 218 | // not update with or take new readings (such as temperature) |
saleiferis | 0:89ec48e52250 | 219 | bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_SHUTDOWN); |
saleiferis | 0:89ec48e52250 | 220 | } |
saleiferis | 0:89ec48e52250 | 221 | |
saleiferis | 0:89ec48e52250 | 222 | void MAX86150::wakeUp(void) { |
saleiferis | 0:89ec48e52250 | 223 | // Pull IC out of low power mode (datasheet pg. 19) |
saleiferis | 0:89ec48e52250 | 224 | bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_WAKEUP); |
saleiferis | 0:89ec48e52250 | 225 | } |
saleiferis | 0:89ec48e52250 | 226 | |
saleiferis | 0:89ec48e52250 | 227 | void MAX86150::setLEDMode(uint8_t mode) { |
saleiferis | 0:89ec48e52250 | 228 | // Set which LEDs are used for sampling -- Red only, RED+IR only, or custom. |
saleiferis | 0:89ec48e52250 | 229 | // See datasheet, page 19 |
saleiferis | 0:89ec48e52250 | 230 | //bitMask(MAX86150_PPGCONFIG1, MAX86150_MODE_MASK, mode); |
saleiferis | 0:89ec48e52250 | 231 | } |
saleiferis | 0:89ec48e52250 | 232 | |
saleiferis | 0:89ec48e52250 | 233 | void MAX86150::setADCRange(uint8_t adcRange) { |
saleiferis | 0:89ec48e52250 | 234 | // adcRange: one of MAX86150_ADCRANGE_2048, _4096, _8192, _16384 |
saleiferis | 0:89ec48e52250 | 235 | //bitMask(MAX86150_PARTICLECONFIG, MAX86150_ADCRANGE_MASK, adcRange); |
saleiferis | 0:89ec48e52250 | 236 | } |
saleiferis | 0:89ec48e52250 | 237 | |
saleiferis | 0:89ec48e52250 | 238 | void MAX86150::setSampleRate(uint8_t sampleRate) { |
saleiferis | 0:89ec48e52250 | 239 | // sampleRate: one of MAX86150_SAMPLERATE_50, _100, _200, _400, _800, _1000, _1600, _3200 |
saleiferis | 0:89ec48e52250 | 240 | //bitMask(MAX86150_PARTICLECONFIG, MAX86150_SAMPLERATE_MASK, sampleRate); |
saleiferis | 0:89ec48e52250 | 241 | } |
saleiferis | 0:89ec48e52250 | 242 | |
saleiferis | 0:89ec48e52250 | 243 | void MAX86150::setPulseWidth(uint8_t pulseWidth) { |
saleiferis | 0:89ec48e52250 | 244 | // pulseWidth: one of MAX86150_PULSEWIDTH_69, _188, _215, _411 |
saleiferis | 0:89ec48e52250 | 245 | bitMask(MAX86150_PPGCONFIG1, MAX86150_PULSEWIDTH_MASK, pulseWidth); |
saleiferis | 0:89ec48e52250 | 246 | } |
saleiferis | 0:89ec48e52250 | 247 | |
saleiferis | 0:89ec48e52250 | 248 | // NOTE: Amplitude values: 0x00 = 0mA, 0x7F = 25.4mA, 0xFF = 50mA (typical) |
saleiferis | 0:89ec48e52250 | 249 | // See datasheet, page 21 |
saleiferis | 0:89ec48e52250 | 250 | void MAX86150::setPulseAmplitudeRed(uint8_t amplitude) |
saleiferis | 0:89ec48e52250 | 251 | { |
saleiferis | 0:89ec48e52250 | 252 | writeRegister8(_i2caddr, MAX86150_LED2_PULSEAMP, amplitude); |
saleiferis | 0:89ec48e52250 | 253 | } |
saleiferis | 0:89ec48e52250 | 254 | |
saleiferis | 0:89ec48e52250 | 255 | void MAX86150::setPulseAmplitudeIR(uint8_t amplitude) |
saleiferis | 0:89ec48e52250 | 256 | { |
saleiferis | 0:89ec48e52250 | 257 | writeRegister8(_i2caddr, MAX86150_LED1_PULSEAMP, amplitude); |
saleiferis | 0:89ec48e52250 | 258 | } |
saleiferis | 0:89ec48e52250 | 259 | |
saleiferis | 0:89ec48e52250 | 260 | void MAX86150::setPulseAmplitudeProximity(uint8_t amplitude) { |
saleiferis | 0:89ec48e52250 | 261 | writeRegister8(_i2caddr, MAX86150_LED_PROX_AMP, amplitude); |
saleiferis | 0:89ec48e52250 | 262 | } |
saleiferis | 0:89ec48e52250 | 263 | |
saleiferis | 0:89ec48e52250 | 264 | void MAX86150::setProximityThreshold(uint8_t threshMSB) |
saleiferis | 0:89ec48e52250 | 265 | { |
saleiferis | 0:89ec48e52250 | 266 | // The threshMSB signifies only the 8 most significant-bits of the ADC count. |
saleiferis | 0:89ec48e52250 | 267 | writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, threshMSB); |
saleiferis | 0:89ec48e52250 | 268 | } |
saleiferis | 0:89ec48e52250 | 269 | |
saleiferis | 0:89ec48e52250 | 270 | //Given a slot number assign a thing to it |
saleiferis | 0:89ec48e52250 | 271 | //Devices are SLOT_RED_LED or SLOT_RED_PILOT (proximity) |
saleiferis | 0:89ec48e52250 | 272 | //Assigning a SLOT_RED_LED will pulse LED |
saleiferis | 0:89ec48e52250 | 273 | //Assigning a SLOT_RED_PILOT will ?? |
saleiferis | 0:89ec48e52250 | 274 | void MAX86150::enableSlot(uint8_t slotNumber, uint8_t device) |
saleiferis | 0:89ec48e52250 | 275 | { |
saleiferis | 0:89ec48e52250 | 276 | uint8_t originalContents; |
saleiferis | 0:89ec48e52250 | 277 | |
saleiferis | 0:89ec48e52250 | 278 | switch (slotNumber) { |
saleiferis | 0:89ec48e52250 | 279 | case (1): |
saleiferis | 0:89ec48e52250 | 280 | bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT1_MASK, device); |
saleiferis | 0:89ec48e52250 | 281 | break; |
saleiferis | 0:89ec48e52250 | 282 | case (2): |
saleiferis | 0:89ec48e52250 | 283 | bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT2_MASK, device << 4); |
saleiferis | 0:89ec48e52250 | 284 | break; |
saleiferis | 0:89ec48e52250 | 285 | case (3): |
saleiferis | 0:89ec48e52250 | 286 | bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT3_MASK, device); |
saleiferis | 0:89ec48e52250 | 287 | break; |
saleiferis | 0:89ec48e52250 | 288 | case (4): |
saleiferis | 0:89ec48e52250 | 289 | bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT4_MASK, device << 4); |
saleiferis | 0:89ec48e52250 | 290 | break; |
saleiferis | 0:89ec48e52250 | 291 | default: |
saleiferis | 0:89ec48e52250 | 292 | //Shouldn't be here! |
saleiferis | 0:89ec48e52250 | 293 | break; |
saleiferis | 0:89ec48e52250 | 294 | } |
saleiferis | 0:89ec48e52250 | 295 | } |
saleiferis | 0:89ec48e52250 | 296 | |
saleiferis | 0:89ec48e52250 | 297 | //Clears all slot assignments |
saleiferis | 0:89ec48e52250 | 298 | void MAX86150::disableSlots(void) |
saleiferis | 0:89ec48e52250 | 299 | { |
saleiferis | 0:89ec48e52250 | 300 | writeRegister8(_i2caddr, MAX86150_FIFOCONTROL1, 0); |
saleiferis | 0:89ec48e52250 | 301 | writeRegister8(_i2caddr, MAX86150_FIFOCONTROL2, 0); |
saleiferis | 0:89ec48e52250 | 302 | } |
saleiferis | 0:89ec48e52250 | 303 | |
saleiferis | 0:89ec48e52250 | 304 | // |
saleiferis | 0:89ec48e52250 | 305 | // FIFO Configuration |
saleiferis | 0:89ec48e52250 | 306 | // |
saleiferis | 0:89ec48e52250 | 307 | |
saleiferis | 0:89ec48e52250 | 308 | void MAX86150::setFIFOAverage(uint8_t numberOfSamples) |
saleiferis | 0:89ec48e52250 | 309 | { |
saleiferis | 0:89ec48e52250 | 310 | bitMask(MAX86150_FIFOCONFIG, MAX86150_SAMPLEAVG_MASK, numberOfSamples); |
saleiferis | 0:89ec48e52250 | 311 | } |
saleiferis | 0:89ec48e52250 | 312 | |
saleiferis | 0:89ec48e52250 | 313 | //Resets all points to start in a known state |
saleiferis | 0:89ec48e52250 | 314 | void MAX86150::clearFIFO(void) { |
saleiferis | 0:89ec48e52250 | 315 | writeRegister8(_i2caddr, MAX86150_FIFOWRITEPTR, 0); |
saleiferis | 0:89ec48e52250 | 316 | writeRegister8(_i2caddr, MAX86150_FIFOOVERFLOW, 0); |
saleiferis | 0:89ec48e52250 | 317 | writeRegister8(_i2caddr, MAX86150_FIFOREADPTR, 0); |
saleiferis | 0:89ec48e52250 | 318 | } |
saleiferis | 0:89ec48e52250 | 319 | |
saleiferis | 0:89ec48e52250 | 320 | //Enable roll over if FIFO over flows |
saleiferis | 0:89ec48e52250 | 321 | void MAX86150::enableFIFORollover(void) { |
saleiferis | 0:89ec48e52250 | 322 | bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_ENABLE); |
saleiferis | 0:89ec48e52250 | 323 | } |
saleiferis | 0:89ec48e52250 | 324 | |
saleiferis | 0:89ec48e52250 | 325 | //Disable roll over if FIFO over flows |
saleiferis | 0:89ec48e52250 | 326 | void MAX86150::disableFIFORollover(void) { |
saleiferis | 0:89ec48e52250 | 327 | bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_DISABLE); |
saleiferis | 0:89ec48e52250 | 328 | } |
saleiferis | 0:89ec48e52250 | 329 | |
saleiferis | 0:89ec48e52250 | 330 | //Power on default is 32 samples |
saleiferis | 0:89ec48e52250 | 331 | //Note it is reverse: 0x00 is 32 samples, 0x0F is 17 samples |
saleiferis | 0:89ec48e52250 | 332 | void MAX86150::setFIFOAlmostFull(uint8_t numberOfSamples) { |
saleiferis | 0:89ec48e52250 | 333 | bitMask(MAX86150_FIFOCONFIG, MAX86150_A_FULL_MASK, numberOfSamples); |
saleiferis | 0:89ec48e52250 | 334 | } |
saleiferis | 0:89ec48e52250 | 335 | |
saleiferis | 0:89ec48e52250 | 336 | //Read the FIFO Write Pointer |
saleiferis | 0:89ec48e52250 | 337 | uint8_t MAX86150::getWritePointer(void) { |
saleiferis | 0:89ec48e52250 | 338 | return (readRegister8(_i2caddr, MAX86150_FIFOWRITEPTR)); |
saleiferis | 0:89ec48e52250 | 339 | } |
saleiferis | 0:89ec48e52250 | 340 | |
saleiferis | 0:89ec48e52250 | 341 | //Read the FIFO Read Pointer |
saleiferis | 0:89ec48e52250 | 342 | uint8_t MAX86150::getReadPointer(void) { |
saleiferis | 0:89ec48e52250 | 343 | return (readRegister8(_i2caddr, MAX86150_FIFOREADPTR)); |
saleiferis | 0:89ec48e52250 | 344 | } |
saleiferis | 0:89ec48e52250 | 345 | |
saleiferis | 0:89ec48e52250 | 346 | // Set the PROX_INT_THRESHold |
saleiferis | 0:89ec48e52250 | 347 | void MAX86150::setPROXINTTHRESH(uint8_t val) { |
saleiferis | 0:89ec48e52250 | 348 | writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, val); |
saleiferis | 0:89ec48e52250 | 349 | } |
saleiferis | 0:89ec48e52250 | 350 | |
saleiferis | 0:89ec48e52250 | 351 | // |
saleiferis | 0:89ec48e52250 | 352 | // Device ID and Revision |
saleiferis | 0:89ec48e52250 | 353 | // |
saleiferis | 0:89ec48e52250 | 354 | uint8_t MAX86150::readPartID() { |
saleiferis | 0:89ec48e52250 | 355 | return readRegister8(_i2caddr, MAX86150_PARTID); |
saleiferis | 0:89ec48e52250 | 356 | } |
saleiferis | 0:89ec48e52250 | 357 | |
saleiferis | 0:89ec48e52250 | 358 | //Setup the sensor |
saleiferis | 0:89ec48e52250 | 359 | //The MAX86150 has many settings. By default we select: |
saleiferis | 0:89ec48e52250 | 360 | // Sample Average = 4 |
saleiferis | 0:89ec48e52250 | 361 | // Mode = MultiLED |
saleiferis | 0:89ec48e52250 | 362 | // ADC Range = 16384 (62.5pA per LSB) |
saleiferis | 0:89ec48e52250 | 363 | // Sample rate = 50 |
saleiferis | 0:89ec48e52250 | 364 | //Use the default setup if you are just getting started with the MAX86150 sensor |
saleiferis | 0:89ec48e52250 | 365 | void MAX86150::setup(uint8_t powerLevel, uint8_t sampleAverage, uint8_t ledMode, int sampleRate, int pulseWidth, int adcRange) |
saleiferis | 0:89ec48e52250 | 366 | { |
saleiferis | 0:89ec48e52250 | 367 | activeDevices=3; |
saleiferis | 0:89ec48e52250 | 368 | writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x01); //it as 0x01 |
saleiferis | 1:6e6f7e3cc1e1 | 369 | wait_ms(2000); |
saleiferis | 0:89ec48e52250 | 370 | //pc.printf("Just set SYSCONTOL REG: %x\n", readRegister8(_i2caddr,MAX86150_SYSCONTROL)); |
saleiferis | 0:89ec48e52250 | 371 | //delay(100); |
saleiferis | 0:89ec48e52250 | 372 | //wait_ms(100); |
saleiferis | 0:89ec48e52250 | 373 | writeRegister8(_i2caddr,MAX86150_FIFOCONFIG,0x7F); |
saleiferis | 0:89ec48e52250 | 374 | |
saleiferis | 0:89ec48e52250 | 375 | //FIFO Configuration |
saleiferis | 0:89ec48e52250 | 376 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
saleiferis | 0:89ec48e52250 | 377 | //The chip will average multiple samples of same type together if you wish |
saleiferis | 0:89ec48e52250 | 378 | if (sampleAverage == 1) setFIFOAverage(MAX86150_SAMPLEAVG_1); //No averaging per FIFO record |
saleiferis | 0:89ec48e52250 | 379 | else if (sampleAverage == 2) setFIFOAverage(MAX86150_SAMPLEAVG_2); |
saleiferis | 0:89ec48e52250 | 380 | else if (sampleAverage == 4) setFIFOAverage(MAX86150_SAMPLEAVG_4); |
saleiferis | 0:89ec48e52250 | 381 | else if (sampleAverage == 8) setFIFOAverage(MAX86150_SAMPLEAVG_8); |
saleiferis | 0:89ec48e52250 | 382 | else if (sampleAverage == 16) setFIFOAverage(MAX86150_SAMPLEAVG_16); |
saleiferis | 0:89ec48e52250 | 383 | else if (sampleAverage == 32) setFIFOAverage(MAX86150_SAMPLEAVG_32); |
saleiferis | 0:89ec48e52250 | 384 | else setFIFOAverage(MAX86150_SAMPLEAVG_4); |
saleiferis | 0:89ec48e52250 | 385 | |
saleiferis | 0:89ec48e52250 | 386 | uint16_t FIFOCode = 0x00; |
saleiferis | 0:89ec48e52250 | 387 | |
saleiferis | 0:89ec48e52250 | 388 | FIFOCode = FIFOCode<<4 | 0x0009;// : FIFOCode; //insert ECG front of ETI in FIFO |
saleiferis | 0:89ec48e52250 | 389 | FIFOCode = FIFOCode<<8 | 0x0021;//) : FIFOCode; //insert Red(2) and IR (1) in front of ECG in FIFO |
saleiferis | 0:89ec48e52250 | 390 | |
saleiferis | 0:89ec48e52250 | 391 | |
saleiferis | 0:89ec48e52250 | 392 | //FIFO Control 1 = FD2|FD1, FIFO Control 2 = FD4|FD3 |
saleiferis | 0:89ec48e52250 | 393 | |
saleiferis | 0:89ec48e52250 | 394 | writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00100001)); |
saleiferis | 0:89ec48e52250 | 395 | //writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00001001)); |
saleiferis | 0:89ec48e52250 | 396 | writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2,(0b00001001)); |
saleiferis | 0:89ec48e52250 | 397 | //writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2,(0b00000000)); |
saleiferis | 0:89ec48e52250 | 398 | //writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1, (char)(FIFOCode & 0x00FF) ); |
saleiferis | 0:89ec48e52250 | 399 | //writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2, (char)(FIFOCode >>8) ); |
saleiferis | 0:89ec48e52250 | 400 | //pc.printf("Set FIFO_CTRL1: %x\n", readRegister8(_i2caddr, MAX86150_FIFOCONTROL1)); |
saleiferis | 0:89ec48e52250 | 401 | //pc.printf("Set FIFO_CTRL2: %x\n", readRegister8(_i2caddr, MAX86150_FIFOCONTROL2)); |
saleiferis | 0:89ec48e52250 | 402 | |
saleiferis | 0:89ec48e52250 | 403 | writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11010111); |
saleiferis | 0:89ec48e52250 | 404 | writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11100111); |
saleiferis | 0:89ec48e52250 | 405 | |
saleiferis | 0:89ec48e52250 | 406 | writeRegister8(_i2caddr,MAX86150_PPGCONFIG2, 0x01); |
saleiferis | 0:89ec48e52250 | 407 | writeRegister8(_i2caddr,MAX86150_LED_RANGE, 0x00 ); // PPG_ADC_RGE: 32768nA |
saleiferis | 0:89ec48e52250 | 408 | |
saleiferis | 0:89ec48e52250 | 409 | //pc.printf("Before setting, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); |
saleiferis | 0:89ec48e52250 | 410 | //wait_ms(2000); |
saleiferis | 1:6e6f7e3cc1e1 | 411 | writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x04);//start FIFO |
saleiferis | 0:89ec48e52250 | 412 | //wait_ms(1000); |
saleiferis | 0:89ec48e52250 | 413 | //pc.printf("Just set FIFO, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); |
saleiferis | 0:89ec48e52250 | 414 | |
saleiferis | 4:4233f5538abf | 415 | writeRegister8(_i2caddr,MAX86150_ECG_CONFIG1,0b00000011); |
saleiferis | 4:4233f5538abf | 416 | writeRegister8(_i2caddr,MAX86150_ECG_CONFIG3,0b00001111); |
saleiferis | 0:89ec48e52250 | 417 | |
saleiferis | 4:4233f5538abf | 418 | setPulseAmplitudeRed(0x00); |
saleiferis | 4:4233f5538abf | 419 | setPulseAmplitudeIR(0x00); |
saleiferis | 0:89ec48e52250 | 420 | |
saleiferis | 0:89ec48e52250 | 421 | //Multi-LED Mode Configuration, Enable the reading of the three LEDs |
saleiferis | 0:89ec48e52250 | 422 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
saleiferis | 0:89ec48e52250 | 423 | //enableSlot(1, SLOT_RED_LED); |
saleiferis | 0:89ec48e52250 | 424 | //if (ledMode > 1) |
saleiferis | 0:89ec48e52250 | 425 | //enableSlot(2, SLOT_IR_LED); |
saleiferis | 0:89ec48e52250 | 426 | //if (ledMode > 2) |
saleiferis | 0:89ec48e52250 | 427 | //enableSlot(3, SLOT_ECG); |
saleiferis | 0:89ec48e52250 | 428 | //enableSlot(1, SLOT_RED_PILOT); |
saleiferis | 0:89ec48e52250 | 429 | //enableSlot(2, SLOT_IR_PILOT); |
saleiferis | 0:89ec48e52250 | 430 | //enableSlot(3, SLOT_GREEN_PILOT); |
saleiferis | 0:89ec48e52250 | 431 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
saleiferis | 0:89ec48e52250 | 432 | //enableFIFORollover(); |
saleiferis | 0:89ec48e52250 | 433 | clearFIFO(); //Reset the FIFO before we begin checking the sensor |
saleiferis | 0:89ec48e52250 | 434 | writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x04); |
saleiferis | 1:6e6f7e3cc1e1 | 435 | //wait_ms(1); |
saleiferis | 0:89ec48e52250 | 436 | pc.printf("Cleared FIFO, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); |
saleiferis | 0:89ec48e52250 | 437 | } |
saleiferis | 0:89ec48e52250 | 438 | |
saleiferis | 0:89ec48e52250 | 439 | //Tell caller how many samples are available |
saleiferis | 0:89ec48e52250 | 440 | uint8_t MAX86150::available(void) |
saleiferis | 0:89ec48e52250 | 441 | { |
saleiferis | 0:89ec48e52250 | 442 | int8_t numberOfSamples = sense.head - sense.tail; |
saleiferis | 0:89ec48e52250 | 443 | if (numberOfSamples < 0) numberOfSamples += STORAGE_SIZE; |
saleiferis | 0:89ec48e52250 | 444 | |
saleiferis | 0:89ec48e52250 | 445 | return (numberOfSamples); |
saleiferis | 0:89ec48e52250 | 446 | } |
saleiferis | 0:89ec48e52250 | 447 | |
saleiferis | 0:89ec48e52250 | 448 | //Report the most recent red value |
saleiferis | 0:89ec48e52250 | 449 | uint32_t MAX86150::getRed(void) |
saleiferis | 0:89ec48e52250 | 450 | { |
saleiferis | 0:89ec48e52250 | 451 | //Check the sensor for new data for 250ms |
saleiferis | 0:89ec48e52250 | 452 | if(safeCheck(250)) |
saleiferis | 0:89ec48e52250 | 453 | return (sense.red[sense.head]); |
saleiferis | 0:89ec48e52250 | 454 | else |
saleiferis | 0:89ec48e52250 | 455 | return(0); //Sensor failed to find new data |
saleiferis | 0:89ec48e52250 | 456 | } |
saleiferis | 0:89ec48e52250 | 457 | |
saleiferis | 0:89ec48e52250 | 458 | //Report the most recent IR value |
saleiferis | 0:89ec48e52250 | 459 | uint32_t MAX86150::getIR(void) |
saleiferis | 0:89ec48e52250 | 460 | { |
saleiferis | 0:89ec48e52250 | 461 | //Check the sensor for new data for 250ms |
saleiferis | 0:89ec48e52250 | 462 | if(safeCheck(250)) |
saleiferis | 0:89ec48e52250 | 463 | return (sense.IR[sense.head]); |
saleiferis | 0:89ec48e52250 | 464 | else |
saleiferis | 0:89ec48e52250 | 465 | return(0); //Sensor failed to find new data |
saleiferis | 0:89ec48e52250 | 466 | } |
saleiferis | 0:89ec48e52250 | 467 | |
saleiferis | 0:89ec48e52250 | 468 | //Report the most recent Green value |
saleiferis | 0:89ec48e52250 | 469 | int32_t MAX86150::getECG(void) |
saleiferis | 0:89ec48e52250 | 470 | { |
saleiferis | 0:89ec48e52250 | 471 | //Check the sensor for new data for 250ms |
saleiferis | 0:89ec48e52250 | 472 | if(safeCheck(250)) |
saleiferis | 0:89ec48e52250 | 473 | return (sense.ecg[sense.head]); |
saleiferis | 0:89ec48e52250 | 474 | else |
saleiferis | 0:89ec48e52250 | 475 | return(0); //Sensor failed to find new data |
saleiferis | 0:89ec48e52250 | 476 | } |
saleiferis | 0:89ec48e52250 | 477 | |
saleiferis | 0:89ec48e52250 | 478 | //Report the next Red value in the FIFO |
saleiferis | 0:89ec48e52250 | 479 | uint32_t MAX86150::getFIFORed(void) |
saleiferis | 0:89ec48e52250 | 480 | { |
saleiferis | 0:89ec48e52250 | 481 | return (sense.red[sense.tail]); |
saleiferis | 0:89ec48e52250 | 482 | } |
saleiferis | 0:89ec48e52250 | 483 | |
saleiferis | 0:89ec48e52250 | 484 | //Report the next IR value in the FIFO |
saleiferis | 0:89ec48e52250 | 485 | uint32_t MAX86150::getFIFOIR(void) |
saleiferis | 0:89ec48e52250 | 486 | { |
saleiferis | 0:89ec48e52250 | 487 | return (sense.IR[sense.tail]); |
saleiferis | 0:89ec48e52250 | 488 | } |
saleiferis | 0:89ec48e52250 | 489 | |
saleiferis | 0:89ec48e52250 | 490 | //Report the next Green value in the FIFO |
saleiferis | 0:89ec48e52250 | 491 | int32_t MAX86150::getFIFOECG(void) |
saleiferis | 0:89ec48e52250 | 492 | { |
saleiferis | 0:89ec48e52250 | 493 | return (sense.ecg[sense.tail]); |
saleiferis | 0:89ec48e52250 | 494 | } |
saleiferis | 0:89ec48e52250 | 495 | |
saleiferis | 0:89ec48e52250 | 496 | //Advance the tail |
saleiferis | 0:89ec48e52250 | 497 | void MAX86150::nextSample(void) |
saleiferis | 0:89ec48e52250 | 498 | { |
saleiferis | 0:89ec48e52250 | 499 | if(available()) //Only advance the tail if new data is available |
saleiferis | 0:89ec48e52250 | 500 | { |
saleiferis | 0:89ec48e52250 | 501 | sense.tail++; |
saleiferis | 0:89ec48e52250 | 502 | sense.tail %= STORAGE_SIZE; //Wrap condition |
saleiferis | 0:89ec48e52250 | 503 | } |
saleiferis | 0:89ec48e52250 | 504 | } |
saleiferis | 0:89ec48e52250 | 505 | |
saleiferis | 0:89ec48e52250 | 506 | //Polls the sensor for new data |
saleiferis | 0:89ec48e52250 | 507 | //Call regularly |
saleiferis | 0:89ec48e52250 | 508 | //If new data is available, it updates the head and tail in the main struct |
saleiferis | 0:89ec48e52250 | 509 | //Returns number of new samples obtained |
saleiferis | 0:89ec48e52250 | 510 | uint16_t MAX86150::check(void) |
saleiferis | 0:89ec48e52250 | 511 | { |
saleiferis | 0:89ec48e52250 | 512 | //pc.printf("In check() ...\n"); |
saleiferis | 0:89ec48e52250 | 513 | //Read register FIDO_DATA in (3-byte * number of active LED) chunks |
saleiferis | 0:89ec48e52250 | 514 | //Until FIFO_RD_PTR = FIFO_WR_PTR |
saleiferis | 0:89ec48e52250 | 515 | // pc.printf("SYSCONTROL REG: %x\n",readRegister8(_i2caddr, 0x0D)); |
saleiferis | 0:89ec48e52250 | 516 | |
saleiferis | 0:89ec48e52250 | 517 | uint8_t readPointer = getReadPointer(); |
saleiferis | 0:89ec48e52250 | 518 | uint8_t writePointer = getWritePointer(); |
saleiferis | 0:89ec48e52250 | 519 | |
saleiferis | 0:89ec48e52250 | 520 | int numberOfSamples = 0; |
saleiferis | 0:89ec48e52250 | 521 | |
saleiferis | 0:89ec48e52250 | 522 | //Do we have new data? |
saleiferis | 0:89ec48e52250 | 523 | if (readPointer != writePointer) |
saleiferis | 0:89ec48e52250 | 524 | { |
saleiferis | 0:89ec48e52250 | 525 | //pc.printf("Checking for new data...\n"); |
saleiferis | 0:89ec48e52250 | 526 | //Calculate the number of readings we need to get from sensor |
saleiferis | 0:89ec48e52250 | 527 | numberOfSamples = writePointer - readPointer; |
saleiferis | 0:89ec48e52250 | 528 | if (numberOfSamples < 0) numberOfSamples += 32; //Wrap condition |
saleiferis | 0:89ec48e52250 | 529 | //pc.printf("Need to get %d samples\n", numberOfSamples); |
saleiferis | 0:89ec48e52250 | 530 | |
saleiferis | 0:89ec48e52250 | 531 | //We now have the number of readings, now calc bytes to read |
saleiferis | 0:89ec48e52250 | 532 | //For this example we are just doing Red and IR (3 bytes each) |
saleiferis | 0:89ec48e52250 | 533 | int bytesLeftToRead = numberOfSamples * activeDevices * 3; |
saleiferis | 0:89ec48e52250 | 534 | |
saleiferis | 0:89ec48e52250 | 535 | //pc.printf("There are %d bytes to read\n", bytesLeftToRead); |
saleiferis | 0:89ec48e52250 | 536 | |
saleiferis | 0:89ec48e52250 | 537 | //Get ready to read a burst of data from the FIFO register |
saleiferis | 0:89ec48e52250 | 538 | /*_i2cPort->beginTransmission(_i2caddr); |
saleiferis | 0:89ec48e52250 | 539 | _i2cPort->write(MAX86150_FIFODATA); |
saleiferis | 0:89ec48e52250 | 540 | _i2cPort->endTransmission();*/ |
saleiferis | 0:89ec48e52250 | 541 | char command[] = {MAX86150_FIFODATA}; |
saleiferis | 0:89ec48e52250 | 542 | _i2cPort->write(_i2caddr,command, 1); |
saleiferis | 0:89ec48e52250 | 543 | //pc.printf("Sent write cmd to read new data\n"); |
saleiferis | 0:89ec48e52250 | 544 | |
saleiferis | 0:89ec48e52250 | 545 | |
saleiferis | 0:89ec48e52250 | 546 | //We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH |
saleiferis | 0:89ec48e52250 | 547 | //I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno. |
saleiferis | 0:89ec48e52250 | 548 | //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno |
saleiferis | 0:89ec48e52250 | 549 | while (bytesLeftToRead > 0) |
saleiferis | 0:89ec48e52250 | 550 | { |
saleiferis | 0:89ec48e52250 | 551 | int toGet = bytesLeftToRead; |
saleiferis | 0:89ec48e52250 | 552 | if (toGet > I2C_BUFFER_LENGTH) |
saleiferis | 0:89ec48e52250 | 553 | { |
saleiferis | 0:89ec48e52250 | 554 | //If toGet is 32 this is bad because we read 6 bytes (Red+IR * 3 = 6) at a time |
saleiferis | 0:89ec48e52250 | 555 | //32 % 6 = 2 left over. We don't want to request 32 bytes, we want to request 30. |
saleiferis | 0:89ec48e52250 | 556 | //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27. |
saleiferis | 0:89ec48e52250 | 557 | |
saleiferis | 0:89ec48e52250 | 558 | toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeDevices * 3)); //Trim toGet to be a multiple of the samples we need to read |
saleiferis | 0:89ec48e52250 | 559 | } |
saleiferis | 0:89ec48e52250 | 560 | |
saleiferis | 0:89ec48e52250 | 561 | bytesLeftToRead -= toGet; |
saleiferis | 0:89ec48e52250 | 562 | |
saleiferis | 0:89ec48e52250 | 563 | //Request toGet number of bytes from sensor |
saleiferis | 0:89ec48e52250 | 564 | //_i2cPort->requestFrom(_i2caddr, toGet); |
saleiferis | 0:89ec48e52250 | 565 | char data[toGet]; |
saleiferis | 0:89ec48e52250 | 566 | char *p = data; |
saleiferis | 0:89ec48e52250 | 567 | //pc.printf("Before reading FIFO data, toGet = %d\n",toGet); |
saleiferis | 0:89ec48e52250 | 568 | _i2cPort->read(_i2caddr, data, toGet, false); |
saleiferis | 0:89ec48e52250 | 569 | //_i2cPort->stop(); |
saleiferis | 0:89ec48e52250 | 570 | //pc.printf("Read FIFO data\n"); |
saleiferis | 0:89ec48e52250 | 571 | |
saleiferis | 0:89ec48e52250 | 572 | |
saleiferis | 0:89ec48e52250 | 573 | |
saleiferis | 0:89ec48e52250 | 574 | while (toGet > 0) |
saleiferis | 0:89ec48e52250 | 575 | { |
saleiferis | 0:89ec48e52250 | 576 | //pc.printf("In while loop\n\n"); |
saleiferis | 0:89ec48e52250 | 577 | sense.head++; //Advance the head of the storage struct |
saleiferis | 0:89ec48e52250 | 578 | sense.head %= STORAGE_SIZE; //Wrap condition |
saleiferis | 0:89ec48e52250 | 579 | |
saleiferis | 0:89ec48e52250 | 580 | uint8_t temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long |
saleiferis | 0:89ec48e52250 | 581 | uint32_t tempLong; |
saleiferis | 0:89ec48e52250 | 582 | |
saleiferis | 0:89ec48e52250 | 583 | //Burst read three bytes - RED |
saleiferis | 0:89ec48e52250 | 584 | /*temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 585 | temp[2] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 586 | temp[1] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 587 | temp[0] = _i2cPort->read();*/ |
saleiferis | 0:89ec48e52250 | 588 | temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 589 | temp[2] = *p++; |
saleiferis | 0:89ec48e52250 | 590 | temp[1] = *p++; |
saleiferis | 0:89ec48e52250 | 591 | temp[0] = *p++; |
saleiferis | 0:89ec48e52250 | 592 | |
saleiferis | 0:89ec48e52250 | 593 | |
saleiferis | 0:89ec48e52250 | 594 | //Convert array to long |
saleiferis | 0:89ec48e52250 | 595 | memcpy(&tempLong, temp, sizeof(tempLong)); |
saleiferis | 0:89ec48e52250 | 596 | |
saleiferis | 0:89ec48e52250 | 597 | tempLong &= 0x7FFFF; //Zero out all but 18 bits |
saleiferis | 0:89ec48e52250 | 598 | |
saleiferis | 0:89ec48e52250 | 599 | sense.red[sense.head] = tempLong; //Store this reading into the sense array |
saleiferis | 0:89ec48e52250 | 600 | |
saleiferis | 0:89ec48e52250 | 601 | //pc.printf("Stored FIFO data into sense array\n"); |
saleiferis | 0:89ec48e52250 | 602 | |
saleiferis | 0:89ec48e52250 | 603 | if (activeDevices > 1) |
saleiferis | 0:89ec48e52250 | 604 | { |
saleiferis | 0:89ec48e52250 | 605 | //Burst read three more bytes - IR |
saleiferis | 0:89ec48e52250 | 606 | /*temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 607 | temp[2] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 608 | temp[1] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 609 | temp[0] = _i2cPort->read();*/ |
saleiferis | 0:89ec48e52250 | 610 | temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 611 | temp[2] = *p++; |
saleiferis | 0:89ec48e52250 | 612 | temp[1] = *p++; |
saleiferis | 0:89ec48e52250 | 613 | temp[0] = *p++; |
saleiferis | 0:89ec48e52250 | 614 | |
saleiferis | 0:89ec48e52250 | 615 | |
saleiferis | 0:89ec48e52250 | 616 | //Convert array to long |
saleiferis | 0:89ec48e52250 | 617 | memcpy(&tempLong, temp, sizeof(tempLong)); |
saleiferis | 0:89ec48e52250 | 618 | //Serial.println(tempLong); |
saleiferis | 0:89ec48e52250 | 619 | tempLong &= 0x7FFFF; //Zero out all but 18 bits |
saleiferis | 0:89ec48e52250 | 620 | |
saleiferis | 0:89ec48e52250 | 621 | sense.IR[sense.head] = tempLong; |
saleiferis | 0:89ec48e52250 | 622 | } |
saleiferis | 0:89ec48e52250 | 623 | |
saleiferis | 0:89ec48e52250 | 624 | if (activeDevices > 2) |
saleiferis | 0:89ec48e52250 | 625 | { |
saleiferis | 0:89ec48e52250 | 626 | //Burst read three more bytes - ECG |
saleiferis | 0:89ec48e52250 | 627 | int32_t tempLongSigned; |
saleiferis | 0:89ec48e52250 | 628 | |
saleiferis | 0:89ec48e52250 | 629 | /*temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 630 | temp[2] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 631 | temp[1] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 632 | temp[0] = _i2cPort->read(); |
saleiferis | 0:89ec48e52250 | 633 | //Serial.println(tempLong);*/ |
saleiferis | 0:89ec48e52250 | 634 | temp[3] = 0; |
saleiferis | 0:89ec48e52250 | 635 | temp[2] = *p++; |
saleiferis | 0:89ec48e52250 | 636 | temp[1] = *p++; |
saleiferis | 0:89ec48e52250 | 637 | temp[0] = *p++; |
saleiferis | 0:89ec48e52250 | 638 | |
saleiferis | 0:89ec48e52250 | 639 | //Convert array to long |
saleiferis | 0:89ec48e52250 | 640 | memcpy(&tempLongSigned, temp, sizeof(tempLongSigned)); |
saleiferis | 0:89ec48e52250 | 641 | |
saleiferis | 0:89ec48e52250 | 642 | //tempLong &= 0x3FFFF; //Zero out all but 18 bits |
saleiferis | 0:89ec48e52250 | 643 | |
saleiferis | 0:89ec48e52250 | 644 | sense.ecg[sense.head] = tempLongSigned; |
saleiferis | 0:89ec48e52250 | 645 | } |
saleiferis | 0:89ec48e52250 | 646 | |
saleiferis | 0:89ec48e52250 | 647 | toGet -= activeDevices * 3; |
saleiferis | 0:89ec48e52250 | 648 | } |
saleiferis | 0:89ec48e52250 | 649 | } //End while (bytesLeftToRead > 0) |
saleiferis | 0:89ec48e52250 | 650 | } //End readPtr != writePtr |
saleiferis | 0:89ec48e52250 | 651 | return (numberOfSamples); //Let the world know how much new data we found |
saleiferis | 0:89ec48e52250 | 652 | } |
saleiferis | 0:89ec48e52250 | 653 | |
saleiferis | 0:89ec48e52250 | 654 | //Check for new data but give up after a certain amount of time |
saleiferis | 0:89ec48e52250 | 655 | //Returns true if new data was found |
saleiferis | 0:89ec48e52250 | 656 | //Returns false if new data was not found |
saleiferis | 0:89ec48e52250 | 657 | |
saleiferis | 0:89ec48e52250 | 658 | bool MAX86150::safeCheck(uint8_t maxTimeToCheck) |
saleiferis | 0:89ec48e52250 | 659 | { |
saleiferis | 0:89ec48e52250 | 660 | // |
saleiferis | 0:89ec48e52250 | 661 | //pc.printf("In safe checkk\n"); |
saleiferis | 0:89ec48e52250 | 662 | Timer t; |
saleiferis | 0:89ec48e52250 | 663 | t.start(); |
saleiferis | 0:89ec48e52250 | 664 | uint32_t markTime = t.read(); |
saleiferis | 0:89ec48e52250 | 665 | |
saleiferis | 0:89ec48e52250 | 666 | while(1) |
saleiferis | 0:89ec48e52250 | 667 | { |
saleiferis | 0:89ec48e52250 | 668 | if(t.read() - markTime > maxTimeToCheck) return(false); |
saleiferis | 0:89ec48e52250 | 669 | |
saleiferis | 0:89ec48e52250 | 670 | if(check() == true) //We found new data! |
saleiferis | 0:89ec48e52250 | 671 | return(true); |
saleiferis | 0:89ec48e52250 | 672 | |
saleiferis | 0:89ec48e52250 | 673 | wait_ms(1); //TODO: make it 1 again |
saleiferis | 0:89ec48e52250 | 674 | } |
saleiferis | 0:89ec48e52250 | 675 | } |
saleiferis | 0:89ec48e52250 | 676 | |
saleiferis | 0:89ec48e52250 | 677 | //Given a register, read it, mask it, and then set the thing |
saleiferis | 0:89ec48e52250 | 678 | void MAX86150::bitMask(uint8_t reg, uint8_t mask, uint8_t thing) |
saleiferis | 0:89ec48e52250 | 679 | { |
saleiferis | 0:89ec48e52250 | 680 | // Grab current register context |
saleiferis | 0:89ec48e52250 | 681 | uint8_t originalContents = readRegister8(_i2caddr, reg); |
saleiferis | 0:89ec48e52250 | 682 | |
saleiferis | 0:89ec48e52250 | 683 | // Zero-out the portions of the register we're interested in |
saleiferis | 0:89ec48e52250 | 684 | originalContents = originalContents & mask; |
saleiferis | 0:89ec48e52250 | 685 | |
saleiferis | 0:89ec48e52250 | 686 | // Change contents |
saleiferis | 0:89ec48e52250 | 687 | writeRegister8(_i2caddr, reg, originalContents | thing); |
saleiferis | 0:89ec48e52250 | 688 | } |
saleiferis | 0:89ec48e52250 | 689 | |
saleiferis | 0:89ec48e52250 | 690 | uint8_t MAX86150::readRegister8(uint8_t address, uint8_t reg) { |
saleiferis | 0:89ec48e52250 | 691 | |
saleiferis | 0:89ec48e52250 | 692 | /* |
saleiferis | 0:89ec48e52250 | 693 | uint8_t tempData = 0; |
saleiferis | 0:89ec48e52250 | 694 | _i2cPort->beginTransmission(address); |
saleiferis | 0:89ec48e52250 | 695 | _i2cPort->write(reg); |
saleiferis | 0:89ec48e52250 | 696 | _i2cPort->endTransmission(false); |
saleiferis | 0:89ec48e52250 | 697 | |
saleiferis | 0:89ec48e52250 | 698 | _i2cPort->requestFrom((uint8_t)address, (uint8_t)1); // Request 1 byte |
saleiferis | 0:89ec48e52250 | 699 | if (_i2cPort->available()) |
saleiferis | 0:89ec48e52250 | 700 | { |
saleiferis | 0:89ec48e52250 | 701 | |
saleiferis | 0:89ec48e52250 | 702 | return(_i2cPort->read()); |
saleiferis | 0:89ec48e52250 | 703 | } |
saleiferis | 0:89ec48e52250 | 704 | return (0); //Fail |
saleiferis | 0:89ec48e52250 | 705 | */ |
saleiferis | 0:89ec48e52250 | 706 | int suc = 0; |
saleiferis | 0:89ec48e52250 | 707 | char regData; |
saleiferis | 0:89ec48e52250 | 708 | char writeData = reg; |
saleiferis | 0:89ec48e52250 | 709 | _i2cPort->write(address,&writeData,1); //true is for repeated start |
saleiferis | 0:89ec48e52250 | 710 | suc = _i2cPort->read(address,®Data,1); |
saleiferis | 0:89ec48e52250 | 711 | //pc.printf("REad in lib was %d",suc); |
saleiferis | 0:89ec48e52250 | 712 | return regData; |
saleiferis | 0:89ec48e52250 | 713 | |
saleiferis | 0:89ec48e52250 | 714 | } |
saleiferis | 0:89ec48e52250 | 715 | |
saleiferis | 0:89ec48e52250 | 716 | void MAX86150::writeRegister8(uint8_t address, uint8_t reg, uint8_t value) { |
saleiferis | 0:89ec48e52250 | 717 | |
saleiferis | 0:89ec48e52250 | 718 | /* |
saleiferis | 0:89ec48e52250 | 719 | _i2cPort->beginTransmission(address); |
saleiferis | 0:89ec48e52250 | 720 | _i2cPort->write(reg); |
saleiferis | 0:89ec48e52250 | 721 | _i2cPort->write(value); |
saleiferis | 0:89ec48e52250 | 722 | _i2cPort->endTransmission(); |
saleiferis | 0:89ec48e52250 | 723 | */ |
saleiferis | 0:89ec48e52250 | 724 | |
saleiferis | 0:89ec48e52250 | 725 | //i2c.write(address, reg, 1); |
saleiferis | 0:89ec48e52250 | 726 | /*writes 1 byte to a single register*/ |
saleiferis | 0:89ec48e52250 | 727 | char writeData[2]; |
saleiferis | 0:89ec48e52250 | 728 | writeData[0] = reg ; |
saleiferis | 0:89ec48e52250 | 729 | writeData[1] = value; |
saleiferis | 0:89ec48e52250 | 730 | _i2cPort->write(address,writeData, 2); |
saleiferis | 0:89ec48e52250 | 731 | |
saleiferis | 0:89ec48e52250 | 732 | } |