Alex Borisevich
/
OpenBCI
OpenBCI 32bit board variation with STM32L476 mircocontroller and mbed support
OpenBCI_32bit_Library.cpp@1:4683702d7ad8, 2017-01-22 (annotated)
- 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?
User | Revision | Line number | New 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; |