diff --git a/app/src/board/ads129x/ads129x.c b/app/src/board/ads129x/ads129x.c index c2bd6a4..c5c92f9 100644 --- a/app/src/board/ads129x/ads129x.c +++ b/app/src/board/ads129x/ads129x.c @@ -3,6 +3,34 @@ #include "ads129x_type.h" #include "board/app_board.h" +/** + * @brief ads129x 使用注意事项 + * + * ads129x SPI 通信格式 + * + * [cmd 8bit] [data nbit] + * + * + * ads129x 支持的指令如下 + * 唤醒 (0x02) + * 待机 (0x04) + * 复位 (0x06) + * 开始转换 (0x08) + * 停止 (0x0A) + * 通道偏移校准 (0x1A) + * 使能数据连续读模式 (0x10) + * 停止数据连续读模式 (0x11) + * 读数据 (0x12) + * 读寄存器 (0x2x) + * 写寄存器 (0x4x) + * + * + * 注意事项: + * 1. 当ads129x处于连续读模式下,寄存器读写指令失效 + * 2. 不进入连续模式下,可以通过[读数据]指令,读取数据,此时寄存器操作指令是有效的 + * + */ + #define ADS129X_CS_SET() nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN); #define ADS129X_CS_RESET() nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); #define ADS129X_START_SET() nrf_gpio_pin_set(ADS1291_START_PIN); @@ -14,10 +42,11 @@ static void port_ads129x_delay_us(uint32_t us) { nrf_delay_us(us); } static void port_ads129x_delay_ms(uint32_t ms) { nrf_delay_ms(ms); } +#define port_delay_ms port_ads129x_delay_ms + /*********************************************************************************************************************** * BASE_FUNCTION_IMPL * ***********************************************************************************************************************/ -static ads129x_regs_t ads129X_reg = {0}; uint8_t port_spi_transmit_receive(uint8_t tx) { uint8_t data; @@ -103,6 +132,41 @@ void ads129X_read_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) { ADS129X_CS_SET(); } +static void ads129x_readback_reg(ads129x_regs_t* regcache) { ads129X_read_multiregs(ADS129X_REG_ID, (uint8_t*)regcache, sizeof(ads129x_regs_t)); } +static void ads129x_dump_reg(ads129x_regs_t* regcache) { + ZLOGI("id : %x", regcache->id); + ZLOGI("cfg1 : %x", regcache->cfg1); + ZLOGI("cfg2 : %x", regcache->cfg2); + ZLOGI("loff : %x", regcache->loff); + ZLOGI("ch1set : %x", regcache->ch1set); + ZLOGI("ch2set : %x", regcache->ch2set); + ZLOGI("rld_sens : %x", regcache->rld_sens); + ZLOGI("loff_sens : %x", regcache->loff_sens); + ZLOGI("loff_stat : %x", regcache->loff_stat); + ZLOGI("resp1 : %x", regcache->resp1); + ZLOGI("resp2 : %x", regcache->resp2); + ZLOGI("gpio : %x", regcache->gpio); +} + +static bool ads129x_write_reg(ads129x_regs_t* writeval) { + static ads129x_regs_t rdbak; + ads129X_write_multiregs(ADS129X_REG_ID, (uint8_t*)writeval, sizeof(ads129x_regs_t)); + ads129X_read_multiregs(ADS129X_REG_ID, (uint8_t*)&rdbak, sizeof(ads129x_regs_t)); + + writeval->id = 0; + writeval->loff_stat = writeval->loff_stat & (0x01 << 6); + + rdbak.id = 0; + rdbak.loff_stat = rdbak.loff_stat & (0x01 << 6); + + if (memcmp(writeval, &rdbak, sizeof(ads129x_regs_t)) != 0) { + ZLOGE("ads129x_write_reg reg fail"); + return false; + } + ZLOGI("ads129x_write_reg reg success"); + return true; +} + /*********************************************************************************************************************** * EXTERN * ***********************************************************************************************************************/ @@ -129,7 +193,9 @@ uint8_t ads129x_init() { nrf_gpio_pin_set(ADS1291_PWDN_PIN); nrf_delay_ms(2000); - char txdata[] = {1, 2, 3, 4}; + + ads129x_start_capture(true); + // char txdata[] = {1, 2, 3, 4}; while (true) /* 识别芯片型号,1291:0x52 */ { uint8_t id = ads129X_rw_reg(ADS129X_COMMAND_RREG | ADS129X_REG_ID, 0); @@ -141,11 +207,90 @@ uint8_t ads129x_init() { } } -uint8_t ads129x_start_capture(uint8_t* cfg, bool test) { return 0; } +void ads129x_read_data_loop() { + ads129x_capture_data_t capture_data; + while (true) { + while (ADS129X_DRDY_GET()) + ; + + ads129x_read_data(&capture_data); + ZLOGI("{%d}", capture_data.ch0data); + } +} + +uint8_t ads129x_start_capture(bool test) { + ads129X_send_cmd(ADS129X_COMMAND_SDATAC); /* 进入停止连续读模式 */ + port_delay_ms(100); + + static ads129x_regs_t regcache; + ads129x_readback_reg(®cache); + ads129x_dump_reg(®cache); + + regcache.cfg1 = 0x02; + regcache.cfg2 = 0xE0; + regcache.loff = 0xF0; + regcache.ch1set = 0x00; + regcache.ch2set = 0x00; + regcache.rld_sens = 0x20; + regcache.loff_sens = 0x03; + + if (test) { + regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON); + regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC); + regcache.ch1set = ADS129X_SET_BITS(regcache.ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST); + regcache.ch2set = ADS129X_SET_BITS(regcache.ch2set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST); + } + + ads129x_write_reg(®cache); + + port_delay_ms(10); + ads129X_send_cmd(ADS129X_COMMAND_START); /* 发送开始数据转换(等效于拉高START引脚) */ + port_delay_ms(10); + + ads129x_read_data_loop(); +} + +static int32_t i24toi32(uint8_t* p_i32) { + int32_t rev = 0; + rev = (((int32_t)p_i32[0]) << 16) | (((int32_t)p_i32[1]) << 8) | ((int32_t)p_i32[2]); + if ((p_i32[0] & 0x80) == 0x80) { + rev |= 0xFF000000; + } + return rev; +} + +void ads129x_read_data(ads129x_capture_data_t* capture_data) { + uint8_t rddata[9]; + + ADS129X_CS_RESET(); /* 选中设备 */ + port_ads129x_delay_us(10); + + port_spi_transmit_receive(ADS129X_COMMAND_RDATA); + port_ads129x_delay_us(1); + for (int i = 0; i < 9; i++) { + rddata[i] = port_spi_transmit_receive(0); + } + ADS129X_CS_SET(); + + /** + * @brief + * + * 回读数据格式(datasheet page 42) + * 24bit status (1100 + LOFF_STAT[4:0] + GPIO[1:0] + 13`b0) + * 24bit ch0 MSB + * 24bit ch1 MSB + * + */ + capture_data->loffstate = rddata[0]; + capture_data->gpio0 = rddata[0]; + capture_data->gpio1 = rddata[0]; + capture_data->ch0data = i24toi32(&rddata[3]); + capture_data->ch1data = i24toi32(&rddata[6]); +} + uint8_t ads129x_enter_low_power_mode() { return 0; } uint8_t ads129x_enter_lead_off_detect_mode() { return 0; } -uint8_t ads129x_data_is_ready() { return 0; } -void ads129x_read_data(uint8_t* data, uint8_t len) {} +uint8_t ads129x_data_is_ready() { return ADS129X_DRDY_GET(); } uint8_t ads129x_get_lead_off_state() { return 0; } \ No newline at end of file diff --git a/app/src/board/ads129x/ads129x.h b/app/src/board/ads129x/ads129x.h index d9047fe..408d687 100644 --- a/app/src/board/ads129x/ads129x.h +++ b/app/src/board/ads129x/ads129x.h @@ -6,18 +6,40 @@ extern "C" { #include #include +typedef struct { + /** + * @brief + * + * loffstate: + * bit4 RLD_STAT + * bit3 IN2N_OFF + * bit2 IN2P_OFF + * bit1 IN1N_OFF + * bit0 IN1P_OFF + * + */ + + uint8_t loffstate; + + uint8_t gpio0; + uint8_t gpio1; + + uint32_t ch0data; + uint32_t ch1data; +} ads129x_capture_data_t; + /** * @brief 初始化SPI */ uint8_t ads129x_init(); -uint8_t ads129x_start_capture(uint8_t* cfg, bool test); +uint8_t ads129x_start_capture(bool test); uint8_t ads129x_enter_low_power_mode(); uint8_t ads129x_enter_lead_off_detect_mode(); uint8_t ads129x_data_is_ready(); -void ads129x_read_data(uint8_t* data, uint8_t len); +void ads129x_read_data(ads129x_capture_data_t* rddata); uint8_t ads129x_get_lead_off_state(); diff --git a/app/src/board/ads129x/ads129x_type.h b/app/src/board/ads129x/ads129x_type.h index fc387b1..d3a5cf6 100644 --- a/app/src/board/ads129x/ads129x_type.h +++ b/app/src/board/ads129x/ads129x_type.h @@ -235,21 +235,21 @@ typedef struct { * @{ */ /* System Commands */ -#define ADS129X_COMMAND_WAKEUP 0x02 -#define ADS129X_COMMAND_STANDBY 0x04 -#define ADS129X_COMMAND_RESET 0x06 -#define ADS129X_COMMAND_START 0x08 -#define ADS129X_COMMAND_STOP 0x0A -#define ADS129X_COMMAND_OFFSETCAL 0x1A +#define ADS129X_COMMAND_WAKEUP 0x02 // Wake-up from standby mode +#define ADS129X_COMMAND_STANDBY 0x04 // Enter standby mode +#define ADS129X_COMMAND_RESET 0x06 // Reset the device +#define ADS129X_COMMAND_START 0x08 // Start or restart (synchronize) conversion +#define ADS129X_COMMAND_STOP 0x0A // Stop conversion +#define ADS129X_COMMAND_OFFSETCAL 0x1A // Channel offset calibration /* Data Read Commands */ -#define ADS129X_COMMAND_RDATAC 0x10 -#define ADS129X_COMMAND_SDATAC 0x11 -#define ADS129X_COMMAND_RDATA 0x12 +#define ADS129X_COMMAND_RDATAC 0x10 // Enable Read Data Continuous mode. This mode is the default mode at power-up.(1) +#define ADS129X_COMMAND_SDATAC 0x11 // Stop Read Data Continuously mode +#define ADS129X_COMMAND_RDATA 0x12 // Read data by command; supports multiple read back /* Register Read Commands,最后5位为读写的地址 */ -#define ADS129X_COMMAND_RREG 0x20 -#define ADS129X_COMMAND_WREG 0x40 +#define ADS129X_COMMAND_RREG 0x20 // Read n nnnn registers starting at address r rrrr +#define ADS129X_COMMAND_WREG 0x40 // Write n nnnn registers starting at address r rrrr /** * @} */ diff --git a/app/src/one_conduction_main.c b/app/src/one_conduction_main.c index 1d17d9f..9ad11e4 100644 --- a/app/src/one_conduction_main.c +++ b/app/src/one_conduction_main.c @@ -432,6 +432,10 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) { void one_conduction_main() { ZLOGI("one_conduction_main"); + + app_board_init(); + ads129x_init(); + BoardBeepCtrl_init(); AppEvent_regListener(app_event_listener); @@ -447,8 +451,6 @@ void one_conduction_main() { BoardEcgSensor_init(); BoardLight_Init(); BoardBattery_load(); - app_board_init(); - ads129x_init(); // power_on(); #if 0