#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
}