Add timer via ADS1298_STATS flag

This commit is contained in:
Musa Mahmood 2025-04-13 20:46:59 -04:00
parent e7e4053f60
commit 3688db710a
4 changed files with 80 additions and 39 deletions

View File

@ -76,10 +76,11 @@ void ads1298_initialize(ads1298_info_t *p_info) {
spi_config.miso_pin = ADS1298_MISO_PIN; spi_config.miso_pin = ADS1298_MISO_PIN;
spi_config.mosi_pin = ADS1298_MOSI_PIN; spi_config.mosi_pin = ADS1298_MOSI_PIN;
spi_config.sck_pin = ADS1298_SCK_PIN; spi_config.sck_pin = ADS1298_SCK_PIN;
spi_config.frequency = NRF_DRV_SPI_FREQ_500K; //spi_config.frequency = NRF_DRV_SPI_FREQ_125K;
//spi_config.frequency = NRF_DRV_SPI_FREQ_1M; //spi_config.frequency = NRF_DRV_SPI_FREQ_500K;
spi_config.frequency = NRF_DRV_SPI_FREQ_1M;
//spi_config.frequency = NRF_DRV_SPI_FREQ_2M; //spi_config.frequency = NRF_DRV_SPI_FREQ_2M;
spi_config.irq_priority = APP_IRQ_PRIORITY_HIGHEST; //spi_config.irq_priority = APP_IRQ_PRIORITY_HIGHEST;
spi_config.mode = NRF_DRV_SPI_MODE_1; spi_config.mode = NRF_DRV_SPI_MODE_1;
spi_config.orc = 0x55; spi_config.orc = 0x55;

View File

@ -65,19 +65,18 @@
#define ADS129x_8CH_BITMASK 0x02 // 0x[...]10[010] #define ADS129x_8CH_BITMASK 0x02 // 0x[...]10[010]
/** DEFAULT REGISTER VALUES **/ /** DEFAULT REGISTER VALUES **/
//#define ADS1298_REGDEFAULT_CONFIG1 0x05 // Low power mode, Daisy-chain mode, clk output disabled, LP: 250 SPS #define ADS1298_REGDEFAULT_CONFIG1 0xC6 // High-res mode, Multiple readback mode, clk output disabled, LP: 250 SPS
#define ADS1298_REGDEFAULT_CONFIG1 0x46 // Low power mode, Multiple readback mode, clk output disabled, LP: 250 SPS
#define ADS1298_REGDEFAULT_CONFIG2 0x00 // Test signals #define ADS1298_REGDEFAULT_CONFIG2 0x00 // Test signals
#define ADS1298_REGDEFAULT_CONFIG3 0xCC // #define ADS1298_REGDEFAULT_CONFIG3 0xCE //
#define ADS1298_REGDEFAULT_LOFF 0x00 #define ADS1298_REGDEFAULT_LOFF 0x00
#define ADS1298_REGDEFAULT_CH1SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH1SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH2SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH2SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH3SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH3SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH4SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH4SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH5SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH5SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH6SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH6SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH7SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH7SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_CH8SET 0x01 // Input Short (for startup) #define ADS1298_REGDEFAULT_CH8SET 0x81 // Input Short (for startup)
#define ADS1298_REGDEFAULT_RLD_SENSP 0x00 #define ADS1298_REGDEFAULT_RLD_SENSP 0x00
#define ADS1298_REGDEFAULT_RLD_SENSN 0x00 #define ADS1298_REGDEFAULT_RLD_SENSN 0x00
#define ADS1298_REGDEFAULT_LOFF_SENSP 0x00 #define ADS1298_REGDEFAULT_LOFF_SENSP 0x00
@ -110,7 +109,10 @@ typedef struct {
char usb_buffer[USBD_MAX_SIZE]; char usb_buffer[USBD_MAX_SIZE];
uint8_t usb_buffer_count; uint8_t usb_buffer_count;
uint8_t usb_buffer_size_max; uint8_t usb_buffer_size_max;
#if ADS1298_STATS
uint32_t drdy_trigger_count; uint32_t drdy_trigger_count;
uint32_t seconds_elapsed;
#endif
} ads1298_info_t; } ads1298_info_t;
/** FUNCTION PROTOTYPES **/ /** FUNCTION PROTOTYPES **/

85
main.c
View File

@ -86,6 +86,7 @@ void reset_counters(void) {
reset_buffer_count(m_info.usb_buffer); reset_buffer_count(m_info.usb_buffer);
// #TODO: Clear stats: // #TODO: Clear stats:
m_info.drdy_trigger_count = 0; m_info.drdy_trigger_count = 0;
m_info.seconds_elapsed = 0;
// #TODO: elapsed time Milliseconds (need last second timer). // #TODO: elapsed time Milliseconds (need last second timer).
#endif #endif
} }
@ -115,11 +116,14 @@ void write_ic_settings(uint8_t* new_packet) {
case TN_IC_ADS1298: { case TN_IC_ADS1298: {
// #TODO: &new_packet[1] // #TODO: &new_packet[1]
#if ADS1298 #if ADS1298
ads1298_stop_rdatac();
NRF_LOG_INFO("Writing new ADS1298 registers:"); NRF_LOG_INFO("Writing new ADS1298 registers:");
NRF_LOG_HEXDUMP_INFO(&new_packet[1], ADS1298_REGISTER_COUNT); NRF_LOG_HEXDUMP_INFO(&new_packet[1], ADS1298_REGISTER_COUNT);
memcpy(m_info.registers, &new_packet[1], ADS1298_REGISTER_COUNT); memcpy(m_info.registers, &new_packet[1], ADS1298_REGISTER_COUNT);
ads1298_update_registers(&m_info); ads1298_update_registers(&m_info);
ads1298_set_data_buffer_length(&m_info); ads1298_set_data_buffer_length(&m_info);
ads1298_start_rdatac();
ads1298_standby();
// #TODO: readback registers into m_info.registers to confirm correct write. // #TODO: readback registers into m_info.registers to confirm correct write.
#endif #endif
} break; } break;
@ -132,9 +136,9 @@ void read_ic_settings(uint8_t* new_packet) {
switch (SECOND_NIBBLE(new_packet[0])) { switch (SECOND_NIBBLE(new_packet[0])) {
case TN_IC_ADS1298: { case TN_IC_ADS1298: {
// #NOTE: you will not be able to read registers while in RDATAC mode. // #NOTE: you will not be able to read registers while in RDATAC mode.
ads1298_stop_rdatac();
// ads1298_check_id(&m_info);
// ads1298_check_id(&m_info);
ads1298_stop_rdatac();
// read all registers into m_info.registers // read all registers into m_info.registers
ads1298_readback_registers(&m_info); ads1298_readback_registers(&m_info);
// Send back over USB. // Send back over USB.
@ -172,6 +176,7 @@ static void process_new_packet(uint8_t* new_packet) {
NRF_LOG_INFO("[ADS129x] Active channels: 0x%X", m_info.active_chs); NRF_LOG_INFO("[ADS129x] Active channels: 0x%X", m_info.active_chs);
} }
#endif #endif
reset_counters();
} }
if (SECOND_NIBBLE(new_packet[0]) == TN_STREAM_STOP) { if (SECOND_NIBBLE(new_packet[0]) == TN_STREAM_STOP) {
recording_mode = RECORDING_MODE_DISABLED; recording_mode = RECORDING_MODE_DISABLED;
@ -236,18 +241,6 @@ static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
process_new_packet(usb_read_buffer); process_new_packet(usb_read_buffer);
// if (usb_read_buffer[0] == 0xBE) {
// }
// if (usb_read_buffer[0] == 0xEF) {
// run_throughput_test = true;
// }
// if (usb_read_buffer[0] == 0xE1) {
// run_throughput_test = false;
// }
// NRF_LOG_INFO("Received packet; first byte: 0x%X", new_packet[0]);
/* Fetch data until internal buffer is empty */ /* Fetch data until internal buffer is empty */
ret = app_usbd_cdc_acm_read(&m_app_cdc_acm, usb_read_buffer, READ_SIZE); ret = app_usbd_cdc_acm_read(&m_app_cdc_acm, usb_read_buffer, READ_SIZE);
} while (ret == NRF_SUCCESS); } while (ret == NRF_SUCCESS);
@ -291,15 +284,12 @@ static void usbd_user_ev_handler(app_usbd_event_type_t event) {
} }
} }
void idle_state_handle(void) {
}
#if ADS1298 #if ADS1298
void drdy_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void drdy_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
UNUSED_PARAMETER(pin); UNUSED_PARAMETER(pin);
UNUSED_PARAMETER(action); UNUSED_PARAMETER(action);
drdy_flag = true; drdy_flag = true;
m_info.drdy_trigger_count += 1;
} }
void ads1298_interrupt_setup(void) { void ads1298_interrupt_setup(void) {
@ -323,6 +313,38 @@ void ads1298_interrupt_setup(void) {
} }
#endif #endif
#if ADS1298_STATS
APP_TIMER_DEF(ads_timer_id);
#define APP_TIMER_INTERVAL APP_TIMER_TICKS(1000) // 1 second.
static volatile bool ads_timer_timeout = false;
static void ads_timer_timeout_handler(void* p_context) {
UNUSED_PARAMETER(p_context);
ads_timer_timeout = true;
m_info.seconds_elapsed += 1;
}
#endif
static void application_timers_start(void) {
#if ADS1298_STATS
ret_code_t err_code;
err_code = app_timer_start(ads_timer_id, APP_TIMER_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
#endif
}
static void timers_init(void) {
ret_code_t ret = app_timer_init();
APP_ERROR_CHECK(ret);
#if ADS1298_STATS
ret_code_t err_code =
app_timer_create(&ads_timer_id, APP_TIMER_MODE_REPEATED, ads_timer_timeout_handler);
APP_ERROR_CHECK(err_code);
#endif
}
int main(void) { int main(void) {
ret_code_t ret; ret_code_t ret;
static const app_usbd_config_t usbd_config = { static const app_usbd_config_t usbd_config = {
@ -342,8 +364,7 @@ int main(void) {
// Wait for LFCLK to init. // Wait for LFCLK to init.
while(!nrf_drv_clock_lfclk_is_running()) { } while(!nrf_drv_clock_lfclk_is_running()) { }
ret = app_timer_init(); timers_init();
APP_ERROR_CHECK(ret);
app_usbd_serial_num_generate(); app_usbd_serial_num_generate();
@ -368,6 +389,7 @@ int main(void) {
// Init peripherals: // Init peripherals:
#if ADS1298 #if ADS1298
ads1298_interrupt_setup(); ads1298_interrupt_setup();
nrf_delay_ms(200);
ads1298_initialize(&m_info); ads1298_initialize(&m_info);
#endif #endif
@ -375,15 +397,26 @@ int main(void) {
reset_counters(); reset_counters();
// #TEMP: application_timers_start
application_timers_start();
while (true) { while (true) {
while (app_usbd_event_queue_process()) { /* Nothing to do */ } while (app_usbd_event_queue_process()) { /* Nothing to do */ }
if (recording_mode == RECORDING_MODE_ALL) { if (recording_mode == RECORDING_MODE_ALL) {
// if (recording_mode & drdy_flag) { // may be faster if we're just using ADS1298 // if (recording_mode & drdy_flag) { // may be faster if we're just using ADS1298
if (drdy_flag) {
#if ADS1298 #if ADS1298
// #TODO: Count samples if (drdy_flag) {
// #Maybe this should select based on the number of *active* channels? drdy_flag = false;
#if ADS1298_STATS
if (ads_timer_timeout) {
ads_timer_timeout = false;
//NRF_LOG_INFO("[ADS1298] Collected %lu samples in %d seconds", m_info.drdy_trigger_count, m_info.seconds_elapsed);
NRF_LOG_INFO("[ADS1298] DR: %lu", m_info.drdy_trigger_count / m_info.seconds_elapsed);
}
#endif
switch (m_info.nChs) { switch (m_info.nChs) {
case 4: case 4:
ads1294_get_data(&m_info); ads1294_get_data(&m_info);
@ -400,12 +433,14 @@ int main(void) {
if (m_info.usb_buffer_count >= m_info.usb_buffer_size_max) { if (m_info.usb_buffer_count >= m_info.usb_buffer_size_max) {
m_info.usb_buffer_count = ADS1298_PACKET_OFFSET; m_info.usb_buffer_count = ADS1298_PACKET_OFFSET;
app_usbd_cdc_acm_write(&m_app_cdc_acm, m_info.usb_buffer, NRF_DRV_USBD_EPSIZE); app_usbd_cdc_acm_write(&m_app_cdc_acm, m_info.usb_buffer, m_info.usb_buffer_size_max);
increment_packet(m_info.usb_buffer); increment_packet(m_info.usb_buffer);
// NRF_LOG_INFO("Current time tick: %lu", app_timer_cnt_get());
}
} }
#endif #endif
} }
}
if (run_throughput_test) { if (run_throughput_test) {
/*ret = */app_usbd_cdc_acm_write(&m_app_cdc_acm, usb_tx_buffer, NRF_DRV_USBD_EPSIZE); /*ret = */app_usbd_cdc_acm_write(&m_app_cdc_acm, usb_tx_buffer, NRF_DRV_USBD_EPSIZE);

View File

@ -3,6 +3,9 @@
#define NRF52840_BREAKOUT_BOARD 1 #define NRF52840_BREAKOUT_BOARD 1
#define ADS1298 1 #define ADS1298 1
#if ADS1298
#define ADS1298_STATS 1
#endif
// Testing with nRF52840: // Testing with nRF52840:
#if NRF52840_BREAKOUT_BOARD #if NRF52840_BREAKOUT_BOARD