David Jung
/
MAX32664C_MAXM86146_Mode1_Optical
Mode1 Optical Validation
main.cpp
- Committer:
- phonemacro
- Date:
- 2021-03-31
- Revision:
- 11:a16b6bf38841
- Parent:
- 10:192ea88e964b
- Child:
- 12:17a0bf823462
File content as of revision 11:a16b6bf38841:
/******************************************************************************* * Copyright (C) 2021 Maxim Integrated Products, Inc., All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Maxim Integrated * Products, Inc. shall not be used except as stated in the Maxim Integrated * Products, Inc. Branding Policy. * * The mere transfer of this software does not imply any licenses * of trade secrets, proprietary technology, copyrights, patents, * trademarks, maskwork rights, or any other form of intellectual * property whatsoever. Maxim Integrated Products, Inc. retains all * ownership rights. ******************************************************************************* */ #include "mbed.h" #include "platform/mbed_thread.h" #include "mbed.h" /****************************************************************************** * Warning, if using the either * MAX32630FTHR+MAXM86161_ADPTER_REVB+MAXM86146EVSYS sensor brd or * MAX32630FTHR+MAXM86161_ADPTER_REVB+MAXM86161EVSYS sensor brd, * The VLED is connected to USB power which is noisy. The VLED should be * connected to a regulated power supply if you are testing accuracy. ******************************************************************************* */ /****************************************************************************** * Tera Term output is set to 115200 baud rate. * ver: 210325 ******************************************************************************/ /*****************************************************************************/ // define one and only one of the following three platforms #define MAXM86146_CFG 1 // tested on MAXM86146EVSYS_sensorBrd+MAXM86161_ADAPTER_REVB+MAX32630FTHR //#define MAXREFDES103_CFG //#define MAX86161_CFG 1 /*****************************************************************************/ #define ALGO_ONLY 1 // define this if you only want the algo data, comment out if you want raw sensor+algo data #ifdef MAXREFDES103_CFG #include "MAX20303.h" I2C sh_i2c_pmic(P5_7, P6_0); #endif #ifdef MAXM86146_CFG #define PPG_SZ 36 //maxm86146 #else #define PPG_SZ 18 //maxm86161, max86141 #endif #define ACCEL_SZ 6 // accel #define SENSOR_SZ (PPG_SZ+ACCEL_SZ) //#define ALGO_SZ 20 // 24 bytes is the algo normal size for 3x.12.0 #define ALGO_SZ 24 // 24 bytes is the algo normal size for 3x.13.x #ifdef ALGO_ONLY #define TTL_SZ (ALGO_SZ) #else #define TTL_SZ (PPG_SZ+ACCEL_SZ+ALGO_SZ) #endif Serial pc(USBTX, USBRX, 115200); DigitalOut rLED(LED1); DigitalOut gLED(LED2); DigitalOut bLED(LED3); /****************************************************************************** * MAX32630FTHR GPIOs ******************************************************************************/ #define RST_PIN P5_6 #define MFIO_PIN P5_4 DigitalOut rst(RST_PIN, PullUp); DigitalOut mfio(MFIO_PIN, PullUp); I2C sh_i2c(P3_4, P3_5); //#define thread_sleep_for(x) wait_ms(x) // for older versions of mbed const int SH_ADDR = 0xAA;//0x55; int32_t Time_to_Read_PPG = 0; #define BLINKING_RATE_MS 1000ms void blink_timer(void) { gLED = !gLED; /* blink the green LED */ } void fifo_timer(void) { Time_to_Read_PPG = 1; } void read_sh_fifo(void) { char cmd[8], i, j, samples; char rsp[3000]; int32_t ppg[12]; int16_t accel[3]; int32_t status, opmode, hr, hr_conf, ibi, ibi_conf, act, r, spo2, spo2_conf; int32_t spo2_compl, spo2_lo, spo2_mo, spo2_lopi, spo2_unrel, spo2_state, ibi_offset, scd; int32_t scnt = 0; int32_t ptr = 0; int32_t sptr = 0; mfio = 0; wait_us(300); Time_to_Read_PPG = 0; #if 0 // 2.1 cmd[0] = 0x00; cmd[1] = 0x00; sh_i2c.write(SH_ADDR, cmd, 2); wait_us(100); sh_i2c.read(SH_ADDR, rsp, 2); // pc.printf("2.1 Status: %x %x\n\r", rsp[0], rsp[1]); #endif // 2.2 cmd[0] = 0x12; cmd[1] = 0x00; sh_i2c.write(SH_ADDR, cmd, 2); wait_us(100); sh_i2c.read(SH_ADDR, rsp, 2); // pc.printf("2.2 Status: %x %x\n\r", rsp[0], rsp[1]); samples = rsp[1]; // pc.printf("num samples %d, (num*ttl)+1 %d\n\r", rsp[1], TTL_SZ*samples+1); // pc.printf("num smpls %d \n\r", samples); scnt = rsp[1]; // 2.3 cmd[0] = 0x12; cmd[1] = 0x01; sh_i2c.write(SH_ADDR, cmd, 2); wait_us(100); // thread_sleep_for(1); sh_i2c.read(SH_ADDR, rsp, 1+(TTL_SZ*samples)); status = rsp[0]; sptr = 1; for (i = 0; i < scnt; i++) { #ifdef ALGO_ONLY ptr = sptr; #else ptr = sptr; ppg[0] = (rsp[ptr+0] << 16) | (rsp[ptr+1] << 8) | (rsp[ptr+2]); ppg[1] = (rsp[ptr+3] << 16) | (rsp[ptr+4] << 8) | (rsp[ptr+5]); ppg[2] = (rsp[ptr+6] << 16) | (rsp[ptr+7] << 8) | (rsp[ptr+8]); ppg[3] = (rsp[ptr+9] << 16) | (rsp[ptr+10] << 8) | (rsp[ptr+11]); ppg[4] = (rsp[ptr+12] << 16) | (rsp[ptr+13] << 8) | (rsp[ptr+14]); ppg[5] = (rsp[ptr+15] << 16) | (rsp[ptr+16] << 8) | (rsp[ptr+17]); pc.printf("%d,%d,%d,%d,", ppg[0], ppg[1], ppg[2], ppg[3]); // pc.printf("%d,%d,", ppg[4], ppg[5]); accel[0] = (rsp[PPG_SZ+0] << 8) | (rsp[PPG_SZ+1]); accel[1] = (rsp[PPG_SZ+2] << 8) | (rsp[PPG_SZ+3]); accel[2] = (rsp[PPG_SZ+4] << 8) | (rsp[PPG_SZ+5]); pc.printf("%d,%d,%d,", accel[0], accel[1], accel[2]); ptr = sptr + SENSOR_SZ; #endif // pc.printf("ptr %d ttlsiz %d ", ptr, TTL_SZ); opmode = rsp[ptr]; hr = (rsp[ptr+1] << 8) + rsp[ptr+2]; hr_conf = rsp[ptr+3]; ibi = (rsp[ptr+5] << 8) + rsp[ptr+4]; ibi_conf = rsp[ptr+6]; act = rsp[ptr+7]; r = (rsp[ptr+8] << 8) + rsp[ptr+9]; spo2_conf = rsp[ptr+10]; spo2 = (rsp[ptr+11] << 8) + rsp[ptr+12]; spo2_compl = rsp[ptr+13]; spo2_lo = rsp[ptr+14]; spo2_mo = rsp[ptr+15]; spo2_lopi = rsp[ptr+16]; spo2_unrel = rsp[ptr+17]; spo2_state = rsp[ptr+18]; scd = rsp[ptr+19]; ibi_offset = rsp[ptr+20]; sptr += (TTL_SZ); #if 0 pc.printf("%d,%d,%d,%d,", opmode, hr, hr_conf, ibi); pc.printf("%d,%d,%d,%d,", ibi_conf, act, r, spo2_conf); pc.printf("%d,%d,%d,%d,", spo2, spo2_compl, spo2_lo, spo2_mo); pc.printf("%d,%d,%d,%d,", spo2_lopi,spo2_unrel, spo2_state, scd); pc.printf("%d,", ibi_offset); #else pc.printf("%d,%d,", hr, hr_conf); pc.printf("%d,%d,", spo2, spo2_conf); pc.printf("%d,", spo2_lo); pc.printf("%d,%d,", spo2_unrel, scd); #endif pc.printf("\n\r"); } mfio = 1; } #ifdef MAXREFDES103_CFG void init_max20303_pmic(void) { /* Wait for pmic to settle down */ thread_sleep_for(800); //set_time(1544787300); // Set RTC time to Wed, 28 Oct 2009 11:35:37 MAX20303 max20303(&sh_i2c); /*Set LDO1 to 1.8v*/ max20303.LDO1Config(); /*Set LDO2 to 3v*/ max20303.LDO2Config(); //max20303.BoostEnable(); max20303.BuckBoostEnable(); max20303.led0on(0); max20303.led1on(0); max20303.led2on(0); /* Wait for pmic to settle down */ thread_sleep_for(200); } #endif // MAXREFDES103_CFG void init_sh(void) { char cmd[8], i, j; char rsp[256]; // switch to application mode rst = 0; mfio = 1; thread_sleep_for(10); rst = 1; thread_sleep_for(1500); #ifdef MAXREFDES103_CFG init_max20303_pmic(); #endif mfio = 0; wait_us(300); //read operating mode cmd[0] = 0x02; cmd[1] = 0x00; sh_i2c.write(SH_ADDR, cmd, 2); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 2); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); pc.printf("\n\r 0x02 0x00 Status, Read Operating Mode: %x %x\n\r", rsp[0], rsp[1]); //1.11 rd ver cmd[0] = 0xFF; cmd[1] = 0x03; sh_i2c.write(SH_ADDR, cmd, 2); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 4); mfio = 1; mfio = 0; wait_us(300); pc.printf("Ver: %d %d %d %d\n\r", rsp[0], rsp[1], rsp[2], rsp[3]); // 1.3 sensor and algo data cmd[0] = 0x10; cmd[1] = 0x00; #ifdef ALGO_ONLY cmd[2] = 0x02; // algo data pc.printf("algo only \n\r"); #else cmd[2] = 0x03; // sensor + algo data pc.printf("sens+algo \n\r"); #endif sh_i2c.write(SH_ADDR, cmd, 3); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.3 Status: %x\n\r", rsp[0]); // 1.7 cont hr, spo2 cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x0A; cmd[3] = 0x00; sh_i2c.write(SH_ADDR, cmd, 4); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.7 Status: %x\n\r", rsp[0]); // 1.8 AEC enable (default) cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x0B; cmd[3] = 0x01; sh_i2c.write(SH_ADDR, cmd, 4); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.8 Status: %x\n\r", rsp[0]); // 1.9 auto PD (default cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x12; cmd[3] = 0x01; sh_i2c.write(SH_ADDR, cmd, 4); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.9 Status: %x\n\r", rsp[0]); // 1.10 SCD (default) cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x0C; cmd[3] = 0x01; sh_i2c.write(SH_ADDR, cmd, 4); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.7 Status: %x\n\r", rsp[0]); #ifdef MAXM86146_CFG //1.20 Sec 4.1 map leds to slots for MAXM86146 cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x19; cmd[3] = 0x13; cmd[4] = 0x56; cmd[5] = 0x00; sh_i2c.write(SH_ADDR, cmd, 6); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map leds to slots%x\n\r", rsp[0]); //1.21 map HR inputs to slots cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x17; cmd[3] = 0x00; cmd[4] = 0x11; sh_i2c.write(SH_ADDR, cmd, 5); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map HR to slots/PDs %x\n\r", rsp[0]); //1.22 map SpO2 inputs to slots cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x18; cmd[3] = 0x30; cmd[4] = 0x20; sh_i2c.write(SH_ADDR, cmd, 5); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map SpO2 to slots/PDs %x\n\r", rsp[0]); #if 0 //1.20 Sec 4.1 map leds to slots for MAXM86146 cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x19; cmd[3] = 0x15; cmd[4] = 0x60; cmd[5] = 0x00; sh_i2c.write(SH_ADDR, cmd, 6); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map leds to slots%x\n\r", rsp[0]); //1.21 map HR inputs to slots cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x17; cmd[3] = 0x00; cmd[4] = 0x01; sh_i2c.write(SH_ADDR, cmd, 5); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map HR to slots/PDs %x\n\r", rsp[0]); //1.22 map SpO2 inputs to slots cmd[0] = 0x50; cmd[1] = 0x07; cmd[2] = 0x18; cmd[3] = 0x20; cmd[4] = 0x10; sh_i2c.write(SH_ADDR, cmd, 5); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 1); mfio = 1; mfio = 0; wait_us(300); pc.printf("map SpO2 to slots/PDs %x\n\r", rsp[0]); #endif #endif // MAXM86146_CFG // 1.3 Enable HR, SpO2 algo cmd[0] = 0x52; cmd[1] = 0x07; cmd[2] = 0x01; sh_i2c.write(SH_ADDR, cmd, 3); thread_sleep_for(465); sh_i2c.read(SH_ADDR, rsp, 1); pc.printf("1.14 status: %x\n\r", rsp[0]); mfio = 1; #if 1 //1.31 rd AFE part id cmd[0] = 0x41; cmd[1] = 0x00; cmd[2] = 0xFF; sh_i2c.write(SH_ADDR, cmd, 3); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 2); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.31 part id afe %x %x\n\r", rsp[0], rsp[1]); //1.32 rd accel who cmd[0] = 0x41; cmd[1] = 0x04; cmd[2] = 0x0F; sh_i2c.write(SH_ADDR, cmd, 3); mfio = 1; thread_sleep_for(2); mfio = 0; wait_us(300); sh_i2c.read(SH_ADDR, rsp, 2); mfio = 1; mfio = 0; wait_us(300); pc.printf("1.32 who accel %x %x\n\r", rsp[0], rsp[1]); #endif } int main() { sh_i2c.frequency(400000); int32_t ledcnt = 0; rLED = LED_OFF; gLED = LED_ON; bLED = LED_OFF; Ticker ticker; // calls a callback repeatedly with a timeout //ticker.attach(callback(&blink_timer), BLINKING_RATE_MS); /* set timer for one second */ init_sh(); #if defined(MAXREFDES103_CFG) || defined(MAXM86161_CFG) || defined(MAXM86146_CFG) Timer tmr1; while (1) { tmr1.start(); if (tmr1.read_ms() > 40) { tmr1.reset(); read_sh_fifo(); if ((ledcnt++ % 50) == 0) gLED = !gLED; } } #else ticker.attach(callback(&fifo_timer), 0.040f); while (1) { if (Time_to_Read_PPG) { read_sh_fifo(); if ((ledcnt++ % 50) == 0) gLED = !gLED; } } #endif }