Skip to content

Commit

Permalink
Merge pull request #16 from neurotechuoft/pi_devel
Browse files Browse the repository at this point in the history
Pi devel
a1bertle authored Mar 15, 2018
2 parents 7dc9c39 + 1742d26 commit 6fea3ae
Showing 7 changed files with 365 additions and 80 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -18,3 +18,13 @@ Meeting-Sean(Electrodes:Diagrams:Stores:More)/
# ODS Lock Files #
##################
.~lock.*

# Ignore `bin` dir
*/bin/*

# Ignore `obj` dir
*/obj/*
*.o

#Ignore log files
*.log
2 changes: 1 addition & 1 deletion code/software/ADS_1299_Embedded/scripts/run_neuro.sh
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ LOG_NAME=bootup_$CREATE_DATE.log
LOG_FILE=$LOG_DIR/$LOG_NAME

printf "\nRunning ./bin/neuro ...\n"
sudo ./bin/neuro > $LOG_FILE
sudo $BSB_EMBEDDED/bin/neuro "$@" > $LOG_FILE

printf "Finished running ./bin/neuro\n"

2 changes: 2 additions & 0 deletions code/software/ADS_1299_Embedded/scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@ export BSB_GUI="$BSB_HOME/code/gui"
export BSB_DIG="$BSB_HOME/code/digital"
export BSB_PCB="$BSB_HOME/EAGLE"

alias run_neuro="sudo $BSB_EMBEDDED/bin/neuro"

#printf "Biosignals-Board Embedded Setup Complete\n\n"

cd $CURR_DIR
135 changes: 93 additions & 42 deletions code/software/ADS_1299_Embedded/src/ADS1299_bcm2835.c
Original file line number Diff line number Diff line change
@@ -15,9 +15,11 @@

void ADS1299_init() {

delayMicroseconds(50000);

// Configure ADS1299 - specific interface pins

// Set the pin_DRDY to be the input
// Set the pin_DRDY to be the input
bcm2835_gpio_fsel(PIN_DRDY, BCM2835_GPIO_FSEL_INPT);


@@ -28,8 +30,11 @@ void ADS1299_init() {
bcm2835_gpio_fsel(PIN_PWDN, BCM2835_GPIO_FSEL_OUTP);

// Configure test pins as outputs
bcm2835_gpio_fsel(TEST_PIN_1, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(TEST_PIN_2, BCM2835_GPIO_FSEL_OUTP);

// FIXME: Uncomment this line. Currently commented out since TEST_PIN_1 (GPIO_J8_03) has been repurposed as PIN_RESET
//bcm2835_gpio_fsel(TEST_PIN_1, BCM2835_GPIO_FSEL_OUTP);

//bcm2835_gpio_fsel(TEST_PIN_2, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(TEST_PIN_3, BCM2835_GPIO_FSEL_OUTP);

// Configure BCM2835 SPI settings
@@ -39,18 +44,18 @@ void ADS1299_init() {

// Set bit order
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default

// Set the spi mode - 4 modes
// BCM2835_SPI_MODE1 = 1, // CPOL = 0, CPHA = 1, Clock idle low, data is clocked in on falling edge, output data (change) on rising edge
bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); // The default

//Set SPI clock speed
// BCM2835_SPI_CLOCK_DIVIDER_512 = 512, ///< 512 = 2.048us = 488.28125kHz
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_512); // The default

// Chip select
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);

// Select the polarity LOW
// ADS1299 uses an active low chip select
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
@@ -59,10 +64,16 @@ void ADS1299_init() {
// Do not try writing to the pin or setting it as an OUTPUT!!

// Initialize pins to default values
bcm2835_gpio_write(PIN_RESET, HIGH);

// FIXME: UNcomment

bcm2835_gpio_write(PIN_RESET, LOW);
bcm2835_gpio_write(PIN_PWDN, LOW);

// PIN_CS (chip select CE0) will be held HIGH when an SPI transfer is not in progress since we
delayMicroseconds(50000);

//bcm2835_gpio_write(PIN_DRDY, LOW);

// PIN_CS (chip select CE0) will be held HIGH when an SPI transfer is not in progress since we
// set the chip select polarity to LOW.
#ifdef __DEBUG__
printf("After ADS1299 initialization\n");
@@ -74,19 +85,25 @@ void ADS1299_init() {
void ADS1299_bootup(){
/* Function: Bootup Routine of the ADS1299
Return: None */



bcm2835_gpio_write(PIN_RESET, HIGH);

// Bring PWDN pin high to exit low-power standby mode. Delay 100 us
bcm2835_gpio_write(PIN_PWDN, HIGH);
delayMicroseconds(100);
delayMicroseconds(pow(2, 18) * TCLK);

// Delay 2 seconds for VCAP1 >= 1.1 V
delayMicroseconds(2000000);

//Set the pin to low and delay for 2*TCLK us (tRST) as per datasheet
bcm2835_gpio_write(PIN_RESET, LOW);
delayMicroseconds(2*TCLK);
delayMicroseconds(2 * TCLK);

//set pin to high to reset and bootup; delay 16 TCLK after end of RESET pulse
//or 18 TCLK after start of RESET pulse, as per Power Up Sequence in datasheet (pg. 70)
bcm2835_gpio_write(PIN_RESET,HIGH);
delayMicroseconds(18*TCLK);
delayMicroseconds(16*TCLK);

// Initialize some state variables

@@ -95,16 +112,50 @@ void ADS1299_bootup(){

// The default PGA gain on bootup is 24
ADS1299_pga_gain = 24;

printf("After ADS1299 bootup\n");
display_all_pin_states();
printf("End of ADS1299_bootup()\n");

}

void ADS1299_config() {
// We are using an internal reference, so set PD_REFBUF to 1
// We are using an internal reference, so set PD_REFBUF to 1
printf("\nSetting PD_REFBUF bit of CONFIG3 to 1 \n");
ADS1299_write_register_field(CONFIG3, 1, 7, 1);
ADS1299_write_register(CONFIG3, 0xE0);

// Arbritrary delay to wait for internal reference to settle
bcm2835_delayMicroseconds(500);
}
bcm2835_delayMicroseconds(500);
}

void ADS1299_power_down() {
printf("\n Powering down ADS1299...\n");
bcm2835_gpio_write(PIN_PWDN, LOW);
bcm2835_gpio_write(PIN_RESET, LOW);
if (!bcm2835_gpio_lev(PIN_PWDN))
printf("\n ADS1299 Powered down\n");
}

void ADS1299_reboot() {
bool powered_on = false;

powered_on = bcm2835_gpio_lev(PIN_PWDN);

if (powered_on) {
printf("\n ADS1299 is powered on. Rebooting ...\n");

ADS1299_power_down();

bcm2835_delayMicroseconds(2 * 1000000); // Wait for 2 seconds before powering up again

ADS1299_init();
ADS1299_bootup();

printf("\n ADS1299 Reboot Finished\n");
} else {
printf("\n ADS1299 is already powered-down. Aborting reboot ...\n");
}
}

//////////////////////// Register interface functions //////////////////////
/* Function: Read a single register of the ADS1299
@@ -146,7 +197,7 @@ uint8_t ADS1299_read_register_field(uint8_t reg_addr, uint8_t fld_size, uint8_t
BYTE_TO_BIN(fld_offset),
BYTE_TO_BIN(rd_data),
BYTE_TO_BIN(rd_fld_data));

#endif

return rd_fld_data;
@@ -172,7 +223,7 @@ void ADS1299_write_register_field(uint8_t reg_addr, uint8_t fld_size, uint8_t fl
// fld_size : 3
// fld_offset : 3
// Field data : 0b010
//
//
// wr_mask = ~(((1 << 3) - 1) << 3)
// = ~((0b00001000 - 1) << 3)
// = ~(0b00000111 << 3)
@@ -245,20 +296,20 @@ bool ADS1299_test_registers() {
result &= register_check(CONFIG1, CONFIG1_DEFAULT, &reg_config1);

result &= register_check(CONFIG2, CONFIG2_DEFAULT, &reg_config2);

// FIXME: Might need to remove CONFIG3 from bootup test. We write to it before testing to enable the internal reference
register_check(CONFIG3, CONFIG3_DEFAULT, &reg_config3);

if (result)
printf("\n--- ADS1299 register defaults test PASSED ---\n");
else
else
printf("\n--- ADS1299 register defaults test FAILED ---\n");

return result;
}

bool ADS1299_test_registers_write() {

uint8_t id_wr_data, config1_wr_data, config2_wr_data, config3_wr_data;
uint8_t id_rd_data, config1_rd_data, config2_rd_data, config3_rd_data;

@@ -278,23 +329,23 @@ bool ADS1299_test_registers_write() {

ADS1299_write_register(CONFIG1, config1_wr_data);
result &= register_check(CONFIG1, config1_wr_data, &config1_rd_data);

ADS1299_write_register(CONFIG2, config2_wr_data);
result &= register_check(CONFIG2, config2_wr_data, &config2_rd_data);

// FIXME: Might need to remove CONFIG3 from test, do not want to clobber PD_REFBUF bit
//ADS1299_write_register(CONFIG3, config3_wr_data);
//result &= register_check(CONFIG3, config3_wr_data, &config3_rd_data);

if (result)
printf("\n--- ADS1299 register write test PASSED ---\n");
else
else
printf("\n--- ADS1299 register write test FAILED ---\n");


return result;
}
}



/////////////////////////////////////////////////////////////////////////////
@@ -303,9 +354,9 @@ bool ADS1299_test_registers_write() {
void output_square_wave(int _pin, double _frequency, double _test_duration) {
double test_wave_frequency = _frequency;
double test_wave_period_us = (1/test_wave_frequency) * 1000000;

int elapsed_cycles;
int num_cycles_for_test = _test_duration * _frequency;
int num_cycles_for_test = _test_duration * _frequency;

for (elapsed_cycles = 0; elapsed_cycles < num_cycles_for_test; elapsed_cycles++) {
bcm2835_gpio_write(_pin, HIGH);
@@ -362,21 +413,21 @@ void display_all_pin_states() {
}

void display_pin_state(int _pin) {
if (_pin == PIN_DRDY )
if (_pin == PIN_DRDY )
printf("\tPIN_DRDY : %x\n", bcm2835_gpio_lev(PIN_DRDY));
else if (_pin == PIN_RESET)
else if (_pin == PIN_RESET)
printf("\tPIN_RESET : %x\n", bcm2835_gpio_lev(PIN_RESET));
else if (_pin == PIN_PWDN)
else if (_pin == PIN_PWDN)
printf("\tPIN_PWDN : %x\n", bcm2835_gpio_lev(PIN_PWDN));
else if (_pin == PIN_MOSI)
else if (_pin == PIN_MOSI)
printf("\tPIN_MOSI : %x\n", bcm2835_gpio_lev(PIN_MOSI));
else if (_pin == PIN_MISO)
else if (_pin == PIN_MISO)
printf("\tPIN_MISO : %x\n", bcm2835_gpio_lev(PIN_MISO));
else if (_pin == PIN_SCLK)
else if (_pin == PIN_SCLK)
printf("\tPIN_SCLK : %x\n", bcm2835_gpio_lev(PIN_SCLK));
else if (_pin == PIN_CS)
else if (_pin == PIN_CS)
printf("\tPIN_CS : %x\n", bcm2835_gpio_lev(PIN_CS));
else
else
printf("\tRPI_BPLUS_GPIO_J8_%d : %x\n", _pin, bcm2835_gpio_lev(_pin));
}

@@ -385,4 +436,4 @@ void display_pin_state(int _pin) {




4 changes: 4 additions & 0 deletions code/software/ADS_1299_Embedded/src/ADS1299_bcm2835.h
Original file line number Diff line number Diff line change
@@ -11,6 +11,10 @@ void ADS1299_init();
void ADS1299_bootup();

void ADS1299_config();

void ADS1299_power_down();

void ADS1299_reboot();
///////////// Register Interface functions //////////////

uint8_t ADS1299_read_register(uint8_t reg_addr);
6 changes: 3 additions & 3 deletions code/software/ADS_1299_Embedded/src/ADS1299_definitions.h
Original file line number Diff line number Diff line change
@@ -24,20 +24,20 @@

// Control Pins
#define PIN_DRDY RPI_BPLUS_GPIO_J8_15 // Make Pin 15 the DRDY pin (purple cable)
#define PIN_RESET RPI_BPLUS_GPIO_J8_16 // Make Pin 16 the RESET pin (brown cable)
#define PIN_RESET RPI_BPLUS_GPIO_J8_03 // FIXME: Temporarily make GPIO Pin 3 the reset pin. Original: Make Pin 16 the RESET pin (brown cable)
#define PIN_PWDN RPI_BPLUS_GPIO_J8_22 // Make Pin 22 the !PWDN pin (red cable)

// SPI pins (DO NOT CHANGE. These are defined in hardware!)
#define PIN_MOSI RPI_BPLUS_GPIO_J8_19 // Pin 19 is the MOSI pin (green cable)
#define PIN_MISO RPI_BPLUS_GPIO_J8_21 // Pin 21 is the MISO pin (blue cable)
#define PIN_SCLK RPI_BPLUS_GPIO_J8_23 // Pin 23 is the SCLK pin (white cable)
#define PIN_CS RPI_BPLUS_GPIO_J8_24 // Pin 24 (CE0) is the CS pin (yellow cable)
#define PIN_CS RPI_BPLUS_GPIO_J8_24 // Pin 24 (CE0) is the CS pin (yellow cable

// Use GPIO pin 20 as DGND. Pin 20 is not a GPIO pin and is not defined in bcm2835.h
#define PIN_DGND 20 // black cable

// Dedicated Test Pins
#define TEST_PIN_1 RPI_BPLUS_GPIO_J8_03 // Dedicated test pin #1
//#define TEST_PIN_1 RPI_BPLUS_GPIO_J8_03 // FIXME: This definistion needs to be commented out to not conflict with the PIN_RESET redefine to GPIO_J8_03. Original: Dedicated test pin #1
#define TEST_PIN_2 RPI_BPLUS_GPIO_J8_05 // Dedicated test pin #2
#define TEST_PIN_3 RPI_BPLUS_GPIO_J8_07 // Dedicated test pin #3

286 changes: 252 additions & 34 deletions code/software/ADS_1299_Embedded/src/main.c
Original file line number Diff line number Diff line change
@@ -3,58 +3,276 @@
#include "ADS1299_bcm2835.h"
#include "ads1299.h"
#include <math.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv)
{
// If error in intializing bcm
if (!bcm2835_init()) {
printf("Failed to init the Raspberry PI");
return 1;
}

int opt;
bool do_bootup = true, do_test = false, dry_run = false, output_wave = false, power_down = false;


char* test_name = NULL;
bool bootup_success = false;
int num_attempts = 1;
int output_test_pin_num = 2;
int test_pin = TEST_PIN_2;
int attempt = 1;

//ADS1299_init();
//output_square_wave(TEST_PIN_1, 10000, 100000);
// Parse command line options
// -b -> Perform bootup sequence: bcm2835_init() -> ADS1299_init() -> AS1299_bootup()
// -t -> Perform specific test
// -w -> Output wave on to one of the three test pins.
// -r -> Repeat test if failed. Default number of repeats is 1
// -d -> Running dry_run mode (not on Raspberry Pi)
// -p -> Power down chip after testing

while ((opt = getopt(argc, argv, "bdpt:r:w:")) != -1) {
switch (opt) {
case 'd':
dry_run = true;
printf("\ngetopt - received 'd'\n");
break;
case 'r':
num_attempts = atoi(optarg);
printf("\ngetopt - received 'r'. num_attempts = %d\n", num_attempts);
break;
case 'b':
do_bootup = true;
printf("\ngetopt - received 'b'\n");
break;
case 'w':
output_wave = true;
// Do not bootup the chip
do_bootup = false;

// Perform boot-up and test CONFIG registers for default values.

while (attempt <= num_attempts && !bootup_success) {
output_test_pin_num = atoi(optarg);
if (output_test_pin_num == 2)
test_pin = TEST_PIN_2;
else if (output_test_pin_num == 3)
test_pin = TEST_PIN_3;
else {
fprintf(stderr, "Error: Invalid test pin. Must be 2 or 3");
exit(EXIT_FAILURE);
}

// Initialize BCM Configuration to communicate with chip
ADS1299_init();
printf("\ngetopt - received 'w'. test_pin = %d\n", output_test_pin_num);

// bootup sequence
ADS1299_bootup();

// Send SDATAC before reading/writing registers
transferCmd(_SDATAC);
break;
case 't':
do_test = true;
do_bootup = true;
test_name = optarg;
printf("\ngetopt - received 't'. test_name = %s\n", test_name);
break;
case 'p':
power_down = true;
printf("\ngetopt - received 'p'\n");
break;
default:
fprintf(stderr, "Usage: %s [-bt] [file...]\n", argv[0]);
exit(EXIT_FAILURE);
}
}

// Write necessary registers/pins for our ADS1299 configuration
ADS1299_config();

printf("\nAttempt #%d\n", attempt);
if (!dry_run) { // If running on the Raspberry Pi

// If error in intializing bcm
if (!bcm2835_init()) {
printf("Failed to init the Raspberry PI");
return 1;
}

// Test registers' default values
bootup_success = ADS1299_test_registers();
// Note: Disable other tests or sequences if testing with a test pin
if (output_wave) {
// set attempt = num_attempts + 1 so we don't enter the following loop
attempt = num_attempts + 1;

if (bootup_success) {
printf("\n-- ADS1299 Boot-up Successful --\n");
} else {
printf("\n-- ADS1299 Boot-up Failed --\n");
// Output a 100 kHz wave to test_pin for 300 seconds (5 minutes).
// Note: This is a blocking call.
output_square_wave(test_pin, 100000, 300);
}

attempt++;
// Delay 500 us before moving on or reattempting bootup
bcm2835_delayMicroseconds(500);
while (attempt <= num_attempts && !bootup_success) {

if (do_bootup) {

printf("\n-- ADS1299 Boot-up --\n");

// Initialize BCM Configuration to communicate with chip
ADS1299_init();

delayMicroseconds(100);

// bootup sequence
ADS1299_bootup();
}

// Tests:
//
// register_test - Bootup and read the 3 CONFIG registers and compare the read values against their default values
// sdatac_test - Bootup and send sdatac command
// pwrup_ref_buf_test - Bootup and write to 0xE0 to CONFIG3 register to power up the reference buffer.
// power_cycle_test - Do 5 cycles of bootup and power down

if (do_test) {

// Cannot do tests if ADS1299 was not boot-up
if (!do_bootup) {
printf("\nError: ADS1299 is not bootup!!!\n");
return 1;
}

if (!strcmp(test_name, "register_test")) { // Test registers' default values

// Send SDATAC before reading/writing registers
transferCmd(_SDATAC);

// Write PD_REFBUF = 1
ADS1299_config();

// Set data rate
printf("Set data rate - start\n");
ADS1299_write_register(CONFIG1, 0x96);
ADS1299_write_register(CONFIG2, 0xC0);
printf("Set data rate - done\n");

// Set all channels to input short
int i;

printf("\nWrite all CHNSET to 0x01\n");
for (i=0; i < NUM_CHANNELS; i++) {
printf("Write CH%0dSET to 0x01 - Start", i);
ADS1299_write_register(CH1SET+i, 0x01);
printf("\nWrite CH%0dSET to 0x01 - End", i);
}

delayMicroseconds(50000);
// Send START command
printf("\nSending START commad\n");
transferCmd(_START);

// Put back in RDATAC
printf("\nSending RDATAC commad\n");
transferCmd(_RDATAC);


// sET-UP TEST SGIANLS
ADS1299_write_register(CONFIG2, 0xD0);
for (i=0; i < NUM_CHANNELS; i++) {
printf("Write CH%0dSET to 0x05 - Start", i);
ADS1299_write_register(CH1SET+i, 0x05);
printf("\nWrite CH%0dSET to 0x05 - End", i);
}

// Loop forever
/*
int recv_data = 0;
while(1) {
//if (!bcm2835_gpio_lev(PIN_DRDY)) { // conversion finished
// Issue 216 = 24 + 8 * 24 SCLKS
int j;
for (j = 0; j < NUM_CHANNELS + 1; j++) {
recv_data = transferData(0x00);
printf("Packet %d, Recv Data %d\n", j, recv_data);
// Delay 1/250 sec = 4 ms
delayMicroseconds(4000);
}
//} else
}
*/

}
///////////////////////////////////////////////


bootup_success = ADS1299_test_registers();

if (bootup_success) {
printf("\n-- ADS1299 Boot-up Successful --\n");
} else {
printf("\n-- ADS1299 Boot-up Failed --\n");
}

} else if (!strcmp(test_name, "sdatac_test")) {

printf("\n--- ADS1299 SDATAC test ---\n");

transferCmd(_SDATAC);

printf("\n--- ADS1299 SDATAC test Finished ---\n");

} else if (!strcmp(test_name, "pwrup_ref_buf_test")) {

printf("\n--- ADS1299 Power-up reference buffer test ---\n");

transferCmd(_SDATAC);

ADS1299_config();

printf("\n--- ADS1299 Power-up reference buffer test Finished ---\n");

} else if (!strcmp(test_name, "power_cycle_test")) {

int cycle;
printf("\n--- ADS1299 power cycle test ---\n");

if (!do_bootup) {

ADS1299_init();

delayMicroseconds(100);

ADS1299_bootup();
}

for (cycle = 0; cycle < 5; cycle++) {
printf("\nReboot #%d\n", cycle + 1);

// Power down the chip, wait 2 seconds, and reboot
ADS1299_reboot();
}

printf("\n--- ADS1299 power cycle test Finished ---\n");
} else if (!strcmp(test_name, "data_test")) {

printf("\n--- ADS1299 data test Started ---\n");
transferCmd(_START);
delayMicroseconds(500);
display_all_pin_states();
printf("\n--- ADS1299 data test Finished ---\n");
} else if (!strcmp(test_name, "stop_test")) {

printf("\n--- ADS1299 stop test Started ---\n");
transferCmd(_STOP);
delayMicroseconds(500);
display_all_pin_states();
printf("\n--- ADS1299 stop test Finished ---\n");
} else {
fprintf(stderr, "Test %s not found\n", test_name);
exit(EXIT_FAILURE);
}
}

attempt++;
// Delay 200 us before moving on or reattempting bootup
bcm2835_delayMicroseconds(200);

// Only power down if we did bootup
if (do_bootup && power_down) {
ADS1299_power_down();
}

bcm2835_delayMicroseconds(200);
}

if (!bootup_success ) {
printf("\nAttempts %d of %d to boot ADS1299 unsuccessful. Aborting...\n", num_attempts, num_attempts);
return 1;
}

if (!bootup_success) {
printf("\nAttempts %d of %d to boot ADS1299 unsuccessful. Aborting...\n", num_attempts, num_attempts);
return 1;
}

return 0;

0 comments on commit 6fea3ae

Please sign in to comment.