Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: max32630fthr USBDevice
max86150.cpp
00001 /*************************************************** 00002 Arduino library written for the Maxim MAX86150 ECG and PPG integrated sensor 00003 00004 Written by Ashwin Whitchurch, ProtoCentral Electronics (www.protocentral.com) 00005 00006 Based on code written by Peter Jansen and Nathan Seidle (SparkFun) for the MAX30105 sensor 00007 BSD license, all text above must be included in any redistribution. 00008 *****************************************************/ 00009 00010 #include "max86150.h" 00011 00012 00013 static const uint8_t MAX86150_INTSTAT1 = 0x00; 00014 static const uint8_t MAX86150_INTSTAT2 = 0x01; 00015 static const uint8_t MAX86150_INTENABLE1 = 0x02; 00016 static const uint8_t MAX86150_INTENABLE2 = 0x03; 00017 00018 static const uint8_t MAX86150_FIFOWRITEPTR = 0x04; 00019 static const uint8_t MAX86150_FIFOOVERFLOW = 0x05; 00020 static const uint8_t MAX86150_FIFOREADPTR = 0x06; 00021 static const uint8_t MAX86150_FIFODATA = 0x07; 00022 00023 static const uint8_t MAX86150_FIFOCONFIG = 0x08; 00024 static const uint8_t MAX86150_FIFOCONTROL1= 0x09; 00025 static const uint8_t MAX86150_FIFOCONTROL2 = 0x0A; 00026 00027 static const uint8_t MAX86150_SYSCONTROL = 0x0D; 00028 static const uint8_t MAX86150_PPGCONFIG1 = 0x0E; 00029 static const uint8_t MAX86150_PPGCONFIG2 = 0x0F; 00030 static const uint8_t MAX86150_LED_PROX_AMP = 0x10; 00031 00032 static const uint8_t MAX86150_LED1_PULSEAMP = 0x11; 00033 static const uint8_t MAX86150_LED2_PULSEAMP = 0x12; 00034 static const uint8_t MAX86150_LED_RANGE = 0x14; 00035 static const uint8_t MAX86150_LED_PILOT_PA = 0x15; 00036 00037 static const uint8_t MAX86150_ECG_CONFIG1 = 0x3C; 00038 static const uint8_t MAX86150_ECG_CONFIG3 = 0x3E; 00039 static const uint8_t MAX86150_PROXINTTHRESH = 0x10; 00040 00041 static const uint8_t MAX86150_PARTID = 0xFF; 00042 00043 // MAX86150 Commands 00044 static const uint8_t MAX86150_INT_A_FULL_MASK = (uint8_t)~0b10000000; 00045 static const uint8_t MAX86150_INT_A_FULL_ENABLE = 0x80; 00046 static const uint8_t MAX86150_INT_A_FULL_DISABLE = 0x00; 00047 00048 static const uint8_t MAX86150_INT_DATA_RDY_MASK = (uint8_t)~0b01000000; 00049 static const uint8_t MAX86150_INT_DATA_RDY_ENABLE = 0x40; 00050 static const uint8_t MAX86150_INT_DATA_RDY_DISABLE = 0x00; 00051 00052 static const uint8_t MAX86150_INT_ALC_OVF_MASK = (uint8_t)~0b00100000; 00053 static const uint8_t MAX86150_INT_ALC_OVF_ENABLE = 0x20; 00054 static const uint8_t MAX86150_INT_ALC_OVF_DISABLE = 0x00; 00055 00056 static const uint8_t MAX86150_INT_PROX_INT_MASK = (uint8_t)~0b00010000; 00057 static const uint8_t MAX86150_INT_PROX_INT_ENABLE = 0x10; 00058 static const uint8_t MAX86150_INT_PROX_INT_DISABLE = 0x00; 00059 00060 static const uint8_t MAX86150_SAMPLEAVG_MASK = (uint8_t)~0b11100000; 00061 static const uint8_t MAX86150_SAMPLEAVG_1 = 0x00; 00062 static const uint8_t MAX86150_SAMPLEAVG_2 = 0x20; 00063 static const uint8_t MAX86150_SAMPLEAVG_4 = 0x40; 00064 static const uint8_t MAX86150_SAMPLEAVG_8 = 0x60; 00065 static const uint8_t MAX86150_SAMPLEAVG_16 = 0x80; 00066 static const uint8_t MAX86150_SAMPLEAVG_32 = 0xA0; 00067 00068 static const uint8_t MAX86150_ROLLOVER_MASK = 0xEF; 00069 static const uint8_t MAX86150_ROLLOVER_ENABLE = 0x10; 00070 static const uint8_t MAX86150_ROLLOVER_DISABLE = 0x00; 00071 00072 static const uint8_t MAX86150_A_FULL_MASK = 0xF0; 00073 00074 static const uint8_t MAX86150_SHUTDOWN_MASK = 0x7F; 00075 static const uint8_t MAX86150_SHUTDOWN = 0x80; 00076 static const uint8_t MAX86150_WAKEUP = 0x00; 00077 00078 static const uint8_t MAX86150_RESET_MASK = 0xFE; 00079 static const uint8_t MAX86150_RESET = 0x01; 00080 00081 static const uint8_t MAX86150_MODE_MASK = 0xF8; 00082 static const uint8_t MAX86150_MODE_REDONLY = 0x02; 00083 static const uint8_t MAX86150_MODE_REDIRONLY = 0x03; 00084 static const uint8_t MAX86150_MODE_MULTILED = 0x07; 00085 00086 static const uint8_t MAX86150_ADCRANGE_MASK = 0x9F; 00087 static const uint8_t MAX86150_ADCRANGE_2048 = 0x00; 00088 static const uint8_t MAX86150_ADCRANGE_4096 = 0x20; 00089 static const uint8_t MAX86150_ADCRANGE_8192 = 0x40; 00090 static const uint8_t MAX86150_ADCRANGE_16384 = 0x60; 00091 00092 static const uint8_t MAX86150_SAMPLERATE_MASK = 0xE3; 00093 static const uint8_t MAX86150_SAMPLERATE_50 = 0x00; 00094 static const uint8_t MAX86150_SAMPLERATE_100 = 0x04; 00095 static const uint8_t MAX86150_SAMPLERATE_200 = 0x08; 00096 static const uint8_t MAX86150_SAMPLERATE_400 = 0x0C; 00097 static const uint8_t MAX86150_SAMPLERATE_800 = 0x10; 00098 static const uint8_t MAX86150_SAMPLERATE_1000 = 0x14; 00099 static const uint8_t MAX86150_SAMPLERATE_1600 = 0x18; 00100 static const uint8_t MAX86150_SAMPLERATE_3200 = 0x1C; 00101 00102 static const uint8_t MAX86150_PULSEWIDTH_MASK = 0xFC; 00103 static const uint8_t MAX86150_PULSEWIDTH_69 = 0x00; 00104 static const uint8_t MAX86150_PULSEWIDTH_118 = 0x01; 00105 static const uint8_t MAX86150_PULSEWIDTH_215 = 0x02; 00106 static const uint8_t MAX86150_PULSEWIDTH_411 = 0x03; 00107 00108 static const uint8_t MAX86150_SLOT1_MASK = 0xF0; 00109 static const uint8_t MAX86150_SLOT2_MASK = 0x0F; 00110 static const uint8_t MAX86150_SLOT3_MASK = 0xF0; 00111 static const uint8_t MAX86150_SLOT4_MASK = 0x0F; 00112 00113 static const uint8_t SLOT_NONE = 0x00; 00114 static const uint8_t SLOT_RED_LED = 0x01; 00115 static const uint8_t SLOT_IR_LED = 0x02; 00116 static const uint8_t SLOT_RED_PILOT = 0x09; 00117 static const uint8_t SLOT_IR_PILOT = 0x0A; 00118 static const uint8_t SLOT_ECG = 0x0D; 00119 00120 static const uint8_t MAX_30105_EXPECTEDPARTID = 0x1E; 00121 //static const uint8_t MAX_30105_EXPECTEDPARTID = 0x00; 00122 00123 extern Serial pc; 00124 00125 MAX86150::MAX86150() { 00126 // Constructor 00127 } 00128 00129 //boolean MAX86150::begin(TwoWire &wirePort, uint32_t i2cSpeed, uint8_t i2caddr) 00130 bool MAX86150::begin(I2C &wirePort, uint32_t i2cSpeed, uint8_t i2caddr) 00131 { 00132 00133 _i2cPort = &wirePort; 00134 _i2cPort->frequency(i2cSpeed); 00135 _i2caddr = i2caddr; 00136 /* 00137 // Step 1: Initial Communication and Verification 00138 // Check that a MAX86150 is connected 00139 //Serial.println(readPartID()); 00140 //Serial.println(MAX_30105_EXPECTEDPARTID); 00141 if (readPartID() != MAX_30105_EXPECTEDPARTID) { 00142 // Error -- Part ID read from MAX86150 does not match expected part ID. 00143 // This may mean there is a physical connectivity problem (broken wire, unpowered, etc). 00144 return false; 00145 } 00146 return true;*/ 00147 00148 00149 00150 return true; 00151 00152 00153 } 00154 00155 // 00156 // Configuration 00157 // 00158 00159 //Begin Interrupt configuration 00160 uint8_t MAX86150::getINT1(void) 00161 { 00162 return (readRegister8(_i2caddr, MAX86150_INTSTAT1)); 00163 } 00164 uint8_t MAX86150::getINT2(void) { 00165 return (readRegister8(_i2caddr, MAX86150_INTSTAT2)); 00166 } 00167 00168 void MAX86150::enableAFULL(void) { 00169 bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_ENABLE); 00170 } 00171 void MAX86150::disableAFULL(void) { 00172 bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_DISABLE); 00173 } 00174 00175 void MAX86150::enableDATARDY(void) { 00176 bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_ENABLE); 00177 } 00178 void MAX86150::disableDATARDY(void) { 00179 bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_DISABLE); 00180 } 00181 00182 void MAX86150::enableALCOVF(void) { 00183 bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_ENABLE); 00184 } 00185 void MAX86150::disableALCOVF(void) { 00186 bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_DISABLE); 00187 } 00188 00189 void MAX86150::enablePROXINT(void) { 00190 bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_ENABLE); 00191 } 00192 void MAX86150::disablePROXINT(void) { 00193 bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_DISABLE); 00194 } 00195 //End Interrupt configuration 00196 00197 void MAX86150::softReset(void) { 00198 00199 Timer t; 00200 t.start(); 00201 bitMask(MAX86150_SYSCONTROL, MAX86150_RESET_MASK, MAX86150_RESET); 00202 00203 // Poll for bit to clear, reset is then complete 00204 // Timeout after 100ms 00205 00206 unsigned long startTime = t.read(); //TODO: double check t.read() returns milliseconds 00207 while (t.read() - startTime < 100) 00208 { 00209 uint8_t response = readRegister8(_i2caddr, MAX86150_SYSCONTROL); 00210 if ((response & MAX86150_RESET) == 0) break; //We're done! 00211 wait_ms(1); //Let's not over burden the I2C bus 00212 } 00213 } 00214 00215 void MAX86150::shutDown(void) { 00216 // Put IC into low power mode (datasheet pg. 19) 00217 // During shutdown the IC will continue to respond to I2C commands but will 00218 // not update with or take new readings (such as temperature) 00219 bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_SHUTDOWN); 00220 } 00221 00222 void MAX86150::wakeUp(void) { 00223 // Pull IC out of low power mode (datasheet pg. 19) 00224 bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_WAKEUP); 00225 } 00226 00227 void MAX86150::setLEDMode(uint8_t mode) { 00228 // Set which LEDs are used for sampling -- Red only, RED+IR only, or custom. 00229 // See datasheet, page 19 00230 //bitMask(MAX86150_PPGCONFIG1, MAX86150_MODE_MASK, mode); 00231 } 00232 00233 void MAX86150::setADCRange(uint8_t adcRange) { 00234 // adcRange: one of MAX86150_ADCRANGE_2048, _4096, _8192, _16384 00235 //bitMask(MAX86150_PARTICLECONFIG, MAX86150_ADCRANGE_MASK, adcRange); 00236 } 00237 00238 void MAX86150::setSampleRate(uint8_t sampleRate) { 00239 // sampleRate: one of MAX86150_SAMPLERATE_50, _100, _200, _400, _800, _1000, _1600, _3200 00240 //bitMask(MAX86150_PARTICLECONFIG, MAX86150_SAMPLERATE_MASK, sampleRate); 00241 } 00242 00243 void MAX86150::setPulseWidth(uint8_t pulseWidth) { 00244 // pulseWidth: one of MAX86150_PULSEWIDTH_69, _188, _215, _411 00245 bitMask(MAX86150_PPGCONFIG1, MAX86150_PULSEWIDTH_MASK, pulseWidth); 00246 } 00247 00248 // NOTE: Amplitude values: 0x00 = 0mA, 0x7F = 25.4mA, 0xFF = 50mA (typical) 00249 // See datasheet, page 21 00250 void MAX86150::setPulseAmplitudeRed(uint8_t amplitude) 00251 { 00252 writeRegister8(_i2caddr, MAX86150_LED2_PULSEAMP, amplitude); 00253 } 00254 00255 void MAX86150::setPulseAmplitudeIR(uint8_t amplitude) 00256 { 00257 writeRegister8(_i2caddr, MAX86150_LED1_PULSEAMP, amplitude); 00258 } 00259 00260 void MAX86150::setPulseAmplitudeProximity(uint8_t amplitude) { 00261 writeRegister8(_i2caddr, MAX86150_LED_PILOT_PA, amplitude); 00262 } 00263 00264 void MAX86150::setProximityThreshold(uint8_t threshMSB) 00265 { 00266 // The threshMSB signifies only the 8 most significant-bits of the ADC count. 00267 writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, threshMSB); 00268 } 00269 00270 //Given a slot number assign a thing to it 00271 //Devices are SLOT_RED_LED or SLOT_RED_PILOT (proximity) 00272 //Assigning a SLOT_RED_LED will pulse LED 00273 //Assigning a SLOT_RED_PILOT will ?? 00274 void MAX86150::enableSlot(uint8_t slotNumber, uint8_t device) 00275 { 00276 uint8_t originalContents; 00277 00278 switch (slotNumber) { 00279 case (1): 00280 bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT1_MASK, device); 00281 break; 00282 case (2): 00283 bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT2_MASK, device << 4); 00284 break; 00285 case (3): 00286 bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT3_MASK, device); 00287 break; 00288 case (4): 00289 bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT4_MASK, device << 4); 00290 break; 00291 default: 00292 //Shouldn't be here! 00293 break; 00294 } 00295 } 00296 00297 //Clears all slot assignments 00298 void MAX86150::disableSlots(void) 00299 { 00300 writeRegister8(_i2caddr, MAX86150_FIFOCONTROL1, 0); 00301 writeRegister8(_i2caddr, MAX86150_FIFOCONTROL2, 0); 00302 } 00303 00304 // 00305 // FIFO Configuration 00306 // 00307 00308 void MAX86150::setFIFOAverage(uint8_t numberOfSamples) 00309 { 00310 bitMask(MAX86150_FIFOCONFIG, MAX86150_SAMPLEAVG_MASK, numberOfSamples); 00311 } 00312 00313 //Resets all points to start in a known state 00314 void MAX86150::clearFIFO(void) { 00315 writeRegister8(_i2caddr, MAX86150_FIFOWRITEPTR, 0); 00316 writeRegister8(_i2caddr, MAX86150_FIFOOVERFLOW, 0); 00317 writeRegister8(_i2caddr, MAX86150_FIFOREADPTR, 0); 00318 } 00319 00320 //Enable roll over if FIFO over flows 00321 void MAX86150::enableFIFORollover(void) { 00322 bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_ENABLE); 00323 } 00324 00325 //Disable roll over if FIFO over flows 00326 void MAX86150::disableFIFORollover(void) { 00327 bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_DISABLE); 00328 } 00329 00330 //Power on default is 32 samples 00331 //Note it is reverse: 0x00 is 32 samples, 0x0F is 17 samples 00332 void MAX86150::setFIFOAlmostFull(uint8_t numberOfSamples) { 00333 bitMask(MAX86150_FIFOCONFIG, MAX86150_A_FULL_MASK, numberOfSamples); 00334 } 00335 00336 //Read the FIFO Write Pointer 00337 uint8_t MAX86150::getWritePointer(void) { 00338 return (readRegister8(_i2caddr, MAX86150_FIFOWRITEPTR)); 00339 } 00340 00341 //Read the FIFO Read Pointer 00342 uint8_t MAX86150::getReadPointer(void) { 00343 return (readRegister8(_i2caddr, MAX86150_FIFOREADPTR)); 00344 } 00345 00346 // Set the PROX_INT_THRESHold 00347 void MAX86150::setPROXINTTHRESH(uint8_t val) { 00348 writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, val); 00349 } 00350 00351 // 00352 // Device ID and Revision 00353 // 00354 uint8_t MAX86150::readPartID() { 00355 return readRegister8(_i2caddr, MAX86150_PARTID); 00356 } 00357 00358 //Setup the sensor 00359 //The MAX86150 has many settings. By default we select: 00360 // Sample Average = 4 00361 // Mode = MultiLED 00362 // ADC Range = 16384 (62.5pA per LSB) 00363 // Sample rate = 50 00364 //Use the default setup if you are just getting started with the MAX86150 sensor 00365 void MAX86150::setup(uint8_t powerLevel, uint8_t sampleAverage, uint8_t ledMode, int sampleRate, int pulseWidth, int adcRange) 00366 { 00367 activeDevices=3; 00368 writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x01); //it as 0x01 00369 wait_ms(2); 00370 //pc.printf("Just set SYSCONTOL REG: %x\n", readRegister8(_i2caddr,MAX86150_SYSCONTROL)); 00371 //delay(100); 00372 //wait_ms(100); 00373 00374 00375 // FIFO Config 00376 writeRegister8(_i2caddr,MAX86150_FIFOCONFIG,0b01111111); //first bit is don't care 00377 //FIFO CONTROL 00378 writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00100001)); 00379 writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2,(0b00001001)); 00380 00381 00382 00383 //pc.printf("Set FIFO_CTRL1: %x\n", readRegister8(_i2caddr, MAX86150_FIFOCONTROL1)); 00384 //pc.printf("Set FIFO_CTRL2: %x\n", readRegister8(_i2caddr, MAX86150_FIFOCONTROL2)); 00385 // PPG CONFIG 00386 writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11010110); 00387 //writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11100111); 00388 writeRegister8(_i2caddr,MAX86150_PPGCONFIG2, 0x00); 00389 writeRegister8(_i2caddr,MAX86150_LED_RANGE, 0b00000101 ); // PPG_ADC_RGE: 32768nA 00390 writeRegister8(_i2caddr,0x12, 0xFF ); 00391 writeRegister8(_i2caddr,0x11, 0xFF ); 00392 //enablePROXINT(); 00393 //setProximityThreshold(0x05); 00394 //setPulseAmplitudeProximity(0xFF); 00395 setPulseAmplitudeRed(0x1F); 00396 setPulseAmplitudeIR(0x1F); 00397 00398 //pc.printf("Before setting, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); 00399 //wait_ms(2000); 00400 // SYSCONTROL 00401 //writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x04);//start FIFO 00402 //wait_ms(1000); 00403 //pc.printf("Just set FIFO, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); 00404 00405 00406 00407 // ECG CONFIG 00408 writeRegister8(_i2caddr,MAX86150_ECG_CONFIG1,0b00000011); 00409 writeRegister8(_i2caddr,MAX86150_ECG_CONFIG3,0b00001111); 00410 00411 //setPulseAmplitudeRed(0x00); 00412 //setPulseAmplitudeIR(0x00); 00413 00414 //Enable Interrupt 00415 writeRegister8(_i2caddr,MAX86150_INTENABLE1,0b00000000); 00416 writeRegister8(_i2caddr,MAX86150_INTENABLE2,0b00000100); 00417 //clearFIFO(); //Reset the FIFO before we begin checking the sensor 00418 //writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x04); 00419 //wait_ms(1); 00420 pc.printf("Cleared FIFO, SYS CTRL REG: %x\n",readRegister8(_i2caddr,MAX86150_SYSCONTROL)); 00421 } 00422 00423 //Tell caller how many samples are available 00424 uint8_t MAX86150::available(void) 00425 { 00426 int8_t numberOfSamples = sense.head - sense.tail; 00427 if (numberOfSamples < 0) numberOfSamples += STORAGE_SIZE; 00428 00429 return (numberOfSamples); 00430 } 00431 00432 //Report the most recent red value 00433 uint32_t MAX86150::getRed(void) 00434 { 00435 //Check the sensor for new data for 250ms 00436 if(safeCheck(250)) 00437 return (sense.red[sense.head]); 00438 else 00439 return(0); //Sensor failed to find new data 00440 } 00441 00442 //Report the most recent IR value 00443 uint32_t MAX86150::getIR(void) 00444 { 00445 //Check the sensor for new data for 250ms 00446 if(safeCheck(250)) 00447 return (sense.IR[sense.head]); 00448 else 00449 return(0); //Sensor failed to find new data 00450 } 00451 00452 //Report the most recent Green value 00453 int32_t MAX86150::getECG(void) 00454 { 00455 //Check the sensor for new data for 250ms 00456 if(safeCheck(250)) 00457 return (sense.ecg[sense.head]); 00458 else 00459 return(0); //Sensor failed to find new data 00460 } 00461 00462 //Report the next Red value in the FIFO 00463 uint32_t MAX86150::getFIFORed(void) 00464 { 00465 return (sense.red[sense.tail]); 00466 } 00467 00468 //Report the next IR value in the FIFO 00469 uint32_t MAX86150::getFIFOIR(void) 00470 { 00471 return (sense.IR[sense.tail]); 00472 } 00473 00474 //Report the next Green value in the FIFO 00475 int32_t MAX86150::getFIFOECG(void) 00476 { 00477 return (sense.ecg[sense.tail]); 00478 } 00479 00480 //Advance the tail 00481 void MAX86150::nextSample(void) 00482 { 00483 if(available()) //Only advance the tail if new data is available 00484 { 00485 sense.tail++; 00486 sense.tail %= STORAGE_SIZE; //Wrap condition 00487 } 00488 } 00489 00490 //Polls the sensor for new data 00491 //Call regularly 00492 //If new data is available, it updates the head and tail in the main struct 00493 //Returns number of new samples obtained 00494 uint16_t MAX86150::check(void) 00495 { 00496 //pc.printf("In check() ...\n"); 00497 //Read register FIDO_DATA in (3-byte * number of active LED) chunks 00498 //Until FIFO_RD_PTR = FIFO_WR_PTR 00499 // pc.printf("SYSCONTROL REG: %x\n",readRegister8(_i2caddr, 0x0D)); 00500 00501 uint8_t readPointer = getReadPointer(); 00502 uint8_t writePointer = getWritePointer(); 00503 00504 int numberOfSamples = 0; 00505 00506 //Do we have new data? 00507 if (readPointer != writePointer) 00508 { 00509 //pc.printf("Checking for new data...\n"); 00510 //Calculate the number of readings we need to get from sensor 00511 numberOfSamples = writePointer - readPointer; 00512 if (numberOfSamples < 0) numberOfSamples += 32; //Wrap condition 00513 //pc.printf("Need to get %d samples\n", numberOfSamples); 00514 00515 //We now have the number of readings, now calc bytes to read 00516 //For this example we are just doing Red and IR (3 bytes each) 00517 int bytesLeftToRead = numberOfSamples * activeDevices * 3; 00518 00519 //pc.printf("There are %d bytes to read\n", bytesLeftToRead); 00520 00521 //Get ready to read a burst of data from the FIFO register 00522 /*_i2cPort->beginTransmission(_i2caddr); 00523 _i2cPort->write(MAX86150_FIFODATA); 00524 _i2cPort->endTransmission();*/ 00525 char command[] = {MAX86150_FIFODATA}; 00526 _i2cPort->write(_i2caddr,command, 1); 00527 //pc.printf("Sent write cmd to read new data\n"); 00528 00529 00530 //We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH 00531 //I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno. 00532 //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno 00533 while (bytesLeftToRead > 0) 00534 { 00535 int toGet = bytesLeftToRead; 00536 if (toGet > I2C_BUFFER_LENGTH) 00537 { 00538 //If toGet is 32 this is bad because we read 6 bytes (Red+IR * 3 = 6) at a time 00539 //32 % 6 = 2 left over. We don't want to request 32 bytes, we want to request 30. 00540 //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27. 00541 00542 toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeDevices * 3)); //Trim toGet to be a multiple of the samples we need to read 00543 } 00544 00545 bytesLeftToRead -= toGet; 00546 00547 //Request toGet number of bytes from sensor 00548 //_i2cPort->requestFrom(_i2caddr, toGet); 00549 char data[toGet]; 00550 char *p = data; 00551 //pc.printf("Before reading FIFO data, toGet = %d\n",toGet); 00552 _i2cPort->read(_i2caddr, data, toGet, false); 00553 //_i2cPort->stop(); 00554 //pc.printf("Read FIFO data\n"); 00555 00556 00557 00558 while (toGet > 0) 00559 { 00560 //pc.printf("In while loop\n\n"); 00561 sense.head++; //Advance the head of the storage struct 00562 sense.head %= STORAGE_SIZE; //Wrap condition 00563 00564 uint8_t temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long 00565 uint32_t tempLong; 00566 00567 //Burst read three bytes - RED 00568 /*temp[3] = 0; 00569 temp[2] = _i2cPort->read(); 00570 temp[1] = _i2cPort->read(); 00571 temp[0] = _i2cPort->read();*/ 00572 temp[3] = 0; 00573 temp[2] = *p++; 00574 temp[1] = *p++; 00575 temp[0] = *p++; 00576 00577 00578 //Convert array to long 00579 memcpy(&tempLong, temp, sizeof(tempLong)); 00580 00581 tempLong &= 0x7FFFF; //Zero out all but 18 bits 00582 00583 sense.red[sense.head] = tempLong; //Store this reading into the sense array 00584 00585 //pc.printf("Stored FIFO data into sense array\n"); 00586 00587 if (activeDevices > 1) 00588 { 00589 //Burst read three more bytes - IR 00590 /*temp[3] = 0; 00591 temp[2] = _i2cPort->read(); 00592 temp[1] = _i2cPort->read(); 00593 temp[0] = _i2cPort->read();*/ 00594 temp[3] = 0; 00595 temp[2] = *p++; 00596 temp[1] = *p++; 00597 temp[0] = *p++; 00598 00599 00600 //Convert array to long 00601 memcpy(&tempLong, temp, sizeof(tempLong)); 00602 //Serial.println(tempLong); 00603 tempLong &= 0x7FFFF; //Zero out all but 18 bits 00604 00605 sense.IR[sense.head] = tempLong; 00606 } 00607 00608 if (activeDevices > 2) 00609 { 00610 //Burst read three more bytes - ECG 00611 int32_t tempLongSigned; 00612 00613 /*temp[3] = 0; 00614 temp[2] = _i2cPort->read(); 00615 temp[1] = _i2cPort->read(); 00616 temp[0] = _i2cPort->read(); 00617 //Serial.println(tempLong);*/ 00618 temp[3] = 0; 00619 temp[2] = *p++; 00620 temp[1] = *p++; 00621 temp[0] = *p++; 00622 00623 //Convert array to long 00624 memcpy(&tempLongSigned, temp, sizeof(tempLongSigned)); 00625 00626 //tempLong &= 0x3FFFF; //Zero out all but 18 bits 00627 00628 sense.ecg[sense.head] = tempLongSigned; 00629 } 00630 00631 toGet -= activeDevices * 3; 00632 } 00633 } //End while (bytesLeftToRead > 0) 00634 } //End readPtr != writePtr 00635 return (numberOfSamples); //Let the world know how much new data we found 00636 } 00637 00638 //Check for new data but give up after a certain amount of time 00639 //Returns true if new data was found 00640 //Returns false if new data was not found 00641 00642 bool MAX86150::safeCheck(uint8_t maxTimeToCheck) 00643 { 00644 // 00645 //pc.printf("In safe checkk\n"); 00646 Timer t; 00647 t.start(); 00648 uint32_t markTime = t.read(); 00649 00650 while(1) 00651 { 00652 if(t.read() - markTime > maxTimeToCheck) return(false); 00653 00654 if(check() == true) //We found new data! 00655 return(true); 00656 00657 wait_ms(1); //TODO: make it 1 again 00658 } 00659 } 00660 00661 //Given a register, read it, mask it, and then set the thing 00662 void MAX86150::bitMask(uint8_t reg, uint8_t mask, uint8_t thing) 00663 { 00664 // Grab current register context 00665 uint8_t originalContents = readRegister8(_i2caddr, reg); 00666 00667 // Zero-out the portions of the register we're interested in 00668 originalContents = originalContents & mask; 00669 00670 // Change contents 00671 writeRegister8(_i2caddr, reg, originalContents | thing); 00672 } 00673 00674 uint8_t MAX86150::readRegister8(uint8_t address, uint8_t reg) { 00675 00676 /* 00677 uint8_t tempData = 0; 00678 _i2cPort->beginTransmission(address); 00679 _i2cPort->write(reg); 00680 _i2cPort->endTransmission(false); 00681 00682 _i2cPort->requestFrom((uint8_t)address, (uint8_t)1); // Request 1 byte 00683 if (_i2cPort->available()) 00684 { 00685 00686 return(_i2cPort->read()); 00687 } 00688 return (0); //Fail 00689 */ 00690 int suc = 0; 00691 char regData; 00692 char writeData = reg; 00693 _i2cPort->write(address,&writeData,1); //true is for repeated start 00694 suc = _i2cPort->read(address,®Data,1); 00695 //pc.printf("REad in lib was %d",suc); 00696 return regData; 00697 00698 } 00699 00700 void MAX86150::writeRegister8(uint8_t address, uint8_t reg, uint8_t value) { 00701 00702 /* 00703 _i2cPort->beginTransmission(address); 00704 _i2cPort->write(reg); 00705 _i2cPort->write(value); 00706 _i2cPort->endTransmission(); 00707 */ 00708 00709 //i2c.write(address, reg, 1); 00710 /*writes 1 byte to a single register*/ 00711 char writeData[2]; 00712 writeData[0] = reg ; 00713 writeData[1] = value; 00714 _i2cPort->write(address,writeData, 2); 00715 00716 }
Generated on Sat Jul 16 2022 12:45:18 by
1.7.2