Hello,
I tried to check SPI communication with a test board.
However, I couldn't read the device info from the max30003wing board.
Board: NRF52840DK --> MAX30003WING Using SPI.
SDK: nRF5_SDK_17.1.0_ddde560
this is my code
#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"
#define HIGH 1
#define LOW 0
#define WREG 0x00
#define RREG 0x01
#define SPI_TIMEOUT 50000
#define NO_OP 0x00
#define STATUS 0x01
#define EN_INT 0x02
#define EN_INT2 0x03
#define MNGR_INT 0x04
#define MNGR_DYN 0x05
#define SW_RST 0x08
#define SYNCH 0x09
#define FIFO_RST 0x0A
#define INFO 0x0F
#define CNFG_GEN 0x10
#define CNFG_CAL 0x12
#define CNFG_EMUX 0x14
#define CNFG_ECG 0x15
#define CNFG_RTOR1 0x1D
#define CNFG_RTOR2 0x1E
#define ECG_FIFO_BURST 0x20
#define ECG_FIFO 0x21
#define RTOR 0x25
#define NO_OP 0x7F
#define MAX30003_CLK_PIN 3
#define MAX30003_MOSI_PIN 4
#define MAX30003_MISO_PIN 28
#define MAX30003_CS_PIN 29
#define RTOR_INTR_MASK 0x04
#define AFE_SPI_INSTANCE 0
const nrf_drv_spi_t afe_spi = NRF_DRV_SPI_INSTANCE(AFE_SPI_INSTANCE); /**< SPI instance. */
volatile bool afe_spi_xfer_done; /**< Flag used to indicate that SPI instance completed the transfer. */
unsigned int heartRate;
unsigned int RRinterval;
signed long ecgdata;
typedef enum
{
SAMPLINGRATE_128 = 128, SAMPLINGRATE_256 = 256, SAMPLINGRATE_512 = 512
}sampRate;
void max30003RegWrite (unsigned char WRITE_ADDRESS, unsigned long data)
{
uint32_t err_code;
uint32_t timeout = SPI_TIMEOUT;
uint8_t dataToSend[4] = {0x00,} ;
afe_spi_xfer_done = false;
// now combine the register address and the command into one byte:
dataToSend[0] = (WRITE_ADDRESS<<1) | WREG;
dataToSend[1] = (data>>16);
dataToSend[2] = (data>>8);
dataToSend[3] = (data);
// take the chip select low to select the device:
nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
nrf_delay_ms(2);
err_code = nrf_drv_spi_transfer(&afe_spi, &dataToSend, 4, NULL, 0);
nrf_delay_ms(2);
// take the chip select high to de-select:
nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
while((!afe_spi_xfer_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
}
void max30003SwReset(void)
{
max30003RegWrite(SW_RST,0x000000);
nrf_delay_ms(100);
}
void max30003Synch(void)
{
max30003RegWrite(SYNCH,0x000000);
}
void max30003RegRead(uint8_t Reg_address, uint8_t * buff)
{
uint32_t err_code;
uint32_t timeout = SPI_TIMEOUT;
uint8_t spiTxBuff;
afe_spi_xfer_done = false;
nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
nrf_delay_ms(2);
spiTxBuff = (Reg_address<<1 ) | RREG;
err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, buff, 4);
nrf_delay_ms(2);
nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
if(err_code != NRF_SUCCESS) return err_code;
while((!afe_spi_xfer_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
}
ret_code_t max30003ReadStatus(void)
{
uint32_t err_code;
uint32_t timeout = SPI_TIMEOUT;
uint8_t spiTxBuff;
uint8_t readBuff[4] ;
afe_spi_xfer_done = false;
spiTxBuff = (STATUS << 1 ) | RREG;
nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
nrf_delay_ms(2);
err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
nrf_delay_ms(2);
nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
if(err_code != NRF_SUCCESS) return err_code;
while((!afe_spi_xfer_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
return NRF_SUCCESS;
}
ret_code_t max30003ReadInfo(void)
{
uint32_t err_code;
uint32_t timeout = SPI_TIMEOUT;
uint8_t spiTxBuff;
uint8_t readBuff[4] = {0x00,} ;
afe_spi_xfer_done = false;
spiTxBuff = (INFO << 1 ) | RREG;
nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
nrf_delay_ms(2);
err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
nrf_delay_ms(2);
nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
if(err_code != NRF_SUCCESS) return err_code;
while((!afe_spi_xfer_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
//afe_spi_xfer_done = false;
if((readBuff[0]&0xf0) == 0x50 ){
NRF_LOG_INFO("max30003 is ready");
NRF_LOG_INFO("Rev ID: 0x%02x", (readBuff[0]&0xf0));
}else{
NRF_LOG_INFO("max30003 read info error\n");
NRF_LOG_INFO("Rev ID: 0x%02x", (readBuff[0]&0xf0));
return NRF_ERROR_NOT_FOUND;
}
return NRF_SUCCESS;
}
void max30003ReadData(int num_samples, uint8_t * readBuffer)
{
uint32_t err_code;
uint32_t timeout = SPI_TIMEOUT;
uint8_t spiTxBuff;
uint8_t readBuff[4] ;
nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
nrf_delay_ms(2);
spiTxBuff = (ECG_FIFO_BURST<<1 ) | RREG;
err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
nrf_delay_ms(2);
nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
if(err_code != NRF_SUCCESS) return err_code;
while((!afe_spi_xfer_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
}
void max30003Begin()
{
max30003SwReset();
nrf_delay_ms(100);
max30003RegWrite(CNFG_GEN, 0x081007);
nrf_delay_ms(100);
max30003RegWrite(CNFG_CAL, 0x720000); // 0x700000
nrf_delay_ms(100);
max30003RegWrite(CNFG_EMUX,0x0B0000);
nrf_delay_ms(100);
max30003RegWrite(CNFG_ECG, 0x805000); // d23 - d22 : 10 for 250sps , 00:500 sps
nrf_delay_ms(100);
max30003RegWrite(CNFG_RTOR1,0x3fc600);
max30003Synch();
nrf_delay_ms(100);
}
void max30003BeginRtorMode()
{
max30003SwReset();
nrf_delay_ms(100);
max30003RegWrite(CNFG_GEN, 0x080004);
nrf_delay_ms(100);
max30003RegWrite(CNFG_CAL, 0x720000); // 0x700000
nrf_delay_ms(100);
max30003RegWrite(CNFG_EMUX,0x0B0000);
nrf_delay_ms(100);
max30003RegWrite(CNFG_ECG, 0x805000); // d23 - d22 : 10 for 250sps , 00:500 sps
nrf_delay_ms(100);
max30003RegWrite(CNFG_RTOR1,0x3fc600);
nrf_delay_ms(100);
max30003RegWrite(EN_INT, 0x000401);
nrf_delay_ms(100);
max30003Synch();
nrf_delay_ms(100);
}
//not tested
void max30003SetsamplingRate(uint16_t samplingRate)
{
uint8_t regBuff[4] = {0};
max30003RegRead(CNFG_ECG, regBuff);
switch(samplingRate){
case SAMPLINGRATE_128:
regBuff[0] = (regBuff[0] | 0x80 );
break;
case SAMPLINGRATE_256:
regBuff[0] = (regBuff[0] | 0x40 );
break;
case SAMPLINGRATE_512:
regBuff[0] = (regBuff[0] | 0x00 );
break;
default :
break;
}
unsigned long cnfgEcg;
memcpy(&cnfgEcg, regBuff, 4);
max30003RegWrite(CNFG_ECG, (cnfgEcg >> 8));
}
void getEcgSamples(void)
{
uint8_t regReadBuff[4];
max30003RegRead(ECG_FIFO, regReadBuff);
unsigned long data0 = (unsigned long) (regReadBuff[0]);
data0 = data0 <<24;
unsigned long data1 = (unsigned long) (regReadBuff[1]);
data1 = data1 <<16;
unsigned long data2 = (unsigned long) (regReadBuff[2]);
data2 = data2 >>6;
data2 = data2 & 0x03;
unsigned long data = (unsigned long) (data0 | data1 | data2);
ecgdata = (signed long) (data);
printf("ecgdata(%d) \r\n", ecgdata);
}
void getHRandRR(void)
{
uint8_t regReadBuff[4];
max30003RegRead(RTOR, regReadBuff);
unsigned long RTOR_msb = (unsigned long) (regReadBuff[0]);
unsigned char RTOR_lsb = (unsigned char) (regReadBuff[1]);
unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
rtor = ((rtor >>2) & 0x3fff) ;
float hr = 60 /((float)rtor*0.0078125);
heartRate = (unsigned int)hr;
unsigned int RR = (unsigned int)rtor* (7.8125) ; //8ms
RRinterval = RR;
}
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
afe_spi_xfer_done = true;
}
int main(void)
{
uint32_t err_code;
bsp_board_init(BSP_INIT_LEDS);
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
nrf_gpio_cfg_output(MAX30003_CS_PIN);
nrf_gpio_pin_write(MAX30003_CS_PIN, 1);
nrfx_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.frequency = NRF_SPI_FREQ_1M;
spi_config.ss_pin = MAX30003_CS_PIN;
spi_config.miso_pin = MAX30003_MISO_PIN;
spi_config.mosi_pin = MAX30003_MOSI_PIN;
spi_config.sck_pin = MAX30003_CLK_PIN;
//spi_config.mode = NRF_SPI_MODE_0;
APP_ERROR_CHECK(nrf_drv_spi_init(&afe_spi, &spi_config, spi_event_handler, NULL));
//APP_ERROR_CHECK(nrf_drv_spi_init(&afe_spi, &spi_config, NULL, NULL));
NRF_LOG_INFO("NRFX SPI example started.");
nrf_delay_ms(2);
err_code = max30003ReadInfo();
nrf_delay_ms(2);
while (1)
{
// Reset rx buffer and transfer done flag
//memset(m_rx_buf, 0, m_length);
//spi_xfer_done = false;
//APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));
while (!afe_spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
bsp_board_led_invert(BSP_BOARD_LED_0);
nrf_delay_ms(200);
#endif
}
}

I don't know what is wrong. Is the problems with the SPI read function?
Please any help is appreciated.
Regards,
ray
