I'm trying to build an spo2 measurement with MAX30102 and MAX32664D. I'm sending my commands from TI CC2640R2F using I2C 400KHz mode. I made a library for MAX32664D and tried to send commands below and I explained the results that I got by running these commands:
1 MAX32664_EnterBootLoaderMode();
2 MAX32664_ReadDeviceMode();
3 MAX32664_ReadMCUType();
4 MAX32664_ReadBootloaderVersion();
5 MAX32664_ReadBootloaderPageSize();
6 MAX32664_EnterAppMode();
7 MAX32664_ReadDeviceMode();
8 MAX32664_BPTalgorithmMode(0x02);
9 MAX32664_SetOutputMode(0x01);
10 MAX32664_SetFifoInterruptThreshold(0x04);
11 MAX32664_SensorEnable(true);
12 MAX32664_ReadSensorMode();
13 MAX32664_ReadSensorHubVersion();
14 MAX32664_GetNumOfSamplesInFifo();
15 receivedData = MAX32664_GetFifoData();
16 MAX32664_ReadSensorFifoLength();
17 MAX32664_ReadNumOfSamplesInSensorFifo();
line 1&2: device goes into boot loader mode successfully
line 3 : command works and indicates that MCU is MAX32664 or MAX32660
line 4 : command doesn't work and returns 0xFE that is ERR_TRY_AGAIN but trying agail also doesn't work - boot loader version is not sent to host by MAX32664D
line 5 : command doesn't work and returns 0xFE that is ERR_TRY_AGAIN but trying agail also doesn't work - boot loader pagesize which must be 8192 is not sent to host by MAX32664D
line 6&7: device goes into application mode successfully
line 8 : command doesn't work and returns 0xFE that is ERR_TRY_AGAIN but trying agail also doesn't work - unable to select estimation mode for BPT algorithm
line 9 : command worked and sensor data is selected as MAX32664D output
line 10 : command worked and interrrupt threshold is set to 0x04
line 11: command doesn't work and returns 0xFE that is ERR_TRY_AGAIN but trying agail also doesn't work - the MAX30102 deosn't get enabled
line 12: command works and indicates that MAX30102 is disable
line 13: command works and indicates that msbl file version is 40.2.2
line 14: command works and indicates that there is 0 samples in output fifo
line 15: command works and recieved data is LED1 = 0x202 , LED2 = 0x440109 ,LED3 = 0x70000 and other data are all zero.
line16: command works and indicates that input fifo length is 160
line17: command works and indicates that there is 160 samples in input fifo
why some of command do not work? is any thing I can do? is it a physical issue or corrupted msbl file? what should I do to be able to read data?
below is my library codes for each command:
bool MAX32664_EnterBootLoaderMode(void){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x01;//Family byte
TxBuffer[1] = 0x00;//Index byte
TxBuffer[2] = 0x08;//Enter boot loader mode
RxBuffer[0] = 0xFF;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
#ifdef DEBUG_PRINTS
System_printf(successful ? "BootLoader Mode Enabled\n" : "BootLoader Mode Failed\n");
System_flush();
#endif
return successful;
}
uint8_t MAX32664_ReadDeviceMode(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[2];
TxBuffer[0] = 0x02;//Family byte
TxBuffer[1] = 0x00;//Index byte
RxBuffer[0] = 0xff;//Reset
RxBuffer[1] = 0xff;//Initialization
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 2, MAX32664_ADDR);
#ifdef DEBUG_PRINTS
switch(RxBuffer[1]){
case 0x00:
System_printf("Device is in application mode\n");
break;
case 0x02:
System_printf("Device is reset\n");
break;
case 0x08:
System_printf("Device is in bot loader mode\n");
break;
default:
System_printf("Invalid data received\n");
}
System_flush();
#endif
return RxBuffer[1];
}
void MAX32664_ReadMCUType(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[2] = {0xff,0xff};
TxBuffer[0] = 0xFF;//Family byte
TxBuffer[1] = 0x00;//Index byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 2, MAX32664_ADDR);
#ifdef DEBUG_PRINTS
switch(RxBuffer[1]){
case 0x00:
System_printf("MCU is MAX32625\n");
break;
case 0x01:
System_printf("MCU is MAX32664 or MAX32660\n");
break;
default :
System_printf("Unknown MCU\n");
}
System_flush();
#endif
}
void MAX32664_ReadBootloaderVersion(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[4] = {0xff,0xff,0xff,0xff};
TxBuffer[0] = 0x81;//Family byte
TxBuffer[1] = 0x00;//Index byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 4, MAX32664_ADDR);
#ifdef DEBUG_PRINTS
System_printf("Bootloader firmware version is %d.%d.%d \n",RxBuffer[1],RxBuffer[2],RxBuffer[3]);
System_flush();
#endif
}
uint16_t MAX32664_ReadBootloaderPageSize(void){
uint16_t pageSize;
uint8_t TxBuffer[2];
uint8_t RxBuffer[3] = {0xff,0xff,0xff};
TxBuffer[0] = 0x81;//Family byte
TxBuffer[1] = 0x01;//Index byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 3, MAX32664_ADDR);
pageSize = (RxBuffer[1]<<8) + RxBuffer[2];
#ifdef DEBUG_PRINTS
System_printf("page size is %d\n",pageSize);
System_flush();
#endif
return pageSize;
}
bool MAX32664_EnterAppMode(void){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x01;//Family byte
TxBuffer[1] = 0x00;//Index byte
TxBuffer[2] = 0x00;//Exit boot loader mode,Enter application mode
RxBuffer[0] = 0xFF;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
#ifdef DEBUG_PRINTS
System_printf(successful ? "Application Mode Enabled\n" : "Application Mode Failed\n");
System_flush();
#endif
return successful;
}
bool MAX32664_BPTalgorithmMode(uint8_t modeByte){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x52;//Family byte
TxBuffer[1] = 0x04;//Index byte
TxBuffer[2] = modeByte;
RxBuffer[0] = 0xff;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(20));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
return successful;
}
bool MAX32664_SetOutputMode(uint8_t formatByte){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x10;//Family byte
TxBuffer[1] = 0x00;//Index byte
TxBuffer[2] = formatByte;
RxBuffer[0] = 0xff;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
return successful;
}
bool MAX32664_SetFifoInterruptThreshold(uint8_t thrByte){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x10;//Family byte
TxBuffer[1] = 0x01;//Index byte
TxBuffer[2] = thrByte;
RxBuffer[0] = 0xff;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
return successful;
}
bool MAX32664_SensorEnable(bool enable){
bool successful;
uint8_t TxBuffer[3];
uint8_t RxBuffer[1];
TxBuffer[0] = 0x44;//Family byte
TxBuffer[1] = 0x03;//Index byte
TxBuffer[2] = (enable)? 0x01:0x00;
RxBuffer[0] = 0xff;//Initialization
I2C_Send(TxBuffer, 3, MAX32664_ADDR);
Task_sleep(DURATION_MS(40));//command delay
I2C_Receive(RxBuffer, 1, MAX32664_ADDR);
successful = (RxBuffer[0] == 0x00)? true:false;
return successful;
}
uint8_t MAX32664_ReadSensorMode(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[2];
TxBuffer[0] = 0x45;//Family byte
TxBuffer[1] = 0x03;//Index byte
RxBuffer[0] = 0xff;//Initialization
RxBuffer[1] = 0xff;//Initialization
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 2, MAX32664_ADDR);
#ifdef DEBUG_PRINTS
switch(RxBuffer[1]){
case 0x00:
System_printf("MAX30101/2 is disabled\n");
break;
case 0x01:
System_printf("MAX30101/2 is enabled\n");
break;
}
System_flush();
#endif
return RxBuffer[1];
}
void MAX32664_ReadSensorHubVersion(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[4];
TxBuffer[0] = 0xff;//Family byte
TxBuffer[1] = 0x03;//Index byte
RxBuffer[0] = 0xff;//Initialization
RxBuffer[1] = 0xff;//Initialization Major version byte
RxBuffer[2] = 0xff;//Initialization Minor version byte
RxBuffer[3] = 0xff;//Initialization Revision byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 4, MAX32664_ADDR);
#ifdef DEBUG_PRINTS
System_printf("SensorHub Version is %d.%d.%d \n",RxBuffer[1],RxBuffer[2],RxBuffer[3]);
System_flush();
#endif
}
uint8_t MAX32664_GetNumOfSamplesInFifo(void){
uint8_t TxBuffer[2];
uint8_t RxBuffer[2];
TxBuffer[0] = 0x12;//Family byte
TxBuffer[1] = 0x00;//Index byte
RxBuffer[0] = 0xff;//Index byte
RxBuffer[1] = 0xff;//Index byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
return RxBuffer[1];
}
fifoData MAX32664_GetFifoData(void){
fifoData receivedData;
uint8_t TxBuffer[2];
uint8_t RxBuffer[20]={0};
TxBuffer[0] = 0x12;//Family byte
TxBuffer[1] = 0x01;//Index byte
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 20, MAX32664_ADDR);
receivedData = MAX32664_RawDataToFifoData(RxBuffer);
Task_sleep(DURATION_MS(45));//command delay
return receivedData;
}
fifoData MAX32664_RawDataToFifoData(uint8_t *RxBuffer){
fifoData receivedData;
receivedData.err = RxBuffer[0];
receivedData.led_1 = (RxBuffer[1]<<16) + (RxBuffer[2]<<8) + RxBuffer[3];
receivedData.led_2 = (RxBuffer[4]<<16) + (RxBuffer[5]<<8) + RxBuffer[6];
receivedData.led_3 = (RxBuffer[7]<<16) + (RxBuffer[8]<<8) + RxBuffer[9];
receivedData.led_4 = (RxBuffer[10]<<16) + (RxBuffer[11]<<8) + RxBuffer[12];
receivedData.status = RxBuffer[13];
receivedData.progress = RxBuffer[14];
receivedData.hr = RxBuffer[15];
receivedData.sys = RxBuffer[16];
receivedData.dia = RxBuffer[17];
receivedData.spo2 = RxBuffer[18];
receivedData.r = RxBuffer[19];
receivedData.hrAboveResting = RxBuffer[20];
return receivedData;
}
uint16_t MAX32664_ReadSensorFifoLength(void){
uint16_t fifoLength;
uint8_t TxBuffer[2] ;
uint8_t RxBuffer[3] = {0xff};
TxBuffer[0] = 0x13;
TxBuffer[1] = 0x01;
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 3, MAX32664_ADDR);
fifoLength = (RxBuffer[1]<<8) + RxBuffer[2];
#ifdef DEBUG_PRINTS
System_printf("fifo length is %d\n",fifoLength);
System_flush();
#endif
return fifoLength;
}
uint16_t MAX32664_ReadNumOfSamplesInSensorFifo(void){
uint16_t numOfSamples;
uint8_t TxBuffer[2] ;
uint8_t RxBuffer[3] = {0xff};
TxBuffer[0] = 0x13;
TxBuffer[1] = 0x01;
I2C_Send(TxBuffer, 2, MAX32664_ADDR);
Task_sleep(DURATION_MS(2));//command delay
I2C_Receive(RxBuffer, 3, MAX32664_ADDR);
numOfSamples = (RxBuffer[1]<<8) + RxBuffer[2];
#ifdef DEBUG_PRINTS
System_printf("number of samples currently in the sensor FIFO is %d\n",numOfSamples);
System_flush();
#endif
return numOfSamples;
}