OpenBCI 32bit board variation with STM32L476 mircocontroller and mbed support

Dependencies:   mbed

Committer:
akpc806a
Date:
Sun Jan 22 04:10:11 2017 +0000
Revision:
1:4683702d7ad8
OpenBCI 32bit board variation with STM32L476 mircocontroller and mbed support. Version V2 of firmware, forked from the same official version for the PIC32 board.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akpc806a 1:4683702d7ad8 1 /*
akpc806a 1:4683702d7ad8 2 OpenBCI 32bit Library
akpc806a 1:4683702d7ad8 3 Place the containing folder into your libraries folder insdie the arduino folder in your Documents folder
akpc806a 1:4683702d7ad8 4
akpc806a 1:4683702d7ad8 5 This library will work with a single OpenBCI 32bit board, or
akpc806a 1:4683702d7ad8 6 an OpenBCI 32bit board with an OpenBCI Daisy Module attached.
akpc806a 1:4683702d7ad8 7
akpc806a 1:4683702d7ad8 8 */
akpc806a 1:4683702d7ad8 9
akpc806a 1:4683702d7ad8 10 #include "OpenBCI_32bit_Library.h"
akpc806a 1:4683702d7ad8 11
akpc806a 1:4683702d7ad8 12 /***************************************************/
akpc806a 1:4683702d7ad8 13 /** PUBLIC METHODS *********************************/
akpc806a 1:4683702d7ad8 14 /***************************************************/
akpc806a 1:4683702d7ad8 15 // CONSTRUCTOR
akpc806a 1:4683702d7ad8 16 OpenBCI_32bit_Library::OpenBCI_32bit_Library() {
akpc806a 1:4683702d7ad8 17 curBoardMode = OPENBCI_BOARD_MODE_DEFAULT;
akpc806a 1:4683702d7ad8 18 daisyPresent = false;
akpc806a 1:4683702d7ad8 19 sniffMode = false;
akpc806a 1:4683702d7ad8 20 useAccel = false;
akpc806a 1:4683702d7ad8 21 useAux = false;
akpc806a 1:4683702d7ad8 22 channelDataAvailable = false;
akpc806a 1:4683702d7ad8 23 initializeVariables();
akpc806a 1:4683702d7ad8 24 }
akpc806a 1:4683702d7ad8 25
akpc806a 1:4683702d7ad8 26 /**
akpc806a 1:4683702d7ad8 27 * @description: The function the OpenBCI board will call in setup.
akpc806a 1:4683702d7ad8 28 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 29 */
akpc806a 1:4683702d7ad8 30 void OpenBCI_32bit_Library::begin(void) {
akpc806a 1:4683702d7ad8 31 curBoardMode = OPENBCI_BOARD_MODE_DEFAULT;
akpc806a 1:4683702d7ad8 32 // Bring the board up
akpc806a 1:4683702d7ad8 33 boardBegin();
akpc806a 1:4683702d7ad8 34 }
akpc806a 1:4683702d7ad8 35
akpc806a 1:4683702d7ad8 36 /**
akpc806a 1:4683702d7ad8 37 * @description: The function the OpenBCI board will call in setup. Turns sniff mode
akpc806a 1:4683702d7ad8 38 * on and allows you to tap into the serial port that is broken out on the OpenBCI
akpc806a 1:4683702d7ad8 39 * 32bit board. You must alter this file:
akpc806a 1:4683702d7ad8 40 * On Mac:
akpc806a 1:4683702d7ad8 41 * `/Users/username/Documents/Arduino/hardware/chipkit-core/pic32/variants/openbci/Board_Defs.h`
akpc806a 1:4683702d7ad8 42 * On Windows:
akpc806a 1:4683702d7ad8 43 * `C:\Users\username\Documents\Arduino\hardware\chipkit-core\pic32\variants\openbci\Board_Defs.h`
akpc806a 1:4683702d7ad8 44 * Specifically lines `311` and `313` from `7` and `10` to `11` and `12` for
akpc806a 1:4683702d7ad8 45 * `_SER1_TX_PIN` and `_SER1_RX_PIN` respectively. Check out this sweet gif if
akpc806a 1:4683702d7ad8 46 * you are a visual person http://g.recordit.co/3jH01sMD6Y.gif
akpc806a 1:4683702d7ad8 47 * You will need to reflash your board! But now you can connect to pins `11`
akpc806a 1:4683702d7ad8 48 * `12` via a FTDI serial port driver, really any serial to USB driver would
akpc806a 1:4683702d7ad8 49 * work. Remember to use 3V3, 115200 baud, and have a common ground!
akpc806a 1:4683702d7ad8 50 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 51 */
akpc806a 1:4683702d7ad8 52 void OpenBCI_32bit_Library::beginDebug(void) {
akpc806a 1:4683702d7ad8 53 // Bring the board up
akpc806a 1:4683702d7ad8 54 boolean started = boardBeginDebug();
akpc806a 1:4683702d7ad8 55 curBoardMode = OPENBCI_BOARD_MODE_DEBUG;
akpc806a 1:4683702d7ad8 56
akpc806a 1:4683702d7ad8 57 sniffMode = true;
akpc806a 1:4683702d7ad8 58
akpc806a 1:4683702d7ad8 59 if (Serial1) {
akpc806a 1:4683702d7ad8 60 if (started) {
akpc806a 1:4683702d7ad8 61 Serial1.println("Board up");
akpc806a 1:4683702d7ad8 62 } else {
akpc806a 1:4683702d7ad8 63 Serial1.println("Board err");
akpc806a 1:4683702d7ad8 64 }
akpc806a 1:4683702d7ad8 65
akpc806a 1:4683702d7ad8 66 }
akpc806a 1:4683702d7ad8 67 }
akpc806a 1:4683702d7ad8 68
akpc806a 1:4683702d7ad8 69 /**
akpc806a 1:4683702d7ad8 70 * @description: The function the OpenBCI board will call in setup. This sets up the hardware serial port on D11 and D12
akpc806a 1:4683702d7ad8 71 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 72 */
akpc806a 1:4683702d7ad8 73 boolean OpenBCI_32bit_Library::beginSecondarySerial(void) {
akpc806a 1:4683702d7ad8 74 // Initalize the serial 1 port
akpc806a 1:4683702d7ad8 75 Serial1.begin(OPENBCI_BAUD_RATE);
akpc806a 1:4683702d7ad8 76 return true;
akpc806a 1:4683702d7ad8 77 }
akpc806a 1:4683702d7ad8 78
akpc806a 1:4683702d7ad8 79
akpc806a 1:4683702d7ad8 80 /**
akpc806a 1:4683702d7ad8 81 * @description Called in every `loop()` and checks `Serial0`
akpc806a 1:4683702d7ad8 82 * @returns {boolean} - `true` if there is data ready to be read
akpc806a 1:4683702d7ad8 83 */
akpc806a 1:4683702d7ad8 84 boolean OpenBCI_32bit_Library::hasDataSerial0(void) {
akpc806a 1:4683702d7ad8 85 if (Serial0.available()) {
akpc806a 1:4683702d7ad8 86 return true;
akpc806a 1:4683702d7ad8 87 } else {
akpc806a 1:4683702d7ad8 88 return false;
akpc806a 1:4683702d7ad8 89 }
akpc806a 1:4683702d7ad8 90 }
akpc806a 1:4683702d7ad8 91
akpc806a 1:4683702d7ad8 92 /**
akpc806a 1:4683702d7ad8 93 * @description Called in every `loop()` and checks `Serial0`
akpc806a 1:4683702d7ad8 94 * @returns {boolean} - `true` if there is data ready to be read
akpc806a 1:4683702d7ad8 95 */
akpc806a 1:4683702d7ad8 96 boolean OpenBCI_32bit_Library::hasDataSerial1(void) {
akpc806a 1:4683702d7ad8 97 if (Serial1.available()) {
akpc806a 1:4683702d7ad8 98 return true;
akpc806a 1:4683702d7ad8 99 } else {
akpc806a 1:4683702d7ad8 100 return false;
akpc806a 1:4683702d7ad8 101 }
akpc806a 1:4683702d7ad8 102 }
akpc806a 1:4683702d7ad8 103
akpc806a 1:4683702d7ad8 104 /**
akpc806a 1:4683702d7ad8 105 * @description Called if `hasDataSerial0` is true, returns a char from `Serial0`
akpc806a 1:4683702d7ad8 106 * @returns {char} - A char from the serial port
akpc806a 1:4683702d7ad8 107 */
akpc806a 1:4683702d7ad8 108 char OpenBCI_32bit_Library::getCharSerial0(void) {
akpc806a 1:4683702d7ad8 109 return Serial0.read();
akpc806a 1:4683702d7ad8 110 }
akpc806a 1:4683702d7ad8 111
akpc806a 1:4683702d7ad8 112 /**
akpc806a 1:4683702d7ad8 113 * @description Called if `hasDataSerial1` is true, returns a char from `Serial1`
akpc806a 1:4683702d7ad8 114 * @returns {char} - A char from the serial port
akpc806a 1:4683702d7ad8 115 */
akpc806a 1:4683702d7ad8 116 char OpenBCI_32bit_Library::getCharSerial1(void) {
akpc806a 1:4683702d7ad8 117 return Serial1.read();
akpc806a 1:4683702d7ad8 118 }
akpc806a 1:4683702d7ad8 119
akpc806a 1:4683702d7ad8 120 /**
akpc806a 1:4683702d7ad8 121 * @description If `isSerialAvailableForRead()` is `true` then this function is
akpc806a 1:4683702d7ad8 122 * called. Reads from `Serial0` first and foremost, which comes from the RFduino.
akpc806a 1:4683702d7ad8 123 * If `sniffMode` is true and `Serial0` didn't have any data, we will try to
akpc806a 1:4683702d7ad8 124 * read from `Serial1`. If both are not available then we will return a `0x00`
akpc806a 1:4683702d7ad8 125 * which is NOT a command that the system will recognize, aka this function has
akpc806a 1:4683702d7ad8 126 * many safe guards.
akpc806a 1:4683702d7ad8 127 * @returns {char} - The character from the serial port.
akpc806a 1:4683702d7ad8 128 */
akpc806a 1:4683702d7ad8 129 // char OpenBCI_32bit_Library::readOneSerialChar(void) {
akpc806a 1:4683702d7ad8 130 // if (Serial0.available()) {
akpc806a 1:4683702d7ad8 131 // return Serial0.read();
akpc806a 1:4683702d7ad8 132 // } else if (sniffMode && Serial1.available()) {
akpc806a 1:4683702d7ad8 133 // return Serial1.read();
akpc806a 1:4683702d7ad8 134 // } else {
akpc806a 1:4683702d7ad8 135 // return 0x00;
akpc806a 1:4683702d7ad8 136 // }
akpc806a 1:4683702d7ad8 137 // }
akpc806a 1:4683702d7ad8 138
akpc806a 1:4683702d7ad8 139 /**
akpc806a 1:4683702d7ad8 140 * @description Public function for sending data to the PC
akpc806a 1:4683702d7ad8 141 * @param data {char *} - The data you want to send
akpc806a 1:4683702d7ad8 142 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 143 */
akpc806a 1:4683702d7ad8 144 void OpenBCI_32bit_Library::writeSerial(char *data, int len) {
akpc806a 1:4683702d7ad8 145 for (int i = 0; i < len; i++) {
akpc806a 1:4683702d7ad8 146 Serial0.write(data[i]);
akpc806a 1:4683702d7ad8 147 }
akpc806a 1:4683702d7ad8 148 }
akpc806a 1:4683702d7ad8 149
akpc806a 1:4683702d7ad8 150 /**
akpc806a 1:4683702d7ad8 151 * @description While processing incoming multi byte messages these will turn
akpc806a 1:4683702d7ad8 152 * true.
akpc806a 1:4683702d7ad8 153 * @return {boolean} - True if processing a message and false otherwise
akpc806a 1:4683702d7ad8 154 */
akpc806a 1:4683702d7ad8 155 boolean OpenBCI_32bit_Library::isProcessingMultibyteMsg(void) {
akpc806a 1:4683702d7ad8 156 return isProcessingIncomingSettingsChannel || isProcessingIncomingSettingsLeadOff || settingBoardMode;
akpc806a 1:4683702d7ad8 157 }
akpc806a 1:4683702d7ad8 158
akpc806a 1:4683702d7ad8 159 /**
akpc806a 1:4683702d7ad8 160 * @description Process one char at a time from serial port. This is the main
akpc806a 1:4683702d7ad8 161 * command processor for the OpenBCI system. Considered mission critical for
akpc806a 1:4683702d7ad8 162 * normal operation.
akpc806a 1:4683702d7ad8 163 * @param `character` {char} - The character to process.
akpc806a 1:4683702d7ad8 164 * @return {boolean} - `true` if the command was recognized, `false` if not
akpc806a 1:4683702d7ad8 165 */
akpc806a 1:4683702d7ad8 166 boolean OpenBCI_32bit_Library::processChar(char character) {
akpc806a 1:4683702d7ad8 167 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 168 Serial1.print("pC: "); Serial1.println(character);
akpc806a 1:4683702d7ad8 169 }
akpc806a 1:4683702d7ad8 170
akpc806a 1:4683702d7ad8 171 if (isProcessingMultibyteMsg()) {
akpc806a 1:4683702d7ad8 172 if (isProcessingIncomingSettingsChannel) {
akpc806a 1:4683702d7ad8 173 processIncomingChannelSettings(character);
akpc806a 1:4683702d7ad8 174 } else if (isProcessingIncomingSettingsLeadOff) {
akpc806a 1:4683702d7ad8 175 processIncomingLeadOffSettings(character);
akpc806a 1:4683702d7ad8 176 } else if (settingBoardMode) {
akpc806a 1:4683702d7ad8 177 processIncomingBoardMode(character);
akpc806a 1:4683702d7ad8 178 }
akpc806a 1:4683702d7ad8 179 } else { // Normal...
akpc806a 1:4683702d7ad8 180 switch (character){
akpc806a 1:4683702d7ad8 181 //TURN CHANNELS ON/OFF COMMANDS
akpc806a 1:4683702d7ad8 182 case OPENBCI_CHANNEL_OFF_1:
akpc806a 1:4683702d7ad8 183 streamSafeChannelDeactivate(1);
akpc806a 1:4683702d7ad8 184 break;
akpc806a 1:4683702d7ad8 185 case OPENBCI_CHANNEL_OFF_2:
akpc806a 1:4683702d7ad8 186 streamSafeChannelDeactivate(2);
akpc806a 1:4683702d7ad8 187 break;
akpc806a 1:4683702d7ad8 188 case OPENBCI_CHANNEL_OFF_3:
akpc806a 1:4683702d7ad8 189 streamSafeChannelDeactivate(3);
akpc806a 1:4683702d7ad8 190 break;
akpc806a 1:4683702d7ad8 191 case OPENBCI_CHANNEL_OFF_4:
akpc806a 1:4683702d7ad8 192 streamSafeChannelDeactivate(4);
akpc806a 1:4683702d7ad8 193 break;
akpc806a 1:4683702d7ad8 194 case OPENBCI_CHANNEL_OFF_5:
akpc806a 1:4683702d7ad8 195 streamSafeChannelDeactivate(5);
akpc806a 1:4683702d7ad8 196 break;
akpc806a 1:4683702d7ad8 197 case OPENBCI_CHANNEL_OFF_6:
akpc806a 1:4683702d7ad8 198 streamSafeChannelDeactivate(6);
akpc806a 1:4683702d7ad8 199 break;
akpc806a 1:4683702d7ad8 200 case OPENBCI_CHANNEL_OFF_7:
akpc806a 1:4683702d7ad8 201 streamSafeChannelDeactivate(7);
akpc806a 1:4683702d7ad8 202 break;
akpc806a 1:4683702d7ad8 203 case OPENBCI_CHANNEL_OFF_8:
akpc806a 1:4683702d7ad8 204 streamSafeChannelDeactivate(8);
akpc806a 1:4683702d7ad8 205 break;
akpc806a 1:4683702d7ad8 206 case OPENBCI_CHANNEL_OFF_9:
akpc806a 1:4683702d7ad8 207 streamSafeChannelDeactivate(9);
akpc806a 1:4683702d7ad8 208 break;
akpc806a 1:4683702d7ad8 209 case OPENBCI_CHANNEL_OFF_10:
akpc806a 1:4683702d7ad8 210 streamSafeChannelDeactivate(10);
akpc806a 1:4683702d7ad8 211 break;
akpc806a 1:4683702d7ad8 212 case OPENBCI_CHANNEL_OFF_11:
akpc806a 1:4683702d7ad8 213 streamSafeChannelDeactivate(11);
akpc806a 1:4683702d7ad8 214 break;
akpc806a 1:4683702d7ad8 215 case OPENBCI_CHANNEL_OFF_12:
akpc806a 1:4683702d7ad8 216 streamSafeChannelDeactivate(12);
akpc806a 1:4683702d7ad8 217 break;
akpc806a 1:4683702d7ad8 218 case OPENBCI_CHANNEL_OFF_13:
akpc806a 1:4683702d7ad8 219 streamSafeChannelDeactivate(13);
akpc806a 1:4683702d7ad8 220 break;
akpc806a 1:4683702d7ad8 221 case OPENBCI_CHANNEL_OFF_14:
akpc806a 1:4683702d7ad8 222 streamSafeChannelDeactivate(14);
akpc806a 1:4683702d7ad8 223 break;
akpc806a 1:4683702d7ad8 224 case OPENBCI_CHANNEL_OFF_15:
akpc806a 1:4683702d7ad8 225 streamSafeChannelDeactivate(15);
akpc806a 1:4683702d7ad8 226 break;
akpc806a 1:4683702d7ad8 227 case OPENBCI_CHANNEL_OFF_16:
akpc806a 1:4683702d7ad8 228 streamSafeChannelDeactivate(16);
akpc806a 1:4683702d7ad8 229 break;
akpc806a 1:4683702d7ad8 230
akpc806a 1:4683702d7ad8 231 case OPENBCI_CHANNEL_ON_1:
akpc806a 1:4683702d7ad8 232 streamSafeChannelActivate(1);
akpc806a 1:4683702d7ad8 233 break;
akpc806a 1:4683702d7ad8 234 case OPENBCI_CHANNEL_ON_2:
akpc806a 1:4683702d7ad8 235 streamSafeChannelActivate(2);
akpc806a 1:4683702d7ad8 236 break;
akpc806a 1:4683702d7ad8 237 case OPENBCI_CHANNEL_ON_3:
akpc806a 1:4683702d7ad8 238 streamSafeChannelActivate(3);
akpc806a 1:4683702d7ad8 239 break;
akpc806a 1:4683702d7ad8 240 case OPENBCI_CHANNEL_ON_4:
akpc806a 1:4683702d7ad8 241 streamSafeChannelActivate(4);
akpc806a 1:4683702d7ad8 242 break;
akpc806a 1:4683702d7ad8 243 case OPENBCI_CHANNEL_ON_5:
akpc806a 1:4683702d7ad8 244 streamSafeChannelActivate(5);
akpc806a 1:4683702d7ad8 245 break;
akpc806a 1:4683702d7ad8 246 case OPENBCI_CHANNEL_ON_6:
akpc806a 1:4683702d7ad8 247 streamSafeChannelActivate(6);
akpc806a 1:4683702d7ad8 248 break;
akpc806a 1:4683702d7ad8 249 case OPENBCI_CHANNEL_ON_7:
akpc806a 1:4683702d7ad8 250 streamSafeChannelActivate(7);
akpc806a 1:4683702d7ad8 251 break;
akpc806a 1:4683702d7ad8 252 case OPENBCI_CHANNEL_ON_8:
akpc806a 1:4683702d7ad8 253 streamSafeChannelActivate(8);
akpc806a 1:4683702d7ad8 254 break;
akpc806a 1:4683702d7ad8 255 case OPENBCI_CHANNEL_ON_9:
akpc806a 1:4683702d7ad8 256 streamSafeChannelActivate(9);
akpc806a 1:4683702d7ad8 257 break;
akpc806a 1:4683702d7ad8 258 case OPENBCI_CHANNEL_ON_10:
akpc806a 1:4683702d7ad8 259 streamSafeChannelActivate(10);
akpc806a 1:4683702d7ad8 260 break;
akpc806a 1:4683702d7ad8 261 case OPENBCI_CHANNEL_ON_11:
akpc806a 1:4683702d7ad8 262 streamSafeChannelActivate(11);
akpc806a 1:4683702d7ad8 263 break;
akpc806a 1:4683702d7ad8 264 case OPENBCI_CHANNEL_ON_12:
akpc806a 1:4683702d7ad8 265 streamSafeChannelActivate(12);
akpc806a 1:4683702d7ad8 266 break;
akpc806a 1:4683702d7ad8 267 case OPENBCI_CHANNEL_ON_13:
akpc806a 1:4683702d7ad8 268 streamSafeChannelActivate(13);
akpc806a 1:4683702d7ad8 269 break;
akpc806a 1:4683702d7ad8 270 case OPENBCI_CHANNEL_ON_14:
akpc806a 1:4683702d7ad8 271 streamSafeChannelActivate(14);
akpc806a 1:4683702d7ad8 272 break;
akpc806a 1:4683702d7ad8 273 case OPENBCI_CHANNEL_ON_15:
akpc806a 1:4683702d7ad8 274 streamSafeChannelActivate(15);
akpc806a 1:4683702d7ad8 275 break;
akpc806a 1:4683702d7ad8 276 case OPENBCI_CHANNEL_ON_16:
akpc806a 1:4683702d7ad8 277 streamSafeChannelActivate(16);
akpc806a 1:4683702d7ad8 278 break;
akpc806a 1:4683702d7ad8 279
akpc806a 1:4683702d7ad8 280 // TEST SIGNAL CONTROL COMMANDS
akpc806a 1:4683702d7ad8 281 case OPENBCI_TEST_SIGNAL_CONNECT_TO_GROUND:
akpc806a 1:4683702d7ad8 282 activateAllChannelsToTestCondition(ADSINPUT_SHORTED,ADSTESTSIG_NOCHANGE,ADSTESTSIG_NOCHANGE);
akpc806a 1:4683702d7ad8 283 break;
akpc806a 1:4683702d7ad8 284 case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_SLOW:
akpc806a 1:4683702d7ad8 285 activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_SLOW);
akpc806a 1:4683702d7ad8 286 break;
akpc806a 1:4683702d7ad8 287 case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_1X_FAST:
akpc806a 1:4683702d7ad8 288 activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_FAST);
akpc806a 1:4683702d7ad8 289 break;
akpc806a 1:4683702d7ad8 290 case OPENBCI_TEST_SIGNAL_CONNECT_TO_DC:
akpc806a 1:4683702d7ad8 291 activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_DCSIG);
akpc806a 1:4683702d7ad8 292 break;
akpc806a 1:4683702d7ad8 293 case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_SLOW:
akpc806a 1:4683702d7ad8 294 activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_SLOW);
akpc806a 1:4683702d7ad8 295 break;
akpc806a 1:4683702d7ad8 296 case OPENBCI_TEST_SIGNAL_CONNECT_TO_PULSE_2X_FAST:
akpc806a 1:4683702d7ad8 297 activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_FAST);
akpc806a 1:4683702d7ad8 298 break;
akpc806a 1:4683702d7ad8 299
akpc806a 1:4683702d7ad8 300
akpc806a 1:4683702d7ad8 301 // CHANNEL SETTING COMMANDS
akpc806a 1:4683702d7ad8 302 case OPENBCI_CHANNEL_CMD_SET: // This is the first byte that tells us to expect more commands
akpc806a 1:4683702d7ad8 303 isProcessingIncomingSettingsChannel = true;
akpc806a 1:4683702d7ad8 304 numberOfIncomingSettingsProcessedChannel = 1;
akpc806a 1:4683702d7ad8 305 break;
akpc806a 1:4683702d7ad8 306
akpc806a 1:4683702d7ad8 307 // LEAD OFF IMPEDANCE DETECTION COMMANDS
akpc806a 1:4683702d7ad8 308 case OPENBCI_CHANNEL_IMPEDANCE_SET:
akpc806a 1:4683702d7ad8 309 isProcessingIncomingSettingsLeadOff = true;
akpc806a 1:4683702d7ad8 310 numberOfIncomingSettingsProcessedLeadOff = 1;
akpc806a 1:4683702d7ad8 311 break;
akpc806a 1:4683702d7ad8 312
akpc806a 1:4683702d7ad8 313 case OPENBCI_CHANNEL_DEFAULT_ALL_SET: // reset all channel settings to default
akpc806a 1:4683702d7ad8 314 if(!streaming) {
akpc806a 1:4683702d7ad8 315 Serial0.println("updating channel settings to default");
akpc806a 1:4683702d7ad8 316 sendEOT();
akpc806a 1:4683702d7ad8 317 }
akpc806a 1:4683702d7ad8 318 streamSafeSetAllChannelsToDefault();
akpc806a 1:4683702d7ad8 319 break;
akpc806a 1:4683702d7ad8 320 case OPENBCI_CHANNEL_DEFAULT_ALL_REPORT: // report the default settings
akpc806a 1:4683702d7ad8 321 reportDefaultChannelSettings();
akpc806a 1:4683702d7ad8 322 break;
akpc806a 1:4683702d7ad8 323
akpc806a 1:4683702d7ad8 324
akpc806a 1:4683702d7ad8 325
akpc806a 1:4683702d7ad8 326 // DAISY MODULE COMMANDS
akpc806a 1:4683702d7ad8 327 case OPENBCI_CHANNEL_MAX_NUMBER_8: // use 8 channel mode
akpc806a 1:4683702d7ad8 328 if(daisyPresent){
akpc806a 1:4683702d7ad8 329 removeDaisy();
akpc806a 1:4683702d7ad8 330 }
akpc806a 1:4683702d7ad8 331 break;
akpc806a 1:4683702d7ad8 332 case OPENBCI_CHANNEL_MAX_NUMBER_16: // use 16 channel mode
akpc806a 1:4683702d7ad8 333 if(daisyPresent == false){
akpc806a 1:4683702d7ad8 334 attachDaisy();
akpc806a 1:4683702d7ad8 335 }
akpc806a 1:4683702d7ad8 336 if(daisyPresent){
akpc806a 1:4683702d7ad8 337 Serial0.print("16");
akpc806a 1:4683702d7ad8 338 }else{
akpc806a 1:4683702d7ad8 339 Serial0.print("8");
akpc806a 1:4683702d7ad8 340 }
akpc806a 1:4683702d7ad8 341 sendEOT();
akpc806a 1:4683702d7ad8 342 break;
akpc806a 1:4683702d7ad8 343
akpc806a 1:4683702d7ad8 344 // STREAM DATA AND FILTER COMMANDS
akpc806a 1:4683702d7ad8 345 case OPENBCI_STREAM_START: // stream data
akpc806a 1:4683702d7ad8 346 if(useAccel){
akpc806a 1:4683702d7ad8 347 enable_accel(RATE_25HZ);
akpc806a 1:4683702d7ad8 348 } // fire up the accelerometer if you want it
akpc806a 1:4683702d7ad8 349 streamStart(); // turn on the fire hose
akpc806a 1:4683702d7ad8 350 break;
akpc806a 1:4683702d7ad8 351 case OPENBCI_STREAM_STOP: // stop streaming data
akpc806a 1:4683702d7ad8 352 if(useAccel){
akpc806a 1:4683702d7ad8 353 disable_accel();
akpc806a 1:4683702d7ad8 354 } // shut down the accelerometer if you're using it
akpc806a 1:4683702d7ad8 355 streamStop();
akpc806a 1:4683702d7ad8 356 break;
akpc806a 1:4683702d7ad8 357
akpc806a 1:4683702d7ad8 358 // INITIALIZE AND VERIFY
akpc806a 1:4683702d7ad8 359 case OPENBCI_MISC_SOFT_RESET:
akpc806a 1:4683702d7ad8 360 boardReset(); // initialize ADS and read device IDs
akpc806a 1:4683702d7ad8 361 break;
akpc806a 1:4683702d7ad8 362 // QUERY THE ADS AND ACCEL REGITSTERS
akpc806a 1:4683702d7ad8 363 case OPENBCI_MISC_QUERY_REGISTER_SETTINGS:
akpc806a 1:4683702d7ad8 364 if (!streaming) {
akpc806a 1:4683702d7ad8 365 printAllRegisters(); // print the ADS and accelerometer register values
akpc806a 1:4683702d7ad8 366 }
akpc806a 1:4683702d7ad8 367 break;
akpc806a 1:4683702d7ad8 368
akpc806a 1:4683702d7ad8 369 // TIME SYNC
akpc806a 1:4683702d7ad8 370 case OPENBCI_TIME_SET:
akpc806a 1:4683702d7ad8 371 // Set flag to send time packet
akpc806a 1:4683702d7ad8 372 if (streaming) {
akpc806a 1:4683702d7ad8 373 sendTimeSyncUpPacket = true;
akpc806a 1:4683702d7ad8 374 } else {
akpc806a 1:4683702d7ad8 375 Serial0.print("Time stamp ON");
akpc806a 1:4683702d7ad8 376 sendEOT();
akpc806a 1:4683702d7ad8 377 }
akpc806a 1:4683702d7ad8 378 timeSynced = true;
akpc806a 1:4683702d7ad8 379 break;
akpc806a 1:4683702d7ad8 380
akpc806a 1:4683702d7ad8 381 case OPENBCI_TIME_STOP:
akpc806a 1:4683702d7ad8 382 // Stop the Sync
akpc806a 1:4683702d7ad8 383 timeSynced = false;
akpc806a 1:4683702d7ad8 384 if (!streaming) {
akpc806a 1:4683702d7ad8 385 Serial0.print("Time stamp OFF");
akpc806a 1:4683702d7ad8 386 sendEOT();
akpc806a 1:4683702d7ad8 387 }
akpc806a 1:4683702d7ad8 388 break;
akpc806a 1:4683702d7ad8 389
akpc806a 1:4683702d7ad8 390 // PACKET SET TYPE
akpc806a 1:4683702d7ad8 391 case OPENBCI_BOARD_MODE_SET:
akpc806a 1:4683702d7ad8 392 // Tell this function which case that is
akpc806a 1:4683702d7ad8 393 settingBoardMode = true;
akpc806a 1:4683702d7ad8 394 break;
akpc806a 1:4683702d7ad8 395
akpc806a 1:4683702d7ad8 396 default:
akpc806a 1:4683702d7ad8 397 return false;
akpc806a 1:4683702d7ad8 398 }
akpc806a 1:4683702d7ad8 399 }
akpc806a 1:4683702d7ad8 400 return true;
akpc806a 1:4683702d7ad8 401 }
akpc806a 1:4683702d7ad8 402
akpc806a 1:4683702d7ad8 403 /**
akpc806a 1:4683702d7ad8 404 * @description Reads a status register to see if there is new accelerometer
akpc806a 1:4683702d7ad8 405 * data.
akpc806a 1:4683702d7ad8 406 * @returns {boolean} `true` if the accelerometer has new data.
akpc806a 1:4683702d7ad8 407 */
akpc806a 1:4683702d7ad8 408 boolean OpenBCI_32bit_Library::accelHasNewData(void) {
akpc806a 1:4683702d7ad8 409 return LIS3DH_DataAvailable();
akpc806a 1:4683702d7ad8 410 }
akpc806a 1:4683702d7ad8 411
akpc806a 1:4683702d7ad8 412 /**
akpc806a 1:4683702d7ad8 413 * @description Reads from the accelerometer to get new X, Y, and Z data. Updates
akpc806a 1:4683702d7ad8 414 * the global array `axisData`.
akpc806a 1:4683702d7ad8 415 */
akpc806a 1:4683702d7ad8 416 void OpenBCI_32bit_Library::accelUpdateAxisData(void) {
akpc806a 1:4683702d7ad8 417 LIS3DH_updateAxisData();
akpc806a 1:4683702d7ad8 418 }
akpc806a 1:4683702d7ad8 419
akpc806a 1:4683702d7ad8 420 /**
akpc806a 1:4683702d7ad8 421 * @description Reads from the accelerometer to get new X, Y, and Z data.
akpc806a 1:4683702d7ad8 422 */
akpc806a 1:4683702d7ad8 423 void OpenBCI_32bit_Library::accelWriteAxisData(void) {
akpc806a 1:4683702d7ad8 424 LIS3DH_writeAxisData();
akpc806a 1:4683702d7ad8 425 }
akpc806a 1:4683702d7ad8 426
akpc806a 1:4683702d7ad8 427 /**
akpc806a 1:4683702d7ad8 428 * @description: This is a function that is called once and confiures all pins on
akpc806a 1:4683702d7ad8 429 * the PIC32 uC
akpc806a 1:4683702d7ad8 430 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 431 */
akpc806a 1:4683702d7ad8 432 boolean OpenBCI_32bit_Library::boardBegin(void) {
akpc806a 1:4683702d7ad8 433 // Initalize the serial port baud rate
akpc806a 1:4683702d7ad8 434 Serial0.begin(OPENBCI_BAUD_RATE);
akpc806a 1:4683702d7ad8 435
akpc806a 1:4683702d7ad8 436 pinMode(OPENBCI_PIN_LED, OUTPUT);
akpc806a 1:4683702d7ad8 437 pinMode(OPENBCI_PIN_PGC, OUTPUT);
akpc806a 1:4683702d7ad8 438
akpc806a 1:4683702d7ad8 439 // Startup for interrupt
akpc806a 1:4683702d7ad8 440 setIntVector(_EXTERNAL_4_VECTOR, ADS_DRDY_Service); // connect interrupt to ISR
akpc806a 1:4683702d7ad8 441 setIntPriority(_EXTERNAL_4_VECTOR, 4, 0); // set interrupt priority and sub priority
akpc806a 1:4683702d7ad8 442 clearIntFlag(_EXTERNAL_4_IRQ); // these two need to be done together
akpc806a 1:4683702d7ad8 443 setIntEnable(_EXTERNAL_4_IRQ); // clear any flags before enabing the irq
akpc806a 1:4683702d7ad8 444
akpc806a 1:4683702d7ad8 445 // Do a soft reset
akpc806a 1:4683702d7ad8 446 boardReset();
akpc806a 1:4683702d7ad8 447
akpc806a 1:4683702d7ad8 448 return true;
akpc806a 1:4683702d7ad8 449 }
akpc806a 1:4683702d7ad8 450
akpc806a 1:4683702d7ad8 451 /**
akpc806a 1:4683702d7ad8 452 * @description: This is a function that is called once and confiures all pins on
akpc806a 1:4683702d7ad8 453 * the PIC32 uC
akpc806a 1:4683702d7ad8 454 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 455 */
akpc806a 1:4683702d7ad8 456 boolean OpenBCI_32bit_Library::boardBeginDebug(void) {
akpc806a 1:4683702d7ad8 457 // Initalize the serial port baud rate
akpc806a 1:4683702d7ad8 458 Serial0.begin(OPENBCI_BAUD_RATE);
akpc806a 1:4683702d7ad8 459
akpc806a 1:4683702d7ad8 460 // Initalize the serial debug port
akpc806a 1:4683702d7ad8 461 Serial1.begin(OPENBCI_BAUD_RATE);
akpc806a 1:4683702d7ad8 462
akpc806a 1:4683702d7ad8 463 // Startup for interrupt
akpc806a 1:4683702d7ad8 464 setIntVector(_EXTERNAL_4_VECTOR, ADS_DRDY_Service); // connect interrupt to ISR
akpc806a 1:4683702d7ad8 465 setIntPriority(_EXTERNAL_4_VECTOR, 4, 0); // set interrupt priority and sub priority
akpc806a 1:4683702d7ad8 466 clearIntFlag(_EXTERNAL_4_IRQ); // these two need to be done together
akpc806a 1:4683702d7ad8 467 setIntEnable(_EXTERNAL_4_IRQ); // clear any flags before enabing the irq
akpc806a 1:4683702d7ad8 468
akpc806a 1:4683702d7ad8 469 // Do a soft reset
akpc806a 1:4683702d7ad8 470 boardReset();
akpc806a 1:4683702d7ad8 471
akpc806a 1:4683702d7ad8 472 return true;
akpc806a 1:4683702d7ad8 473 }
akpc806a 1:4683702d7ad8 474
akpc806a 1:4683702d7ad8 475 /**
akpc806a 1:4683702d7ad8 476 * @description: This is a function that is called once and confiures the Pic to run in secondary serial mode
akpc806a 1:4683702d7ad8 477 * @param baudRate {int} - The baudRate you want the secondary serial port to run at.
akpc806a 1:4683702d7ad8 478 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 479 */
akpc806a 1:4683702d7ad8 480 boolean OpenBCI_32bit_Library::boardBeginDebug(int baudRate) {
akpc806a 1:4683702d7ad8 481 // Initalize the serial port baud rate
akpc806a 1:4683702d7ad8 482 Serial0.begin(OPENBCI_BAUD_RATE);
akpc806a 1:4683702d7ad8 483
akpc806a 1:4683702d7ad8 484 // Initalize the serial debug port
akpc806a 1:4683702d7ad8 485 Serial1.begin(baudRate);
akpc806a 1:4683702d7ad8 486
akpc806a 1:4683702d7ad8 487 // Do a soft reset
akpc806a 1:4683702d7ad8 488 boardReset();
akpc806a 1:4683702d7ad8 489
akpc806a 1:4683702d7ad8 490 return true;
akpc806a 1:4683702d7ad8 491 }
akpc806a 1:4683702d7ad8 492
akpc806a 1:4683702d7ad8 493 /**
akpc806a 1:4683702d7ad8 494 * @description: This is a function that can be called multiple times, this is
akpc806a 1:4683702d7ad8 495 * what we refer to as a `soft reset`. You will hear/see this
akpc806a 1:4683702d7ad8 496 * many times.
akpc806a 1:4683702d7ad8 497 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 498 */
akpc806a 1:4683702d7ad8 499 void OpenBCI_32bit_Library::boardReset(void) {
akpc806a 1:4683702d7ad8 500 initialize(); // initalizes accelerometer and on-board ADS and on-daisy ADS if present
akpc806a 1:4683702d7ad8 501 delay(500);
akpc806a 1:4683702d7ad8 502
akpc806a 1:4683702d7ad8 503 Serial0.println("OpenBCI V3 8-16 channel");
akpc806a 1:4683702d7ad8 504 configureLeadOffDetection(LOFF_MAG_6NA, LOFF_FREQ_31p2HZ);
akpc806a 1:4683702d7ad8 505 Serial0.print("On Board ADS1299 Device ID: 0x"); Serial0.println(ADS_getDeviceID(ON_BOARD),HEX);
akpc806a 1:4683702d7ad8 506 if(daisyPresent){ // library will set this in initialize() if daisy present and functional
akpc806a 1:4683702d7ad8 507 Serial0.print("On Daisy ADS1299 Device ID: 0x"); Serial0.println(ADS_getDeviceID(ON_DAISY),HEX);
akpc806a 1:4683702d7ad8 508 }
akpc806a 1:4683702d7ad8 509 Serial0.print("LIS3DH Device ID: 0x"); Serial0.println(LIS3DH_getDeviceID(),HEX);
akpc806a 1:4683702d7ad8 510 Serial0.println("Firmware: v2.0.0");
akpc806a 1:4683702d7ad8 511 sendEOT();
akpc806a 1:4683702d7ad8 512 }
akpc806a 1:4683702d7ad8 513
akpc806a 1:4683702d7ad8 514 /**
akpc806a 1:4683702d7ad8 515 * @description: Simple method to send the EOT over serial...
akpc806a 1:4683702d7ad8 516 * @author: AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 517 */
akpc806a 1:4683702d7ad8 518 void OpenBCI_32bit_Library::sendEOT(void) {
akpc806a 1:4683702d7ad8 519 Serial0.print("$$$");
akpc806a 1:4683702d7ad8 520 }
akpc806a 1:4683702d7ad8 521
akpc806a 1:4683702d7ad8 522
akpc806a 1:4683702d7ad8 523
akpc806a 1:4683702d7ad8 524 void OpenBCI_32bit_Library::activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode)
akpc806a 1:4683702d7ad8 525 {
akpc806a 1:4683702d7ad8 526 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 527
akpc806a 1:4683702d7ad8 528 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 529 if (streaming) {
akpc806a 1:4683702d7ad8 530 streamStop();
akpc806a 1:4683702d7ad8 531 }
akpc806a 1:4683702d7ad8 532
akpc806a 1:4683702d7ad8 533 //set the test signal to the desired state
akpc806a 1:4683702d7ad8 534 configureInternalTestSignal(amplitudeCode,freqCode);
akpc806a 1:4683702d7ad8 535 //change input type settings for all channels
akpc806a 1:4683702d7ad8 536 changeInputType(testInputCode);
akpc806a 1:4683702d7ad8 537
akpc806a 1:4683702d7ad8 538 // Restart stream if need be
akpc806a 1:4683702d7ad8 539 if (wasStreaming) {
akpc806a 1:4683702d7ad8 540 streamStart();
akpc806a 1:4683702d7ad8 541 }
akpc806a 1:4683702d7ad8 542 }
akpc806a 1:4683702d7ad8 543
akpc806a 1:4683702d7ad8 544 /**
akpc806a 1:4683702d7ad8 545 * @description When a 'z' is found on the serial port, we jump to this function
akpc806a 1:4683702d7ad8 546 * where we continue to read from the serial port and read the
akpc806a 1:4683702d7ad8 547 * remaining 4 bytes.
akpc806a 1:4683702d7ad8 548 * @param `character` - {char} - The character you want to process...
akpc806a 1:4683702d7ad8 549 */
akpc806a 1:4683702d7ad8 550 void OpenBCI_32bit_Library::processIncomingBoardMode(char c) {
akpc806a 1:4683702d7ad8 551
akpc806a 1:4683702d7ad8 552 if (isValidBoardType(c)) {
akpc806a 1:4683702d7ad8 553 curBoardMode = c;
akpc806a 1:4683702d7ad8 554 if (!streaming) {
akpc806a 1:4683702d7ad8 555 Serial0.print("Success: Board type set");
akpc806a 1:4683702d7ad8 556 sendEOT();
akpc806a 1:4683702d7ad8 557 }
akpc806a 1:4683702d7ad8 558 } else {
akpc806a 1:4683702d7ad8 559 if (!streaming) {
akpc806a 1:4683702d7ad8 560 Serial0.print("Failure: invalid board mode");
akpc806a 1:4683702d7ad8 561 sendEOT();
akpc806a 1:4683702d7ad8 562 }
akpc806a 1:4683702d7ad8 563 }
akpc806a 1:4683702d7ad8 564 settingBoardMode = false;
akpc806a 1:4683702d7ad8 565 }
akpc806a 1:4683702d7ad8 566
akpc806a 1:4683702d7ad8 567 /**
akpc806a 1:4683702d7ad8 568 * @description When a 'x' is found on the serial port, we jump to this function
akpc806a 1:4683702d7ad8 569 * where we continue to read from the serial port and read the
akpc806a 1:4683702d7ad8 570 * remaining 7 bytes.
akpc806a 1:4683702d7ad8 571 */
akpc806a 1:4683702d7ad8 572 void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) {
akpc806a 1:4683702d7ad8 573
akpc806a 1:4683702d7ad8 574 if (character == OPENBCI_CHANNEL_CMD_LATCH && numberOfIncomingSettingsProcessedChannel < OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL - 1) {
akpc806a 1:4683702d7ad8 575 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 576 numberOfIncomingSettingsProcessedChannel = 0;
akpc806a 1:4683702d7ad8 577
akpc806a 1:4683702d7ad8 578 // put flag back down
akpc806a 1:4683702d7ad8 579 isProcessingIncomingSettingsChannel = false;
akpc806a 1:4683702d7ad8 580
akpc806a 1:4683702d7ad8 581 if (!streaming) {
akpc806a 1:4683702d7ad8 582 Serial0.print("Channel setting failure: too few chars"); sendEOT();
akpc806a 1:4683702d7ad8 583 }
akpc806a 1:4683702d7ad8 584
akpc806a 1:4683702d7ad8 585 return;
akpc806a 1:4683702d7ad8 586 }
akpc806a 1:4683702d7ad8 587 switch (numberOfIncomingSettingsProcessedChannel) {
akpc806a 1:4683702d7ad8 588 case 1: // channel number
akpc806a 1:4683702d7ad8 589 currentChannelSetting = getChannelCommandForAsciiChar(character);
akpc806a 1:4683702d7ad8 590 break;
akpc806a 1:4683702d7ad8 591 case 2: // POWER_DOWN
akpc806a 1:4683702d7ad8 592 channelSettings[currentChannelSetting][POWER_DOWN] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 593 break;
akpc806a 1:4683702d7ad8 594 case 3: // GAIN_SET
akpc806a 1:4683702d7ad8 595 channelSettings[currentChannelSetting][GAIN_SET] = getGainForAsciiChar(character);
akpc806a 1:4683702d7ad8 596 break;
akpc806a 1:4683702d7ad8 597 case 4: // INPUT_TYPE_SET
akpc806a 1:4683702d7ad8 598 channelSettings[currentChannelSetting][INPUT_TYPE_SET] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 599 break;
akpc806a 1:4683702d7ad8 600 case 5: // BIAS_SET
akpc806a 1:4683702d7ad8 601 channelSettings[currentChannelSetting][BIAS_SET] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 602 break;
akpc806a 1:4683702d7ad8 603 case 6: // SRB2_SET
akpc806a 1:4683702d7ad8 604 channelSettings[currentChannelSetting][SRB2_SET] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 605 break;
akpc806a 1:4683702d7ad8 606 case 7: // SRB1_SET
akpc806a 1:4683702d7ad8 607 channelSettings[currentChannelSetting][SRB1_SET] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 608 break;
akpc806a 1:4683702d7ad8 609 case 8: // 'X' latch
akpc806a 1:4683702d7ad8 610 if (character != OPENBCI_CHANNEL_CMD_LATCH) {
akpc806a 1:4683702d7ad8 611 if (!streaming) {
akpc806a 1:4683702d7ad8 612 Serial0.print("Err: 9th char not ");
akpc806a 1:4683702d7ad8 613 Serial0.println(OPENBCI_CHANNEL_CMD_LATCH);
akpc806a 1:4683702d7ad8 614 sendEOT();
akpc806a 1:4683702d7ad8 615 }
akpc806a 1:4683702d7ad8 616 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 617 numberOfIncomingSettingsProcessedChannel = 0;
akpc806a 1:4683702d7ad8 618
akpc806a 1:4683702d7ad8 619 // put flag back down
akpc806a 1:4683702d7ad8 620 isProcessingIncomingSettingsChannel = false;
akpc806a 1:4683702d7ad8 621
akpc806a 1:4683702d7ad8 622 }
akpc806a 1:4683702d7ad8 623 break;
akpc806a 1:4683702d7ad8 624 default: // should have exited
akpc806a 1:4683702d7ad8 625 if (!streaming) {
akpc806a 1:4683702d7ad8 626 Serial0.print("Err: too many chars");
akpc806a 1:4683702d7ad8 627 sendEOT();
akpc806a 1:4683702d7ad8 628 }
akpc806a 1:4683702d7ad8 629 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 630 numberOfIncomingSettingsProcessedChannel = 0;
akpc806a 1:4683702d7ad8 631
akpc806a 1:4683702d7ad8 632 // put flag back down
akpc806a 1:4683702d7ad8 633 isProcessingIncomingSettingsChannel = false;
akpc806a 1:4683702d7ad8 634 return;
akpc806a 1:4683702d7ad8 635 }
akpc806a 1:4683702d7ad8 636
akpc806a 1:4683702d7ad8 637 // increment the number of bytes processed
akpc806a 1:4683702d7ad8 638 numberOfIncomingSettingsProcessedChannel++;
akpc806a 1:4683702d7ad8 639
akpc806a 1:4683702d7ad8 640 if (numberOfIncomingSettingsProcessedChannel == (OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL)) {
akpc806a 1:4683702d7ad8 641 // We are done processing channel settings...
akpc806a 1:4683702d7ad8 642
akpc806a 1:4683702d7ad8 643 if (!streaming) {
akpc806a 1:4683702d7ad8 644 Serial0.print("Channel set for "); Serial0.println(currentChannelSetting + 1); sendEOT();
akpc806a 1:4683702d7ad8 645 }
akpc806a 1:4683702d7ad8 646
akpc806a 1:4683702d7ad8 647 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 648 Serial1.print("Channel set for "); Serial1.println(currentChannelSetting + 1);
akpc806a 1:4683702d7ad8 649 }
akpc806a 1:4683702d7ad8 650
akpc806a 1:4683702d7ad8 651 // Set channel settings
akpc806a 1:4683702d7ad8 652 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]);
akpc806a 1:4683702d7ad8 653
akpc806a 1:4683702d7ad8 654 // Reset
akpc806a 1:4683702d7ad8 655 numberOfIncomingSettingsProcessedChannel = 0;
akpc806a 1:4683702d7ad8 656
akpc806a 1:4683702d7ad8 657 // put flag back down
akpc806a 1:4683702d7ad8 658 isProcessingIncomingSettingsChannel = false;
akpc806a 1:4683702d7ad8 659 }
akpc806a 1:4683702d7ad8 660 }
akpc806a 1:4683702d7ad8 661
akpc806a 1:4683702d7ad8 662 /**
akpc806a 1:4683702d7ad8 663 * @description When a 'z' is found on the serial port, we jump to this function
akpc806a 1:4683702d7ad8 664 * where we continue to read from the serial port and read the
akpc806a 1:4683702d7ad8 665 * remaining 4 bytes.
akpc806a 1:4683702d7ad8 666 * @param `character` - {char} - The character you want to process...
akpc806a 1:4683702d7ad8 667 */
akpc806a 1:4683702d7ad8 668 void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) {
akpc806a 1:4683702d7ad8 669
akpc806a 1:4683702d7ad8 670 if (character == OPENBCI_CHANNEL_IMPEDANCE_LATCH && numberOfIncomingSettingsProcessedLeadOff < OPENBCI_NUMBER_OF_BYTES_SETTINGS_LEAD_OFF - 1) {
akpc806a 1:4683702d7ad8 671 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 672 // reset numberOfIncomingSettingsProcessedLeadOff
akpc806a 1:4683702d7ad8 673 numberOfIncomingSettingsProcessedLeadOff = 0;
akpc806a 1:4683702d7ad8 674
akpc806a 1:4683702d7ad8 675 // put flag back down
akpc806a 1:4683702d7ad8 676 isProcessingIncomingSettingsLeadOff = false;
akpc806a 1:4683702d7ad8 677
akpc806a 1:4683702d7ad8 678 if (!streaming) {
akpc806a 1:4683702d7ad8 679 Serial0.print("Lead off failure: too few chars"); sendEOT();
akpc806a 1:4683702d7ad8 680 }
akpc806a 1:4683702d7ad8 681
akpc806a 1:4683702d7ad8 682 return;
akpc806a 1:4683702d7ad8 683 }
akpc806a 1:4683702d7ad8 684 switch (numberOfIncomingSettingsProcessedLeadOff) {
akpc806a 1:4683702d7ad8 685 case 1: // channel number
akpc806a 1:4683702d7ad8 686 currentChannelSetting = getChannelCommandForAsciiChar(character);
akpc806a 1:4683702d7ad8 687 break;
akpc806a 1:4683702d7ad8 688 case 2: // pchannel setting
akpc806a 1:4683702d7ad8 689 leadOffSettings[currentChannelSetting][PCHAN] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 690 break;
akpc806a 1:4683702d7ad8 691 case 3: // nchannel setting
akpc806a 1:4683702d7ad8 692 leadOffSettings[currentChannelSetting][NCHAN] = getNumberForAsciiChar(character);
akpc806a 1:4683702d7ad8 693 break;
akpc806a 1:4683702d7ad8 694 case 4: // 'Z' latch
akpc806a 1:4683702d7ad8 695 if (character != OPENBCI_CHANNEL_IMPEDANCE_LATCH) {
akpc806a 1:4683702d7ad8 696 if (!streaming) {
akpc806a 1:4683702d7ad8 697 Serial0.print("Err: 5th char not ");
akpc806a 1:4683702d7ad8 698 Serial0.println(OPENBCI_CHANNEL_IMPEDANCE_LATCH);
akpc806a 1:4683702d7ad8 699 sendEOT();
akpc806a 1:4683702d7ad8 700 }
akpc806a 1:4683702d7ad8 701 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 702 // reset numberOfIncomingSettingsProcessedLeadOff
akpc806a 1:4683702d7ad8 703 numberOfIncomingSettingsProcessedLeadOff = 0;
akpc806a 1:4683702d7ad8 704
akpc806a 1:4683702d7ad8 705 // put flag back down
akpc806a 1:4683702d7ad8 706 isProcessingIncomingSettingsLeadOff = false;
akpc806a 1:4683702d7ad8 707
akpc806a 1:4683702d7ad8 708 }
akpc806a 1:4683702d7ad8 709 break;
akpc806a 1:4683702d7ad8 710 default: // should have exited
akpc806a 1:4683702d7ad8 711 if (!streaming) {
akpc806a 1:4683702d7ad8 712 Serial0.print("Err: too many chars ");
akpc806a 1:4683702d7ad8 713 sendEOT();
akpc806a 1:4683702d7ad8 714 }
akpc806a 1:4683702d7ad8 715 // We failed somehow and should just abort
akpc806a 1:4683702d7ad8 716 // reset numberOfIncomingSettingsProcessedLeadOff
akpc806a 1:4683702d7ad8 717 numberOfIncomingSettingsProcessedLeadOff = 0;
akpc806a 1:4683702d7ad8 718
akpc806a 1:4683702d7ad8 719 // put flag back down
akpc806a 1:4683702d7ad8 720 isProcessingIncomingSettingsLeadOff = false;
akpc806a 1:4683702d7ad8 721 return;
akpc806a 1:4683702d7ad8 722 }
akpc806a 1:4683702d7ad8 723
akpc806a 1:4683702d7ad8 724 // increment the number of bytes processed
akpc806a 1:4683702d7ad8 725 numberOfIncomingSettingsProcessedLeadOff++;
akpc806a 1:4683702d7ad8 726
akpc806a 1:4683702d7ad8 727 if (numberOfIncomingSettingsProcessedLeadOff == (OPENBCI_NUMBER_OF_BYTES_SETTINGS_LEAD_OFF)) {
akpc806a 1:4683702d7ad8 728 // We are done processing lead off settings...
akpc806a 1:4683702d7ad8 729
akpc806a 1:4683702d7ad8 730 if (!streaming) {
akpc806a 1:4683702d7ad8 731 Serial0.print("Lead off set for "); Serial0.println(currentChannelSetting + 1); sendEOT();
akpc806a 1:4683702d7ad8 732 }
akpc806a 1:4683702d7ad8 733
akpc806a 1:4683702d7ad8 734 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 735 Serial1.print("Lead off set for "); Serial1.println(currentChannelSetting + 1);
akpc806a 1:4683702d7ad8 736 }
akpc806a 1:4683702d7ad8 737
akpc806a 1:4683702d7ad8 738 // Set lead off settings
akpc806a 1:4683702d7ad8 739 streamSafeLeadOffSetForChannel(currentChannelSetting + 1,leadOffSettings[currentChannelSetting][PCHAN],leadOffSettings[currentChannelSetting][NCHAN]);
akpc806a 1:4683702d7ad8 740
akpc806a 1:4683702d7ad8 741 // reset numberOfIncomingSettingsProcessedLeadOff
akpc806a 1:4683702d7ad8 742 numberOfIncomingSettingsProcessedLeadOff = 0;
akpc806a 1:4683702d7ad8 743
akpc806a 1:4683702d7ad8 744 // put flag back down
akpc806a 1:4683702d7ad8 745 isProcessingIncomingSettingsLeadOff = false;
akpc806a 1:4683702d7ad8 746 }
akpc806a 1:4683702d7ad8 747 }
akpc806a 1:4683702d7ad8 748
akpc806a 1:4683702d7ad8 749
akpc806a 1:4683702d7ad8 750 boolean OpenBCI_32bit_Library::isValidBoardType(char c) {
akpc806a 1:4683702d7ad8 751 switch (c) {
akpc806a 1:4683702d7ad8 752 case OPENBCI_BOARD_MODE_DEFAULT:
akpc806a 1:4683702d7ad8 753 case OPENBCI_BOARD_MODE_DEBUG:
akpc806a 1:4683702d7ad8 754 case OPENBCI_BOARD_MODE_WIFI:
akpc806a 1:4683702d7ad8 755 case OPENBCI_BOARD_MODE_INPUT_ANALOG:
akpc806a 1:4683702d7ad8 756 case OPENBCI_BOARD_MODE_INPUT_DIGITAL:
akpc806a 1:4683702d7ad8 757 return true;
akpc806a 1:4683702d7ad8 758 default:
akpc806a 1:4683702d7ad8 759 return false;
akpc806a 1:4683702d7ad8 760 }
akpc806a 1:4683702d7ad8 761 }
akpc806a 1:4683702d7ad8 762
akpc806a 1:4683702d7ad8 763
akpc806a 1:4683702d7ad8 764 // <<<<<<<<<<<<<<<<<<<<<<<<< BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 765
akpc806a 1:4683702d7ad8 766 void OpenBCI_32bit_Library::initialize(){
akpc806a 1:4683702d7ad8 767 pinMode(SD_SS,OUTPUT); digitalWrite(SD_SS,HIGH); // de-select SDcard if present
akpc806a 1:4683702d7ad8 768 pinMode(BOARD_ADS, OUTPUT); digitalWrite(BOARD_ADS,HIGH);
akpc806a 1:4683702d7ad8 769 pinMode(DAISY_ADS, OUTPUT); digitalWrite(DAISY_ADS,HIGH);
akpc806a 1:4683702d7ad8 770 pinMode(LIS3DH_SS,OUTPUT); digitalWrite(LIS3DH_SS,HIGH);
akpc806a 1:4683702d7ad8 771 spi.begin();
akpc806a 1:4683702d7ad8 772 spi.setSpeed(4000000); // use 4MHz for ADS and LIS3DH
akpc806a 1:4683702d7ad8 773 spi.setMode(DSPI_MODE0); // default to SD card mode!
akpc806a 1:4683702d7ad8 774 initialize_ads(); // hard reset ADS, set pin directions
akpc806a 1:4683702d7ad8 775 initialize_accel(SCALE_4G); // set pin directions, G scale, DRDY interrupt, power down
akpc806a 1:4683702d7ad8 776 initializeVariables();
akpc806a 1:4683702d7ad8 777 }
akpc806a 1:4683702d7ad8 778
akpc806a 1:4683702d7ad8 779 // void __USER_ISR ADS_DRDY_Service() {
akpc806a 1:4683702d7ad8 780 void __USER_ISR ADS_DRDY_Service() {
akpc806a 1:4683702d7ad8 781 clearIntFlag(_EXTERNAL_4_IRQ); // clear the irq, or else it will continually interrupt!
akpc806a 1:4683702d7ad8 782 if(bitRead(PORTA,0) == 0){
akpc806a 1:4683702d7ad8 783 board.channelDataAvailable = true;
akpc806a 1:4683702d7ad8 784 }
akpc806a 1:4683702d7ad8 785 }
akpc806a 1:4683702d7ad8 786
akpc806a 1:4683702d7ad8 787 void OpenBCI_32bit_Library::initializeVariables(void) {
akpc806a 1:4683702d7ad8 788 streaming = false;
akpc806a 1:4683702d7ad8 789 sendTimeSyncUpPacket = false;
akpc806a 1:4683702d7ad8 790 timeSynced = false;
akpc806a 1:4683702d7ad8 791 isProcessingIncomingSettingsChannel = false;
akpc806a 1:4683702d7ad8 792 isProcessingIncomingSettingsLeadOff = false;
akpc806a 1:4683702d7ad8 793 settingBoardMode = false;
akpc806a 1:4683702d7ad8 794 numberOfIncomingSettingsProcessedChannel = 0;
akpc806a 1:4683702d7ad8 795 numberOfIncomingSettingsProcessedLeadOff = 0;
akpc806a 1:4683702d7ad8 796 currentChannelSetting = 0;
akpc806a 1:4683702d7ad8 797 timeOffset = 0;
akpc806a 1:4683702d7ad8 798 timeSetCharArrived = 0;
akpc806a 1:4683702d7ad8 799 streamPacketType = (char)OPENBCI_PACKET_TYPE_V3;
akpc806a 1:4683702d7ad8 800 }
akpc806a 1:4683702d7ad8 801
akpc806a 1:4683702d7ad8 802 void OpenBCI_32bit_Library::printAllRegisters(){
akpc806a 1:4683702d7ad8 803 if(!isRunning){
akpc806a 1:4683702d7ad8 804 Serial0.println("\nBoard ADS Registers");
akpc806a 1:4683702d7ad8 805 printADSregisters(BOARD_ADS);
akpc806a 1:4683702d7ad8 806 if(daisyPresent){
akpc806a 1:4683702d7ad8 807 Serial0.println("\nDaisy ADS Registers");
akpc806a 1:4683702d7ad8 808 printADSregisters(DAISY_ADS);
akpc806a 1:4683702d7ad8 809 }
akpc806a 1:4683702d7ad8 810 Serial0.println("\nLIS3DH Registers");
akpc806a 1:4683702d7ad8 811 LIS3DH_readAllRegs();
akpc806a 1:4683702d7ad8 812 sendEOT();
akpc806a 1:4683702d7ad8 813 }
akpc806a 1:4683702d7ad8 814 }
akpc806a 1:4683702d7ad8 815
akpc806a 1:4683702d7ad8 816 /**
akpc806a 1:4683702d7ad8 817 * @description Writes channel data and `axisData` array to serial port in
akpc806a 1:4683702d7ad8 818 * the correct stream packet format.
akpc806a 1:4683702d7ad8 819 *
akpc806a 1:4683702d7ad8 820 * Adds stop byte `OPENBCI_EOP_STND_ACCEL`. See `OpenBCI_32bit_Library_Definitions.h`
akpc806a 1:4683702d7ad8 821 */
akpc806a 1:4683702d7ad8 822 void OpenBCI_32bit_Library::sendChannelDataWithAccel(void) {
akpc806a 1:4683702d7ad8 823
akpc806a 1:4683702d7ad8 824 Serial0.write(OPENBCI_SOP_SYMBOL);
akpc806a 1:4683702d7ad8 825
akpc806a 1:4683702d7ad8 826 Serial0.write(sampleCounter); // 1 byte
akpc806a 1:4683702d7ad8 827
akpc806a 1:4683702d7ad8 828 ADS_writeChannelData(); // 24 bytes
akpc806a 1:4683702d7ad8 829
akpc806a 1:4683702d7ad8 830 accelWriteAxisData(); // 6 bytes
akpc806a 1:4683702d7ad8 831
akpc806a 1:4683702d7ad8 832 Serial0.write(OPENBCI_EOP_STND_ACCEL); // 0xC0
akpc806a 1:4683702d7ad8 833
akpc806a 1:4683702d7ad8 834 sampleCounter++;
akpc806a 1:4683702d7ad8 835
akpc806a 1:4683702d7ad8 836 }
akpc806a 1:4683702d7ad8 837
akpc806a 1:4683702d7ad8 838 /**
akpc806a 1:4683702d7ad8 839 * @description Writes channel data and `auxData` array to serial port in
akpc806a 1:4683702d7ad8 840 * the correct stream packet format.
akpc806a 1:4683702d7ad8 841 *
akpc806a 1:4683702d7ad8 842 * Adds stop byte `OPENBCI_EOP_STND_RAW_AUX`. See `OpenBCI_32bit_Library_Definitions.h`
akpc806a 1:4683702d7ad8 843 */
akpc806a 1:4683702d7ad8 844 void OpenBCI_32bit_Library::sendChannelDataWithRawAux(void) {
akpc806a 1:4683702d7ad8 845
akpc806a 1:4683702d7ad8 846 Serial0.write(OPENBCI_SOP_SYMBOL);
akpc806a 1:4683702d7ad8 847
akpc806a 1:4683702d7ad8 848 Serial0.write(sampleCounter); // 1 byte
akpc806a 1:4683702d7ad8 849
akpc806a 1:4683702d7ad8 850 ADS_writeChannelData(); // 24 bytes
akpc806a 1:4683702d7ad8 851
akpc806a 1:4683702d7ad8 852 writeAuxData(); // 6 bytes
akpc806a 1:4683702d7ad8 853
akpc806a 1:4683702d7ad8 854 Serial0.write(OPENBCI_EOP_STND_RAW_AUX); // 0xC1 - 1 byte
akpc806a 1:4683702d7ad8 855
akpc806a 1:4683702d7ad8 856 sampleCounter++;
akpc806a 1:4683702d7ad8 857 }
akpc806a 1:4683702d7ad8 858
akpc806a 1:4683702d7ad8 859 /**
akpc806a 1:4683702d7ad8 860 * @description Writes channel data, `axisData` array, and 4 byte unsigned time
akpc806a 1:4683702d7ad8 861 * stamp in ms to serial port in the correct stream packet format.
akpc806a 1:4683702d7ad8 862 *
akpc806a 1:4683702d7ad8 863 * `axisData` will be split up and sent on the samples with `sampleCounter` of
akpc806a 1:4683702d7ad8 864 * 7, 8, and 9 for X, Y, and Z respectively. Driver writers parse accordingly.
akpc806a 1:4683702d7ad8 865 *
akpc806a 1:4683702d7ad8 866 * If the global variable `sendTimeSyncUpPacket` is `true` (set by `processChar`
akpc806a 1:4683702d7ad8 867 * getting a time sync set `<` command) then:
akpc806a 1:4683702d7ad8 868 * Adds stop byte `OPENBCI_EOP_ACCEL_TIME_SET` and sets `sendTimeSyncUpPacket`
akpc806a 1:4683702d7ad8 869 * to `false`.
akpc806a 1:4683702d7ad8 870 * Else if `sendTimeSyncUpPacket` is `false` then:
akpc806a 1:4683702d7ad8 871 * Adds stop byte `OPENBCI_EOP_ACCEL_TIME_SYNCED`
akpc806a 1:4683702d7ad8 872 */
akpc806a 1:4683702d7ad8 873 void OpenBCI_32bit_Library::sendChannelDataWithTimeAndAccel(void) {
akpc806a 1:4683702d7ad8 874
akpc806a 1:4683702d7ad8 875 Serial0.write(OPENBCI_SOP_SYMBOL);
akpc806a 1:4683702d7ad8 876
akpc806a 1:4683702d7ad8 877 Serial0.write(sampleCounter); // 1 byte
akpc806a 1:4683702d7ad8 878
akpc806a 1:4683702d7ad8 879 ADS_writeChannelData(); // 24 bytes
akpc806a 1:4683702d7ad8 880
akpc806a 1:4683702d7ad8 881 // send two bytes of either accel data or blank
akpc806a 1:4683702d7ad8 882 switch (sampleCounter % 10) {
akpc806a 1:4683702d7ad8 883 case ACCEL_AXIS_X: // 7
akpc806a 1:4683702d7ad8 884 LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_X);
akpc806a 1:4683702d7ad8 885 break;
akpc806a 1:4683702d7ad8 886 case ACCEL_AXIS_Y: // 8
akpc806a 1:4683702d7ad8 887 LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_Y);
akpc806a 1:4683702d7ad8 888 break;
akpc806a 1:4683702d7ad8 889 case ACCEL_AXIS_Z: // 9
akpc806a 1:4683702d7ad8 890 LIS3DH_writeAxisDataForAxis(ACCEL_AXIS_Z);
akpc806a 1:4683702d7ad8 891 break;
akpc806a 1:4683702d7ad8 892 default:
akpc806a 1:4683702d7ad8 893 Serial0.write((byte)0x00); // high byte
akpc806a 1:4683702d7ad8 894 Serial0.write((byte)0x00); // low byte
akpc806a 1:4683702d7ad8 895 break;
akpc806a 1:4683702d7ad8 896 }
akpc806a 1:4683702d7ad8 897
akpc806a 1:4683702d7ad8 898 writeTimeCurrent(); // 4 bytes
akpc806a 1:4683702d7ad8 899
akpc806a 1:4683702d7ad8 900 if (sendTimeSyncUpPacket) {
akpc806a 1:4683702d7ad8 901 sendTimeSyncUpPacket = false;
akpc806a 1:4683702d7ad8 902 Serial0.write(OPENBCI_EOP_ACCEL_TIME_SET); // 0xC3
akpc806a 1:4683702d7ad8 903 } else {
akpc806a 1:4683702d7ad8 904 Serial0.write(OPENBCI_EOP_ACCEL_TIME_SYNCED); // 0xC4
akpc806a 1:4683702d7ad8 905 }
akpc806a 1:4683702d7ad8 906
akpc806a 1:4683702d7ad8 907 sampleCounter++;
akpc806a 1:4683702d7ad8 908 }
akpc806a 1:4683702d7ad8 909
akpc806a 1:4683702d7ad8 910 /**
akpc806a 1:4683702d7ad8 911 * @description Writes channel data, `auxData[0]` 2 bytes, and 4 byte unsigned
akpc806a 1:4683702d7ad8 912 * time stamp in ms to serial port in the correct stream packet format.
akpc806a 1:4683702d7ad8 913 *
akpc806a 1:4683702d7ad8 914 * If the global variable `sendTimeSyncUpPacket` is `true` (set by `processChar`
akpc806a 1:4683702d7ad8 915 * getting a time sync set `<` command) then:
akpc806a 1:4683702d7ad8 916 * Adds stop byte `OPENBCI_EOP_RAW_AUX_TIME_SET` and sets `sendTimeSyncUpPacket`
akpc806a 1:4683702d7ad8 917 * to `false`.
akpc806a 1:4683702d7ad8 918 * Else if `sendTimeSyncUpPacket` is `false` then:
akpc806a 1:4683702d7ad8 919 * Adds stop byte `OPENBCI_EOP_RAW_AUX_TIME_SYNCED`
akpc806a 1:4683702d7ad8 920 */
akpc806a 1:4683702d7ad8 921 void OpenBCI_32bit_Library::sendChannelDataWithTimeAndRawAux(void) {
akpc806a 1:4683702d7ad8 922
akpc806a 1:4683702d7ad8 923 Serial0.print(OPENBCI_SOP_SYMBOL);
akpc806a 1:4683702d7ad8 924
akpc806a 1:4683702d7ad8 925 Serial0.write(sampleCounter); // 1 byte
akpc806a 1:4683702d7ad8 926
akpc806a 1:4683702d7ad8 927 ADS_writeChannelData(); // 24 bytes
akpc806a 1:4683702d7ad8 928
akpc806a 1:4683702d7ad8 929 Serial0.write(highByte(auxData[0])); // 2 bytes of aux data
akpc806a 1:4683702d7ad8 930 Serial0.write(lowByte(auxData[0]));
akpc806a 1:4683702d7ad8 931
akpc806a 1:4683702d7ad8 932 writeTimeCurrent(); // 4 bytes
akpc806a 1:4683702d7ad8 933
akpc806a 1:4683702d7ad8 934 if (sendTimeSyncUpPacket) {
akpc806a 1:4683702d7ad8 935 sendTimeSyncUpPacket = false;
akpc806a 1:4683702d7ad8 936 Serial0.write(OPENBCI_EOP_RAW_AUX_TIME_SET); // 0xC5
akpc806a 1:4683702d7ad8 937 } else {
akpc806a 1:4683702d7ad8 938 Serial0.write(OPENBCI_EOP_RAW_AUX_TIME_SYNCED); // 0xC6
akpc806a 1:4683702d7ad8 939 }
akpc806a 1:4683702d7ad8 940
akpc806a 1:4683702d7ad8 941 sampleCounter++;
akpc806a 1:4683702d7ad8 942
akpc806a 1:4683702d7ad8 943 }
akpc806a 1:4683702d7ad8 944
akpc806a 1:4683702d7ad8 945 /**
akpc806a 1:4683702d7ad8 946 * @description Writes channel data, aux data, and footer to serial port. This
akpc806a 1:4683702d7ad8 947 * is the old way to send channel data. Based on global variables `useAux`
akpc806a 1:4683702d7ad8 948 * and `useAccel` Must keep for portability. Will look to deprecate in 3.0.0.
akpc806a 1:4683702d7ad8 949 *
akpc806a 1:4683702d7ad8 950 * If `useAccel` is `true` then sends data from `axisData` array and sets the
akpc806a 1:4683702d7ad8 951 * contents of `axisData` to `0`.
akpc806a 1:4683702d7ad8 952 * If `useAux` is `true` then sends data from `auxData` array and sets the
akpc806a 1:4683702d7ad8 953 * contents of `auxData` to `0`.
akpc806a 1:4683702d7ad8 954 *
akpc806a 1:4683702d7ad8 955 * Adds stop byte `OPENBCI_EOP_STND_ACCEL`. See `OpenBCI_32bit_Library_Definitions.h`
akpc806a 1:4683702d7ad8 956 */
akpc806a 1:4683702d7ad8 957 void OpenBCI_32bit_Library::sendChannelData(void) {
akpc806a 1:4683702d7ad8 958
akpc806a 1:4683702d7ad8 959 Serial0.print(OPENBCI_SOP_SYMBOL);
akpc806a 1:4683702d7ad8 960
akpc806a 1:4683702d7ad8 961 Serial0.write(sampleCounter); // 1 byte
akpc806a 1:4683702d7ad8 962 ADS_writeChannelData(); // 24 bytes
akpc806a 1:4683702d7ad8 963 if(useAux){
akpc806a 1:4683702d7ad8 964 writeAuxData(); // 6 bytes of aux data
akpc806a 1:4683702d7ad8 965 } else if(useAccel){ // or
akpc806a 1:4683702d7ad8 966 LIS3DH_writeAxisData(); // 6 bytes of accelerometer data
akpc806a 1:4683702d7ad8 967 } else{
akpc806a 1:4683702d7ad8 968 for(int i=0; i<6; i++){
akpc806a 1:4683702d7ad8 969 Serial0.write((byte)0x00);
akpc806a 1:4683702d7ad8 970 }
akpc806a 1:4683702d7ad8 971 }
akpc806a 1:4683702d7ad8 972
akpc806a 1:4683702d7ad8 973 Serial0.write(OPENBCI_EOP_STND_ACCEL); // 0xF0
akpc806a 1:4683702d7ad8 974
akpc806a 1:4683702d7ad8 975 sampleCounter++;
akpc806a 1:4683702d7ad8 976 }
akpc806a 1:4683702d7ad8 977
akpc806a 1:4683702d7ad8 978 void OpenBCI_32bit_Library::writeAuxData(){
akpc806a 1:4683702d7ad8 979 for(int i=0; i<3; i++){
akpc806a 1:4683702d7ad8 980 Serial0.write(highByte(auxData[i])); // write 16 bit axis data MSB first
akpc806a 1:4683702d7ad8 981 Serial0.write(lowByte(auxData[i])); // axisData is array of type short (16bit)
akpc806a 1:4683702d7ad8 982 auxData[i] = 0; // reset auxData bytes to 0
akpc806a 1:4683702d7ad8 983 }
akpc806a 1:4683702d7ad8 984 }
akpc806a 1:4683702d7ad8 985
akpc806a 1:4683702d7ad8 986 void OpenBCI_32bit_Library::writeTimeCurrent(void) {
akpc806a 1:4683702d7ad8 987 uint32_t newTime = millis(); // serialize the number, placing the MSB in lower packets
akpc806a 1:4683702d7ad8 988 for (int j = 3; j >= 0; j--) {
akpc806a 1:4683702d7ad8 989 Serial0.write(newTime >> (j*8));
akpc806a 1:4683702d7ad8 990 }
akpc806a 1:4683702d7ad8 991 }
akpc806a 1:4683702d7ad8 992
akpc806a 1:4683702d7ad8 993 //SPI communication method
akpc806a 1:4683702d7ad8 994 byte OpenBCI_32bit_Library::xfer(byte _data)
akpc806a 1:4683702d7ad8 995 {
akpc806a 1:4683702d7ad8 996 byte inByte;
akpc806a 1:4683702d7ad8 997 inByte = spi.transfer(_data);
akpc806a 1:4683702d7ad8 998 return inByte;
akpc806a 1:4683702d7ad8 999 }
akpc806a 1:4683702d7ad8 1000
akpc806a 1:4683702d7ad8 1001 //SPI chip select method
akpc806a 1:4683702d7ad8 1002 void OpenBCI_32bit_Library::csLow(int SS)
akpc806a 1:4683702d7ad8 1003 { // select an SPI slave to talk to
akpc806a 1:4683702d7ad8 1004 switch(SS){
akpc806a 1:4683702d7ad8 1005 case BOARD_ADS:
akpc806a 1:4683702d7ad8 1006 spi.setMode(DSPI_MODE1);
akpc806a 1:4683702d7ad8 1007 spi.setSpeed(4000000);
akpc806a 1:4683702d7ad8 1008 digitalWrite(BOARD_ADS, LOW);
akpc806a 1:4683702d7ad8 1009 break;
akpc806a 1:4683702d7ad8 1010 case LIS3DH_SS:
akpc806a 1:4683702d7ad8 1011 spi.setMode(DSPI_MODE3);
akpc806a 1:4683702d7ad8 1012 spi.setSpeed(4000000);
akpc806a 1:4683702d7ad8 1013 digitalWrite(LIS3DH_SS, LOW);
akpc806a 1:4683702d7ad8 1014 break;
akpc806a 1:4683702d7ad8 1015 case SD_SS:
akpc806a 1:4683702d7ad8 1016 spi.setMode(DSPI_MODE0);
akpc806a 1:4683702d7ad8 1017 spi.setSpeed(20000000);
akpc806a 1:4683702d7ad8 1018 digitalWrite(SD_SS, LOW);
akpc806a 1:4683702d7ad8 1019 break;
akpc806a 1:4683702d7ad8 1020 case DAISY_ADS:
akpc806a 1:4683702d7ad8 1021 spi.setMode(DSPI_MODE1);
akpc806a 1:4683702d7ad8 1022 spi.setSpeed(4000000);
akpc806a 1:4683702d7ad8 1023 digitalWrite(DAISY_ADS, LOW);
akpc806a 1:4683702d7ad8 1024 break;
akpc806a 1:4683702d7ad8 1025 case BOTH_ADS:
akpc806a 1:4683702d7ad8 1026 spi.setMode(DSPI_MODE1);
akpc806a 1:4683702d7ad8 1027 spi.setSpeed(4000000);
akpc806a 1:4683702d7ad8 1028 digitalWrite(BOARD_ADS,LOW);
akpc806a 1:4683702d7ad8 1029 digitalWrite(DAISY_ADS,LOW);
akpc806a 1:4683702d7ad8 1030 break;
akpc806a 1:4683702d7ad8 1031 default:
akpc806a 1:4683702d7ad8 1032 break;
akpc806a 1:4683702d7ad8 1033 }
akpc806a 1:4683702d7ad8 1034 }
akpc806a 1:4683702d7ad8 1035
akpc806a 1:4683702d7ad8 1036 void OpenBCI_32bit_Library::csHigh(int SS)
akpc806a 1:4683702d7ad8 1037 { // deselect SPI slave
akpc806a 1:4683702d7ad8 1038 switch(SS){
akpc806a 1:4683702d7ad8 1039 case BOARD_ADS:
akpc806a 1:4683702d7ad8 1040 digitalWrite(BOARD_ADS, HIGH);
akpc806a 1:4683702d7ad8 1041 spi.setSpeed(20000000);
akpc806a 1:4683702d7ad8 1042 break;
akpc806a 1:4683702d7ad8 1043 case LIS3DH_SS:
akpc806a 1:4683702d7ad8 1044 digitalWrite(LIS3DH_SS, HIGH);
akpc806a 1:4683702d7ad8 1045 spi.setSpeed(20000000);
akpc806a 1:4683702d7ad8 1046 break;
akpc806a 1:4683702d7ad8 1047 case SD_SS:
akpc806a 1:4683702d7ad8 1048 digitalWrite(SD_SS, HIGH);
akpc806a 1:4683702d7ad8 1049 spi.setSpeed(4000000);
akpc806a 1:4683702d7ad8 1050 break;
akpc806a 1:4683702d7ad8 1051 case DAISY_ADS:
akpc806a 1:4683702d7ad8 1052 digitalWrite(DAISY_ADS, HIGH);
akpc806a 1:4683702d7ad8 1053 spi.setSpeed(20000000);
akpc806a 1:4683702d7ad8 1054 break;
akpc806a 1:4683702d7ad8 1055 case BOTH_ADS:
akpc806a 1:4683702d7ad8 1056 digitalWrite(BOARD_ADS, HIGH);
akpc806a 1:4683702d7ad8 1057 digitalWrite(DAISY_ADS, HIGH);
akpc806a 1:4683702d7ad8 1058 spi.setSpeed(20000000); break;
akpc806a 1:4683702d7ad8 1059 default:
akpc806a 1:4683702d7ad8 1060 break;
akpc806a 1:4683702d7ad8 1061 }
akpc806a 1:4683702d7ad8 1062 spi.setMode(DSPI_MODE0); // DEFAULT TO SD MODE!
akpc806a 1:4683702d7ad8 1063 }
akpc806a 1:4683702d7ad8 1064
akpc806a 1:4683702d7ad8 1065 // <<<<<<<<<<<<<<<<<<<<<<<<< END OF BOARD WIDE FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 1066 // *************************************************************************************
akpc806a 1:4683702d7ad8 1067 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ADS1299 FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 1068
akpc806a 1:4683702d7ad8 1069
akpc806a 1:4683702d7ad8 1070 void OpenBCI_32bit_Library::initialize_ads(){
akpc806a 1:4683702d7ad8 1071 // recommended power up sequence requiers >Tpor (~32mS)
akpc806a 1:4683702d7ad8 1072 delay(50);
akpc806a 1:4683702d7ad8 1073 pinMode(ADS_RST,OUTPUT);
akpc806a 1:4683702d7ad8 1074 digitalWrite(ADS_RST,LOW); // reset pin connected to both ADS ICs
akpc806a 1:4683702d7ad8 1075 delayMicroseconds(4); // toggle reset pin
akpc806a 1:4683702d7ad8 1076 digitalWrite(ADS_RST,HIGH); // this will reset the Daisy if it is present
akpc806a 1:4683702d7ad8 1077 delayMicroseconds(20); // recommended to wait 18 Tclk before using device (~8uS);
akpc806a 1:4683702d7ad8 1078 // initalize the data ready chip select and reset pins:
akpc806a 1:4683702d7ad8 1079 pinMode(ADS_DRDY, INPUT); // we get DRDY asertion from the on-board ADS
akpc806a 1:4683702d7ad8 1080 delay(40);
akpc806a 1:4683702d7ad8 1081 resetADS(BOARD_ADS); // reset the on-board ADS registers, and stop DataContinuousMode
akpc806a 1:4683702d7ad8 1082 delay(10);
akpc806a 1:4683702d7ad8 1083 WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output its clk, set the data rate to 250SPS
akpc806a 1:4683702d7ad8 1084 delay(40);
akpc806a 1:4683702d7ad8 1085 resetADS(DAISY_ADS); // software reset daisy module if present
akpc806a 1:4683702d7ad8 1086 delay(10);
akpc806a 1:4683702d7ad8 1087 daisyPresent = smellDaisy(); // check to see if daisy module is present
akpc806a 1:4683702d7ad8 1088 if(!daisyPresent){
akpc806a 1:4683702d7ad8 1089 WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
akpc806a 1:4683702d7ad8 1090 numChannels = 8; // expect up to 8 ADS channels
akpc806a 1:4683702d7ad8 1091 }else{
akpc806a 1:4683702d7ad8 1092 numChannels = 16; // expect up to 16 ADS channels
akpc806a 1:4683702d7ad8 1093 }
akpc806a 1:4683702d7ad8 1094
akpc806a 1:4683702d7ad8 1095 // DEFAULT CHANNEL SETTINGS FOR ADS
akpc806a 1:4683702d7ad8 1096 defaultChannelSettings[POWER_DOWN] = NO; // on = NO, off = YES
akpc806a 1:4683702d7ad8 1097 defaultChannelSettings[GAIN_SET] = ADS_GAIN24; // Gain setting
akpc806a 1:4683702d7ad8 1098 defaultChannelSettings[INPUT_TYPE_SET] = ADSINPUT_NORMAL;// input muxer setting
akpc806a 1:4683702d7ad8 1099 defaultChannelSettings[BIAS_SET] = YES; // add this channel to bias generation
akpc806a 1:4683702d7ad8 1100 defaultChannelSettings[SRB2_SET] = YES; // connect this P side to SRB2
akpc806a 1:4683702d7ad8 1101 defaultChannelSettings[SRB1_SET] = NO; // don't use SRB1
akpc806a 1:4683702d7ad8 1102
akpc806a 1:4683702d7ad8 1103 for(int i=0; i<numChannels; i++){
akpc806a 1:4683702d7ad8 1104 for(int j=0; j<6; j++){
akpc806a 1:4683702d7ad8 1105 channelSettings[i][j] = defaultChannelSettings[j]; // assign default settings
akpc806a 1:4683702d7ad8 1106 }
akpc806a 1:4683702d7ad8 1107 useInBias[i] = true; // keeping track of Bias Generation
akpc806a 1:4683702d7ad8 1108 useSRB2[i] = true; // keeping track of SRB2 inclusion
akpc806a 1:4683702d7ad8 1109 }
akpc806a 1:4683702d7ad8 1110 boardUseSRB1 = daisyUseSRB1 = false;
akpc806a 1:4683702d7ad8 1111
akpc806a 1:4683702d7ad8 1112 writeChannelSettings(); // write settings to the on-board and on-daisy ADS if present
akpc806a 1:4683702d7ad8 1113
akpc806a 1:4683702d7ad8 1114 WREG(CONFIG3,0b11101100,BOTH_ADS); delay(1); // enable internal reference drive and etc.
akpc806a 1:4683702d7ad8 1115 for(int i=0; i<numChannels; i++){ // turn off the impedance measure signal
akpc806a 1:4683702d7ad8 1116 leadOffSettings[i][PCHAN] = OFF;
akpc806a 1:4683702d7ad8 1117 leadOffSettings[i][NCHAN] = OFF;
akpc806a 1:4683702d7ad8 1118 }
akpc806a 1:4683702d7ad8 1119 verbosity = false; // when verbosity is true, there will be Serial feedback
akpc806a 1:4683702d7ad8 1120 firstDataPacket = true;
akpc806a 1:4683702d7ad8 1121
akpc806a 1:4683702d7ad8 1122 streaming = false;
akpc806a 1:4683702d7ad8 1123 }
akpc806a 1:4683702d7ad8 1124
akpc806a 1:4683702d7ad8 1125 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1126 ///////////// STREAM METHODS /////////////////
akpc806a 1:4683702d7ad8 1127 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1128
akpc806a 1:4683702d7ad8 1129 /**
akpc806a 1:4683702d7ad8 1130 * @description Used to activate a channel, if running must stop and start after...
akpc806a 1:4683702d7ad8 1131 * @param channelNumber int the channel you want to change
akpc806a 1:4683702d7ad8 1132 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1133 */
akpc806a 1:4683702d7ad8 1134 void OpenBCI_32bit_Library::streamSafeChannelActivate(byte channelNumber) {
akpc806a 1:4683702d7ad8 1135 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1136
akpc806a 1:4683702d7ad8 1137 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1138 if (streaming) {
akpc806a 1:4683702d7ad8 1139 streamStop();
akpc806a 1:4683702d7ad8 1140 }
akpc806a 1:4683702d7ad8 1141
akpc806a 1:4683702d7ad8 1142 // Activate the channel
akpc806a 1:4683702d7ad8 1143 activateChannel(channelNumber);
akpc806a 1:4683702d7ad8 1144
akpc806a 1:4683702d7ad8 1145 // Restart stream if need be
akpc806a 1:4683702d7ad8 1146 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1147 streamStart();
akpc806a 1:4683702d7ad8 1148 }
akpc806a 1:4683702d7ad8 1149 }
akpc806a 1:4683702d7ad8 1150
akpc806a 1:4683702d7ad8 1151 /**
akpc806a 1:4683702d7ad8 1152 * @description Used to deactivate a channel, if running must stop and start after...
akpc806a 1:4683702d7ad8 1153 * @param channelNumber int the channel you want to change
akpc806a 1:4683702d7ad8 1154 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1155 */
akpc806a 1:4683702d7ad8 1156 void OpenBCI_32bit_Library::streamSafeChannelDeactivate(byte channelNumber){
akpc806a 1:4683702d7ad8 1157 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1158
akpc806a 1:4683702d7ad8 1159 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1160 if (streaming) {
akpc806a 1:4683702d7ad8 1161 streamStop();
akpc806a 1:4683702d7ad8 1162 }
akpc806a 1:4683702d7ad8 1163
akpc806a 1:4683702d7ad8 1164 // deactivate the channel
akpc806a 1:4683702d7ad8 1165 deactivateChannel(channelNumber);
akpc806a 1:4683702d7ad8 1166
akpc806a 1:4683702d7ad8 1167 // Restart stream if need be
akpc806a 1:4683702d7ad8 1168 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1169 streamStart();
akpc806a 1:4683702d7ad8 1170 }
akpc806a 1:4683702d7ad8 1171 }
akpc806a 1:4683702d7ad8 1172
akpc806a 1:4683702d7ad8 1173 /**
akpc806a 1:4683702d7ad8 1174 * @description Used to set lead off for a channel, if running must stop and start after...
akpc806a 1:4683702d7ad8 1175 * @param `channelNumber` - [byte] - The channel you want to change
akpc806a 1:4683702d7ad8 1176 * @param `pInput` - [byte] - Apply signal to P input, either ON (1) or OFF (0)
akpc806a 1:4683702d7ad8 1177 * @param `nInput` - [byte] - Apply signal to N input, either ON (1) or OFF (0)
akpc806a 1:4683702d7ad8 1178 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1179 */
akpc806a 1:4683702d7ad8 1180 void OpenBCI_32bit_Library::streamSafeLeadOffSetForChannel(byte channelNumber, byte pInput, byte nInput) {
akpc806a 1:4683702d7ad8 1181 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1182
akpc806a 1:4683702d7ad8 1183 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1184 if (streaming) {
akpc806a 1:4683702d7ad8 1185 streamStop();
akpc806a 1:4683702d7ad8 1186 }
akpc806a 1:4683702d7ad8 1187
akpc806a 1:4683702d7ad8 1188 changeChannelLeadOffDetect(channelNumber);
akpc806a 1:4683702d7ad8 1189
akpc806a 1:4683702d7ad8 1190 // leadOffSetForChannel(channelNumber, pInput, nInput);
akpc806a 1:4683702d7ad8 1191
akpc806a 1:4683702d7ad8 1192 // Restart stream if need be
akpc806a 1:4683702d7ad8 1193 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1194 streamStart();
akpc806a 1:4683702d7ad8 1195 }
akpc806a 1:4683702d7ad8 1196 }
akpc806a 1:4683702d7ad8 1197
akpc806a 1:4683702d7ad8 1198 /**
akpc806a 1:4683702d7ad8 1199 * @description Used to set lead off for a channel, if running must stop and start after...
akpc806a 1:4683702d7ad8 1200 * @param see `.channelSettingsSetForChannel()` for parameters
akpc806a 1:4683702d7ad8 1201 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1202 */
akpc806a 1:4683702d7ad8 1203 void OpenBCI_32bit_Library::streamSafeChannelSettingsForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1) {
akpc806a 1:4683702d7ad8 1204 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1205
akpc806a 1:4683702d7ad8 1206 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1207 if (streaming) {
akpc806a 1:4683702d7ad8 1208 streamStop();
akpc806a 1:4683702d7ad8 1209 }
akpc806a 1:4683702d7ad8 1210
akpc806a 1:4683702d7ad8 1211 writeChannelSettings(channelNumber);
akpc806a 1:4683702d7ad8 1212
akpc806a 1:4683702d7ad8 1213 // channelSettingsSetForChannel(channelNumber, powerDown, gain, inputType, bias, srb2, srb1);
akpc806a 1:4683702d7ad8 1214
akpc806a 1:4683702d7ad8 1215 // Restart stream if need be
akpc806a 1:4683702d7ad8 1216 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1217 streamStart();
akpc806a 1:4683702d7ad8 1218 }
akpc806a 1:4683702d7ad8 1219 }
akpc806a 1:4683702d7ad8 1220
akpc806a 1:4683702d7ad8 1221 /**
akpc806a 1:4683702d7ad8 1222 * @description Used to report (Serial0.print) the default channel settings
akpc806a 1:4683702d7ad8 1223 * if running must stop and start after...
akpc806a 1:4683702d7ad8 1224 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1225 */
akpc806a 1:4683702d7ad8 1226 void OpenBCI_32bit_Library::streamSafeReportAllChannelDefaults(void) {
akpc806a 1:4683702d7ad8 1227 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1228
akpc806a 1:4683702d7ad8 1229 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1230 if (streaming) {
akpc806a 1:4683702d7ad8 1231 streamStop();
akpc806a 1:4683702d7ad8 1232 }
akpc806a 1:4683702d7ad8 1233
akpc806a 1:4683702d7ad8 1234 reportDefaultChannelSettings();
akpc806a 1:4683702d7ad8 1235
akpc806a 1:4683702d7ad8 1236 // Restart stream if need be
akpc806a 1:4683702d7ad8 1237 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1238 streamStart();
akpc806a 1:4683702d7ad8 1239 }
akpc806a 1:4683702d7ad8 1240 }
akpc806a 1:4683702d7ad8 1241
akpc806a 1:4683702d7ad8 1242 /**
akpc806a 1:4683702d7ad8 1243 * @description Used to set all channels on Board (and Daisy) to the default
akpc806a 1:4683702d7ad8 1244 * channel settings if running must stop and start after...
akpc806a 1:4683702d7ad8 1245 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1246 */
akpc806a 1:4683702d7ad8 1247 void OpenBCI_32bit_Library::streamSafeSetAllChannelsToDefault(void) {
akpc806a 1:4683702d7ad8 1248 boolean wasStreaming = streaming;
akpc806a 1:4683702d7ad8 1249
akpc806a 1:4683702d7ad8 1250 // Stop streaming if you are currently streaming
akpc806a 1:4683702d7ad8 1251 if (streaming) {
akpc806a 1:4683702d7ad8 1252 streamStop();
akpc806a 1:4683702d7ad8 1253 }
akpc806a 1:4683702d7ad8 1254
akpc806a 1:4683702d7ad8 1255 setChannelsToDefault();
akpc806a 1:4683702d7ad8 1256
akpc806a 1:4683702d7ad8 1257 // Restart stream if need be
akpc806a 1:4683702d7ad8 1258 if (wasStreaming) {
akpc806a 1:4683702d7ad8 1259 streamStart();
akpc806a 1:4683702d7ad8 1260 }
akpc806a 1:4683702d7ad8 1261 }
akpc806a 1:4683702d7ad8 1262
akpc806a 1:4683702d7ad8 1263 /**
akpc806a 1:4683702d7ad8 1264 * @description Call this to start the streaming data from the ADS1299
akpc806a 1:4683702d7ad8 1265 * @returns boolean if able to start streaming
akpc806a 1:4683702d7ad8 1266 */
akpc806a 1:4683702d7ad8 1267 void OpenBCI_32bit_Library::streamStart(){ // needs daisy functionality
akpc806a 1:4683702d7ad8 1268 streaming = true;
akpc806a 1:4683702d7ad8 1269 startADS();
akpc806a 1:4683702d7ad8 1270 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 1271 Serial1.println("ADS Started");
akpc806a 1:4683702d7ad8 1272 }
akpc806a 1:4683702d7ad8 1273 }
akpc806a 1:4683702d7ad8 1274
akpc806a 1:4683702d7ad8 1275 /**
akpc806a 1:4683702d7ad8 1276 * @description Call this to stop streaming from the ADS1299
akpc806a 1:4683702d7ad8 1277 * @returns boolean if able to stop streaming
akpc806a 1:4683702d7ad8 1278 */
akpc806a 1:4683702d7ad8 1279 void OpenBCI_32bit_Library::streamStop(){
akpc806a 1:4683702d7ad8 1280 streaming = false;
akpc806a 1:4683702d7ad8 1281 stopADS();
akpc806a 1:4683702d7ad8 1282 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 1283 Serial1.println("ADS Stopped");
akpc806a 1:4683702d7ad8 1284 }
akpc806a 1:4683702d7ad8 1285
akpc806a 1:4683702d7ad8 1286 }
akpc806a 1:4683702d7ad8 1287
akpc806a 1:4683702d7ad8 1288 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1289 ////////////// DAISY METHODS /////////////////
akpc806a 1:4683702d7ad8 1290 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1291 boolean OpenBCI_32bit_Library::smellDaisy(void){ // check if daisy present
akpc806a 1:4683702d7ad8 1292 boolean isDaisy = false;
akpc806a 1:4683702d7ad8 1293 byte setting = RREG(ID_REG,DAISY_ADS); // try to read the daisy product ID
akpc806a 1:4683702d7ad8 1294 if(verbosity){Serial0.print("Daisy ID 0x"); Serial0.println(setting,HEX); sendEOT();}
akpc806a 1:4683702d7ad8 1295 if(setting == ADS_ID) {isDaisy = true;} // should read as 0x3E
akpc806a 1:4683702d7ad8 1296 return isDaisy;
akpc806a 1:4683702d7ad8 1297 }
akpc806a 1:4683702d7ad8 1298
akpc806a 1:4683702d7ad8 1299 void OpenBCI_32bit_Library::removeDaisy(void){
akpc806a 1:4683702d7ad8 1300 if(daisyPresent){
akpc806a 1:4683702d7ad8 1301 // Daisy removed
akpc806a 1:4683702d7ad8 1302 SDATAC(DAISY_ADS);
akpc806a 1:4683702d7ad8 1303 RESET(DAISY_ADS);
akpc806a 1:4683702d7ad8 1304 STANDBY(DAISY_ADS);
akpc806a 1:4683702d7ad8 1305 daisyPresent = false;
akpc806a 1:4683702d7ad8 1306 if(!isRunning) {
akpc806a 1:4683702d7ad8 1307 Serial0.println("daisy removed");
akpc806a 1:4683702d7ad8 1308 sendEOT();
akpc806a 1:4683702d7ad8 1309 }
akpc806a 1:4683702d7ad8 1310 }else{
akpc806a 1:4683702d7ad8 1311 if(!isRunning) {
akpc806a 1:4683702d7ad8 1312 Serial0.println("no daisy to remove!");
akpc806a 1:4683702d7ad8 1313 sendEOT();
akpc806a 1:4683702d7ad8 1314 }
akpc806a 1:4683702d7ad8 1315 }
akpc806a 1:4683702d7ad8 1316 }
akpc806a 1:4683702d7ad8 1317
akpc806a 1:4683702d7ad8 1318 void OpenBCI_32bit_Library::attachDaisy(void){
akpc806a 1:4683702d7ad8 1319 WREG(CONFIG1,0xB6,BOARD_ADS); // tell on-board ADS to output the clk, set the data rate to 250SPS
akpc806a 1:4683702d7ad8 1320 delay(40);
akpc806a 1:4683702d7ad8 1321 resetADS(DAISY_ADS); // software reset daisy module if present
akpc806a 1:4683702d7ad8 1322 delay(10);
akpc806a 1:4683702d7ad8 1323 daisyPresent = smellDaisy();
akpc806a 1:4683702d7ad8 1324 if(!daisyPresent){
akpc806a 1:4683702d7ad8 1325 WREG(CONFIG1,0x96,BOARD_ADS); // turn off clk output if no daisy present
akpc806a 1:4683702d7ad8 1326 numChannels = 8; // expect up to 8 ADS channels
akpc806a 1:4683702d7ad8 1327 if(!isRunning) Serial0.println("no daisy to attach!");
akpc806a 1:4683702d7ad8 1328 }else{
akpc806a 1:4683702d7ad8 1329 numChannels = 16; // expect up to 16 ADS channels
akpc806a 1:4683702d7ad8 1330 if(!isRunning) Serial0.println("daisy attached");
akpc806a 1:4683702d7ad8 1331 }
akpc806a 1:4683702d7ad8 1332 }
akpc806a 1:4683702d7ad8 1333
akpc806a 1:4683702d7ad8 1334 //reset all the ADS1299's settings. Stops all data acquisition
akpc806a 1:4683702d7ad8 1335 void OpenBCI_32bit_Library::resetADS(int targetSS)
akpc806a 1:4683702d7ad8 1336 {
akpc806a 1:4683702d7ad8 1337 int startChan, stopChan;
akpc806a 1:4683702d7ad8 1338 if(targetSS == BOARD_ADS) {startChan = 1; stopChan = 8;}
akpc806a 1:4683702d7ad8 1339 if(targetSS == DAISY_ADS) {startChan = 9; stopChan = 16;}
akpc806a 1:4683702d7ad8 1340 RESET(targetSS); // send RESET command to default all registers
akpc806a 1:4683702d7ad8 1341 SDATAC(targetSS); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1342 delay(100);
akpc806a 1:4683702d7ad8 1343 // turn off all channels
akpc806a 1:4683702d7ad8 1344 for (int chan=startChan; chan <= stopChan; chan++) {
akpc806a 1:4683702d7ad8 1345 deactivateChannel(chan);
akpc806a 1:4683702d7ad8 1346 }
akpc806a 1:4683702d7ad8 1347 }
akpc806a 1:4683702d7ad8 1348
akpc806a 1:4683702d7ad8 1349 void OpenBCI_32bit_Library::setChannelsToDefault(void){
akpc806a 1:4683702d7ad8 1350 for(int i=0; i<numChannels; i++){
akpc806a 1:4683702d7ad8 1351 for(int j=0; j<6; j++){
akpc806a 1:4683702d7ad8 1352 channelSettings[i][j] = defaultChannelSettings[j];
akpc806a 1:4683702d7ad8 1353 }
akpc806a 1:4683702d7ad8 1354 useInBias[i] = true; // keeping track of Bias Generation
akpc806a 1:4683702d7ad8 1355 useSRB2[i] = true; // keeping track of SRB2 inclusion
akpc806a 1:4683702d7ad8 1356 }
akpc806a 1:4683702d7ad8 1357 boardUseSRB1 = daisyUseSRB1 = false;
akpc806a 1:4683702d7ad8 1358
akpc806a 1:4683702d7ad8 1359 writeChannelSettings(); // write settings to on-board ADS
akpc806a 1:4683702d7ad8 1360
akpc806a 1:4683702d7ad8 1361 for(int i=0; i<numChannels; i++){ // turn off the impedance measure signal
akpc806a 1:4683702d7ad8 1362 leadOffSettings[i][PCHAN] = OFF;
akpc806a 1:4683702d7ad8 1363 leadOffSettings[i][NCHAN] = OFF;
akpc806a 1:4683702d7ad8 1364 }
akpc806a 1:4683702d7ad8 1365 changeChannelLeadOffDetect(); // write settings to all ADS
akpc806a 1:4683702d7ad8 1366
akpc806a 1:4683702d7ad8 1367
akpc806a 1:4683702d7ad8 1368 WREG(MISC1,0x00,BOARD_ADS); // open SRB1 switch on-board
akpc806a 1:4683702d7ad8 1369 if(daisyPresent){ WREG(MISC1,0x00,DAISY_ADS); } // open SRB1 switch on-daisy
akpc806a 1:4683702d7ad8 1370 }
akpc806a 1:4683702d7ad8 1371
akpc806a 1:4683702d7ad8 1372 // void OpenBCI_32bit_Library::setChannelsToDefault(void){
akpc806a 1:4683702d7ad8 1373
akpc806a 1:4683702d7ad8 1374 // // Reset the global channel settings array to default
akpc806a 1:4683702d7ad8 1375 // resetChannelSettingsArrayToDefault(channelSettings);
akpc806a 1:4683702d7ad8 1376 // // Write channel settings to board (and daisy) ADS
akpc806a 1:4683702d7ad8 1377 // channelSettingsArraySetForAll();
akpc806a 1:4683702d7ad8 1378
akpc806a 1:4683702d7ad8 1379 // // Reset the global lead off settings array to default
akpc806a 1:4683702d7ad8 1380 // resetLeadOffArrayToDefault(leadOffSettings);
akpc806a 1:4683702d7ad8 1381 // // Write lead off settings to board (and daisy) ADS
akpc806a 1:4683702d7ad8 1382 // leadOffSetForAllChannels();
akpc806a 1:4683702d7ad8 1383
akpc806a 1:4683702d7ad8 1384 // WREG(MISC1,0x00,BOARD_ADS); // open SRB1 switch on-board
akpc806a 1:4683702d7ad8 1385 // if(daisyPresent){ // open SRB1 switch on-daisy
akpc806a 1:4683702d7ad8 1386 // WREG(MISC1,0x00,DAISY_ADS);
akpc806a 1:4683702d7ad8 1387 // }
akpc806a 1:4683702d7ad8 1388 // }
akpc806a 1:4683702d7ad8 1389
akpc806a 1:4683702d7ad8 1390 /**
akpc806a 1:4683702d7ad8 1391 * @description Writes the default channel settings over the serial port
akpc806a 1:4683702d7ad8 1392 */
akpc806a 1:4683702d7ad8 1393 void OpenBCI_32bit_Library::reportDefaultChannelSettings(void){
akpc806a 1:4683702d7ad8 1394 Serial0.write(getDefaultChannelSettingForSettingAscii(POWER_DOWN)); // on = NO, off = YES
akpc806a 1:4683702d7ad8 1395 Serial0.write(getDefaultChannelSettingForSettingAscii(GAIN_SET)); // Gain setting
akpc806a 1:4683702d7ad8 1396 Serial0.write(getDefaultChannelSettingForSettingAscii(INPUT_TYPE_SET)); // input muxer setting
akpc806a 1:4683702d7ad8 1397 Serial0.write(getDefaultChannelSettingForSettingAscii(BIAS_SET)); // add this channel to bias generation
akpc806a 1:4683702d7ad8 1398 Serial0.write(getDefaultChannelSettingForSettingAscii(SRB2_SET)); // connect this P side to SRB2
akpc806a 1:4683702d7ad8 1399 Serial0.write(getDefaultChannelSettingForSettingAscii(SRB1_SET)); // don't use SRB1
akpc806a 1:4683702d7ad8 1400 sendEOT();
akpc806a 1:4683702d7ad8 1401 }
akpc806a 1:4683702d7ad8 1402
akpc806a 1:4683702d7ad8 1403 /**
akpc806a 1:4683702d7ad8 1404 * @description Set all channels using global channelSettings array
akpc806a 1:4683702d7ad8 1405 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1406 */
akpc806a 1:4683702d7ad8 1407 // void OpenBCI_32bit_Library::channelSettingsArraySetForAll(void) {
akpc806a 1:4683702d7ad8 1408 // byte channelNumberUpperLimit;
akpc806a 1:4683702d7ad8 1409
akpc806a 1:4683702d7ad8 1410 // // The upper limit of the channels, either 8 or 16
akpc806a 1:4683702d7ad8 1411 // channelNumberUpperLimit = daisyPresent ? OPENBCI_NUMBER_OF_CHANNELS_DAISY : OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
akpc806a 1:4683702d7ad8 1412
akpc806a 1:4683702d7ad8 1413 // // Loop through all channels
akpc806a 1:4683702d7ad8 1414 // for (byte i = 1; i <= channelNumberUpperLimit; i++) {
akpc806a 1:4683702d7ad8 1415 // // Set for this channel
akpc806a 1:4683702d7ad8 1416 // 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]);
akpc806a 1:4683702d7ad8 1417 // }
akpc806a 1:4683702d7ad8 1418 // }
akpc806a 1:4683702d7ad8 1419
akpc806a 1:4683702d7ad8 1420 /**
akpc806a 1:4683702d7ad8 1421 * @description Set channel using global channelSettings array for channelNumber
akpc806a 1:4683702d7ad8 1422 * @param `channelNumber` - [byte] - 1-16 channel number
akpc806a 1:4683702d7ad8 1423 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1424 */
akpc806a 1:4683702d7ad8 1425 // void OpenBCI_32bit_Library::channelSettingsArraySetForChannel(byte channelNumber) {
akpc806a 1:4683702d7ad8 1426 // // contstrain the channel number to 0-15
akpc806a 1:4683702d7ad8 1427 // char index = getConstrainedChannelNumber(channelNumber);
akpc806a 1:4683702d7ad8 1428
akpc806a 1:4683702d7ad8 1429 // // Set for this channel
akpc806a 1:4683702d7ad8 1430 // 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]);
akpc806a 1:4683702d7ad8 1431 // }
akpc806a 1:4683702d7ad8 1432
akpc806a 1:4683702d7ad8 1433 /**
akpc806a 1:4683702d7ad8 1434 * @description To add a usability abstraction layer above channel setting commands. Due to the
akpc806a 1:4683702d7ad8 1435 * extensive and highly specific nature of the channel setting command chain.
akpc806a 1:4683702d7ad8 1436 * @param `channelNumber` - [byte] (1-16) for index, so convert channel to array prior
akpc806a 1:4683702d7ad8 1437 * @param `powerDown` - [byte] - YES (1) or NO (0)
akpc806a 1:4683702d7ad8 1438 * Powers channel down
akpc806a 1:4683702d7ad8 1439 * @param `gain` - [byte] - Sets the gain for the channel
akpc806a 1:4683702d7ad8 1440 * ADS_GAIN01 (0b00000000) // 0x00
akpc806a 1:4683702d7ad8 1441 * ADS_GAIN02 (0b00010000) // 0x10
akpc806a 1:4683702d7ad8 1442 * ADS_GAIN04 (0b00100000) // 0x20
akpc806a 1:4683702d7ad8 1443 * ADS_GAIN06 (0b00110000) // 0x30
akpc806a 1:4683702d7ad8 1444 * ADS_GAIN08 (0b01000000) // 0x40
akpc806a 1:4683702d7ad8 1445 * ADS_GAIN12 (0b01010000) // 0x50
akpc806a 1:4683702d7ad8 1446 * ADS_GAIN24 (0b01100000) // 0x60
akpc806a 1:4683702d7ad8 1447 * @param `inputType` - [byte] - Selects the ADC channel input source, either:
akpc806a 1:4683702d7ad8 1448 * ADSINPUT_NORMAL (0b00000000)
akpc806a 1:4683702d7ad8 1449 * ADSINPUT_SHORTED (0b00000001)
akpc806a 1:4683702d7ad8 1450 * ADSINPUT_BIAS_MEAS (0b00000010)
akpc806a 1:4683702d7ad8 1451 * ADSINPUT_MVDD (0b00000011)
akpc806a 1:4683702d7ad8 1452 * ADSINPUT_TEMP (0b00000100)
akpc806a 1:4683702d7ad8 1453 * ADSINPUT_TESTSIG (0b00000101)
akpc806a 1:4683702d7ad8 1454 * ADSINPUT_BIAS_DRP (0b00000110)
akpc806a 1:4683702d7ad8 1455 * ADSINPUT_BIAL_DRN (0b00000111)
akpc806a 1:4683702d7ad8 1456 * @param `bias` - [byte] (YES (1) -> Include in bias (default), NO (0) -> remove from bias)
akpc806a 1:4683702d7ad8 1457 * selects to include the channel input in bias generation
akpc806a 1:4683702d7ad8 1458 * @param `srb2` - [byte] (YES (1) -> Connect this input to SRB2 (default),
akpc806a 1:4683702d7ad8 1459 * NO (0) -> Disconnect this input from SRB2)
akpc806a 1:4683702d7ad8 1460 * Select to connect (YES) this channel's P input to the SRB2 pin. This closes
akpc806a 1:4683702d7ad8 1461 * a switch between P input and SRB2 for the given channel, and allows the
akpc806a 1:4683702d7ad8 1462 * P input to also remain connected to the ADC.
akpc806a 1:4683702d7ad8 1463 * @param `srb1` - [byte] (YES (1) -> connect all N inputs to SRB1,
akpc806a 1:4683702d7ad8 1464 * NO (0) -> Disconnect all N inputs from SRB1 (default))
akpc806a 1:4683702d7ad8 1465 * Select to connect (YES) all channels' N inputs to SRB1. This effects all pins,
akpc806a 1:4683702d7ad8 1466 * and disconnects all N inputs from the ADC.
akpc806a 1:4683702d7ad8 1467 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1468 */
akpc806a 1:4683702d7ad8 1469 // void OpenBCI_32bit_Library::channelSettingsSetForChannel(byte channelNumber, byte powerDown, byte gain, byte inputType, byte bias, byte srb2, byte srb1) {
akpc806a 1:4683702d7ad8 1470 // byte setting, targetSS;
akpc806a 1:4683702d7ad8 1471
akpc806a 1:4683702d7ad8 1472 // // contstrain the channel number to 0-15
akpc806a 1:4683702d7ad8 1473 // char index = getConstrainedChannelNumber(channelNumber);
akpc806a 1:4683702d7ad8 1474
akpc806a 1:4683702d7ad8 1475 // // Get the slave select pin for this channel
akpc806a 1:4683702d7ad8 1476 // targetSS = getTargetSSForConstrainedChannelNumber(index);
akpc806a 1:4683702d7ad8 1477
akpc806a 1:4683702d7ad8 1478 // if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 1479 // if (targetSS == BOARD_ADS) {
akpc806a 1:4683702d7ad8 1480 // Serial1.print("Set channel "); Serial1.print(channelNumber); Serial1.println(" settings");
akpc806a 1:4683702d7ad8 1481 // }
akpc806a 1:4683702d7ad8 1482 // }
akpc806a 1:4683702d7ad8 1483
akpc806a 1:4683702d7ad8 1484 // // first, disable any data collection
akpc806a 1:4683702d7ad8 1485 // SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1486
akpc806a 1:4683702d7ad8 1487 // setting = 0x00;
akpc806a 1:4683702d7ad8 1488
akpc806a 1:4683702d7ad8 1489 // // Set the power down bit
akpc806a 1:4683702d7ad8 1490 // if(powerDown == YES) {
akpc806a 1:4683702d7ad8 1491 // setting |= 0x80;
akpc806a 1:4683702d7ad8 1492 // }
akpc806a 1:4683702d7ad8 1493
akpc806a 1:4683702d7ad8 1494 // // Set the gain bits
akpc806a 1:4683702d7ad8 1495 // setting |= gain;
akpc806a 1:4683702d7ad8 1496
akpc806a 1:4683702d7ad8 1497 // // Set input type bits
akpc806a 1:4683702d7ad8 1498 // setting |= inputType;
akpc806a 1:4683702d7ad8 1499
akpc806a 1:4683702d7ad8 1500 // if(srb2 == YES){
akpc806a 1:4683702d7ad8 1501 // setting |= 0x08; // close this SRB2 switch
akpc806a 1:4683702d7ad8 1502 // useSRB2[index] = true; // keep track of SRB2 usage
akpc806a 1:4683702d7ad8 1503 // }else{
akpc806a 1:4683702d7ad8 1504 // useSRB2[index] = false;
akpc806a 1:4683702d7ad8 1505 // }
akpc806a 1:4683702d7ad8 1506
akpc806a 1:4683702d7ad8 1507 // byte channelNumberRegister = 0x00;
akpc806a 1:4683702d7ad8 1508
akpc806a 1:4683702d7ad8 1509 // // Since we are addressing 8 bit registers, we need to subtract 8 from the
akpc806a 1:4683702d7ad8 1510 // // channelNumber if we are addressing the Daisy ADS
akpc806a 1:4683702d7ad8 1511 // if (targetSS == DAISY_ADS) {
akpc806a 1:4683702d7ad8 1512 // channelNumberRegister = index - OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
akpc806a 1:4683702d7ad8 1513 // } else {
akpc806a 1:4683702d7ad8 1514 // channelNumberRegister = index;
akpc806a 1:4683702d7ad8 1515 // }
akpc806a 1:4683702d7ad8 1516 // WREG(CH1SET+channelNumberRegister, setting, targetSS); // write this channel's register settings
akpc806a 1:4683702d7ad8 1517
akpc806a 1:4683702d7ad8 1518 // // add or remove from inclusion in BIAS generation
akpc806a 1:4683702d7ad8 1519 // setting = RREG(BIAS_SENSP,targetSS); //get the current P bias settings
akpc806a 1:4683702d7ad8 1520 // if(bias == YES){
akpc806a 1:4683702d7ad8 1521 // useInBias[index] = true;
akpc806a 1:4683702d7ad8 1522 // bitSet(setting,channelNumberRegister); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1523 // }else{
akpc806a 1:4683702d7ad8 1524 // useInBias[index] = false;
akpc806a 1:4683702d7ad8 1525 // bitClear(setting,channelNumberRegister); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1526 // }
akpc806a 1:4683702d7ad8 1527 // WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1528
akpc806a 1:4683702d7ad8 1529 // setting = RREG(BIAS_SENSN,targetSS); //get the current N bias settings
akpc806a 1:4683702d7ad8 1530 // if(bias == YES){
akpc806a 1:4683702d7ad8 1531 // bitSet(setting,channelNumberRegister); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1532 // }else{
akpc806a 1:4683702d7ad8 1533 // bitClear(setting,channelNumberRegister); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1534 // }
akpc806a 1:4683702d7ad8 1535 // WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1536
akpc806a 1:4683702d7ad8 1537 // byte startChan = targetSS == BOARD_ADS ? 0 : OPENBCI_CHANNEL_MAX_NUMBER_8 - 1;
akpc806a 1:4683702d7ad8 1538 // byte endChan = targetSS == BOARD_ADS ? OPENBCI_CHANNEL_MAX_NUMBER_8 : OPENBCI_CHANNEL_MAX_NUMBER_16 - 1;
akpc806a 1:4683702d7ad8 1539 // // if SRB1 is closed or open for one channel, it will be the same for all channels
akpc806a 1:4683702d7ad8 1540 // if(srb1 == YES){
akpc806a 1:4683702d7ad8 1541 // for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1542 // channelSettings[i][SRB1_SET] = YES;
akpc806a 1:4683702d7ad8 1543 // }
akpc806a 1:4683702d7ad8 1544 // if(targetSS == BOARD_ADS) boardUseSRB1 = true;
akpc806a 1:4683702d7ad8 1545 // if(targetSS == DAISY_ADS) daisyUseSRB1 = true;
akpc806a 1:4683702d7ad8 1546 // setting = 0x20; // close SRB1 swtich
akpc806a 1:4683702d7ad8 1547 // }
akpc806a 1:4683702d7ad8 1548 // if(srb1 == NO){
akpc806a 1:4683702d7ad8 1549 // for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1550 // channelSettings[i][SRB1_SET] = NO;
akpc806a 1:4683702d7ad8 1551 // }
akpc806a 1:4683702d7ad8 1552 // if(targetSS == BOARD_ADS) boardUseSRB1 = false;
akpc806a 1:4683702d7ad8 1553 // if(targetSS == DAISY_ADS) daisyUseSRB1 = false;
akpc806a 1:4683702d7ad8 1554 // setting = 0x00; // open SRB1 switch
akpc806a 1:4683702d7ad8 1555 // }
akpc806a 1:4683702d7ad8 1556 // WREG(MISC1,setting,targetSS);
akpc806a 1:4683702d7ad8 1557 // }
akpc806a 1:4683702d7ad8 1558
akpc806a 1:4683702d7ad8 1559 // write settings for ALL 8 channels for a given ADS board
akpc806a 1:4683702d7ad8 1560 // channel settings: powerDown, gain, inputType, SRB2, SRB1
akpc806a 1:4683702d7ad8 1561 void OpenBCI_32bit_Library::writeChannelSettings(){
akpc806a 1:4683702d7ad8 1562 boolean use_SRB1 = false;
akpc806a 1:4683702d7ad8 1563 byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1564
akpc806a 1:4683702d7ad8 1565 for(int b=0; b<2; b++){
akpc806a 1:4683702d7ad8 1566 if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
akpc806a 1:4683702d7ad8 1567 if(b == 1){
akpc806a 1:4683702d7ad8 1568 if(!daisyPresent){ return; }
akpc806a 1:4683702d7ad8 1569 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1570 }
akpc806a 1:4683702d7ad8 1571
akpc806a 1:4683702d7ad8 1572 SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1573
akpc806a 1:4683702d7ad8 1574 for(byte i=startChan; i<endChan; i++){ // write 8 channel settings
akpc806a 1:4683702d7ad8 1575 setting = 0x00;
akpc806a 1:4683702d7ad8 1576 if(channelSettings[i][POWER_DOWN] == YES){setting |= 0x80;}
akpc806a 1:4683702d7ad8 1577 setting |= channelSettings[i][GAIN_SET]; // gain
akpc806a 1:4683702d7ad8 1578 setting |= channelSettings[i][INPUT_TYPE_SET]; // input code
akpc806a 1:4683702d7ad8 1579 if(channelSettings[i][SRB2_SET] == YES){
akpc806a 1:4683702d7ad8 1580 setting |= 0x08; // close this SRB2 switch
akpc806a 1:4683702d7ad8 1581 useSRB2[i] = true; // remember SRB2 state for this channel
akpc806a 1:4683702d7ad8 1582 }else{
akpc806a 1:4683702d7ad8 1583 useSRB2[i] = false; // rememver SRB2 state for this channel
akpc806a 1:4683702d7ad8 1584 }
akpc806a 1:4683702d7ad8 1585 WREG(CH1SET+(i-startChan),setting,targetSS); // write this channel's register settings
akpc806a 1:4683702d7ad8 1586
akpc806a 1:4683702d7ad8 1587 // add or remove this channel from inclusion in BIAS generation
akpc806a 1:4683702d7ad8 1588 setting = RREG(BIAS_SENSP,targetSS); //get the current P bias settings
akpc806a 1:4683702d7ad8 1589 if(channelSettings[i][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1590 bitSet(setting,i-startChan); useInBias[i] = true; //add this channel to the bias generation
akpc806a 1:4683702d7ad8 1591 }else{
akpc806a 1:4683702d7ad8 1592 bitClear(setting,i-startChan); useInBias[i] = false; //remove this channel from bias generation
akpc806a 1:4683702d7ad8 1593 }
akpc806a 1:4683702d7ad8 1594 WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1595
akpc806a 1:4683702d7ad8 1596 setting = RREG(BIAS_SENSN,targetSS); //get the current N bias settings
akpc806a 1:4683702d7ad8 1597 if(channelSettings[i][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1598 bitSet(setting,i-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1599 }else{
akpc806a 1:4683702d7ad8 1600 bitClear(setting,i-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1601 }
akpc806a 1:4683702d7ad8 1602 WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1603
akpc806a 1:4683702d7ad8 1604 if(channelSettings[i][SRB1_SET] == YES){
akpc806a 1:4683702d7ad8 1605 use_SRB1 = true; // if any of the channel setting closes SRB1, it is closed for all
akpc806a 1:4683702d7ad8 1606 }
akpc806a 1:4683702d7ad8 1607 } // end of CHnSET and BIAS settings
akpc806a 1:4683702d7ad8 1608 } // end of board select loop
akpc806a 1:4683702d7ad8 1609 if(use_SRB1){
akpc806a 1:4683702d7ad8 1610 for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1611 channelSettings[i][SRB1_SET] = YES;
akpc806a 1:4683702d7ad8 1612 }
akpc806a 1:4683702d7ad8 1613 WREG(MISC1,0x20,targetSS); // close SRB1 swtich
akpc806a 1:4683702d7ad8 1614 if(targetSS == BOARD_ADS){ boardUseSRB1 = true; }
akpc806a 1:4683702d7ad8 1615 if(targetSS == DAISY_ADS){ daisyUseSRB1 = true; }
akpc806a 1:4683702d7ad8 1616 }else{
akpc806a 1:4683702d7ad8 1617 for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1618 channelSettings[i][SRB1_SET] = NO;
akpc806a 1:4683702d7ad8 1619 }
akpc806a 1:4683702d7ad8 1620 WREG(MISC1,0x00,targetSS); // open SRB1 switch
akpc806a 1:4683702d7ad8 1621 if(targetSS == BOARD_ADS){ boardUseSRB1 = false; }
akpc806a 1:4683702d7ad8 1622 if(targetSS == DAISY_ADS){ daisyUseSRB1 = false; }
akpc806a 1:4683702d7ad8 1623 }
akpc806a 1:4683702d7ad8 1624 }
akpc806a 1:4683702d7ad8 1625
akpc806a 1:4683702d7ad8 1626 // write settings for a SPECIFIC channel on a given ADS board
akpc806a 1:4683702d7ad8 1627 void OpenBCI_32bit_Library::writeChannelSettings(byte N){
akpc806a 1:4683702d7ad8 1628
akpc806a 1:4683702d7ad8 1629 byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1630 if(N < 9){ // channels 1-8 on board
akpc806a 1:4683702d7ad8 1631 targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1632 }else{ // channels 9-16 on daisy module
akpc806a 1:4683702d7ad8 1633 if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1634 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1635 }
akpc806a 1:4683702d7ad8 1636 // function accepts channel 1-16, must be 0 indexed to work with array
akpc806a 1:4683702d7ad8 1637 N = constrain(N-1,startChan,endChan-1); //subtracts 1 so that we're counting from 0, not 1
akpc806a 1:4683702d7ad8 1638 // first, disable any data collection
akpc806a 1:4683702d7ad8 1639 SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1640
akpc806a 1:4683702d7ad8 1641 setting = 0x00;
akpc806a 1:4683702d7ad8 1642 if(channelSettings[N][POWER_DOWN] == YES) setting |= 0x80;
akpc806a 1:4683702d7ad8 1643 setting |= channelSettings[N][GAIN_SET]; // gain
akpc806a 1:4683702d7ad8 1644 setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
akpc806a 1:4683702d7ad8 1645 if(channelSettings[N][SRB2_SET] == YES){
akpc806a 1:4683702d7ad8 1646 setting |= 0x08; // close this SRB2 switch
akpc806a 1:4683702d7ad8 1647 useSRB2[N] = true; // keep track of SRB2 usage
akpc806a 1:4683702d7ad8 1648 }else{
akpc806a 1:4683702d7ad8 1649 useSRB2[N] = false;
akpc806a 1:4683702d7ad8 1650 }
akpc806a 1:4683702d7ad8 1651 WREG(CH1SET+(N-startChan), setting, targetSS); // write this channel's register settings
akpc806a 1:4683702d7ad8 1652
akpc806a 1:4683702d7ad8 1653 // add or remove from inclusion in BIAS generation
akpc806a 1:4683702d7ad8 1654 setting = RREG(BIAS_SENSP,targetSS); //get the current P bias settings
akpc806a 1:4683702d7ad8 1655 if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1656 useInBias[N] = true;
akpc806a 1:4683702d7ad8 1657 bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1658 }else{
akpc806a 1:4683702d7ad8 1659 useInBias[N] = false;
akpc806a 1:4683702d7ad8 1660 bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1661 }
akpc806a 1:4683702d7ad8 1662 WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1663 setting = RREG(BIAS_SENSN,targetSS); //get the current N bias settings
akpc806a 1:4683702d7ad8 1664 if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1665 bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1666 }else{
akpc806a 1:4683702d7ad8 1667 bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1668 }
akpc806a 1:4683702d7ad8 1669 WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1670
akpc806a 1:4683702d7ad8 1671 // if SRB1 is closed or open for one channel, it will be the same for all channels
akpc806a 1:4683702d7ad8 1672 if(channelSettings[N][SRB1_SET] == YES){
akpc806a 1:4683702d7ad8 1673 for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1674 channelSettings[i][SRB1_SET] = YES;
akpc806a 1:4683702d7ad8 1675 }
akpc806a 1:4683702d7ad8 1676 if(targetSS == BOARD_ADS) boardUseSRB1 = true;
akpc806a 1:4683702d7ad8 1677 if(targetSS == DAISY_ADS) daisyUseSRB1 = true;
akpc806a 1:4683702d7ad8 1678 setting = 0x20; // close SRB1 swtich
akpc806a 1:4683702d7ad8 1679 }
akpc806a 1:4683702d7ad8 1680 if(channelSettings[N][SRB1_SET] == NO){
akpc806a 1:4683702d7ad8 1681 for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1682 channelSettings[i][SRB1_SET] = NO;
akpc806a 1:4683702d7ad8 1683 }
akpc806a 1:4683702d7ad8 1684 if(targetSS == BOARD_ADS) boardUseSRB1 = false;
akpc806a 1:4683702d7ad8 1685 if(targetSS == DAISY_ADS) daisyUseSRB1 = false;
akpc806a 1:4683702d7ad8 1686 setting = 0x00; // open SRB1 switch
akpc806a 1:4683702d7ad8 1687 }
akpc806a 1:4683702d7ad8 1688 WREG(MISC1,setting,targetSS);
akpc806a 1:4683702d7ad8 1689 }
akpc806a 1:4683702d7ad8 1690
akpc806a 1:4683702d7ad8 1691 // deactivate the given channel.
akpc806a 1:4683702d7ad8 1692 void OpenBCI_32bit_Library::deactivateChannel(byte N)
akpc806a 1:4683702d7ad8 1693 {
akpc806a 1:4683702d7ad8 1694 byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1695 if(N < 9){
akpc806a 1:4683702d7ad8 1696 targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1697 }else{
akpc806a 1:4683702d7ad8 1698 if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1699 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1700 }
akpc806a 1:4683702d7ad8 1701 SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1702 N = constrain(N-1,startChan,endChan-1); //subtracts 1 so that we're counting from 0, not 1
akpc806a 1:4683702d7ad8 1703
akpc806a 1:4683702d7ad8 1704 setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings
akpc806a 1:4683702d7ad8 1705 bitSet(setting,7); // set bit7 to shut down channel
akpc806a 1:4683702d7ad8 1706 bitClear(setting,3); // clear bit3 to disclude from SRB2 if used
akpc806a 1:4683702d7ad8 1707 WREG(CH1SET+(N-startChan),setting,targetSS); delay(1); // write the new value to disable the channel
akpc806a 1:4683702d7ad8 1708
akpc806a 1:4683702d7ad8 1709 //remove the channel from the bias generation...
akpc806a 1:4683702d7ad8 1710 setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings
akpc806a 1:4683702d7ad8 1711 bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1712 WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1713
akpc806a 1:4683702d7ad8 1714 setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings
akpc806a 1:4683702d7ad8 1715 bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1716 WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1717
akpc806a 1:4683702d7ad8 1718 leadOffSettings[N][0] = leadOffSettings[N][1] = NO;
akpc806a 1:4683702d7ad8 1719 changeChannelLeadOffDetect(N+1);
akpc806a 1:4683702d7ad8 1720 }
akpc806a 1:4683702d7ad8 1721
akpc806a 1:4683702d7ad8 1722 void OpenBCI_32bit_Library::activateChannel(byte N)
akpc806a 1:4683702d7ad8 1723 {
akpc806a 1:4683702d7ad8 1724 byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1725 if(N < 9){
akpc806a 1:4683702d7ad8 1726 targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1727 }else{
akpc806a 1:4683702d7ad8 1728 if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1729 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1730 }
akpc806a 1:4683702d7ad8 1731
akpc806a 1:4683702d7ad8 1732 N = constrain(N-1,startChan,endChan-1); // 0-7 or 8-15
akpc806a 1:4683702d7ad8 1733
akpc806a 1:4683702d7ad8 1734 SDATAC(targetSS); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1735 setting = 0x00;
akpc806a 1:4683702d7ad8 1736 // channelSettings[N][POWER_DOWN] = NO; // keep track of channel on/off in this array REMOVE?
akpc806a 1:4683702d7ad8 1737 setting |= channelSettings[N][GAIN_SET]; // gain
akpc806a 1:4683702d7ad8 1738 setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
akpc806a 1:4683702d7ad8 1739 if(useSRB2[N] == true){channelSettings[N][SRB2_SET] = YES;}else{channelSettings[N][SRB2_SET] = NO;}
akpc806a 1:4683702d7ad8 1740 if(channelSettings[N][SRB2_SET] == YES) {bitSet(setting,3);} // close this SRB2 switch
akpc806a 1:4683702d7ad8 1741 WREG(CH1SET+(N-startChan),setting,targetSS);
akpc806a 1:4683702d7ad8 1742 // add or remove from inclusion in BIAS generation
akpc806a 1:4683702d7ad8 1743 if(useInBias[N]){channelSettings[N][BIAS_SET] = YES;}else{channelSettings[N][BIAS_SET] = NO;}
akpc806a 1:4683702d7ad8 1744 setting = RREG(BIAS_SENSP,targetSS); //get the current P bias settings
akpc806a 1:4683702d7ad8 1745 if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1746 bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1747 useInBias[N] = true;
akpc806a 1:4683702d7ad8 1748 }else{
akpc806a 1:4683702d7ad8 1749 bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1750 useInBias[N] = false;
akpc806a 1:4683702d7ad8 1751 }
akpc806a 1:4683702d7ad8 1752 WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1753 setting = RREG(BIAS_SENSN,targetSS); //get the current N bias settings
akpc806a 1:4683702d7ad8 1754 if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1755 bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1756 }else{
akpc806a 1:4683702d7ad8 1757 bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1758 }
akpc806a 1:4683702d7ad8 1759 WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1760
akpc806a 1:4683702d7ad8 1761 setting = 0x00;
akpc806a 1:4683702d7ad8 1762 if(targetSS == BOARD_ADS && boardUseSRB1 == true) setting = 0x20;
akpc806a 1:4683702d7ad8 1763 if(targetSS == DAISY_ADS && daisyUseSRB1 == true) setting = 0x20;
akpc806a 1:4683702d7ad8 1764 WREG(MISC1,setting,targetSS); // close all SRB1 swtiches
akpc806a 1:4683702d7ad8 1765 }
akpc806a 1:4683702d7ad8 1766
akpc806a 1:4683702d7ad8 1767 // change the lead off detect settings for all channels
akpc806a 1:4683702d7ad8 1768 void OpenBCI_32bit_Library::changeChannelLeadOffDetect()
akpc806a 1:4683702d7ad8 1769 {
akpc806a 1:4683702d7ad8 1770 byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1771
akpc806a 1:4683702d7ad8 1772 for(int b=0; b<2; b++){
akpc806a 1:4683702d7ad8 1773 if(b == 0){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; }
akpc806a 1:4683702d7ad8 1774 if(b == 1){
akpc806a 1:4683702d7ad8 1775 if(!daisyPresent){ return; }
akpc806a 1:4683702d7ad8 1776 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1777 }
akpc806a 1:4683702d7ad8 1778
akpc806a 1:4683702d7ad8 1779 SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1780 byte P_setting = RREG(LOFF_SENSP,targetSS);
akpc806a 1:4683702d7ad8 1781 byte N_setting = RREG(LOFF_SENSN,targetSS);
akpc806a 1:4683702d7ad8 1782
akpc806a 1:4683702d7ad8 1783 for(int i=startChan; i<endChan; i++){
akpc806a 1:4683702d7ad8 1784 if(leadOffSettings[i][PCHAN] == ON){
akpc806a 1:4683702d7ad8 1785 bitSet(P_setting,i-startChan);
akpc806a 1:4683702d7ad8 1786 }else{
akpc806a 1:4683702d7ad8 1787 bitClear(P_setting,i-startChan);
akpc806a 1:4683702d7ad8 1788 }
akpc806a 1:4683702d7ad8 1789 if(leadOffSettings[i][NCHAN] == ON){
akpc806a 1:4683702d7ad8 1790 bitSet(N_setting,i-startChan);
akpc806a 1:4683702d7ad8 1791 }else{
akpc806a 1:4683702d7ad8 1792 bitClear(N_setting,i-startChan);
akpc806a 1:4683702d7ad8 1793 }
akpc806a 1:4683702d7ad8 1794 WREG(LOFF_SENSP,P_setting,targetSS);
akpc806a 1:4683702d7ad8 1795 WREG(LOFF_SENSN,N_setting,targetSS);
akpc806a 1:4683702d7ad8 1796 }
akpc806a 1:4683702d7ad8 1797 }
akpc806a 1:4683702d7ad8 1798 }
akpc806a 1:4683702d7ad8 1799
akpc806a 1:4683702d7ad8 1800 // change the lead off detect settings for specified channel
akpc806a 1:4683702d7ad8 1801 void OpenBCI_32bit_Library::changeChannelLeadOffDetect(byte N)
akpc806a 1:4683702d7ad8 1802 {
akpc806a 1:4683702d7ad8 1803 byte setting, targetSS, startChan, endChan;
akpc806a 1:4683702d7ad8 1804
akpc806a 1:4683702d7ad8 1805 if(N < 9){
akpc806a 1:4683702d7ad8 1806 targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1807 }else{
akpc806a 1:4683702d7ad8 1808 if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1809 targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1810 }
akpc806a 1:4683702d7ad8 1811
akpc806a 1:4683702d7ad8 1812 N = constrain(N-1,startChan,endChan-1);
akpc806a 1:4683702d7ad8 1813 SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1814 byte P_setting = RREG(LOFF_SENSP,targetSS);
akpc806a 1:4683702d7ad8 1815 byte N_setting = RREG(LOFF_SENSN,targetSS);
akpc806a 1:4683702d7ad8 1816
akpc806a 1:4683702d7ad8 1817 if(leadOffSettings[N][PCHAN] == ON){
akpc806a 1:4683702d7ad8 1818 bitSet(P_setting,N-startChan);
akpc806a 1:4683702d7ad8 1819 }else{
akpc806a 1:4683702d7ad8 1820 bitClear(P_setting,N-startChan);
akpc806a 1:4683702d7ad8 1821 }
akpc806a 1:4683702d7ad8 1822 if(leadOffSettings[N][NCHAN] == ON){
akpc806a 1:4683702d7ad8 1823 bitSet(N_setting,N-startChan);
akpc806a 1:4683702d7ad8 1824 }else{
akpc806a 1:4683702d7ad8 1825 bitClear(N_setting,N-startChan);
akpc806a 1:4683702d7ad8 1826 }
akpc806a 1:4683702d7ad8 1827 WREG(LOFF_SENSP,P_setting,targetSS);
akpc806a 1:4683702d7ad8 1828 WREG(LOFF_SENSN,N_setting,targetSS);
akpc806a 1:4683702d7ad8 1829 }
akpc806a 1:4683702d7ad8 1830
akpc806a 1:4683702d7ad8 1831 void OpenBCI_32bit_Library::configureLeadOffDetection(byte amplitudeCode, byte freqCode)
akpc806a 1:4683702d7ad8 1832 {
akpc806a 1:4683702d7ad8 1833 amplitudeCode &= 0b00001100; //only these two bits should be used
akpc806a 1:4683702d7ad8 1834 freqCode &= 0b00000011; //only these two bits should be used
akpc806a 1:4683702d7ad8 1835
akpc806a 1:4683702d7ad8 1836 byte setting, targetSS;
akpc806a 1:4683702d7ad8 1837 for(int i=0; i<2; i++){
akpc806a 1:4683702d7ad8 1838 if(i == 0){ targetSS = BOARD_ADS; }
akpc806a 1:4683702d7ad8 1839 if(i == 1){
akpc806a 1:4683702d7ad8 1840 if(!daisyPresent){ return; }
akpc806a 1:4683702d7ad8 1841 targetSS = DAISY_ADS;
akpc806a 1:4683702d7ad8 1842 }
akpc806a 1:4683702d7ad8 1843 setting = RREG(LOFF,targetSS); //get the current bias settings
akpc806a 1:4683702d7ad8 1844 //reconfigure the byte to get what we want
akpc806a 1:4683702d7ad8 1845 setting &= 0b11110000; //clear out the last four bits
akpc806a 1:4683702d7ad8 1846 setting |= amplitudeCode; //set the amplitude
akpc806a 1:4683702d7ad8 1847 setting |= freqCode; //set the frequency
akpc806a 1:4683702d7ad8 1848 //send the config byte back to the hardware
akpc806a 1:4683702d7ad8 1849 WREG(LOFF,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1850 }
akpc806a 1:4683702d7ad8 1851 }
akpc806a 1:4683702d7ad8 1852
akpc806a 1:4683702d7ad8 1853 // // deactivate the given channel.
akpc806a 1:4683702d7ad8 1854 // void OpenBCI_32bit_Library::deactivateChannel(byte N)
akpc806a 1:4683702d7ad8 1855 // {
akpc806a 1:4683702d7ad8 1856 // byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1857 // if(N < 9){
akpc806a 1:4683702d7ad8 1858 // targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1859 // }else{
akpc806a 1:4683702d7ad8 1860 // if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1861 // targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1862 // }
akpc806a 1:4683702d7ad8 1863 // SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1864 // N = constrain(N-1,startChan,endChan-1); //subtracts 1 so that we're counting from 0, not 1
akpc806a 1:4683702d7ad8 1865
akpc806a 1:4683702d7ad8 1866 // setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings
akpc806a 1:4683702d7ad8 1867 // bitSet(setting,7); // set bit7 to shut down channel
akpc806a 1:4683702d7ad8 1868 // bitClear(setting,3); // clear bit3 to disclude from SRB2 if used
akpc806a 1:4683702d7ad8 1869 // WREG(CH1SET+(N-startChan),setting,targetSS); delay(1); // write the new value to disable the channel
akpc806a 1:4683702d7ad8 1870
akpc806a 1:4683702d7ad8 1871 // //remove the channel from the bias generation...
akpc806a 1:4683702d7ad8 1872 // setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings
akpc806a 1:4683702d7ad8 1873 // bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1874 // WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1875
akpc806a 1:4683702d7ad8 1876 // setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings
akpc806a 1:4683702d7ad8 1877 // bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1878 // WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1879
akpc806a 1:4683702d7ad8 1880 // leadOffSettings[N][PCHAN] = leadOffSettings[N][NCHAN] = NO;
akpc806a 1:4683702d7ad8 1881 // leadOffSetForChannel(N+1, NO, NO);
akpc806a 1:4683702d7ad8 1882 // }
akpc806a 1:4683702d7ad8 1883
akpc806a 1:4683702d7ad8 1884 // void OpenBCI_32bit_Library::activateChannel(byte N)
akpc806a 1:4683702d7ad8 1885 // {
akpc806a 1:4683702d7ad8 1886 // byte setting, startChan, endChan, targetSS;
akpc806a 1:4683702d7ad8 1887 // if(N < 9){
akpc806a 1:4683702d7ad8 1888 // targetSS = BOARD_ADS; startChan = 0; endChan = 8;
akpc806a 1:4683702d7ad8 1889 // }else{
akpc806a 1:4683702d7ad8 1890 // if(!daisyPresent) { return; }
akpc806a 1:4683702d7ad8 1891 // targetSS = DAISY_ADS; startChan = 8; endChan = 16;
akpc806a 1:4683702d7ad8 1892 // }
akpc806a 1:4683702d7ad8 1893
akpc806a 1:4683702d7ad8 1894 // N = constrain(N-1,startChan,endChan-1); // 0-7 or 8-15
akpc806a 1:4683702d7ad8 1895
akpc806a 1:4683702d7ad8 1896 // SDATAC(targetSS); // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1897 // setting = 0x00;
akpc806a 1:4683702d7ad8 1898 // // channelSettings[N][POWER_DOWN] = NO; // keep track of channel on/off in this array REMOVE?
akpc806a 1:4683702d7ad8 1899 // setting |= channelSettings[N][GAIN_SET]; // gain
akpc806a 1:4683702d7ad8 1900 // setting |= channelSettings[N][INPUT_TYPE_SET]; // input code
akpc806a 1:4683702d7ad8 1901 // if(useSRB2[N] == true){channelSettings[N][SRB2_SET] = YES;}else{channelSettings[N][SRB2_SET] = NO;}
akpc806a 1:4683702d7ad8 1902 // if(channelSettings[N][SRB2_SET] == YES) {bitSet(setting,3);} // close this SRB2 switch
akpc806a 1:4683702d7ad8 1903 // WREG(CH1SET+(N-startChan),setting,targetSS);
akpc806a 1:4683702d7ad8 1904 // // add or remove from inclusion in BIAS generation
akpc806a 1:4683702d7ad8 1905 // if(useInBias[N]){channelSettings[N][BIAS_SET] = YES;}else{channelSettings[N][BIAS_SET] = NO;}
akpc806a 1:4683702d7ad8 1906 // setting = RREG(BIAS_SENSP,targetSS); //get the current P bias settings
akpc806a 1:4683702d7ad8 1907 // if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1908 // bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1909 // useInBias[N] = true;
akpc806a 1:4683702d7ad8 1910 // }else{
akpc806a 1:4683702d7ad8 1911 // bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1912 // useInBias[N] = false;
akpc806a 1:4683702d7ad8 1913 // }
akpc806a 1:4683702d7ad8 1914 // WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1915 // setting = RREG(BIAS_SENSN,targetSS); //get the current N bias settings
akpc806a 1:4683702d7ad8 1916 // if(channelSettings[N][BIAS_SET] == YES){
akpc806a 1:4683702d7ad8 1917 // bitSet(setting,N-startChan); //set this channel's bit to add it to the bias generation
akpc806a 1:4683702d7ad8 1918 // }else{
akpc806a 1:4683702d7ad8 1919 // bitClear(setting,N-startChan); // clear this channel's bit to remove from bias generation
akpc806a 1:4683702d7ad8 1920 // }
akpc806a 1:4683702d7ad8 1921 // WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 1922
akpc806a 1:4683702d7ad8 1923 // setting = 0x00;
akpc806a 1:4683702d7ad8 1924 // if(targetSS == BOARD_ADS && boardUseSRB1 == true) setting = 0x20;
akpc806a 1:4683702d7ad8 1925 // if(targetSS == DAISY_ADS && daisyUseSRB1 == true) setting = 0x20;
akpc806a 1:4683702d7ad8 1926 // WREG(MISC1,setting,targetSS); // close all SRB1 swtiches
akpc806a 1:4683702d7ad8 1927 // }
akpc806a 1:4683702d7ad8 1928
akpc806a 1:4683702d7ad8 1929 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1930 ///////////// LEAD OFF METHODS ///////////////
akpc806a 1:4683702d7ad8 1931 //////////////////////////////////////////////
akpc806a 1:4683702d7ad8 1932
akpc806a 1:4683702d7ad8 1933 /**
akpc806a 1:4683702d7ad8 1934 * @description Runs through the `leadOffSettings` global array to set/change
akpc806a 1:4683702d7ad8 1935 * the lead off signals for all inputs of all channels.
akpc806a 1:4683702d7ad8 1936 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1937 */
akpc806a 1:4683702d7ad8 1938 // void OpenBCI_32bit_Library::leadOffSetForAllChannels(void) {
akpc806a 1:4683702d7ad8 1939 // byte channelNumberUpperLimit;
akpc806a 1:4683702d7ad8 1940
akpc806a 1:4683702d7ad8 1941 // // The upper limit of the channels, either 8 or 16
akpc806a 1:4683702d7ad8 1942 // channelNumberUpperLimit = daisyPresent ? OPENBCI_NUMBER_OF_CHANNELS_DAISY : OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
akpc806a 1:4683702d7ad8 1943
akpc806a 1:4683702d7ad8 1944 // // Loop through all channels
akpc806a 1:4683702d7ad8 1945 // for (int i = 1; i <= channelNumberUpperLimit; i++) {
akpc806a 1:4683702d7ad8 1946 // leadOffSetForChannel((byte)i,leadOffSettings[i-1][PCHAN],leadOffSettings[i-1][NCHAN]);
akpc806a 1:4683702d7ad8 1947 // }
akpc806a 1:4683702d7ad8 1948 // }
akpc806a 1:4683702d7ad8 1949
akpc806a 1:4683702d7ad8 1950 /**
akpc806a 1:4683702d7ad8 1951 * @description Used to set lead off for a channel
akpc806a 1:4683702d7ad8 1952 * @param `channelNumber` - [byte] - The channel you want to change
akpc806a 1:4683702d7ad8 1953 * @param `pInput` - [byte] - Apply signal to P input, either ON (1) or OFF (0)
akpc806a 1:4683702d7ad8 1954 * @param `nInput` - [byte] - Apply signal to N input, either ON (1) or OFF (0)
akpc806a 1:4683702d7ad8 1955 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 1956 */
akpc806a 1:4683702d7ad8 1957 // void OpenBCI_32bit_Library::leadOffSetForChannel(byte channelNumber, byte pInput, byte nInput) {
akpc806a 1:4683702d7ad8 1958
akpc806a 1:4683702d7ad8 1959 // // contstrain the channel number to 0-15
akpc806a 1:4683702d7ad8 1960 // channelNumber = getConstrainedChannelNumber(channelNumber);
akpc806a 1:4683702d7ad8 1961
akpc806a 1:4683702d7ad8 1962 // // Get the slave select pin for this channel
akpc806a 1:4683702d7ad8 1963 // byte targetSS = getTargetSSForConstrainedChannelNumber(channelNumber);
akpc806a 1:4683702d7ad8 1964
akpc806a 1:4683702d7ad8 1965 // // exit Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 1966 // SDATAC(targetSS);
akpc806a 1:4683702d7ad8 1967 // delay(1);
akpc806a 1:4683702d7ad8 1968
akpc806a 1:4683702d7ad8 1969 // // Read P register
akpc806a 1:4683702d7ad8 1970 // byte P_setting = RREG(LOFF_SENSP,targetSS);
akpc806a 1:4683702d7ad8 1971
akpc806a 1:4683702d7ad8 1972 // // Read N register
akpc806a 1:4683702d7ad8 1973 // byte N_setting = RREG(LOFF_SENSN,targetSS);
akpc806a 1:4683702d7ad8 1974
akpc806a 1:4683702d7ad8 1975 // // Since we are addressing 8 bit registers, we need to subtract 8 from the
akpc806a 1:4683702d7ad8 1976 // // channelNumber if we are addressing the Daisy ADS
akpc806a 1:4683702d7ad8 1977 // if (targetSS == DAISY_ADS) {
akpc806a 1:4683702d7ad8 1978 // channelNumber -= OPENBCI_NUMBER_OF_CHANNELS_DEFAULT;
akpc806a 1:4683702d7ad8 1979 // }
akpc806a 1:4683702d7ad8 1980
akpc806a 1:4683702d7ad8 1981 // // If pInput is ON then we want to set, otherwise we want to clear
akpc806a 1:4683702d7ad8 1982 // if (pInput == ON) {
akpc806a 1:4683702d7ad8 1983 // bitSet(P_setting, channelNumber);
akpc806a 1:4683702d7ad8 1984 // } else {
akpc806a 1:4683702d7ad8 1985 // bitClear(P_setting, channelNumber);
akpc806a 1:4683702d7ad8 1986 // }
akpc806a 1:4683702d7ad8 1987 // // Write to the P register
akpc806a 1:4683702d7ad8 1988 // WREG(LOFF_SENSP,P_setting,targetSS);
akpc806a 1:4683702d7ad8 1989
akpc806a 1:4683702d7ad8 1990 // // If nInput is ON then we want to set, otherwise we want to clear
akpc806a 1:4683702d7ad8 1991 // if (nInput == ON) {
akpc806a 1:4683702d7ad8 1992 // bitSet(N_setting, channelNumber);
akpc806a 1:4683702d7ad8 1993 // } else {
akpc806a 1:4683702d7ad8 1994 // bitClear(N_setting, channelNumber);
akpc806a 1:4683702d7ad8 1995 // }
akpc806a 1:4683702d7ad8 1996 // // Write to the N register
akpc806a 1:4683702d7ad8 1997 // WREG(LOFF_SENSN,N_setting,targetSS);
akpc806a 1:4683702d7ad8 1998 // }
akpc806a 1:4683702d7ad8 1999
akpc806a 1:4683702d7ad8 2000 /**
akpc806a 1:4683702d7ad8 2001 * @description This sets the LOFF register on the Board ADS and the Daisy ADS
akpc806a 1:4683702d7ad8 2002 * @param `amplitudeCode` - [byte] - The amplitude of the of impedance signal.
akpc806a 1:4683702d7ad8 2003 * See `.setleadOffForSS()` for complete description
akpc806a 1:4683702d7ad8 2004 * @param `freqCode` - [byte] - The frequency of the impedance signal can be either.
akpc806a 1:4683702d7ad8 2005 * See `.setleadOffForSS()` for complete description
akpc806a 1:4683702d7ad8 2006 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 2007 */
akpc806a 1:4683702d7ad8 2008 // void OpenBCI_32bit_Library::leadOffConfigureSignalForAll(byte amplitudeCode, byte freqCode)
akpc806a 1:4683702d7ad8 2009 // {
akpc806a 1:4683702d7ad8 2010 // // Set the lead off detection for the on board ADS
akpc806a 1:4683702d7ad8 2011 // leadOffConfigureSignalForTargetSS(BOARD_ADS, amplitudeCode, freqCode);
akpc806a 1:4683702d7ad8 2012
akpc806a 1:4683702d7ad8 2013 // // if the daisy board is present, set that register as well
akpc806a 1:4683702d7ad8 2014 // if (daisyPresent) {
akpc806a 1:4683702d7ad8 2015 // leadOffConfigureSignalForTargetSS(DAISY_ADS, amplitudeCode, freqCode);
akpc806a 1:4683702d7ad8 2016 // }
akpc806a 1:4683702d7ad8 2017 // }
akpc806a 1:4683702d7ad8 2018
akpc806a 1:4683702d7ad8 2019 /**
akpc806a 1:4683702d7ad8 2020 * @description This sets the LOFF (lead off) register for the given ADS with slave
akpc806a 1:4683702d7ad8 2021 * select
akpc806a 1:4683702d7ad8 2022 * @param `targetSS` - [byte] - The Slave Select pin.
akpc806a 1:4683702d7ad8 2023 * @param `amplitudeCode` - [byte] - The amplitude of the of impedance signal.
akpc806a 1:4683702d7ad8 2024 * LOFF_MAG_6NA (0b00000000)
akpc806a 1:4683702d7ad8 2025 * LOFF_MAG_24NA (0b00000100)
akpc806a 1:4683702d7ad8 2026 * LOFF_MAG_6UA (0b00001000)
akpc806a 1:4683702d7ad8 2027 * LOFF_MAG_24UA (0b00001100)
akpc806a 1:4683702d7ad8 2028 * @param `freqCode` - [byte] - The frequency of the impedance signal can be either.
akpc806a 1:4683702d7ad8 2029 * LOFF_FREQ_DC (0b00000000)
akpc806a 1:4683702d7ad8 2030 * LOFF_FREQ_7p8HZ (0b00000001)
akpc806a 1:4683702d7ad8 2031 * LOFF_FREQ_31p2HZ (0b00000010)
akpc806a 1:4683702d7ad8 2032 * LOFF_FREQ_FS_4 (0b00000011)
akpc806a 1:4683702d7ad8 2033 * @author Joel/Leif/Conor (@OpenBCI) Summer 2014
akpc806a 1:4683702d7ad8 2034 */
akpc806a 1:4683702d7ad8 2035 // void OpenBCI_32bit_Library::leadOffConfigureSignalForTargetSS(byte targetSS, byte amplitudeCode, byte freqCode) {
akpc806a 1:4683702d7ad8 2036 // byte setting;
akpc806a 1:4683702d7ad8 2037
akpc806a 1:4683702d7ad8 2038 // amplitudeCode &= 0b00001100; //only these two bits should be used
akpc806a 1:4683702d7ad8 2039 // freqCode &= 0b00000011; //only these two bits should be used
akpc806a 1:4683702d7ad8 2040
akpc806a 1:4683702d7ad8 2041 // setting = RREG(LOFF,targetSS); //get the current bias settings
akpc806a 1:4683702d7ad8 2042 // //reconfigure the byte to get what we want
akpc806a 1:4683702d7ad8 2043 // setting &= 0b11110000; //clear out the last four bits
akpc806a 1:4683702d7ad8 2044 // setting |= amplitudeCode; //set the amplitude
akpc806a 1:4683702d7ad8 2045 // setting |= freqCode; //set the frequency
akpc806a 1:4683702d7ad8 2046 // //send the config byte back to the hardware
akpc806a 1:4683702d7ad8 2047 // WREG(LOFF,setting,targetSS); delay(1); //send the modified byte back to the ADS
akpc806a 1:4683702d7ad8 2048 // }
akpc806a 1:4683702d7ad8 2049
akpc806a 1:4683702d7ad8 2050 //Configure the test signals that can be inernally generated by the ADS1299
akpc806a 1:4683702d7ad8 2051 void OpenBCI_32bit_Library::configureInternalTestSignal(byte amplitudeCode, byte freqCode)
akpc806a 1:4683702d7ad8 2052 {
akpc806a 1:4683702d7ad8 2053 byte setting, targetSS;
akpc806a 1:4683702d7ad8 2054 for(int i=0; i<2; i++){
akpc806a 1:4683702d7ad8 2055 if(i == 0){ targetSS = BOARD_ADS;}
akpc806a 1:4683702d7ad8 2056 if(i == 1){
akpc806a 1:4683702d7ad8 2057 if(daisyPresent == false){ return; }
akpc806a 1:4683702d7ad8 2058 targetSS = DAISY_ADS;
akpc806a 1:4683702d7ad8 2059 }
akpc806a 1:4683702d7ad8 2060 if (amplitudeCode == ADSTESTSIG_NOCHANGE) amplitudeCode = (RREG(CONFIG2,targetSS) & (0b00000100));
akpc806a 1:4683702d7ad8 2061 if (freqCode == ADSTESTSIG_NOCHANGE) freqCode = (RREG(CONFIG2,targetSS) & (0b00000011));
akpc806a 1:4683702d7ad8 2062 freqCode &= 0b00000011; //only the last two bits are used
akpc806a 1:4683702d7ad8 2063 amplitudeCode &= 0b00000100; //only this bit is used
akpc806a 1:4683702d7ad8 2064 byte setting = 0b11010000 | freqCode | amplitudeCode; //compose the code
akpc806a 1:4683702d7ad8 2065 WREG(CONFIG2,setting,targetSS); delay(1);
akpc806a 1:4683702d7ad8 2066 if (sniffMode && Serial1) {
akpc806a 1:4683702d7ad8 2067 Serial1.print("Wrote to CONFIG2: ");
akpc806a 1:4683702d7ad8 2068 Serial1.print(setting,BIN);
akpc806a 1:4683702d7ad8 2069 }
akpc806a 1:4683702d7ad8 2070 }
akpc806a 1:4683702d7ad8 2071 }
akpc806a 1:4683702d7ad8 2072
akpc806a 1:4683702d7ad8 2073 void OpenBCI_32bit_Library::changeInputType(byte inputCode){
akpc806a 1:4683702d7ad8 2074
akpc806a 1:4683702d7ad8 2075 for(int i=0; i<numChannels; i++){
akpc806a 1:4683702d7ad8 2076 channelSettings[i][INPUT_TYPE_SET] = inputCode;
akpc806a 1:4683702d7ad8 2077 }
akpc806a 1:4683702d7ad8 2078
akpc806a 1:4683702d7ad8 2079 // OLD CODE REVERT
akpc806a 1:4683702d7ad8 2080 //channelSettingsArraySetForAll();
akpc806a 1:4683702d7ad8 2081
akpc806a 1:4683702d7ad8 2082 writeChannelSettings();
akpc806a 1:4683702d7ad8 2083 }
akpc806a 1:4683702d7ad8 2084
akpc806a 1:4683702d7ad8 2085 // Start continuous data acquisition
akpc806a 1:4683702d7ad8 2086 void OpenBCI_32bit_Library::startADS(void) // NEEDS ADS ADDRESS, OR BOTH?
akpc806a 1:4683702d7ad8 2087 {
akpc806a 1:4683702d7ad8 2088 sampleCounter = 0;
akpc806a 1:4683702d7ad8 2089 firstDataPacket = true;
akpc806a 1:4683702d7ad8 2090 RDATAC(BOTH_ADS); // enter Read Data Continuous mode
akpc806a 1:4683702d7ad8 2091 delay(1);
akpc806a 1:4683702d7ad8 2092 START(BOTH_ADS); // start the data acquisition
akpc806a 1:4683702d7ad8 2093 delay(1);
akpc806a 1:4683702d7ad8 2094 isRunning = true;
akpc806a 1:4683702d7ad8 2095 }
akpc806a 1:4683702d7ad8 2096
akpc806a 1:4683702d7ad8 2097 /**
akpc806a 1:4683702d7ad8 2098 * @description Check status register to see if data is available from the ADS1299.
akpc806a 1:4683702d7ad8 2099 * @returns {boolean} - `true` if data is available
akpc806a 1:4683702d7ad8 2100 */
akpc806a 1:4683702d7ad8 2101 boolean OpenBCI_32bit_Library::waitForNewChannelData(void) {
akpc806a 1:4683702d7ad8 2102 return !isADSDataAvailable();
akpc806a 1:4683702d7ad8 2103 }
akpc806a 1:4683702d7ad8 2104
akpc806a 1:4683702d7ad8 2105 /**
akpc806a 1:4683702d7ad8 2106 * @description Check status register to see if data is available from the ADS1299.
akpc806a 1:4683702d7ad8 2107 * @returns {boolean} - `true` if data is available
akpc806a 1:4683702d7ad8 2108 */
akpc806a 1:4683702d7ad8 2109 boolean OpenBCI_32bit_Library::isADSDataAvailable(void) {
akpc806a 1:4683702d7ad8 2110 return (!(digitalRead(ADS_DRDY)));
akpc806a 1:4683702d7ad8 2111 }
akpc806a 1:4683702d7ad8 2112
akpc806a 1:4683702d7ad8 2113 // CALLED WHEN DRDY PIN IS ASSERTED. NEW ADS DATA AVAILABLE!
akpc806a 1:4683702d7ad8 2114 void OpenBCI_32bit_Library::updateChannelData(){
akpc806a 1:4683702d7ad8 2115 // this needs to be reset, or else it will constantly flag us
akpc806a 1:4683702d7ad8 2116 channelDataAvailable = false;
akpc806a 1:4683702d7ad8 2117 updateBoardData();
akpc806a 1:4683702d7ad8 2118 if(daisyPresent) {updateDaisyData();}
akpc806a 1:4683702d7ad8 2119 }
akpc806a 1:4683702d7ad8 2120
akpc806a 1:4683702d7ad8 2121 void OpenBCI_32bit_Library::updateBoardData(){
akpc806a 1:4683702d7ad8 2122 byte inByte;
akpc806a 1:4683702d7ad8 2123 int byteCounter = 0;
akpc806a 1:4683702d7ad8 2124
akpc806a 1:4683702d7ad8 2125 if(daisyPresent && !firstDataPacket){
akpc806a 1:4683702d7ad8 2126 for(int i=0; i < 8; i++){ // shift and average the byte arrays
akpc806a 1:4683702d7ad8 2127 lastBoardChannelDataInt[i] = boardChannelDataInt[i]; // remember the last samples
akpc806a 1:4683702d7ad8 2128 }
akpc806a 1:4683702d7ad8 2129 }
akpc806a 1:4683702d7ad8 2130
akpc806a 1:4683702d7ad8 2131 csLow(BOARD_ADS); // open SPI
akpc806a 1:4683702d7ad8 2132 for(int i=0; i<3; i++){
akpc806a 1:4683702d7ad8 2133 inByte = xfer(0x00); // read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
akpc806a 1:4683702d7ad8 2134 boardStat = (boardStat << 8) | inByte;
akpc806a 1:4683702d7ad8 2135 }
akpc806a 1:4683702d7ad8 2136 for(int i = 0; i<8; i++){
akpc806a 1:4683702d7ad8 2137 for(int j=0; j<3; j++){ // read 24 bits of channel data in 8 3 byte chunks
akpc806a 1:4683702d7ad8 2138 inByte = xfer(0x00);
akpc806a 1:4683702d7ad8 2139 boardChannelDataRaw[byteCounter] = inByte; // raw data goes here
akpc806a 1:4683702d7ad8 2140 byteCounter++;
akpc806a 1:4683702d7ad8 2141 boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte; // int data goes here
akpc806a 1:4683702d7ad8 2142 }
akpc806a 1:4683702d7ad8 2143 }
akpc806a 1:4683702d7ad8 2144 csHigh(BOARD_ADS); // close SPI
akpc806a 1:4683702d7ad8 2145
akpc806a 1:4683702d7ad8 2146 // need to convert 24bit to 32bit if using the filter
akpc806a 1:4683702d7ad8 2147 for(int i=0; i<8; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
akpc806a 1:4683702d7ad8 2148 if(bitRead(boardChannelDataInt[i],23) == 1){
akpc806a 1:4683702d7ad8 2149 boardChannelDataInt[i] |= 0xFF000000;
akpc806a 1:4683702d7ad8 2150 } else{
akpc806a 1:4683702d7ad8 2151 boardChannelDataInt[i] &= 0x00FFFFFF;
akpc806a 1:4683702d7ad8 2152 }
akpc806a 1:4683702d7ad8 2153 }
akpc806a 1:4683702d7ad8 2154 if(daisyPresent && !firstDataPacket){
akpc806a 1:4683702d7ad8 2155 byteCounter = 0;
akpc806a 1:4683702d7ad8 2156 for(int i=0; i<8; i++){ // take the average of this and the last sample
akpc806a 1:4683702d7ad8 2157 meanBoardChannelDataInt[i] = (lastBoardChannelDataInt[i] + boardChannelDataInt[i])/2;
akpc806a 1:4683702d7ad8 2158 }
akpc806a 1:4683702d7ad8 2159 for(int i=0; i<8; i++){ // place the average values in the meanRaw array
akpc806a 1:4683702d7ad8 2160 for(int b=2; b>=0; b--){
akpc806a 1:4683702d7ad8 2161 meanBoardDataRaw[byteCounter] = (meanBoardChannelDataInt[i] >> (b*8)) & 0xFF;
akpc806a 1:4683702d7ad8 2162 byteCounter++;
akpc806a 1:4683702d7ad8 2163 }
akpc806a 1:4683702d7ad8 2164 }
akpc806a 1:4683702d7ad8 2165 }
akpc806a 1:4683702d7ad8 2166
akpc806a 1:4683702d7ad8 2167 if(firstDataPacket == true){
akpc806a 1:4683702d7ad8 2168 firstDataPacket = false;
akpc806a 1:4683702d7ad8 2169 }
akpc806a 1:4683702d7ad8 2170 }
akpc806a 1:4683702d7ad8 2171
akpc806a 1:4683702d7ad8 2172 void OpenBCI_32bit_Library::updateDaisyData(){
akpc806a 1:4683702d7ad8 2173 byte inByte;
akpc806a 1:4683702d7ad8 2174 int byteCounter = 0;
akpc806a 1:4683702d7ad8 2175
akpc806a 1:4683702d7ad8 2176 if(daisyPresent && !firstDataPacket){
akpc806a 1:4683702d7ad8 2177 for(int i=0; i<8; i++){ // shift and average the byte arrays
akpc806a 1:4683702d7ad8 2178 lastDaisyChannelDataInt[i] = daisyChannelDataInt[i]; // remember the last samples
akpc806a 1:4683702d7ad8 2179 }
akpc806a 1:4683702d7ad8 2180 }
akpc806a 1:4683702d7ad8 2181
akpc806a 1:4683702d7ad8 2182 csLow(DAISY_ADS); // open SPI
akpc806a 1:4683702d7ad8 2183 for(int i=0; i<3; i++){
akpc806a 1:4683702d7ad8 2184 inByte = xfer(0x00); // read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
akpc806a 1:4683702d7ad8 2185 daisyStat = (daisyStat << 8) | inByte;
akpc806a 1:4683702d7ad8 2186 }
akpc806a 1:4683702d7ad8 2187 for(int i = 0; i<8; i++){
akpc806a 1:4683702d7ad8 2188 for(int j=0; j<3; j++){ // read 24 bits of channel data in 8 3 byte chunks
akpc806a 1:4683702d7ad8 2189 inByte = xfer(0x00);
akpc806a 1:4683702d7ad8 2190 daisyChannelDataRaw[byteCounter] = inByte; // raw data goes here
akpc806a 1:4683702d7ad8 2191 byteCounter++;
akpc806a 1:4683702d7ad8 2192 daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte; // int data goes here
akpc806a 1:4683702d7ad8 2193 }
akpc806a 1:4683702d7ad8 2194 }
akpc806a 1:4683702d7ad8 2195 csHigh(DAISY_ADS); // close SPI
akpc806a 1:4683702d7ad8 2196 // need to convert 24bit to 32bit
akpc806a 1:4683702d7ad8 2197 for(int i=0; i<8; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
akpc806a 1:4683702d7ad8 2198 if(bitRead(daisyChannelDataInt[i],23) == 1){
akpc806a 1:4683702d7ad8 2199 daisyChannelDataInt[i] |= 0xFF000000;
akpc806a 1:4683702d7ad8 2200 }else{
akpc806a 1:4683702d7ad8 2201 daisyChannelDataInt[i] &= 0x00FFFFFF;
akpc806a 1:4683702d7ad8 2202 }
akpc806a 1:4683702d7ad8 2203 }
akpc806a 1:4683702d7ad8 2204 if(daisyPresent && !firstDataPacket){
akpc806a 1:4683702d7ad8 2205 byteCounter = 0;
akpc806a 1:4683702d7ad8 2206 for(int i=0; i<8; i++){ // average this sample with the last sample
akpc806a 1:4683702d7ad8 2207 meanDaisyChannelDataInt[i] = (lastDaisyChannelDataInt[i] + daisyChannelDataInt[i])/2;
akpc806a 1:4683702d7ad8 2208 }
akpc806a 1:4683702d7ad8 2209 for(int i=0; i<8; i++){ // place the average values in the meanRaw array
akpc806a 1:4683702d7ad8 2210 for(int b=2; b>=0; b--){
akpc806a 1:4683702d7ad8 2211 meanDaisyDataRaw[byteCounter] = (meanDaisyChannelDataInt[i] >> (b*8)) & 0xFF;
akpc806a 1:4683702d7ad8 2212 byteCounter++;
akpc806a 1:4683702d7ad8 2213 }
akpc806a 1:4683702d7ad8 2214 }
akpc806a 1:4683702d7ad8 2215 }
akpc806a 1:4683702d7ad8 2216
akpc806a 1:4683702d7ad8 2217 if(firstDataPacket == true) {
akpc806a 1:4683702d7ad8 2218 firstDataPacket = false;
akpc806a 1:4683702d7ad8 2219 }
akpc806a 1:4683702d7ad8 2220 }
akpc806a 1:4683702d7ad8 2221
akpc806a 1:4683702d7ad8 2222 // Stop the continuous data acquisition
akpc806a 1:4683702d7ad8 2223 void OpenBCI_32bit_Library::stopADS()
akpc806a 1:4683702d7ad8 2224 {
akpc806a 1:4683702d7ad8 2225 STOP(BOTH_ADS); // stop the data acquisition
akpc806a 1:4683702d7ad8 2226 delay(1);
akpc806a 1:4683702d7ad8 2227 SDATAC(BOTH_ADS); // stop Read Data Continuous mode to communicate with ADS
akpc806a 1:4683702d7ad8 2228 delay(1);
akpc806a 1:4683702d7ad8 2229 isRunning = false;
akpc806a 1:4683702d7ad8 2230 }
akpc806a 1:4683702d7ad8 2231
akpc806a 1:4683702d7ad8 2232
akpc806a 1:4683702d7ad8 2233 //write as binary each channel's data
akpc806a 1:4683702d7ad8 2234 void OpenBCI_32bit_Library::ADS_writeChannelData()
akpc806a 1:4683702d7ad8 2235 {
akpc806a 1:4683702d7ad8 2236
akpc806a 1:4683702d7ad8 2237 if(daisyPresent){
akpc806a 1:4683702d7ad8 2238 if(sampleCounter % 2 != 0){ //CHECK SAMPLE ODD-EVEN AND SEND THE APPROPRIATE ADS DATA
akpc806a 1:4683702d7ad8 2239 for (int i=0; i<24; i++){
akpc806a 1:4683702d7ad8 2240 Serial0.write(meanBoardDataRaw[i]); // send board data on odd samples
akpc806a 1:4683702d7ad8 2241 }
akpc806a 1:4683702d7ad8 2242 }else{
akpc806a 1:4683702d7ad8 2243 for (int i=0; i<24; i++){
akpc806a 1:4683702d7ad8 2244 Serial0.write(meanDaisyDataRaw[i]); // send daisy data on even samples
akpc806a 1:4683702d7ad8 2245 }
akpc806a 1:4683702d7ad8 2246 }
akpc806a 1:4683702d7ad8 2247 }else{
akpc806a 1:4683702d7ad8 2248 for(int i=0; i<24; i++){
akpc806a 1:4683702d7ad8 2249 Serial0.write(boardChannelDataRaw[i]);
akpc806a 1:4683702d7ad8 2250 }
akpc806a 1:4683702d7ad8 2251 }
akpc806a 1:4683702d7ad8 2252 }
akpc806a 1:4683702d7ad8 2253
akpc806a 1:4683702d7ad8 2254
akpc806a 1:4683702d7ad8 2255 //print out the state of all the control registers
akpc806a 1:4683702d7ad8 2256 void OpenBCI_32bit_Library::printADSregisters(int targetSS)
akpc806a 1:4683702d7ad8 2257 {
akpc806a 1:4683702d7ad8 2258 boolean prevverbosityState = verbosity;
akpc806a 1:4683702d7ad8 2259 verbosity = true; // set up for verbosity output
akpc806a 1:4683702d7ad8 2260 RREGS(0x00,0x0C,targetSS); // read out the first registers
akpc806a 1:4683702d7ad8 2261 delay(10); // stall to let all that data get read by the PC
akpc806a 1:4683702d7ad8 2262 RREGS(0x0D,0x17-0x0D,targetSS); // read out the rest
akpc806a 1:4683702d7ad8 2263 verbosity = prevverbosityState;
akpc806a 1:4683702d7ad8 2264 }
akpc806a 1:4683702d7ad8 2265
akpc806a 1:4683702d7ad8 2266 byte OpenBCI_32bit_Library::ADS_getDeviceID(int targetSS) { // simple hello world com check
akpc806a 1:4683702d7ad8 2267 byte data = RREG(ID_REG,targetSS);
akpc806a 1:4683702d7ad8 2268 if(verbosity){ // verbosity otuput
akpc806a 1:4683702d7ad8 2269 Serial0.print("On Board ADS ID ");
akpc806a 1:4683702d7ad8 2270 printHex(data); Serial0.println();
akpc806a 1:4683702d7ad8 2271 sendEOT();
akpc806a 1:4683702d7ad8 2272 }
akpc806a 1:4683702d7ad8 2273 return data;
akpc806a 1:4683702d7ad8 2274 }
akpc806a 1:4683702d7ad8 2275
akpc806a 1:4683702d7ad8 2276 //System Commands
akpc806a 1:4683702d7ad8 2277 void OpenBCI_32bit_Library::WAKEUP(int targetSS) {
akpc806a 1:4683702d7ad8 2278 csLow(targetSS);
akpc806a 1:4683702d7ad8 2279 xfer(_WAKEUP);
akpc806a 1:4683702d7ad8 2280 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2281 delayMicroseconds(3); //must wait 4 tCLK cycles before sending another command (Datasheet, pg. 35)
akpc806a 1:4683702d7ad8 2282 }
akpc806a 1:4683702d7ad8 2283
akpc806a 1:4683702d7ad8 2284 void OpenBCI_32bit_Library::STANDBY(int targetSS) { // only allowed to send WAKEUP after sending STANDBY
akpc806a 1:4683702d7ad8 2285 csLow(targetSS);
akpc806a 1:4683702d7ad8 2286 xfer(_STANDBY);
akpc806a 1:4683702d7ad8 2287 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2288 }
akpc806a 1:4683702d7ad8 2289
akpc806a 1:4683702d7ad8 2290 void OpenBCI_32bit_Library::RESET(int targetSS) { // reset all the registers to default settings
akpc806a 1:4683702d7ad8 2291 csLow(targetSS);
akpc806a 1:4683702d7ad8 2292 xfer(_RESET);
akpc806a 1:4683702d7ad8 2293 delayMicroseconds(12); //must wait 18 tCLK cycles to execute this command (Datasheet, pg. 35)
akpc806a 1:4683702d7ad8 2294 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2295 }
akpc806a 1:4683702d7ad8 2296
akpc806a 1:4683702d7ad8 2297 void OpenBCI_32bit_Library::START(int targetSS) { //start data conversion
akpc806a 1:4683702d7ad8 2298 csLow(targetSS);
akpc806a 1:4683702d7ad8 2299 xfer(_START); // KEEP ON-BOARD AND ON-DAISY IN SYNC
akpc806a 1:4683702d7ad8 2300 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2301 }
akpc806a 1:4683702d7ad8 2302
akpc806a 1:4683702d7ad8 2303 void OpenBCI_32bit_Library::STOP(int targetSS) { //stop data conversion
akpc806a 1:4683702d7ad8 2304 csLow(targetSS);
akpc806a 1:4683702d7ad8 2305 xfer(_STOP); // KEEP ON-BOARD AND ON-DAISY IN SYNC
akpc806a 1:4683702d7ad8 2306 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2307 }
akpc806a 1:4683702d7ad8 2308
akpc806a 1:4683702d7ad8 2309 void OpenBCI_32bit_Library::RDATAC(int targetSS) {
akpc806a 1:4683702d7ad8 2310 csLow(targetSS);
akpc806a 1:4683702d7ad8 2311 xfer(_RDATAC); // read data continuous
akpc806a 1:4683702d7ad8 2312 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2313 delayMicroseconds(3);
akpc806a 1:4683702d7ad8 2314 }
akpc806a 1:4683702d7ad8 2315 void OpenBCI_32bit_Library::SDATAC(int targetSS) {
akpc806a 1:4683702d7ad8 2316 csLow(targetSS);
akpc806a 1:4683702d7ad8 2317 xfer(_SDATAC);
akpc806a 1:4683702d7ad8 2318 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2319 delayMicroseconds(10); //must wait at least 4 tCLK cycles after executing this command (Datasheet, pg. 37)
akpc806a 1:4683702d7ad8 2320 }
akpc806a 1:4683702d7ad8 2321
akpc806a 1:4683702d7ad8 2322
akpc806a 1:4683702d7ad8 2323 // THIS NEEDS CLEANING AND UPDATING TO THE NEW FORMAT
akpc806a 1:4683702d7ad8 2324 void OpenBCI_32bit_Library::RDATA(int targetSS) { // use in Stop Read Continuous mode when DRDY goes low
akpc806a 1:4683702d7ad8 2325 byte inByte; // to read in one sample of the channels
akpc806a 1:4683702d7ad8 2326 csLow(targetSS); // open SPI
akpc806a 1:4683702d7ad8 2327 xfer(_RDATA); // send the RDATA command
akpc806a 1:4683702d7ad8 2328 for(int i=0; i<3; i++){ // read in the status register and new channel data
akpc806a 1:4683702d7ad8 2329 inByte = xfer(0x00);
akpc806a 1:4683702d7ad8 2330 boardStat = (boardStat<<8) | inByte; // read status register (1100 + LOFF_STATP + LOFF_STATN + GPIO[7:4])
akpc806a 1:4683702d7ad8 2331 }
akpc806a 1:4683702d7ad8 2332 if(targetSS == BOARD_ADS){
akpc806a 1:4683702d7ad8 2333 for(int i = 0; i<8; i++){
akpc806a 1:4683702d7ad8 2334 for(int j=0; j<3; j++){ // read in the new channel data
akpc806a 1:4683702d7ad8 2335 inByte = xfer(0x00);
akpc806a 1:4683702d7ad8 2336 boardChannelDataInt[i] = (boardChannelDataInt[i]<<8) | inByte;
akpc806a 1:4683702d7ad8 2337 }
akpc806a 1:4683702d7ad8 2338 }
akpc806a 1:4683702d7ad8 2339 for(int i=0; i<8; i++){
akpc806a 1:4683702d7ad8 2340 if(bitRead(boardChannelDataInt[i],23) == 1){ // convert 3 byte 2's compliment to 4 byte 2's compliment
akpc806a 1:4683702d7ad8 2341 boardChannelDataInt[i] |= 0xFF000000;
akpc806a 1:4683702d7ad8 2342 }else{
akpc806a 1:4683702d7ad8 2343 boardChannelDataInt[i] &= 0x00FFFFFF;
akpc806a 1:4683702d7ad8 2344 }
akpc806a 1:4683702d7ad8 2345 }
akpc806a 1:4683702d7ad8 2346 }else{
akpc806a 1:4683702d7ad8 2347 for(int i = 0; i<8; i++){
akpc806a 1:4683702d7ad8 2348 for(int j=0; j<3; j++){ // read in the new channel data
akpc806a 1:4683702d7ad8 2349 inByte = xfer(0x00);
akpc806a 1:4683702d7ad8 2350 daisyChannelDataInt[i] = (daisyChannelDataInt[i]<<8) | inByte;
akpc806a 1:4683702d7ad8 2351 }
akpc806a 1:4683702d7ad8 2352 }
akpc806a 1:4683702d7ad8 2353 for(int i=0; i<8; i++){
akpc806a 1:4683702d7ad8 2354 if(bitRead(daisyChannelDataInt[i],23) == 1){ // convert 3 byte 2's compliment to 4 byte 2's compliment
akpc806a 1:4683702d7ad8 2355 daisyChannelDataInt[i] |= 0xFF000000;
akpc806a 1:4683702d7ad8 2356 }else{
akpc806a 1:4683702d7ad8 2357 daisyChannelDataInt[i] &= 0x00FFFFFF;
akpc806a 1:4683702d7ad8 2358 }
akpc806a 1:4683702d7ad8 2359 }
akpc806a 1:4683702d7ad8 2360 }
akpc806a 1:4683702d7ad8 2361 csHigh(targetSS); // close SPI
akpc806a 1:4683702d7ad8 2362
akpc806a 1:4683702d7ad8 2363
akpc806a 1:4683702d7ad8 2364 }
akpc806a 1:4683702d7ad8 2365
akpc806a 1:4683702d7ad8 2366 byte OpenBCI_32bit_Library::RREG(byte _address,int targetSS) { // reads ONE register at _address
akpc806a 1:4683702d7ad8 2367 byte opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
akpc806a 1:4683702d7ad8 2368 csLow(targetSS); // open SPI
akpc806a 1:4683702d7ad8 2369 xfer(opcode1); // opcode1
akpc806a 1:4683702d7ad8 2370 xfer(0x00); // opcode2
akpc806a 1:4683702d7ad8 2371 regData[_address] = xfer(0x00);// update mirror location with returned byte
akpc806a 1:4683702d7ad8 2372 csHigh(targetSS); // close SPI
akpc806a 1:4683702d7ad8 2373 if (verbosity){ // verbosity output
akpc806a 1:4683702d7ad8 2374 printRegisterName(_address);
akpc806a 1:4683702d7ad8 2375 printHex(_address);
akpc806a 1:4683702d7ad8 2376 Serial0.print(", ");
akpc806a 1:4683702d7ad8 2377 printHex(regData[_address]);
akpc806a 1:4683702d7ad8 2378 Serial0.print(", ");
akpc806a 1:4683702d7ad8 2379 for(byte j = 0; j<8; j++){
akpc806a 1:4683702d7ad8 2380 Serial0.print(bitRead(regData[_address], 7-j));
akpc806a 1:4683702d7ad8 2381 if(j!=7) Serial0.print(", ");
akpc806a 1:4683702d7ad8 2382 }
akpc806a 1:4683702d7ad8 2383
akpc806a 1:4683702d7ad8 2384 Serial0.println();
akpc806a 1:4683702d7ad8 2385 }
akpc806a 1:4683702d7ad8 2386 return regData[_address]; // return requested register value
akpc806a 1:4683702d7ad8 2387 }
akpc806a 1:4683702d7ad8 2388
akpc806a 1:4683702d7ad8 2389
akpc806a 1:4683702d7ad8 2390 // Read more than one register starting at _address
akpc806a 1:4683702d7ad8 2391 void OpenBCI_32bit_Library::RREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
akpc806a 1:4683702d7ad8 2392
akpc806a 1:4683702d7ad8 2393 byte opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
akpc806a 1:4683702d7ad8 2394 csLow(targetSS); // open SPI
akpc806a 1:4683702d7ad8 2395 xfer(opcode1); // opcode1
akpc806a 1:4683702d7ad8 2396 xfer(_numRegistersMinusOne); // opcode2
akpc806a 1:4683702d7ad8 2397 for(int i = 0; i <= _numRegistersMinusOne; i++){
akpc806a 1:4683702d7ad8 2398 regData[_address + i] = xfer(0x00); // add register byte to mirror array
akpc806a 1:4683702d7ad8 2399 }
akpc806a 1:4683702d7ad8 2400 csHigh(targetSS); // close SPI
akpc806a 1:4683702d7ad8 2401 if(verbosity){ // verbosity output
akpc806a 1:4683702d7ad8 2402 for(int i = 0; i<= _numRegistersMinusOne; i++){
akpc806a 1:4683702d7ad8 2403 printRegisterName(_address + i);
akpc806a 1:4683702d7ad8 2404 printHex(_address + i);
akpc806a 1:4683702d7ad8 2405 Serial0.print(", ");
akpc806a 1:4683702d7ad8 2406 printHex(regData[_address + i]);
akpc806a 1:4683702d7ad8 2407 Serial0.print(", ");
akpc806a 1:4683702d7ad8 2408 for(int j = 0; j<8; j++){
akpc806a 1:4683702d7ad8 2409 Serial0.print(bitRead(regData[_address + i], 7-j));
akpc806a 1:4683702d7ad8 2410 if(j!=7) Serial0.print(", ");
akpc806a 1:4683702d7ad8 2411 }
akpc806a 1:4683702d7ad8 2412 Serial0.println();
akpc806a 1:4683702d7ad8 2413 delay(30);
akpc806a 1:4683702d7ad8 2414 }
akpc806a 1:4683702d7ad8 2415 }
akpc806a 1:4683702d7ad8 2416 }
akpc806a 1:4683702d7ad8 2417
akpc806a 1:4683702d7ad8 2418 void OpenBCI_32bit_Library::WREG(byte _address, byte _value, int target_SS) { // Write ONE register at _address
akpc806a 1:4683702d7ad8 2419 byte opcode1 = _address + 0x40; // WREG expects 010rrrrr where rrrrr = _address
akpc806a 1:4683702d7ad8 2420 csLow(target_SS); // open SPI
akpc806a 1:4683702d7ad8 2421 xfer(opcode1); // Send WREG command & address
akpc806a 1:4683702d7ad8 2422 xfer(0x00); // Send number of registers to read -1
akpc806a 1:4683702d7ad8 2423 xfer(_value); // Write the value to the register
akpc806a 1:4683702d7ad8 2424 csHigh(target_SS); // close SPI
akpc806a 1:4683702d7ad8 2425 regData[_address] = _value; // update the mirror array
akpc806a 1:4683702d7ad8 2426 if(verbosity){ // verbosity output
akpc806a 1:4683702d7ad8 2427 Serial0.print("Register ");
akpc806a 1:4683702d7ad8 2428 printHex(_address);
akpc806a 1:4683702d7ad8 2429 Serial0.println(" modified.");
akpc806a 1:4683702d7ad8 2430 sendEOT();
akpc806a 1:4683702d7ad8 2431 }
akpc806a 1:4683702d7ad8 2432 }
akpc806a 1:4683702d7ad8 2433
akpc806a 1:4683702d7ad8 2434 void OpenBCI_32bit_Library::WREGS(byte _address, byte _numRegistersMinusOne, int targetSS) {
akpc806a 1:4683702d7ad8 2435 byte opcode1 = _address + 0x40; // WREG expects 010rrrrr where rrrrr = _address
akpc806a 1:4683702d7ad8 2436 csLow(targetSS); // open SPI
akpc806a 1:4683702d7ad8 2437 xfer(opcode1); // Send WREG command & address
akpc806a 1:4683702d7ad8 2438 xfer(_numRegistersMinusOne); // Send number of registers to read -1
akpc806a 1:4683702d7ad8 2439 for (int i=_address; i <=(_address + _numRegistersMinusOne); i++){
akpc806a 1:4683702d7ad8 2440 xfer(regData[i]); // Write to the registers
akpc806a 1:4683702d7ad8 2441 }
akpc806a 1:4683702d7ad8 2442 csHigh(targetSS);
akpc806a 1:4683702d7ad8 2443 if(verbosity){
akpc806a 1:4683702d7ad8 2444 Serial0.print("Registers ");
akpc806a 1:4683702d7ad8 2445 printHex(_address); Serial0.print(" to ");
akpc806a 1:4683702d7ad8 2446 printHex(_address + _numRegistersMinusOne);
akpc806a 1:4683702d7ad8 2447 Serial0.println(" modified");
akpc806a 1:4683702d7ad8 2448 sendEOT();
akpc806a 1:4683702d7ad8 2449 }
akpc806a 1:4683702d7ad8 2450 }
akpc806a 1:4683702d7ad8 2451
akpc806a 1:4683702d7ad8 2452
akpc806a 1:4683702d7ad8 2453 // <<<<<<<<<<<<<<<<<<<<<<<<< END OF ADS1299 FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 2454 // ******************************************************************************
akpc806a 1:4683702d7ad8 2455 // <<<<<<<<<<<<<<<<<<<<<<<<< LIS3DH FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 2456
akpc806a 1:4683702d7ad8 2457
akpc806a 1:4683702d7ad8 2458 void OpenBCI_32bit_Library::initialize_accel(byte g){
akpc806a 1:4683702d7ad8 2459 byte setting = g | 0x08; // mask the g range for REG4
akpc806a 1:4683702d7ad8 2460 pinMode(LIS3DH_DRDY,INPUT); // setup dataReady interupt from accelerometer
akpc806a 1:4683702d7ad8 2461 LIS3DH_write(TMP_CFG_REG, 0x00); // DISable ADC inputs, enable temperature sensor
akpc806a 1:4683702d7ad8 2462 LIS3DH_write(CTRL_REG1, 0x08); // disable accel, low power mode
akpc806a 1:4683702d7ad8 2463 LIS3DH_write(CTRL_REG2, 0x00); // don't use the high pass filter
akpc806a 1:4683702d7ad8 2464 LIS3DH_write(CTRL_REG3, 0x00); // no interrupts yet
akpc806a 1:4683702d7ad8 2465 LIS3DH_write(CTRL_REG4, setting); // set scale to g, high resolution
akpc806a 1:4683702d7ad8 2466 LIS3DH_write(CTRL_REG5, 0x00); // no boot, no fifo
akpc806a 1:4683702d7ad8 2467 LIS3DH_write(CTRL_REG6, 0x00);
akpc806a 1:4683702d7ad8 2468 LIS3DH_write(REFERENCE, 0x00);
akpc806a 1:4683702d7ad8 2469 DRDYpinValue = lastDRDYpinValue = digitalRead(LIS3DH_DRDY); // take a reading to seed these variables
akpc806a 1:4683702d7ad8 2470 }
akpc806a 1:4683702d7ad8 2471
akpc806a 1:4683702d7ad8 2472 void OpenBCI_32bit_Library::enable_accel(byte Hz){
akpc806a 1:4683702d7ad8 2473 for(int i=0; i<3; i++){
akpc806a 1:4683702d7ad8 2474 axisData[i] = 0; // clear the axisData array so we don't get any stale news
akpc806a 1:4683702d7ad8 2475 }
akpc806a 1:4683702d7ad8 2476 byte setting = Hz | 0x07; // mask the desired frequency
akpc806a 1:4683702d7ad8 2477 LIS3DH_write(CTRL_REG1, setting); // set freq and enable all axis in normal mode
akpc806a 1:4683702d7ad8 2478 LIS3DH_write(CTRL_REG3, 0x10); // enable DRDY1 on INT1 (tied to PIC pin 0, LIS3DH_DRDY)
akpc806a 1:4683702d7ad8 2479 }
akpc806a 1:4683702d7ad8 2480
akpc806a 1:4683702d7ad8 2481 void OpenBCI_32bit_Library::disable_accel(){
akpc806a 1:4683702d7ad8 2482 LIS3DH_write(CTRL_REG1, 0x08); // power down, low power mode
akpc806a 1:4683702d7ad8 2483 LIS3DH_write(CTRL_REG3, 0x00); // disable DRDY1 on INT1
akpc806a 1:4683702d7ad8 2484 }
akpc806a 1:4683702d7ad8 2485
akpc806a 1:4683702d7ad8 2486 byte OpenBCI_32bit_Library::LIS3DH_getDeviceID(){
akpc806a 1:4683702d7ad8 2487 return LIS3DH_read(WHO_AM_I);
akpc806a 1:4683702d7ad8 2488 }
akpc806a 1:4683702d7ad8 2489
akpc806a 1:4683702d7ad8 2490 boolean OpenBCI_32bit_Library::LIS3DH_DataAvailable(){
akpc806a 1:4683702d7ad8 2491 boolean x = false;
akpc806a 1:4683702d7ad8 2492 if((LIS3DH_read(STATUS_REG2) & 0x08) > 0) x = true; // read STATUS_REG
akpc806a 1:4683702d7ad8 2493 return x;
akpc806a 1:4683702d7ad8 2494 }
akpc806a 1:4683702d7ad8 2495
akpc806a 1:4683702d7ad8 2496 boolean OpenBCI_32bit_Library::LIS3DH_DataReady(){
akpc806a 1:4683702d7ad8 2497 boolean r = false;
akpc806a 1:4683702d7ad8 2498 DRDYpinValue = digitalRead(LIS3DH_DRDY); // take a look at LIS3DH_DRDY pin
akpc806a 1:4683702d7ad8 2499 if(DRDYpinValue != lastDRDYpinValue){ // if the value has changed since last looking
akpc806a 1:4683702d7ad8 2500 if(DRDYpinValue == HIGH){ // see if this is the rising edge
akpc806a 1:4683702d7ad8 2501 r = true; // if so, there is fresh data!
akpc806a 1:4683702d7ad8 2502 }
akpc806a 1:4683702d7ad8 2503 lastDRDYpinValue = DRDYpinValue; // keep track of the changing pin
akpc806a 1:4683702d7ad8 2504 }
akpc806a 1:4683702d7ad8 2505 return r;
akpc806a 1:4683702d7ad8 2506 }
akpc806a 1:4683702d7ad8 2507
akpc806a 1:4683702d7ad8 2508 void OpenBCI_32bit_Library::LIS3DH_writeAxisData(void){
akpc806a 1:4683702d7ad8 2509 for(int i=0; i<3; i++){
akpc806a 1:4683702d7ad8 2510 Serial0.write(highByte(axisData[i])); // write 16 bit axis data MSB first
akpc806a 1:4683702d7ad8 2511 Serial0.write(lowByte(axisData[i])); // axisData is array of type short (16bit)
akpc806a 1:4683702d7ad8 2512 axisData[i] = 0;
akpc806a 1:4683702d7ad8 2513 }
akpc806a 1:4683702d7ad8 2514 }
akpc806a 1:4683702d7ad8 2515
akpc806a 1:4683702d7ad8 2516 void OpenBCI_32bit_Library::LIS3DH_writeAxisDataForAxis(uint8_t axis) {
akpc806a 1:4683702d7ad8 2517 if (axis > 2) axis = 0;
akpc806a 1:4683702d7ad8 2518 Serial0.write(highByte(axisData[axis])); // write 16 bit axis data MSB first
akpc806a 1:4683702d7ad8 2519 Serial0.write(lowByte(axisData[axis])); // axisData is array of type short (16bit)
akpc806a 1:4683702d7ad8 2520 axisData[axis] = 0;
akpc806a 1:4683702d7ad8 2521 }
akpc806a 1:4683702d7ad8 2522
akpc806a 1:4683702d7ad8 2523 byte OpenBCI_32bit_Library::LIS3DH_read(byte reg){
akpc806a 1:4683702d7ad8 2524 reg |= READ_REG; // add the READ_REG bit
akpc806a 1:4683702d7ad8 2525 csLow(LIS3DH_SS); // take spi
akpc806a 1:4683702d7ad8 2526 spi.transfer(reg); // send reg to read
akpc806a 1:4683702d7ad8 2527 byte inByte = spi.transfer(0x00); // retrieve data
akpc806a 1:4683702d7ad8 2528 csHigh(LIS3DH_SS); // release spi
akpc806a 1:4683702d7ad8 2529 return inByte;
akpc806a 1:4683702d7ad8 2530 }
akpc806a 1:4683702d7ad8 2531
akpc806a 1:4683702d7ad8 2532 void OpenBCI_32bit_Library::LIS3DH_write(byte reg, byte value){
akpc806a 1:4683702d7ad8 2533 csLow(LIS3DH_SS); // take spi
akpc806a 1:4683702d7ad8 2534 spi.transfer(reg); // send reg to write
akpc806a 1:4683702d7ad8 2535 spi.transfer(value); // write value
akpc806a 1:4683702d7ad8 2536 csHigh(LIS3DH_SS); // release spi
akpc806a 1:4683702d7ad8 2537 }
akpc806a 1:4683702d7ad8 2538
akpc806a 1:4683702d7ad8 2539 int OpenBCI_32bit_Library::LIS3DH_read16(byte reg){ // use for reading axis data.
akpc806a 1:4683702d7ad8 2540 int inData;
akpc806a 1:4683702d7ad8 2541 reg |= READ_REG | READ_MULTI; // add the READ_REG and READ_MULTI bits
akpc806a 1:4683702d7ad8 2542 csLow(LIS3DH_SS); // take spi
akpc806a 1:4683702d7ad8 2543 spi.transfer(reg); // send reg to start reading from
akpc806a 1:4683702d7ad8 2544 inData = spi.transfer(0x00) | (spi.transfer(0x00) << 8); // get the data and arrange it
akpc806a 1:4683702d7ad8 2545 csHigh(LIS3DH_SS); // release spi
akpc806a 1:4683702d7ad8 2546 return inData;
akpc806a 1:4683702d7ad8 2547 }
akpc806a 1:4683702d7ad8 2548
akpc806a 1:4683702d7ad8 2549 int OpenBCI_32bit_Library::getX(){
akpc806a 1:4683702d7ad8 2550 return LIS3DH_read16(OUT_X_L);
akpc806a 1:4683702d7ad8 2551 }
akpc806a 1:4683702d7ad8 2552
akpc806a 1:4683702d7ad8 2553 int OpenBCI_32bit_Library::getY(){
akpc806a 1:4683702d7ad8 2554 return LIS3DH_read16(OUT_Y_L);
akpc806a 1:4683702d7ad8 2555 }
akpc806a 1:4683702d7ad8 2556
akpc806a 1:4683702d7ad8 2557 int OpenBCI_32bit_Library::getZ(){
akpc806a 1:4683702d7ad8 2558 return LIS3DH_read16(OUT_Z_L);
akpc806a 1:4683702d7ad8 2559 }
akpc806a 1:4683702d7ad8 2560
akpc806a 1:4683702d7ad8 2561 void OpenBCI_32bit_Library::LIS3DH_updateAxisData(){
akpc806a 1:4683702d7ad8 2562 axisData[0] = getX();
akpc806a 1:4683702d7ad8 2563 axisData[1] = getY();
akpc806a 1:4683702d7ad8 2564 axisData[2] = getZ();
akpc806a 1:4683702d7ad8 2565 }
akpc806a 1:4683702d7ad8 2566
akpc806a 1:4683702d7ad8 2567 void OpenBCI_32bit_Library::LIS3DH_readAllRegs(){
akpc806a 1:4683702d7ad8 2568
akpc806a 1:4683702d7ad8 2569 byte inByte;
akpc806a 1:4683702d7ad8 2570
akpc806a 1:4683702d7ad8 2571 for (int i = STATUS_REG_AUX; i <= WHO_AM_I; i++){
akpc806a 1:4683702d7ad8 2572 inByte = LIS3DH_read(i);
akpc806a 1:4683702d7ad8 2573 Serial0.print("0x0");Serial0.print(i,HEX);
akpc806a 1:4683702d7ad8 2574 Serial0.print("\t");Serial0.println(inByte,HEX);
akpc806a 1:4683702d7ad8 2575 delay(20);
akpc806a 1:4683702d7ad8 2576 }
akpc806a 1:4683702d7ad8 2577 Serial0.println();
akpc806a 1:4683702d7ad8 2578
akpc806a 1:4683702d7ad8 2579 for (int i = TMP_CFG_REG; i <= INT1_DURATION; i++){
akpc806a 1:4683702d7ad8 2580 inByte = LIS3DH_read(i);
akpc806a 1:4683702d7ad8 2581 // printRegisterName(i);
akpc806a 1:4683702d7ad8 2582 Serial0.print("0x");Serial0.print(i,HEX);
akpc806a 1:4683702d7ad8 2583 Serial0.print("\t");Serial0.println(inByte,HEX);
akpc806a 1:4683702d7ad8 2584 delay(20);
akpc806a 1:4683702d7ad8 2585 }
akpc806a 1:4683702d7ad8 2586 Serial0.println();
akpc806a 1:4683702d7ad8 2587
akpc806a 1:4683702d7ad8 2588 for (int i = CLICK_CFG; i <= TIME_WINDOW; i++){
akpc806a 1:4683702d7ad8 2589 inByte = LIS3DH_read(i);
akpc806a 1:4683702d7ad8 2590 Serial0.print("0x");Serial0.print(i,HEX);
akpc806a 1:4683702d7ad8 2591 Serial0.print("\t");Serial0.println(inByte,HEX);
akpc806a 1:4683702d7ad8 2592 delay(20);
akpc806a 1:4683702d7ad8 2593 }
akpc806a 1:4683702d7ad8 2594
akpc806a 1:4683702d7ad8 2595 }
akpc806a 1:4683702d7ad8 2596
akpc806a 1:4683702d7ad8 2597
akpc806a 1:4683702d7ad8 2598
akpc806a 1:4683702d7ad8 2599 // <<<<<<<<<<<<<<<<<<<<<<<<< END OF LIS3DH FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
akpc806a 1:4683702d7ad8 2600
akpc806a 1:4683702d7ad8 2601
akpc806a 1:4683702d7ad8 2602
akpc806a 1:4683702d7ad8 2603 // String-Byte converters for ADS
akpc806a 1:4683702d7ad8 2604 void OpenBCI_32bit_Library::printRegisterName(byte _address) {
akpc806a 1:4683702d7ad8 2605 switch(_address){
akpc806a 1:4683702d7ad8 2606 case ID_REG:
akpc806a 1:4683702d7ad8 2607 Serial0.print("ADS_ID, "); break;
akpc806a 1:4683702d7ad8 2608 case CONFIG1:
akpc806a 1:4683702d7ad8 2609 Serial0.print("CONFIG1, "); break;
akpc806a 1:4683702d7ad8 2610 case CONFIG2:
akpc806a 1:4683702d7ad8 2611 Serial0.print("CONFIG2, "); break;
akpc806a 1:4683702d7ad8 2612 case CONFIG3:
akpc806a 1:4683702d7ad8 2613 Serial0.print("CONFIG3, "); break;
akpc806a 1:4683702d7ad8 2614 case LOFF:
akpc806a 1:4683702d7ad8 2615 Serial0.print("LOFF, "); break;
akpc806a 1:4683702d7ad8 2616 case CH1SET:
akpc806a 1:4683702d7ad8 2617 Serial0.print("CH1SET, "); break;
akpc806a 1:4683702d7ad8 2618 case CH2SET:
akpc806a 1:4683702d7ad8 2619 Serial0.print("CH2SET, "); break;
akpc806a 1:4683702d7ad8 2620 case CH3SET:
akpc806a 1:4683702d7ad8 2621 Serial0.print("CH3SET, "); break;
akpc806a 1:4683702d7ad8 2622 case CH4SET:
akpc806a 1:4683702d7ad8 2623 Serial0.print("CH4SET, "); break;
akpc806a 1:4683702d7ad8 2624 case CH5SET:
akpc806a 1:4683702d7ad8 2625 Serial0.print("CH5SET, "); break;
akpc806a 1:4683702d7ad8 2626 case CH6SET:
akpc806a 1:4683702d7ad8 2627 Serial0.print("CH6SET, "); break;
akpc806a 1:4683702d7ad8 2628 case CH7SET:
akpc806a 1:4683702d7ad8 2629 Serial0.print("CH7SET, "); break;
akpc806a 1:4683702d7ad8 2630 case CH8SET:
akpc806a 1:4683702d7ad8 2631 Serial0.print("CH8SET, "); break;
akpc806a 1:4683702d7ad8 2632 case BIAS_SENSP:
akpc806a 1:4683702d7ad8 2633 Serial0.print("BIAS_SENSP, "); break;
akpc806a 1:4683702d7ad8 2634 case BIAS_SENSN:
akpc806a 1:4683702d7ad8 2635 Serial0.print("BIAS_SENSN, "); break;
akpc806a 1:4683702d7ad8 2636 case LOFF_SENSP:
akpc806a 1:4683702d7ad8 2637 Serial0.print("LOFF_SENSP, "); break;
akpc806a 1:4683702d7ad8 2638 case LOFF_SENSN:
akpc806a 1:4683702d7ad8 2639 Serial0.print("LOFF_SENSN, "); break;
akpc806a 1:4683702d7ad8 2640 case LOFF_FLIP:
akpc806a 1:4683702d7ad8 2641 Serial0.print("LOFF_FLIP, "); break;
akpc806a 1:4683702d7ad8 2642 case LOFF_STATP:
akpc806a 1:4683702d7ad8 2643 Serial0.print("LOFF_STATP, "); break;
akpc806a 1:4683702d7ad8 2644 case LOFF_STATN:
akpc806a 1:4683702d7ad8 2645 Serial0.print("LOFF_STATN, "); break;
akpc806a 1:4683702d7ad8 2646 case GPIO:
akpc806a 1:4683702d7ad8 2647 Serial0.print("GPIO, "); break;
akpc806a 1:4683702d7ad8 2648 case MISC1:
akpc806a 1:4683702d7ad8 2649 Serial0.print("MISC1, "); break;
akpc806a 1:4683702d7ad8 2650 case MISC2:
akpc806a 1:4683702d7ad8 2651 Serial0.print("MISC2, "); break;
akpc806a 1:4683702d7ad8 2652 case CONFIG4:
akpc806a 1:4683702d7ad8 2653 Serial0.print("CONFIG4, "); break;
akpc806a 1:4683702d7ad8 2654 default:
akpc806a 1:4683702d7ad8 2655 break;
akpc806a 1:4683702d7ad8 2656 }
akpc806a 1:4683702d7ad8 2657 }
akpc806a 1:4683702d7ad8 2658
akpc806a 1:4683702d7ad8 2659 // Used for printing HEX in verbosity feedback mode
akpc806a 1:4683702d7ad8 2660 void OpenBCI_32bit_Library::printHex(byte _data){
akpc806a 1:4683702d7ad8 2661 Serial0.print("0x");
akpc806a 1:4683702d7ad8 2662 if(_data < 0x10) Serial0.print("0");
akpc806a 1:4683702d7ad8 2663 Serial0.print(_data, HEX);
akpc806a 1:4683702d7ad8 2664 }
akpc806a 1:4683702d7ad8 2665
akpc806a 1:4683702d7ad8 2666 /**
akpc806a 1:4683702d7ad8 2667 * @description Converts ascii character to byte value for channel setting bytes
akpc806a 1:4683702d7ad8 2668 * @param `asciiChar` - [char] - The ascii character to convert
akpc806a 1:4683702d7ad8 2669 * @return [char] - Byte number value of acsii character, defaults to 0
akpc806a 1:4683702d7ad8 2670 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 2671 */
akpc806a 1:4683702d7ad8 2672 char OpenBCI_32bit_Library::getChannelCommandForAsciiChar(char asciiChar) {
akpc806a 1:4683702d7ad8 2673 switch(asciiChar){
akpc806a 1:4683702d7ad8 2674 case OPENBCI_CHANNEL_CMD_CHANNEL_1:
akpc806a 1:4683702d7ad8 2675 return 0x00;
akpc806a 1:4683702d7ad8 2676 case OPENBCI_CHANNEL_CMD_CHANNEL_2:
akpc806a 1:4683702d7ad8 2677 return 0x01;
akpc806a 1:4683702d7ad8 2678 case OPENBCI_CHANNEL_CMD_CHANNEL_3:
akpc806a 1:4683702d7ad8 2679 return 0x02;
akpc806a 1:4683702d7ad8 2680 case OPENBCI_CHANNEL_CMD_CHANNEL_4:
akpc806a 1:4683702d7ad8 2681 return 0x03;
akpc806a 1:4683702d7ad8 2682 case OPENBCI_CHANNEL_CMD_CHANNEL_5:
akpc806a 1:4683702d7ad8 2683 return 0x04;
akpc806a 1:4683702d7ad8 2684 case OPENBCI_CHANNEL_CMD_CHANNEL_6:
akpc806a 1:4683702d7ad8 2685 return 0x05;
akpc806a 1:4683702d7ad8 2686 case OPENBCI_CHANNEL_CMD_CHANNEL_7:
akpc806a 1:4683702d7ad8 2687 return 0x06;
akpc806a 1:4683702d7ad8 2688 case OPENBCI_CHANNEL_CMD_CHANNEL_8:
akpc806a 1:4683702d7ad8 2689 return 0x07;
akpc806a 1:4683702d7ad8 2690 case OPENBCI_CHANNEL_CMD_CHANNEL_9:
akpc806a 1:4683702d7ad8 2691 return 0x08;
akpc806a 1:4683702d7ad8 2692 case OPENBCI_CHANNEL_CMD_CHANNEL_10:
akpc806a 1:4683702d7ad8 2693 return 0x09;
akpc806a 1:4683702d7ad8 2694 case OPENBCI_CHANNEL_CMD_CHANNEL_11:
akpc806a 1:4683702d7ad8 2695 return 0x0A;
akpc806a 1:4683702d7ad8 2696 case OPENBCI_CHANNEL_CMD_CHANNEL_12:
akpc806a 1:4683702d7ad8 2697 return 0x0B;
akpc806a 1:4683702d7ad8 2698 case OPENBCI_CHANNEL_CMD_CHANNEL_13:
akpc806a 1:4683702d7ad8 2699 return 0x0C;
akpc806a 1:4683702d7ad8 2700 case OPENBCI_CHANNEL_CMD_CHANNEL_14:
akpc806a 1:4683702d7ad8 2701 return 0x0D;
akpc806a 1:4683702d7ad8 2702 case OPENBCI_CHANNEL_CMD_CHANNEL_15:
akpc806a 1:4683702d7ad8 2703 return 0x0E;
akpc806a 1:4683702d7ad8 2704 case OPENBCI_CHANNEL_CMD_CHANNEL_16:
akpc806a 1:4683702d7ad8 2705 return 0x0F;
akpc806a 1:4683702d7ad8 2706 default:
akpc806a 1:4683702d7ad8 2707 return 0x00;
akpc806a 1:4683702d7ad8 2708 }
akpc806a 1:4683702d7ad8 2709 }
akpc806a 1:4683702d7ad8 2710
akpc806a 1:4683702d7ad8 2711 /**
akpc806a 1:4683702d7ad8 2712 * @description Converts ascii '0' to number 0 and ascii '1' to number 1
akpc806a 1:4683702d7ad8 2713 * @param `asciiChar` - [char] - The ascii character to convert
akpc806a 1:4683702d7ad8 2714 * @return [char] - Byte number value of acsii character, defaults to 0
akpc806a 1:4683702d7ad8 2715 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 2716 */
akpc806a 1:4683702d7ad8 2717 char OpenBCI_32bit_Library::getYesOrNoForAsciiChar(char asciiChar) {
akpc806a 1:4683702d7ad8 2718 switch (asciiChar) {
akpc806a 1:4683702d7ad8 2719 case '1':
akpc806a 1:4683702d7ad8 2720 return ACTIVATE;
akpc806a 1:4683702d7ad8 2721 case '0':
akpc806a 1:4683702d7ad8 2722 default:
akpc806a 1:4683702d7ad8 2723 return DEACTIVATE;
akpc806a 1:4683702d7ad8 2724 }
akpc806a 1:4683702d7ad8 2725 }
akpc806a 1:4683702d7ad8 2726
akpc806a 1:4683702d7ad8 2727 /**
akpc806a 1:4683702d7ad8 2728 * @description Converts ascii character to get gain from channel settings
akpc806a 1:4683702d7ad8 2729 * @param `asciiChar` - [char] - The ascii character to convert
akpc806a 1:4683702d7ad8 2730 * @return [char] - Byte number value of acsii character, defaults to 0
akpc806a 1:4683702d7ad8 2731 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 2732 */
akpc806a 1:4683702d7ad8 2733 char OpenBCI_32bit_Library::getGainForAsciiChar(char asciiChar) {
akpc806a 1:4683702d7ad8 2734
akpc806a 1:4683702d7ad8 2735 char output = 0x00;
akpc806a 1:4683702d7ad8 2736
akpc806a 1:4683702d7ad8 2737 if (asciiChar < '0' || asciiChar > '6') {
akpc806a 1:4683702d7ad8 2738 asciiChar = '6'; // Default to 24
akpc806a 1:4683702d7ad8 2739 }
akpc806a 1:4683702d7ad8 2740
akpc806a 1:4683702d7ad8 2741 output = asciiChar - '0';
akpc806a 1:4683702d7ad8 2742
akpc806a 1:4683702d7ad8 2743 return output << 4;
akpc806a 1:4683702d7ad8 2744 }
akpc806a 1:4683702d7ad8 2745
akpc806a 1:4683702d7ad8 2746 /**
akpc806a 1:4683702d7ad8 2747 * @description Converts ascii character to get gain from channel settings
akpc806a 1:4683702d7ad8 2748 * @param `asciiChar` - [char] - The ascii character to convert
akpc806a 1:4683702d7ad8 2749 * @return [char] - Byte number value of acsii character, defaults to 0
akpc806a 1:4683702d7ad8 2750 * @author AJ Keller (@pushtheworldllc)
akpc806a 1:4683702d7ad8 2751 */
akpc806a 1:4683702d7ad8 2752 char OpenBCI_32bit_Library::getNumberForAsciiChar(char asciiChar) {
akpc806a 1:4683702d7ad8 2753 if (asciiChar < '0' || asciiChar > '9') {
akpc806a 1:4683702d7ad8 2754 asciiChar = '0';
akpc806a 1:4683702d7ad8 2755 }
akpc806a 1:4683702d7ad8 2756
akpc806a 1:4683702d7ad8 2757 // Convert ascii char to number
akpc806a 1:4683702d7ad8 2758 asciiChar -= '0';
akpc806a 1:4683702d7ad8 2759
akpc806a 1:4683702d7ad8 2760 return asciiChar;
akpc806a 1:4683702d7ad8 2761 }
akpc806a 1:4683702d7ad8 2762
akpc806a 1:4683702d7ad8 2763 /**
akpc806a 1:4683702d7ad8 2764 * @description Used to set the channelSettings array to default settings
akpc806a 1:4683702d7ad8 2765 * @param `setting` - [byte] - The byte you need a setting for....
akpc806a 1:4683702d7ad8 2766 * @returns - [byte] - Retuns the proper byte for the input setting, defualts to 0
akpc806a 1:4683702d7ad8 2767 */
akpc806a 1:4683702d7ad8 2768 byte OpenBCI_32bit_Library::getDefaultChannelSettingForSetting(byte setting) {
akpc806a 1:4683702d7ad8 2769 switch (setting) {
akpc806a 1:4683702d7ad8 2770 case POWER_DOWN:
akpc806a 1:4683702d7ad8 2771 return NO;
akpc806a 1:4683702d7ad8 2772 case GAIN_SET:
akpc806a 1:4683702d7ad8 2773 return ADS_GAIN24;
akpc806a 1:4683702d7ad8 2774 case INPUT_TYPE_SET:
akpc806a 1:4683702d7ad8 2775 return ADSINPUT_NORMAL;
akpc806a 1:4683702d7ad8 2776 case BIAS_SET:
akpc806a 1:4683702d7ad8 2777 return YES;
akpc806a 1:4683702d7ad8 2778 case SRB2_SET:
akpc806a 1:4683702d7ad8 2779 return YES;
akpc806a 1:4683702d7ad8 2780 case SRB1_SET:
akpc806a 1:4683702d7ad8 2781 default:
akpc806a 1:4683702d7ad8 2782 return NO;
akpc806a 1:4683702d7ad8 2783 }
akpc806a 1:4683702d7ad8 2784 }
akpc806a 1:4683702d7ad8 2785
akpc806a 1:4683702d7ad8 2786 /**
akpc806a 1:4683702d7ad8 2787 * @description Used to set the channelSettings array to default settings
akpc806a 1:4683702d7ad8 2788 * @param `setting` - [byte] - The byte you need a setting for....
akpc806a 1:4683702d7ad8 2789 * @returns - [char] - Retuns the proper ascii char for the input setting, defaults to '0'
akpc806a 1:4683702d7ad8 2790 */
akpc806a 1:4683702d7ad8 2791 char OpenBCI_32bit_Library::getDefaultChannelSettingForSettingAscii(byte setting) {
akpc806a 1:4683702d7ad8 2792 switch (setting) {
akpc806a 1:4683702d7ad8 2793 case GAIN_SET: // Special case where GAIN_SET needs to be shifted first
akpc806a 1:4683702d7ad8 2794 return (ADS_GAIN24 >> 4) + '0';
akpc806a 1:4683702d7ad8 2795 default: // All other settings are just adding the ascii value for '0'
akpc806a 1:4683702d7ad8 2796 return getDefaultChannelSettingForSetting(setting) + '0';
akpc806a 1:4683702d7ad8 2797 }
akpc806a 1:4683702d7ad8 2798 }
akpc806a 1:4683702d7ad8 2799
akpc806a 1:4683702d7ad8 2800 /**
akpc806a 1:4683702d7ad8 2801 * @description Convert user channelNumber for use in array indexs by subtracting 1,
akpc806a 1:4683702d7ad8 2802 * also make sure N is not greater than 15 or less than 0
akpc806a 1:4683702d7ad8 2803 * @param `channelNumber` - [byte] - The channel number
akpc806a 1:4683702d7ad8 2804 * @return [byte] - Constrained channel number
akpc806a 1:4683702d7ad8 2805 */
akpc806a 1:4683702d7ad8 2806 char OpenBCI_32bit_Library::getConstrainedChannelNumber(byte channelNumber) {
akpc806a 1:4683702d7ad8 2807 return constrain(channelNumber - 1, 0, OPENBCI_NUMBER_OF_CHANNELS_DAISY - 1);
akpc806a 1:4683702d7ad8 2808 }
akpc806a 1:4683702d7ad8 2809
akpc806a 1:4683702d7ad8 2810 /**
akpc806a 1:4683702d7ad8 2811 * @description Get slave select pin for channelNumber
akpc806a 1:4683702d7ad8 2812 * @param `channelNumber` - [byte] - The channel number
akpc806a 1:4683702d7ad8 2813 * @return [byte] - Constrained channel number
akpc806a 1:4683702d7ad8 2814 */
akpc806a 1:4683702d7ad8 2815 char OpenBCI_32bit_Library::getTargetSSForConstrainedChannelNumber(byte channelNumber) {
akpc806a 1:4683702d7ad8 2816 // Is channelNumber in the range of default [0,7]
akpc806a 1:4683702d7ad8 2817 if (channelNumber < OPENBCI_NUMBER_OF_CHANNELS_DEFAULT) {
akpc806a 1:4683702d7ad8 2818 return BOARD_ADS;
akpc806a 1:4683702d7ad8 2819 } else {
akpc806a 1:4683702d7ad8 2820 return DAISY_ADS;
akpc806a 1:4683702d7ad8 2821 }
akpc806a 1:4683702d7ad8 2822 }
akpc806a 1:4683702d7ad8 2823
akpc806a 1:4683702d7ad8 2824 /**
akpc806a 1:4683702d7ad8 2825 * @description Used to set the channelSettings array to default settings
akpc806a 1:4683702d7ad8 2826 * @param `channelSettingsArray` - [byte **] - Takes a two dimensional array of
akpc806a 1:4683702d7ad8 2827 * length OPENBCI_NUMBER_OF_CHANNELS_DAISY by 6 elements
akpc806a 1:4683702d7ad8 2828 */
akpc806a 1:4683702d7ad8 2829 void OpenBCI_32bit_Library::resetChannelSettingsArrayToDefault(byte channelSettingsArray[][OPENBCI_NUMBER_OF_CHANNEL_SETTINGS]) {
akpc806a 1:4683702d7ad8 2830 // Loop through all channels
akpc806a 1:4683702d7ad8 2831 for (int i = 0; i < OPENBCI_NUMBER_OF_CHANNELS_DAISY; i++) {
akpc806a 1:4683702d7ad8 2832 channelSettingsArray[i][POWER_DOWN] = getDefaultChannelSettingForSetting(POWER_DOWN); // on = NO, off = YES
akpc806a 1:4683702d7ad8 2833 channelSettingsArray[i][GAIN_SET] = getDefaultChannelSettingForSetting(GAIN_SET); // Gain setting
akpc806a 1:4683702d7ad8 2834 channelSettingsArray[i][INPUT_TYPE_SET] = getDefaultChannelSettingForSetting(INPUT_TYPE_SET); // input muxer setting
akpc806a 1:4683702d7ad8 2835 channelSettingsArray[i][BIAS_SET] = getDefaultChannelSettingForSetting(BIAS_SET); // add this channel to bias generation
akpc806a 1:4683702d7ad8 2836 channelSettingsArray[i][SRB2_SET] = getDefaultChannelSettingForSetting(SRB2_SET); // connect this P side to SRB2
akpc806a 1:4683702d7ad8 2837 channelSettingsArray[i][SRB1_SET] = getDefaultChannelSettingForSetting(SRB1_SET); // don't use SRB1
akpc806a 1:4683702d7ad8 2838
akpc806a 1:4683702d7ad8 2839 useInBias[i] = true; // keeping track of Bias Generation
akpc806a 1:4683702d7ad8 2840 useSRB2[i] = true; // keeping track of SRB2 inclusion
akpc806a 1:4683702d7ad8 2841 }
akpc806a 1:4683702d7ad8 2842
akpc806a 1:4683702d7ad8 2843 boardUseSRB1 = daisyUseSRB1 = false;
akpc806a 1:4683702d7ad8 2844 }
akpc806a 1:4683702d7ad8 2845
akpc806a 1:4683702d7ad8 2846 /**
akpc806a 1:4683702d7ad8 2847 * @description Used to set the channelSettings array to default settings
akpc806a 1:4683702d7ad8 2848 * @param `channelSettingsArray` - [byte **] - A two dimensional array of
akpc806a 1:4683702d7ad8 2849 * length OPENBCI_NUMBER_OF_CHANNELS_DAISY by 2 elements
akpc806a 1:4683702d7ad8 2850 */
akpc806a 1:4683702d7ad8 2851 void OpenBCI_32bit_Library::resetLeadOffArrayToDefault(byte leadOffArray[][OPENBCI_NUMBER_OF_LEAD_OFF_SETTINGS]) {
akpc806a 1:4683702d7ad8 2852 // Loop through all channels
akpc806a 1:4683702d7ad8 2853 for (int i = 0; i < OPENBCI_NUMBER_OF_CHANNELS_DAISY; i++) {
akpc806a 1:4683702d7ad8 2854 leadOffArray[i][PCHAN] = OFF;
akpc806a 1:4683702d7ad8 2855 leadOffArray[i][NCHAN] = OFF;
akpc806a 1:4683702d7ad8 2856 }
akpc806a 1:4683702d7ad8 2857 }
akpc806a 1:4683702d7ad8 2858
akpc806a 1:4683702d7ad8 2859 OpenBCI_32bit_Library board;