#include "nrf.h" #include "nrf_drv_clock.h" #include "nrf_gpio.h" #include "nrf_delay.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "nrf_drv_power.h" #include "nrf_serial.h" #include "nrf_drv_twi.h" #include "app_timer.h" #include "app_error.h" #include "app_util.h" #include "app_util_platform.h" #include "boards.h" #define OP_QUEUES_SIZE 3 #define RX_PIN 23 #define TX_PIN 24 #define TWI_INSTANCE_ID 0 /* MAX30100 Register Map */ #define MAX30102_ADDRESS 0x57 #define REV_ID ((uint8_t)0xFE) #define PART_ID ((uint8_t)0xFF) #define INT_STATUS_1 ((uint8_t)0x00) #define INT_STATUS_2 ((uint8_t)0x01) #define INT_ENABLE_1 ((uint8_t)0x02) #define INT_ENABLE_2 ((uint8_t)0x03) #define FIFO_WR_PTR ((uint8_t)0x04) #define OVERFLOW_CTR ((uint8_t)0x05) #define FIFO_RD_PTR ((uint8_t)0x06) #define FIFO_DATA ((uint8_t)0x07) #define FIFO_CONF ((uint8_t)0x08) #define MODE_CONF ((uint8_t)0x09) #define SPO2_CONF ((uint8_t)0X0A) #define LED1_PA ((uint8_t)0x0C) #define LED2_PA ((uint8_t)0x0D) #define PILOT_PA ((uint8_t)0x10) #define MULTILED_1 ((uint8_t)0x11) #define MULTILED_2 ((uint8_t)0x12) #define TEMP_INTR 0x1F #define TEMP_FRAC 0x20 #define TEMP_CONF 0x21 #define PROX_INT_TH 0x30 extern uint8_t temp_array[6]; static const nrf_drv_twi_t m_twi_max30100 = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID); void MAX30102_reset (); void MAX30102_init (); void MAX30102_setup (); void read_fifo (); static void sleep_handler(void) { __WFE(); __SEV(); __WFE(); } void uart_event_handler(struct nrf_serial_s const *p_serial,nrf_serial_event_t event); NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config, RX_PIN,TX_PIN, RTS_PIN_NUMBER,CTS_PIN_NUMBER, NRF_UART_HWFC_DISABLED,NRF_UART_PARITY_EXCLUDED, NRF_UARTE_BAUDRATE_115200, UART_DEFAULT_CONFIG_IRQ_PRIORITY ); #define SERIAL_FIFO_TX_SIZE 32 #define SERIAL_FIFO_RX_SIZE 32 NRF_SERIAL_QUEUES_DEF(serial_queues,SERIAL_FIFO_RX_SIZE,SERIAL_FIFO_TX_SIZE); #define SERIAL_BUFF_RX_SIZE 1 #define SERIAL_BUFF_TX_SIZE 1 NRF_SERIAL_BUFFERS_DEF(serial_buffs,SERIAL_BUFF_RX_SIZE,SERIAL_BUFF_TX_SIZE); NRF_SERIAL_CONFIG_DEF(serial_config,NRF_SERIAL_MODE_IRQ,&serial_queues,&serial_buffs,uart_event_handler,sleep_handler); NRF_SERIAL_UART_DEF(serial_uart,0); void uart_event_handler(struct nrf_serial_s const *p_serial,nrf_serial_event_t event) { ret_code_t err_code; uint8_t c; switch(event) { case NRF_SERIAL_EVENT_TX_DONE: break; case NRF_SERIAL_EVENT_RX_DATA: err_code=nrf_serial_write(&serial_uart,"Int",3,NULL,5); APP_ERROR_CHECK(err_code); break; default: break; } } void twi_init() { ret_code_t err_code; const nrf_drv_twi_config_t twi_config={ .scl=16, .sda=17, .frequency=NRF_DRV_TWI_FREQ_400K, .interrupt_priority=APP_IRQ_PRIORITY_HIGH, .clear_bus_init=false, }; err_code=nrf_drv_twi_init(&m_twi_max30100,&twi_config,NULL,NULL); APP_ERROR_CHECK(err_code); nrf_drv_twi_enable(&m_twi_max30100); } /*ret_code_t max30100_I2C_register_write(uint8_t reg_addr, uint8_t * p_tx_data, uint8_t bytes) { ret_code_t ret_code; uint8_t tx_data[bytes+1]; tx_data[0] = reg_addr; for(uint8_t i = 0 ; i<bytes ; i++) { tx_data[i+1] = p_tx_data[i]; } ret_code = nrf_drv_twi_tx(&m_twi_max30100, MAX30100_ADDRESS, tx_data, sizeof(tx_data), false); return ret_code; }*/ /** * @brief Function for reading from registers on the MAX30100. */ /*ret_code_t max30100_I2C_register_read( uint8_t reg_addr, uint8_t * p_rx_data, uint32_t bytes) { ret_code_t ret_code; ret_code = nrf_drv_twi_tx(&m_twi_max30100,MAX30100_ADDRESS, ®_addr, 1, true); if(ret_code != NRF_SUCCESS) { return ret_code; } ret_code = nrf_drv_twi_rx(&m_twi_max30100, MAX30100_ADDRESS, p_rx_data, bytes); return ret_code; } void max30100_read_hr_spo2(int16_t * p_hr_val, int16_t * p_spo2_val) { ret_code_t err_code; // Raw HR& SPo2 data from FIFO uint8_t hr_H[1]; uint8_t hr_L[1]; uint8_t spo2_H[1]; uint8_t spo2_L[1]; // Read the four data registers from MAX30100_FIFO_DATA err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_H,sizeof(hr_H)); err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_L,sizeof(hr_L)); err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_H,sizeof(spo2_H)); err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_L,sizeof(spo2_L)); APP_ERROR_CHECK(err_code); *p_hr_val = (hr_H[0]<<8)|hr_L[0]; *p_spo2_val = (spo2_H[0]<<8)|spo2_L[0]; nrf_serial_write(&serial_uart,spo2_H,1,NULL,10); nrf_serial_write(&serial_uart,spo2_L,1,NULL,10); }*/ /** * @brief Function for application main entry. */ int main(void) { ret_code_t err_code; uint8_t address=0x57; uint8_t sample_data=0x00; err_code=nrf_drv_clock_init(); APP_ERROR_CHECK(err_code); err_code=nrf_drv_power_init(NULL); APP_ERROR_CHECK(err_code); nrf_drv_clock_lfclk_request(NULL); err_code=app_timer_init(); APP_ERROR_CHECK(err_code); uint8_t tx_buf[10]="Hello"; err_code=nrf_serial_init(&serial_uart,&m_uart0_drv_config,&serial_config); APP_ERROR_CHECK(err_code); nrf_serial_write(&serial_uart,"Started",8,NULL,10); //printf("Begin"); //======================MAX30100============================// twi_init(); //=========================================================// err_code = nrf_drv_twi_rx(&m_twi_max30100,address,&sample_data,sizeof(sample_data)); if(err_code==NRF_SUCCESS) { NRF_LOG_INFO("Device detected at address = 0x%x",address); nrf_serial_write(&serial_uart,"Ok ",3,NULL,10); } nrf_serial_write(&serial_uart,"Started1",9,NULL,10); NRF_LOG_FLUSH(); MAX30102_init(); MAX30102_reset(); MAX30102_setup (); while(true) { read_fifo(); nrf_delay_ms(1000); } } uint32_t read_register(uint8_t reg, uint8_t * p_data, uint32_t length) { uint32_t err_code; err_code = nrf_drv_twi_tx(&m_twi_max30100, MAX30102_ADDRESS, ®, 1, false); if(err_code != NRF_SUCCESS) return err_code; err_code = nrf_drv_twi_rx(&m_twi_max30100, MAX30102_ADDRESS, p_data, length); if(err_code != NRF_SUCCESS) return err_code; return err_code; } uint32_t write_register(uint8_t reg_address, uint8_t data) { ret_code_t err_code; uint8_t buffer_send[2] = {reg_address, data}; err_code = nrf_drv_twi_tx(&m_twi_max30100, MAX30102_ADDRESS, buffer_send, sizeof(buffer_send), true); APP_ERROR_CHECK(err_code); } void MAX30102_reset (void) { write_register(MODE_CONF, 0x40); } void MAX30102_setup (void) { write_register(INT_ENABLE_1, 0xC0); write_register(INT_ENABLE_2, 0x00); write_register(FIFO_WR_PTR, 0x00); // Reset FIFO Write pointer write_register(OVERFLOW_CTR, 0x00); // Reset OVERFLOW_CTR pointer write_register(FIFO_RD_PTR, 0x00); // Reset FIFO READ pointer write_register(FIFO_CONF, 0x4F); //average sampling = 4 write_register(MODE_CONF, 0x03); // ADC range = 4096nA | Sampling Rate = 100 Hz | LED pulseWidth = 411uS write_register(SPO2_CONF, 0x27); // 400 samples per second write_register(LED1_PA, 0x5F); // LED1 current = 19 mA write_register(LED2_PA, 0x5F); // LED2 current = 19 mA write_register(PILOT_PA, 0x7F); // Pilot LED ~ 25mA } void MAX30102_init (void) { uint8_t revID; uint8_t partID; ret_code_t err_code; err_code = read_register (PART_ID, &partID,sizeof(partID)); APP_ERROR_CHECK(err_code); NRF_LOG_INFO("MAX30102 PART ID: 0x%02x \r\n", partID); err_code = read_register (REV_ID, &revID,sizeof(revID)); APP_ERROR_CHECK(err_code); NRF_LOG_INFO("MAX30102 REV ID: 0x%02x \r\n", revID); } void read_fifo() { uint8_t clearINT1; uint8_t clearINT2; uint32_t LEDdata=0; uint8_t dataArray[6]; ret_code_t err_code; uint8_t FIFO_data; //Clear Interrupts err_code = read_register(INT_STATUS_1, &clearINT1,sizeof(clearINT1)); err_code = read_register(INT_STATUS_1, &clearINT2,sizeof(clearINT2)); err_code =read_register(FIFO_DATA,dataArray,sizeof(dataArray)); APP_ERROR_CHECK(err_code); //Extract 3 bytes for IR LED LEDdata=dataArray[0]<<16|dataArray[1]<<8 |dataArray[2]; NRF_LOG_RAW_INFO("%d,",LEDdata) ; // RED LED data LEDdata=0; //Extract 3 bytes for RED LED LEDdata=dataArray[3]<<16|dataArray[4]<<8 |dataArray[5]; NRF_LOG_RAW_INFO("%d\r\n", LEDdata); // IR LED data }