OpenBCI 32bit board variation with STM32L476 mircocontroller and mbed support

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
akpc806a
Date:
Sun Jan 22 04:10:11 2017 +0000
Parent:
0:2cb59ea20ace
Commit message:
OpenBCI 32bit board variation with STM32L476 mircocontroller and mbed support. Version V2 of firmware, forked from the same official version for the PIC32 board.

Changed in this revision

Definitions.h Show annotated file Show diff for this revision Revisions of this file
Definitions_32_Daisy.h Show diff for this revision Revisions of this file
OpenBCI_32_Daisy.cpp Show diff for this revision Revisions of this file
OpenBCI_32_Daisy.h Show diff for this revision Revisions of this file
OpenBCI_32bit_Library.cpp Show annotated file Show diff for this revision Revisions of this file
OpenBCI_32bit_Library.h Show annotated file Show diff for this revision Revisions of this file
PlatformDefs.h Show annotated file Show diff for this revision Revisions of this file
PlatformGPIO.cpp Show annotated file Show diff for this revision Revisions of this file
PlatformGPIO.h Show annotated file Show diff for this revision Revisions of this file
PlatformSPI.cpp Show annotated file Show diff for this revision Revisions of this file
PlatformUart.cpp Show annotated file Show diff for this revision Revisions of this file
PlatformUart.h Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.cpp Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Definitions.h	Sun Jan 22 04:10:11 2017 +0000
@@ -0,0 +1,383 @@
+//
+//  Definitions_32.h
+//
+//
+//  Created by Conor Russomanno, Luke Travis, and Joel Murphy. Summer 2013.
+//  Modified by Joel Murphy, Summer 2014
+//  Joel Added Daisy Functionality Fall 2014
+//
+
+#ifndef _____OpenBCI_32bit_Library_Definitions_h
+#define _____OpenBCI_32bit_Library_Definitions_h
+
+// The default baud rate
+#define OPENBCI_BAUD_RATE 115200
+
+// File transmissions
+#define OPENBCI_BOP 'A' // Begining of stream packet
+#define OPENBCI_EOP_STND_ACCEL          0xC0 // End of standard stream packet
+#define OPENBCI_EOP_STND_RAW_AUX        0xC1 // End of stream packet with raw packet
+#define OPENBCI_EOP_USER_DEFINED        0xC2 // End of stream packet, user defined
+#define OPENBCI_EOP_ACCEL_TIME_SET      0xC3 // End of time sync up with accel stream packet
+#define OPENBCI_EOP_ACCEL_TIME_SYNCED   0xC4 // End of time synced stream packet
+#define OPENBCI_EOP_RAW_AUX_TIME_SET    0xC5 // End of time sync up stream packet
+#define OPENBCI_EOP_RAW_AUX_TIME_SYNCED 0xC6 // End of time synced stream packet
+
+//PIN CONNECTIONS
+/*
+// MBED: pin definitions are in PlatformDefs.h
+#define ADS_DRDY        9   // ADS data ready pin
+#define ADS_RST         4   // ADS reset pin
+#define BOARD_ADS       8   // ADS chip select
+#define DAISY_ADS       3   // ADS Daisy chip select
+#define BOTH_ADS        5   // Slave Select Both ADS chips
+#define SD_SS           2   // SD card chip select
+#define LIS3DH_SS       1   // LIS3DH chip select
+#define LIS3DH_DRDY     0   // LIS3DH data ready pin
+#define OPENBCI_PIN_LED 11
+#define OPENBCI_PIN_PGC 12
+*/
+#define BOTH_ADS        5   // Slave Select Both ADS chips
+
+//ADS1299 SPI Command Definition Byte Assignments
+#define _WAKEUP 0x02 // Wake-up from standby mode
+#define _STANDBY 0x04 // Enter Standby mode
+#define _RESET 0x06 // Reset the device registers to default
+#define _START 0x08 // Start and restart (synchronize) conversions
+#define _STOP 0x0A // Stop conversion
+#define _RDATAC 0x10 // Enable Read Data Continuous mode (default mode at power-up)
+#define _SDATAC 0x11 // Stop Read Data Continuous mode
+#define _RDATA 0x12 // Read data by command supports multiple read back
+
+//ASD1299 Register Addresses
+#define ADS_ID  0x3E    // product ID for ADS1299
+#define ID_REG  0x00    // this register contains ADS_ID
+#define CONFIG1 0x01
+#define CONFIG2 0x02
+#define CONFIG3 0x03
+#define LOFF 0x04
+#define CH1SET 0x05
+#define CH2SET 0x06
+#define CH3SET 0x07
+#define CH4SET 0x08
+#define CH5SET 0x09
+#define CH6SET 0x0A
+#define CH7SET 0x0B
+#define CH8SET 0x0C
+#define BIAS_SENSP 0x0D
+#define BIAS_SENSN 0x0E
+#define LOFF_SENSP 0x0F
+#define LOFF_SENSN 0x10
+#define LOFF_FLIP 0x11
+#define LOFF_STATP 0x12
+#define LOFF_STATN 0x13
+//#define GPIO 0x14  // MBED: interfere with STM32 library
+static const int GPIO = 0x14;
+#define MISC1 0x15
+#define MISC2 0x16
+#define CONFIG4 0x17
+
+#define OUTPUT_NOTHING (0)  // quiet
+#define OUTPUT_8_CHAN (1)   // not using Daisy module
+#define OUTPUT_16_CHAN (2)  // using Daisy module
+#define ON_BOARD    (BOARD_ADS)           // slave address for on board ADS
+#define ON_DAISY    (DAISY_ADS)             // slave address for daisy ADS
+// CHANNEL SETTINGS 
+#define POWER_DOWN      (0)
+#define GAIN_SET        (1)
+#define INPUT_TYPE_SET  (2)
+#define BIAS_SET        (3)
+#define SRB2_SET        (4)
+#define SRB1_SET        (5)
+#define YES         (0x01)
+#define NO          (0x00)
+
+//gainCode choices
+#define ADS_GAIN01 (0b00000000) // 0x00
+#define ADS_GAIN02 (0b00010000) // 0x10
+#define ADS_GAIN04 (0b00100000) // 0x20
+#define ADS_GAIN06 (0b00110000) // 0x30
+#define ADS_GAIN08 (0b01000000) // 0x40
+#define ADS_GAIN12 (0b01010000) // 0x50
+#define ADS_GAIN24 (0b01100000) // 0x60
+
+//inputType choices
+#define ADSINPUT_NORMAL     (0b00000000)
+#define ADSINPUT_SHORTED    (0b00000001)
+#define ADSINPUT_BIAS_MEAS  (0b00000010)
+#define ADSINPUT_MVDD       (0b00000011)
+#define ADSINPUT_TEMP       (0b00000100)
+#define ADSINPUT_TESTSIG    (0b00000101)
+#define ADSINPUT_BIAS_DRP   (0b00000110)
+#define ADSINPUT_BIAL_DRN   (0b00000111)
+
+//test signal choices...ADS1299 datasheet page 41
+#define ADSTESTSIG_AMP_1X (0b00000000)
+#define ADSTESTSIG_AMP_2X (0b00000100)
+#define ADSTESTSIG_PULSE_SLOW (0b00000000)
+#define ADSTESTSIG_PULSE_FAST (0b00000001)
+#define ADSTESTSIG_DCSIG (0b00000011)
+#define ADSTESTSIG_NOCHANGE (0b11111111)
+
+//Lead-off signal choices
+#define LOFF_MAG_6NA        (0b00000000)
+#define LOFF_MAG_24NA       (0b00000100)
+#define LOFF_MAG_6UA        (0b00001000)
+#define LOFF_MAG_24UA       (0b00001100)
+#define LOFF_FREQ_DC        (0b00000000)
+#define LOFF_FREQ_7p8HZ     (0b00000001)
+#define LOFF_FREQ_31p2HZ    (0b00000010)
+#define LOFF_FREQ_FS_4      (0b00000011)
+#define PCHAN (0)
+#define NCHAN (1)
+#define OFF (0)
+#define ON (1)
+
+// used for channel settings
+#define ACTIVATE_SHORTED (2)
+#define ACTIVATE (1)
+#define DEACTIVATE (0)
+
+#define PCKT_START 0xA0 // prefix for data packet error checking
+#define PCKT_END 0xC0   // postfix for data packet error checking
+
+// daisy module
+#define CLK_EN  5
+
+//LIS3DH
+//#define READ_REG      0x80 // MBED: interfere with STM32 library
+static const int READ_REG = 0x80; 
+
+#define READ_MULTI      0x40
+
+#define STATUS_REG_AUX  0x07    // axis over-run and data available flags (see 0x27)
+#define OUT_ADC1_L      0x08    //
+#define OUT_ADC1_H      0x09    //
+#define OUT_ADC2_L      0x0A    //  ADC input values (check DS)
+#define OUT_ADC2_H      0x0B    //
+#define OUT_ADC3_L      0x0C    //
+#define OUT_ADC3_H      0x0D    //
+#define INT_COUNTER_REG 0x0E    // ??
+#define WHO_AM_I        0x0F    // DEVICE ID 0x33
+#define TMP_CFG_REG     0x1F    // ADC enable (0x80) Temperature sensor enable (0x40)
+#define CTRL_REG1       0x20    // Data Rate Power Mode X enable Y enable Z enable (on >0x10)
+#define CTRL_REG2       0x21    // High Pass Filter Stuph
+#define CTRL_REG3       0x22    // INT1 select register
+#define CTRL_REG4       0x23    // Block update timing endian G-force resolution self test SPI pins
+#define CTRL_REG5       0x24    // reboot FIFO enable latch 4D detection
+#define CTRL_REG6       0x25    // ??
+#define REFERENCE       0x26    // interrupt reference
+#define STATUS_REG2     0x27    // axis overrun and availale flags (see 0x07)
+#define OUT_X_L         0x28    //
+#define OUT_X_H         0x29    //
+#define OUT_Y_L         0x2A    //  tripple axis values (see 0x0A)
+#define OUT_Y_H         0x2B    //
+#define OUT_Z_L         0x2C    //
+#define OUT_Z_H         0x2D    //
+#define FIFO_CTRL_REG   0x2E    // FIFO mode trigger output pin select (?)
+#define FIFO_SRC_REG    0x2F    // ??
+#define INT1_CFG        0x30    // 6 degree control register
+#define INT1_SOURCE     0x31    // axis threshold interrupt control
+#define INT1_THS        0x32    // INT1 threshold
+#define INT1_DURATION   0x33    // INT1 duration
+#define CLICK_CFG       0x38    // click on axis
+#define CLICK_SRC       0x39    // other click
+#define CLICK_THS       0x3A    // more click
+#define TIME_LIMIT      0x3B    // click related
+#define TIME_LATENCY    0x3C    // and so on
+#define TIME_WINDOW     0x3D    // contined click
+
+#define SCALE_2G        0x00  //(b00000000) // +/- 2G sensitivity
+#define SCALE_4G        0x10  //(b00010000) // +/- 4G sensitivity
+#define SCALE_8G        0x20  //(b00100000) // +/- 8G sensitivity
+#define SCALE_16G       0x30  //(b00110000) // +/- 16G sensitivity
+#define RATE_1HZ        0x10  //(b00010000) // 1Hz sample rate in normal or low-power mode
+#define RATE_10HZ       0x20  //(b00100000) // 10Hz sample rate in normal or low-power mode
+#define RATE_25HZ       0x30  //(b00110000) // 25Hz sample rate in normal or low-power mode
+#define RATE_50HZ       0x40  //(b01000000) // 50Hz sample rate in normal or low-power mode
+#define RATE_100HZ      0x50  //(b01010000) // 100Hz sample rate in normal or low-power mode
+#define RATE_200HZ      0x60  //(b01100000) // 200Hz sample rate in normal or low-power mode
+#define RATE_400HZ      0x70  //(b01110000) // 400Hz sample rate in normal or low-power mode
+#define RATE_1600HZ_LP  0x80  //(b10000000) // 1600Hz sample rate in low-power mode
+#define RATE_1250HZ_N   0x90  //(b10010000) // 1250Hz sample rate in normal mode
+#define RATE_5000HZ_LP  0x90  //(b10010000) // 5000Hz sample rate in low-power mode
+#define ACCEL_AXIS_X    0x07 // x axis
+#define ACCEL_AXIS_Y    0x08 // y axis
+#define ACCEL_AXIS_Z    0x09 // z axis
+
+// OPENBCI_COMMANDS
+/** Turning channels off */
+#define OPENBCI_CHANNEL_OFF_1 '1'
+#define OPENBCI_CHANNEL_OFF_2 '2'
+#define OPENBCI_CHANNEL_OFF_3 '3'
+#define OPENBCI_CHANNEL_OFF_4 '4'
+#define OPENBCI_CHANNEL_OFF_5 '5'
+#define OPENBCI_CHANNEL_OFF_6 '6'
+#define OPENBCI_CHANNEL_OFF_7 '7'
+#define OPENBCI_CHANNEL_OFF_8 '8'
+#define OPENBCI_CHANNEL_OFF_9 'q'
+#define OPENBCI_CHANNEL_OFF_10 'w'
+#define OPENBCI_CHANNEL_OFF_11 'e'
+#define OPENBCI_CHANNEL_OFF_12 'r'
+#define OPENBCI_CHANNEL_OFF_13 't'
+#define OPENBCI_CHANNEL_OFF_14 'y'
+#define OPENBCI_CHANNEL_OFF_15 'u'
+#define OPENBCI_CHANNEL_OFF_16 'i'
+
+/** Turn channels on */
+#define OPENBCI_CHANNEL_ON_1 '!'
+#define OPENBCI_CHANNEL_ON_2 '@'
+#define OPENBCI_CHANNEL_ON_3 '#'
+#define OPENBCI_CHANNEL_ON_4 '$'
+#define OPENBCI_CHANNEL_ON_5 '%'
+#define OPENBCI_CHANNEL_ON_6 '^'
+#define OPENBCI_CHANNEL_ON_7 '&'
+#define OPENBCI_CHANNEL_ON_8 '*'
+#define OPENBCI_CHANNEL_ON_9 'Q'
+#define OPENBCI_CHANNEL_ON_10 'W'
+#define OPENBCI_CHANNEL_ON_11 'E'
+#define OPENBCI_CHANNEL_ON_12 'R'
+#define OPENBCI_CHANNEL_ON_13 'T'
+#define OPENBCI_CHANNEL_ON_14 'Y'
+#define OPENBCI_CHANNEL_ON_15 'U'
+#define OPENBCI_CHANNEL_ON_16 'I'
+
+/** Test Signal Control Commands
+ * 1x - Voltage will be 1 * (VREFP - VREFN) / 2.4 mV
+ * 2x - Voltage will be 2 * (VREFP - VREFN) / 2.4 mV
+ */
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_DC            'p'
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_GROUND        '0'
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_FAST '='
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_SLOW '-'
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_FAST ']'
+#define OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_SLOW '['
+
+/** Channel Setting Commands */
+#define OPENBCI_CHANNEL_CMD_ADC_Normal      '0'
+#define OPENBCI_CHANNEL_CMD_ADC_Shorted     '1'
+#define OPENBCI_CHANNEL_CMD_ADC_BiasDRP     '6'
+#define OPENBCI_CHANNEL_CMD_ADC_BiasDRN     '7'
+#define OPENBCI_CHANNEL_CMD_ADC_BiasMethod  '2'
+#define OPENBCI_CHANNEL_CMD_ADC_MVDD        '3'
+#define OPENBCI_CHANNEL_CMD_ADC_Temp        '4'
+#define OPENBCI_CHANNEL_CMD_ADC_TestSig     '5'
+#define OPENBCI_CHANNEL_CMD_BIAS_INCLUDE    '1'
+#define OPENBCI_CHANNEL_CMD_BIAS_REMOVE     '0'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_1       '1'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_2       '2'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_3       '3'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_4       '4'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_5       '5'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_6       '6'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_7       '7'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_8       '8'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_9       'Q'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_10      'W'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_11      'E'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_12      'R'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_13      'T'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_14      'Y'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_15      'U'
+#define OPENBCI_CHANNEL_CMD_CHANNEL_16      'I'
+#define OPENBCI_CHANNEL_CMD_GAIN_1          '0'
+#define OPENBCI_CHANNEL_CMD_GAIN_2          '1'
+#define OPENBCI_CHANNEL_CMD_GAIN_4          '2'
+#define OPENBCI_CHANNEL_CMD_GAIN_6          '3'
+#define OPENBCI_CHANNEL_CMD_GAIN_8          '4'
+#define OPENBCI_CHANNEL_CMD_GAIN_12         '5'
+#define OPENBCI_CHANNEL_CMD_GAIN_24         '6'
+#define OPENBCI_CHANNEL_CMD_LATCH           'X'
+#define OPENBCI_CHANNEL_CMD_POWER_OFF       '1'
+#define OPENBCI_CHANNEL_CMD_POWER_ON        '0'
+#define OPENBCI_CHANNEL_CMD_SET             'x'
+#define OPENBCI_CHANNEL_CMD_SRB1_CONNECT    '1'
+#define OPENBCI_CHANNEL_CMD_SRB1_DISCONNECT '0'
+#define OPENBCI_CHANNEL_CMD_SRB2_CONNECT    '1'
+#define OPENBCI_CHANNEL_CMD_SRB2_DISCONNECT '0'
+
+/** Default Channel Settings */
+#define OPENBCI_CHANNEL_DEFAULT_ALL_SET 'd'
+#define OPENBCI_CHANNEL_DEFAULT_ALL_REPORT 'D'
+
+/** LeadOff Impedance Commands */
+#define OPENBCI_CHANNEL_IMPEDANCE_LATCH                'Z'
+#define OPENBCI_CHANNEL_IMPEDANCE_SET                  'z'
+#define OPENBCI_CHANNEL_IMPEDANCE_TEST_SIGNAL_APPLIED    '1'
+#define OPENBCI_CHANNEL_IMPEDANCE_TEST_SIGNAL_APPLIED_NOT '0'
+
+/** SD card Commands */
+#define OPENBCI_SD_LOG_FOR_HOUR_1    'G'
+#define OPENBCI_SD_LOG_FOR_HOUR_2    'H'
+#define OPENBCI_SD_LOG_FOR_HOUR_4    'J'
+#define OPENBCI_SD_LOG_FOR_HOUR_12   'K'
+#define OPENBCI_SD_LOG_FOR_HOUR_24   'L'
+#define OPENBCI_SD_LOG_FOR_MIN_5     'A'
+#define OPENBCI_SD_LOG_FOR_MIN_15    'S'
+#define OPENBCI_SD_LOG_FOR_MIN_30    'F'
+#define OPENBCI_SD_LOG_FOR_SEC_14    'a'
+#define OPENBCI_SD_LOG_STOP        'j'
+
+/** Stream Data Commands */
+#define OPENBCI_STREAM_START  'b'
+#define OPENBCI_STREAM_STOP   's'
+
+/** Miscellaneous */
+#define OPENBCI_MISC_QUERY_REGISTER_SETTINGS '?'
+#define OPENBCI_MISC_SOFT_RESET              'v'
+
+/** 16 Channel Commands */
+#define OPENBCI_CHANNEL_MAX_NUMBER_8    'c'
+#define OPENBCI_CHANNEL_MAX_NUMBER_16   'C'
+
+/** Set Packet Type */
+#define OPENBCI_BOARD_MODE_SET '/'
+#define OPENBCI_BOARD_MODE_DEFAULT '0'
+#define OPENBCI_BOARD_MODE_DEBUG '1'
+#define OPENBCI_BOARD_MODE_WIFI '2'
+#define OPENBCI_BOARD_MODE_INPUT_ANALOG '3'
+#define OPENBCI_BOARD_MODE_INPUT_DIGITAL '4'
+
+/** Sync Clocks */
+#define OPENBCI_TIME_SET '<'
+#define OPENBCI_TIME_STOP '>'
+
+/** Possible number of channels */
+#define OPENBCI_NUMBER_OF_CHANNELS_DAISY 16
+#define OPENBCI_NUMBER_OF_CHANNELS_DEFAULT 8
+
+/** Helpful numbers */
+#define OPENBCI_NUMBER_OF_BOARD_SETTINGS 1
+#define OPENBCI_NUMBER_OF_CHANNEL_SETTINGS 6
+#define OPENBCI_NUMBER_OF_LEAD_OFF_SETTINGS 2
+
+/** Possible Sample Rates*/
+#define OPENBCI_SAMPLE_RATE_125 125
+#define OPENBCI_SAMPLE_RATE_250 250
+
+/** Packet Size */
+#define OPENBCI_PACKET_SIZE 33
+
+/** Impedance Calculation Variables */
+#define OPENBCI_LEAD_OFF_DRIVE_AMPS 0.000000006
+#define OPENBCI_LEAD_OFF_FREQUENCY_HZ 31
+
+/** Raw data packet types/codes */
+#define OPENBCI_PACKET_TYPE_V3              0 // 0000
+#define OPENBCI_PACKET_TYPE_TIME_SYNCED     1 // 0001
+#define OPENBCI_PACKET_TYPE_TIME_SET        2 // 0010
+#define OPENBCI_PACKET_TYPE_USER_DEFINED    3 // 0011
+#define OPENBCI_PACKET_TYPE_RAW_AUX         4 // 0100
+
+#define OPENBCI_TIME_OUT_MS_1 1
+#define OPENBCI_TIME_OUT_MS_3 3
+
+#define OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL 9
+#define OPENBCI_NUMBER_OF_BYTES_SETTINGS_LEAD_OFF 5
+
+#define OPENBCI_NUMBER_OF_BYTES_AUX 6
+
+#define OPENBCI_FIRMWARE_VERSION_V1 1
+#define OPENBCI_FIRMWARE_VERSION_V2 1
+
+#endif
--- a/Definitions_32_Daisy.h	Sun Dec 04 03:38:44 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-//
-//  Definitions_32.h
-//  
-//  
-//  Created by Conor Russomanno, Luke Travis, and Joel Murphy. Summer 2013.
-//  Modified by Joel Murphy, Summer 2014
-//  Joel Added Daisy Functionality Fall 2014
-//
-
-#ifndef _Definitions_32_Daisy_h
-#define _Definitions_32_Daisy_h
-
-//PIN CONNECTIONS 
-/*
-// MBED: pin definitions are in PlatformDefs.h
-  #define ADS_DRDY  9   // ADS data ready pin
-  #define ADS_RST   4       // ADS reset pin
-  #define BOARD_ADS 8       // ADS chip select
-  #define DAISY_ADS 3  // ADS Daisy chip select
-  
-  #define SD_SS 2       // SD card chip select
-  #define LIS3DH_SS 1 // LIS3DH chip select
-  #define LIS3DH_DRDY   0   // LIS3DH data ready pin
-*/
-#define BOTH_ADS    5    // Slave Select Both ADS chips
-
-//ADS1299 SPI Command Definition Byte Assignments
-#define _WAKEUP 0x02 // Wake-up from standby mode
-#define _STANDBY 0x04 // Enter Standby mode
-#define _RESET 0x06 // Reset the device registers to default
-#define _START 0x08 // Start and restart (synchronize) conversions
-#define _STOP 0x0A // Stop conversion
-#define _RDATAC 0x10 // Enable Read Data Continuous mode (default mode at power-up)
-#define _SDATAC 0x11 // Stop Read Data Continuous mode
-#define _RDATA 0x12 // Read data by command; supports multiple read back
-
-//ASD1299 Register Addresses
-#define ADS_ID  0x3E    // product ID for ADS1299
-#define ID_REG  0x00    // this register contains ADS_ID
-#define CONFIG1 0x01
-#define CONFIG2 0x02
-#define CONFIG3 0x03
-#define LOFF 0x04
-#define CH1SET 0x05
-#define CH2SET 0x06
-#define CH3SET 0x07
-#define CH4SET 0x08
-#define CH5SET 0x09
-#define CH6SET 0x0A
-#define CH7SET 0x0B
-#define CH8SET 0x0C
-#define BIAS_SENSP 0x0D
-#define BIAS_SENSN 0x0E
-#define LOFF_SENSP 0x0F
-#define LOFF_SENSN 0x10
-#define LOFF_FLIP 0x11
-#define LOFF_STATP 0x12
-#define LOFF_STATN 0x13
-//#define GPIO 0x14  // MBED: interfere with STM32 library
-static const int GPIO = 0x14;
-#define MISC1 0x15
-#define MISC2 0x16
-#define CONFIG4 0x17
-
-#define OUTPUT_NOTHING (0)  // quiet
-#define OUTPUT_8_CHAN (1)   // not using Daisy module
-#define OUTPUT_16_CHAN (2)  // using Daisy module
-#define ON_BOARD    (BOARD_ADS)           // slave address for on board ADS
-#define ON_DAISY    (DAISY_ADS)             // slave address for daisy ADS
-// CHANNEL SETTINGS 
-#define POWER_DOWN      (0)
-#define GAIN_SET        (1)
-#define INPUT_TYPE_SET  (2)
-#define BIAS_SET        (3)
-#define SRB2_SET        (4)
-#define SRB1_SET        (5)
-#define YES         (0x01)
-#define NO          (0x00)
-
-//gainCode choices
-#define ADS_GAIN01 (0b00000000) // 0x00
-#define ADS_GAIN02 (0b00010000) // 0x10
-#define ADS_GAIN04 (0b00100000) // 0x20
-#define ADS_GAIN06 (0b00110000) // 0x30
-#define ADS_GAIN08 (0b01000000) // 0x40
-#define ADS_GAIN12 (0b01010000) // 0x50
-#define ADS_GAIN24 (0b01100000) // 0x60
-
-//inputType choices
-#define ADSINPUT_NORMAL (0b00000000)
-#define ADSINPUT_SHORTED (0b00000001)
-#define ADSINPUT_BIAS_MEAS (0b00000010)
-#define ADSINPUT_MVDD (0b00000011)
-#define ADSINPUT_TEMP (0b00000100)
-#define ADSINPUT_TESTSIG (0b00000101)
-#define ADSINPUT_BIAS_DRP (0b00000110)
-#define ADSINPUT_BIAL_DRN (0b00000111)
-
-//test signal choices...ADS1299 datasheet page 41
-#define ADSTESTSIG_AMP_1X (0b00000000)
-#define ADSTESTSIG_AMP_2X (0b00000100)
-#define ADSTESTSIG_PULSE_SLOW (0b00000000)
-#define ADSTESTSIG_PULSE_FAST (0b00000001)
-#define ADSTESTSIG_DCSIG (0b00000011)
-#define ADSTESTSIG_NOCHANGE (0b11111111)
-
-//Lead-off signal choices
-#define LOFF_MAG_6NA (0b00000000)
-#define LOFF_MAG_24NA (0b00000100)
-#define LOFF_MAG_6UA (0b00001000)
-#define LOFF_MAG_24UA (0b00001100)
-#define LOFF_FREQ_DC (0b00000000)
-#define LOFF_FREQ_7p8HZ (0b00000001)
-#define LOFF_FREQ_31p2HZ (0b00000010)
-#define LOFF_FREQ_FS_4 (0b00000011)
-#define PCHAN (0)
-#define NCHAN (1)
-#define OFF (0)
-#define ON (1)
-
-// used for channel settings
-#define ACTIVATE_SHORTED (2)
-#define ACTIVATE (1)
-#define DEACTIVATE (0)
-
-#define PCKT_START 0xA0 // prefix for data packet error checking
-#define PCKT_END 0xC0   // postfix for data packet error checking
-
-// daisy module 
-#define CLK_EN  5
-
-//LIS3DH
-//#define READ_REG      0x80 // MBED: interfere with STM32 library
-static const int READ_REG = 0x80; 
-
-#define READ_MULTI      0x40
-
-#define STATUS_REG_AUX          0x07    // axis over-run and data available flags (see 0x27)
-#define OUT_ADC1_L      0x08    // 
-#define OUT_ADC1_H      0x09    //
-#define OUT_ADC2_L      0x0A    //  ADC input values (check DS)
-#define OUT_ADC2_H      0x0B    //
-#define OUT_ADC3_L      0x0C    //
-#define OUT_ADC3_H      0x0D    //
-#define INT_COUNTER_REG         0x0E    // ??
-#define WHO_AM_I        0x0F    // DEVICE ID = 0x33
-#define TMP_CFG_REG     0x1F    // ADC enable (0x80); Temperature sensor enable (0x40)
-#define CTRL_REG1       0x20    // Data Rate; Power Mode; X enable; Y enable; Z enable (on >= 0x10)
-#define CTRL_REG2       0x21    // High Pass Filter Stuph
-#define CTRL_REG3       0x22    // INT1 select register
-#define CTRL_REG4       0x23    // Block update timing; endian; G-force; resolution; self test; SPI pins
-#define CTRL_REG5       0x24    // reboot; FIFO enable; latch; 4D detection;
-#define CTRL_REG6       0x25    // ??
-#define REFERENCE       0x26    // interrupt reference
-#define STATUS_REG2     0x27    // axis overrun and availale flags (see 0x07)
-#define OUT_X_L         0x28    //
-#define OUT_X_H         0x29    //
-#define OUT_Y_L         0x2A    //  tripple axis values (see 0x0A)
-#define OUT_Y_H         0x2B    //
-#define OUT_Z_L         0x2C    //
-#define OUT_Z_H         0x2D    //
-#define FIFO_CTRL_REG           0x2E    // FIFO mode; trigger output pin select (?); 
-#define FIFO_SRC_REG            0x2F    // ??
-#define INT1_CFG        0x30    // 6 degree control register
-#define INT1_SOURCE     0x31    // axis threshold interrupt control
-#define INT1_THS        0x32    // INT1 threshold
-#define INT1_DURATION           0x33    // INT1 duration
-#define CLICK_CFG       0x38    // click on axis
-#define CLICK_SRC       0x39    // other click
-#define CLICK_THS       0x3A    // more click
-#define TIME_LIMIT      0x3B    // click related
-#define TIME_LATENCY            0x3C    // and so on
-#define TIME_WINDOW     0x3D    // contined click
-
-#define SCALE_2G        0x00  //(b00000000) // +/- 2G sensitivity
-#define SCALE_4G        0x10  //(b00010000) // +/- 4G sensitivity
-#define SCALE_8G        0x20  //(b00100000) // +/- 8G sensitivity
-#define SCALE_16G       0x30  //(b00110000) // +/- 16G sensitivity
-#define RATE_1HZ        0x10  //(b00010000) // 1Hz sample rate in normal or low-power mode
-#define RATE_10HZ       0x20  //(b00100000) // 10Hz sample rate in normal or low-power mode
-#define RATE_25HZ       0x30  //(b00110000) // 25Hz sample rate in normal or low-power mode
-#define RATE_50HZ       0x40  //(b01000000) // 50Hz sample rate in normal or low-power mode
-#define RATE_100HZ      0x50  //(b01010000) // 100Hz sample rate in normal or low-power mode
-#define RATE_200HZ      0x60  //(b01100000) // 200Hz sample rate in normal or low-power mode
-#define RATE_400HZ      0x70  //(b01110000) // 400Hz sample rate in normal or low-power mode
-#define RATE_1600HZ_LP          0x80  //(b10000000) // 1600Hz sample rate in low-power mode
-#define RATE_1250HZ_N       0x90  //(b10010000) // 1250Hz sample rate in normal mode
-#define RATE_5000HZ_LP          0x90  //(b10010000) // 5000Hz sample rate in low-power mode
-
-
-
-#endif
--- a/OpenBCI_32_Daisy.cpp	Sun Dec 04 03:38:44 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1140 +0,0 @@
-
-/*
-    OpenBCI 32bit Library
-    Place the containing folder into your libraries folder insdie the arduino folder in your Documents folder
-    
-    This library will work with a single OpenBCI 32bit board, or 
-    an OpenBCI 32bit board with an OpenBCI Daisy Module attached.
-
-*/
-
-#include "OpenBCI_32_Daisy.h"
-
-
-// <<<<<<<<<<<<<<<<<<<<<<<<<  BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-
-void OpenBCI_32_Daisy::initialize(){
-  pinMode(SD_SS,OUTPUT); digitalWrite(SD_SS,HIGH);  // de-select SDcard if present
-  pinMode(BOARD_ADS, OUTPUT); digitalWrite(BOARD_ADS,HIGH); 
-  pinMode(DAISY_ADS, OUTPUT); digitalWrite(DAISY_ADS,HIGH); 
-  pinMode(LIS3DH_SS,OUTPUT); digitalWrite(LIS3DH_SS,HIGH);
-  spi.begin();
-  spi.setSpeed(4000000);  // use 4MHz for ADS and LIS3DH
-  spi.setMode(DSPI_MODE0);  // default to SD card mode!
-  initialize_ads(); // hard reset ADS, set pin directions 
-  initialize_accel(SCALE_4G); // set pin directions, G scale, DRDY interrupt, power down
-}
-
-void OpenBCI_32_Daisy::printAllRegisters(){
-  if(!isRunning){
-    Serial0.println("\nBoard ADS Registers");
-    printADSregisters(BOARD_ADS);  
-    if(daisyPresent){ 
-      Serial0.println("\nDaisy ADS Registers");
-      printADSregisters(DAISY_ADS); 
-    }
-    Serial0.println("\nLIS3DH Registers");
-    LIS3DH_readAllRegs(); 
-  }
-}
-
-void OpenBCI_32_Daisy::startStreaming(){  // needs daisy functionality
-  startADS(); 
-} 
-
-void OpenBCI_32_Daisy::sendChannelData(){ 
-Serial0.write(0xA0); // start byte
-  Serial0.write(sampleCounter); // 1 byte
-  ADS_writeChannelData();       // 24 bytes  
-  if(useAux){
-    writeAuxData();             // 6 bytes of aux data
-  }else if(useAccel){           // or
-    LIS3DH_writeAxisData();     // 6 bytes of accelerometer data
-  }else{
-    byte zero = 0x00;
-    for(int i=0; i<6; i++){
-      Serial0.write(zero);
-    }
-  }
-Serial0.write(0xC0); // end byte
-  sampleCounter++;
-}
-
-void OpenBCI_32_Daisy::writeAuxData(){
-  for(int i=0; i<3; i++){
-    Serial0.write(highByte(auxData[i])); // write 16 bit axis data MSB first
-    Serial0.write(lowByte(auxData[i]));  // axisData is array of type short (16bit)
-    auxData[i] = 0;   // reset auxData bytes to 0
-  }
-}
-
-void OpenBCI_32_Daisy::stopStreaming(){
-  stopADS();  
-}
-
-//SPI communication method
-byte OpenBCI_32_Daisy::xfer(byte _data) 
-{
-    byte inByte;
-    inByte = spi.transfer(_data);
-    return inByte;
-}
-
-//SPI chip select method
-void OpenBCI_32_Daisy::csLow(int SS)
-{ // select an SPI slave to talk to
-  switch(SS){
-    case BOARD_ADS:
-      spi.setMode(DSPI_MODE1); spi.setSpeed(4000000); digitalWrite(BOARD_ADS, LOW); break;
-    case LIS3DH_SS:
-      spi.setMode(DSPI_MODE3); spi.setSpeed(4000000); digitalWrite(LIS3DH_SS, LOW); break;
-    case SD_SS:
-      spi.setMode(DSPI_MODE0); spi.setSpeed(20000000); digitalWrite(SD_SS, LOW); break;
-    case DAISY_ADS:
-      spi.setMode(DSPI_MODE1); spi.setSpeed(4000000); digitalWrite(DAISY_ADS, LOW); break;  
-    case BOTH_ADS:
-      spi.setMode(DSPI_MODE1); spi.setSpeed(4000000);
-      digitalWrite(BOARD_ADS,LOW); digitalWrite(DAISY_ADS,LOW); break;
-    default: break;
-  }
-}
-
-void OpenBCI_32_Daisy::csHigh(int SS)
-{ // deselect SPI slave
-  switch(SS){
-    case BOARD_ADS:
-      digitalWrite(BOARD_ADS, HIGH); spi.setSpeed(20000000); break;
-    case LIS3DH_SS:
-      digitalWrite(LIS3DH_SS, HIGH); spi.setSpeed(20000000); break;
-    case SD_SS:
-      digitalWrite(SD_SS, HIGH); spi.setSpeed(4000000); break;
-    case DAISY_ADS:
-      digitalWrite(DAISY_ADS, HIGH); spi.setSpeed(20000000); break;  
-    case BOTH_ADS:
-      digitalWrite(BOARD_ADS, HIGH); digitalWrite(DAISY_ADS, HIGH);
-      spi.setSpeed(20000000); break;
-    default:
-      break;
-  }
-  spi.setMode(DSPI_MODE0);  // DEFAULT TO SD MODE!
-}
-
-// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-// *************************************************************************************
-// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  ADS1299 FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-
-
-void OpenBCI_32_Daisy::initialize_ads(){
-// recommended power up sequence requiers >Tpor (~32mS) 
-    delay(50);              
-    pinMode(ADS_RST,OUTPUT);  
-    digitalWrite(ADS_RST,LOW);  // reset pin connected to both ADS ICs
-    delayMicroseconds(4);   // toggle reset pin
-    digitalWrite(ADS_RST,HIGH); // this will reset the Daisy if it is present
-    delayMicroseconds(20);  // recommended to wait 18 Tclk before using device (~8uS);    
-// initalize the  data ready chip select and reset pins:
-    pinMode(ADS_DRDY, INPUT); // we get DRDY asertion from the on-board ADS
-    delay(40);
-    resetADS(BOARD_ADS); // reset the on-board ADS registers, and stop DataContinuousMode
-    delay(10);
-    WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output its clk, set the data rate to 250SPS
-    delay(40);
-    resetADS(DAISY_ADS); // software reset daisy module if present
-    delay(10);
-    daisyPresent = smellDaisy(); // check to see if daisy module is present
-    if(!daisyPresent){
-      WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
-      numChannels = 8;    // expect up to 8 ADS channels
-    }else{
-      numChannels = 16;   // expect up to 16 ADS channels
-    } 
-
-    // DEFAULT CHANNEL SETTINGS FOR ADS
-    defaultChannelSettings[POWER_DOWN] = NO;        // on = NO, off = YES
-    defaultChannelSettings[GAIN_SET] = ADS_GAIN24;     // Gain setting
-    defaultChannelSettings[INPUT_TYPE_SET] = ADSINPUT_NORMAL;// input muxer setting
-    defaultChannelSettings[BIAS_SET] = YES;    // add this channel to bias generation
-    defaultChannelSettings[SRB2_SET] = YES;       // connect this P side to SRB2
-    defaultChannelSettings[SRB1_SET] = NO;        // don't use SRB1
-
-    for(int i=0; i<numChannels; i++){
-      for(int j=0; j<6; j++){
-        channelSettings[i][j] = defaultChannelSettings[j];  // assign default settings
-      }
-      useInBias[i] = true;    // keeping track of Bias Generation
-      useSRB2[i] = true;      // keeping track of SRB2 inclusion
-    }
-    boardUseSRB1 = daisyUseSRB1 = false;
-
-    writeChannelSettings(); // write settings to the on-board and on-daisy ADS if present
-
-    WREG(CONFIG3,0b11101100,BOTH_ADS); delay(1);  // enable internal reference drive and etc.
-    for(int i=0; i<numChannels; i++){  // turn off the impedance measure signal
-      leadOffSettings[i][PCHAN] = OFF;
-      leadOffSettings[i][NCHAN] = OFF;
-    }
-    verbosity = false;      // when verbosity is true, there will be Serial feedback
-    firstDataPacket = true;
-}
-
-boolean OpenBCI_32_Daisy::smellDaisy(void){ // check if daisy present
-  boolean isDaisy = false;
-  byte setting = RREG(ID_REG,DAISY_ADS); // try to read the daisy product ID
-  if(verbosity){Serial0.print("Daisy ID 0x"); Serial0.println(setting,HEX);}
-  if(setting == ADS_ID) {isDaisy = true;} // should read as 0x3E
-  return isDaisy;
-}
-
-void OpenBCI_32_Daisy::removeDaisy(void){
-  if(daisyPresent){
-    SDATAC(DAISY_ADS);
-    RESET(DAISY_ADS);
-    STANDBY(DAISY_ADS);
-    daisyPresent = false;
-    if(!isRunning) Serial0.println("daisy removed");
-  }else{
-    if(!isRunning) Serial0.println("no daisy to remove!");
-  }
-}
-
-void OpenBCI_32_Daisy::attachDaisy(void){
-  WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output the clk, set the data rate to 250SPS
-  delay(40);
-  resetADS(DAISY_ADS); // software reset daisy module if present
-  delay(10);
-  daisyPresent = smellDaisy(); 
-  if(!daisyPresent){
-    WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
-    numChannels = 8;    // expect up to 8 ADS channels
-    if(!isRunning) Serial0.println("no daisy to attach!");
-  }else{
-    numChannels = 16;   // expect up to 16 ADS channels
-    if(!isRunning) Serial0.println("daisy attached");
-  } 
-}
-
-//reset all the ADS1299's settings. Stops all data acquisition
-void OpenBCI_32_Daisy::resetADS(int targetSS) 
-{
-  int startChan, stopChan;
-  if(targetSS == BOARD_ADS) {startChan = 1; stopChan = 8;}
-  if(targetSS == DAISY_ADS) {startChan = 9; stopChan = 16;}
-  RESET(targetSS);             // send RESET command to default all registers
-  SDATAC(targetSS);            // exit Read Data Continuous mode to communicate with ADS
-  delay(100);
-  // turn off all channels
-  for (int chan=startChan; chan <= stopChan; chan++) {
-    deactivateChannel(chan);
-  } 
-}
-
-void OpenBCI_32_Daisy::setChannelsToDefault(void){ 
-  for(int i=0; i<numChannels; i++){
-    for(int j=0; j<6; j++){
-      channelSettings[i][j] = defaultChannelSettings[j];
-    }
-    useInBias[i] = true;    // keeping track of Bias Generation
-    useSRB2[i] = true;      // keeping track of SRB2 inclusion
-  }
-  boardUseSRB1 = daisyUseSRB1 = false;
-
-  writeChannelSettings();       // write settings to on-board ADS
-
-  for(int i=0; i<numChannels; i++){   // turn off the impedance measure signal
-    leadOffSettings[i][PCHAN] = OFF;
-    leadOffSettings[i][NCHAN] = OFF;
-  }
-  changeChannelLeadOffDetect(); // write settings to all ADS
-
-  
-  WREG(MISC1,0x00,BOARD_ADS);  // open SRB1 switch on-board
-  if(daisyPresent){ WREG(MISC1,0x00,DAISY_ADS); } // open SRB1 switch on-daisy
-}
-
-
-void OpenBCI_32_Daisy::reportDefaultChannelSettings(void){
-
-    Serial0.write(defaultChannelSettings[POWER_DOWN] + '0');        // on = NO, off = YES
-    Serial0.write((defaultChannelSettings[GAIN_SET] >> 4) + '0');     // Gain setting
-    Serial0.write(defaultChannelSettings[INPUT_TYPE_SET] +'0');// input muxer setting
-    Serial0.write(defaultChannelSettings[BIAS_SET] + '0');    // add this channel to bias generation
-    Serial0.write(defaultChannelSettings[SRB2_SET] + '0');       // connect this P side to SRB2
-    Serial0.write(defaultChannelSettings[SRB1_SET] + '0');        // don't use SRB1
-}
-
-// write settings for ALL 8 channels for a given ADS board
-// channel settings: powerDown, gain, inputType, SRB2, SRB1 
-void OpenBCI_32_Daisy::writeChannelSettings(){   
-  boolean use_SRB1 = false;
-  byte setting, startChan, endChan, targetSS;  
-
-  for(int b=0; b<2; b++){
-    if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
-    if(b == 1){ 
-      if(!daisyPresent){ return; }
-      targetSS = DAISY_ADS; startChan = 8; endChan = 16;
-    }
-  
-    SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
-
-    for(byte i=startChan; i<endChan; i++){ // write 8 channel settings
-      setting = 0x00;
-      if(channelSettings[i][POWER_DOWN] == YES){setting |= 0x80;}
-      setting |= channelSettings[i][GAIN_SET]; // gain
-      setting |= channelSettings[i][INPUT_TYPE_SET]; // input code
-      if(channelSettings[i][SRB2_SET] == YES){
-        setting |= 0x08;    // close this SRB2 switch
-        useSRB2[i] = true;  // remember SRB2 state for this channel 
-      }else{
-        useSRB2[i] = false; // rememver SRB2 state for this channel
-      }
-      WREG(CH1SET+(i-startChan),setting,targetSS);  // write this channel's register settings
-      
-      // add or remove this channel from inclusion in BIAS generation
-      setting = RREG(BIAS_SENSP,targetSS);                   //get the current P bias settings
-      if(channelSettings[i][BIAS_SET] == YES){
-        bitSet(setting,i-startChan); useInBias[i] = true;    //add this channel to the bias generation
-      }else{
-        bitClear(setting,i-startChan); useInBias[i] = false; //remove this channel from bias generation
-      }
-      WREG(BIAS_SENSP,setting,targetSS); delay(1);           //send the modified byte back to the ADS
-
-      setting = RREG(BIAS_SENSN,targetSS);                   //get the current N bias settings
-      if(channelSettings[i][BIAS_SET] == YES){
-        bitSet(setting,i-startChan);    //set this channel's bit to add it to the bias generation
-      }else{
-        bitClear(setting,i-startChan);  // clear this channel's bit to remove from bias generation
-      }
-      WREG(BIAS_SENSN,setting,targetSS); delay(1);           //send the modified byte back to the ADS
-       
-      if(channelSettings[i][SRB1_SET] == YES){
-        use_SRB1 = true;  // if any of the channel setting closes SRB1, it is closed for all
-      }
-    } // end of CHnSET and BIAS settings
-  } // end of board select loop
-    if(use_SRB1){
-      for(int i=startChan; i<endChan; i++){
-        channelSettings[i][SRB1_SET] = YES;
-      }
-      WREG(MISC1,0x20,targetSS);     // close SRB1 swtich
-      if(targetSS == BOARD_ADS){ boardUseSRB1 = true; }
-      if(targetSS == DAISY_ADS){ daisyUseSRB1 = true; }
-    }else{
-      for(int i=startChan; i<endChan; i++){
-        channelSettings[i][SRB1_SET] = NO;
-      }
-      WREG(MISC1,0x00,targetSS);    // open SRB1 switch
-      if(targetSS == BOARD_ADS){ boardUseSRB1 = false; }
-      if(targetSS == DAISY_ADS){ daisyUseSRB1 = false; }
-    }
-}
-
-// write settings for a SPECIFIC channel on a given ADS board
-void OpenBCI_32_Daisy::writeChannelSettings(byte N){  
-  
-  byte setting, startChan, endChan, targetSS;  
-  if(N < 9){  // channels 1-8 on board
-    targetSS = BOARD_ADS; startChan = 0; endChan = 8; 
-  }else{      // channels 9-16 on daisy module
-    if(!daisyPresent) { return; }
-    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
-  }
-// function accepts channel 1-16, must be 0 indexed to work with array
-  N = constrain(N-1,startChan,endChan-1);  //subtracts 1 so that we're counting from 0, not 1
-// first, disable any data collection
-  SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
-  
-  setting = 0x00;
-  if(channelSettings[N][POWER_DOWN] == YES) setting |= 0x80;
-  setting |= channelSettings[N][GAIN_SET]; // gain
-  setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
-  if(channelSettings[N][SRB2_SET] == YES){
-    setting |= 0x08; // close this SRB2 switch
-    useSRB2[N] = true;  // keep track of SRB2 usage
-  }else{
-    useSRB2[N] = false;
-  }
-  WREG(CH1SET+(N-startChan), setting, targetSS);  // write this channel's register settings
-
-  // add or remove from inclusion in BIAS generation
-  setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
-  if(channelSettings[N][BIAS_SET] == YES){
-    useInBias[N] = true;
-    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
-  }else{
-    useInBias[N] = false;
-    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
-  }
-  WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
-  setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
-  if(channelSettings[N][BIAS_SET] == YES){
-    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
-  }else{
-    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
-  }
-  WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
-    
-// if SRB1 is closed or open for one channel, it will be the same for all channels    
-  if(channelSettings[N][SRB1_SET] == YES){
-    for(int i=startChan; i<endChan; i++){
-      channelSettings[i][SRB1_SET] = YES;
-    }
-    if(targetSS == BOARD_ADS) boardUseSRB1 = true;
-    if(targetSS == DAISY_ADS) daisyUseSRB1 = true;
-    setting = 0x20;     // close SRB1 swtich
-  }
-  if(channelSettings[N][SRB1_SET] == NO){
-    for(int i=startChan; i<endChan; i++){
-      channelSettings[i][SRB1_SET] = NO;
-    }
-    if(targetSS == BOARD_ADS) boardUseSRB1 = false;
-    if(targetSS == DAISY_ADS) daisyUseSRB1 = false;
-    setting = 0x00;     // open SRB1 switch
-  }
-  WREG(MISC1,setting,targetSS);
-}
-
-//  deactivate the given channel.
-void OpenBCI_32_Daisy::deactivateChannel(byte N) 
-{
-  byte setting, startChan, endChan, targetSS;  
-  if(N < 9){
-    targetSS = BOARD_ADS; startChan = 0; endChan = 8; 
-  }else{
-    if(!daisyPresent) { return; }
-    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
-  }
-  SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
-  N = constrain(N-1,startChan,endChan-1);  //subtracts 1 so that we're counting from 0, not 1
-
-  setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings
-  bitSet(setting,7);     // set bit7 to shut down channel
-  bitClear(setting,3);   // clear bit3 to disclude from SRB2 if used
-  WREG(CH1SET+(N-startChan),setting,targetSS); delay(1);     // write the new value to disable the channel
-  
-  //remove the channel from the bias generation...
-  setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings
-  bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
-  WREG(BIAS_SENSP,setting,targetSS); delay(1);   //send the modified byte back to the ADS
-
-  setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings
-  bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
-  WREG(BIAS_SENSN,setting,targetSS); delay(1);   //send the modified byte back to the ADS
-  
-  leadOffSettings[N][0] = leadOffSettings[N][1] = NO;
-  changeChannelLeadOffDetect(N+1);
-} 
-
-void OpenBCI_32_Daisy::activateChannel(byte N) 
-{
-    byte setting, startChan, endChan, targetSS;  
-  if(N < 9){
-    targetSS = BOARD_ADS; startChan = 0; endChan = 8; 
-  }else{
-    if(!daisyPresent) { return; }
-    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
-  }
-
-  N = constrain(N-1,startChan,endChan-1);  // 0-7 or 8-15
-
-  SDATAC(targetSS);  // exit Read Data Continuous mode to communicate with ADS
-  setting = 0x00;
-//  channelSettings[N][POWER_DOWN] = NO; // keep track of channel on/off in this array  REMOVE?
-  setting |= channelSettings[N][GAIN_SET]; // gain
-  setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
-  if(useSRB2[N] == true){channelSettings[N][SRB2_SET] = YES;}else{channelSettings[N][SRB2_SET] = NO;}
-  if(channelSettings[N][SRB2_SET] == YES) {bitSet(setting,3);} // close this SRB2 switch
-  WREG(CH1SET+(N-startChan),setting,targetSS);
-  // add or remove from inclusion in BIAS generation
-  if(useInBias[N]){channelSettings[N][BIAS_SET] = YES;}else{channelSettings[N][BIAS_SET] = NO;}
-  setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
-  if(channelSettings[N][BIAS_SET] == YES){
-    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
-    useInBias[N] = true;
-  }else{
-    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
-    useInBias[N] = false;
-  }
-  WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
-  setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
-  if(channelSettings[N][BIAS_SET] == YES){
-    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
-  }else{
-    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
-  }
-  WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
-    
-  setting = 0x00;
-  if(targetSS == BOARD_ADS && boardUseSRB1 == true) setting = 0x20;
-  if(targetSS == DAISY_ADS && daisyUseSRB1 == true) setting = 0x20;
-  WREG(MISC1,setting,targetSS);     // close all SRB1 swtiches
-}
-
-// change the lead off detect settings for all channels
-void OpenBCI_32_Daisy::changeChannelLeadOffDetect() 
-{
-  byte setting, startChan, endChan, targetSS;  
-
-  for(int b=0; b<2; b++){
-    if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
-    if(b == 1){ 
-      if(!daisyPresent){ return; }
-      targetSS = DAISY_ADS; startChan = 8; endChan = 16;
-    }
- 
-    SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
-    byte P_setting = RREG(LOFF_SENSP,targetSS);
-    byte N_setting = RREG(LOFF_SENSN,targetSS);
-    
-    for(int i=startChan; i<endChan; i++){
-      if(leadOffSettings[i][PCHAN] == ON){
-        bitSet(P_setting,i-startChan);
-      }else{
-        bitClear(P_setting,i-startChan);
-      }
-      if(leadOffSettings[i][NCHAN] == ON){
-        bitSet(N_setting,i-startChan);
-      }else{
-        bitClear(N_setting,i-startChan);
-      }
-     WREG(LOFF_SENSP,P_setting,targetSS);
-     WREG(LOFF_SENSN,N_setting,targetSS);
-    }
-  }
-}
-
-// change the lead off detect settings for specified channel
-void OpenBCI_32_Daisy::changeChannelLeadOffDetect(byte N) // N arrives as zero indexed
-{
-  byte setting, targetSS, startChan; //, endChan;
-
-  if(N < 0x08){
-    targetSS = BOARD_ADS; startChan = 0x00; //endChan = 0x08; 
-  }else{
-    if(!daisyPresent) { Serial0.println("no daisy attached!"); return; }
-    targetSS = DAISY_ADS; startChan = 0x08; //endChan = 0x10;
-  }
-
-
-  // N = constrain(N-1,startChan,endChan-1);
-  // SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
-  byte P_setting = RREG(LOFF_SENSP,targetSS);
-  byte N_setting = RREG(LOFF_SENSN,targetSS);
-  
-    if(leadOffSettings[N][PCHAN] == ON){
-      bitSet(P_setting,N-startChan);
-    }else{
-      bitClear(P_setting,N-startChan);
-    }
-    if(leadOffSettings[N][NCHAN] == ON){
-      bitSet(N_setting,N-startChan);
-    }else{
-      bitClear(N_setting,N-startChan);
-    }
-   WREG(LOFF_SENSP,P_setting,targetSS);
-   WREG(LOFF_SENSN,N_setting,targetSS);
-} 
-
-void OpenBCI_32_Daisy::configureLeadOffDetection(byte amplitudeCode, byte freqCode) 
-{
-    amplitudeCode &= 0b00001100;  //only these two bits should be used
-    freqCode &= 0b00000011;  //only these two bits should be used
-    
-    byte setting, targetSS;
-    for(int i=0; i<2; i++){
-    if(i == 0){ targetSS = BOARD_ADS; }
-    if(i == 1){ 
-      if(!daisyPresent){ return; }
-      targetSS = DAISY_ADS; 
-    }
-    setting = RREG(LOFF,targetSS); //get the current bias settings
-    //reconfigure the byte to get what we want
-    setting &= 0b11110000;  //clear out the last four bits
-    setting |= amplitudeCode;  //set the amplitude
-    setting |= freqCode;    //set the frequency
-    //send the config byte back to the hardware
-    WREG(LOFF,setting,targetSS); delay(1);  //send the modified byte back to the ADS
-    }
-}
-
-//Configure the test signals that can be inernally generated by the ADS1299
-void OpenBCI_32_Daisy::configureInternalTestSignal(byte amplitudeCode, byte freqCode) 
-{
-  byte setting, targetSS;
-  for(int i=0; i<2; i++){
-    if(i == 0){ targetSS = BOARD_ADS;}
-    if(i == 1){ 
-      if(daisyPresent == false){ return; }
-      targetSS = DAISY_ADS; 
-    }
-    if (amplitudeCode == ADSTESTSIG_NOCHANGE) amplitudeCode = (RREG(CONFIG2,targetSS) & (0b00000100));
-    if (freqCode == ADSTESTSIG_NOCHANGE) freqCode = (RREG(CONFIG2,targetSS) & (0b00000011));
-    freqCode &= 0b00000011;         //only the last two bits are used
-    amplitudeCode &= 0b00000100;    //only this bit is used
-    byte setting = 0b11010000 | freqCode | amplitudeCode;  //compose the code
-    WREG(CONFIG2,setting,targetSS); delay(1);
-    }
-}
-
-void OpenBCI_32_Daisy::changeInputType(byte inputCode){
-
-  for(int i=0; i<numChannels; i++){
-    channelSettings[i][INPUT_TYPE_SET] = inputCode;
-  }
-
-  writeChannelSettings();
-
-}
- 
-// Start continuous data acquisition
-void OpenBCI_32_Daisy::startADS(void) // NEEDS ADS ADDRESS, OR BOTH?
-{
-  sampleCounter = 0;
-  firstDataPacket = true;
-  RDATAC(BOTH_ADS); // enter Read Data Continuous mode
-    delay(1);   
-  START(BOTH_ADS);  // start the data acquisition
-    delay(1);
-  isRunning = true;
-}
-  
-// Query to see if data is available from the ADS1299...return TRUE is data is available
-boolean OpenBCI_32_Daisy::isDataAvailable(void)
-{
-  return (!(digitalRead(ADS_DRDY)));
-}
-  
-// CALLED WHEN DRDY PIN IS ASSERTED. NEW ADS DATA AVAILABLE!
-void OpenBCI_32_Daisy::updateChannelData(){ 
-  updateBoardData();
-  if(daisyPresent) {updateDaisyData();}
-}
-
-void OpenBCI_32_Daisy::updateBoardData(){
-  byte inByte;
-  int byteCounter = 0;
-
-  if(daisyPresent && !firstDataPacket){
-    for(int i=0; i<8; i++){  // shift and average the byte arrays
-      lastBoardChannelDataInt[i] = boardChannelDataInt[i]; // remember the last samples
-    }
-  }
-  csLow(BOARD_ADS);       //  open SPI
-  for(int i=0; i<3; i++){ 
-    inByte = xfer(0x00);    //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
-    boardStat = (boardStat << 8) | inByte;
-  }
-  for(int i = 0; i<8; i++){
-    for(int j=0; j<3; j++){   //  read 24 bits of channel data in 8 3 byte chunks
-      inByte = xfer(0x00);
-      boardChannelDataRaw[byteCounter] = inByte;  // raw data goes here
-      byteCounter++;
-      boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte;  // int data goes here
-    }
-  }
-  csHigh(BOARD_ADS);        //  close SPI
-  // need to convert 24bit to 32bit if using the filter
-  for(int i=0; i<8; i++){     // convert 3 byte 2's compliment to 4 byte 2's compliment 
-    if(bitRead(boardChannelDataInt[i],23) == 1){ 
-      boardChannelDataInt[i] |= 0xFF000000;
-    }else{
-      boardChannelDataInt[i] &= 0x00FFFFFF;
-    }
-  }
-  if(daisyPresent && !firstDataPacket){
-    byteCounter = 0;
-    for(int i=0; i<8; i++){   // take the average of this and the last sample
-      meanBoardChannelDataInt[i] = (lastBoardChannelDataInt[i] + boardChannelDataInt[i])/2;
-    }
-    for(int i=0; i<8; i++){  // place the average values in the meanRaw array
-      for(int b=2; b>=0; b--){
-        meanBoardDataRaw[byteCounter] = (meanBoardChannelDataInt[i] >> (b*8)) & 0xFF;
-        byteCounter++;
-      }
-    }    
-  }
-    
-  if(firstDataPacket == true){firstDataPacket = false;}
-}
-
-void OpenBCI_32_Daisy::updateDaisyData(){
-    byte inByte;
-    int byteCounter = 0;
-    
-    if(daisyPresent && !firstDataPacket){
-      for(int i=0; i<8; i++){  // shift and average the byte arrays
-        lastDaisyChannelDataInt[i] = daisyChannelDataInt[i]; // remember the last samples
-      }
-    }
-
-    csLow(DAISY_ADS);       //  open SPI
-    for(int i=0; i<3; i++){ 
-      inByte = xfer(0x00);    //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
-      daisyStat = (daisyStat << 8) | inByte;
-    }
-    for(int i = 0; i<8; i++){
-      for(int j=0; j<3; j++){   //  read 24 bits of channel data in 8 3 byte chunks
-        inByte = xfer(0x00);
-        daisyChannelDataRaw[byteCounter] = inByte;  // raw data goes here
-        byteCounter++;
-        daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte; // int data goes here
-      }
-    }
-    csHigh(DAISY_ADS);        //  close SPI
-  // need to convert 24bit to 32bit
-  for(int i=0; i<8; i++){     // convert 3 byte 2's compliment to 4 byte 2's compliment 
-    if(bitRead(daisyChannelDataInt[i],23) == 1){ 
-      daisyChannelDataInt[i] |= 0xFF000000;
-    }else{
-      daisyChannelDataInt[i] &= 0x00FFFFFF;
-    }
-  }
-  if(daisyPresent && !firstDataPacket){
-    byteCounter = 0;
-    for(int i=0; i<8; i++){   // average this sample with the last sample
-      meanDaisyChannelDataInt[i] = (lastDaisyChannelDataInt[i] + daisyChannelDataInt[i])/2;
-    }
-    for(int i=0; i<8; i++){  // place the average values in the meanRaw array
-      for(int b=2; b>=0; b--){
-        meanDaisyDataRaw[byteCounter] = (meanDaisyChannelDataInt[i] >> (b*8)) & 0xFF;
-        byteCounter++;
-      }
-    }   
-  }  
-    
-  if(firstDataPacket == true){firstDataPacket = false;}
-}
-
-// Stop the continuous data acquisition
-void OpenBCI_32_Daisy::stopADS()  
-{
-  STOP(BOTH_ADS);     // stop the data acquisition
-    delay(1);           
-  SDATAC(BOTH_ADS);   // stop Read Data Continuous mode to communicate with ADS
-    delay(1);   
-  isRunning = false;
-}
-
-
-//write as binary each channel's data
-void OpenBCI_32_Daisy::ADS_writeChannelData() 
-{ 
-  
-  if(daisyPresent){
-    if(sampleCounter % 2 != 0){ //CHECK SAMPLE ODD-EVEN AND SEND THE APPROPRIATE ADS DATA
-      for (int i=0; i<24; i++){ 
-        Serial0.write(meanBoardDataRaw[i]); // send board data on odd samples
-      }
-    }else{
-      for (int i=0; i<24; i++){
-        Serial0.write(meanDaisyDataRaw[i]); // send daisy data on even samples
-      }
-    }
-  }else{
-    for(int i=0; i<24; i++){
-      Serial0.write(boardChannelDataRaw[i]);
-    }
-  }
-}
-
-
-//print out the state of all the control registers
-void OpenBCI_32_Daisy::printADSregisters(int targetSS)   
-{
-    boolean prevverbosityState = verbosity;
-    verbosity = true;                       // set up for verbosity output
-    RREGS(0x00,0x0C,targetSS);      // read out the first registers
-    delay(10);                          // stall to let all that data get read by the PC
-    RREGS(0x0D,0x17-0x0D,targetSS); // read out the rest
-    verbosity = prevverbosityState;
-}
-
-byte OpenBCI_32_Daisy::ADS_getDeviceID(int targetSS) {      // simple hello world com check
-  byte data = RREG(ID_REG,targetSS);
-  if(verbosity){            // verbosity otuput
-    Serial0.print("On Board ADS ID ");
-    printHex(data); Serial0.println();
-  }
-  return data;
-}
-  
-//System Commands
-void OpenBCI_32_Daisy::WAKEUP(int targetSS) {
-    csLow(targetSS); 
-    xfer(_WAKEUP);
-    csHigh(targetSS); 
-    delayMicroseconds(3);     //must wait 4 tCLK cycles before sending another command (Datasheet, pg. 35)
-}
-
-void OpenBCI_32_Daisy::STANDBY(int targetSS) {    // only allowed to send WAKEUP after sending STANDBY
-    csLow(targetSS);
-    xfer(_STANDBY);
-    csHigh(targetSS);
-}
-
-void OpenBCI_32_Daisy::RESET(int targetSS) {      // reset all the registers to default settings
-    csLow(targetSS);
-    xfer(_RESET);
-    delayMicroseconds(12);    //must wait 18 tCLK cycles to execute this command (Datasheet, pg. 35)
-    csHigh(targetSS);
-}
-
-void OpenBCI_32_Daisy::START(int targetSS) {      //start data conversion 
-    csLow(targetSS);
-    xfer(_START);           // KEEP ON-BOARD AND ON-DAISY IN SYNC
-    csHigh(targetSS);
-}
-
-void OpenBCI_32_Daisy::STOP(int targetSS) {     //stop data conversion
-    csLow(targetSS);
-    xfer(_STOP);            // KEEP ON-BOARD AND ON-DAISY IN SYNC
-    csHigh(targetSS);
-}
-
-void OpenBCI_32_Daisy::RDATAC(int targetSS) {
-    csLow(targetSS);
-    xfer(_RDATAC);      // read data continuous
-    csHigh(targetSS);
-    delayMicroseconds(3);   
-}
-void OpenBCI_32_Daisy::SDATAC(int targetSS) {
-    csLow(targetSS);
-    xfer(_SDATAC);
-    csHigh(targetSS);
-    delayMicroseconds(10);   //must wait at least 4 tCLK cycles after executing this command (Datasheet, pg. 37)
-}
-
-
-//  THIS NEEDS CLEANING AND UPDATING TO THE NEW FORMAT
-void OpenBCI_32_Daisy::RDATA(int targetSS) {          //  use in Stop Read Continuous mode when DRDY goes low
-  byte inByte;            //  to read in one sample of the channels
-    csLow(targetSS);        //  open SPI
-    xfer(_RDATA);         //  send the RDATA command
-    for(int i=0; i<3; i++){   //  read in the status register and new channel data
-      inByte = xfer(0x00);
-      boardStat = (boardStat<<8) | inByte; //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
-    }   
-  if(targetSS == BOARD_ADS){    
-    for(int i = 0; i<8; i++){
-      for(int j=0; j<3; j++){   //  read in the new channel data
-        inByte = xfer(0x00);
-        boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte;
-      }
-    }
-    for(int i=0; i<8; i++){
-      if(bitRead(boardChannelDataInt[i],23) == 1){  // convert 3 byte 2's compliment to 4 byte 2's compliment
-        boardChannelDataInt[i] |= 0xFF000000;
-      }else{
-        boardChannelDataInt[i] &= 0x00FFFFFF;
-      }
-    }
-  }else{
-    for(int i = 0; i<8; i++){
-      for(int j=0; j<3; j++){   //  read in the new channel data
-        inByte = xfer(0x00);
-        daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte;
-      }
-    }
-    for(int i=0; i<8; i++){
-      if(bitRead(daisyChannelDataInt[i],23) == 1){  // convert 3 byte 2's compliment to 4 byte 2's compliment
-        daisyChannelDataInt[i] |= 0xFF000000;
-      }else{
-        daisyChannelDataInt[i] &= 0x00FFFFFF;
-      }
-    }
-  }
-   csHigh(targetSS);        //  close SPI
-  
-  
-}
-
-byte OpenBCI_32_Daisy::RREG(byte _address,int targetSS) {    //  reads ONE register at _address
-    byte opcode1 = _address + 0x20;   //  RREG expects 001rrrrr where rrrrr = _address
-    csLow(targetSS);        //  open SPI
-    xfer(opcode1);          //  opcode1
-    xfer(0x00);           //  opcode2
-    regData[_address] = xfer(0x00);//  update mirror location with returned byte
-    csHigh(targetSS);       //  close SPI 
-  if (verbosity){           //  verbosity output
-    printRegisterName(_address);
-    printHex(_address);
-    Serial0.print(", ");
-    printHex(regData[_address]);
-    Serial0.print(", ");
-    for(byte j = 0; j<8; j++){
-      Serial0.print(bitRead(regData[_address], 7-j));
-      if(j!=7) Serial0.print(", ");
-    }
-    
-    Serial0.println();
-  }
-  return regData[_address];     // return requested register value
-}
-
-
-// Read more than one register starting at _address
-void OpenBCI_32_Daisy::RREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
-
-    byte opcode1 = _address + 0x20;   //  RREG expects 001rrrrr where rrrrr = _address
-    csLow(targetSS);        //  open SPI
-    xfer(opcode1);          //  opcode1
-    xfer(_numRegistersMinusOne);  //  opcode2
-    for(int i = 0; i <= _numRegistersMinusOne; i++){
-        regData[_address + i] = xfer(0x00);   //  add register byte to mirror array
-    }
-    csHigh(targetSS);       //  close SPI
-  if(verbosity){            //  verbosity output
-    for(int i = 0; i<= _numRegistersMinusOne; i++){
-      printRegisterName(_address + i);
-      printHex(_address + i);
-      Serial0.print(", ");
-      printHex(regData[_address + i]);
-      Serial0.print(", ");
-      for(int j = 0; j<8; j++){
-        Serial0.print(bitRead(regData[_address + i], 7-j));
-        if(j!=7) Serial0.print(", ");
-      }
-      Serial0.println();
-      delay(30);
-    }
-    }
-}
-
-void OpenBCI_32_Daisy::WREG(byte _address, byte _value, int target_SS) { //  Write ONE register at _address
-    byte opcode1 = _address + 0x40;   //  WREG expects 010rrrrr where rrrrr = _address
-    csLow(target_SS);        //  open SPI
-    xfer(opcode1);          //  Send WREG command & address
-    xfer(0x00);           //  Send number of registers to read -1
-    xfer(_value);         //  Write the value to the register
-    csHigh(target_SS);       //  close SPI
-    regData[_address] = _value;     //  update the mirror array
-    if(verbosity){            //  verbosity output
-    Serial0.print("Register ");
-    printHex(_address);
-    Serial0.println(" modified.");
-  }
-}
-
-void OpenBCI_32_Daisy::WREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
-    byte opcode1 = _address + 0x40;   //  WREG expects 010rrrrr where rrrrr = _address
-    csLow(targetSS);        //  open SPI
-    xfer(opcode1);          //  Send WREG command & address
-    xfer(_numRegistersMinusOne);  //  Send number of registers to read -1 
-  for (int i=_address; i <=(_address + _numRegistersMinusOne); i++){
-    xfer(regData[i]);     //  Write to the registers
-  } 
-    csHigh(targetSS);
-  if(verbosity){
-    Serial0.print("Registers ");
-    printHex(_address); Serial0.print(" to ");
-    printHex(_address + _numRegistersMinusOne);
-    Serial0.println(" modified");
-  }
-}
-
-
-// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF ADS1299 FUNCTIONS  >>>>>>>>>>>>>>>>>>>>>>>>>
-// ******************************************************************************
-// <<<<<<<<<<<<<<<<<<<<<<<<<  LIS3DH FUNCTIONS  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-
-
-void OpenBCI_32_Daisy::initialize_accel(byte g){ 
-  byte setting =  g | 0x08;           // mask the g range for REG4   
-  pinMode(LIS3DH_DRDY,INPUT);   // setup dataReady interupt from accelerometer
-  LIS3DH_write(TMP_CFG_REG, 0x00);  // DISable ADC inputs, enable temperature sensor
-  LIS3DH_write(CTRL_REG1, 0x08);    // disable accel, low power mode
-  LIS3DH_write(CTRL_REG2, 0x00);    // don't use the high pass filter
-  LIS3DH_write(CTRL_REG3, 0x00);    // no interrupts yet
-  LIS3DH_write(CTRL_REG4, setting); // set scale to g, high resolution
-  LIS3DH_write(CTRL_REG5, 0x00);    // no boot, no fifo
-  LIS3DH_write(CTRL_REG6, 0x00);
-  LIS3DH_write(REFERENCE, 0x00);
-  DRDYpinValue = lastDRDYpinValue = digitalRead(LIS3DH_DRDY);  // take a reading to seed these variables
-}
-  
-void OpenBCI_32_Daisy::enable_accel(byte Hz){   
-  for(int i=0; i<3; i++){
-    axisData[i] = 0;            // clear the axisData array so we don't get any stale news
-  }
-  byte setting = Hz | 0x07;           // mask the desired frequency
-  LIS3DH_write(CTRL_REG1, setting);   // set freq and enable all axis in normal mode
-  LIS3DH_write(CTRL_REG3, 0x10);      // enable DRDY1 on INT1 (tied to PIC pin 0, LIS3DH_DRDY)
-}
-
-void OpenBCI_32_Daisy::disable_accel(){
-  LIS3DH_write(CTRL_REG1, 0x08);      // power down, low power mode
-  LIS3DH_write(CTRL_REG3, 0x00);      // disable DRDY1 on INT1
-}
-
-byte OpenBCI_32_Daisy::LIS3DH_getDeviceID(){
-  return LIS3DH_read(WHO_AM_I);
-}
-
-boolean OpenBCI_32_Daisy::LIS3DH_DataAvailable(){
-  boolean x = false;
-  if((LIS3DH_read(STATUS_REG2) & 0x08) > 0) x = true;  // read STATUS_REG
-  return x;
-}
-
-boolean OpenBCI_32_Daisy::LIS3DH_DataReady(){
-  boolean r = false;
-  DRDYpinValue = digitalRead(LIS3DH_DRDY);  // take a look at LIS3DH_DRDY pin
-  if(DRDYpinValue != lastDRDYpinValue){     // if the value has changed since last looking
-    if(DRDYpinValue == HIGH){               // see if this is the rising edge
-      r = true;                             // if so, there is fresh data!
-    }
-    lastDRDYpinValue = DRDYpinValue;        // keep track of the changing pin
-  }
-  return r;
-}
-
-void OpenBCI_32_Daisy::LIS3DH_writeAxisData(void){
-  for(int i=0; i<3; i++){
-    Serial0.write(highByte(axisData[i])); // write 16 bit axis data MSB first
-    Serial0.write(lowByte(axisData[i]));  // axisData is array of type short (16bit)
-    axisData[i] = 0;
-  }
-}
-
-byte OpenBCI_32_Daisy::LIS3DH_read(byte reg){
-  reg |= READ_REG;                    // add the READ_REG bit
-  csLow(LIS3DH_SS);                   // take spi
-  spi.transfer(reg);                  // send reg to read
-  byte inByte = spi.transfer(0x00);   // retrieve data
-  csHigh(LIS3DH_SS);                  // release spi
-  return inByte;  
-}
-
-void OpenBCI_32_Daisy::LIS3DH_write(byte reg, byte value){
-  csLow(LIS3DH_SS);         // take spi
-  spi.transfer(reg);        // send reg to write
-  spi.transfer(value);      // write value
-  csHigh(LIS3DH_SS);        // release spi
-}
-
-int OpenBCI_32_Daisy::LIS3DH_read16(byte reg){    // use for reading axis data. 
-  int inData;  
-  reg |= READ_REG | READ_MULTI;   // add the READ_REG and READ_MULTI bits
-  csLow(LIS3DH_SS);               // take spi
-  spi.transfer(reg);              // send reg to start reading from
-  inData = spi.transfer(0x00) | (spi.transfer(0x00) << 8);  // get the data and arrange it
-  csHigh(LIS3DH_SS);              // release spi
-  return inData;
-}
-
-int OpenBCI_32_Daisy::getX(){
-  return LIS3DH_read16(OUT_X_L);
-}
-
-int OpenBCI_32_Daisy::getY(){
-  return LIS3DH_read16(OUT_Y_L);
-}
-
-int OpenBCI_32_Daisy::getZ(){
-  return LIS3DH_read16(OUT_Z_L);
-}
-
-void OpenBCI_32_Daisy::LIS3DH_updateAxisData(){
-  axisData[0] = getX();
-  axisData[1] = getY();
-  axisData[2] = getZ();
-}
-
-void OpenBCI_32_Daisy::LIS3DH_readAllRegs(){
-  
-  byte inByte;
-
-  for (int i = STATUS_REG_AUX; i <= WHO_AM_I; i++){
-    inByte = LIS3DH_read(i);
-    Serial0.print("0x0");Serial0.print(i,HEX);
-    Serial0.print("\t");Serial0.println(inByte,HEX);
-    delay(20);
-  }
-  Serial0.println();
-
-  for (int i = TMP_CFG_REG; i <= INT1_DURATION; i++){
-    inByte = LIS3DH_read(i);
-    // printRegisterName(i);
-    Serial0.print("0x");Serial0.print(i,HEX);
-    Serial0.print("\t");Serial0.println(inByte,HEX);
-    delay(20);
-  }
-  Serial0.println();
-
-  for (int i = CLICK_CFG; i <= TIME_WINDOW; i++){
-    inByte = LIS3DH_read(i);
-    Serial0.print("0x");Serial0.print(i,HEX);
-    Serial0.print("\t");Serial0.println(inByte,HEX);
-    delay(20);
-  }
-  
-}
-
-
-
-// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF LIS3DH FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-
-
-
-// String-Byte converters for ADS 
-void OpenBCI_32_Daisy::printRegisterName(byte _address) {
-    switch(_address){ 
-      case ID_REG: 
-        Serial0.print("ADS_ID, "); break;
-      case CONFIG1:
-        Serial0.print("CONFIG1, "); break;
-      case CONFIG2:
-        Serial0.print("CONFIG2, "); break;
-      case CONFIG3:
-        Serial0.print("CONFIG3, "); break;
-      case LOFF:
-        Serial0.print("LOFF, "); break;
-      case CH1SET:
-        Serial0.print("CH1SET, "); break;
-      case CH2SET:
-        Serial0.print("CH2SET, "); break;
-      case CH3SET:
-        Serial0.print("CH3SET, "); break;
-      case CH4SET:
-        Serial0.print("CH4SET, "); break;
-      case CH5SET:
-        Serial0.print("CH5SET, "); break;
-      case CH6SET:
-        Serial0.print("CH6SET, "); break;
-      case CH7SET:
-        Serial0.print("CH7SET, "); break;
-      case CH8SET:
-        Serial0.print("CH8SET, "); break;
-      case BIAS_SENSP:
-        Serial0.print("BIAS_SENSP, "); break;
-      case BIAS_SENSN:
-        Serial0.print("BIAS_SENSN, "); break;
-      case LOFF_SENSP:
-        Serial0.print("LOFF_SENSP, "); break;
-      case LOFF_SENSN:
-        Serial0.print("LOFF_SENSN, "); break;
-      case LOFF_FLIP:
-        Serial0.print("LOFF_FLIP, "); break;
-      case LOFF_STATP:
-        Serial0.print("LOFF_STATP, "); break;
-      case LOFF_STATN:
-        Serial0.print("LOFF_STATN, "); break;
-      case GPIO:
-        Serial0.print("GPIO, "); break;
-      case MISC1:
-        Serial0.print("MISC1, "); break;
-      case MISC2:
-        Serial0.print("MISC2, "); break;
-      case CONFIG4:
-        Serial0.print("CONFIG4, "); break;
-      default: 
-        break;
-    }
-}
-
-// Used for printing HEX in verbosity feedback mode
-void OpenBCI_32_Daisy::printHex(byte _data){
-  Serial0.print("0x");
-    if(_data < 0x10) Serial0.print("0");
-    Serial0.print(_data, HEX);
-}
--- a/OpenBCI_32_Daisy.h	Sun Dec 04 03:38:44 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
-   insert header here
-
-*/
-#ifndef _____OpenBCI_32_Daisy__
-#define _____OpenBCI_32_Daisy__
-
-
-//#include <DSPI.h> // MBED: not needed
-//#include <WProgram.h> // MBED: not needed
-#include "PlatformDefs.h" // MBED: hardware emulation
-#include "Definitions_32_Daisy.h"
-
-
-
-  
-class OpenBCI_32_Daisy {
-public:
-    DSPI0 spi;  // use DSPI library
-
-// BOARD 
-    boolean useAccel;
-    boolean useAux;
-    void initialize(void);  // ADD DAISY USE outputType
-    void printAllRegisters(void);   // ADD DAISY USE outputType
-    void sendChannelData(void); // send the current data with sample number
-    void startStreaming(void);  // ADD DAISY USE outputType
-    void stopStreaming(void);   // ADD DAISY USE outputType
-
-// ADS1299  
-    void initialize_ads(void);
-    void updateChannelSettings(void);
-    void writeChannelSettings(void);
-    void writeChannelSettings(byte);
-    void setChannelsToDefault(void);
-    void setChannelsToEMG(void);
-    void setChannelsToECG(void);
-    void reportDefaultChannelSettings(void);
-    void printADSregisters(int);
-    void WAKEUP(int);  // get out of low power mode
-    void STANDBY(int); // go into low power mode
-    void RESET(int);   // set all register values to default
-    void START(int);   // start data acquisition
-    void STOP(int);    // stop data acquisition
-    void RDATAC(int);  // go into read data continuous mode 
-    void SDATAC(int);  // get out of read data continuous mode
-    void RDATA(int);   // read data one-shot   
-    byte RREG(byte,int);            // read one ADS register
-    void RREGS(byte,byte,int);      // read multiple ADS registers
-    void WREG(byte,byte,int);       // write one ADS register
-    void WREGS(byte,byte,int);      // write multiple ADS registers
-    byte ADS_getDeviceID(int);         
-    void printRegisterName(byte);   // used for verbosity
-    void printHex(byte);            // used for verbosity
-    void updateChannelData(void);   // retrieve data from ADS
-    void updateBoardData(void);
-    void updateDaisyData(void);
-    byte xfer(byte);        // SPI Transfer function 
-    void resetADS(int);     // reset all the ADS1299's settings
-    void startADS(void);
-    void stopADS(void);
-    void activateChannel(byte);                  // enable the selected channel
-    void deactivateChannel(byte);                // disable given channel 1-8(16)
-    void configureLeadOffDetection(byte,byte);
-    void changeChannelLeadOffDetect(void);
-    void changeChannelLeadOffDetect(byte);
-    void configureInternalTestSignal(byte,byte); 
-    void changeInputType(byte); 
-    boolean isDataAvailable(void);
-    void ADS_writeChannelData(void);
-    // void ADS_printDeviceID(int);   // 
-    boolean smellDaisy(void);
-    void removeDaisy(void);
-    void attachDaisy(void);
-    void writeAuxData(void);
-
-    short auxData[3];
-    byte regData[24];          // array is used to mirror register data
-    byte lastBoardDataRaw[24];
-    byte boardChannelDataRaw[24];    // array to hold raw channel data
-    byte meanBoardDataRaw[24];
-    byte lastDaisyDataRaw[24];
-    byte daisyChannelDataRaw[24];
-    byte meanDaisyDataRaw[24];
-    int boardStat;           // used to hold the status register
-    int daisyStat;
-    int boardChannelDataInt[8];    // array used when reading channel data as ints
-    int lastBoardChannelDataInt[8];
-    int meanBoardChannelDataInt[8];
-    int daisyChannelDataInt[8];    // array used when reading channel data as ints
-    int lastDaisyChannelDataInt[8];
-    int meanDaisyChannelDataInt[8];
-    int numChannels;
-    byte channelSettings[16][6];  // array to hold current channel settings
-    byte defaultChannelSettings[6];  // default channel settings
-    byte leadOffSettings[16][2];  // used to control on/off of impedance measure for P and N side of each channel
-    boolean useInBias[16];        // used to remember if we were included in Bias before channel power down
-    boolean useSRB2[16];
-    boolean boardUseSRB1;             // used to keep track of if we are using SRB1
-    boolean daisyUseSRB1;
-    boolean verbosity;      // turn on/off Serial verbosity
-    boolean daisyPresent;
-    boolean firstDataPacket;
-    byte sampleCounter;
-
-// LIS3DH
-    short axisData[3];
-    void initialize_accel(byte);    // initialize 
-    void enable_accel(byte);  // start acceleromoeter with default settings
-    void disable_accel(void); // stop data acquisition and go into low power mode
-    byte LIS3DH_getDeviceID(void);    
-    byte LIS3DH_read(byte);     // read a register on LIS3DH
-    void LIS3DH_write(byte,byte);   // write a register on LIS3DH
-    int LIS3DH_read16(byte);    // read two bytes, used to get axis data
-    int getX(void);     
-    int getY(void);
-    int getZ(void);
-    boolean LIS3DH_DataReady(void); // check LIS3DH_DRDY pin
-    boolean LIS3DH_DataAvailable(void); // check LIS3DH STATUS_REG2
-    void LIS3DH_readAllRegs(void);
-    void LIS3DH_writeAxisData(void);
-    void LIS3DH_updateAxisData(void);
-
-    void csLow(int);
-    void csHigh(int);
-
-
-private:
-// ADS1299
-    boolean isRunning;  
-// LIS3DH
-    int DRDYpinValue;
-    int lastDRDYpinValue;
-
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OpenBCI_32bit_Library.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -0,0 +1,2859 @@
+/*
+OpenBCI 32bit Library
+Place the containing folder into your libraries folder insdie the arduino folder in your Documents folder
+
+This library will work with a single OpenBCI 32bit board, or
+an OpenBCI 32bit board with an OpenBCI Daisy Module attached.
+
+*/
+
+#include "OpenBCI_32bit_Library.h"
+
+/***************************************************/
+/** PUBLIC METHODS *********************************/
+/***************************************************/
+// CONSTRUCTOR
+OpenBCI_32bit_Library::OpenBCI_32bit_Library() {
+    curBoardMode = OPENBCI_BOARD_MODE_DEFAULT;
+    daisyPresent = false;
+    sniffMode = false;
+    useAccel = false;
+    useAux = false;
+    channelDataAvailable = false;
+    initializeVariables();
+}
+
+/**
+* @description: The function the OpenBCI board will call in setup.
+* @author: AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::begin(void) {
+    curBoardMode = OPENBCI_BOARD_MODE_DEFAULT;
+    // Bring the board up
+    boardBegin();
+}
+
+/**
+* @description: The function the OpenBCI board will call in setup. Turns sniff mode
+*  on and allows you to tap into the serial port that is broken out on the OpenBCI
+*  32bit board. You must alter this file:
+*   On Mac:
+*     `/Users/username/Documents/Arduino/hardware/chipkit-core/pic32/variants/openbci/Board_Defs.h`
+*   On Windows:
+*     `C:\Users\username\Documents\Arduino\hardware\chipkit-core\pic32\variants\openbci\Board_Defs.h`
+* Specifically lines `311` and `313` from `7` and `10` to `11` and `12` for
+*   `_SER1_TX_PIN` and `_SER1_RX_PIN` respectively. Check out this sweet gif if
+*   you are a visual person http://g.recordit.co/3jH01sMD6Y.gif
+*  You will need to reflash your board! But now you can connect to pins `11`
+*    `12` via a FTDI serial port driver, really any serial to USB driver would
+*    work. Remember to use 3V3, 115200 baud, and have a common ground!
+* @author: AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::beginDebug(void) {
+    // Bring the board up
+    boolean started = boardBeginDebug();
+    curBoardMode = OPENBCI_BOARD_MODE_DEBUG;
+
+    sniffMode = true;
+
+    if (Serial1) {
+        if (started) {
+            Serial1.println("Board up");
+        } else {
+            Serial1.println("Board err");
+        }
+
+    }
+}
+
+/**
+* @description: The function the OpenBCI board will call in setup. This sets up the hardware serial port on D11 and D12
+* @author: AJ Keller (@pushtheworldllc)
+*/
+boolean OpenBCI_32bit_Library::beginSecondarySerial(void) {
+    // Initalize the serial 1 port
+    Serial1.begin(OPENBCI_BAUD_RATE);
+    return true;
+}
+
+
+/**
+* @description Called in every `loop()` and checks `Serial0`
+* @returns {boolean} - `true` if there is data ready to be read
+*/
+boolean OpenBCI_32bit_Library::hasDataSerial0(void) {
+    if (Serial0.available()) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/**
+* @description Called in every `loop()` and checks `Serial0`
+* @returns {boolean} - `true` if there is data ready to be read
+*/
+boolean OpenBCI_32bit_Library::hasDataSerial1(void) {
+    if (Serial1.available()) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/**
+* @description Called if `hasDataSerial0` is true, returns a char from `Serial0`
+* @returns {char} - A char from the serial port
+*/
+char OpenBCI_32bit_Library::getCharSerial0(void) {
+    return Serial0.read();
+}
+
+/**
+* @description Called if `hasDataSerial1` is true, returns a char from `Serial1`
+* @returns {char} - A char from the serial port
+*/
+char OpenBCI_32bit_Library::getCharSerial1(void) {
+    return Serial1.read();
+}
+
+/**
+* @description If `isSerialAvailableForRead()` is `true` then this function is
+*  called. Reads from `Serial0` first and foremost, which comes from the RFduino.
+*  If `sniffMode` is true and `Serial0` didn't have any data, we will try to
+*  read from `Serial1`. If both are not available then we will return a `0x00`
+*  which is NOT a command that the system will recognize, aka this function has
+*  many safe guards.
+* @returns {char} - The character from the serial port.
+*/
+// char OpenBCI_32bit_Library::readOneSerialChar(void) {
+//     if (Serial0.available()) {
+//         return Serial0.read();
+//     } else if (sniffMode && Serial1.available()) {
+//         return Serial1.read();
+//     } else {
+//         return 0x00;
+//     }
+// }
+
+/**
+* @description Public function for sending data to the PC
+* @param data {char *} - The data you want to send
+* @author AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::writeSerial(char *data, int len) {
+    for (int i = 0; i < len; i++) {
+        Serial0.write(data[i]);
+    }
+}
+
+/**
+ * @description While processing incoming multi byte messages these will turn
+ *  true.
+ * @return {boolean} - True if processing a message and false otherwise
+ */
+boolean OpenBCI_32bit_Library::isProcessingMultibyteMsg(void) {
+    return isProcessingIncomingSettingsChannel || isProcessingIncomingSettingsLeadOff || settingBoardMode;
+}
+
+/**
+ * @description Process one char at a time from serial port. This is the main
+ *  command processor for the OpenBCI system. Considered mission critical for
+ *  normal operation.
+ * @param `character` {char} - The character to process.
+ * @return {boolean} - `true` if the command was recognized, `false` if not
+ */
+boolean OpenBCI_32bit_Library::processChar(char character) {
+    if (sniffMode && Serial1) {
+        Serial1.print("pC: "); Serial1.println(character);
+    }
+
+    if (isProcessingMultibyteMsg()) {
+        if (isProcessingIncomingSettingsChannel) {
+            processIncomingChannelSettings(character);
+        } else if (isProcessingIncomingSettingsLeadOff) {
+            processIncomingLeadOffSettings(character);
+        } else if (settingBoardMode) {
+            processIncomingBoardMode(character);
+        }
+    } else { // Normal...
+        switch (character){
+            //TURN CHANNELS ON/OFF COMMANDS
+            case OPENBCI_CHANNEL_OFF_1:
+                streamSafeChannelDeactivate(1);
+                break;
+            case OPENBCI_CHANNEL_OFF_2:
+                streamSafeChannelDeactivate(2);
+                break;
+            case OPENBCI_CHANNEL_OFF_3:
+                streamSafeChannelDeactivate(3);
+                break;
+            case OPENBCI_CHANNEL_OFF_4:
+                streamSafeChannelDeactivate(4);
+                break;
+            case OPENBCI_CHANNEL_OFF_5:
+                streamSafeChannelDeactivate(5);
+                break;
+            case OPENBCI_CHANNEL_OFF_6:
+                streamSafeChannelDeactivate(6);
+                break;
+            case OPENBCI_CHANNEL_OFF_7:
+                streamSafeChannelDeactivate(7);
+                break;
+            case OPENBCI_CHANNEL_OFF_8:
+                streamSafeChannelDeactivate(8);
+                break;
+            case OPENBCI_CHANNEL_OFF_9:
+                streamSafeChannelDeactivate(9);
+                break;
+            case OPENBCI_CHANNEL_OFF_10:
+                streamSafeChannelDeactivate(10);
+                break;
+            case OPENBCI_CHANNEL_OFF_11:
+                streamSafeChannelDeactivate(11);
+                break;
+            case OPENBCI_CHANNEL_OFF_12:
+                streamSafeChannelDeactivate(12);
+                break;
+            case OPENBCI_CHANNEL_OFF_13:
+                streamSafeChannelDeactivate(13);
+                break;
+            case OPENBCI_CHANNEL_OFF_14:
+                streamSafeChannelDeactivate(14);
+                break;
+            case OPENBCI_CHANNEL_OFF_15:
+                streamSafeChannelDeactivate(15);
+                break;
+            case OPENBCI_CHANNEL_OFF_16:
+                streamSafeChannelDeactivate(16);
+                break;
+
+            case OPENBCI_CHANNEL_ON_1:
+                streamSafeChannelActivate(1);
+                break;
+            case OPENBCI_CHANNEL_ON_2:
+                streamSafeChannelActivate(2);
+                break;
+            case OPENBCI_CHANNEL_ON_3:
+                streamSafeChannelActivate(3);
+                break;
+            case OPENBCI_CHANNEL_ON_4:
+                streamSafeChannelActivate(4);
+                break;
+            case OPENBCI_CHANNEL_ON_5:
+                streamSafeChannelActivate(5);
+                break;
+            case OPENBCI_CHANNEL_ON_6:
+                streamSafeChannelActivate(6);
+                break;
+            case OPENBCI_CHANNEL_ON_7:
+                streamSafeChannelActivate(7);
+                break;
+            case OPENBCI_CHANNEL_ON_8:
+                streamSafeChannelActivate(8);
+                break;
+            case OPENBCI_CHANNEL_ON_9:
+                streamSafeChannelActivate(9);
+                break;
+            case OPENBCI_CHANNEL_ON_10:
+                streamSafeChannelActivate(10);
+                break;
+            case OPENBCI_CHANNEL_ON_11:
+                streamSafeChannelActivate(11);
+                break;
+            case OPENBCI_CHANNEL_ON_12:
+                streamSafeChannelActivate(12);
+                break;
+            case OPENBCI_CHANNEL_ON_13:
+                streamSafeChannelActivate(13);
+                break;
+            case OPENBCI_CHANNEL_ON_14:
+                streamSafeChannelActivate(14);
+                break;
+            case OPENBCI_CHANNEL_ON_15:
+                streamSafeChannelActivate(15);
+                break;
+            case OPENBCI_CHANNEL_ON_16:
+                streamSafeChannelActivate(16);
+                break;
+
+            // TEST SIGNAL CONTROL COMMANDS
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_GROUND:
+                activateAllChannelsToTestCondition(ADSINPUT_SHORTED,ADSTESTSIG_NOCHANGE,ADSTESTSIG_NOCHANGE);
+                break;
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_SLOW:
+                activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_SLOW);
+                break;
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_FAST:
+                activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_FAST);
+                break;
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_DC:
+                activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_DCSIG);
+                break;
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_SLOW:
+                activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_SLOW);
+                break;
+            case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_FAST:
+                activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_FAST);
+                break;
+
+
+            // CHANNEL SETTING COMMANDS
+            case OPENBCI_CHANNEL_CMD_SET:  // This is the first byte that tells us to expect more commands
+                isProcessingIncomingSettingsChannel = true;
+                numberOfIncomingSettingsProcessedChannel = 1;
+                break;
+
+            // LEAD OFF IMPEDANCE DETECTION COMMANDS
+            case OPENBCI_CHANNEL_IMPEDANCE_SET:
+                isProcessingIncomingSettingsLeadOff = true;
+                numberOfIncomingSettingsProcessedLeadOff = 1;
+                break;
+
+            case OPENBCI_CHANNEL_DEFAULT_ALL_SET:  // reset all channel settings to default
+                if(!streaming) {
+                    Serial0.println("updating channel settings to default");
+                    sendEOT();
+                }
+                streamSafeSetAllChannelsToDefault();
+                break;
+            case OPENBCI_CHANNEL_DEFAULT_ALL_REPORT:  // report the default settings
+                reportDefaultChannelSettings();
+                break;
+
+
+
+            // DAISY MODULE COMMANDS
+            case OPENBCI_CHANNEL_MAX_NUMBER_8:  // use 8 channel mode
+                if(daisyPresent){
+                    removeDaisy();
+                }
+                break;
+            case OPENBCI_CHANNEL_MAX_NUMBER_16:  // use 16 channel mode
+                if(daisyPresent == false){
+                    attachDaisy();
+                }
+                if(daisyPresent){
+                    Serial0.print("16");
+                }else{
+                    Serial0.print("8");
+                }
+                sendEOT();
+                break;
+
+            // STREAM DATA AND FILTER COMMANDS
+            case OPENBCI_STREAM_START:  // stream data
+                if(useAccel){
+                    enable_accel(RATE_25HZ);
+                }      // fire up the accelerometer if you want it
+                streamStart(); // turn on the fire hose
+                break;
+            case OPENBCI_STREAM_STOP:  // stop streaming data
+                if(useAccel){
+                    disable_accel();
+                }  // shut down the accelerometer if you're using it
+                streamStop();
+                break;
+
+            //  INITIALIZE AND VERIFY
+            case OPENBCI_MISC_SOFT_RESET:
+                boardReset();  // initialize ADS and read device IDs
+                break;
+            //  QUERY THE ADS AND ACCEL REGITSTERS
+            case OPENBCI_MISC_QUERY_REGISTER_SETTINGS:
+                if (!streaming) {
+                    printAllRegisters(); // print the ADS and accelerometer register values
+                }
+                break;
+
+            // TIME SYNC
+            case OPENBCI_TIME_SET:
+                // Set flag to send time packet
+                if (streaming) {
+                    sendTimeSyncUpPacket = true;
+                } else {
+                    Serial0.print("Time stamp ON");
+                    sendEOT();
+                }
+                timeSynced = true;
+                break;
+
+            case OPENBCI_TIME_STOP:
+                // Stop the Sync
+                timeSynced = false;
+                if (!streaming) {
+                    Serial0.print("Time stamp OFF");
+                    sendEOT();
+                }
+                break;
+
+            // PACKET SET TYPE
+            case OPENBCI_BOARD_MODE_SET:
+                // Tell this function which case that is
+                settingBoardMode = true;
+                break;
+
+            default:
+                return false;
+        }
+    }
+    return true;
+}
+
+/**
+ * @description Reads a status register to see if there is new accelerometer
+ *  data.
+ * @returns {boolean} `true` if the accelerometer has new data.
+ */
+boolean OpenBCI_32bit_Library::accelHasNewData(void) {
+    return LIS3DH_DataAvailable();
+}
+
+/**
+ * @description Reads from the accelerometer to get new X, Y, and Z data. Updates
+ *  the global array `axisData`.
+ */
+void OpenBCI_32bit_Library::accelUpdateAxisData(void) {
+    LIS3DH_updateAxisData();
+}
+
+/**
+ * @description Reads from the accelerometer to get new X, Y, and Z data.
+ */
+void OpenBCI_32bit_Library::accelWriteAxisData(void) {
+    LIS3DH_writeAxisData();
+}
+
+/**
+* @description: This is a function that is called once and confiures all pins on
+*                 the PIC32 uC
+* @author: AJ Keller (@pushtheworldllc)
+*/
+boolean OpenBCI_32bit_Library::boardBegin(void) {
+    // Initalize the serial port baud rate
+    Serial0.begin(OPENBCI_BAUD_RATE);
+
+    pinMode(OPENBCI_PIN_LED, OUTPUT);
+    pinMode(OPENBCI_PIN_PGC, OUTPUT);
+
+    // Startup for interrupt
+    setIntVector(_EXTERNAL_4_VECTOR, ADS_DRDY_Service); // connect interrupt to ISR
+    setIntPriority(_EXTERNAL_4_VECTOR, 4, 0); // set interrupt priority and sub priority
+    clearIntFlag(_EXTERNAL_4_IRQ); // these two need to be done together
+    setIntEnable(_EXTERNAL_4_IRQ); // clear any flags before enabing the irq
+
+    // Do a soft reset
+    boardReset();
+
+    return true;
+}
+
+/**
+* @description: This is a function that is called once and confiures all pins on
+*                 the PIC32 uC
+* @author: AJ Keller (@pushtheworldllc)
+*/
+boolean OpenBCI_32bit_Library::boardBeginDebug(void) {
+    // Initalize the serial port baud rate
+    Serial0.begin(OPENBCI_BAUD_RATE);
+
+    // Initalize the serial debug port
+    Serial1.begin(OPENBCI_BAUD_RATE);
+
+    // Startup for interrupt
+    setIntVector(_EXTERNAL_4_VECTOR, ADS_DRDY_Service); // connect interrupt to ISR
+    setIntPriority(_EXTERNAL_4_VECTOR, 4, 0); // set interrupt priority and sub priority
+    clearIntFlag(_EXTERNAL_4_IRQ); // these two need to be done together
+    setIntEnable(_EXTERNAL_4_IRQ); // clear any flags before enabing the irq
+
+    // Do a soft reset
+    boardReset();
+
+    return true;
+}
+
+/**
+* @description: This is a function that is called once and confiures the Pic to run in secondary serial mode
+* @param baudRate {int} - The baudRate you want the secondary serial port to run at.
+* @author: AJ Keller (@pushtheworldllc)
+*/
+boolean OpenBCI_32bit_Library::boardBeginDebug(int baudRate) {
+    // Initalize the serial port baud rate
+    Serial0.begin(OPENBCI_BAUD_RATE);
+
+    // Initalize the serial debug port
+    Serial1.begin(baudRate);
+
+    // Do a soft reset
+    boardReset();
+
+    return true;
+}
+
+/**
+* @description: This is a function that can be called multiple times, this is
+*                 what we refer to as a `soft reset`. You will hear/see this
+*                 many times.
+* @author: AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::boardReset(void) {
+    initialize(); // initalizes accelerometer and on-board ADS and on-daisy ADS if present
+    delay(500);
+
+    Serial0.println("OpenBCI V3 8-16 channel");
+    configureLeadOffDetection(LOFF_MAG_6NA, LOFF_FREQ_31p2HZ);
+    Serial0.print("On Board ADS1299 Device ID: 0x"); Serial0.println(ADS_getDeviceID(ON_BOARD),HEX);
+    if(daisyPresent){  // library will set this in initialize() if daisy present and functional
+      Serial0.print("On Daisy ADS1299 Device ID: 0x"); Serial0.println(ADS_getDeviceID(ON_DAISY),HEX);
+    }
+    Serial0.print("LIS3DH Device ID: 0x"); Serial0.println(LIS3DH_getDeviceID(),HEX);
+    Serial0.println("Firmware: v2.0.0");
+    sendEOT();
+}
+
+/**
+* @description: Simple method to send the EOT over serial...
+* @author: AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::sendEOT(void) {
+    Serial0.print("$$$");
+}
+
+
+
+void OpenBCI_32bit_Library::activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode)
+{
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    //set the test signal to the desired state
+    configureInternalTestSignal(amplitudeCode,freqCode);
+    //change input type settings for all channels
+    changeInputType(testInputCode);
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+ * @description When a 'z' is found on the serial port, we jump to this function
+ *                  where we continue to read from the serial port and read the
+ *                  remaining 4 bytes.
+ * @param `character` - {char} - The character you want to process...
+ */
+void OpenBCI_32bit_Library::processIncomingBoardMode(char c) {
+
+    if (isValidBoardType(c)) {
+        curBoardMode = c;
+        if (!streaming) {
+            Serial0.print("Success: Board type set");
+            sendEOT();
+        }
+    } else {
+        if (!streaming) {
+            Serial0.print("Failure: invalid board mode");
+            sendEOT();
+        }
+    }
+    settingBoardMode = false;
+}
+
+/**
+ * @description When a 'x' is found on the serial port, we jump to this function
+ *                  where we continue to read from the serial port and read the
+ *                  remaining 7 bytes.
+ */
+void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) {
+
+    if (character == OPENBCI_CHANNEL_CMD_LATCH && numberOfIncomingSettingsProcessedChannel < OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL - 1) {
+        // We failed somehow and should just abort
+        numberOfIncomingSettingsProcessedChannel = 0;
+
+        // put flag back down
+        isProcessingIncomingSettingsChannel = false;
+
+        if (!streaming) {
+            Serial0.print("Channel setting failure: too few chars"); sendEOT();
+        }
+
+        return;
+    }
+    switch (numberOfIncomingSettingsProcessedChannel) {
+        case 1: // channel number
+            currentChannelSetting = getChannelCommandForAsciiChar(character);
+            break;
+        case 2:  // POWER_DOWN
+            channelSettings[currentChannelSetting][POWER_DOWN] = getNumberForAsciiChar(character);
+            break;
+        case 3: // GAIN_SET
+            channelSettings[currentChannelSetting][GAIN_SET] = getGainForAsciiChar(character);
+            break;
+        case 4: // INPUT_TYPE_SET
+            channelSettings[currentChannelSetting][INPUT_TYPE_SET] = getNumberForAsciiChar(character);
+            break;
+        case 5: // BIAS_SET
+            channelSettings[currentChannelSetting][BIAS_SET] = getNumberForAsciiChar(character);
+            break;
+        case 6: // SRB2_SET
+            channelSettings[currentChannelSetting][SRB2_SET] = getNumberForAsciiChar(character);
+            break;
+        case 7: // SRB1_SET
+            channelSettings[currentChannelSetting][SRB1_SET] = getNumberForAsciiChar(character);
+            break;
+        case 8: // 'X' latch
+            if (character != OPENBCI_CHANNEL_CMD_LATCH) {
+                if (!streaming) {
+                    Serial0.print("Err: 9th char not ");
+                    Serial0.println(OPENBCI_CHANNEL_CMD_LATCH);
+                    sendEOT();
+                }
+                // We failed somehow and should just abort
+                numberOfIncomingSettingsProcessedChannel = 0;
+
+                // put flag back down
+                isProcessingIncomingSettingsChannel = false;
+
+            }
+            break;
+        default: // should have exited
+            if (!streaming) {
+                Serial0.print("Err: too many chars");
+                sendEOT();
+            }
+            // We failed somehow and should just abort
+            numberOfIncomingSettingsProcessedChannel = 0;
+
+            // put flag back down
+            isProcessingIncomingSettingsChannel = false;
+            return;
+    }
+
+    // increment the number of bytes processed
+    numberOfIncomingSettingsProcessedChannel++;
+
+    if (numberOfIncomingSettingsProcessedChannel == (OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL)) {
+        // We are done processing channel settings...
+
+        if (!streaming) {
+            Serial0.print("Channel set for "); Serial0.println(currentChannelSetting + 1); sendEOT();
+        }
+
+        if (sniffMode && Serial1) {
+            Serial1.print("Channel set for  "); Serial1.println(currentChannelSetting + 1);
+        }
+
+        // Set channel settings
+        streamSafeChannelSettingsForChannel(currentChannelSetting + 1, channelSettings[currentChannelSetting][POWER_DOWN], channelSettings[currentChannelSetting][GAIN_SET], channelSettings[currentChannelSetting][INPUT_TYPE_SET], channelSettings[currentChannelSetting][BIAS_SET], channelSettings[currentChannelSetting][SRB2_SET], channelSettings[currentChannelSetting][SRB1_SET]);
+
+        // Reset
+        numberOfIncomingSettingsProcessedChannel = 0;
+
+        // put flag back down
+        isProcessingIncomingSettingsChannel = false;
+    }
+}
+
+/**
+ * @description When a 'z' is found on the serial port, we jump to this function
+ *                  where we continue to read from the serial port and read the
+ *                  remaining 4 bytes.
+ * @param `character` - {char} - The character you want to process...
+ */
+void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) {
+
+    if (character == OPENBCI_CHANNEL_IMPEDANCE_LATCH && numberOfIncomingSettingsProcessedLeadOff < OPENBCI_NUMBER_OF_BYTES_SETTINGS_LEAD_OFF - 1) {
+        // We failed somehow and should just abort
+        // reset numberOfIncomingSettingsProcessedLeadOff
+        numberOfIncomingSettingsProcessedLeadOff = 0;
+
+        // put flag back down
+        isProcessingIncomingSettingsLeadOff = false;
+
+        if (!streaming) {
+            Serial0.print("Lead off failure: too few chars"); sendEOT();
+        }
+
+        return;
+    }
+    switch (numberOfIncomingSettingsProcessedLeadOff) {
+        case 1: // channel number
+            currentChannelSetting = getChannelCommandForAsciiChar(character);
+            break;
+        case 2: // pchannel setting
+            leadOffSettings[currentChannelSetting][PCHAN] = getNumberForAsciiChar(character);
+            break;
+        case 3: // nchannel setting
+            leadOffSettings[currentChannelSetting][NCHAN] = getNumberForAsciiChar(character);
+            break;
+        case 4: // 'Z' latch
+            if (character != OPENBCI_CHANNEL_IMPEDANCE_LATCH) {
+                if (!streaming) {
+                    Serial0.print("Err: 5th char not ");
+                    Serial0.println(OPENBCI_CHANNEL_IMPEDANCE_LATCH);
+                    sendEOT();
+                }
+                // We failed somehow and should just abort
+                // reset numberOfIncomingSettingsProcessedLeadOff
+                numberOfIncomingSettingsProcessedLeadOff = 0;
+
+                // put flag back down
+                isProcessingIncomingSettingsLeadOff = false;
+
+            }
+            break;
+        default: // should have exited
+            if (!streaming) {
+                Serial0.print("Err: too many chars ");
+                sendEOT();
+            }
+            // We failed somehow and should just abort
+            // reset numberOfIncomingSettingsProcessedLeadOff
+            numberOfIncomingSettingsProcessedLeadOff = 0;
+
+            // put flag back down
+            isProcessingIncomingSettingsLeadOff = false;
+            return;
+    }
+
+    // increment the number of bytes processed
+    numberOfIncomingSettingsProcessedLeadOff++;
+
+    if (numberOfIncomingSettingsProcessedLeadOff == (OPENBCI_NUMBER_OF_BYTES_SETTINGS_LEAD_OFF)) {
+        // We are done processing lead off settings...
+
+        if (!streaming) {
+            Serial0.print("Lead off set for "); Serial0.println(currentChannelSetting + 1); sendEOT();
+        }
+
+        if (sniffMode && Serial1) {
+            Serial1.print("Lead off set for  "); Serial1.println(currentChannelSetting + 1);
+        }
+
+        // Set lead off settings
+        streamSafeLeadOffSetForChannel(currentChannelSetting + 1,leadOffSettings[currentChannelSetting][PCHAN],leadOffSettings[currentChannelSetting][NCHAN]);
+
+        // reset numberOfIncomingSettingsProcessedLeadOff
+        numberOfIncomingSettingsProcessedLeadOff = 0;
+
+        // put flag back down
+        isProcessingIncomingSettingsLeadOff = false;
+    }
+}
+
+
+boolean OpenBCI_32bit_Library::isValidBoardType(char c) {
+    switch (c) {
+        case OPENBCI_BOARD_MODE_DEFAULT:
+        case OPENBCI_BOARD_MODE_DEBUG:
+        case OPENBCI_BOARD_MODE_WIFI:
+        case OPENBCI_BOARD_MODE_INPUT_ANALOG:
+        case OPENBCI_BOARD_MODE_INPUT_DIGITAL:
+            return true;
+        default:
+            return false;
+    }
+}
+
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<  BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+void OpenBCI_32bit_Library::initialize(){
+    pinMode(SD_SS,OUTPUT); digitalWrite(SD_SS,HIGH);  // de-select SDcard if present
+    pinMode(BOARD_ADS, OUTPUT); digitalWrite(BOARD_ADS,HIGH);
+    pinMode(DAISY_ADS, OUTPUT); digitalWrite(DAISY_ADS,HIGH);
+    pinMode(LIS3DH_SS,OUTPUT); digitalWrite(LIS3DH_SS,HIGH);
+    spi.begin();
+    spi.setSpeed(4000000);  // use 4MHz for ADS and LIS3DH
+    spi.setMode(DSPI_MODE0);  // default to SD card mode!
+    initialize_ads(); // hard reset ADS, set pin directions
+    initialize_accel(SCALE_4G); // set pin directions, G scale, DRDY interrupt, power down
+    initializeVariables();
+}
+
+// void __USER_ISR ADS_DRDY_Service() {
+void __USER_ISR ADS_DRDY_Service() {
+  clearIntFlag(_EXTERNAL_4_IRQ); // clear the irq, or else it will continually interrupt!
+  if(bitRead(PORTA,0) == 0){
+    board.channelDataAvailable = true;
+  }
+}
+
+void OpenBCI_32bit_Library::initializeVariables(void) {
+    streaming = false;
+    sendTimeSyncUpPacket = false;
+    timeSynced = false;
+    isProcessingIncomingSettingsChannel = false;
+    isProcessingIncomingSettingsLeadOff = false;
+    settingBoardMode = false;
+    numberOfIncomingSettingsProcessedChannel = 0;
+    numberOfIncomingSettingsProcessedLeadOff = 0;
+    currentChannelSetting = 0;
+    timeOffset = 0;
+    timeSetCharArrived = 0;
+    streamPacketType = (char)OPENBCI_PACKET_TYPE_V3;
+}
+
+void OpenBCI_32bit_Library::printAllRegisters(){
+    if(!isRunning){
+        Serial0.println("\nBoard ADS Registers");
+        printADSregisters(BOARD_ADS);
+        if(daisyPresent){
+            Serial0.println("\nDaisy ADS Registers");
+            printADSregisters(DAISY_ADS);
+        }
+        Serial0.println("\nLIS3DH Registers");
+        LIS3DH_readAllRegs();
+        sendEOT();
+    }
+}
+
+/**
+ * @description Writes channel data and `axisData` array to serial port in
+ *  the correct stream packet format.
+ *
+ *  Adds stop byte `OPENBCI_EOP_STND_ACCEL`. See `OpenBCI_32bit_Library_Definitions.h`
+ */
+void OpenBCI_32bit_Library::sendChannelDataWithAccel(void)  {
+
+    Serial0.write(OPENBCI_SOP_SYMBOL);
+
+    Serial0.write(sampleCounter); // 1 byte
+
+    ADS_writeChannelData(); // 24 bytes
+
+    accelWriteAxisData(); // 6 bytes
+
+    Serial0.write(OPENBCI_EOP_STND_ACCEL); // 0xC0
+
+    sampleCounter++;
+
+}
+
+/**
+ * @description Writes channel data and `auxData` array to serial port in
+ *  the correct stream packet format.
+ *
+ *  Adds stop byte `OPENBCI_EOP_STND_RAW_AUX`. See `OpenBCI_32bit_Library_Definitions.h`
+ */
+void OpenBCI_32bit_Library::sendChannelDataWithRawAux(void) {
+
+    Serial0.write(OPENBCI_SOP_SYMBOL);
+
+    Serial0.write(sampleCounter); // 1 byte
+
+    ADS_writeChannelData();       // 24 bytes
+
+    writeAuxData();         // 6 bytes
+
+    Serial0.write(OPENBCI_EOP_STND_RAW_AUX); // 0xC1 - 1 byte
+
+    sampleCounter++;
+}
+
+/**
+ * @description Writes channel data, `axisData` array, and 4 byte unsigned time
+ *  stamp in ms to serial port in the correct stream packet format.
+ *
+ *  `axisData` will be split up and sent on the samples with `sampleCounter` of
+ *   7, 8, and 9 for X, Y, and Z respectively. Driver writers parse accordingly.
+ *
+ *  If the global variable `sendTimeSyncUpPacket` is `true` (set by `processChar`
+ *   getting a time sync set `<` command) then:
+ *      Adds stop byte `OPENBCI_EOP_ACCEL_TIME_SET` and sets `sendTimeSyncUpPacket`
+ *      to `false`.
+ *  Else if `sendTimeSyncUpPacket` is `false` then:
+ *      Adds stop byte `OPENBCI_EOP_ACCEL_TIME_SYNCED`
+ */
+void OpenBCI_32bit_Library::sendChannelDataWithTimeAndAccel(void) {
+
+    Serial0.write(OPENBCI_SOP_SYMBOL);
+
+    Serial0.write(sampleCounter); // 1 byte
+
+    ADS_writeChannelData();       // 24 bytes
+
+    // send two bytes of either accel data or blank
+    switch (sampleCounter % 10) {
+        case ACCEL_AXIS_X: // 7
+            LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_X);
+            break;
+        case ACCEL_AXIS_Y: // 8
+            LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_Y);
+            break;
+        case ACCEL_AXIS_Z: // 9
+            LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_Z);
+            break;
+        default:
+            Serial0.write((byte)0x00); // high byte
+            Serial0.write((byte)0x00); // low byte
+            break;
+    }
+
+    writeTimeCurrent(); // 4 bytes
+
+    if (sendTimeSyncUpPacket) {
+        sendTimeSyncUpPacket = false;
+        Serial0.write(OPENBCI_EOP_ACCEL_TIME_SET); // 0xC3
+    } else {
+        Serial0.write(OPENBCI_EOP_ACCEL_TIME_SYNCED); // 0xC4
+    }
+
+    sampleCounter++;
+}
+
+/**
+ * @description Writes channel data, `auxData[0]` 2 bytes, and 4 byte unsigned
+ *  time stamp in ms to serial port in the correct stream packet format.
+ *
+ *  If the global variable `sendTimeSyncUpPacket` is `true` (set by `processChar`
+ *   getting a time sync set `<` command) then:
+ *      Adds stop byte `OPENBCI_EOP_RAW_AUX_TIME_SET` and sets `sendTimeSyncUpPacket`
+ *      to `false`.
+ *  Else if `sendTimeSyncUpPacket` is `false` then:
+ *      Adds stop byte `OPENBCI_EOP_RAW_AUX_TIME_SYNCED`
+ */
+void OpenBCI_32bit_Library::sendChannelDataWithTimeAndRawAux(void) {
+
+    Serial0.print(OPENBCI_SOP_SYMBOL);
+
+    Serial0.write(sampleCounter); // 1 byte
+
+    ADS_writeChannelData();       // 24 bytes
+
+    Serial0.write(highByte(auxData[0])); // 2 bytes of aux data
+    Serial0.write(lowByte(auxData[0]));
+
+    writeTimeCurrent(); // 4 bytes
+
+    if (sendTimeSyncUpPacket) {
+        sendTimeSyncUpPacket = false;
+        Serial0.write(OPENBCI_EOP_RAW_AUX_TIME_SET); // 0xC5
+    } else {
+        Serial0.write(OPENBCI_EOP_RAW_AUX_TIME_SYNCED); // 0xC6
+    }
+
+    sampleCounter++;
+
+}
+
+/**
+ * @description Writes channel data, aux data, and footer to serial port. This
+ *  is the old way to send channel data. Based on global variables `useAux`
+ *  and `useAccel` Must keep for portability. Will look to deprecate in 3.0.0.
+ *
+ *  If `useAccel` is `true` then sends data from `axisData` array and sets the
+ *    contents of `axisData` to `0`.
+ *  If `useAux` is `true` then sends data from `auxData` array and sets the
+ *   contents of `auxData` to `0`.
+ *
+ *  Adds stop byte `OPENBCI_EOP_STND_ACCEL`. See `OpenBCI_32bit_Library_Definitions.h`
+ */
+void OpenBCI_32bit_Library::sendChannelData(void) {
+
+    Serial0.print(OPENBCI_SOP_SYMBOL);
+
+    Serial0.write(sampleCounter); // 1 byte
+    ADS_writeChannelData();       // 24 bytes
+    if(useAux){
+        writeAuxData();         // 6 bytes of aux data
+    } else if(useAccel){        // or
+        LIS3DH_writeAxisData(); // 6 bytes of accelerometer data
+    } else{
+        for(int i=0; i<6; i++){
+            Serial0.write((byte)0x00);
+        }
+    }
+
+    Serial0.write(OPENBCI_EOP_STND_ACCEL); // 0xF0
+
+    sampleCounter++;
+}
+
+void OpenBCI_32bit_Library::writeAuxData(){
+    for(int i=0; i<3; i++){
+        Serial0.write(highByte(auxData[i])); // write 16 bit axis data MSB first
+        Serial0.write(lowByte(auxData[i]));  // axisData is array of type short (16bit)
+        auxData[i] = 0;   // reset auxData bytes to 0
+    }
+}
+
+void OpenBCI_32bit_Library::writeTimeCurrent(void) {
+    uint32_t newTime = millis(); // serialize the number, placing the MSB in lower packets
+    for (int j = 3; j >= 0; j--) {
+        Serial0.write(newTime >> (j*8));
+    }
+}
+
+//SPI communication method
+byte OpenBCI_32bit_Library::xfer(byte _data)
+{
+    byte inByte;
+    inByte = spi.transfer(_data);
+    return inByte;
+}
+
+//SPI chip select method
+void OpenBCI_32bit_Library::csLow(int SS)
+{ // select an SPI slave to talk to
+    switch(SS){
+        case BOARD_ADS:
+            spi.setMode(DSPI_MODE1);
+            spi.setSpeed(4000000);
+            digitalWrite(BOARD_ADS, LOW);
+            break;
+        case LIS3DH_SS:
+            spi.setMode(DSPI_MODE3);
+            spi.setSpeed(4000000);
+            digitalWrite(LIS3DH_SS, LOW);
+            break;
+        case SD_SS:
+            spi.setMode(DSPI_MODE0);
+            spi.setSpeed(20000000);
+            digitalWrite(SD_SS, LOW);
+            break;
+        case DAISY_ADS:
+            spi.setMode(DSPI_MODE1);
+            spi.setSpeed(4000000);
+            digitalWrite(DAISY_ADS, LOW);
+            break;
+        case BOTH_ADS:
+            spi.setMode(DSPI_MODE1);
+            spi.setSpeed(4000000);
+            digitalWrite(BOARD_ADS,LOW);
+            digitalWrite(DAISY_ADS,LOW);
+            break;
+        default:
+            break;
+    }
+}
+
+void OpenBCI_32bit_Library::csHigh(int SS)
+{ // deselect SPI slave
+    switch(SS){
+        case BOARD_ADS:
+            digitalWrite(BOARD_ADS, HIGH);
+            spi.setSpeed(20000000);
+            break;
+        case LIS3DH_SS:
+            digitalWrite(LIS3DH_SS, HIGH);
+            spi.setSpeed(20000000);
+            break;
+        case SD_SS:
+            digitalWrite(SD_SS, HIGH);
+            spi.setSpeed(4000000);
+            break;
+        case DAISY_ADS:
+            digitalWrite(DAISY_ADS, HIGH);
+            spi.setSpeed(20000000);
+            break;
+        case BOTH_ADS:
+            digitalWrite(BOARD_ADS, HIGH);
+            digitalWrite(DAISY_ADS, HIGH);
+            spi.setSpeed(20000000); break;
+            default:
+        break;
+    }
+    spi.setMode(DSPI_MODE0);  // DEFAULT TO SD MODE!
+}
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+// *************************************************************************************
+// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  ADS1299 FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+
+void OpenBCI_32bit_Library::initialize_ads(){
+// recommended power up sequence requiers >Tpor (~32mS)
+    delay(50);
+    pinMode(ADS_RST,OUTPUT);
+    digitalWrite(ADS_RST,LOW);  // reset pin connected to both ADS ICs
+    delayMicroseconds(4);   // toggle reset pin
+    digitalWrite(ADS_RST,HIGH); // this will reset the Daisy if it is present
+    delayMicroseconds(20);  // recommended to wait 18 Tclk before using device (~8uS);
+// initalize the  data ready chip select and reset pins:
+    pinMode(ADS_DRDY, INPUT); // we get DRDY asertion from the on-board ADS
+    delay(40);
+    resetADS(BOARD_ADS); // reset the on-board ADS registers, and stop DataContinuousMode
+    delay(10);
+    WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output its clk, set the data rate to 250SPS
+    delay(40);
+    resetADS(DAISY_ADS); // software reset daisy module if present
+    delay(10);
+    daisyPresent = smellDaisy(); // check to see if daisy module is present
+    if(!daisyPresent){
+      WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
+      numChannels = 8;    // expect up to 8 ADS channels
+    }else{
+      numChannels = 16;   // expect up to 16 ADS channels
+    }
+
+    // DEFAULT CHANNEL SETTINGS FOR ADS
+    defaultChannelSettings[POWER_DOWN] = NO;        // on = NO, off = YES
+    defaultChannelSettings[GAIN_SET] = ADS_GAIN24;     // Gain setting
+    defaultChannelSettings[INPUT_TYPE_SET] = ADSINPUT_NORMAL;// input muxer setting
+    defaultChannelSettings[BIAS_SET] = YES;    // add this channel to bias generation
+    defaultChannelSettings[SRB2_SET] = YES;       // connect this P side to SRB2
+    defaultChannelSettings[SRB1_SET] = NO;        // don't use SRB1
+
+    for(int i=0; i<numChannels; i++){
+      for(int j=0; j<6; j++){
+        channelSettings[i][j] = defaultChannelSettings[j];  // assign default settings
+      }
+      useInBias[i] = true;    // keeping track of Bias Generation
+      useSRB2[i] = true;      // keeping track of SRB2 inclusion
+    }
+    boardUseSRB1 = daisyUseSRB1 = false;
+
+    writeChannelSettings(); // write settings to the on-board and on-daisy ADS if present
+
+    WREG(CONFIG3,0b11101100,BOTH_ADS); delay(1);  // enable internal reference drive and etc.
+    for(int i=0; i<numChannels; i++){  // turn off the impedance measure signal
+      leadOffSettings[i][PCHAN] = OFF;
+      leadOffSettings[i][NCHAN] = OFF;
+    }
+    verbosity = false;      // when verbosity is true, there will be Serial feedback
+    firstDataPacket = true;
+
+    streaming = false;
+}
+
+//////////////////////////////////////////////
+///////////// STREAM METHODS /////////////////
+//////////////////////////////////////////////
+
+/**
+* @description Used to activate a channel, if running must stop and start after...
+* @param channelNumber int the channel you want to change
+* @author AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::streamSafeChannelActivate(byte channelNumber) {
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    // Activate the channel
+    activateChannel(channelNumber);
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+* @description Used to deactivate a channel, if running must stop and start after...
+* @param channelNumber int the channel you want to change
+* @author AJ Keller (@pushtheworldllc)
+*/
+void OpenBCI_32bit_Library::streamSafeChannelDeactivate(byte channelNumber){
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    // deactivate the channel
+    deactivateChannel(channelNumber);
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+ * @description Used to set lead off for a channel, if running must stop and start after...
+ * @param `channelNumber` - [byte] - The channel you want to change
+ * @param `pInput` - [byte] - Apply signal to P input, either ON (1) or OFF (0)
+ * @param `nInput` - [byte] - Apply signal to N input, either ON (1) or OFF (0)
+ * @author AJ Keller (@pushtheworldllc)
+ */
+void OpenBCI_32bit_Library::streamSafeLeadOffSetForChannel(byte channelNumber, byte pInput, byte nInput) {
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    changeChannelLeadOffDetect(channelNumber);
+
+    // leadOffSetForChannel(channelNumber, pInput, nInput);
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+ * @description Used to set lead off for a channel, if running must stop and start after...
+ * @param see `.channelSettingsSetForChannel()` for parameters
+ * @author AJ Keller (@pushtheworldllc)
+ */
+void OpenBCI_32bit_Library::streamSafeChannelSettingsForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1) {
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    writeChannelSettings(channelNumber);
+
+    // channelSettingsSetForChannel(channelNumber, powerDown, gain, inputType, bias, srb2, srb1);
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+ * @description Used to report (Serial0.print) the default channel settings
+ *                  if running must stop and start after...
+ * @author AJ Keller (@pushtheworldllc)
+ */
+void OpenBCI_32bit_Library::streamSafeReportAllChannelDefaults(void) {
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    reportDefaultChannelSettings();
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+ * @description Used to set all channels on Board (and Daisy) to the default
+ *                  channel settings if running must stop and start after...
+ * @author AJ Keller (@pushtheworldllc)
+ */
+void OpenBCI_32bit_Library::streamSafeSetAllChannelsToDefault(void) {
+    boolean wasStreaming = streaming;
+
+    // Stop streaming if you are currently streaming
+    if (streaming) {
+        streamStop();
+    }
+
+    setChannelsToDefault();
+
+    // Restart stream if need be
+    if (wasStreaming) {
+        streamStart();
+    }
+}
+
+/**
+* @description Call this to start the streaming data from the ADS1299
+* @returns boolean if able to start streaming
+*/
+void OpenBCI_32bit_Library::streamStart(){  // needs daisy functionality
+    streaming = true;
+    startADS();
+    if (sniffMode && Serial1) {
+        Serial1.println("ADS Started");
+    }
+}
+
+/**
+* @description Call this to stop streaming from the ADS1299
+* @returns boolean if able to stop streaming
+*/
+void OpenBCI_32bit_Library::streamStop(){
+    streaming = false;
+    stopADS();
+    if (sniffMode && Serial1) {
+        Serial1.println("ADS Stopped");
+    }
+
+}
+
+//////////////////////////////////////////////
+////////////// DAISY METHODS /////////////////
+//////////////////////////////////////////////
+boolean OpenBCI_32bit_Library::smellDaisy(void){ // check if daisy present
+    boolean isDaisy = false;
+    byte setting = RREG(ID_REG,DAISY_ADS); // try to read the daisy product ID
+    if(verbosity){Serial0.print("Daisy ID 0x"); Serial0.println(setting,HEX); sendEOT();}
+    if(setting == ADS_ID) {isDaisy = true;} // should read as 0x3E
+    return isDaisy;
+}
+
+void OpenBCI_32bit_Library::removeDaisy(void){
+    if(daisyPresent){
+        // Daisy removed
+        SDATAC(DAISY_ADS);
+        RESET(DAISY_ADS);
+        STANDBY(DAISY_ADS);
+        daisyPresent = false;
+        if(!isRunning) {
+            Serial0.println("daisy removed");
+            sendEOT();
+        }
+    }else{
+        if(!isRunning) {
+            Serial0.println("no daisy to remove!");
+            sendEOT();
+        }
+    }
+}
+
+void OpenBCI_32bit_Library::attachDaisy(void){
+    WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output the clk, set the data rate to 250SPS
+    delay(40);
+    resetADS(DAISY_ADS); // software reset daisy module if present
+    delay(10);
+    daisyPresent = smellDaisy();
+    if(!daisyPresent){
+        WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
+        numChannels = 8;    // expect up to 8 ADS channels
+        if(!isRunning) Serial0.println("no daisy to attach!");
+    }else{
+        numChannels = 16;   // expect up to 16 ADS channels
+        if(!isRunning) Serial0.println("daisy attached");
+    }
+}
+
+//reset all the ADS1299's settings. Stops all data acquisition
+void OpenBCI_32bit_Library::resetADS(int targetSS)
+{
+    int startChan, stopChan;
+    if(targetSS == BOARD_ADS) {startChan = 1; stopChan = 8;}
+    if(targetSS == DAISY_ADS) {startChan = 9; stopChan = 16;}
+    RESET(targetSS);             // send RESET command to default all registers
+    SDATAC(targetSS);            // exit Read Data Continuous mode to communicate with ADS
+    delay(100);
+    // turn off all channels
+    for (int chan=startChan; chan <= stopChan; chan++) {
+        deactivateChannel(chan);    
+    }
+}
+
+void OpenBCI_32bit_Library::setChannelsToDefault(void){
+  for(int i=0; i<numChannels; i++){
+    for(int j=0; j<6; j++){
+      channelSettings[i][j] = defaultChannelSettings[j];
+    }
+    useInBias[i] = true;    // keeping track of Bias Generation
+    useSRB2[i] = true;      // keeping track of SRB2 inclusion
+  }
+  boardUseSRB1 = daisyUseSRB1 = false;
+
+  writeChannelSettings();       // write settings to on-board ADS
+
+  for(int i=0; i<numChannels; i++){   // turn off the impedance measure signal
+    leadOffSettings[i][PCHAN] = OFF;
+    leadOffSettings[i][NCHAN] = OFF;
+  }
+  changeChannelLeadOffDetect(); // write settings to all ADS
+
+
+  WREG(MISC1,0x00,BOARD_ADS);  // open SRB1 switch on-board
+  if(daisyPresent){ WREG(MISC1,0x00,DAISY_ADS); } // open SRB1 switch on-daisy
+}
+
+// void OpenBCI_32bit_Library::setChannelsToDefault(void){
+
+//     // Reset the global channel settings array to default
+//     resetChannelSettingsArrayToDefault(channelSettings);
+//     // Write channel settings to board (and daisy) ADS
+//     channelSettingsArraySetForAll();
+
+//     // Reset the global lead off settings array to default
+//     resetLeadOffArrayToDefault(leadOffSettings);
+//     // Write lead off settings to board (and daisy) ADS
+//     leadOffSetForAllChannels();
+
+//     WREG(MISC1,0x00,BOARD_ADS);  // open SRB1 switch on-board
+//     if(daisyPresent){  // open SRB1 switch on-daisy
+//         WREG(MISC1,0x00,DAISY_ADS);
+//     }
+// }
+
+/**
+ * @description Writes the default channel settings over the serial port
+ */
+void OpenBCI_32bit_Library::reportDefaultChannelSettings(void){
+    Serial0.write(getDefaultChannelSettingForSettingAscii(POWER_DOWN));     // on = NO, off = YES
+    Serial0.write(getDefaultChannelSettingForSettingAscii(GAIN_SET));       // Gain setting
+    Serial0.write(getDefaultChannelSettingForSettingAscii(INPUT_TYPE_SET)); // input muxer setting
+    Serial0.write(getDefaultChannelSettingForSettingAscii(BIAS_SET));       // add this channel to bias generation
+    Serial0.write(getDefaultChannelSettingForSettingAscii(SRB2_SET));       // connect this P side to SRB2
+    Serial0.write(getDefaultChannelSettingForSettingAscii(SRB1_SET));       // don't use SRB1
+    sendEOT();
+}
+
+/**
+ * @description Set all channels using global channelSettings array
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::channelSettingsArraySetForAll(void) {
+//     byte channelNumberUpperLimit;
+
+//     // The upper limit of the channels, either 8 or 16
+//     channelNumberUpperLimit = daisyPresent ? OPENBCI_NUMBER_OF_CHANNELS_DAISY : OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
+
+//     // Loop through all channels
+//     for (byte i = 1; i <= channelNumberUpperLimit; i++) {
+//         // Set for this channel
+//         channelSettingsSetForChannel(i, channelSettings[i][POWER_DOWN], channelSettings[i][GAIN_SET], channelSettings[i][INPUT_TYPE_SET], channelSettings[i][BIAS_SET], channelSettings[i][SRB2_SET], channelSettings[i][SRB1_SET]);
+//     }
+// }
+
+/**
+ * @description Set channel using global channelSettings array for channelNumber
+ * @param `channelNumber` - [byte] - 1-16 channel number
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::channelSettingsArraySetForChannel(byte channelNumber) {
+//     // contstrain the channel number to 0-15
+//     char index = getConstrainedChannelNumber(channelNumber);
+
+//     // Set for this channel
+//     channelSettingsSetForChannel(channelNumber, channelSettings[index][POWER_DOWN], channelSettings[index][GAIN_SET], channelSettings[index][INPUT_TYPE_SET], channelSettings[index][BIAS_SET], channelSettings[index][SRB2_SET], channelSettings[index][SRB1_SET]);
+// }
+
+/**
+ * @description To add a usability abstraction layer above channel setting commands. Due to the
+ *          extensive and highly specific nature of the channel setting command chain.
+ * @param `channelNumber` - [byte] (1-16) for index, so convert channel to array prior
+ * @param `powerDown` - [byte] - YES (1) or NO (0)
+ *          Powers channel down
+ * @param `gain` - [byte] - Sets the gain for the channel
+ *          ADS_GAIN01 (0b00000000) // 0x00
+ *          ADS_GAIN02 (0b00010000) // 0x10
+ *          ADS_GAIN04 (0b00100000) // 0x20
+ *          ADS_GAIN06 (0b00110000) // 0x30
+ *          ADS_GAIN08 (0b01000000) // 0x40
+ *          ADS_GAIN12 (0b01010000) // 0x50
+ *          ADS_GAIN24 (0b01100000) // 0x60
+ * @param `inputType` - [byte] - Selects the ADC channel input source, either:
+ *          ADSINPUT_NORMAL     (0b00000000)
+ *          ADSINPUT_SHORTED    (0b00000001)
+ *          ADSINPUT_BIAS_MEAS  (0b00000010)
+ *          ADSINPUT_MVDD       (0b00000011)
+ *          ADSINPUT_TEMP       (0b00000100)
+ *          ADSINPUT_TESTSIG    (0b00000101)
+ *          ADSINPUT_BIAS_DRP   (0b00000110)
+ *          ADSINPUT_BIAL_DRN   (0b00000111)
+ * @param `bias` - [byte] (YES (1) -> Include in bias (default), NO (0) -> remove from bias)
+ *          selects to include the channel input in bias generation
+ * @param `srb2` - [byte] (YES (1) -> Connect this input to SRB2 (default),
+ *                     NO (0) -> Disconnect this input from SRB2)
+ *          Select to connect (YES) this channel's P input to the SRB2 pin. This closes
+ *              a switch between P input and SRB2 for the given channel, and allows the
+ *              P input to also remain connected to the ADC.
+ * @param `srb1` - [byte] (YES (1) -> connect all N inputs to SRB1,
+ *                     NO (0) -> Disconnect all N inputs from SRB1 (default))
+ *          Select to connect (YES) all channels' N inputs to SRB1. This effects all pins,
+ *              and disconnects all N inputs from the ADC.
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::channelSettingsSetForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1) {
+//     byte setting, targetSS;
+
+//     // contstrain the channel number to 0-15
+//     char index = getConstrainedChannelNumber(channelNumber);
+
+//     // Get the slave select pin for this channel
+//     targetSS = getTargetSSForConstrainedChannelNumber(index);
+
+//     if (sniffMode && Serial1) {
+//         if (targetSS == BOARD_ADS) {
+//             Serial1.print("Set channel "); Serial1.print(channelNumber); Serial1.println(" settings");
+//         }
+//     }
+
+//     // first, disable any data collection
+//     SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+
+//     setting = 0x00;
+
+//     // Set the power down bit
+//     if(powerDown == YES) {
+//         setting |= 0x80;
+//     }
+
+//     // Set the gain bits
+//     setting |= gain;
+
+//     // Set input type bits
+//     setting |= inputType;
+
+//     if(srb2 == YES){
+//         setting |= 0x08; // close this SRB2 switch
+//         useSRB2[index] = true;  // keep track of SRB2 usage
+//     }else{
+//         useSRB2[index] = false;
+//     }
+
+//     byte channelNumberRegister = 0x00;
+
+//     // Since we are addressing 8 bit registers, we need to subtract 8 from the
+//     //  channelNumber if we are addressing the Daisy ADS
+//     if (targetSS == DAISY_ADS) {
+//         channelNumberRegister = index - OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
+//     } else {
+//         channelNumberRegister = index;
+//     }
+//     WREG(CH1SET+channelNumberRegister, setting, targetSS);  // write this channel's register settings
+
+//     // add or remove from inclusion in BIAS generation
+//     setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
+//     if(bias == YES){
+//         useInBias[index] = true;
+//         bitSet(setting,channelNumberRegister);    //set this channel's bit to add it to the bias generation
+//     }else{
+//         useInBias[index] = false;
+//         bitClear(setting,channelNumberRegister);  // clear this channel's bit to remove from bias generation
+//     }
+//     WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
+
+//     setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
+//     if(bias == YES){
+//         bitSet(setting,channelNumberRegister);    //set this channel's bit to add it to the bias generation
+//     }else{
+//         bitClear(setting,channelNumberRegister);  // clear this channel's bit to remove from bias generation
+//     }
+//     WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
+
+//     byte startChan = targetSS == BOARD_ADS ? 0 : OPENBCI_CHANNEL_MAX_NUMBER_8 - 1;
+//     byte endChan = targetSS == BOARD_ADS ? OPENBCI_CHANNEL_MAX_NUMBER_8 : OPENBCI_CHANNEL_MAX_NUMBER_16 - 1;
+//     // if SRB1 is closed or open for one channel, it will be the same for all channels
+//     if(srb1 == YES){
+//         for(int i=startChan; i<endChan; i++){
+//             channelSettings[i][SRB1_SET] = YES;
+//         }
+//         if(targetSS == BOARD_ADS) boardUseSRB1 = true;
+//         if(targetSS == DAISY_ADS) daisyUseSRB1 = true;
+//         setting = 0x20;     // close SRB1 swtich
+//     }
+//     if(srb1 == NO){
+//         for(int i=startChan; i<endChan; i++){
+//             channelSettings[i][SRB1_SET] = NO;
+//         }
+//         if(targetSS == BOARD_ADS) boardUseSRB1 = false;
+//         if(targetSS == DAISY_ADS) daisyUseSRB1 = false;
+//         setting = 0x00;     // open SRB1 switch
+//     }
+//     WREG(MISC1,setting,targetSS);
+// }
+
+// write settings for ALL 8 channels for a given ADS board
+// channel settings: powerDown, gain, inputType, SRB2, SRB1
+void OpenBCI_32bit_Library::writeChannelSettings(){
+  boolean use_SRB1 = false;
+  byte setting, startChan, endChan, targetSS;
+
+  for(int b=0; b<2; b++){
+    if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
+    if(b == 1){
+      if(!daisyPresent){ return; }
+      targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+    }
+
+    SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+
+    for(byte i=startChan; i<endChan; i++){ // write 8 channel settings
+      setting = 0x00;
+      if(channelSettings[i][POWER_DOWN] == YES){setting |= 0x80;}
+      setting |= channelSettings[i][GAIN_SET]; // gain
+      setting |= channelSettings[i][INPUT_TYPE_SET]; // input code
+      if(channelSettings[i][SRB2_SET] == YES){
+        setting |= 0x08;    // close this SRB2 switch
+        useSRB2[i] = true;  // remember SRB2 state for this channel
+      }else{
+        useSRB2[i] = false; // rememver SRB2 state for this channel
+      }
+      WREG(CH1SET+(i-startChan),setting,targetSS);  // write this channel's register settings
+
+      // add or remove this channel from inclusion in BIAS generation
+      setting = RREG(BIAS_SENSP,targetSS);                   //get the current P bias settings
+      if(channelSettings[i][BIAS_SET] == YES){
+        bitSet(setting,i-startChan); useInBias[i] = true;    //add this channel to the bias generation
+      }else{
+        bitClear(setting,i-startChan); useInBias[i] = false; //remove this channel from bias generation
+      }
+      WREG(BIAS_SENSP,setting,targetSS); delay(1);           //send the modified byte back to the ADS
+
+      setting = RREG(BIAS_SENSN,targetSS);                   //get the current N bias settings
+      if(channelSettings[i][BIAS_SET] == YES){
+        bitSet(setting,i-startChan);    //set this channel's bit to add it to the bias generation
+      }else{
+        bitClear(setting,i-startChan);  // clear this channel's bit to remove from bias generation
+      }
+      WREG(BIAS_SENSN,setting,targetSS); delay(1);           //send the modified byte back to the ADS
+
+      if(channelSettings[i][SRB1_SET] == YES){
+        use_SRB1 = true;  // if any of the channel setting closes SRB1, it is closed for all
+      }
+    } // end of CHnSET and BIAS settings
+  } // end of board select loop
+    if(use_SRB1){
+      for(int i=startChan; i<endChan; i++){
+        channelSettings[i][SRB1_SET] = YES;
+      }
+      WREG(MISC1,0x20,targetSS);     // close SRB1 swtich
+      if(targetSS == BOARD_ADS){ boardUseSRB1 = true; }
+      if(targetSS == DAISY_ADS){ daisyUseSRB1 = true; }
+    }else{
+      for(int i=startChan; i<endChan; i++){
+        channelSettings[i][SRB1_SET] = NO;
+      }
+      WREG(MISC1,0x00,targetSS);    // open SRB1 switch
+      if(targetSS == BOARD_ADS){ boardUseSRB1 = false; }
+      if(targetSS == DAISY_ADS){ daisyUseSRB1 = false; }
+    }
+}
+
+// write settings for a SPECIFIC channel on a given ADS board
+void OpenBCI_32bit_Library::writeChannelSettings(byte N){
+
+  byte setting, startChan, endChan, targetSS;
+  if(N < 9){  // channels 1-8 on board
+    targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+  }else{      // channels 9-16 on daisy module
+    if(!daisyPresent) { return; }
+    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+  }
+// function accepts channel 1-16, must be 0 indexed to work with array
+  N = constrain(N-1,startChan,endChan-1);  //subtracts 1 so that we're counting from 0, not 1
+// first, disable any data collection
+  SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+
+  setting = 0x00;
+  if(channelSettings[N][POWER_DOWN] == YES) setting |= 0x80;
+  setting |= channelSettings[N][GAIN_SET]; // gain
+  setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
+  if(channelSettings[N][SRB2_SET] == YES){
+    setting |= 0x08; // close this SRB2 switch
+    useSRB2[N] = true;  // keep track of SRB2 usage
+  }else{
+    useSRB2[N] = false;
+  }
+  WREG(CH1SET+(N-startChan), setting, targetSS);  // write this channel's register settings
+
+  // add or remove from inclusion in BIAS generation
+  setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
+  if(channelSettings[N][BIAS_SET] == YES){
+    useInBias[N] = true;
+    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+  }else{
+    useInBias[N] = false;
+    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+  }
+  WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
+  setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
+  if(channelSettings[N][BIAS_SET] == YES){
+    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+  }else{
+    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+  }
+  WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
+
+// if SRB1 is closed or open for one channel, it will be the same for all channels
+  if(channelSettings[N][SRB1_SET] == YES){
+    for(int i=startChan; i<endChan; i++){
+      channelSettings[i][SRB1_SET] = YES;
+    }
+    if(targetSS == BOARD_ADS) boardUseSRB1 = true;
+    if(targetSS == DAISY_ADS) daisyUseSRB1 = true;
+    setting = 0x20;     // close SRB1 swtich
+  }
+  if(channelSettings[N][SRB1_SET] == NO){
+    for(int i=startChan; i<endChan; i++){
+      channelSettings[i][SRB1_SET] = NO;
+    }
+    if(targetSS == BOARD_ADS) boardUseSRB1 = false;
+    if(targetSS == DAISY_ADS) daisyUseSRB1 = false;
+    setting = 0x00;     // open SRB1 switch
+  }
+  WREG(MISC1,setting,targetSS);
+}
+
+//  deactivate the given channel.
+void OpenBCI_32bit_Library::deactivateChannel(byte N)
+{
+  byte setting, startChan, endChan, targetSS;
+  if(N < 9){
+    targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+  }else{
+    if(!daisyPresent) { return; }
+    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+  }
+  SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+  N = constrain(N-1,startChan,endChan-1);  //subtracts 1 so that we're counting from 0, not 1
+
+  setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings
+  bitSet(setting,7);     // set bit7 to shut down channel
+  bitClear(setting,3);   // clear bit3 to disclude from SRB2 if used
+  WREG(CH1SET+(N-startChan),setting,targetSS); delay(1);     // write the new value to disable the channel
+
+  //remove the channel from the bias generation...
+  setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings
+  bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
+  WREG(BIAS_SENSP,setting,targetSS); delay(1);   //send the modified byte back to the ADS
+
+  setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings
+  bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
+  WREG(BIAS_SENSN,setting,targetSS); delay(1);   //send the modified byte back to the ADS
+
+  leadOffSettings[N][0] = leadOffSettings[N][1] = NO;
+  changeChannelLeadOffDetect(N+1);
+}
+
+void OpenBCI_32bit_Library::activateChannel(byte N)
+{
+    byte setting, startChan, endChan, targetSS;
+  if(N < 9){
+    targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+  }else{
+    if(!daisyPresent) { return; }
+    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+  }
+
+  N = constrain(N-1,startChan,endChan-1);  // 0-7 or 8-15
+
+  SDATAC(targetSS);  // exit Read Data Continuous mode to communicate with ADS
+  setting = 0x00;
+//  channelSettings[N][POWER_DOWN] = NO; // keep track of channel on/off in this array  REMOVE?
+  setting |= channelSettings[N][GAIN_SET]; // gain
+  setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
+  if(useSRB2[N] == true){channelSettings[N][SRB2_SET] = YES;}else{channelSettings[N][SRB2_SET] = NO;}
+  if(channelSettings[N][SRB2_SET] == YES) {bitSet(setting,3);} // close this SRB2 switch
+  WREG(CH1SET+(N-startChan),setting,targetSS);
+  // add or remove from inclusion in BIAS generation
+  if(useInBias[N]){channelSettings[N][BIAS_SET] = YES;}else{channelSettings[N][BIAS_SET] = NO;}
+  setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
+  if(channelSettings[N][BIAS_SET] == YES){
+    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+    useInBias[N] = true;
+  }else{
+    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+    useInBias[N] = false;
+  }
+  WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
+  setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
+  if(channelSettings[N][BIAS_SET] == YES){
+    bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+  }else{
+    bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+  }
+  WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
+
+  setting = 0x00;
+  if(targetSS == BOARD_ADS && boardUseSRB1 == true) setting = 0x20;
+  if(targetSS == DAISY_ADS && daisyUseSRB1 == true) setting = 0x20;
+  WREG(MISC1,setting,targetSS);     // close all SRB1 swtiches
+}
+
+// change the lead off detect settings for all channels
+void OpenBCI_32bit_Library::changeChannelLeadOffDetect()
+{
+  byte setting, startChan, endChan, targetSS;
+
+  for(int b=0; b<2; b++){
+    if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
+    if(b == 1){
+      if(!daisyPresent){ return; }
+      targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+    }
+
+    SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+    byte P_setting = RREG(LOFF_SENSP,targetSS);
+    byte N_setting = RREG(LOFF_SENSN,targetSS);
+
+    for(int i=startChan; i<endChan; i++){
+      if(leadOffSettings[i][PCHAN] == ON){
+        bitSet(P_setting,i-startChan);
+      }else{
+        bitClear(P_setting,i-startChan);
+      }
+      if(leadOffSettings[i][NCHAN] == ON){
+        bitSet(N_setting,i-startChan);
+      }else{
+        bitClear(N_setting,i-startChan);
+      }
+     WREG(LOFF_SENSP,P_setting,targetSS);
+     WREG(LOFF_SENSN,N_setting,targetSS);
+    }
+  }
+}
+
+// change the lead off detect settings for specified channel
+void OpenBCI_32bit_Library::changeChannelLeadOffDetect(byte N)
+{
+  byte setting, targetSS, startChan, endChan;
+
+  if(N < 9){
+    targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+  }else{
+    if(!daisyPresent) { return; }
+    targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+  }
+
+  N = constrain(N-1,startChan,endChan-1);
+  SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+  byte P_setting = RREG(LOFF_SENSP,targetSS);
+  byte N_setting = RREG(LOFF_SENSN,targetSS);
+
+    if(leadOffSettings[N][PCHAN] == ON){
+      bitSet(P_setting,N-startChan);
+    }else{
+      bitClear(P_setting,N-startChan);
+    }
+    if(leadOffSettings[N][NCHAN] == ON){
+      bitSet(N_setting,N-startChan);
+    }else{
+      bitClear(N_setting,N-startChan);
+    }
+   WREG(LOFF_SENSP,P_setting,targetSS);
+   WREG(LOFF_SENSN,N_setting,targetSS);
+}
+
+void OpenBCI_32bit_Library::configureLeadOffDetection(byte amplitudeCode, byte freqCode)
+{
+    amplitudeCode &= 0b00001100;  //only these two bits should be used
+    freqCode &= 0b00000011;  //only these two bits should be used
+
+    byte setting, targetSS;
+    for(int i=0; i<2; i++){
+    if(i == 0){ targetSS = BOARD_ADS; }
+    if(i == 1){
+      if(!daisyPresent){ return; }
+      targetSS = DAISY_ADS;
+    }
+    setting = RREG(LOFF,targetSS); //get the current bias settings
+    //reconfigure the byte to get what we want
+    setting &= 0b11110000;  //clear out the last four bits
+    setting |= amplitudeCode;  //set the amplitude
+    setting |= freqCode;    //set the frequency
+    //send the config byte back to the hardware
+    WREG(LOFF,setting,targetSS); delay(1);  //send the modified byte back to the ADS
+    }
+}
+
+// //  deactivate the given channel.
+// void OpenBCI_32bit_Library::deactivateChannel(byte N)
+// {
+//     byte setting, startChan, endChan, targetSS;
+//     if(N < 9){
+//         targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+//     }else{
+//         if(!daisyPresent) { return; }
+//         targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+//     }
+//     SDATAC(targetSS); delay(1);      // exit Read Data Continuous mode to communicate with ADS
+//     N = constrain(N-1,startChan,endChan-1);  //subtracts 1 so that we're counting from 0, not 1
+
+//     setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings
+//     bitSet(setting,7);     // set bit7 to shut down channel
+//     bitClear(setting,3);   // clear bit3 to disclude from SRB2 if used
+//     WREG(CH1SET+(N-startChan),setting,targetSS); delay(1);     // write the new value to disable the channel
+
+//     //remove the channel from the bias generation...
+//     setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings
+//     bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
+//     WREG(BIAS_SENSP,setting,targetSS); delay(1);   //send the modified byte back to the ADS
+
+//     setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings
+//     bitClear(setting,N-startChan);                  //clear this channel's bit to remove from bias generation
+//     WREG(BIAS_SENSN,setting,targetSS); delay(1);   //send the modified byte back to the ADS
+
+//     leadOffSettings[N][PCHAN] = leadOffSettings[N][NCHAN] = NO;
+//     leadOffSetForChannel(N+1, NO, NO);
+// }
+
+// void OpenBCI_32bit_Library::activateChannel(byte N)
+// {
+//     byte setting, startChan, endChan, targetSS;
+//     if(N < 9){
+//         targetSS = BOARD_ADS; startChan = 0; endChan = 8;
+//     }else{
+//         if(!daisyPresent) { return; }
+//         targetSS = DAISY_ADS; startChan = 8; endChan = 16;
+//     }
+
+//     N = constrain(N-1,startChan,endChan-1);  // 0-7 or 8-15
+
+//     SDATAC(targetSS);  // exit Read Data Continuous mode to communicate with ADS
+//     setting = 0x00;
+//     //  channelSettings[N][POWER_DOWN] = NO; // keep track of channel on/off in this array  REMOVE?
+//     setting |= channelSettings[N][GAIN_SET]; // gain
+//     setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
+//     if(useSRB2[N] == true){channelSettings[N][SRB2_SET] = YES;}else{channelSettings[N][SRB2_SET] = NO;}
+//     if(channelSettings[N][SRB2_SET] == YES) {bitSet(setting,3);} // close this SRB2 switch
+//     WREG(CH1SET+(N-startChan),setting,targetSS);
+//     // add or remove from inclusion in BIAS generation
+//     if(useInBias[N]){channelSettings[N][BIAS_SET] = YES;}else{channelSettings[N][BIAS_SET] = NO;}
+//     setting = RREG(BIAS_SENSP,targetSS);       //get the current P bias settings
+//     if(channelSettings[N][BIAS_SET] == YES){
+//         bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+//         useInBias[N] = true;
+//     }else{
+//         bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+//         useInBias[N] = false;
+//     }
+//     WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
+//     setting = RREG(BIAS_SENSN,targetSS);       //get the current N bias settings
+//     if(channelSettings[N][BIAS_SET] == YES){
+//         bitSet(setting,N-startChan);    //set this channel's bit to add it to the bias generation
+//     }else{
+//         bitClear(setting,N-startChan);  // clear this channel's bit to remove from bias generation
+//     }
+//     WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
+
+//     setting = 0x00;
+//     if(targetSS == BOARD_ADS && boardUseSRB1 == true) setting = 0x20;
+//     if(targetSS == DAISY_ADS && daisyUseSRB1 == true) setting = 0x20;
+//     WREG(MISC1,setting,targetSS);     // close all SRB1 swtiches
+// }
+
+//////////////////////////////////////////////
+///////////// LEAD OFF METHODS ///////////////
+//////////////////////////////////////////////
+
+/**
+ * @description Runs through the `leadOffSettings` global array to set/change
+ *                  the lead off signals for all inputs of all channels.
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::leadOffSetForAllChannels(void) {
+//     byte channelNumberUpperLimit;
+
+//     // The upper limit of the channels, either 8 or 16
+//     channelNumberUpperLimit = daisyPresent ? OPENBCI_NUMBER_OF_CHANNELS_DAISY : OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
+
+//     // Loop through all channels
+//     for (int i = 1; i <= channelNumberUpperLimit; i++) {
+//         leadOffSetForChannel((byte)i,leadOffSettings[i-1][PCHAN],leadOffSettings[i-1][NCHAN]);
+//     }
+// }
+
+/**
+ * @description Used to set lead off for a channel
+ * @param `channelNumber` - [byte] - The channel you want to change
+ * @param `pInput` - [byte] - Apply signal to P input, either ON (1) or OFF (0)
+ * @param `nInput` - [byte] - Apply signal to N input, either ON (1) or OFF (0)
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::leadOffSetForChannel(byte channelNumber, byte pInput, byte nInput) {
+
+//     // contstrain the channel number to 0-15
+//     channelNumber = getConstrainedChannelNumber(channelNumber);
+
+//     // Get the slave select pin for this channel
+//     byte targetSS = getTargetSSForConstrainedChannelNumber(channelNumber);
+
+//     // exit Read Data Continuous mode to communicate with ADS
+//     SDATAC(targetSS);
+//     delay(1);
+
+//     // Read P register
+//     byte P_setting = RREG(LOFF_SENSP,targetSS);
+
+//     // Read N register
+//     byte N_setting = RREG(LOFF_SENSN,targetSS);
+
+//     // Since we are addressing 8 bit registers, we need to subtract 8 from the
+//     //  channelNumber if we are addressing the Daisy ADS
+//     if (targetSS == DAISY_ADS) {
+//         channelNumber -= OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
+//     }
+
+//     // If pInput is ON then we want to set, otherwise we want to clear
+//     if (pInput == ON) {
+//         bitSet(P_setting, channelNumber);
+//     } else {
+//         bitClear(P_setting, channelNumber);
+//     }
+//     // Write to the P register
+//     WREG(LOFF_SENSP,P_setting,targetSS);
+
+//     // If nInput is ON then we want to set, otherwise we want to clear
+//     if (nInput == ON) {
+//         bitSet(N_setting, channelNumber);
+//     } else {
+//         bitClear(N_setting, channelNumber);
+//     }
+//     // Write to the N register
+//     WREG(LOFF_SENSN,N_setting,targetSS);
+// }
+
+/**
+ * @description This sets the LOFF register on the Board ADS and the Daisy ADS
+ * @param `amplitudeCode` - [byte] - The amplitude of the of impedance signal.
+ *                 See `.setleadOffForSS()` for complete description
+ * @param `freqCode` - [byte] - The frequency of the impedance signal can be either.
+ *                 See `.setleadOffForSS()` for complete description
+ * @author AJ Keller (@pushtheworldllc)
+ */
+// void OpenBCI_32bit_Library::leadOffConfigureSignalForAll(byte amplitudeCode, byte freqCode)
+// {
+//     // Set the lead off detection for the on board ADS
+//     leadOffConfigureSignalForTargetSS(BOARD_ADS, amplitudeCode, freqCode);
+
+//     // if the daisy board is present, set that register as well
+//     if (daisyPresent) {
+//         leadOffConfigureSignalForTargetSS(DAISY_ADS, amplitudeCode, freqCode);
+//     }
+// }
+
+/**
+ * @description This sets the LOFF (lead off) register for the given ADS with slave
+ *                  select
+ * @param `targetSS` - [byte] - The Slave Select pin.
+ * @param `amplitudeCode` - [byte] - The amplitude of the of impedance signal.
+ *          LOFF_MAG_6NA        (0b00000000)
+ *          LOFF_MAG_24NA       (0b00000100)
+ *          LOFF_MAG_6UA        (0b00001000)
+ *          LOFF_MAG_24UA       (0b00001100)
+ * @param `freqCode` - [byte] - The frequency of the impedance signal can be either.
+ *          LOFF_FREQ_DC        (0b00000000)
+ *          LOFF_FREQ_7p8HZ     (0b00000001)
+ *          LOFF_FREQ_31p2HZ    (0b00000010)
+ *          LOFF_FREQ_FS_4      (0b00000011)
+ * @author Joel/Leif/Conor (@OpenBCI) Summer 2014
+ */
+// void OpenBCI_32bit_Library::leadOffConfigureSignalForTargetSS(byte targetSS, byte amplitudeCode, byte freqCode) {
+//     byte setting;
+
+//     amplitudeCode &= 0b00001100;  //only these two bits should be used
+//     freqCode &= 0b00000011;  //only these two bits should be used
+
+//     setting = RREG(LOFF,targetSS); //get the current bias settings
+//     //reconfigure the byte to get what we want
+//     setting &= 0b11110000;  //clear out the last four bits
+//     setting |= amplitudeCode;  //set the amplitude
+//     setting |= freqCode;    //set the frequency
+//     //send the config byte back to the hardware
+//     WREG(LOFF,setting,targetSS); delay(1);  //send the modified byte back to the ADS
+// }
+
+//Configure the test signals that can be inernally generated by the ADS1299
+void OpenBCI_32bit_Library::configureInternalTestSignal(byte amplitudeCode, byte freqCode)
+{
+    byte setting, targetSS;
+    for(int i=0; i<2; i++){
+        if(i == 0){ targetSS = BOARD_ADS;}
+        if(i == 1){
+            if(daisyPresent == false){ return; }
+            targetSS = DAISY_ADS;
+        }
+        if (amplitudeCode == ADSTESTSIG_NOCHANGE) amplitudeCode = (RREG(CONFIG2,targetSS) & (0b00000100));
+        if (freqCode == ADSTESTSIG_NOCHANGE) freqCode = (RREG(CONFIG2,targetSS) & (0b00000011));
+        freqCode &= 0b00000011;         //only the last two bits are used
+        amplitudeCode &= 0b00000100;    //only this bit is used
+        byte setting = 0b11010000 | freqCode | amplitudeCode;  //compose the code
+        WREG(CONFIG2,setting,targetSS); delay(1);
+        if (sniffMode && Serial1) {
+            Serial1.print("Wrote to CONFIG2: ");
+            Serial1.print(setting,BIN);
+        }
+    }
+}
+
+void OpenBCI_32bit_Library::changeInputType(byte inputCode){
+
+    for(int i=0; i<numChannels; i++){
+        channelSettings[i][INPUT_TYPE_SET] = inputCode;
+    }
+
+    // OLD CODE REVERT
+    //channelSettingsArraySetForAll();
+
+    writeChannelSettings();
+}
+
+// Start continuous data acquisition
+void OpenBCI_32bit_Library::startADS(void) // NEEDS ADS ADDRESS, OR BOTH?
+{
+    sampleCounter = 0;
+    firstDataPacket = true;
+    RDATAC(BOTH_ADS); // enter Read Data Continuous mode
+    delay(1);
+    START(BOTH_ADS);  // start the data acquisition
+    delay(1);
+    isRunning = true;
+}
+
+/**
+ * @description Check status register to see if data is available from the ADS1299.
+ * @returns {boolean} - `true` if data is available
+ */
+boolean OpenBCI_32bit_Library::waitForNewChannelData(void) {
+    return !isADSDataAvailable();
+}
+
+/**
+ * @description Check status register to see if data is available from the ADS1299.
+ * @returns {boolean} - `true` if data is available
+ */
+boolean OpenBCI_32bit_Library::isADSDataAvailable(void) {
+    return (!(digitalRead(ADS_DRDY)));
+}
+
+// CALLED WHEN DRDY PIN IS ASSERTED. NEW ADS DATA AVAILABLE!
+void OpenBCI_32bit_Library::updateChannelData(){
+    // this needs to be reset, or else it will constantly flag us
+    channelDataAvailable = false;
+    updateBoardData();
+    if(daisyPresent) {updateDaisyData();}
+}
+
+void OpenBCI_32bit_Library::updateBoardData(){
+    byte inByte;
+    int byteCounter = 0;
+
+    if(daisyPresent && !firstDataPacket){
+        for(int i=0; i < 8; i++){  // shift and average the byte arrays
+            lastBoardChannelDataInt[i] = boardChannelDataInt[i]; // remember the last samples
+        }
+    }
+
+    csLow(BOARD_ADS);       //  open SPI
+    for(int i=0; i<3; i++){
+        inByte = xfer(0x00);    //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
+        boardStat = (boardStat << 8) | inByte;
+    }
+    for(int i = 0; i<8; i++){
+        for(int j=0; j<3; j++){   //  read 24 bits of channel data in 8 3 byte chunks
+            inByte = xfer(0x00);
+            boardChannelDataRaw[byteCounter] = inByte;  // raw data goes here
+            byteCounter++;
+            boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte;  // int data goes here
+        }
+    }
+    csHigh(BOARD_ADS); // close SPI
+
+    // need to convert 24bit to 32bit if using the filter
+    for(int i=0; i<8; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
+        if(bitRead(boardChannelDataInt[i],23) == 1){
+            boardChannelDataInt[i] |= 0xFF000000;
+        } else{
+            boardChannelDataInt[i] &= 0x00FFFFFF;
+        }
+    }
+    if(daisyPresent && !firstDataPacket){
+        byteCounter = 0;
+        for(int i=0; i<8; i++){   // take the average of this and the last sample
+            meanBoardChannelDataInt[i] = (lastBoardChannelDataInt[i] + boardChannelDataInt[i])/2;
+        }
+        for(int i=0; i<8; i++){  // place the average values in the meanRaw array
+            for(int b=2; b>=0; b--){
+                meanBoardDataRaw[byteCounter] = (meanBoardChannelDataInt[i] >> (b*8)) & 0xFF;
+                byteCounter++;
+            }
+        }
+    }
+
+    if(firstDataPacket == true){
+        firstDataPacket = false;
+    }
+}
+
+void OpenBCI_32bit_Library::updateDaisyData(){
+    byte inByte;
+    int byteCounter = 0;
+
+    if(daisyPresent && !firstDataPacket){
+        for(int i=0; i<8; i++){  // shift and average the byte arrays
+            lastDaisyChannelDataInt[i] = daisyChannelDataInt[i]; // remember the last samples
+        }
+    }
+
+    csLow(DAISY_ADS);       //  open SPI
+    for(int i=0; i<3; i++){
+        inByte = xfer(0x00);    //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
+        daisyStat = (daisyStat << 8) | inByte;
+    }
+    for(int i = 0; i<8; i++){
+        for(int j=0; j<3; j++){   //  read 24 bits of channel data in 8 3 byte chunks
+            inByte = xfer(0x00);
+            daisyChannelDataRaw[byteCounter] = inByte;  // raw data goes here
+            byteCounter++;
+            daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte; // int data goes here
+        }
+    }
+    csHigh(DAISY_ADS);        //  close SPI
+    // need to convert 24bit to 32bit
+    for(int i=0; i<8; i++){     // convert 3 byte 2's compliment to 4 byte 2's compliment
+        if(bitRead(daisyChannelDataInt[i],23) == 1){
+            daisyChannelDataInt[i] |= 0xFF000000;
+        }else{
+            daisyChannelDataInt[i] &= 0x00FFFFFF;
+        }
+    }
+    if(daisyPresent && !firstDataPacket){
+        byteCounter = 0;
+        for(int i=0; i<8; i++){   // average this sample with the last sample
+            meanDaisyChannelDataInt[i] = (lastDaisyChannelDataInt[i] + daisyChannelDataInt[i])/2;
+        }
+        for(int i=0; i<8; i++){  // place the average values in the meanRaw array
+            for(int b=2; b>=0; b--){
+                meanDaisyDataRaw[byteCounter] = (meanDaisyChannelDataInt[i] >> (b*8)) & 0xFF;
+                byteCounter++;
+            }
+        }
+    }
+
+    if(firstDataPacket == true) {
+        firstDataPacket = false;
+    }
+}
+
+// Stop the continuous data acquisition
+void OpenBCI_32bit_Library::stopADS()
+{
+    STOP(BOTH_ADS);     // stop the data acquisition
+    delay(1);
+    SDATAC(BOTH_ADS);   // stop Read Data Continuous mode to communicate with ADS
+    delay(1);
+    isRunning = false;
+}
+
+
+//write as binary each channel's data
+void OpenBCI_32bit_Library::ADS_writeChannelData()
+{
+
+  if(daisyPresent){
+    if(sampleCounter % 2 != 0){ //CHECK SAMPLE ODD-EVEN AND SEND THE APPROPRIATE ADS DATA
+      for (int i=0; i<24; i++){
+        Serial0.write(meanBoardDataRaw[i]); // send board data on odd samples
+      }
+    }else{
+      for (int i=0; i<24; i++){
+        Serial0.write(meanDaisyDataRaw[i]); // send daisy data on even samples
+      }
+    }
+  }else{
+    for(int i=0; i<24; i++){
+      Serial0.write(boardChannelDataRaw[i]);
+    }
+  }
+}
+
+
+//print out the state of all the control registers
+void OpenBCI_32bit_Library::printADSregisters(int targetSS)
+{
+    boolean prevverbosityState = verbosity;
+    verbosity = true;                       // set up for verbosity output
+    RREGS(0x00,0x0C,targetSS);      // read out the first registers
+    delay(10);                          // stall to let all that data get read by the PC
+    RREGS(0x0D,0x17-0x0D,targetSS); // read out the rest
+    verbosity = prevverbosityState;
+}
+
+byte OpenBCI_32bit_Library::ADS_getDeviceID(int targetSS) {      // simple hello world com check
+    byte data = RREG(ID_REG,targetSS);
+    if(verbosity){            // verbosity otuput
+        Serial0.print("On Board ADS ID ");
+        printHex(data); Serial0.println();
+        sendEOT();
+    }
+    return data;
+}
+
+//System Commands
+void OpenBCI_32bit_Library::WAKEUP(int targetSS) {
+    csLow(targetSS);
+    xfer(_WAKEUP);
+    csHigh(targetSS);
+    delayMicroseconds(3);     //must wait 4 tCLK cycles before sending another command (Datasheet, pg. 35)
+}
+
+void OpenBCI_32bit_Library::STANDBY(int targetSS) {    // only allowed to send WAKEUP after sending STANDBY
+    csLow(targetSS);
+    xfer(_STANDBY);
+    csHigh(targetSS);
+}
+
+void OpenBCI_32bit_Library::RESET(int targetSS) {      // reset all the registers to default settings
+    csLow(targetSS);
+    xfer(_RESET);
+    delayMicroseconds(12);    //must wait 18 tCLK cycles to execute this command (Datasheet, pg. 35)
+    csHigh(targetSS);
+}
+
+void OpenBCI_32bit_Library::START(int targetSS) {      //start data conversion
+    csLow(targetSS);
+    xfer(_START);           // KEEP ON-BOARD AND ON-DAISY IN SYNC
+    csHigh(targetSS);
+}
+
+void OpenBCI_32bit_Library::STOP(int targetSS) {     //stop data conversion
+    csLow(targetSS);
+    xfer(_STOP);            // KEEP ON-BOARD AND ON-DAISY IN SYNC
+    csHigh(targetSS);
+}
+
+void OpenBCI_32bit_Library::RDATAC(int targetSS) {
+    csLow(targetSS);
+    xfer(_RDATAC);      // read data continuous
+    csHigh(targetSS);
+    delayMicroseconds(3);
+}
+void OpenBCI_32bit_Library::SDATAC(int targetSS) {
+    csLow(targetSS);
+    xfer(_SDATAC);
+    csHigh(targetSS);
+    delayMicroseconds(10);   //must wait at least 4 tCLK cycles after executing this command (Datasheet, pg. 37)
+}
+
+
+//  THIS NEEDS CLEANING AND UPDATING TO THE NEW FORMAT
+void OpenBCI_32bit_Library::RDATA(int targetSS) {          //  use in Stop Read Continuous mode when DRDY goes low
+    byte inByte;            //  to read in one sample of the channels
+    csLow(targetSS);        //  open SPI
+    xfer(_RDATA);         //  send the RDATA command
+    for(int i=0; i<3; i++){   //  read in the status register and new channel data
+        inByte = xfer(0x00);
+        boardStat = (boardStat<<8) | inByte; //  read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
+    }
+    if(targetSS == BOARD_ADS){
+        for(int i = 0; i<8; i++){
+            for(int j=0; j<3; j++){   //  read in the new channel data
+                inByte = xfer(0x00);
+                boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte;
+            }
+        }
+        for(int i=0; i<8; i++){
+            if(bitRead(boardChannelDataInt[i],23) == 1){  // convert 3 byte 2's compliment to 4 byte 2's compliment
+            boardChannelDataInt[i] |= 0xFF000000;
+        }else{
+            boardChannelDataInt[i] &= 0x00FFFFFF;
+        }
+    }
+}else{
+    for(int i = 0; i<8; i++){
+        for(int j=0; j<3; j++){   //  read in the new channel data
+            inByte = xfer(0x00);
+            daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte;
+        }
+    }
+    for(int i=0; i<8; i++){
+        if(bitRead(daisyChannelDataInt[i],23) == 1){  // convert 3 byte 2's compliment to 4 byte 2's compliment
+        daisyChannelDataInt[i] |= 0xFF000000;
+    }else{
+        daisyChannelDataInt[i] &= 0x00FFFFFF;
+    }
+}
+}
+csHigh(targetSS);        //  close SPI
+
+
+}
+
+byte OpenBCI_32bit_Library::RREG(byte _address,int targetSS) {    //  reads ONE register at _address
+    byte opcode1 = _address + 0x20;   //  RREG expects 001rrrrr where rrrrr = _address
+    csLow(targetSS);        //  open SPI
+    xfer(opcode1);          //  opcode1
+    xfer(0x00);           //  opcode2
+    regData[_address] = xfer(0x00);//  update mirror location with returned byte
+    csHigh(targetSS);       //  close SPI
+    if (verbosity){           //  verbosity output
+        printRegisterName(_address);
+        printHex(_address);
+        Serial0.print(", ");
+        printHex(regData[_address]);
+        Serial0.print(", ");
+        for(byte j = 0; j<8; j++){
+            Serial0.print(bitRead(regData[_address], 7-j));
+            if(j!=7) Serial0.print(", ");
+        }
+
+        Serial0.println();
+    }
+    return regData[_address];     // return requested register value
+}
+
+
+// Read more than one register starting at _address
+void OpenBCI_32bit_Library::RREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
+
+    byte opcode1 = _address + 0x20;   //  RREG expects 001rrrrr where rrrrr = _address
+    csLow(targetSS);        //  open SPI
+    xfer(opcode1);          //  opcode1
+    xfer(_numRegistersMinusOne);  //  opcode2
+    for(int i = 0; i <= _numRegistersMinusOne; i++){
+        regData[_address + i] = xfer(0x00);   //  add register byte to mirror array
+    }
+    csHigh(targetSS);       //  close SPI
+    if(verbosity){            //  verbosity output
+        for(int i = 0; i<= _numRegistersMinusOne; i++){
+            printRegisterName(_address + i);
+            printHex(_address + i);
+            Serial0.print(", ");
+            printHex(regData[_address + i]);
+            Serial0.print(", ");
+            for(int j = 0; j<8; j++){
+                Serial0.print(bitRead(regData[_address + i], 7-j));
+                if(j!=7) Serial0.print(", ");
+            }
+            Serial0.println();
+            delay(30);
+        }
+    }
+}
+
+void OpenBCI_32bit_Library::WREG(byte _address, byte _value, int target_SS) { //  Write ONE register at _address
+    byte opcode1 = _address + 0x40;   //  WREG expects 010rrrrr where rrrrr = _address
+    csLow(target_SS);        //  open SPI
+    xfer(opcode1);          //  Send WREG command & address
+    xfer(0x00);           //  Send number of registers to read -1
+    xfer(_value);         //  Write the value to the register
+    csHigh(target_SS);       //  close SPI
+    regData[_address] = _value;     //  update the mirror array
+    if(verbosity){            //  verbosity output
+        Serial0.print("Register ");
+        printHex(_address);
+        Serial0.println(" modified.");
+        sendEOT();
+    }
+}
+
+void OpenBCI_32bit_Library::WREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
+    byte opcode1 = _address + 0x40;   //  WREG expects 010rrrrr where rrrrr = _address
+    csLow(targetSS);        //  open SPI
+    xfer(opcode1);          //  Send WREG command & address
+    xfer(_numRegistersMinusOne);  //  Send number of registers to read -1
+    for (int i=_address; i <=(_address + _numRegistersMinusOne); i++){
+        xfer(regData[i]);     //  Write to the registers
+    }
+    csHigh(targetSS);
+    if(verbosity){
+        Serial0.print("Registers ");
+        printHex(_address); Serial0.print(" to ");
+        printHex(_address + _numRegistersMinusOne);
+        Serial0.println(" modified");
+        sendEOT();
+    }
+}
+
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF ADS1299 FUNCTIONS  >>>>>>>>>>>>>>>>>>>>>>>>>
+// ******************************************************************************
+// <<<<<<<<<<<<<<<<<<<<<<<<<  LIS3DH FUNCTIONS  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+
+void OpenBCI_32bit_Library::initialize_accel(byte g){
+    byte setting =  g | 0x08;           // mask the g range for REG4
+    pinMode(LIS3DH_DRDY,INPUT);   // setup dataReady interupt from accelerometer
+    LIS3DH_write(TMP_CFG_REG, 0x00);  // DISable ADC inputs, enable temperature sensor
+    LIS3DH_write(CTRL_REG1, 0x08);    // disable accel, low power mode
+    LIS3DH_write(CTRL_REG2, 0x00);    // don't use the high pass filter
+    LIS3DH_write(CTRL_REG3, 0x00);    // no interrupts yet
+    LIS3DH_write(CTRL_REG4, setting); // set scale to g, high resolution
+    LIS3DH_write(CTRL_REG5, 0x00);    // no boot, no fifo
+    LIS3DH_write(CTRL_REG6, 0x00);
+    LIS3DH_write(REFERENCE, 0x00);
+    DRDYpinValue = lastDRDYpinValue = digitalRead(LIS3DH_DRDY);  // take a reading to seed these variables
+}
+
+void OpenBCI_32bit_Library::enable_accel(byte Hz){
+    for(int i=0; i<3; i++){
+        axisData[i] = 0;            // clear the axisData array so we don't get any stale news
+    }
+    byte setting = Hz | 0x07;           // mask the desired frequency
+    LIS3DH_write(CTRL_REG1, setting);   // set freq and enable all axis in normal mode
+    LIS3DH_write(CTRL_REG3, 0x10);      // enable DRDY1 on INT1 (tied to PIC pin 0, LIS3DH_DRDY)
+}
+
+void OpenBCI_32bit_Library::disable_accel(){
+    LIS3DH_write(CTRL_REG1, 0x08);      // power down, low power mode
+    LIS3DH_write(CTRL_REG3, 0x00);      // disable DRDY1 on INT1
+}
+
+byte OpenBCI_32bit_Library::LIS3DH_getDeviceID(){
+    return LIS3DH_read(WHO_AM_I);
+}
+
+boolean OpenBCI_32bit_Library::LIS3DH_DataAvailable(){
+    boolean x = false;
+    if((LIS3DH_read(STATUS_REG2) & 0x08) > 0) x = true;  // read STATUS_REG
+    return x;
+}
+
+boolean OpenBCI_32bit_Library::LIS3DH_DataReady(){
+    boolean r = false;
+    DRDYpinValue = digitalRead(LIS3DH_DRDY);  // take a look at LIS3DH_DRDY pin
+    if(DRDYpinValue != lastDRDYpinValue){     // if the value has changed since last looking
+        if(DRDYpinValue == HIGH){               // see if this is the rising edge
+            r = true;                             // if so, there is fresh data!
+        }
+        lastDRDYpinValue = DRDYpinValue;        // keep track of the changing pin
+    }
+    return r;
+}
+
+void OpenBCI_32bit_Library::LIS3DH_writeAxisData(void){
+    for(int i=0; i<3; i++){
+        Serial0.write(highByte(axisData[i])); // write 16 bit axis data MSB first
+        Serial0.write(lowByte(axisData[i]));  // axisData is array of type short (16bit)
+        axisData[i] = 0;
+    }
+}
+
+void OpenBCI_32bit_Library::LIS3DH_writeAxisDataForAxis(uint8_t axis) {
+    if (axis > 2) axis = 0;
+    Serial0.write(highByte(axisData[axis])); // write 16 bit axis data MSB first
+    Serial0.write(lowByte(axisData[axis]));  // axisData is array of type short (16bit)
+    axisData[axis] = 0;
+}
+
+byte OpenBCI_32bit_Library::LIS3DH_read(byte reg){
+    reg |= READ_REG;                    // add the READ_REG bit
+    csLow(LIS3DH_SS);                   // take spi
+    spi.transfer(reg);                  // send reg to read
+    byte inByte = spi.transfer(0x00);   // retrieve data
+    csHigh(LIS3DH_SS);                  // release spi
+    return inByte;
+}
+
+void OpenBCI_32bit_Library::LIS3DH_write(byte reg, byte value){
+    csLow(LIS3DH_SS);         // take spi
+    spi.transfer(reg);        // send reg to write
+    spi.transfer(value);      // write value
+    csHigh(LIS3DH_SS);        // release spi
+}
+
+int OpenBCI_32bit_Library::LIS3DH_read16(byte reg){    // use for reading axis data.
+    int inData;
+    reg |= READ_REG | READ_MULTI;   // add the READ_REG and READ_MULTI bits
+    csLow(LIS3DH_SS);               // take spi
+    spi.transfer(reg);              // send reg to start reading from
+    inData = spi.transfer(0x00) | (spi.transfer(0x00) << 8);  // get the data and arrange it
+    csHigh(LIS3DH_SS);              // release spi
+    return inData;
+}
+
+int OpenBCI_32bit_Library::getX(){
+    return LIS3DH_read16(OUT_X_L);
+}
+
+int OpenBCI_32bit_Library::getY(){
+    return LIS3DH_read16(OUT_Y_L);
+}
+
+int OpenBCI_32bit_Library::getZ(){
+    return LIS3DH_read16(OUT_Z_L);
+}
+
+void OpenBCI_32bit_Library::LIS3DH_updateAxisData(){
+    axisData[0] = getX();
+    axisData[1] = getY();
+    axisData[2] = getZ();
+}
+
+void OpenBCI_32bit_Library::LIS3DH_readAllRegs(){
+
+    byte inByte;
+
+    for (int i = STATUS_REG_AUX; i <= WHO_AM_I; i++){
+        inByte = LIS3DH_read(i);
+        Serial0.print("0x0");Serial0.print(i,HEX);
+        Serial0.print("\t");Serial0.println(inByte,HEX);
+        delay(20);
+    }
+    Serial0.println();
+
+    for (int i = TMP_CFG_REG; i <= INT1_DURATION; i++){
+        inByte = LIS3DH_read(i);
+        // printRegisterName(i);
+        Serial0.print("0x");Serial0.print(i,HEX);
+        Serial0.print("\t");Serial0.println(inByte,HEX);
+        delay(20);
+    }
+    Serial0.println();
+
+    for (int i = CLICK_CFG; i <= TIME_WINDOW; i++){
+        inByte = LIS3DH_read(i);
+        Serial0.print("0x");Serial0.print(i,HEX);
+        Serial0.print("\t");Serial0.println(inByte,HEX);
+        delay(20);
+    }
+
+}
+
+
+
+// <<<<<<<<<<<<<<<<<<<<<<<<<  END OF LIS3DH FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+
+
+// String-Byte converters for ADS
+void OpenBCI_32bit_Library::printRegisterName(byte _address) {
+    switch(_address){
+        case ID_REG:
+        Serial0.print("ADS_ID, "); break;
+        case CONFIG1:
+        Serial0.print("CONFIG1, "); break;
+        case CONFIG2:
+        Serial0.print("CONFIG2, "); break;
+        case CONFIG3:
+        Serial0.print("CONFIG3, "); break;
+        case LOFF:
+        Serial0.print("LOFF, "); break;
+        case CH1SET:
+        Serial0.print("CH1SET, "); break;
+        case CH2SET:
+        Serial0.print("CH2SET, "); break;
+        case CH3SET:
+        Serial0.print("CH3SET, "); break;
+        case CH4SET:
+        Serial0.print("CH4SET, "); break;
+        case CH5SET:
+        Serial0.print("CH5SET, "); break;
+        case CH6SET:
+        Serial0.print("CH6SET, "); break;
+        case CH7SET:
+        Serial0.print("CH7SET, "); break;
+        case CH8SET:
+        Serial0.print("CH8SET, "); break;
+        case BIAS_SENSP:
+        Serial0.print("BIAS_SENSP, "); break;
+        case BIAS_SENSN:
+        Serial0.print("BIAS_SENSN, "); break;
+        case LOFF_SENSP:
+        Serial0.print("LOFF_SENSP, "); break;
+        case LOFF_SENSN:
+        Serial0.print("LOFF_SENSN, "); break;
+        case LOFF_FLIP:
+        Serial0.print("LOFF_FLIP, "); break;
+        case LOFF_STATP:
+        Serial0.print("LOFF_STATP, "); break;
+        case LOFF_STATN:
+        Serial0.print("LOFF_STATN, "); break;
+        case GPIO:
+        Serial0.print("GPIO, "); break;
+        case MISC1:
+        Serial0.print("MISC1, "); break;
+        case MISC2:
+        Serial0.print("MISC2, "); break;
+        case CONFIG4:
+        Serial0.print("CONFIG4, "); break;
+        default:
+        break;
+    }
+}
+
+// Used for printing HEX in verbosity feedback mode
+void OpenBCI_32bit_Library::printHex(byte _data){
+    Serial0.print("0x");
+    if(_data < 0x10) Serial0.print("0");
+    Serial0.print(_data, HEX);
+}
+
+/**
+ * @description Converts ascii character to byte value for channel setting bytes
+ * @param `asciiChar` - [char] - The ascii character to convert
+ * @return [char] - Byte number value of acsii character, defaults to 0
+ * @author AJ Keller (@pushtheworldllc)
+ */
+char OpenBCI_32bit_Library::getChannelCommandForAsciiChar(char asciiChar) {
+    switch(asciiChar){
+        case OPENBCI_CHANNEL_CMD_CHANNEL_1:
+            return 0x00;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_2:
+            return 0x01;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_3:
+            return 0x02;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_4:
+            return 0x03;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_5:
+            return 0x04;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_6:
+            return 0x05;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_7:
+            return 0x06;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_8:
+            return 0x07;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_9:
+            return 0x08;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_10:
+            return 0x09;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_11:
+            return 0x0A;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_12:
+            return 0x0B;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_13:
+            return 0x0C;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_14:
+            return 0x0D;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_15:
+            return 0x0E;
+        case OPENBCI_CHANNEL_CMD_CHANNEL_16:
+            return 0x0F;
+        default:
+            return 0x00;
+    }
+}
+
+/**
+ * @description Converts ascii '0' to number 0 and ascii '1' to number 1
+ * @param `asciiChar` - [char] - The ascii character to convert
+ * @return [char] - Byte number value of acsii character, defaults to 0
+ * @author AJ Keller (@pushtheworldllc)
+ */
+char OpenBCI_32bit_Library::getYesOrNoForAsciiChar(char asciiChar) {
+    switch (asciiChar) {
+        case '1':
+            return ACTIVATE;
+        case '0':
+        default:
+            return DEACTIVATE;
+    }
+}
+
+/**
+ * @description Converts ascii character to get gain from channel settings
+ * @param `asciiChar` - [char] - The ascii character to convert
+ * @return [char] - Byte number value of acsii character, defaults to 0
+ * @author AJ Keller (@pushtheworldllc)
+ */
+char OpenBCI_32bit_Library::getGainForAsciiChar(char asciiChar) {
+
+    char output = 0x00;
+
+    if (asciiChar < '0' || asciiChar > '6') {
+        asciiChar = '6'; // Default to 24
+    }
+
+    output = asciiChar - '0';
+
+    return output << 4;
+}
+
+/**
+ * @description Converts ascii character to get gain from channel settings
+ * @param `asciiChar` - [char] - The ascii character to convert
+ * @return [char] - Byte number value of acsii character, defaults to 0
+ * @author AJ Keller (@pushtheworldllc)
+ */
+char OpenBCI_32bit_Library::getNumberForAsciiChar(char asciiChar) {
+    if (asciiChar < '0' || asciiChar > '9') {
+        asciiChar = '0';
+    }
+
+    // Convert ascii char to number
+    asciiChar -= '0';
+
+    return asciiChar;
+}
+
+/**
+ * @description Used to set the channelSettings array to default settings
+ * @param `setting` - [byte] - The byte you need a setting for....
+ * @returns - [byte] - Retuns the proper byte for the input setting, defualts to 0
+ */
+byte OpenBCI_32bit_Library::getDefaultChannelSettingForSetting(byte setting) {
+    switch (setting) {
+        case POWER_DOWN:
+            return NO;
+        case GAIN_SET:
+            return ADS_GAIN24;
+        case INPUT_TYPE_SET:
+            return ADSINPUT_NORMAL;
+        case BIAS_SET:
+            return YES;
+        case SRB2_SET:
+            return YES;
+        case SRB1_SET:
+        default:
+            return NO;
+    }
+}
+
+/**
+ * @description Used to set the channelSettings array to default settings
+ * @param `setting` - [byte] - The byte you need a setting for....
+ * @returns - [char] - Retuns the proper ascii char for the input setting, defaults to '0'
+ */
+char OpenBCI_32bit_Library::getDefaultChannelSettingForSettingAscii(byte setting) {
+    switch (setting) {
+        case GAIN_SET: // Special case where GAIN_SET needs to be shifted first
+            return (ADS_GAIN24 >> 4) + '0';
+        default: // All other settings are just adding the ascii value for '0'
+            return getDefaultChannelSettingForSetting(setting) + '0';
+    }
+}
+
+/**
+ * @description Convert user channelNumber for use in array indexs by subtracting 1,
+ *                  also make sure N is not greater than 15 or less than 0
+ * @param `channelNumber` - [byte] - The channel number
+ * @return [byte] - Constrained channel number
+ */
+char OpenBCI_32bit_Library::getConstrainedChannelNumber(byte channelNumber) {
+    return constrain(channelNumber - 1, 0, OPENBCI_NUMBER_OF_CHANNELS_DAISY - 1);
+}
+
+/**
+ * @description Get slave select pin for channelNumber
+ * @param `channelNumber` - [byte] - The channel number
+ * @return [byte] - Constrained channel number
+ */
+char OpenBCI_32bit_Library::getTargetSSForConstrainedChannelNumber(byte channelNumber) {
+    // Is channelNumber in the range of default [0,7]
+    if (channelNumber < OPENBCI_NUMBER_OF_CHANNELS_DEFAULT) {
+        return BOARD_ADS;
+    } else {
+        return DAISY_ADS;
+    }
+}
+
+/**
+ * @description Used to set the channelSettings array to default settings
+ * @param `channelSettingsArray` - [byte **] - Takes a two dimensional array of
+ *          length OPENBCI_NUMBER_OF_CHANNELS_DAISY by 6 elements
+ */
+void OpenBCI_32bit_Library::resetChannelSettingsArrayToDefault(byte channelSettingsArray[][OPENBCI_NUMBER_OF_CHANNEL_SETTINGS]) {
+    // Loop through all channels
+    for (int i = 0; i < OPENBCI_NUMBER_OF_CHANNELS_DAISY; i++) {
+        channelSettingsArray[i][POWER_DOWN]     = getDefaultChannelSettingForSetting(POWER_DOWN);       // on = NO, off = YES
+        channelSettingsArray[i][GAIN_SET]       = getDefaultChannelSettingForSetting(GAIN_SET);         // Gain setting
+        channelSettingsArray[i][INPUT_TYPE_SET] = getDefaultChannelSettingForSetting(INPUT_TYPE_SET);   // input muxer setting
+        channelSettingsArray[i][BIAS_SET]       = getDefaultChannelSettingForSetting(BIAS_SET);         // add this channel to bias generation
+        channelSettingsArray[i][SRB2_SET]       = getDefaultChannelSettingForSetting(SRB2_SET);         // connect this P side to SRB2
+        channelSettingsArray[i][SRB1_SET]       = getDefaultChannelSettingForSetting(SRB1_SET);         // don't use SRB1
+
+        useInBias[i] = true;    // keeping track of Bias Generation
+        useSRB2[i] = true;      // keeping track of SRB2 inclusion
+    }
+
+    boardUseSRB1 = daisyUseSRB1 = false;
+}
+
+/**
+ * @description Used to set the channelSettings array to default settings
+ * @param `channelSettingsArray` - [byte **] - A two dimensional array of
+ *          length OPENBCI_NUMBER_OF_CHANNELS_DAISY by 2 elements
+ */
+void OpenBCI_32bit_Library::resetLeadOffArrayToDefault(byte leadOffArray[][OPENBCI_NUMBER_OF_LEAD_OFF_SETTINGS]) {
+    // Loop through all channels
+    for (int i = 0; i < OPENBCI_NUMBER_OF_CHANNELS_DAISY; i++) {
+        leadOffArray[i][PCHAN] = OFF;
+        leadOffArray[i][NCHAN] = OFF;
+    }
+}
+
+OpenBCI_32bit_Library board;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OpenBCI_32bit_Library.h	Sun Jan 22 04:10:11 2017 +0000
@@ -0,0 +1,249 @@
+/*
+   insert header here
+
+*/
+#ifndef _____OpenBCI_32bit__
+#define _____OpenBCI_32bit__
+
+
+//#include <DSPI.h> // MBED: not needed
+//#include <Arduino.h> // MBED: not needed
+#include "PlatformDefs.h" // MBED: arduino hardware emulation
+#include "Definitions.h"
+
+void __USER_ISR ADS_DRDY_Service(void);
+class OpenBCI_32bit_Library {
+
+public:
+
+    // Start up functions
+    OpenBCI_32bit_Library();
+    boolean accelHasNewData(void);
+    void    accelUpdateAxisData(void);
+    void    accelWriteAxisData(void);
+    void    begin(void);
+    void    beginDebug(void);
+    boolean beginSecondarySerial(void);
+    char    getCharSerial0(void);
+    char    getCharSerial1(void);
+    boolean hasDataSerial0(void);
+    boolean hasDataSerial1(void);
+
+
+    void    writeSerial(char *data, int len);
+
+    boolean isADSDataAvailable(void);
+
+
+
+    void writeTimeCurrent(void);
+    void writeZeroAux(void);
+    void activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode);
+
+    void channelSettingsArraySetForAll(void);
+    void channelSettingsArraySetForChannel(byte N);
+    void channelSettingsSetForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1);
+
+    void leadOffConfigureSignalForAll(byte amplitudeCode, byte freqCode);
+    void leadOffConfigureSignalForTargetSS(byte targetSS, byte amplitudeCode, byte freqCode);
+
+    void leadOffSetForAllChannels(void);
+    void leadOffSetForChannel(byte channelNumber, byte pInput, byte nInput);
+
+    boolean processChar(char character);
+    void processIncomingBoardMode(char character);
+    void processIncomingChannelSettings(char character);
+    void processIncomingLeadOffSettings(char character);
+
+    void resetChannelSettingsArrayToDefault(byte channelSettingsArray[][OPENBCI_NUMBER_OF_CHANNEL_SETTINGS]);
+    void resetLeadOffArrayToDefault(byte leadOffArray[][OPENBCI_NUMBER_OF_LEAD_OFF_SETTINGS]);
+
+    void sendChannelDataWithAccel(void);
+    void sendChannelDataWithRawAux(void);
+    void sendChannelDataWithTimeAndAccel(void);
+    void sendChannelDataWithTimeAndRawAux(void);
+
+    void streamSafeChannelDeactivate(byte channelNumber);
+    void streamSafeChannelActivate(byte channelNumber);
+    void streamSafeChannelSettingsForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1);
+    void streamSafeSetAllChannelsToDefault(void);
+    void streamSafeReportAllChannelDefaults(void);
+    void streamSafeLeadOffSetForChannel(byte channelNumber, byte pInput, byte nInput);
+    void streamSafeTimeSendSyncSetPacket(void);
+    void streamStart(void);
+    void streamStop(void);
+
+    // OLD CODE REVERT
+    void writeChannelSettings();
+    void writeChannelSettings(byte N);
+    void changeChannelLeadOffDetect();
+    void changeChannelLeadOffDetect(byte N);
+    void configureLeadOffDetection(byte amplitudeCode, byte freqCode);
+
+    boolean waitForNewChannelData(void);
+
+    // Variables
+    boolean daisy;
+    boolean sniffMode;
+    boolean streaming;
+    boolean timeSynced;
+    boolean sendTimeSyncUpPacket;
+    boolean isProcessingIncomingSettingsChannel;
+    boolean isProcessingIncomingSettingsLeadOff;
+    boolean settingBoardMode;
+    volatile boolean channelDataAvailable;
+
+    boolean isProcessingMultibyteMsg(void);
+    boolean isValidBoardType(char c);
+
+    uint8_t curBoardMode;
+
+    int numberOfIncomingSettingsProcessedChannel;
+    int numberOfIncomingSettingsProcessedLeadOff;
+    char streamPacketType;
+    char currentChannelSetting;
+
+    // Getters
+    char getChannelCommandForAsciiChar(char asciiChar);
+    char getConstrainedChannelNumber(byte channelNumber);
+    byte getDefaultChannelSettingForSetting(byte setting);
+    char getDefaultChannelSettingForSettingAscii(byte setting);
+    char getGainForAsciiChar(char asciiChar);
+    char getNumberForAsciiChar(char asciiChar);
+    char getTargetSSForConstrainedChannelNumber(byte channelNumber);
+    char getYesOrNoForAsciiChar(char asciiChar);
+
+    DSPI0 spi;  // use DSPI library
+
+// BOARD
+    boolean useAccel;
+    boolean useAux;
+    void initialize(void);
+    void initializeVariables(void);
+    void printAllRegisters(void);
+    void sendChannelData(void); // send the current data with sample number
+
+
+// ADS1299
+    void initialize_ads(void);
+    void setChannelsToDefault(void);
+    void reportDefaultChannelSettings(void);
+    void printADSregisters(int);
+    void WAKEUP(int);  // get out of low power mode
+    void STANDBY(int); // go into low power mode
+    void RESET(int);   // set all register values to default
+    void START(int);   // start data acquisition
+    void STOP(int);    // stop data acquisition
+    void RDATAC(int);  // go into read data continuous mode
+    void SDATAC(int);  // get out of read data continuous mode
+    void RDATA(int);   // read data one-shot
+    byte RREG(byte,int);            // read one ADS register
+    void RREGS(byte,byte,int);      // read multiple ADS registers
+    void WREG(byte,byte,int);       // write one ADS register
+    void WREGS(byte,byte,int);      // write multiple ADS registers
+    byte ADS_getDeviceID(int);
+    void printRegisterName(byte);   // used for verbosity
+    void printHex(byte);            // used for verbosity
+    void updateChannelData(void);   // retrieve data from ADS
+    void updateBoardData(void);
+    void updateDaisyData(void);
+    byte xfer(byte);        // SPI Transfer function
+    void resetADS(int);     // reset all the ADS1299's settings
+    void startADS(void);
+    void stopADS(void);
+    void activateChannel(byte);                  // enable the selected channel
+    void deactivateChannel(byte);                // disable given channel 1-8(16)
+    void configureInternalTestSignal(byte,byte);
+
+    void changeInputType(byte);
+
+    void ADS_writeChannelData(void);
+    // void ADS_printDeviceID(int);   //
+    boolean smellDaisy(void);
+    void removeDaisy(void);
+    void attachDaisy(void);
+    void writeAuxData(void);
+
+    short auxData[3];           // This is user faceing
+    byte regData[24];           // array is used to mirror register data
+    byte lastBoardDataRaw[24];
+    byte boardChannelDataRaw[24];    // array to hold raw channel data
+    byte meanBoardDataRaw[24];
+    byte lastDaisyDataRaw[24];
+    byte daisyChannelDataRaw[24];
+    byte meanDaisyDataRaw[24];
+    int boardStat;           // used to hold the status register
+    int daisyStat;
+    int boardChannelDataInt[8];    // array used when reading channel data as ints
+    int lastBoardChannelDataInt[8];
+    int meanBoardChannelDataInt[8];
+    int daisyChannelDataInt[8];    // array used when reading channel data as ints
+    int lastDaisyChannelDataInt[8];
+    int meanDaisyChannelDataInt[8];
+    int numChannels;
+    byte channelSettings[OPENBCI_NUMBER_OF_CHANNELS_DAISY][OPENBCI_NUMBER_OF_CHANNEL_SETTINGS];  // array to hold current channel settings
+    byte defaultChannelSettings[OPENBCI_NUMBER_OF_CHANNEL_SETTINGS];  // default channel settings
+    byte leadOffSettings[OPENBCI_NUMBER_OF_CHANNELS_DAISY][OPENBCI_NUMBER_OF_LEAD_OFF_SETTINGS];  // used to control on/off of impedance measure for P and N side of each channel
+    boolean useInBias[OPENBCI_NUMBER_OF_CHANNELS_DAISY];        // used to remember if we were included in Bias before channel power down
+    boolean useSRB2[OPENBCI_NUMBER_OF_CHANNELS_DAISY];
+    boolean boardUseSRB1;             // used to keep track of if we are using SRB1
+    boolean daisyUseSRB1;
+    boolean verbosity;      // turn on/off Serial verbosity
+    boolean daisyPresent;
+    boolean firstDataPacket;
+    byte sampleCounter;
+
+// LIS3DH
+    short axisData[3];
+    void initialize_accel(byte);    // initialize
+    void enable_accel(byte);  // start acceleromoeter with default settings
+    void disable_accel(void); // stop data acquisition and go into low power mode
+    byte LIS3DH_getDeviceID(void);
+    byte LIS3DH_read(byte);     // read a register on LIS3DH
+    void LIS3DH_write(byte,byte);   // write a register on LIS3DH
+    int LIS3DH_read16(byte);    // read two bytes, used to get axis data
+    int getX(void);
+    int getY(void);
+    int getZ(void);
+    boolean LIS3DH_DataReady(void); // check LIS3DH_DRDY pin
+    boolean LIS3DH_DataAvailable(void); // check LIS3DH STATUS_REG2
+    void LIS3DH_readAllRegs(void);
+    void LIS3DH_writeAxisData(void);
+    void LIS3DH_writeAxisDataForAxis(uint8_t axis);
+    void LIS3DH_updateAxisData(void);
+
+    void csLow(int);
+    void csHigh(int);
+
+    //
+    boolean boardBegin(void);
+    boolean boardBeginDebug(void);
+    boolean boardBeginDebug(int);
+    void boardReset(void);
+    void ledFlash(int numberOfFlashes);
+    void sendEOT(void);
+
+    char buffer[1];
+
+// ADS1299
+    boolean isRunning;
+// LIS3DH
+    int DRDYpinValue;
+    int lastDRDYpinValue;
+
+    // Time sync Variables
+    unsigned long timeOffset;
+    unsigned long timeSetCharArrived;
+    unsigned long timeComputer;
+    unsigned long timeCurrent;
+    // Time sync Methods
+    // unsigned long   timeGet(void);
+    // void            timeSet(char character);
+    void            timeSendSyncSetPacket(void);
+
+};
+
+// This let's us call into the class from within the library if necessary
+extern OpenBCI_32bit_Library board;
+
+#endif
--- a/PlatformDefs.h	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformDefs.h	Sun Jan 22 04:10:11 2017 +0000
@@ -4,7 +4,7 @@
 #define boolean  unsigned char
 #define byte     unsigned char
   
-
+#define __USER_ISR
 
 #define HIGH 1
 #define LOW 0
@@ -25,6 +25,7 @@
 
 #include "PlatformUart.h"
 extern platformUart Serial0;
+extern platformUart_Dummy  Serial1;
 
 #include "PlatformSPI.h"
 
@@ -35,3 +36,15 @@
 #define writeDataToSDcard(x)
 #define setupSDcard(x) 1
 #define closeSDfile(x) 0
+
+#define setIntVector(x,y)
+#define setIntPriority(x,y,z)
+#define clearIntFlag(x)
+//#define setIntEnable(x)
+
+#define PORTA 0
+#define _EXTERNAL_4_IRQ 0
+
+#define millis() time(NULL)
+
+#define OPENBCI_SOP_SYMBOL 0xA0//'A'
\ No newline at end of file
--- a/PlatformGPIO.cpp	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformGPIO.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -9,7 +9,7 @@
 DigitalOut daisy_SS(DAISY_ADS);
 DigitalOut accel_SS(LIS3DH_SS);
 
-DigitalIn adc_ready(ADS_DRDY);
+InterruptIn adc_ready(ADS_DRDY);
 DigitalIn accel_ready(LIS3DH_DRDY);
 
 void digitalWrite(int pin, unsigned char value)
@@ -38,3 +38,11 @@
   if (pin == LIS3DH_DRDY)
     return accel_ready;
 }
+
+// external interrupt as ready signal
+extern void ADS_DRDY_Service();
+
+void setIntEnable(int x)
+{
+  adc_ready.fall(&ADS_DRDY_Service);
+}
\ No newline at end of file
--- a/PlatformGPIO.h	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformGPIO.h	Sun Jan 22 04:10:11 2017 +0000
@@ -19,5 +19,6 @@
 
 void digitalWrite(int pin, unsigned char value);
 unsigned char digitalRead(int pin);
+void setIntEnable(int x);
 
 #endif
\ No newline at end of file
--- a/PlatformSPI.cpp	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformSPI.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -7,7 +7,7 @@
 
 void DSPI0::begin()
 {
-  
+
 }
 
 void DSPI0::setSpeed(int speed_hz)
--- a/PlatformUart.cpp	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformUart.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -2,8 +2,11 @@
 
 #include "PlatformUart.h"
 #include "mbed.h"
+#include "SerialBuffered.h"
 
-Serial uart(PA_9, PA_10, 115200); // Serial(PinName tx, PinName rx, const char *name=NULL, int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
+
+//Serial uart(PA_9, PA_10, 115200); // Serial(PinName tx, PinName rx, const char *name=NULL, int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
+SerialBuffered uart( 256, PA_9, PA_10, 115200 );
 
 
 int platformUart::write(int data)
@@ -199,19 +202,17 @@
 }
 
 
-extern void eventSerial();
+
+
 unsigned char rx_data;
-unsigned char rx_avalible;
 
 // Interupt Routine to read in data from serial port
 void Rx_interrupt() 
 {
-    while (uart.readable())
+    //while (uart.readable())
     {
       rx_data = uart.getc();
-      rx_avalible = 1;
-      
-      eventSerial();
+      //byteQueue_Put(&rxQueue, rx_data);
     }
 }
 
@@ -219,24 +220,23 @@
 
 platformUart::platformUart()
 {
-  rx_data = 0;
-  rx_avalible = 0;
+    //byteQueue_Init(&rxQueue);
   
-  uart.attach(&Rx_interrupt, Serial::RxIrq);
+  //uart.attach(&Rx_interrupt, Serial::RxIrq);
 }
 
 unsigned char platformUart::available()
 {
-  return rx_avalible;
+  return uart.readable(); //!(byteQueue_IsEmpty(&rxQueue));
 }
 
 unsigned char platformUart::read()
 {
-  rx_avalible = 0;
-  return rx_data;
+  return uart.getc(); //byteQueue_Get(&rxQueue);
 }
 
 
 
 
-platformUart Serial0;
\ No newline at end of file
+platformUart Serial0;
+platformUart_Dummy Serial1;
\ No newline at end of file
--- a/PlatformUart.h	Sun Dec 04 03:38:44 2016 +0000
+++ b/PlatformUart.h	Sun Jan 22 04:10:11 2017 +0000
@@ -11,6 +11,39 @@
 #include <stddef.h>
 #include <stdint.h>
 
+
+class platformUart_Dummy {
+public:
+  int write(int data) { return 0; }
+  //int write(char* str);
+
+    size_t print(const char[]) { return 0; }
+    size_t print(char) { return 0; }
+    size_t print(unsigned char, int = DEC) { return 0; }
+    size_t print(int, int = DEC) { return 0; }
+    size_t print(unsigned int, int = DEC) { return 0; }
+    size_t print(long, int = DEC) { return 0; }
+    size_t print(unsigned long, int = DEC) { return 0; }
+    size_t print(double, int = 2) { return 0; }
+
+    size_t println(const char[]) { return 0; }
+    size_t println(char) { return 0; }
+    size_t println(unsigned char, int = DEC) { return 0; }
+    size_t println(int, int = DEC) { return 0; }
+    size_t println(unsigned int, int = DEC) { return 0; }
+    size_t println(long, int = DEC) { return 0; }
+    size_t println(unsigned long, int = DEC) { return 0; }
+    size_t println(double, int = 2) { return 0; }
+    size_t println(void) { return 0; }
+    
+    unsigned char available() { return 0; }
+    unsigned char read() { return 0; }
+        void begin(int baudrate) {};
+            
+        operator int() const { return 0; }
+  
+};
+
 class platformUart {
 public:
   int write(int data);
@@ -37,6 +70,7 @@
     
     unsigned char available();
     unsigned char read();
+        void begin(int baudrate) {}
     
     platformUart();
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -0,0 +1,117 @@
+
+#include "mbed.h"
+#include "SerialBuffered.h"
+ 
+//extern Serial loggerSerial;
+ 
+SerialBuffered::SerialBuffered( size_t bufferSize, PinName tx, PinName rx, int baud ) : RawSerial(  tx,  rx, baud ) 
+{
+    m_buffSize = 0;
+    m_contentStart = 0;
+    m_contentEnd = 0;
+    m_timeout = 1.0;
+   
+    
+    attach( this, &SerialBuffered::handleInterrupt );
+    
+    m_buff = (uint8_t *) malloc( bufferSize );
+    if( m_buff == NULL )
+    {
+        //loggerSerial.printf("SerialBuffered - failed to alloc buffer size %d\r\n", (int) bufferSize );
+    }
+    else
+    {
+        m_buffSize = bufferSize;
+    }
+}
+
+
+SerialBuffered::~SerialBuffered()
+{
+    if( m_buff )
+        free( m_buff );
+}
+
+void SerialBuffered::setTimeout( float seconds )
+{
+    m_timeout = seconds;
+}
+    
+size_t SerialBuffered::readBytes( uint8_t *bytes, size_t requested )
+{
+    int i = 0;
+
+    for( ; i < requested; )
+    {
+        int c = getc();
+        if( c < 0 )
+            break;
+        bytes[i] = c;
+        i++;
+    }
+    
+    return i;
+        
+}
+
+
+int SerialBuffered::getc()
+{
+    m_timer.reset();
+    m_timer.start();
+    while( m_contentStart == m_contentEnd )
+    {
+      
+
+        wait_ms( 1 );
+        if( m_timeout > 0 &&  m_timer.read() > m_timeout )
+            return EOF;
+    }
+
+    m_timer.stop();
+   
+    uint8_t result = m_buff[m_contentStart++];
+    m_contentStart =  m_contentStart % m_buffSize;
+
+   
+    return result;    
+}
+
+
+int SerialBuffered::readable()
+{
+    return m_contentStart != m_contentEnd ;
+}
+
+#include "stm32l4xx_hal_def.h"
+#include "stm32l4xx_hal_uart.h"
+
+void SerialBuffered::handleInterrupt()
+{
+    
+    while( RawSerial::readable())
+    {
+        if( m_contentStart == (m_contentEnd +1) % m_buffSize)
+        {
+           //loggerSerial.printf("SerialBuffered - buffer overrun, data lost!\r\n" );
+          RawSerial::getc();
+          //UART_HandleTypeDef huart;
+          //huart.Instance = (USART_TypeDef *)USART1_BASE;
+          //__HAL_UART_CLEAR_FLAG(&huart, UART_FLAG_RXNE);
+          //volatile uint32_t tmpval = huart.Instance->RDR;
+          
+          //break;
+
+        }
+        else
+        {
+          
+            m_buff[ m_contentEnd ++ ] = RawSerial::getc();
+            m_contentEnd = m_contentEnd % m_buffSize;
+            
+           
+           
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.h	Sun Jan 22 04:10:11 2017 +0000
@@ -0,0 +1,39 @@
+#pragma once
+
+// This is a buffered serial reading class, using the serial interrupt introduced in mbed library version 18 on 17/11/09
+
+// In the simplest case, construct it with a buffer size at least equal to the largest message you 
+// expect your program to receive in one go.
+
+class SerialBuffered : public RawSerial
+{
+public:
+    SerialBuffered( size_t bufferSize, PinName tx, PinName rx, int baud );
+    virtual ~SerialBuffered();
+    
+    int getc();     // will block till the next character turns up, or return -1 if there is a timeout
+    
+    int readable(); // returns 1 if there is a character available to read, 0 otherwise
+    
+    void setTimeout( float seconds );    // maximum time in seconds that getc() should block 
+                                         // while waiting for a character
+                                         // Pass -1 to disable the timeout.
+    
+    size_t readBytes( uint8_t *bytes, size_t requested );    // read requested bytes into a buffer, 
+                                                             // return number actually read, 
+                                                             // which may be less than requested if there has been a timeout
+    
+
+private:
+    
+    void handleInterrupt();
+    
+   
+    uint8_t *m_buff;            // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
+    uint16_t  m_contentStart;   // index of first bytes of content
+    uint16_t  m_contentEnd;     // index of bytes after last byte of content
+    uint16_t m_buffSize;
+    float m_timeout;
+    Timer m_timer;
+
+};
\ No newline at end of file
--- a/main.cpp	Sun Dec 04 03:38:44 2016 +0000
+++ b/main.cpp	Sun Jan 22 04:10:11 2017 +0000
@@ -5,551 +5,53 @@
 DigitalOut led_blue(PB_5);
 
 
-
-#include "OpenBCI_32_Daisy.h"
-
-//------------------------------------------------------------------------------
-void setup(void);
-void loop();
-void loadChannelSettings(char c);
-void eventSerial();
-void getCommand(char token);
-void sendEOT();
-void loadChannelSettings(char c);
-void writeChannelSettings_maintainRunningState(char chan);
-void setChannelsToDefaultSetting();
-void loadLeadOffSettings(char c);
-char getChannelNumber(char n);
-void changeChannelState_maintainRunningState(byte chan, int start);
-void activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode);
-int changeChannelLeadOffDetect_maintainRunningState(char chan);
-void sendDefaultChannelSettings();
-boolean stopRunning(void);
-boolean startRunning(int OUT_TYPE);
-void printRegisters();
-void startFromScratch();
-
+//#include <DSPI.h>
+#include "OpenBCI_32bit_Library.h"
+#include "Definitions.h"
 
-//------------------------------------------------------------------------------
-//  << SD CARD BUSINESS >>
-boolean SDfileOpen = false;
-char fileSize = '0';  // SD file size indicator
-int blockCounter = 0;
-//------------------------------------------------------------------------------
-//  << OpenBCI BUSINESS >>
-boolean is_running = false;    // this flag is set in serialEvent on reciept of ascii prompt
-OpenBCI_32_Daisy OBCI;         //Uses SPI bus and pins to say data is ready.
-// these are used to change individual channel settings from PC
-char currentChannelToSet;      // keep track of what channel we're loading settings for
-boolean getChannelSettings = false; // used to receive channel settings command
-int channelSettingsCounter;    // used to retrieve channel settings from serial port
-int leadOffSettingsCounter;
-boolean getLeadOffSettings = false;
-// these are all subject to the radio requirements: 31byte max packet length (maxPacketLength - 1 for packet checkSum)
-#define OUTPUT_NOTHING (0)        // quiet
-#define OUTPUT_8_CHAN (1)         // not using Daisy module
-#define OUTPUT_16_CHAN (2)        // using Daisy module
-int outputType = OUTPUT_8_CHAN;   // default to 8 channels
-
-//------------------------------------------------------------------------------
-//  << LIS3DH Accelerometer Business >>
-boolean addAccelToSD = false;   // this flag get's set and cleared in the code below
-//------------------------------------------------------------------------------
-//  << PUT FILTER STUFF HERE >>
-boolean useFilters = false;     // add DSP if you like, and set this true to turn them on
-//------------------------------------------------------------------------------
-//  << BASIC BOARD STUFF >>
-int LED = 11;     // alias for the blue LED
-int PGCpin = 12;  // PGC pin goes high when PIC is in bootloader mode
-//------------------------------------------------------------------------------
-//  << AUXILIARY DATA STUFF >>
-boolean addAuxToSD = false;     // use this to write auxiliary data to SD if you like
-//------------------------------------------------------------------------------
-void setup(void) {
-
-  pinMode(LED, OUTPUT); digitalWrite(LED, HIGH);   // blue LED
-  pinMode(PGCpin, OUTPUT); digitalWrite(PGCpin, LOW); // used to tell RFduino if we are in bootloader mode NOT IMPLEMENTED
-  delay(1000);            // take a break
-
-  startFromScratch();     // initialize OpenBCI, read device IDs
-  // you can set EITHER useAccel or useAux to true
-  // if you want both, you MUST set and clear one of the variables every sample
-  OBCI.useAccel = true;  // option to add/remove accelerometer data to stream
-  OBCI.useAux = false;     // option to add/remove auxiliary data to stream
-
-
+void setup() {
+  // Bring up the OpenBCI Board
+  board.begin();
 }
 
-
-
 void loop() {
 
-  if (is_running) {
-
-    while (!(OBCI.isDataAvailable())) {} // wait for DRDY pin...
-
-    OBCI.updateChannelData();            // get the fresh ADS results
-    if (OBCI.useAccel && OBCI.LIS3DH_DataAvailable()) {
-      OBCI.LIS3DH_updateAxisData();      // fresh axis data goes into the X Y Z
-      addAccelToSD = true;
-    }
-    if (SDfileOpen) {
-      writeDataToSDcard(OBCI.sampleCounter); // store data locally
-    }
-
-    OBCI.sendChannelData();  // serial fire hose
-  }
-
-  eventSerial();
-
-}
-
-
-// some variables to help find 'burger protocol' commands
-int plusCounter = 0;
-char testChar;
-unsigned long commandTimer;
-
-void eventSerial() {
-  while (Serial0.available()) {
-    char inChar = (char)Serial0.read();
-    
-    //getCommand(inChar);    // decode the command
-
-    if (getChannelSettings) { // if we just got an 'x' expect channel setting parameters
-      loadChannelSettings(inChar);  // go get em!
-    } else if (getLeadOffSettings) { // if we just got a 'z' expect lead-off setting parameters
-      loadLeadOffSettings(inChar); // go get em!
-    } else {
-      getCommand(inChar);    // decode the command
-    }
-    
-/*
-    if (plusCounter == 1) { // if we have received the first 'bun'
-      testChar = inChar;   // this might be the 'patty', stop laughing
-      plusCounter++;       // get ready to look for another 'bun'
-      commandTimer = millis();  // don't wait too long!
-    }
-
-    if (inChar == '+') { // if we see a 'bun' on the serial
-      plusCounter++;    // make a note of it
-      if (plusCounter == 3) { // looks like we got a command character
-        if (millis() - commandTimer < 5) { // if it's not too late,
-          if (getChannelSettings) { // if we just got an 'x' expect channel setting parameters
-            loadChannelSettings(testChar);  // go get em!
-          } else if (getLeadOffSettings) { // if we just got a 'z' expect lead-off setting parameters
-            loadLeadOffSettings(testChar); // go get em!
-          } else {
-            getCommand(testChar);    // decode the command
-          }
-        }
-        plusCounter = 0;  // get ready for the next one
-      }
-    }
-*/
-  }
-}
-
+  if (board.streaming) {
+    if (board.channelDataAvailable) {
+      // Read from the ADS(s), store data, set channelDataAvailable flag to false
+      board.updateChannelData();
 
-void getCommand(char token) {
-  switch (token) {
-    //TURN CHANNELS ON/OFF COMMANDS
-    case '1':
-      changeChannelState_maintainRunningState(1, DEACTIVATE); break;
-    case '2':
-      changeChannelState_maintainRunningState(2, DEACTIVATE); break;
-    case '3':
-      changeChannelState_maintainRunningState(3, DEACTIVATE); break;
-    case '4':
-      changeChannelState_maintainRunningState(4, DEACTIVATE); break;
-    case '5':
-      changeChannelState_maintainRunningState(5, DEACTIVATE); break;
-    case '6':
-      changeChannelState_maintainRunningState(6, DEACTIVATE); break;
-    case '7':
-      changeChannelState_maintainRunningState(7, DEACTIVATE); break;
-    case '8':
-      changeChannelState_maintainRunningState(8, DEACTIVATE); break;
-    case '!':
-      changeChannelState_maintainRunningState(1, ACTIVATE); break;
-    case '@':
-      changeChannelState_maintainRunningState(2, ACTIVATE); break;
-    case '#':
-      changeChannelState_maintainRunningState(3, ACTIVATE); break;
-    case '$':
-      changeChannelState_maintainRunningState(4, ACTIVATE); break;
-    case '%':
-      changeChannelState_maintainRunningState(5, ACTIVATE); break;
-    case '^':
-      changeChannelState_maintainRunningState(6, ACTIVATE); break;
-    case '&':
-      changeChannelState_maintainRunningState(7, ACTIVATE); break;
-    case '*':
-      changeChannelState_maintainRunningState(8, ACTIVATE); break;
-    case 'q':
-      changeChannelState_maintainRunningState(9, DEACTIVATE); break;
-    case 'w':
-      changeChannelState_maintainRunningState(10, DEACTIVATE); break;
-    case 'e':
-      changeChannelState_maintainRunningState(11, DEACTIVATE); break;
-    case 'r':
-      changeChannelState_maintainRunningState(12, DEACTIVATE); break;
-    case 't':
-      changeChannelState_maintainRunningState(13, DEACTIVATE); break;
-    case 'y':
-      changeChannelState_maintainRunningState(14, DEACTIVATE); break;
-    case 'u':
-      changeChannelState_maintainRunningState(15, DEACTIVATE); break;
-    case 'i':
-      changeChannelState_maintainRunningState(16, DEACTIVATE); break;
-    case 'Q':
-      changeChannelState_maintainRunningState(9, ACTIVATE); break;
-    case 'W':
-      changeChannelState_maintainRunningState(10, ACTIVATE); break;
-    case 'E':
-      changeChannelState_maintainRunningState(11, ACTIVATE); break;
-    case 'R':
-      changeChannelState_maintainRunningState(12, ACTIVATE); break;
-    case 'T':
-      changeChannelState_maintainRunningState(13, ACTIVATE); break;
-    case 'Y':
-      changeChannelState_maintainRunningState(14, ACTIVATE); break;
-    case 'U':
-      changeChannelState_maintainRunningState(15, ACTIVATE); break;
-    case 'I':
-      changeChannelState_maintainRunningState(16, ACTIVATE); break;
-
-    // TEST SIGNAL CONTROL COMMANDS
-    case '0':
-      activateAllChannelsToTestCondition(ADSINPUT_SHORTED, ADSTESTSIG_NOCHANGE, ADSTESTSIG_NOCHANGE); break;
-    case '-':
-      activateAllChannelsToTestCondition(ADSINPUT_TESTSIG, ADSTESTSIG_AMP_1X, ADSTESTSIG_PULSE_SLOW); break;
-    case '=':
-      activateAllChannelsToTestCondition(ADSINPUT_TESTSIG, ADSTESTSIG_AMP_1X, ADSTESTSIG_PULSE_FAST); break;
-    case 'p':
-      activateAllChannelsToTestCondition(ADSINPUT_TESTSIG, ADSTESTSIG_AMP_2X, ADSTESTSIG_DCSIG); break;
-    case '[':
-      activateAllChannelsToTestCondition(ADSINPUT_TESTSIG, ADSTESTSIG_AMP_2X, ADSTESTSIG_PULSE_SLOW); break;
-    case ']':
-      activateAllChannelsToTestCondition(ADSINPUT_TESTSIG, ADSTESTSIG_AMP_2X, ADSTESTSIG_PULSE_FAST); break;
-
-    // SD CARD COMMANDS
-    //    5min     15min    30min    1hr      2hr      4hr      12hr     24hr    512blocks
-    case 'A': case'S': case'F': case'G': case'H': case'J': case'K': case'L': case 'a':
-      fileSize = token; SDfileOpen = setupSDcard(fileSize); //
-      break;
-    case 'j': // close the file, if it's open
-      if (SDfileOpen) {
-        SDfileOpen = closeSDfile();
-      }
-      break;
-
-    // CHANNEL SETTING COMMANDS
-    case 'x':  // expect 6 parameters
-      if (!is_running) {
-        Serial0.println("ready to accept new channel settings");
-      }
-      channelSettingsCounter = 0;
-      getChannelSettings = true; break;
-    case 'X':  // latch channel settings
-      if (!is_running) {
-        Serial0.println("updating channel settings");
-      }
-      writeChannelSettings_maintainRunningState(currentChannelToSet); break;
-    case 'd':  // reset all channel settings to default
-      if (!is_running) {
-        Serial0.println("updating channel settings to default");
-      }
-      setChannelsToDefaultSetting(); break;
-    case 'D':  // report the default settings
-      sendDefaultChannelSettings(); break;
-
-    // LEAD OFF IMPEDANCE DETECTION COMMANDS
-    case 'z':  // expect 2 parameters
-      if (!is_running) {
-        Serial0.println("ready to accept new impedance detect settings");
-      }
-      leadOffSettingsCounter = 0;  // reset counter
-      getLeadOffSettings = true;
-      break;
-    case 'Z':  // latch impedance parameters
-      if (!is_running) {
-        Serial0.println("updating impedance detect settings");
-      }
-      changeChannelLeadOffDetect_maintainRunningState(currentChannelToSet);
-      break;
-
-    // DAISY MODULE COMMANDS
-    case 'c':  // use 8 channel mode
-      if (OBCI.daisyPresent) {
-        OBCI.removeDaisy();
-      }
-      outputType = OUTPUT_8_CHAN;
-      break;
-    case 'C':  // use 16 channel mode
-      if (OBCI.daisyPresent == false) {
-        OBCI.attachDaisy();
-      }
-      if (OBCI.daisyPresent) {
-        Serial0.print("16"); outputType = OUTPUT_16_CHAN;
+      if (board.timeSynced) {
+        // Send time synced packet with channel data, current board time, and an accel reading
+        //  X axis is sent on sampleCounter % 10 == 7
+        //  Y axis is sent on sampleCounter % 10 == 8
+        //  Z axis is sent on sampleCounter % 10 == 9
+        board.sendChannelDataWithTimeAndAccel();
       } else {
-        Serial0.print("8"); outputType = OUTPUT_8_CHAN;
-      }
-      sendEOT();
-      break;
-
-    // STREAM DATA AND FILTER COMMANDS
-    case 'b':  // stream data
-      if (SDfileOpen) stampSD(ACTIVATE);                    // time stamp the start time
-      if (OBCI.useAccel) {
-        OBCI.enable_accel(RATE_25HZ); // fire up the accelerometer if you want it
-      }
-      startRunning(outputType);                             // turn on the fire hose
-      break;
-    case 's':  // stop streaming data
-      if (SDfileOpen) stampSD(DEACTIVATE);      // time stamp the stop time
-      if (OBCI.useAccel) {
-        OBCI.disable_accel(); // shut down the accelerometer if you're using it
+        // Send standard packet with channel data
+        board.sendChannelDataWithAccel();
       }
-      stopRunning();
-      break;
-    case 'f':
-      useFilters = true;
-      break;
-    case 'g':
-      useFilters = false;
-      break;
-
-    //  INITIALIZE AND VERIFY
-    case 'v':
-      startFromScratch();  // initialize ADS and read device IDs
-      break;
-    //  QUERY THE ADS AND ACCEL REGITSTERS
-    case '?':
-      printRegisters();     // print the ADS and accelerometer register values
-      break;
-    default:
-      break;
-  }
-}// end of getCommand
-
-void sendEOT() {
-  Serial0.print("$$$");  // shake hands with the controlling program
-}
-
-void loadChannelSettings(char c) {
-
-  if (channelSettingsCounter == 0) { // if it's the first byte in this channel's array, this byte is the channel number to set
-    currentChannelToSet = getChannelNumber(c); // we just got the channel to load settings into (shift number down for array usage)
-    channelSettingsCounter++;
-    if (!is_running) {
-      Serial0.print("load setting ");
-      Serial0.print("for channel ");
-      Serial0.println(currentChannelToSet + 1, DEC);
+      /*
+      if (board.timeSynced) {
+        board.sendChannelDataWithTimeAndRawAux();
+      } else {
+        // Send standard packet with channel data
+        board.sendChannelDataWithRawAux();
+      }
+      */
     }
-    return;
-  }
-  //  setting bytes are in order: POWER_DOWN, GAIN_SET, INPUT_TYPE_SET, BIAS_SET, SRB2_SET, SRB1_SET
-  if (!is_running) {
-    Serial0.print(channelSettingsCounter - 1);
-    Serial0.print(" with "); Serial0.println(c);
-  }
-  c -= '0';
-  if (channelSettingsCounter - 1 == GAIN_SET) {
-    c <<= 4;
-  }
-  OBCI.channelSettings[currentChannelToSet][channelSettingsCounter - 1] = c;
-  channelSettingsCounter++;
-  if (channelSettingsCounter == 7) { // 1 currentChannelToSet, plus 6 channelSetting parameters
-    if (!is_running) Serial0.print("done receiving settings for channel "); Serial0.println(currentChannelToSet + 1, DEC);
-    getChannelSettings = false;
-  }
-}
-
-void writeChannelSettings_maintainRunningState(char chan) {
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-  stopRunning();                   //must stop running to change channel settings
-
-  OBCI.writeChannelSettings(chan + 1);  // change the channel settings on ADS
-
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);  //restart, if it was running before
-  }
-}
-
-void setChannelsToDefaultSetting() {
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-  stopRunning();  //must stop running to change channel settings
-
-  OBCI.setChannelsToDefault();   // default channel settings
-
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);  //restart, if it was running before
-  }
-}
-
-void loadLeadOffSettings(char c) {
-  if (leadOffSettingsCounter == 0) { // if it's the first byte in this channel's array, this byte is the channel number to set
-    currentChannelToSet = getChannelNumber(c); // we just got the channel to load settings into (shift number down for array usage)
-    if (!is_running) Serial0.print("changing LeadOff settings for channel "); Serial0.println(currentChannelToSet + 1, DEC);
-    leadOffSettingsCounter++;
-    return;
-  }
-  //  setting bytes are in order: PCHAN, NCHAN
-  if (!is_running) {
-    Serial0.print("load setting "); Serial0.print(leadOffSettingsCounter - 1);
-    Serial0.print(" with "); Serial0.println(c);
-  }
-  c -= '0';
-  OBCI.leadOffSettings[currentChannelToSet][leadOffSettingsCounter - 1] = c;
-  leadOffSettingsCounter++;
-  if (leadOffSettingsCounter == 3) { // 1 currentChannelToSet, plus 2 leadOff setting parameters
-    if (!is_running) Serial0.print("done receiving leadOff settings for channel "); Serial0.println(currentChannelToSet + 1, DEC);
-    getLeadOffSettings = false; // release the serial COM
-  }
-}
-
-char getChannelNumber(char n) {
-  if (n > '0' && n < '9') {
-    n -= '1';
   }
-  switch (n) {
-    case 'Q':
-      n = 0x08; break;
-    case 'W':
-      n = 0x09; break;
-    case 'E':
-      n = 0x0A; break;
-    case 'R':
-      n = 0x0B; break;
-    case 'T':
-      n = 0x0C; break;
-    case 'Y':
-      n = 0x0D; break;
-    case 'U':
-      n = 0x0E; break;
-    case 'I':
-      n = 0x0F; break;
-    default: break;
-  }
-  return n;
-}
-
-void changeChannelState_maintainRunningState(byte chan, int start)
-{
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-
-  //must stop running to change channel settings
-  stopRunning();
-  if (start == 1) {
-    OBCI.activateChannel(chan);
-  } else if (start == 0) {
-    OBCI.deactivateChannel(chan);
-  }
-  //restart, if it was running before
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);
-  }
-}
-
-void activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode)
-{
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-  //must stop running to change channel settings
-  stopRunning(); delay(10);
-
-  //set the test signal to the desired state
-  OBCI.configureInternalTestSignal(amplitudeCode, freqCode);
-  //change input type settings for all channels
-  OBCI.changeInputType(testInputCode);
-
-  //restart, if it was running before
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);
-  }
-}
-
-int changeChannelLeadOffDetect_maintainRunningState(char chan)
-{
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-
-  //must stop running to change channel settings
-  stopRunning();
-
-  OBCI.changeChannelLeadOffDetect(chan);
-
-  //restart, if it was running before
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);
-  }
-}
-
-void sendDefaultChannelSettings() {
-  boolean is_running_when_called = is_running;
-  int cur_outputType = outputType;
-
-  OBCI.reportDefaultChannelSettings();
-  sendEOT();
-  delay(10);
-
-  //restart, if it was running before
-  if (is_running_when_called == true) {
-    startRunning(cur_outputType);
-  }
-}
-
-boolean stopRunning(void) {
-  if (is_running) {
-    OBCI.stopStreaming();  // stop the data acquisition, turn off accelerometer
-    is_running = false;
-  }
-  return is_running;
-}
-
-boolean startRunning(int OUT_TYPE) {
-  if (!is_running) {
-    outputType = OUT_TYPE;
-    OBCI.startStreaming();  // start the data acquisition, turn on accelerometer
-    is_running = true;
-  }
-  return is_running;
-}
-
-void printRegisters() {
-
-  if (!is_running) {
-    // print the ADS and LIS3DH registers
-    OBCI.printAllRegisters();
-    sendEOT();
-    delay(20);
-  }
-
-}
-
-void startFromScratch() {
-  if (!is_running) {
-    OBCI.initialize();     // initializes accelerometer and on-board ADS and on-daisy ADS if present
-    delay(500);
-    Serial0.println("OpenBCI V3 16 channel");
-    OBCI.configureLeadOffDetection(LOFF_MAG_6NA, LOFF_FREQ_31p2HZ);
-    Serial0.print("On Board ADS1299 Device ID: 0x"); Serial0.println(OBCI.ADS_getDeviceID(ON_BOARD), HEX);
-    if (OBCI.daisyPresent) { // library will set this in initialize() if daisy present and functional
-      Serial0.print("On Daisy ADS1299 Device ID: 0x"); Serial0.println(OBCI.ADS_getDeviceID(ON_DAISY), HEX);
-    }
-    Serial0.print("LIS3DH Device ID: 0x"); Serial0.println(OBCI.LIS3DH_getDeviceID(), HEX);
-    sendEOT();
+  // Check the serial port for new data
+  if (board.hasDataSerial0()) {
+    // Read one char and process it
+    board.processChar(board.getCharSerial0());
   }
 }
 
 
 
 int main() 
-{
+{  
   setup();
 
   while (1) loop();