Hello Nordic,
I am trying to make NRF52840-DK Communication with MAX30003 ECG Board via SPI. I am using the SPI example and it works fine. Now I have made three SPI functions that I can use in my project:
- _Read_Data(int num_samples)
- _Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data)
-_Reg_Read(uint8_t Reg_address)
I have made the following so far and the event handler works fine if I keep the original example code for the SPI transfer. It is just the _Reg_Read(uint8_t Reg_address) and _Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data) function which doesn't work. I am sure it has something to do with my function arguments. I am not too familiar with using pointers. The code below compiles without errors, but the LED does not flash as it is the case with the original sample code. I have referred MAX30003 ECG working Arduino code. See my both code below.
Any help is appreciated.
Regards,
rohit
#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "MAX30003.h"
#include <math.h>
#include <string.h>
#define SPI_INSTANCE 0 /**< SPI instance index. */
#define ECG_FIFO ((uint8_t)0x21)
#define RTOR ((uint8_t)0x25)
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
static volatile bool spi_xfer_done; /**< Flag used to indicate that SPI instance completed the transfer. */
//FOr ECG Tx Buffer
uint8_t SPI_RX_Buff[6]; /**< RX buffer. */
uint8_t SPI_TX_Buff[6]={6,5,4,3,2,25};
uint8_t ECG_length = sizeof(SPI_TX_Buff);
uint8_t dataToSend[1];
uint8_t A[1]=0xFF;
uint8_t A1[1]=0x00;
uint8_t ECG_FIFO_BURST1;
volatile char *SPI_RX_Buff_Ptr;
int i=0;
unsigned long uintECGraw = 0;
signed long intECGraw=0;
uint8_t DataPacketHeader[20];
uint8_t data_len = 8;
signed long ecgdata;
unsigned long data;
char SPI_temp_32b[4];
char SPI_temp_Burst[100];
static const uint8_t m_board_led_list[LEDS_NUMBER] = SPI_LIST;
/* As Reference from Aurdino Code */
//void bsp_board_toggle_pin(uint32_t pin_idx);
void timerIsr();
void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data);
void max30003_sw_reset(void);
void max30003_synch(void);
void MAX30003_Reg_Read(uint8_t Reg_address);
void MAX30003_Read_Data(int num_samples);
void MAX30003_begin();
void max30003_sw_reset(void)
{
nrf_gpio_pin_set(SPI_SS_PIN); //Slave select Set
nrf_gpio_pin_clear(SPI_SS_PIN); //Slave select High
MAX30003_Reg_Write(SW_RST,0x00); //As per Arduino Code
}
void max30003_synch(void){
MAX30003_Reg_Write(SYNCH,0x000000); //As per Arduino Code
}
void timerIsr(){
nrf_gpio_pin_toggle(NRF_FCLK_PIN); //As per Arduino Code
}
void MAX30003_begin(){
max30003_sw_reset();
nrf_delay_ms(100);
MAX30003_Reg_Write(CNFG_GEN, 0x081007);
nrf_delay_ms(100);
MAX30003_Reg_Write(CNFG_CAL, 0x720000); // 0x700000
nrf_delay_ms(100);
MAX30003_Reg_Write(CNFG_EMUX,0x0B0000);
nrf_delay_ms(100);
MAX30003_Reg_Write(CNFG_ECG, 0x005000); // d23 - d22 : 10 for 250sps , 00:500 sps
nrf_delay_ms(100);
MAX30003_Reg_Write(CNFG_RTOR1,0x3fc600);
max30003_synch();
nrf_delay_ms(100);
}
void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data) //Its Completed //for main.oerror
{
nrf_gpio_pin_clear(SPI_SS_PIN);
nrf_delay_ms(200);
WRITE_ADDRESS= WRITE_ADDRESS | WREG;
dataToSend[1]=WRITE_ADDRESS;
memset(SPI_RX_Buff, 0, ECG_length);
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)dataToSend[1], ECG_length, SPI_RX_Buff, ECG_length));
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data>>16), ECG_length, SPI_RX_Buff, ECG_length));
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data>>8), ECG_length, SPI_RX_Buff, ECG_length));
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data), ECG_length, SPI_RX_Buff, ECG_length));
nrf_delay_ms(200);
nrf_gpio_pin_set(SPI_SS_PIN);
}
void MAX30003_Read_Data(int num_samples) //Its Completed
{
nrf_gpio_pin_clear(SPI_SS_PIN); // as per arduino code
ECG_FIFO_BURST1 = (ECG_FIFO_BURST<<1 ) | RREG;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)ECG_FIFO_BURST1, ECG_length, SPI_RX_Buff, ECG_length));
for ( i = 0; i < num_samples*3; ++i)
{
SPI_temp_Burst[i] = (nrf_drv_spi_transfer(&spi, (const uint8_t *)A1[1], ECG_length, SPI_RX_Buff, ECG_length));
}
nrf_gpio_pin_set(SPI_SS_PIN); //it make High
}
void MAX30003_Reg_Read(uint8_t Reg_address) //Its Completed
{
nrf_gpio_pin_clear(SPI_SS_PIN); // as per arduino code
Reg_address= (Reg_address<<1 ) | RREG;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)Reg_address, ECG_length, SPI_RX_Buff, ECG_length));
for ( i = 0; i < 3; i++)
{
SPI_temp_32b[i]=(nrf_drv_spi_transfer(&spi, (const uint8_t *)A[1], ECG_length, SPI_RX_Buff, ECG_length));
}
nrf_gpio_pin_set(SPI_SS_PIN); //it make High
}
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
nrf_gpio_pin_set(SPI_SS_PIN);
spi_xfer_done = true;
NRF_LOG_INFO("Transfer completed.");
if (SPI_RX_Buff[0] != 0)
{
NRF_LOG_INFO(" Received:");
NRF_LOG_HEXDUMP_INFO(SPI_RX_Buff, strlen((const char *)SPI_RX_Buff));
}
}
int main(void)
{
char ECG_CHAR[30];
/*From Procentral upto line 222 */
MAX30003_Reg_Read(ECG_FIFO); //Its stuck
unsigned long data0 = (unsigned long) (SPI_temp_32b[0]);
data0 = data0 <<24;
unsigned long data1 = (unsigned long) (SPI_temp_32b[1]);
data1 = data1 <<16;
unsigned long data2 = (unsigned long) (SPI_temp_32b[2]);
data2 = data2 >>6;
data2 = data2 & 0x03;
data = (unsigned long) (data0 | data1 | data2);
ecgdata = (signed long) (data);
MAX30003_Reg_Read(RTOR); //Its stuck
unsigned long RTOR_msb = (unsigned long) (SPI_temp_32b[0]);
unsigned char RTOR_lsb = (unsigned char) (SPI_temp_32b[1]);
unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
rtor = ((rtor >>2) & 0x3fff);
float hr = 60 /((float)rtor*0.008);
unsigned int HR = (unsigned int)hr; // type cast to int
unsigned int RR = (unsigned int)rtor*8 ; //8ms
DataPacketHeader[0] = 0x0A;
DataPacketHeader[1] = 0xFA;
DataPacketHeader[2] = 0x0C;
DataPacketHeader[3] = 0;
DataPacketHeader[4] = 0x02;
DataPacketHeader[5] = ecgdata;
DataPacketHeader[6] = ecgdata>>8;
DataPacketHeader[7] = ecgdata>>16;
DataPacketHeader[8] = ecgdata>>24;
DataPacketHeader[9] = RR ;
DataPacketHeader[10] = RR >>8;
DataPacketHeader[11] = 0x00;
DataPacketHeader[12] = 0x00;
DataPacketHeader[13] = HR ;
DataPacketHeader[14] = HR >>8;
DataPacketHeader[15] = 0x00;
DataPacketHeader[16] = 0x00;
DataPacketHeader[17] = 0x00;
DataPacketHeader[18] = 0x0b;
bsp_board_init(BSP_INIT_LEDS);
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.ss_pin = SPI_SS_PIN; //29
spi_config.miso_pin = SPI_MISO_PIN; //28
spi_config.mosi_pin = SPI_MOSI_PIN; //4
spi_config.sck_pin = SPI_SCK_PIN; //3
nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);
NRF_LOG_INFO("SPI example started.");
while (1)
{
// Reset rx buffer and transfer done flag
memset(SPI_RX_Buff, 0, ECG_length);
spi_xfer_done = false;
for(i=0; i<19; i++) // transmit the data
{
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)SPI_TX_Buff, ECG_length, SPI_RX_Buff, ECG_length));
}
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
bsp_board_led_invert(BSP_BOARD_LED_0);
nrf_delay_ms(200);
}
}
#include<SPI.h>
#include <TimerOne.h>
#include "MAX30003.h"
#define MAX30003_CS_PIN 7
#define CLK_PIN 6
volatile char SPI_RX_Buff[5] ;
volatile char *SPI_RX_Buff_Ptr;
int i=0;
unsigned long uintECGraw = 0;
signed long intECGraw=0;
uint8_t DataPacketHeader[20];
uint8_t data_len = 8;
signed long ecgdata;
unsigned long data;
char SPI_temp_32b[4];
char SPI_temp_Burst[100];
// 32KHz clock using timer1
void timerIsr()
{
digitalWrite( CLK_PIN, digitalRead(CLK_PIN ) ^ 1 ); // toggle Digital6 attached to FCLK of MAX30003
}
void setup()
{
Serial.begin(115200); //Serial begin
pinMode(MAX30003_CS_PIN,OUTPUT);
digitalWrite(MAX30003_CS_PIN,HIGH); //disable device
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV4);
pinMode(CLK_PIN,OUTPUT);
MAX30003_begin(); // initialize MAX30003
}
void loop()
{
MAX30003_Reg_Read(ECG_FIFO);
unsigned long data0 = (unsigned long) (SPI_temp_32b[0]);
data0 = data0 <<24;
unsigned long data1 = (unsigned long) (SPI_temp_32b[1]);
data1 = data1 <<16;
unsigned long data2 = (unsigned long) (SPI_temp_32b[2]);
data2 = data2 >>6;
data2 = data2 & 0x03;
data = (unsigned long) (data0 | data1 | data2);
ecgdata = (signed long) (data);
MAX30003_Reg_Read(RTOR);
unsigned long RTOR_msb = (unsigned long) (SPI_temp_32b[0]);
// RTOR_msb = RTOR_msb <<8;
unsigned char RTOR_lsb = (unsigned char) (SPI_temp_32b[1]);
unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
rtor = ((rtor >>2) & 0x3fff) ;
float hr = 60 /((float)rtor*0.008);
unsigned int HR = (unsigned int)hr; // type cast to int
unsigned int RR = (unsigned int)rtor*8 ; //8ms
/*Serial.print(RTOR_msb);
Serial.print(",");
Serial.print(RTOR_lsb);
Serial.print(",");
Serial.print(rtor);
Serial.print(",");
Serial.print(rr);
Serial.print(",");
Serial.println(hr); */
DataPacketHeader[0] = 0x0A;
DataPacketHeader[1] = 0xFA;
DataPacketHeader[2] = 0x0C;
DataPacketHeader[3] = 0;
DataPacketHeader[4] = 0x02;
DataPacketHeader[5] = ecgdata;
DataPacketHeader[6] = ecgdata>>8;
DataPacketHeader[7] = ecgdata>>16;
DataPacketHeader[8] = ecgdata>>24;
DataPacketHeader[9] = RR ;
DataPacketHeader[10] = RR >>8;
DataPacketHeader[11] = 0x00;
DataPacketHeader[12] = 0x00;
DataPacketHeader[13] = HR ;
DataPacketHeader[14] = HR >>8;
DataPacketHeader[15] = 0x00;
DataPacketHeader[16] = 0x00;
DataPacketHeader[17] = 0x00;
DataPacketHeader[18] = 0x0b;
for(i=0; i<19; i++) // transmit the data
{
Serial.write(DataPacketHeader[i]);
}
delay(1);
}
void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data)
{
// now combine the register address and the command into one byte:
byte dataToSend = (WRITE_ADDRESS<<1) | WREG;
// take the chip select low to select the device:
digitalWrite(MAX30003_CS_PIN, LOW);
delay(2);
SPI.transfer(dataToSend); //Send register location
SPI.transfer(data>>16); //number of register to wr
SPI.transfer(data>>8); //number of register to wr
SPI.transfer(data); //Send value to record into register
delay(2);
// take the chip select high to de-select:
digitalWrite(MAX30003_CS_PIN, HIGH);
}
void max30003_sw_reset(void)
{
MAX30003_Reg_Write(SW_RST,0x000000);
delay(100);
}
void max30003_synch(void)
{
MAX30003_Reg_Write(SYNCH,0x000000);
}
void MAX30003_Reg_Read(uint8_t Reg_address)
{
uint8_t SPI_TX_Buff;
digitalWrite(MAX30003_CS_PIN, LOW);
SPI_TX_Buff = (Reg_address<<1 ) | RREG;
SPI.transfer(SPI_TX_Buff); //Send register location
for ( i = 0; i < 3; i++)
{
SPI_temp_32b[i] = SPI.transfer(0xff);
}
digitalWrite(MAX30003_CS_PIN, HIGH);
}
void MAX30003_Read_Data(int num_samples)
{
uint8_t SPI_TX_Buff;
digitalWrite(MAX30003_CS_PIN, LOW);
SPI_TX_Buff = (ECG_FIFO_BURST<<1 ) | RREG;
SPI.transfer(SPI_TX_Buff); //Send register location
for ( i = 0; i < num_samples*3; ++i)
{
SPI_temp_Burst[i] = SPI.transfer(0x00);
}
digitalWrite(MAX30003_CS_PIN, HIGH);
}
void MAX30003_begin()
{
//Start CLK timer
Timer1.initialize(16); // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second)
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
max30003_sw_reset();
delay(100);
MAX30003_Reg_Write(CNFG_GEN, 0x081007);
delay(100);
MAX30003_Reg_Write(CNFG_CAL, 0x720000); // 0x700000
delay(100);
MAX30003_Reg_Write(CNFG_EMUX,0x0B0000);
delay(100);
MAX30003_Reg_Write(CNFG_ECG, 0x005000); // d23 - d22 : 10 for 250sps , 00:500 sps
delay(100);
MAX30003_Reg_Write(CNFG_RTOR1,0x3fc600);
max30003_synch();
delay(100);
}