Rename project files, add ADS1298 drivers, update .gitignore
This commit is contained in:
parent
aa699467f1
commit
44b5e30ded
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
Output/
|
||||
*.jlink
|
||||
*.eww
|
||||
*.eww
|
||||
*.emSession
|
||||
369
ads1298.c
Normal file
369
ads1298.c
Normal file
@ -0,0 +1,369 @@
|
||||
/* Author: Musa Mahmood - JIIM, Inc.
|
||||
* Date: 11/11/2023
|
||||
* License: This is proprietary code and may not be used without express written permission.
|
||||
*/
|
||||
|
||||
#include "ads1298.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "app_error.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#include "nrf_drv_gpiote.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
uint8_t ads1298_default_regs[] = {
|
||||
ADS1298_REGDEFAULT_CONFIG1,
|
||||
ADS1298_REGDEFAULT_CONFIG2,
|
||||
ADS1298_REGDEFAULT_CONFIG3,
|
||||
ADS1298_REGDEFAULT_LOFF,
|
||||
ADS1298_REGDEFAULT_CH1SET,
|
||||
ADS1298_REGDEFAULT_CH2SET,
|
||||
ADS1298_REGDEFAULT_CH3SET,
|
||||
ADS1298_REGDEFAULT_CH4SET,
|
||||
ADS1298_REGDEFAULT_CH5SET,
|
||||
ADS1298_REGDEFAULT_CH6SET,
|
||||
ADS1298_REGDEFAULT_CH7SET,
|
||||
ADS1298_REGDEFAULT_CH8SET,
|
||||
ADS1298_REGDEFAULT_RLD_SENSP,
|
||||
ADS1298_REGDEFAULT_RLD_SENSN,
|
||||
ADS1298_REGDEFAULT_LOFF_SENSP,
|
||||
ADS1298_REGDEFAULT_LOFF_SENSN,
|
||||
ADS1298_REGDEFAULT_LOFF_FLIP,
|
||||
ADS1298_REGDEFAULT_LOFF_STATP,
|
||||
ADS1298_REGDEFAULT_LOFF_STATN,
|
||||
ADS1298_REGDEFAULT_GPIO,
|
||||
ADS1298_REGDEFAULT_PACE,
|
||||
ADS1298_REGDEFAULT_RESP,
|
||||
ADS1298_REGDEFAULT_CONFIG4,
|
||||
ADS1298_REGDEFAULT_WCT1,
|
||||
ADS1298_REGDEFAULT_WCT2
|
||||
};
|
||||
|
||||
// SPI flags:
|
||||
static volatile bool spi_xfer_done;
|
||||
static uint8_t rx_buffer[27+2];
|
||||
|
||||
// SPI Instance:
|
||||
static const nrf_drv_spi_t spi0 = NRF_DRV_SPI_INSTANCE(0);
|
||||
|
||||
// SPI Event Handler:
|
||||
static void spi_event_handler(nrf_drv_spi_evt_t const *p_event, void *p_context)
|
||||
{
|
||||
spi_xfer_done = true;
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_DEBUG("SPI transfer completed.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ads1298_initialize(ble_exg_t *p_exg, ads1298_info_t *p_info) {
|
||||
NRF_LOG_INFO("Initializing ADS1298...");
|
||||
// 1. Power up the ADS1298:
|
||||
ads1298_power_up();
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_FLUSH();
|
||||
#endif
|
||||
nrf_drv_spi_config_t spi_config;
|
||||
memset(&spi_config, 0, sizeof(spi_config));
|
||||
// 2. Initialize SPI
|
||||
spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
|
||||
spi_config.ss_pin = ADS1298_CS_PIN;
|
||||
spi_config.miso_pin = ADS1298_MISO_PIN;
|
||||
spi_config.mosi_pin = ADS1298_MOSI_PIN;
|
||||
spi_config.sck_pin = ADS1298_SCK_PIN;
|
||||
spi_config.frequency = NRF_DRV_SPI_FREQ_2M;
|
||||
spi_config.irq_priority = APP_IRQ_PRIORITY_HIGHEST;
|
||||
spi_config.mode = NRF_DRV_SPI_MODE_1;
|
||||
spi_config.orc = 0x55;
|
||||
|
||||
APP_ERROR_CHECK(nrf_drv_spi_init(&spi0, &spi_config, spi_event_handler, NULL));
|
||||
// 3. Stop read data continuous mode (rdatac)
|
||||
ads1298_stop_rdatac();
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_FLUSH();
|
||||
#endif
|
||||
// 4. Init registers:
|
||||
// Copy default registers into p_exg->ads1298_settings (first 25 bytes)
|
||||
memset(p_exg->ads1298_settings, 0, ADS1298_SETTINGS_SIZE);
|
||||
memcpy(p_exg->ads1298_settings, ads1298_default_regs, ADS1298_REGISTER_COUNT);
|
||||
ads1298_init_default_registers();
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_FLUSH();
|
||||
#endif
|
||||
// 5. Soft start:
|
||||
ads1298_soft_start_conversion();
|
||||
// 6. Check ID: (sets lower 3 bits of ads1298_settings[25])
|
||||
ads1298_check_id(p_exg, p_info);
|
||||
// 7. Start read data continuous mode (rdatac):
|
||||
ads1298_start_rdatac();
|
||||
// 8. Place on standby mode:
|
||||
ads1298_standby();
|
||||
// 9. Set remainder of ads1298_settings[25]:
|
||||
p_exg->ads1298_settings[25] |= 0x80; // 16-bit mode
|
||||
// ads1298_settings[25] &= 0b10011111; // TODO: sets downsample to zero
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_FLUSH();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ads1298_uninitialize(void) {
|
||||
NRF_LOG_INFO("Uninitializing ADS1298...");
|
||||
nrf_drv_spi_uninit(&spi0);
|
||||
}
|
||||
|
||||
bool ads1298_check_id(ble_exg_t *p_exg, ads1298_info_t *p_info) {
|
||||
bool device_found = false;
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_INFO("Checking ADS129xR? ID:");
|
||||
#endif
|
||||
uint8_t tx_buf[6] = {ADS1298_OPC_RREG|ADS1298_REGADDR_ID, 0x01, 0, 0, 0, 0};
|
||||
uint8_t rx_buf[6] = {0,0,0,0,0,0};
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, tx_buf, 2, rx_buf, 6));
|
||||
while(!spi_xfer_done) {
|
||||
__WFE();
|
||||
}
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_INFO("rx_buf[3] = 0x%X", rx_buf[3]);
|
||||
NRF_LOG_INFO("rx_buf dump:");
|
||||
NRF_LOG_HEXDUMP_INFO(rx_buf, 6);
|
||||
#endif
|
||||
// Check lower 3 bits 0x[...]..[???]
|
||||
uint8_t nch_check = rx_buf[3] & 0x07; // 0x.....111
|
||||
p_exg->ads1298_settings[25] |= nch_check;
|
||||
p_info->nChs = 0;
|
||||
if (nch_check == ADS129x_4CH_BITMASK) {
|
||||
p_info->nChs = 4; // ADS1294
|
||||
} else if (nch_check == ADS129x_6CH_BITMASK) {
|
||||
p_info->nChs = 6; // ADS1296
|
||||
} else if (nch_check == ADS129x_8CH_BITMASK) {
|
||||
p_info->nChs = 8; // ADS1298
|
||||
} else {
|
||||
NRF_LOG_ERROR("Expected ADS129xX not detected! E0");
|
||||
return false;
|
||||
}
|
||||
// Check middle bits 0x[...]10[...] < always should be 10
|
||||
if ((rx_buf[3] & 0x10) != 0x10 || p_info->nChs == 0) {
|
||||
NRF_LOG_ERROR("Expected ADS129xX not detected! E1");
|
||||
return false;
|
||||
}
|
||||
// Check first three bits: 0x[???]..[...]
|
||||
uint8_t r_ver_chk = rx_buf[3] & 0xE0;
|
||||
if (r_ver_chk == ADS129x_DEVICE_FAMILY_BITMASK) {
|
||||
p_info->name_len = sprintf(p_info->name, "ADS129%d", p_info->nChs);
|
||||
NRF_LOG_INFO("%s detected! (name_len: %d)", p_info->name, p_info->name_len);
|
||||
device_found = true;
|
||||
p_exg->ads1298_settings[25] &= (~0x08);
|
||||
} else if (r_ver_chk == ADS129xR_DEVICE_FAMILY_BITMASK) {
|
||||
p_info->name_len = sprintf(p_info->name, "ADS129%dR", p_info->nChs);
|
||||
NRF_LOG_INFO("%s detected! (name_len: %d)", p_info->name, p_info->name_len);
|
||||
p_exg->ads1298_settings[25] |= 0x08;
|
||||
device_found = true;
|
||||
} else {
|
||||
NRF_LOG_ERROR("Expected ADS129xX not detected! E2");
|
||||
return false;
|
||||
}
|
||||
|
||||
return device_found;
|
||||
}
|
||||
|
||||
// chNumber = 1:8
|
||||
__STATIC_INLINE bool ads1298_check_channel(ads1298_info_t *p_info, uint8_t chNumber) {
|
||||
if (chNumber > p_info->nChs) return false;
|
||||
if (chNumber > 8) {
|
||||
NRF_LOG_INFO("[ads1298_check_channel] INVALID CHANNEL NUMBER: %d!", chNumber);
|
||||
return false;
|
||||
}
|
||||
return !((p_info->registers[3 + chNumber] & 0x80) == 0x80);
|
||||
}
|
||||
|
||||
void ads1298_update_active_chs(ads1298_info_t *p_info) {
|
||||
p_info->active_chs = 0;
|
||||
if (ads1298_check_channel(p_info, 1)) p_info->active_chs |= 0x80;
|
||||
if (ads1298_check_channel(p_info, 2)) p_info->active_chs |= 0x40;
|
||||
if (ads1298_check_channel(p_info, 3)) p_info->active_chs |= 0x20;
|
||||
if (ads1298_check_channel(p_info, 4)) p_info->active_chs |= 0x10;
|
||||
if (p_info->nChs == 4) return;
|
||||
if (ads1298_check_channel(p_info, 5)) p_info->active_chs |= 0x08;
|
||||
if (ads1298_check_channel(p_info, 6)) p_info->active_chs |= 0x04;
|
||||
if (p_info->nChs == 6) return;
|
||||
if (ads1298_check_channel(p_info, 7)) p_info->active_chs |= 0x02;
|
||||
if (ads1298_check_channel(p_info, 8)) p_info->active_chs |= 0x01;
|
||||
}
|
||||
|
||||
void ads1298_update_registers(ads1298_info_t *p_info) {
|
||||
NRF_LOG_INFO("Updating ADS1298 registers...");
|
||||
ads1298_update_active_chs(p_info);
|
||||
uint8_t i = 0; // Register index
|
||||
uint8_t tx_data[ADS1298_REGISTER_COUNT + 2]; // plus 2 for opcodes
|
||||
uint8_t rx_data[ADS1298_REGISTER_COUNT + 2];
|
||||
memset(tx_data, 0, ADS1298_REGISTER_COUNT + 2);
|
||||
memset(rx_data, 0, ADS1298_REGISTER_COUNT + 2);
|
||||
// Write Register Opcode | Register Address:
|
||||
tx_data[0] = ADS1298_OPC_WREG | ADS1298_REGADDR_CONFIG1;
|
||||
tx_data[1] = ADS1298_REGISTER_COUNT;
|
||||
// Copy default register values:
|
||||
memcpy(&tx_data[2], p_info->registers, ADS1298_REGISTER_COUNT);
|
||||
// Transaction size = 2 + number of registers to write
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, tx_data, ADS1298_REGISTER_COUNT + 2, rx_data, ADS1298_REGISTER_COUNT + 2));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_INFO("[ADS1298] Registers updated!");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ads1298_init_default_registers(void) {
|
||||
NRF_LOG_INFO("Initializing ADS1298 registers...");
|
||||
uint8_t i = 0; // Register index
|
||||
uint8_t tx_data[ADS1298_REGISTER_COUNT + 2]; // plus 2 for opcodes
|
||||
uint8_t rx_data[ADS1298_REGISTER_COUNT + 2];
|
||||
memset(tx_data, 0, ADS1298_REGISTER_COUNT + 2);
|
||||
memset(rx_data, 0, ADS1298_REGISTER_COUNT + 2);
|
||||
// Write Register Opcode | Register Address:
|
||||
tx_data[0] = ADS1298_OPC_WREG | ADS1298_REGADDR_CONFIG1;
|
||||
tx_data[1] = ADS1298_REGISTER_COUNT;
|
||||
// Copy default register values:
|
||||
memcpy(&tx_data[2], ads1298_default_regs, ADS1298_REGISTER_COUNT);
|
||||
// Transaction size = 2 + number of registers to write
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, tx_data, ADS1298_REGISTER_COUNT + 2, rx_data, ADS1298_REGISTER_COUNT + 2));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
#if ADS1298_LOG_DEBUG
|
||||
NRF_LOG_INFO("[ADS1298] Registers initialized.");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Power controls:
|
||||
void ads1298_power_down(void) {
|
||||
nrf_gpio_pin_clear(ADS1298_PWDN_PIN);
|
||||
nrf_delay_ms(5);
|
||||
}
|
||||
|
||||
void ads1298_power_up(void) {
|
||||
nrf_gpio_pin_set(ADS1298_PWDN_PIN);
|
||||
nrf_delay_ms(80);
|
||||
}
|
||||
|
||||
// Standby/Wakeup controls:
|
||||
void ads1298_wakeup(void) {
|
||||
NRF_LOG_INFO("Waking up ADS1298...");
|
||||
uint8_t cmd = ADS1298_OPC_WAKEUP;
|
||||
uint8_t rx_buf;
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, &cmd, 1, &rx_buf, 1));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
void ads1298_standby(void) {
|
||||
NRF_LOG_INFO("Placing ADS1298 in standby mode...");
|
||||
uint8_t cmd = ADS1298_OPC_STANDBY;
|
||||
uint8_t rx_buf;
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, &cmd, 1, &rx_buf, 1));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
// Start/stop conversions
|
||||
void ads1298_soft_start_conversion(void) {
|
||||
NRF_LOG_INFO("[ADS1298] Starting conversion...");
|
||||
uint8_t cmd = ADS1298_OPC_START;
|
||||
uint8_t rx_buf;
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, &cmd, 1, &rx_buf, 1));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
void ads1298_start_rdatac(void) {
|
||||
NRF_LOG_INFO("[ADS1298] Starting Read Data Continuous Mode...");
|
||||
uint8_t cmd = ADS1298_OPC_RDATAC;
|
||||
uint8_t rx_buf;
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, &cmd, 1, &rx_buf, 1));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
void ads1298_stop_rdatac(void) {
|
||||
NRF_LOG_INFO("[ADS1298] Stopping Read Data Continuous Mode...");
|
||||
uint8_t cmd = ADS1298_OPC_SDATAC;
|
||||
uint8_t rx_buf;
|
||||
spi_xfer_done = false;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi0, &cmd, 1, &rx_buf, 1));
|
||||
while (!spi_xfer_done)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
// __STATIC_INLINE uint8_t get_channel_count_from_settings(uint8_t settings) {
|
||||
// uint8_t lower_bits = settings & 0x07;
|
||||
// if (lower_bits == ADS129x_4CH_BITMASK) {
|
||||
// return 4;
|
||||
// } else if (lower_bits == ADS129x_6CH_BITMASK) {
|
||||
// return 6;
|
||||
// } else if (lower_bits == ADS129x_8CH_BITMASK) {
|
||||
// return 8;
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: Add option for 2 bytes (low resolution)
|
||||
__STATIC_INLINE void copy_relevant_data(ble_exg_t *p_exg, uint8_t active_chs/*, bool hi_res*/) {
|
||||
if ((active_chs & 0x80) == 0x80) memcpy(&p_exg->exg_ch1_buffer[p_exg->data_buffer_count], &rx_buffer[3], 3);
|
||||
if ((active_chs & 0x40) == 0x40) memcpy(&p_exg->exg_ch2_buffer[p_exg->data_buffer_count], &rx_buffer[6], 3);
|
||||
if ((active_chs & 0x20) == 0x20) memcpy(&p_exg->exg_ch3_buffer[p_exg->data_buffer_count], &rx_buffer[9], 3);
|
||||
if ((active_chs & 0x10) == 0x10) memcpy(&p_exg->exg_ch4_buffer[p_exg->data_buffer_count], &rx_buffer[12], 3);
|
||||
if ((active_chs & 0x08) == 0x08) memcpy(&p_exg->exg_ch5_buffer[p_exg->data_buffer_count], &rx_buffer[15], 3);
|
||||
if ((active_chs & 0x04) == 0x04) memcpy(&p_exg->exg_ch6_buffer[p_exg->data_buffer_count], &rx_buffer[18], 3);
|
||||
if ((active_chs & 0x02) == 0x02) memcpy(&p_exg->exg_ch7_buffer[p_exg->data_buffer_count], &rx_buffer[21], 3);
|
||||
if ((active_chs & 0x01) == 0x01) memcpy(&p_exg->exg_ch8_buffer[p_exg->data_buffer_count], &rx_buffer[24], 3);
|
||||
p_exg->data_buffer_count += 3;
|
||||
}
|
||||
|
||||
// Buffer size depends on version (27 bytes for ADS1298, 21 for ADS1296, and 15 for ADS1294)
|
||||
void ads1298_get_data(ble_exg_t *p_exg, uint8_t active_chs) {
|
||||
spi_xfer_done = false;
|
||||
memset(rx_buffer, 0, 27);
|
||||
nrf_drv_spi_transfer(&spi0, rx_buffer, 27, rx_buffer, 27);
|
||||
while (!spi_xfer_done) { __WFE(); }
|
||||
copy_relevant_data(p_exg, active_chs);
|
||||
}
|
||||
|
||||
void ads1296_get_data(ble_exg_t *p_exg, uint8_t active_chs) {
|
||||
spi_xfer_done = false;
|
||||
memset(rx_buffer, 0, 21);
|
||||
nrf_drv_spi_transfer(&spi0, rx_buffer, 21, rx_buffer, 21);
|
||||
while (!spi_xfer_done) { __WFE(); }
|
||||
copy_relevant_data(p_exg, active_chs);
|
||||
}
|
||||
|
||||
void ads1294_get_data(ble_exg_t *p_exg, uint8_t active_chs) {
|
||||
spi_xfer_done = false;
|
||||
memset(rx_buffer, 0, 15);
|
||||
nrf_drv_spi_transfer(&spi0, rx_buffer, 15, rx_buffer, 15);
|
||||
while (!spi_xfer_done) { __WFE(); }
|
||||
// Check mode p_exg->ads1298_settings[26] b0
|
||||
copy_relevant_data(p_exg, active_chs);
|
||||
}
|
||||
163
ads1298.h
Normal file
163
ads1298.h
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef ADS1298_H_
|
||||
#define ADS1298_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_drv_spi.h"
|
||||
|
||||
// Debug flag for logging:
|
||||
#define ADS1298_LOG_DEBUG 1
|
||||
|
||||
// Testing with nRF52840-DK:
|
||||
#define ADS1298_MISO_PIN 29
|
||||
#define ADS1298_DRDY_PIN 12
|
||||
#define ADS1298_CS_PIN 19
|
||||
#define ADS1298_SCK_PIN 11
|
||||
#define ADS1298_MOSI_PIN 26
|
||||
#define ADS1298_PWDN_PIN 03
|
||||
|
||||
|
||||
// Number of WRITABLE registers (Not inc. ID register)
|
||||
#define ADS1298_REGISTER_COUNT 25
|
||||
|
||||
/** REGISTER ADDRESSES **/
|
||||
#define ADS1298_REGADDR_ID 0x00
|
||||
#define ADS1298_REGADDR_CONFIG1 0x01
|
||||
#define ADS1298_REGADDR_CONFIG2 0x02
|
||||
#define ADS1298_REGADDR_CONFIG3 0x03
|
||||
#define ADS1298_REGADDR_LOFF 0x04
|
||||
#define ADS1298_REGADDR_CH1SET 0x05
|
||||
#define ADS1298_REGADDR_CH2SET 0x06
|
||||
#define ADS1298_REGADDR_CH3SET 0x07
|
||||
#define ADS1298_REGADDR_CH4SET 0x08
|
||||
#define ADS1298_REGADDR_CH5SET 0x09
|
||||
#define ADS1298_REGADDR_CH6SET 0x0A
|
||||
#define ADS1298_REGADDR_CH7SET 0x0B
|
||||
#define ADS1298_REGADDR_CH8SET 0x0C
|
||||
#define ADS1298_REGADDR_RLD_SENSP 0x0D
|
||||
#define ADS1298_REGADDR_RLD_SENSN 0x0E
|
||||
#define ADS1298_REGADDR_LOFF_SENSP 0x0F
|
||||
#define ADS1298_REGADDR_LOFF_SENSN 0x10
|
||||
#define ADS1298_REGADDR_LOFF_FLIP 0x11
|
||||
#define ADS1298_REGADDR_LOFF_STATP 0x12
|
||||
#define ADS1298_REGADDR_LOFF_STATN 0x13
|
||||
#define ADS1298_REGADDR_GPIO 0x14
|
||||
#define ADS1298_REGADDR_PACE 0x15
|
||||
#define ADS1298_REGADDR_RESP 0x16
|
||||
#define ADS1298_REGADDR_CONFIG4 0x17
|
||||
#define ADS1298_REGADDR_WCT1 0x18
|
||||
#define ADS1298_REGADDR_WCT2 0x19
|
||||
|
||||
/** SPI OPCODES **/
|
||||
// TODO: Double check!
|
||||
#define ADS1298_OPC_WAKEUP 0x02 // Wake up from standby.
|
||||
#define ADS1298_OPC_STANDBY 0x04 // Enter standby.
|
||||
#define ADS1298_OPC_RESET 0x06 // Reset all registers.
|
||||
#define ADS1298_OPC_START 0x08 // Start data conversions.
|
||||
#define ADS1298_OPC_STOP 0x0A // Stop data conversions.
|
||||
|
||||
#define ADS1298_OPC_RDATAC 0x10 // Read data continuously (registers cannot be read or written in this mode).
|
||||
#define ADS1298_OPC_SDATAC 0x11 // Stop continuous data read.
|
||||
#define ADS1298_OPC_RDATA 0x12 // Read single data value.
|
||||
|
||||
#define ADS1298_OPC_RREG 0x20 // Read register value. System must not be in RDATAC mode.
|
||||
#define ADS1298_OPC_WREG 0x40 // Write register value. System must not be in RDATAC mode.
|
||||
|
||||
/** FACTORY IDs FOR ADS129x **/
|
||||
#define ADS129x_DEVICE_FAMILY_BITMASK 0x80 // 0x[100]10[...]
|
||||
#define ADS129xR_DEVICE_FAMILY_BITMASK 0xC0 // 0x[110]10[...]
|
||||
|
||||
#define ADS129x_4CH_BITMASK 0x00 // 0x[...]10[000]
|
||||
#define ADS129x_6CH_BITMASK 0x01 // 0x[...]10[001]
|
||||
#define ADS129x_8CH_BITMASK 0x02 // 0x[...]10[010]
|
||||
|
||||
/** DEFAULT REGISTER VALUES **/
|
||||
//#define ADS1298_REGDEFAULT_CONFIG1 0x05 // Low power mode, Daisy-chain 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_CONFIG3 0x40 //
|
||||
#define ADS1298_REGDEFAULT_LOFF 0x00
|
||||
#define ADS1298_REGDEFAULT_CH1SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH2SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH3SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH4SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH5SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH6SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH7SET 0x00
|
||||
#define ADS1298_REGDEFAULT_CH8SET 0x00
|
||||
#define ADS1298_REGDEFAULT_RLD_SENSP 0x00
|
||||
#define ADS1298_REGDEFAULT_RLD_SENSN 0x00
|
||||
#define ADS1298_REGDEFAULT_LOFF_SENSP 0x00
|
||||
#define ADS1298_REGDEFAULT_LOFF_SENSN 0x00
|
||||
#define ADS1298_REGDEFAULT_LOFF_FLIP 0x00
|
||||
#define ADS1298_REGDEFAULT_LOFF_STATP 0x00
|
||||
#define ADS1298_REGDEFAULT_LOFF_STATN 0x00
|
||||
#define ADS1298_REGDEFAULT_GPIO 0x0F
|
||||
#define ADS1298_REGDEFAULT_PACE 0x00
|
||||
#define ADS1298_REGDEFAULT_RESP 0x00
|
||||
#define ADS1298_REGDEFAULT_CONFIG4 0x00
|
||||
#define ADS1298_REGDEFAULT_WCT1 0x00
|
||||
#define ADS1298_REGDEFAULT_WCT2 0x00
|
||||
|
||||
#define ADS1298_BUFFER_SIZE 64
|
||||
#define ADS1298_SETTINGS_SIZE 26
|
||||
|
||||
typedef struct {
|
||||
uint16_t service_handle; /**< Handle of ble_exg Service (as provided by the BLE stack). */
|
||||
uint16_t conn_handle; /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */
|
||||
uint8_t uuid_type; /**< UUID type for the ble_exg Service. */
|
||||
uint8_t exg_ch1_buffer[ADS1298_BUFFER_SIZE]; /**< Buffer for sending data to the peer device. */
|
||||
uint8_t exg_ch2_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch3_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch4_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch5_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch6_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch7_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t exg_ch8_buffer[ADS1298_BUFFER_SIZE];
|
||||
uint8_t ads1298_settings[ADS1298_SETTINGS_SIZE];
|
||||
uint16_t data_buffer_count; /**< Counter for data buffer. */
|
||||
uint16_t data_buffer_length; /**< Length of the data buffer. */
|
||||
} ble_exg_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t nChs; // 4, 6, or 8 channels depending on variant.
|
||||
uint8_t state; // Powered on or off!
|
||||
uint8_t name_len; // does not include null terminator
|
||||
// [active_chs] bit-packed array of active channels 1:8:
|
||||
// Chs: [1,2,3,4,5,6,7,8]. Ch1 active |= 0x80, ch2 |= 0x40 and so on..
|
||||
uint8_t active_chs;
|
||||
uint8_t registers[ADS1298_REGISTER_COUNT];
|
||||
char name[12];
|
||||
} ads1298_info_t;
|
||||
|
||||
/** FUNCTION PROTOTYPES **/
|
||||
void ads1298_initialize(ble_exg_t *p_exg, ads1298_info_t *p_info);
|
||||
|
||||
void ads1298_uninitialize(void);
|
||||
|
||||
bool ads1298_check_id(ble_exg_t *p_exg, ads1298_info_t *p_info);
|
||||
|
||||
void ads1298_update_registers(ads1298_info_t *p_info);
|
||||
|
||||
void ads1298_init_default_registers(void);
|
||||
|
||||
void ads1298_power_down(void);
|
||||
|
||||
void ads1298_power_up(void);
|
||||
|
||||
void ads1298_standby(void);
|
||||
|
||||
void ads1298_wakeup(void);
|
||||
|
||||
void ads1298_soft_start_conversion(void);
|
||||
|
||||
void ads1298_start_rdatac(void);
|
||||
|
||||
void ads1298_stop_rdatac(void);
|
||||
|
||||
void ads1294_get_data(ble_exg_t *p_exg, uint8_t active_chs);
|
||||
|
||||
void ads1296_get_data(ble_exg_t *p_exg, uint8_t active_chs);
|
||||
|
||||
void ads1298_get_data(ble_exg_t *p_exg, uint8_t active_chs);
|
||||
|
||||
#endif // ADS1298_H_
|
||||
6
main.c
6
main.c
@ -1,9 +1,3 @@
|
||||
// ~TODO
|
||||
// [ ] Add SPI files (see: fw-mvp), enable SPI interface.
|
||||
// [ ] Add ADS1292 driver, and test (just print for now)
|
||||
// [ ] Increase size of USB receive buffer, and see if we can program the ADS1292 via USB.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@ -2881,6 +2881,123 @@
|
||||
#define SAADC_CONFIG_DEBUG_COLOR 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
// <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
|
||||
//==========================================================
|
||||
#ifndef NRFX_SPIM_ENABLED
|
||||
#define NRFX_SPIM_ENABLED 0
|
||||
#endif
|
||||
// <q> NRFX_SPIM0_ENABLED - Enable SPIM0 instance
|
||||
|
||||
|
||||
#ifndef NRFX_SPIM0_ENABLED
|
||||
#define NRFX_SPIM0_ENABLED 0
|
||||
#endif
|
||||
|
||||
// <q> NRFX_SPIM1_ENABLED - Enable SPIM1 instance
|
||||
|
||||
|
||||
#ifndef NRFX_SPIM1_ENABLED
|
||||
#define NRFX_SPIM1_ENABLED 0
|
||||
#endif
|
||||
|
||||
// <q> NRFX_SPIM2_ENABLED - Enable SPIM2 instance
|
||||
|
||||
|
||||
#ifndef NRFX_SPIM2_ENABLED
|
||||
#define NRFX_SPIM2_ENABLED 0
|
||||
#endif
|
||||
|
||||
// <o> NRFX_SPIM_MISO_PULL_CFG - MISO pin pull configuration.
|
||||
|
||||
// <0=> NRF_GPIO_PIN_NOPULL
|
||||
// <1=> NRF_GPIO_PIN_PULLDOWN
|
||||
// <3=> NRF_GPIO_PIN_PULLUP
|
||||
|
||||
#ifndef NRFX_SPIM_MISO_PULL_CFG
|
||||
#define NRFX_SPIM_MISO_PULL_CFG 1
|
||||
#endif
|
||||
|
||||
// <o> NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
|
||||
|
||||
// <0=> 0 (highest)
|
||||
// <1=> 1
|
||||
// <2=> 2
|
||||
// <3=> 3
|
||||
// <4=> 4
|
||||
// <5=> 5
|
||||
// <6=> 6
|
||||
// <7=> 7
|
||||
|
||||
#ifndef NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY
|
||||
#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 6
|
||||
#endif
|
||||
|
||||
// <e> NRFX_SPIM_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||
//==========================================================
|
||||
#ifndef NRFX_SPIM_CONFIG_LOG_ENABLED
|
||||
#define NRFX_SPIM_CONFIG_LOG_ENABLED 0
|
||||
#endif
|
||||
// <o> NRFX_SPIM_CONFIG_LOG_LEVEL - Default Severity level
|
||||
|
||||
// <0=> Off
|
||||
// <1=> Error
|
||||
// <2=> Warning
|
||||
// <3=> Info
|
||||
// <4=> Debug
|
||||
|
||||
#ifndef NRFX_SPIM_CONFIG_LOG_LEVEL
|
||||
#define NRFX_SPIM_CONFIG_LOG_LEVEL 3
|
||||
#endif
|
||||
|
||||
// <o> NRFX_SPIM_CONFIG_INFO_COLOR - ANSI escape code prefix.
|
||||
|
||||
// <0=> Default
|
||||
// <1=> Black
|
||||
// <2=> Red
|
||||
// <3=> Green
|
||||
// <4=> Yellow
|
||||
// <5=> Blue
|
||||
// <6=> Magenta
|
||||
// <7=> Cyan
|
||||
// <8=> White
|
||||
|
||||
#ifndef NRFX_SPIM_CONFIG_INFO_COLOR
|
||||
#define NRFX_SPIM_CONFIG_INFO_COLOR 0
|
||||
#endif
|
||||
|
||||
// <o> NRFX_SPIM_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
|
||||
|
||||
// <0=> Default
|
||||
// <1=> Black
|
||||
// <2=> Red
|
||||
// <3=> Green
|
||||
// <4=> Yellow
|
||||
// <5=> Blue
|
||||
// <6=> Magenta
|
||||
// <7=> Cyan
|
||||
// <8=> White
|
||||
|
||||
#ifndef NRFX_SPIM_CONFIG_DEBUG_COLOR
|
||||
#define NRFX_SPIM_CONFIG_DEBUG_COLOR 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <q> NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED - Enables nRF52 anomaly 109 workaround for SPIM.
|
||||
|
||||
|
||||
// <i> The workaround uses interrupts to wake up the CPU by catching
|
||||
// <i> a start event of zero-length transmission to start the clock. This
|
||||
// <i> ensures that the DMA transfer will be executed without issues and
|
||||
// <i> that the proper transfer will be started. See more in the Errata
|
||||
// <i> document or Anomaly 109 Addendum located at
|
||||
// <i> https://infocenter.nordicsemi.com/
|
||||
|
||||
#ifndef NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED
|
||||
#define NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> SPIS_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||
@ -2934,6 +3051,80 @@
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
|
||||
//==========================================================
|
||||
#ifndef SPI_ENABLED
|
||||
#define SPI_ENABLED 1
|
||||
#endif
|
||||
// <o> SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
|
||||
|
||||
|
||||
// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
|
||||
// <0=> 0 (highest)
|
||||
// <1=> 1
|
||||
// <2=> 2
|
||||
// <3=> 3
|
||||
// <4=> 4
|
||||
// <5=> 5
|
||||
// <6=> 6
|
||||
// <7=> 7
|
||||
|
||||
#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY
|
||||
#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 6
|
||||
#endif
|
||||
|
||||
// <o> NRF_SPI_DRV_MISO_PULLUP_CFG - MISO PIN pull-up configuration.
|
||||
|
||||
// <0=> NRF_GPIO_PIN_NOPULL
|
||||
// <1=> NRF_GPIO_PIN_PULLDOWN
|
||||
// <3=> NRF_GPIO_PIN_PULLUP
|
||||
|
||||
#ifndef NRF_SPI_DRV_MISO_PULLUP_CFG
|
||||
#define NRF_SPI_DRV_MISO_PULLUP_CFG 1
|
||||
#endif
|
||||
|
||||
// <e> SPI0_ENABLED - Enable SPI0 instance
|
||||
//==========================================================
|
||||
#ifndef SPI0_ENABLED
|
||||
#define SPI0_ENABLED 1
|
||||
#endif
|
||||
// <q> SPI0_USE_EASY_DMA - Use EasyDMA
|
||||
|
||||
|
||||
#ifndef SPI0_USE_EASY_DMA
|
||||
#define SPI0_USE_EASY_DMA 1
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> SPI1_ENABLED - Enable SPI1 instance
|
||||
//==========================================================
|
||||
#ifndef SPI1_ENABLED
|
||||
#define SPI1_ENABLED 0
|
||||
#endif
|
||||
// <q> SPI1_USE_EASY_DMA - Use EasyDMA
|
||||
|
||||
|
||||
#ifndef SPI1_USE_EASY_DMA
|
||||
#define SPI1_USE_EASY_DMA 1
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> SPI2_ENABLED - Enable SPI2 instance
|
||||
//==========================================================
|
||||
#ifndef SPI2_ENABLED
|
||||
#define SPI2_ENABLED 1
|
||||
#endif
|
||||
// <q> SPI2_USE_EASY_DMA - Use EasyDMA
|
||||
|
||||
|
||||
#ifndef SPI2_USE_EASY_DMA
|
||||
#define SPI2_USE_EASY_DMA 1
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> SPI_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||
//==========================================================
|
||||
#ifndef SPI_CONFIG_LOG_ENABLED
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE CrossStudio_Project_File>
|
||||
<solution Name="usbd_cdc_acm_pca10056" target="8" version="2">
|
||||
<solution Name="Multimodal_CV_USB_ADS1298R_pca10056" target="8" version="2">
|
||||
<configuration
|
||||
Name="Debug"
|
||||
c_preprocessor_definitions="DEBUG; DEBUG_NRF"
|
||||
@ -9,7 +9,7 @@
|
||||
c_preprocessor_definitions="NDEBUG"
|
||||
gcc_optimization_level="Optimize For Size"
|
||||
link_time_optimization="No" />
|
||||
<project Name="usbd_cdc_acm_pca10056">
|
||||
<project Name="Multimodal_CV_USB_ADS1298R_pca10056">
|
||||
<configuration
|
||||
Name="Common"
|
||||
arm_architecture="v7EM"
|
||||
@ -42,6 +42,8 @@
|
||||
project_directory=""
|
||||
project_type="Executable" />
|
||||
<folder Name="Application">
|
||||
<file file_name="../../../ads1298.c" />
|
||||
<file file_name="../../../ads1298.h" />
|
||||
<file file_name="../../../main.c" />
|
||||
<file file_name="../config/sdk_config.h" />
|
||||
</folder>
|
||||
@ -60,6 +62,7 @@
|
||||
<folder Name="nRF_Drivers">
|
||||
<file file_name="../../../../../../integration/nrfx/legacy/nrf_drv_clock.c" />
|
||||
<file file_name="../../../../../../integration/nrfx/legacy/nrf_drv_power.c" />
|
||||
<file file_name="../../../../../../integration/nrfx/legacy/nrf_drv_spi.c" />
|
||||
<file file_name="../../../../../../integration/nrfx/legacy/nrf_drv_uart.c" />
|
||||
<file file_name="../../../../../../components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c" />
|
||||
<file file_name="../../../../../../components/drivers_nrf/nrf_soc_nosd/nrf_soc.c" />
|
||||
@ -68,6 +71,8 @@
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_gpiote.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_power.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/prs/nrfx_prs.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_spi.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_spim.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_systick.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_uart.c" />
|
||||
<file file_name="../../../../../../modules/nrfx/drivers/src/nrfx_uarte.c" />
|
||||
@ -1,47 +0,0 @@
|
||||
<!DOCTYPE CrossStudio_Session_File>
|
||||
<session>
|
||||
<Bookmarks/>
|
||||
<Breakpoints groups="Breakpoints" active_group="Breakpoints"/>
|
||||
<ExecutionProfileWindow/>
|
||||
<FrameBuffer/>
|
||||
<Memory1/>
|
||||
<Memory2/>
|
||||
<Memory3/>
|
||||
<Memory4/>
|
||||
<Project>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056"/>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056;usbd_cdc_acm_pca10056"/>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056;usbd_cdc_acm_pca10056;Application"/>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056;usbd_cdc_acm_pca10056;nRF_Drivers"/>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056;usbd_cdc_acm_pca10056;nRF_Libraries"/>
|
||||
<ProjectSessionItem path="usbd_cdc_acm_pca10056;usbd_cdc_acm_pca10056;Segger Startup Files"/>
|
||||
</Project>
|
||||
<Register1/>
|
||||
<Register2/>
|
||||
<Register3/>
|
||||
<Register4/>
|
||||
<Threads>
|
||||
<ThreadsWindow showLists=""/>
|
||||
</Threads>
|
||||
<TraceWindow>
|
||||
<Trace enabled="Yes"/>
|
||||
</TraceWindow>
|
||||
<Watch1>
|
||||
<Watches active="1" update="Never"/>
|
||||
</Watch1>
|
||||
<Watch2>
|
||||
<Watches active="0" update="Never"/>
|
||||
</Watch2>
|
||||
<Watch3>
|
||||
<Watches active="0" update="Never"/>
|
||||
</Watch3>
|
||||
<Watch4>
|
||||
<Watches active="0" update="Never"/>
|
||||
</Watch4>
|
||||
<Files>
|
||||
<SessionOpenFile windowGroup="DockEditLeft" x="9" y="97" useTextEdit="1" path="../../../main.c" left="0" selected="1" top="46" codecName="Default"/>
|
||||
<SessionOpenFile windowGroup="DockEditLeft" x="4" y="103" useTextEdit="1" openedFrom="D:/Firmware/nRF5_SDK_17.1.0/1.Musa/fw_in_progress/musa_usbd_cdc_acm/main.c" path="../../../../../../components/libraries/usbd/class/cdc/app_usbd_cdc_types.h" left="0" top="64" codecName="Default"/>
|
||||
<SessionOpenFile windowGroup="DockEditLeft" x="30" y="1425" useTextEdit="1" path="../config/sdk_config.h" left="0" top="1425" codecName="Default"/>
|
||||
</Files>
|
||||
<EMStudioWindow activeProject="usbd_cdc_acm_pca10056" fileDialogDefaultFilter="*.c" autoConnectTarget="J-Link" buildConfiguration="Release" sessionSettings="" debugSearchFileMap="" fileDialogInitialDirectory="" debugSearchPath="" autoConnectCapabilities="3711"/>
|
||||
</session>
|
||||
Loading…
Reference in New Issue
Block a user