Chanel Richardson / Mbed OS vitalsplus-max86150_chanel

Dependencies:   max32630fthr USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers max86150.cpp Source File

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,&regData,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 }