diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/OpenBCI_32bit_Library.cpp b/OpenBCI_32bit_Library.cpp index 18a676f..b7804b6 100644 --- a/OpenBCI_32bit_Library.cpp +++ b/OpenBCI_32bit_Library.cpp @@ -139,6 +139,18 @@ boolean OpenBCI_32bit_Library::isProcessingMultibyteMsg(void) { return isProcessingIncomingSettingsChannel || isProcessingIncomingSettingsLeadOff || settingBoardMode || settingSampleRate; } + +/** +* @description Process one char at a time from serial port. This is the main +* command processor for the OpenBCI system. Considered mission critical for +* normal operation. +* @param `character` {char} - The character to process. +* @return {boolean} - `true` if the command was recognized, `false` if not +*/ +boolean OpenBCI_32bit_Library::processCharWifi(char character) { + // Serial0.print("pc wifi "); + return processChar(character); +} /** * @description Process one char at a time from serial port. This is the main * command processor for the OpenBCI system. Considered mission critical for @@ -147,6 +159,7 @@ boolean OpenBCI_32bit_Library::isProcessingMultibyteMsg(void) { * @return {boolean} - `true` if the command was recognized, `false` if not */ boolean OpenBCI_32bit_Library::processChar(char character) { + // Serial0.print("pC: "); Serial0.print(character); Serial0.print(" 0x"); Serial0.println(character, HEX); if (curBoardMode == BOARD_MODE_DEBUG) { Serial1.print("pC: "); Serial1.println(character); } @@ -297,7 +310,8 @@ boolean OpenBCI_32bit_Library::processChar(char character) { case OPENBCI_CHANNEL_DEFAULT_ALL_SET: // reset all channel settings to default if(!streaming) { - Serial0.println("updating channel settings to default"); + printAll("updating channel settings to"); + printAll(" default"); sendEOT(); } streamSafeSetAllChannelsToDefault(); @@ -306,8 +320,6 @@ boolean OpenBCI_32bit_Library::processChar(char character) { reportDefaultChannelSettings(); break; - - // DAISY MODULE COMMANDS case OPENBCI_CHANNEL_MAX_NUMBER_8: // use 8 channel mode if(daisyPresent){ @@ -319,9 +331,9 @@ boolean OpenBCI_32bit_Library::processChar(char character) { attachDaisy(); } if(daisyPresent){ - Serial0.print("16"); - }else{ - Serial0.print("8"); + printAll("16"); + } else { + printAll("8"); } sendEOT(); break; @@ -331,6 +343,7 @@ boolean OpenBCI_32bit_Library::processChar(char character) { if(curAccelMode == ACCEL_MODE_ON){ enable_accel(RATE_25HZ); } // fire up the accelerometer if you want it + // Serial0.println("streamStart - pc"); streamStart(); // turn on the fire hose break; case OPENBCI_STREAM_STOP: // stop streaming data @@ -384,20 +397,35 @@ boolean OpenBCI_32bit_Library::processChar(char character) { settingSampleRate = true; break; - case '}': - if (iSerial1.tx) { - char code = 'c'; - Serial1.print("ADS1299_CONFIG1_DAISY: 0x"); - Serial1.println(ADS1299_CONFIG1_DAISY, HEX); - Serial1.print("curSampleRate: 0x"); - Serial1.println(curSampleRate, HEX); - code = (char)(ADS1299_CONFIG1_DAISY | curSampleRate); - Serial1.print("Sample Rate 0x"); - Serial1.println(code, HEX); + case OPENBCI_WIFI_ATTACH: + if (wifiAttach()) { + printSuccess(); + printSerial("Wifi attached"); + sendEOT(); + } else { + printFailure(); + printSerial("Wifi not attached"); + sendEOT(); + } + break; + case OPENBCI_WIFI_REMOVE: + if (wifiRemove()) { + printSuccess(); + printSerial("Wifi removed"); + } else { + printFailure(); + printSerial("Wifi not removed"); } sendEOT(); break; - + case OPENBCI_WIFI_STATUS: + if (wifiPresent) { + printAll("Wifi present"); + } else { + printAll("Wifi not present, send {"); + printAll(" to attach the shield"); + } + sendEOT(); default: return false; } @@ -582,9 +610,8 @@ void OpenBCI_32bit_Library::boardReset(void) { * @author: AJ Keller (@pushtheworldllc) */ void OpenBCI_32bit_Library::sendEOT(void) { - Serial0.print('$'); - Serial0.print('$'); - Serial0.print('$'); + printSerial("$$$"); + wifiSendStringLast(); } void OpenBCI_32bit_Library::activateAllChannelsToTestCondition(byte testInputCode, byte amplitudeCode, byte freqCode) @@ -607,89 +634,62 @@ void OpenBCI_32bit_Library::activateAllChannelsToTestCondition(byte testInputCod } } -/** -* @description When a 'z' is found on the serial port, we jump to this function -* where we continue to read from the serial port and read the -* remaining 4 bytes. -* @param `character` - {char} - The character you want to process... -*/ void OpenBCI_32bit_Library::processIncomingBoardMode(char c) { if (c == OPENBCI_BOARD_MODE_SET) { - if (numberOfIncomingSettingsProcessedBoardType > 0) { - // did we get an optional arg? - int newBaud = OPENBCI_BAUD_RATE; - if (optionalArgCounter > 0) { - switch (optionalArgCounter) { - case 5: - optionalArgBuffer5[4] = '\0'; - newBaud = atoi(optionalArgBuffer7); - break; - case 6: - optionalArgBuffer6[5] = '\0'; - newBaud = atoi(optionalArgBuffer7); - break; - case 7: - optionalArgBuffer7[6] = '\0'; - newBaud = atoi(optionalArgBuffer7); - break; - } - } - if (curBoardMode == BOARD_MODE_DEBUG) { - beginSerial1(newBaud); - } - - if (!streaming) { - printSuccess(); - Serial0.print("Board type set to "); - Serial0.print(curBoardMode); - Serial0.print(" new baud is "); - Serial0.print(newBaud); - sendEOT(); - } - } else if (numberOfIncomingSettingsProcessedBoardType == 0) { - if (!streaming) { - printSuccess(); - Serial0.print("Current Board type set to "); - Serial0.print(curBoardMode); - sendEOT(); - } + printSuccess(); + printAll(getBoardMode()); + sendEOT(); + } else if (isDigit(c)) { + uint8_t digit = c - '0'; + if (digit <= BOARD_MODE_DIGITAL) { + setBoardMode(digit); + printSuccess(); + printAll(getBoardMode()); + sendEOT(); } else { - if (!streaming) { - printFailure(); - Serial0.print("invalid board mode"); - sendEOT(); - } + printFailure(); + printAll("board mode value out of bounds."); + sendEOT(); } - settingBoardMode = false; - return; + } else { + printFailure(); + printAll("invalid board mode value."); + sendEOT(); } + settingBoardMode = false; +} - // This one is the board type always - if (numberOfIncomingSettingsProcessedBoardType == 0) { - if (isDigit(c)) { - curBoardMode = (BOARD_MODE)(c - '0'); - numberOfIncomingSettingsProcessedBoardType = 1; - } else { - numberOfIncomingSettingsProcessedBoardType = -1; - } - } else if (numberOfIncomingSettingsProcessedBoardType > 0) { - // Is there an optional arg? - if (isDigit(c)) { - // convert the incoming byte to a char - // and add it to the string: - if (optionalArgCounter < 4) { - optionalArgBuffer5[optionalArgCounter] = c; - } - if (optionalArgCounter < 5) { - optionalArgBuffer6[optionalArgCounter] = c; - } - if (optionalArgCounter < 6) { - optionalArgBuffer7[optionalArgCounter] = c; - } - optionalArgCounter++; - } - // numberOfIncomingSettingsProcessedBoardType++; +/** + * Used to set the board mode of the system. + * @param newBoardMode The board mode to swtich to + */ +void OpenBCI_32bit_Library::setBoardMode(uint8_t newBoardMode) { + curBoardMode = (BOARD_MODE)newBoardMode; + switch (curBoardMode) { + case BOARD_MODE_ANALOG: + curAccelMode = ACCEL_MODE_OFF; + pinMode(11, INPUT); + pinMode(12, INPUT); + if (!wifiPresent) pinMode(13, INPUT); + break; + case BOARD_MODE_DIGITAL: + curAccelMode = ACCEL_MODE_OFF; + pinMode(11, INPUT); + pinMode(12, INPUT); + if (!wifiPresent) pinMode(WIFI_SS, INPUT); + pinMode(17, INPUT); + if (!wifiPresent) pinMode(WIFI_RESET, INPUT); + break; + case BOARD_MODE_DEBUG: + curAccelMode = ACCEL_MODE_ON; + boardBeginDebug(); + break; + case BOARD_MODE_DEFAULT: + curAccelMode = ACCEL_MODE_ON; + boardBegin(); + break; } + setCurPacketType(); } void OpenBCI_32bit_Library::setSampleRate(uint8_t newSampleRateCode) { @@ -697,60 +697,67 @@ void OpenBCI_32bit_Library::setSampleRate(uint8_t newSampleRateCode) { initialize_ads(); } -void OpenBCI_32bit_Library::printSampleRate() { +const char* OpenBCI_32bit_Library::getSampleRate() { switch (curSampleRate) { case SAMPLE_RATE_16000: - Serial0.print("16000"); - break; + return "16000"; case SAMPLE_RATE_8000: - Serial0.print("8000"); - break; + return "8000"; case SAMPLE_RATE_4000: - Serial0.print("4000"); - break; + return "4000"; case SAMPLE_RATE_2000: - Serial0.print("2000"); - break; + return "2000"; case SAMPLE_RATE_1000: - Serial0.print("1000"); - break; + return "1000"; case SAMPLE_RATE_500: - Serial0.print("500"); - break; + return "500"; case SAMPLE_RATE_250: default: - Serial0.print("250"); - break; + return "250"; + } +} +const char* OpenBCI_32bit_Library::getBoardMode(void) { + switch (curBoardMode) { + case BOARD_MODE_DEBUG: + return "debug"; + case BOARD_MODE_ANALOG: + return "analog"; + case BOARD_MODE_DIGITAL: + return "digital"; + case BOARD_MODE_DEFAULT: + default: + return "default"; } } void OpenBCI_32bit_Library::processIncomingSampleRate(char c) { if (c == OPENBCI_SAMPLE_RATE_SET) { printSuccess(); - printSampleRate(); + printAll(getSampleRate()); sendEOT(); } else if (isDigit(c)) { uint8_t digit = c - '0'; if (digit <= SAMPLE_RATE_250) { if (!streaming) { setSampleRate(digit); - // initialize(); printSuccess(); - printSampleRate(); + printAll("Sample rate is "); + printAll(getSampleRate()); + printAll("Hz"); sendEOT(); } } else { if (!streaming) { printFailure(); - Serial0.print("sample value out of bounds. "); + printAll("sample value out of bounds"); sendEOT(); } } } else { if (!streaming) { printFailure(); - Serial0.print("invalid sample value."); + printAll("invalid sample value"); sendEOT(); } } @@ -772,7 +779,9 @@ void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) { isProcessingIncomingSettingsChannel = false; if (!streaming) { - Serial0.print("Channel setting failure: too few chars"); sendEOT(); + printFailure(); + printAll("too few chars"); + sendEOT(); } return; @@ -802,8 +811,8 @@ void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) { case 8: // 'X' latch if (character != OPENBCI_CHANNEL_CMD_LATCH) { if (!streaming) { - Serial0.print("Err: 9th char not "); - Serial0.println(OPENBCI_CHANNEL_CMD_LATCH); + printFailure(); + printAll("Err: 9th char not X"); sendEOT(); } // We failed somehow and should just abort @@ -816,7 +825,8 @@ void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) { break; default: // should have exited if (!streaming) { - Serial0.print("Err: too many chars"); + printFailure(); + printAll("Err: too many chars"); sendEOT(); } // We failed somehow and should just abort @@ -832,13 +842,12 @@ void OpenBCI_32bit_Library::processIncomingChannelSettings(char character) { if (numberOfIncomingSettingsProcessedChannel == (OPENBCI_NUMBER_OF_BYTES_SETTINGS_CHANNEL)) { // We are done processing channel settings... - if (!streaming) { - Serial0.print("Channel set for "); Serial0.println(currentChannelSetting + 1); sendEOT(); - } - - if (curBoardMode == BOARD_MODE_DEBUG) { - Serial1.print("Channel set for "); Serial1.println(currentChannelSetting + 1); + char buf[2]; + printSuccess(); + printAll("Channel set for "); + printAll(itoa(currentChannelSetting + 1, buf, 10)); + sendEOT(); } // Set channel settings @@ -869,7 +878,9 @@ void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) { isProcessingIncomingSettingsLeadOff = false; if (!streaming) { - Serial0.print("Lead off failure: too few chars"); sendEOT(); + printFailure(); + printAll("too few chars"); + sendEOT(); } return; @@ -887,8 +898,8 @@ void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) { case 4: // 'Z' latch if (character != OPENBCI_CHANNEL_IMPEDANCE_LATCH) { if (!streaming) { - Serial0.print("Err: 5th char not "); - Serial0.println(OPENBCI_CHANNEL_IMPEDANCE_LATCH); + printFailure(); + printAll("Err: 5th char not Z"); sendEOT(); } // We failed somehow and should just abort @@ -902,7 +913,8 @@ void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) { break; default: // should have exited if (!streaming) { - Serial0.print("Err: too many chars "); + printFailure(); + printAll("Err: too many chars"); sendEOT(); } // We failed somehow and should just abort @@ -921,11 +933,11 @@ void OpenBCI_32bit_Library::processIncomingLeadOffSettings(char character) { // We are done processing lead off settings... if (!streaming) { - Serial0.print("Lead off set for "); Serial0.println(currentChannelSetting + 1); sendEOT(); - } - - if (curBoardMode == BOARD_MODE_DEBUG) { - Serial1.print("Lead off set for "); Serial1.println(currentChannelSetting + 1); + char buf[3]; + printSuccess(); + printAll("Lead off set for "); + printAll(itoa(currentChannelSetting + 1, buf, 10)); + sendEOT(); } // Set lead off settings @@ -947,7 +959,7 @@ void OpenBCI_32bit_Library::initialize(){ pinMode(BOARD_ADS, OUTPUT); digitalWrite(BOARD_ADS,HIGH); pinMode(DAISY_ADS, OUTPUT); digitalWrite(DAISY_ADS,HIGH); pinMode(LIS3DH_SS,OUTPUT); digitalWrite(LIS3DH_SS,HIGH); - pinMode(WIFI_SS,OUTPUT); digitalWrite(WIFI_SS, HIGH); + pinMode(WIFI_SS,OUTPUT); digitalWrite(WIFI_SS, LOW); pinMode(WIFI_RESET,OUTPUT); digitalWrite(WIFI_RESET, HIGH); wifiReset(); @@ -964,13 +976,14 @@ void OpenBCI_32bit_Library::initialize(){ */ void OpenBCI_32bit_Library::loop(void) { if (toggleWifiReset) { - if ((millis() - timeOfWifiToggle) > 200) { + if ((millis() - timeOfWifiToggle) > 50) { + digitalWrite(WIFI_SS, LOW); digitalWrite(WIFI_RESET, HIGH); toggleWifiReset = false; } } if (toggleWifiCS) { - if ((millis() - timeOfWifiToggle) > 2000) { + if ((millis() - timeOfWifiToggle) > 2500) { digitalWrite(OPENBCI_PIN_LED, HIGH); digitalWrite(WIFI_SS, HIGH); // Set back to high toggleWifiCS = false; @@ -979,16 +992,27 @@ void OpenBCI_32bit_Library::loop(void) { } } if (seekingWifi) { - if ((millis() - timeOfWifiToggle) > 8000) { + if ((millis() - timeOfWifiToggle) > 4500) { seekingWifi = false; - wifiAttach(); + if (!wifiAttach()) { + wifiAttachAttempts++; + if (wifiAttachAttempts < 3) { + seekingWifi = true; + timeOfWifiToggle = millis(); + } + } } } - if (wifiPresent && iWifi.rx) { + if (iWifi.rx) { if ((millis() - timeOfLastRead) > 20) { wifiReadData(); - if (wifiBufferInput[0] == 0x01) { - processChar(wifiBufferInput[1]); + uint8_t numChars = (uint8_t)wifiBufferRx[0]; + if (numChars > 0 && numChars < WIFI_SPI_MAX_PACKET_SIZE) { + // Serial0.print("Recieved "); Serial0.print(numChars); Serial0.print(" chars @ "); Serial0.println(micros()); + for(uint8_t i = 0; i < numChars; i++) { + // Serial0.println(wifiBufferRx[i+1],HEX); + processCharWifi(wifiBufferRx[i+1]); + } } timeOfLastRead = millis(); } @@ -1025,8 +1049,12 @@ void OpenBCI_32bit_Library::initializeVariables(void) { numberOfIncomingSettingsProcessedChannel = 0; numberOfIncomingSettingsProcessedLeadOff = 0; numberOfIncomingSettingsProcessedBoardType = 0; + sampleCounter = 0; + timeOfLastRead = 0; timeOfWifiToggle = 0; timeOfWifiStart = 0; + wifiAttachAttempts = 0; + wifiBufferTxPosition = 0; // Enums curAccelMode = ACCEL_MODE_ON; @@ -1038,6 +1066,7 @@ void OpenBCI_32bit_Library::initializeVariables(void) { // Structs initializeSerialInfo(iSerial0); initializeSerialInfo(iSerial1); + initializeSpiInfo(iWifi); } void OpenBCI_32bit_Library::initializeSerialInfo(SerialInfo si) { @@ -1086,8 +1115,12 @@ void OpenBCI_32bit_Library::sendChannelData(PACKET_TYPE packetType) { if (iWifi.tx) { sendChannelDataWifi(packetType, false); if (daisyPresent) sendChannelDataWifi(packetType, true); + if (iSerial1.tx) sendChannelDataSerial(packetType); // Serial1 can work under high speed + } else { + // Send over bluetooth + if (iSerial0.tx || iSerial1.tx) sendChannelDataSerial(packetType); } - if (iSerial0.tx || iSerial1.tx) sendChannelDataSerial(packetType); + if (packetType == PACKET_TYPE_ACCEL) LIS3DH_zeroAxisData(); if (packetType == PACKET_TYPE_RAW_AUX || packetType == PACKET_TYPE_RAW_AUX_TIME_SYNC) zeroAuxData(); @@ -1141,8 +1174,8 @@ void OpenBCI_32bit_Library::sendChannelDataSerial(PACKET_TYPE packetType) { */ void OpenBCI_32bit_Library::sendChannelDataWifi(PACKET_TYPE packetType, boolean daisy) { - wifiStoreByte((uint8_t)(PCKT_END | packetType)); // 1 byte - wifiStoreByte(sampleCounter); // 1 byte + wifiStoreByteBufTx((uint8_t)(PCKT_END | packetType)); // 1 byte + wifiStoreByteBufTx(sampleCounter); // 1 byte ADS_writeChannelDataWifi(daisy); // 24 bytes switch (packetType) { @@ -1168,7 +1201,7 @@ void OpenBCI_32bit_Library::sendChannelDataWifi(PACKET_TYPE packetType, boolean writeAuxDataWifi(); // 6 bytes break; } - wifiFlushBuffer(); + wifiFlushBufferTx(); } /** @@ -1242,8 +1275,8 @@ void OpenBCI_32bit_Library::sendTimeWithAccelWifi(void) { LIS3DH_writeAxisDataForAxisWifi(ACCEL_AXIS_Z); break; default: - wifiStoreByte((byte)0x00); // high byte - wifiStoreByte((byte)0x00); // low byte + wifiStoreByteBufTx((byte)0x00); // high byte + wifiStoreByteBufTx((byte)0x00); // low byte break; } writeTimeCurrentWifi(lastSampleTime); // 4 bytes @@ -1294,8 +1327,8 @@ void OpenBCI_32bit_Library::sendTimeWithRawAuxSerial(void) { * Adds stop byte `OPENBCI_EOP_RAW_AUX_TIME_SYNCED` */ void OpenBCI_32bit_Library::sendTimeWithRawAuxWifi(void) { - wifiStoreByte(highByte(auxData[0])); // 2 bytes of aux data - wifiStoreByte(lowByte(auxData[0])); + wifiStoreByteBufTx(highByte(auxData[0])); // 2 bytes of aux data + wifiStoreByteBufTx(lowByte(auxData[0])); writeTimeCurrentWifi(lastSampleTime); // 4 bytes } @@ -1308,8 +1341,8 @@ void OpenBCI_32bit_Library::writeAuxDataSerial(void){ void OpenBCI_32bit_Library::writeAuxDataWifi(void){ for(int i = 0; i < 3; i++){ - wifiStoreByte((uint8_t)highByte(auxData[i])); // write 16 bit axis data MSB first - wifiStoreByte((uint8_t)lowByte(auxData[i])); // axisData is array of type short (16bit) + wifiStoreByteBufTx((uint8_t)highByte(auxData[i])); // write 16 bit axis data MSB first + wifiStoreByteBufTx((uint8_t)lowByte(auxData[i])); // axisData is array of type short (16bit) } } @@ -1337,7 +1370,7 @@ void OpenBCI_32bit_Library::writeTimeCurrentSerial(uint32_t newTime) { void OpenBCI_32bit_Library::writeTimeCurrentWifi(uint32_t newTime) { // serialize the number, placing the MSB in lower packets for (int j = 3; j >= 0; j--) { - wifiStoreByte((uint8_t)(newTime >> (j*8))); + wifiStoreByteBufTx((uint8_t)(newTime >> (j*8))); } } @@ -1394,27 +1427,21 @@ void OpenBCI_32bit_Library::csHigh(int SS) switch(SS){ case BOARD_ADS: digitalWrite(BOARD_ADS, HIGH); - spi.setSpeed(20000000); break; case LIS3DH_SS: digitalWrite(LIS3DH_SS, HIGH); - spi.setSpeed(20000000); break; case SD_SS: digitalWrite(SD_SS, HIGH); - spi.setSpeed(4000000); break; case DAISY_ADS: digitalWrite(DAISY_ADS, HIGH); - spi.setSpeed(20000000); break; case BOTH_ADS: digitalWrite(BOARD_ADS, HIGH); digitalWrite(DAISY_ADS, HIGH); - spi.setSpeed(20000000); break; case WIFI_SS: digitalWrite(WIFI_SS, HIGH); - spi.setSpeed(10000000); break; default: break; @@ -1624,6 +1651,10 @@ void OpenBCI_32bit_Library::streamSafeSetAllChannelsToDefault(void) { * @returns boolean if able to start streaming */ void OpenBCI_32bit_Library::streamStart(){ // needs daisy functionality + if (iWifi.tx) { + wifiSendGains(); + // Serial0.println("sendGains - ss"); + } streaming = true; startADS(); if (curBoardMode == BOARD_MODE_DEBUG) { @@ -1663,12 +1694,12 @@ void OpenBCI_32bit_Library::removeDaisy(void){ STANDBY(DAISY_ADS); daisyPresent = false; if(!isRunning) { - Serial0.println("daisy removed"); + printAll("daisy removed"); sendEOT(); } }else{ if(!isRunning) { - Serial0.println("no daisy to remove!"); + printAll("no daisy to remove!"); sendEOT(); } } @@ -1683,10 +1714,14 @@ void OpenBCI_32bit_Library::attachDaisy(void){ if(!daisyPresent){ WREG(CONFIG1,(ADS1299_CONFIG1_DAISY_NOT | curSampleRate),BOARD_ADS); // turn off clk output if no daisy present numChannels = 8; // expect up to 8 ADS channels - if(!isRunning) Serial0.println("no daisy to attach!"); + if(!isRunning) { + printAll("no daisy to attach!"); + } }else{ numChannels = 16; // expect up to 16 ADS channels - if(!isRunning) Serial0.println("daisy attached"); + if(!isRunning) { + printAll("daisy attached"); + } } } @@ -2048,8 +2083,7 @@ void OpenBCI_32bit_Library::writeChannelSettings(byte N){ } // deactivate the given channel. -void OpenBCI_32bit_Library::deactivateChannel(byte N) -{ +void OpenBCI_32bit_Library::deactivateChannel(byte N) { byte setting, startChan, endChan, targetSS; if(N < 9){ targetSS = BOARD_ADS; startChan = 0; endChan = 8; @@ -2221,21 +2255,21 @@ void OpenBCI_32bit_Library::configureLeadOffDetection(byte amplitudeCode, byte f // } // SDATAC(targetSS); delay(1); // exit Read Data Continuous mode to communicate with ADS // N = constrain(N-1,startChan,endChan-1); //subtracts 1 so that we're counting from 0, not 1 - +// // setting = RREG(CH1SET+(N-startChan),targetSS); delay(1); // get the current channel settings // bitSet(setting,7); // set bit7 to shut down channel // bitClear(setting,3); // clear bit3 to disclude from SRB2 if used // WREG(CH1SET+(N-startChan),setting,targetSS); delay(1); // write the new value to disable the channel - +// // //remove the channel from the bias generation... // setting = RREG(BIAS_SENSP,targetSS); delay(1); //get the current bias settings // bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation // WREG(BIAS_SENSP,setting,targetSS); delay(1); //send the modified byte back to the ADS - +// // setting = RREG(BIAS_SENSN,targetSS); delay(1); //get the current bias settings // bitClear(setting,N-startChan); //clear this channel's bit to remove from bias generation // WREG(BIAS_SENSN,setting,targetSS); delay(1); //send the modified byte back to the ADS - +// // leadOffSettings[N][PCHAN] = leadOffSettings[N][NCHAN] = NO; // leadOffSetForChannel(N+1, NO, NO); // } @@ -2475,6 +2509,24 @@ void OpenBCI_32bit_Library::updateChannelData(){ updateBoardData(downsample); if(daisyPresent) {updateDaisyData(downsample);} + + switch (curBoardMode) { + case BOARD_MODE_ANALOG: + auxData[0] = analogRead(A5); + auxData[1] = analogRead(A6); + if (!wifiPresent) { + auxData[2] = analogRead(A7); + } + break; + case BOARD_MODE_DIGITAL: + auxData[0] = digitalRead(11) << 8 | digitalRead(12); + auxData[1] = (wifiPresent ? 0 : digitalRead(WIFI_SS) << 8) | digitalRead(17); + auxData[2] = wifiPresent ? 0 : digitalRead(WIFI_RESET); + break; + case BOARD_MODE_DEBUG: + case BOARD_MODE_DEFAULT: + break; + } } void OpenBCI_32bit_Library::updateBoardData(void){ @@ -2620,10 +2672,16 @@ void OpenBCI_32bit_Library::stopADS() isRunning = false; } +void OpenBCI_32bit_Library::printSerial(int i) { + if (iSerial0.tx) { + Serial0.print(i); + } + if (iSerial1.tx) { + Serial1.print(i); + } +} -void OpenBCI_32bit_Library::printSerial(uint8_t c) { - Serial1.print("printSerial(uint8_t c)"); - +void OpenBCI_32bit_Library::printSerial(char c) { if (iSerial0.tx) { Serial0.print(c); } @@ -2632,9 +2690,7 @@ void OpenBCI_32bit_Library::printSerial(uint8_t c) { } } -void OpenBCI_32bit_Library::printSerial(uint8_t c, uint8_t arg) { - Serial1.print("printSerial(uint8_t c, uint8_t arg)"); - +void OpenBCI_32bit_Library::printSerial(int c, int arg) { if (iSerial0.tx) { Serial0.print(c, arg); } @@ -2643,33 +2699,40 @@ void OpenBCI_32bit_Library::printSerial(uint8_t c, uint8_t arg) { } } -void OpenBCI_32bit_Library::printSerial(uint8_t *c, size_t len) { - Serial1.print("printSerial(uint8_t *c, size_t len)"); - - for (int i = 0; i < len; i++) { - printSerial(c[i]); +void OpenBCI_32bit_Library::printSerial(const char *c) { + if (c != NULL) { + for (int i = 0; i < strlen(c); i++) { + printSerial(c[i]); + } } } -void OpenBCI_32bit_Library::printlnSerial(uint8_t c) { +void OpenBCI_32bit_Library::printlnSerial(void) { + printSerial("\n"); +} + +void OpenBCI_32bit_Library::printlnSerial(char c) { printSerial(c); - printSerial('\n'); + printlnSerial(); } -void OpenBCI_32bit_Library::printlnSerial(uint8_t *c, size_t len) { - for (int i = 0; i < len; i++) { - printSerial(c[i]); - } - printSerial('\n'); +void OpenBCI_32bit_Library::printlnSerial(int c) { + printSerial(c); + printlnSerial(); } -void OpenBCI_32bit_Library::printlnSerial(uint8_t c, uint8_t arg) { +void OpenBCI_32bit_Library::printlnSerial(int c, int arg) { printSerial(c, arg); - printSerial('\n'); + printlnSerial(); +} + +void OpenBCI_32bit_Library::printlnSerial(const char *c) { + printSerial(c); + printlnSerial(); } void OpenBCI_32bit_Library::write(uint8_t b) { - wifiStoreByte(b); + wifiStoreByteBufTx(b); writeSerial(b); } @@ -2692,12 +2755,12 @@ void OpenBCI_32bit_Library::ADS_writeChannelDataWifi(boolean daisy) { if (daisy) { // Send daisy for(int i = 0; i < 24; i++) { - wifiStoreByte(daisyChannelDataRaw[i]); + wifiStoreByteBufTx(daisyChannelDataRaw[i]); } } else { // Send on board for(int i = 0; i < 24; i++) { - wifiStoreByte(boardChannelDataRaw[i]); + wifiStoreByteBufTx(boardChannelDataRaw[i]); } } } @@ -2942,53 +3005,63 @@ void OpenBCI_32bit_Library::WREGS(byte _address, byte _numRegistersMinusOne, int // <<<<<<<<<<<<<<<<<<<<<<<<< END OF ADS1299 FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>> // ****************************************************************************** -// <<<<<<<<<<<<<<<<<<<<<<<<<<< WIFI FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +// <<<<<<<<<<<<<<<<<<<<<<<<<<< WIFI FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>s /** -* @description Creates a byteId for sending data spi to wifi shield -* @param isStreamPacket {boolean} Set true if this is a streaming packet -* @param isDaisy {boolean} Set true if daisy packet -* @param packetNumber {uint8_t} What number packet are you trying to send? -* @returns [char] The newly formed byteId where a byteId is defined as -* Bit 7 - Streaming byte packet -* Bits[6:3] - Packet count -* Bits[2:0] - Free -* @author AJ Keller (@pushtheworldllc) -*/ -// uint8_t OpenBCI_32bit_Library::wifiByteIdMake(boolean isStreamPacket, uint8_t packetNumber) { -// // Set output initially equal to 0 -// uint8_t output = 0x00; -// -// // Set first bit if this is a streaming packet -// if (isStreamPacket) output = output | 0x80; -// -// // Set packet count bits Bits[6:3] NOTE: 0xFF is error -// // convert int to char then shift then or -// output = output | ((packetNumber & 0x0F) << 3); -// -// return output; -// } + * Used to attach a wifi shield, only if there is actuall a wifi shield present + */ +boolean OpenBCI_32bit_Library::wifiAttach(void) { + wifiPresent = wifiSmell(); + if(!wifiPresent) { + iWifi.rx = false; + iWifi.tx = false; + return false; + // if(!isRunning) Serial0.print("no wifi shield to attach!"); sendEOT(); + } else { + iWifi.rx = true; + iWifi.tx = true; + return true; + // if(!isRunning) Serial0.println("wifi attached"); sendEOT(); + } +} + +/** + * Clear the wifi tx buffer + */ +void OpenBCI_32bit_Library::wifiBufferRxClear(void) { + for (uint8_t i = 0; i < WIFI_SPI_MAX_PACKET_SIZE; i++) { + wifiBufferRx[i] = 0; + } +} + +/** + * Clear the wifi tx buffer + */ +void OpenBCI_32bit_Library::wifiBufferTxClear(void) { + for (uint8_t i = 0; i < WIFI_SPI_MAX_PACKET_SIZE; i++) { + wifiBufferTx[i] = 0; + } + wifiBufferTxPosition = 0; +} /** - * [OpenBCI_32bit_Library::wifiStoreByte description] + * [OpenBCI_32bit_Library::wifiStoreByteBufTx description] * @param b {uint8_t} A single byte to store * @return {boolean} True if the byte was stored, false if the buffer is full. */ -boolean OpenBCI_32bit_Library::wifiStoreByte(uint8_t b) { - if (wifiBufferPosition >= WIFI_SPI_MAX_PACKET_SIZE) return false; - - wifiBuffer[wifiBufferPosition] = b; - wifiBufferPosition++; +boolean OpenBCI_32bit_Library::wifiStoreByteBufTx(uint8_t b) { + if (wifiBufferTxPosition >= WIFI_SPI_MAX_PACKET_SIZE) return false; + wifiBufferTx[wifiBufferTxPosition] = b; + wifiBufferTxPosition++; return true; } /** * Flush the 32 byte buffer to the wifi shield. Set byte id too... */ -void OpenBCI_32bit_Library::wifiFlushBuffer() { - // wifiBuffer[WIFI_SPI_BYTE_ID_POS] = wifiByteIdMake(streaming, daisyPresent, 0); - wifiWriteData(wifiBuffer, WIFI_SPI_MAX_PACKET_SIZE); - wifiBufferPosition = 0; +void OpenBCI_32bit_Library::wifiFlushBufferTx() { + wifiWriteData(wifiBufferTx, WIFI_SPI_MAX_PACKET_SIZE); + wifiBufferTxPosition = 0; } /** @@ -3019,43 +3092,43 @@ void OpenBCI_32bit_Library::wifiReadData() { xfer(0x03); xfer(0x00); for(uint8_t i = 0; i < 32; i++) { - wifiBufferInput[i] = xfer(0); + wifiBufferRx[i] = xfer(0); } csHigh(WIFI_SS); } /** - * Used to attach a wifi shield, only if there is actuall a wifi shield present + * Used to read the status register from the ESP8266 wifi shield + * @return uint32_t the status */ -void OpenBCI_32bit_Library::wifiAttach(void) { - wifiPresent = wifiSmell(); - if(!wifiPresent) { - iWifi.rx = false; - iWifi.tx = false; - iSerial0.tx = true; - // if(!isRunning) Serial0.print("no wifi shield to attach!"); sendEOT(); - } else { - iWifi.rx = true; - iWifi.tx = true; - iSerial0.tx = false; - // if(!isRunning) Serial0.println("wifi attached"); sendEOT(); - } +uint32_t OpenBCI_32bit_Library::wifiReadStatus(void){ + // TODO: Remove this line + csLow(WIFI_SS); + xfer(0x04); + uint32_t status = (xfer(0x00) | ((uint32_t)(xfer(0x00)) << 8) | ((uint32_t)(xfer(0x00)) << 16) | ((uint32_t)(xfer(0x00)) << 24)); + csHigh(WIFI_SS); + return status; } /** * Used to detach the wifi shield, sort of. */ -void OpenBCI_32bit_Library::wifiRemove(void) { - iWifi.rx = false; - iWifi.tx = false; - wifiPresent = false; - iSerial0.tx = true; +boolean OpenBCI_32bit_Library::wifiRemove(void) { + if (wifiPresent) { + iWifi.rx = false; + iWifi.tx = false; + wifiPresent = false; + return true; + } + return false; } /** * Used to power on reset the ESP8266 wifi shield. Used in conjunction with `.loop()` */ void OpenBCI_32bit_Library::wifiReset(void) { + initializeSpiInfo(iWifi); + wifiPresent = false; // Always keep pin low or else esp will fail to boot. // See https://github.com/esp8266/Arduino/blob/master/libraries/SPISlave/examples/SPISlave_SafeMaster/SPISlave_SafeMaster.ino#L12-L15 digitalWrite(WIFI_SS,LOW); @@ -3066,6 +3139,77 @@ void OpenBCI_32bit_Library::wifiReset(void) { toggleWifiReset = true; } +void OpenBCI_32bit_Library::wifiSendGains(void) { + if (!wifiPresent) return; + if (!iWifi.tx) return; + + // Clear the wifi buffer + wifiBufferTxClear(); + + wifiStoreByteBufTx(WIFI_SPI_MSG_GAINS); + wifiStoreByteBufTx(numChannels); + for (uint8_t i = 0; i < numChannels; i++) { + wifiStoreByteBufTx(channelSettings[i][GAIN_SET]); + } + wifiFlushBufferTx(); +} + +/** + * This will tell the Wifi shield to send the contents of this message to the requesting + * client, if there was one... if this functions sister function, wifiSendStringMulti was used + * then this will indicate the end of a multi byte message. + * @param str [description] + */ +void OpenBCI_32bit_Library::wifiSendStringLast(void) { + wifiSendStringLast(""); +} + +/** + * This will tell the Wifi shield to send the contents of this message to the requesting + * client, if there was one... if this functions sister function, wifiSendStringMulti was used + * then this will indicate the end of a multi byte message. + * @param str [description] + */ +void OpenBCI_32bit_Library::wifiSendStringLast(const char *str) { + if (!wifiPresent) return; + if (!iWifi.tx) return; + if (str == NULL) return; + int len = strlen(str); + if (len > WIFI_SPI_MAX_PACKET_SIZE - 1) { + return; // Don't send more than 31 bytes at a time -o-o- (deal with it) + } + wifiBufferTxClear(); + wifiStoreByteBufTx(WIFI_SPI_MSG_LAST); + for (int i = 0; i < len; i++) { + wifiStoreByteBufTx(str[i]); + } + wifiFlushBufferTx(); + wifiBufferTxClear(); +} + +/** + * Will send a const char string (less than 32 bytes) to the wifi shield, call + * wifiSendStringLast to indicate to the wifi shield the multi part transmission is over. + * @param str const char * less than 32 bytes to be sent over SPI + */ +void OpenBCI_32bit_Library::wifiSendStringMulti(const char *str) { + if (!wifiPresent) return; + if (!iWifi.tx) return; + if (str == NULL) return; + int len = strlen(str); + if (len > WIFI_SPI_MAX_PACKET_SIZE - 1) { + return; // Don't send more than 31 bytes at a time -o-o- (deal with it) + } + + wifiBufferTxClear(); + wifiStoreByteBufTx(WIFI_SPI_MSG_MULTI); + for (int i = 0; i < len; i++) { + wifiStoreByteBufTx(str[i]); + } + wifiFlushBufferTx(); + wifiBufferTxClear(); +} + /** * Used to check and see if the wifi is present * @return [description] @@ -3073,23 +3217,16 @@ void OpenBCI_32bit_Library::wifiReset(void) { boolean OpenBCI_32bit_Library::wifiSmell(void){ boolean isWifi = false; uint32_t uuid = wifiReadStatus(); - if(verbosity){Serial0.print("Wifi ID 0x"); Serial0.println(uuid,HEX); sendEOT();} - if(uuid == 0) {isWifi = true;} // should read as 0x3E + if (verbosity) { + Serial0.print("Wifi ID 0x"); + Serial0.println(uuid,HEX); + Serial.println(micros()); + sendEOT(); + } + if(uuid == 209) {isWifi = true;} // should read as 0x3E return isWifi; } -/** - * Used to read the status register from the ESP8266 wifi shield - * @return uint32_t the status - */ -uint32_t OpenBCI_32bit_Library::wifiReadStatus(void){ - csLow(WIFI_SS); - xfer(0x04); - uint32_t status = (xfer(0x00) | ((uint32_t)(xfer(0x00)) << 8) | ((uint32_t)(xfer(0x00)) << 16) | ((uint32_t)(xfer(0x00)) << 24)); - csHigh(WIFI_SS); - return status; -} - // <<<<<<<<<<<<<<<<<<<<<<<<< END OF WIFI FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>> // ****************************************************************************** // <<<<<<<<<<<<<<<<<<<<<<<<< LIS3DH FUNCTIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -3154,8 +3291,8 @@ void OpenBCI_32bit_Library::LIS3DH_writeAxisDataSerial(void){ void OpenBCI_32bit_Library::LIS3DH_writeAxisDataWifi(void){ for(int i = 0; i < 3; i++){ - wifiStoreByte(highByte(axisData[i])); // write 16 bit axis data MSB first - wifiStoreByte(lowByte(axisData[i])); // axisData is array of type short (16bit) + wifiStoreByteBufTx(highByte(axisData[i])); // write 16 bit axis data MSB first + wifiStoreByteBufTx(lowByte(axisData[i])); // axisData is array of type short (16bit) } } @@ -3167,8 +3304,8 @@ void OpenBCI_32bit_Library::LIS3DH_writeAxisDataForAxisSerial(uint8_t axis) { void OpenBCI_32bit_Library::LIS3DH_writeAxisDataForAxisWifi(uint8_t axis) { if (axis > 2) axis = 0; - wifiStoreByte(highByte(axisData[axis])); // write 16 bit axis data MSB first - wifiStoreByte(lowByte(axisData[axis])); // axisData is array of type short (16bit) + wifiStoreByteBufTx(highByte(axisData[axis])); // write 16 bit axis data MSB first + wifiStoreByteBufTx(lowByte(axisData[axis])); // axisData is array of type short (16bit) } void OpenBCI_32bit_Library::LIS3DH_zeroAxisData(void){ @@ -3261,53 +3398,53 @@ void OpenBCI_32bit_Library::LIS3DH_readAllRegs(){ void OpenBCI_32bit_Library::printRegisterName(byte _address) { switch(_address){ case ID_REG: - Serial0.print("ADS_ID, "); break; + printAll("ADS_ID, "); break; case CONFIG1: - Serial0.print("CONFIG1, "); break; + printAll("CONFIG1, "); break; case CONFIG2: - Serial0.print("CONFIG2, "); break; + printAll("CONFIG2, "); break; case CONFIG3: - Serial0.print("CONFIG3, "); break; + printAll("CONFIG3, "); break; case LOFF: - Serial0.print("LOFF, "); break; + printAll("LOFF, "); break; case CH1SET: - Serial0.print("CH1SET, "); break; + printAll("CH1SET, "); break; case CH2SET: - Serial0.print("CH2SET, "); break; + printAll("CH2SET, "); break; case CH3SET: - Serial0.print("CH3SET, "); break; + printAll("CH3SET, "); break; case CH4SET: - Serial0.print("CH4SET, "); break; + printAll("CH4SET, "); break; case CH5SET: - Serial0.print("CH5SET, "); break; + printAll("CH5SET, "); break; case CH6SET: - Serial0.print("CH6SET, "); break; + printAll("CH6SET, "); break; case CH7SET: - Serial0.print("CH7SET, "); break; + printAll("CH7SET, "); break; case CH8SET: - Serial0.print("CH8SET, "); break; + printAll("CH8SET, "); break; case BIAS_SENSP: - Serial0.print("BIAS_SENSP, "); break; + printAll("BIAS_SENSP, "); break; case BIAS_SENSN: - Serial0.print("BIAS_SENSN, "); break; + printAll("BIAS_SENSN, "); break; case LOFF_SENSP: - Serial0.print("LOFF_SENSP, "); break; + printAll("LOFF_SENSP, "); break; case LOFF_SENSN: - Serial0.print("LOFF_SENSN, "); break; + printAll("LOFF_SENSN, "); break; case LOFF_FLIP: - Serial0.print("LOFF_FLIP, "); break; + printAll("LOFF_FLIP, "); break; case LOFF_STATP: - Serial0.print("LOFF_STATP, "); break; + printAll("LOFF_STATP, "); break; case LOFF_STATN: - Serial0.print("LOFF_STATN, "); break; + printAll("LOFF_STATN, "); break; case GPIO: - Serial0.print("GPIO, "); break; + printAll("GPIO, "); break; case MISC1: - Serial0.print("MISC1, "); break; + printAll("MISC1, "); break; case MISC2: - Serial0.print("MISC2, "); break; + printAll("MISC2, "); break; case CONFIG4: - Serial0.print("CONFIG4, "); break; + printAll("CONFIG4, "); break; default: break; } @@ -3321,11 +3458,21 @@ void OpenBCI_32bit_Library::printHex(byte _data){ } void OpenBCI_32bit_Library::printFailure() { - Serial0.print("Failure: "); + printAll("Failure: "); } void OpenBCI_32bit_Library::printSuccess() { - Serial0.print("Success: "); + printAll("Success: "); +} + +void OpenBCI_32bit_Library::printAll(const char *arr) { + printSerial(arr); + wifiSendStringMulti(arr); +} + +void OpenBCI_32bit_Library::printlnAll(const char *arr) { + printlnSerial(arr); + wifiSendStringLast(arr); } /** diff --git a/OpenBCI_32bit_Library.h b/OpenBCI_32bit_Library.h index 5d4a53f..cbc45ac 100644 --- a/OpenBCI_32bit_Library.h +++ b/OpenBCI_32bit_Library.h @@ -27,7 +27,9 @@ class OpenBCI_32bit_Library { typedef enum BOARD_MODE { BOARD_MODE_DEFAULT, - BOARD_MODE_DEBUG + BOARD_MODE_DEBUG, + BOARD_MODE_ANALOG, + BOARD_MODE_DIGITAL }; typedef enum PACKET_TYPE { @@ -93,6 +95,7 @@ class OpenBCI_32bit_Library { void deactivateChannel(byte); // disable given channel 1-8(16) void disable_accel(void); // stop data acquisition and go into low power mode void enable_accel(byte); // start acceleromoeter with default settings + const char* getBoardMode(void); char getChannelCommandForAsciiChar(char); char getCharSerial0(void); char getCharSerial1(void); @@ -101,6 +104,7 @@ class OpenBCI_32bit_Library { char getDefaultChannelSettingForSettingAscii(byte); char getGainForAsciiChar(char); char getNumberForAsciiChar(char); + const char* getSampleRate(void); char getTargetSSForConstrainedChannelNumber(byte); char getYesOrNoForAsciiChar(char); boolean hasDataSerial0(void); @@ -113,18 +117,17 @@ class OpenBCI_32bit_Library { void leadOffSetForChannel(byte, byte, byte); void ledFlash(int); void loop(void); - void printSerial(uint8_t); - void printSerial(uint8_t c, uint8_t arg); - void printSerial(uint8_t *, size_t len); - void printSerial(const char *data) { - printSerial((uint8_t *)data, strlen(data)); - } - void printlnSerial(uint8_t); - void printlnSerial(uint8_t c, uint8_t arg); - void printlnSerial(uint8_t *, size_t len); - void printlnSerial(const char *data) { - printlnSerial((uint8_t *)data, strlen(data)); - } + void printAll(const char *arr); + void printlnAll(const char *arr); + void printlnSerial(void); + void printlnSerial(char); + void printlnSerial(int); + void printlnSerial(int, int); + void printlnSerial(const char *); + void printSerial(int); + void printSerial(char); + void printSerial(int, int); + void printSerial(const char *); boolean processChar(char); void processIncomingBoardMode(char); void processIncomingSampleRate(char); @@ -139,11 +142,12 @@ class OpenBCI_32bit_Library { void stopADS(void); void sendChannelData(void); void sendChannelData(PACKET_TYPE); + void setBoardMode(uint8_t); void setChannelsToDefault(void); void setCurPacketType(void); void setSampleRate(uint8_t newSampleRateCode); void sendEOT(void); - void setSerialInfo(SerialInfo si, boolean rx, boolean tx, uint32_t baudRate); + void setSerialInfo(SerialInfo, boolean, boolean, uint32_t); boolean smellDaisy(void); void streamSafeChannelDeactivate(byte); void streamSafeChannelActivate(byte); @@ -161,15 +165,21 @@ class OpenBCI_32bit_Library { void updateDaisyData(boolean); void useAccel(boolean); void useTimeStamp(boolean); - void wifiAttach(void); - void wifiSetInfo(SpiInfo, boolean, boolean); - boolean wifiStoreByte(uint8_t); - void wifiFlushBuffer(void); + boolean wifiAttach(void); + void wifiBufferTxClear(void); + void wifiBufferRxClear(void); + void wifiFlushBufferTx(void); void wifiReadData(void); uint32_t wifiReadStatus(void); - void wifiRemove(void); + boolean wifiRemove(void); void wifiReset(void); + void wifiSendGains(void); + void wifiSendStringMulti(const char *); + void wifiSendStringLast(); + void wifiSendStringLast(const char *); + void wifiSetInfo(SpiInfo, boolean, boolean); boolean wifiSmell(void); + boolean wifiStoreByteBufTx(uint8_t); void wifiWriteData(uint8_t *, size_t); void write(uint8_t); void writeAuxDataSerial(void); @@ -216,9 +226,9 @@ class OpenBCI_32bit_Library { short auxData[3]; // This is user faceing short axisData[3]; - uint8_t wifiBuffer[WIFI_SPI_MAX_PACKET_SIZE]; - char wifiBufferInput[WIFI_SPI_MAX_PACKET_SIZE]; - uint8_t wifiBufferPosition; + uint8_t wifiBufferTx[WIFI_SPI_MAX_PACKET_SIZE]; + char wifiBufferRx[WIFI_SPI_MAX_PACKET_SIZE]; + uint8_t wifiBufferTxPosition; unsigned long lastSampleTime; @@ -269,12 +279,12 @@ class OpenBCI_32bit_Library { void LIS3DH_writeAxisDataForAxisWifi(uint8_t); void LIS3DH_updateAxisData(void); void LIS3DH_zeroAxisData(void); + boolean processCharWifi(char character); void printADSregisters(int); void printAllRegisters(void); void printFailure(); void printHex(byte); void printRegisterName(byte); - void printSampleRate(void); void printSuccess(); void processCharWifi(uint8_t); void RDATA(int); // read data one-shot @@ -323,6 +333,7 @@ class OpenBCI_32bit_Library { int numberOfIncomingSettingsProcessedChannel; int numberOfIncomingSettingsProcessedLeadOff; int numberOfIncomingSettingsProcessedBoardType; + int wifiAttachAttempts; uint8_t optionalArgCounter; unsigned long timeOfLastRead; unsigned long timeOfWifiToggle; diff --git a/OpenBCI_32bit_Library_Definitions.h b/OpenBCI_32bit_Library_Definitions.h index ab09620..8f23633 100644 --- a/OpenBCI_32bit_Library_Definitions.h +++ b/OpenBCI_32bit_Library_Definitions.h @@ -334,6 +334,11 @@ #define OPENBCI_TIME_SET '<' #define OPENBCI_TIME_STOP '>' +/** Wifi Stuff */ +#define OPENBCI_WIFI_ATTACH '{' +#define OPENBCI_WIFI_REMOVE '}' +#define OPENBCI_WIFI_STATUS ':' + /** Possible number of channels */ #define OPENBCI_NUMBER_OF_CHANNELS_DAISY 16 #define OPENBCI_NUMBER_OF_CHANNELS_DEFAULT 8 @@ -378,6 +383,8 @@ #define WIFI_SPI_CMD_STATUS_READ 0x04 #define WIFI_SPI_CMD_STATUS_WRITE 0x01 #define WIFI_SPI_MAX_PACKET_SIZE 32 -// #define WIFI_SPI_BYTE_ID_POS 31 +#define WIFI_SPI_MSG_LAST 0x01 +#define WIFI_SPI_MSG_MULTI 0x02 +#define WIFI_SPI_MSG_GAINS 0x03 #endif diff --git a/README.md b/README.md index 59f7d38..0211120 100644 --- a/README.md +++ b/README.md @@ -99,13 +99,6 @@ void setup() { } ``` -#### Bare board -```Arduino -void setup() { - board.begin(); // Bring up the OpenBCI Board -} -``` - ### loop(): We will start with the basics here, and work our way up... The loop function can be thought of as the meat and core executor of the OpenBCI_32bit_Library functionality. Keep in mind the main purpose of this library is to stream data from the ADS1299 to the computer, that's our focus, everything takes a back seat to that. @@ -233,30 +226,96 @@ Called when the board ADS1299 has new data available. If there is a daisy module ## ENUMS: -### PACKET_TYPE_ACCEL +### BOARD_MODE + +Board mode changes the hardware pins. + +#### BOARD_MODE_DEFAULT + +`0` - Board will operate leave all pins in default mode. + +#### BOARD_MODE_DEBUG + +`1` - Board will output serial debug data out of the external serial port. + +#### BOARD_MODE_ANALOG + +`2` - Board will read from `A6` (`D11`), `A7` (`D12`), and `A8` (`D13`). `A8` is only is use when there is no wifi present. The analog to digital converter is 10bits and the data will be in . + +|Pin|Aux Bytes|Notes| +|----|----|----| +|`A6`|0:1|`D11`| +|`A7`|2:3|`D12`| +|`A8`|4:5|`D13` - If wifi not present| + +#### BOARD_MODE_DIGITAL + +`3` - Board will read from `D11`, `D12`, `D13` (if wifi not present), `D17`, and `D18` (if wifi not present). + +|Pin|Aux Byte|Notes| +|----|----|----| +|`D11`|0|| +|`D11`|1|| +|`D13`|2|If wifi not present| +|`D17`|3|| +|`D18`|4|If wifi not present| + +### PACKET_TYPE + +#### PACKET_TYPE_ACCEL `0` - End of standard stream packet. -### PACKET_TYPE_RAW_AUX +#### PACKET_TYPE_RAW_AUX `1` - End of stream packet with raw packet. -### PACKET_TYPE_USER_DEFINED +#### PACKET_TYPE_USER_DEFINED `2` - End of stream packet, user defined. -### PACKET_TYPE_ACCEL_TIME_SET +#### PACKET_TYPE_ACCEL_TIME_SET `3` - End of time sync up with accelerometer stream packet. -### PACKET_TYPE_ACCEL_TIME_SYNC +#### PACKET_TYPE_ACCEL_TIME_SYNC `4` - End of time synced stream packet. -### PACKET_TYPE_RAW_AUX_TIME_SET +#### PACKET_TYPE_RAW_AUX_TIME_SET `5` - End of time sync up stream packet. -### PACKET_TYPE_RAW_AUX_TIME_SYNC +#### PACKET_TYPE_RAW_AUX_TIME_SYNC `6` - End of time synced stream packet. + +### SAMPLE_RATE + +#### SAMPLE_RATE_16000 + +`0` - Sample rate 16000Hz + +#### SAMPLE_RATE_8000 + +`1` - Sample rate 8000Hz + +#### SAMPLE_RATE_4000 + +`2` - Sample rate 4000Hz + +#### SAMPLE_RATE_2000 + +`3` - Sample rate 2000Hz + +#### SAMPLE_RATE_1000 + +`4` - Sample rate 1000Hz + +#### SAMPLE_RATE_500 + +`5` - Sample rate 500Hz + +#### SAMPLE_RATE_250 + +`6` - Sample rate 250Hz diff --git a/UPGRADE_GUIDE.md b/UPGRADE_GUIDE.md index 71975f6..c7ad52e 100644 --- a/UPGRADE_GUIDE.md +++ b/UPGRADE_GUIDE.md @@ -1,6 +1,38 @@ # OpenBCI 32bit Upgrade Guide -The purpose of this document is to provide instruction, resources, and advice for upgrading an OpenBCI 32bit 8-16 channel board firmware. +The purpose of this document is to provide instruction, resources, and advice for upgrading an OpenBCI Cyton 8-16 channel board firmware. + +## Upgrading to 3.0.0 + +### Upgrading from 2.x.x + +Flash the `Pic` with [`DefaultBoard`](https://github.com/OpenBCI/OpenBCI_32bit_Library/blob/master/examples/DefaultBoard/DefaultBoard.ino) + +#### Awesome New Features + +* Wifi shield support +* Read from analog or digital ports in a single line or command. (board mode) +* Simplified user experience +* Variable sample rate with wifi shield or Serial1 (with baud of 468000) + +#### What this update set out to solve + +* Have a single `.sendChannelData()` data function to call that manages the stop byte behind the scenes. I.e. if accel data should be added to aux bytes vs. reading from analog input pins and putting that in the aux bytes. +* Add wifi support without breaking any firmware v2.0.0 or v1.0.0 features. +* Prevent users from having to upload custom code to the pic + +#### In depth tutorials +* [How to get/install/upload code to Pic32 `Board`](http://docs.openbci.com/tutorials/02-Upload_Code_to_OpenBCI_Board#upload-code-to-openbci-board-32bit-upload-how-to-firmware-version-2xx-fall-2016) + +#### New commands + +* [Set Board Mode]() +* [Set sample rate]() +* [Wifi attach/remove/status]() + +### Upgrading from 1.x.x + +Read *Upgrading to 2.0.0* below: ## Upgrading to 2.0.0 diff --git a/changelog.md b/changelog.md index 78d6a00..25c24c3 100644 --- a/changelog.md +++ b/changelog.md @@ -2,11 +2,22 @@ ### New Features +* Add wifi shield support + * Send channel gains to wifi shield at start of stream + * takes ~4 seconds for the wifi shield to be reachable * Add ability to turn external serial port `Serial1` on through commands. * Add ability to use ESP8266 through SPI port. -* Change board types on the fly! -* Add loop function for internal timing operations -* Add function to turn time stamps on `useTimeStamp(true)`, time stamps are disabled by default. +* Change board types on the fly! No longer do you have to upload new code to the Cyton's Pic32 just to do an analog read. You can now read from analog or digital pins with the press send of a code! `/` now sets the board mode, where: + * BOARD_MODE_DEFAULT is `0` + * BOARD_MODE_DEBUG is `1` + * BOARD_MODE_ANALOG is `2` + * BOARD_MODE_DIGITAL is `3` +* Add loop function for internal timing operations related to power on reset for wifi shield, remove `loop` to free up pins and such and remove wifi capability. +* Add function to turn time stamps on `useTimeStamp(true)`, time stamps are disabled by default. Note the Wifi shield will use NTP time stamps. +* Add wifi commands: + * _OpenBCI Wifi Attach_ - `{` + * _OpenBCI Wifi Remove_ - `}` + * _OpenBCI Wifi Status_ - `:` ### Enhancements @@ -14,7 +25,7 @@ ### Breaking Changes -* Removed boolean `useAccel` in support of new mode paradigm. To use the accel, do nothing, it's enabled by default, to not use the accel simply call `useAccel(false)` and send the contents of `auxData` array each packet. +* Removed boolean `useAccel` in support of new mode paradigm. To use the accel, do nothing, it's enabled by default, to not use the accel simply call `useAccel(false)` and this library will automatically send the contents of `auxData` array each packet. * Removed `OPENBCI_EOP_STND_ACCEL`, `OPENBCI_EOP_STND_RAW_AUX`, `OPENBCI_EOP_USER_DEFINED`, `OPENBCI_EOP_ACCEL_TIME_SET`, `OPENBCI_EOP_ACCEL_TIME_SYNCED`, `OPENBCI_EOP_RAW_AUX_TIME_SET`, and `OPENBCI_EOP_RAW_AUX_TIME_SYNCED` in place of `enum` support replacement: `PACKET_TYPE_ACCEL`, `PACKET_TYPE_RAW_AUX`, `PACKET_TYPE_USER_DEFINED`, `PACKET_TYPE_ACCEL_TIME_SET`, `PACKET_TYPE_ACCEL_TIME_SYNC`, `PACKET_TYPE_RAW_AUX_TIME_SET`, and `PACKET_TYPE_RAW_AUX_TIME_SYNC`. * Removed `sniffMode` in place for `curBoardMode == OPENBCI_BOARD_MODE_DEBUG` * Removed public `waitForNewChannelData()` diff --git a/examples/BoardNoAccelOrSD/BoardNoAccelOrSD.ino b/examples/BoardNoAccelSDWifi/BoardNoAccelSDWifi.ino similarity index 100% rename from examples/BoardNoAccelOrSD/BoardNoAccelOrSD.ino rename to examples/BoardNoAccelSDWifi/BoardNoAccelSDWifi.ino diff --git a/examples/BoardNoAccelOrSDDebug/BoardNoAccelOrSDDebug.ino b/examples/BoardNoAccelSDWifiDebug/BoardNoAccelSDWifiDebug.ino similarity index 100% rename from examples/BoardNoAccelOrSDDebug/BoardNoAccelOrSDDebug.ino rename to examples/BoardNoAccelSDWifiDebug/BoardNoAccelSDWifiDebug.ino diff --git a/examples/BoardWithAnalogSensor/BoardWithAnalogSensor.ino b/examples/BoardWithAnalogSensor/BoardWithAnalogSensor.ino index 6006b24..ef8a997 100644 --- a/examples/BoardWithAnalogSensor/BoardWithAnalogSensor.ino +++ b/examples/BoardWithAnalogSensor/BoardWithAnalogSensor.ino @@ -2,12 +2,19 @@ #include #include +// NOTE: THIS DOES NOT HAVE SD + void setup() { // Bring up the OpenBCI Board board.begin(); - // Notify the board we want to use aux data, this effects `::sendChannelData()` - board.useAccel(false); + // Read from the analog sensor and store auxiliary position 0 + // take a reading from the ADC. Result range from 0 to 1023 + // Will put 10 bits from: + // Aux 1:2 D11 (A5) + // Aux 3:4 D12 (A6) + // Aux 5:6 D17 (A7) + board.setBoardMode(BOARD_MODE_ANALOG); } void loop() { @@ -19,12 +26,7 @@ void loop() { // Read from the ADS(s), store data, set channelDataAvailable flag to false board.updateChannelData(); - // Read from the analog sensor and store auxiliary position 0 - // take a reading from the ADC. Result range from 0 to 1023 - board.auxData[0] = analogRead(A7); - // Send standard packet with channel data and aux data - // includes aux data because we set `useAux` in setup() board.sendChannelData(); } } diff --git a/examples/BoardWithDigitalRead/BoardWithDigitalRead.ino b/examples/BoardWithDigitalRead/BoardWithDigitalRead.ino index e79a0ea..37fbd42 100644 --- a/examples/BoardWithDigitalRead/BoardWithDigitalRead.ino +++ b/examples/BoardWithDigitalRead/BoardWithDigitalRead.ino @@ -6,11 +6,13 @@ void setup() { // Bring up the OpenBCI Board board.begin(); - // Notify the board we want to use aux data, this effects `::sendChannelData()` - board.useAccel(false); - - // Set pin to input A0-A5 can be digital input - pinMode(17, INPUT); + // Read from digital input and store auxiliary position 0 + // take a reading from the ADC. Result range from 0 to 1023 + // Will put 10 bits from: + // Aux 1:2 D11 + // Aux 3:4 D12 + // Aux 5:6 D17 + board.setBoardMode(BOARD_MODE_DIGITAL); } void loop() { @@ -22,10 +24,6 @@ void loop() { // Read from the ADS(s), store data, set channelDataAvailable flag to false board.updateChannelData(); - // Read from the analog sensor and store auxiliary position 0 - // take a reading from the ADC. Result range from 0 to 1023 - board.auxData[0] = digitalRead(17); - // Send packet with channel data and auxData contents board.sendChannelData(); } diff --git a/examples/BoardWithSD/BoardWithSD.ino b/examples/BoardWithSD/BoardWithSD.ino deleted file mode 100644 index 8b26f1d..0000000 --- a/examples/BoardWithSD/BoardWithSD.ino +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include -#include -#include - -// Booleans Required for SD_Card_Stuff.ino -boolean addAccelToSD = false; // On writeDataToSDcard() call adds Accel data to SD card write -boolean addAuxToSD = false; // On writeDataToSDCard() call adds Aux data to SD card write -boolean SDfileOpen = false; // Set true by SD_Card_Stuff.ino on successful file open - -void setup() { - board.useAccel(false); - // Bring up the OpenBCI Board - board.begin(); -} - -void loop() { - board.loop(); - if (board.streaming) { - if (board.channelDataAvailable) { - // Read from the ADS(s), store data, set channelDataAvailable flag to false - board.updateChannelData(); - - // Verify the SD file is open - if(SDfileOpen) { - // Write to the SD card - writeDataToSDcard(board.sampleCounter); - } - - // Send standard packet with channel data - board.sendChannelData(); - } - } - - // Check the serial port for new data - if (board.hasDataSerial0()) { - // Read one char from the serial port - char newChar = board.getCharSerial0(); - - // Send to the sd library for processing - sdProcessChar(newChar); - - // Send to the board library - board.processChar(newChar); - } -} diff --git a/examples/BoardWithSD/SD_Card_Stuff.ino b/examples/BoardWithSD/SD_Card_Stuff.ino deleted file mode 100644 index 39b92e4..0000000 --- a/examples/BoardWithSD/SD_Card_Stuff.ino +++ /dev/null @@ -1,423 +0,0 @@ - -#define BLOCK_5MIN 11000 -#define BLOCK_15MIN 33000 -#define BLOCK_30MIN 66000 -#define BLOCK_1HR 131000 -#define BLOCK_2HR 261000 -#define BLOCK_4HR 521000 -#define BLOCK_12HR 1561000 -#define BLOCK_24HR 3122000 - -#define OVER_DIM 20 // make room for up to 20 write-time overruns - - -char fileSize = '0'; // SD file size indicator -int blockCounter = 0; - -uint32_t BLOCK_COUNT; -SdFile openfile; // want to put this before setup... -Sd2Card card(&board.spi,SD_SS);// SPI needs to be init'd before here -SdVolume volume; -SdFile root; -uint8_t* pCache; // array that points to the block buffer on SD card -uint32_t MICROS_PER_BLOCK = 2000; // block write longer than this will get flaged -uint32_t bgnBlock, endBlock; // file extent bookends -int byteCounter = 0; // used to hold position in cache -//int blockCounter; // count up to BLOCK_COUNT with this -boolean openvol; -boolean cardInit = false; -boolean fileIsOpen = false; - -struct { - uint32_t block; // holds block number that over-ran - uint32_t micro; // holds the length of this of over-run -} over[OVER_DIM]; -uint32_t overruns; // count the number of overruns -uint32_t maxWriteTime; // keep track of longest write time -uint32_t minWriteTime; // and shortest write time -uint32_t t; // used to measure total file write time - -byte fileTens, fileOnes; // enumerate succesive files on card and store number in EEPROM -char currentFileName[] = "OBCI_00.TXT"; // file name will enumerate in hex 00 - FF -prog_char elapsedTime[] PROGMEM = {"\n%Total time mS:\n"}; // 17 -prog_char minTime[] PROGMEM = { "%min Write time uS:\n"}; // 20 -prog_char maxTime[] PROGMEM = { "%max Write time uS:\n"}; // 20 -prog_char overNum[] PROGMEM = { "%Over:\n"}; // 7 -prog_char blockTime[] PROGMEM = { "%block, uS\n"}; // 11 74 chars + 2 32(16) + 2 16(8) = 98 + (n 32x2) up to 24 overruns... -prog_char stopStamp[] PROGMEM = { "%STOP AT\n"}; // used to stamp SD record when stopped by PC -prog_char startStamp[] PROGMEM = { "%START AT\n"}; // used to stamp SD record when started by PC - - -char sdProcessChar(char character) { - - switch (character) { - case 'A': // 5min - case 'S': // 15min - case 'F': // 30min - case 'G': // 1hr - case 'H': // 2hr - case 'J': // 4hr - case 'K': // 12hr - case 'L': // 24hr - case 'a': // 512 blocks - fileSize = character; - SDfileOpen = setupSDcard(character); - break; - case 'j': // close the file, if it's open - if(SDfileOpen){ - SDfileOpen = closeSDfile(); - } - break; - case 's': - if(SDfileOpen) { - stampSD(ACTIVATE); - } - break; - case 'b': - if(SDfileOpen) { - stampSD(DEACTIVATE); - } - break; - default: - break; - } - return character; - -} - - -boolean setupSDcard(char limit){ - - if(!cardInit){ - if(!card.init(SPI_FULL_SPEED, SD_SS)) { - if(!board.streaming) { - Serial0.println("initialization failed. Things to check:"); - Serial0.println("* is a card is inserted?"); - } - // card.init(SPI_FULL_SPEED, SD_SS); - } else { - if(!board.streaming) { - Serial0.println("Wiring is correct and a card is present."); - } - cardInit = true; - } - if (!volume.init(card)) { // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 - if(!board.streaming) { - Serial0.println("Could not find FAT16/FAT32 partition. Make sure you've formatted the card"); - board.sendEOT(); - } - return fileIsOpen; - } - } - - // use limit to determine file size - switch(limit){ - case 'h': - BLOCK_COUNT = 50; break; - case 'a': - BLOCK_COUNT = 512; break; - case 'A': - BLOCK_COUNT = BLOCK_5MIN; break; - case 'S': - BLOCK_COUNT = BLOCK_15MIN; break; - case 'F': - BLOCK_COUNT = BLOCK_30MIN; break; - case 'G': - BLOCK_COUNT = BLOCK_1HR; break; - case 'H': - BLOCK_COUNT = BLOCK_2HR; break; - case 'J': - BLOCK_COUNT = BLOCK_4HR; break; - case 'K': - BLOCK_COUNT = BLOCK_12HR; break; - case 'L': - BLOCK_COUNT = BLOCK_24HR; break; - default: - if(!board.streaming) { - Serial0.println("invalid BLOCK count"); - board.sendEOT(); // Write end of transmission because we exit here - } - return fileIsOpen; - } - - incrementFileCounter(); - openvol = root.openRoot(volume); - openfile.remove(root, currentFileName); // if the file is over-writing, let it! - - if (!openfile.createContiguous(root, currentFileName, BLOCK_COUNT*512UL)) { - if(!board.streaming) { - Serial0.print("createfdContiguous fail"); - } - cardInit = false; - }//else{Serial0.print("got contiguous file...");delay(1);} - // get the location of the file's blocks - if (!openfile.contiguousRange(&bgnBlock, &endBlock)) { - if(!board.streaming) { - Serial0.print("get contiguousRange fail"); - } - cardInit = false; - }//else{Serial0.print("got file range...");delay(1);} - // grab the Cache - pCache = (uint8_t*)volume.cacheClear(); - // tell card to setup for multiple block write with pre-erase - if (!card.erase(bgnBlock, endBlock)){ - if(!board.streaming) { - Serial0.println("erase block fail"); - } - cardInit = false; - }//else{Serial0.print("erased...");delay(1);} - if (!card.writeStart(bgnBlock, BLOCK_COUNT)){ - if(!board.streaming) { - Serial0.println("writeStart fail"); - } - cardInit = false; - } else{ - fileIsOpen = true; - delay(1); - } - board.csHigh(SD_SS); // release the spi - // initialize write-time overrun error counter and min/max wirte time benchmarks - overruns = 0; - maxWriteTime = 0; - minWriteTime = 65000; - byteCounter = 0; // counter from 0 - 512 - blockCounter = 0; // counter from 0 - BLOCK_COUNT; - if(fileIsOpen == true){ // send corresponding file name to controlling program - if(!board.streaming) { - Serial0.print("Corresponding SD file "); - Serial0.println(currentFileName); - } - } - if(!board.streaming) { - board.sendEOT(); - } - return fileIsOpen; -} - -boolean closeSDfile(){ - if(fileIsOpen){ - board.csLow(SD_SS); // take spi - card.writeStop(); - openfile.close(); - board.csHigh(SD_SS); // release the spi - fileIsOpen = false; - if(!board.streaming){ // verbosity. this also gets insterted as footer in openFile - Serial0.print("Total Elapsed Time: ");Serial0.print(t);Serial0.println(" mS"); //delay(10); - Serial0.print("Max write time: "); Serial0.print(maxWriteTime); Serial0.println(" uS"); //delay(10); - Serial0.print("Min write time: ");Serial0.print(minWriteTime); Serial0.println(" uS"); //delay(10); - Serial0.print("Overruns: "); Serial0.print(overruns); Serial0.println(); //delay(10); - if (overruns) { - uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns; - Serial0.println("fileBlock,micros"); - for (uint8_t i = 0; i < n; i++) { - Serial0.print(over[i].block); Serial0.print(','); Serial0.println(over[i].micro); - } - } - board.sendEOT(); - } - }else{ - if(!board.streaming) { - Serial0.println("No open file to close"); - board.sendEOT(); - } - } - // delay(100); // cool down - return fileIsOpen; -} - -void writeDataToSDcard(byte sampleNumber){ - boolean addComma = true; - // convert 8 bit sampleCounter into HEX - convertToHex(sampleNumber, 1, addComma); - // convert 24 bit channelData into HEX - for (int currentChannel = 0; currentChannel < 8; currentChannel++){ - convertToHex(board.boardChannelDataInt[currentChannel], 5, addComma); - if(board.daisyPresent == false){ - if(currentChannel == 6){ - addComma = false; - if(addAuxToSD || addAccelToSD) {addComma = true;} // format CSV - } - } - } - if(board.daisyPresent){ - for (int currentChannel = 0; currentChannel < 8; currentChannel++){ - convertToHex(board.daisyChannelDataInt[currentChannel], 5, addComma); - if(currentChannel == 6){ - addComma = false; - if(addAuxToSD || addAccelToSD) {addComma = true;} // format CSV - } - } - } - - if(addAuxToSD == true){ - // convert auxData into HEX - for(int currentChannel = 0; currentChannel < 3; currentChannel++){ - convertToHex(board.auxData[currentChannel], 3, addComma); - if(currentChannel == 1) addComma = false; - } - addAuxToSD = false; - }// end of aux data log - else if(addAccelToSD == true){ // if we have accelerometer data to log - // convert 16 bit accelerometer data into HEX - for (int currentChannel = 0; currentChannel < 3; currentChannel++){ - convertToHex(board.axisData[currentChannel], 3, addComma); - if(currentChannel == 1) addComma = false; - } - addAccelToSD = false; // reset addAccel - }// end of accelerometer data log - - // add aux data logging... -} - - -void writeCache(){ - if(blockCounter > BLOCK_COUNT) return; - uint32_t tw = micros(); // start block write timer - board.csLow(SD_SS); // take spi - if(!card.writeData(pCache)) { - if (!board.streaming) { - Serial0.println("block write fail"); - board.sendEOT(); - } - } // write the block - board.csHigh(SD_SS); // release spi - tw = micros() - tw; // stop block write timer - if (tw > maxWriteTime) maxWriteTime = tw; // check for max write time - if (tw < minWriteTime) minWriteTime = tw; // check for min write time - if (tw > MICROS_PER_BLOCK) { // check for overrun - if (overruns < OVER_DIM) { - over[overruns].block = blockCounter; - over[overruns].micro = tw; - } - overruns++; - } - byteCounter = 0; // reset 512 byte counter for next block - blockCounter++; // increment BLOCK counter - if(blockCounter == BLOCK_COUNT-1){ - t = millis() - t; - board.streamStop(); - // stopRunning(); - board.disable_accel(); - writeFooter(); - } - if(blockCounter == BLOCK_COUNT){ - closeSDfile(); - BLOCK_COUNT = 0; - } // we did it! -} - - -void incrementFileCounter(){ - fileTens = EEPROM.read(0); - fileOnes = EEPROM.read(1); - // if it's the first time writing to EEPROM, seed the file number to '00' - if(fileTens == 0xFF | fileOnes == 0xFF){ - fileTens = fileOnes = '0'; - } - fileOnes++; // increment the file name - if (fileOnes == ':'){fileOnes = 'A';} - if (fileOnes > 'F'){ - fileOnes = '0'; // hexify - fileTens++; - if(fileTens == ':'){fileTens = 'A';} - if(fileTens > 'F'){fileTens = '0';fileOnes = '1';} - } - EEPROM.write(0,fileTens); // store current file number in eeprom - EEPROM.write(1,fileOnes); - currentFileName[5] = fileTens; - currentFileName[6] = fileOnes; -// // send corresponding file name to controlling program -// Serial0.print("Corresponding SD file ");Serial0.println(currentFileName); -} - -void stampSD(boolean state){ - unsigned long time = millis(); - if(state){ - for(int i=0; i<10; i++){ - pCache[byteCounter] = pgm_read_byte_near(startStamp+i); - byteCounter++; - if(byteCounter == 512){ - writeCache(); - } - } - } - else{ - for(int i=0; i<9; i++){ - pCache[byteCounter] = pgm_read_byte_near(stopStamp+i); - byteCounter++; - if(byteCounter == 512){ - writeCache(); - } - } - } - convertToHex(time, 7, false); -} - -void writeFooter(){ - for(int i=0; i<17; i++){ - pCache[byteCounter] = pgm_read_byte_near(elapsedTime+i); - byteCounter++; - } - convertToHex(t, 7, false); - - for(int i=0; i<20; i++){ - pCache[byteCounter] = pgm_read_byte_near(minTime+i); - byteCounter++; - } - convertToHex(minWriteTime, 7, false); - - for(int i=0; i<20; i++){ - pCache[byteCounter] = pgm_read_byte_near(maxTime+i); - byteCounter++; - } - convertToHex(maxWriteTime, 7, false); - - for(int i=0; i<7; i++){ - pCache[byteCounter] = pgm_read_byte_near(overNum+i); - byteCounter++; - } - convertToHex(overruns, 7, false); - for(int i=0; i<11; i++){ - pCache[byteCounter] = pgm_read_byte_near(blockTime+i); - byteCounter++; - } - if (overruns) { - uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns; - for (uint8_t i = 0; i < n; i++) { - convertToHex(over[i].block, 7, true); - convertToHex(over[i].micro, 7, false); - } - } - for(int i=byteCounter; i<512; i++){ - pCache[i] = NULL; - } - writeCache(); -} - -// CONVERT RAW BYTE DATA TO HEX FOR SD STORAGE -void convertToHex(long rawData, int numNibbles, boolean useComma){ - - for (int currentNibble = numNibbles; currentNibble >= 0; currentNibble--){ - byte nibble = (rawData >> currentNibble*4) & 0x0F; - if (nibble > 9){ - nibble += 55; // convert to ASCII A-F - } - else{ - nibble += 48; // convert to ASCII 0-9 - } - pCache[byteCounter] = nibble; - byteCounter++; - if(byteCounter == 512){ - writeCache(); - } - } - if(useComma == true){ - pCache[byteCounter] = ','; - }else{ - pCache[byteCounter] = '\n'; - } - byteCounter++; - if(byteCounter == 512){ - writeCache(); - } -}// end of byteToHex converter diff --git a/examples/BoardWithWifiDebug/BoardWithWifiDebug.ino b/examples/BoardWithWifiDebug/BoardWithWifiDebug.ino deleted file mode 100644 index a16735f..0000000 --- a/examples/BoardWithWifiDebug/BoardWithWifiDebug.ino +++ /dev/null @@ -1,94 +0,0 @@ -#include - -int packetSendIntervalMs = 100; // 50 ms -unsigned long lastPacketSent = millis(); -const int packetSize = 32; -uint8_t buf[packetSize]; -uint8_t WIFI_SS = 13; - -DSPI0 spi; // use DSPI library - -boolean streaming = false; -boolean wifi = false; - -void setup() { - - - buf[1] = (uint8_t)'A'; - buf[2] = (uint8_t)'J'; - buf[3] = (uint8_t)' '; - buf[4] = (uint8_t)'K'; - buf[5] = (uint8_t)'E'; - buf[6] = (uint8_t)'L'; - buf[7] = (uint8_t)'L'; - buf[8] = (uint8_t)'E'; - buf[9] = (uint8_t)'R'; - - pinMode(WIFI_SS,OUTPUT); digitalWrite(WIFI_SS,HIGH); - - spi.begin(); - spi.setSpeed(10000000); // use 4MHz for ADS and LIS3DH - spi.setMode(DSPI_MODE0); // default to SD card mode! - - Serial0.begin(115200); -} - -void loop() { - if (millis() > lastPacketSent + packetSendIntervalMs) { - if (streaming) { - flushbufToSpi(); - } - lastPacketSent = millis(); - } - - - // Check serial 0 for new data - if (Serial0.available()) { - // Read one char from the serial 0 port - char newChar = Serial0.read(); - - switch (newChar) { - case 'b': - streaming = true; - Serial0.println("starting stream"); - break; - case 's': - streaming = false; - Serial0.println("stopping stream"); - break; - case 'w': - wifi = !wifi; - if (wifi) { - Serial0.println("enabled wifi mode"); - } else { - Serial0.println("disabled wifi mode"); - } - break; - case '0': - digitalWrite(WIFI_SS,LOW); - Serial0.println("forced pin 13 to low"); - break; - case '1': - digitalWrite(WIFI_SS,HIGH); - Serial0.println("forced pin 13 to high"); - break; - default: - Serial0.print("Sup? Dis char i don't get... "); - Serial0.println(newChar); - break; - } - } -} - -void flushbufToSpi() { - uint8_t i = 0; - uint8_t len = packetSize; - if (wifi) digitalWrite(WIFI_SS,LOW); - spi.transfer(0x02); - spi.transfer(0x00); - while(i < packetSize) { - spi.transfer('a'); - i++; - } - if (wifi) digitalWrite(WIFI_SS,HIGH); -} diff --git a/examples/DefaultBoard/DefaultBoard.ino b/examples/DefaultBoard/DefaultBoard.ino index d8ebab8..7e58a6c 100644 --- a/examples/DefaultBoard/DefaultBoard.ino +++ b/examples/DefaultBoard/DefaultBoard.ino @@ -22,14 +22,19 @@ void loop() { board.updateChannelData(); // Check to see if accel has new data - if(board.accelHasNewData()) { - // Get new accel data - board.accelUpdateAxisData(); + if (board.curAccelMode == board.ACCEL_MODE_ON) { + if(board.accelHasNewData()) { + // Get new accel data + board.accelUpdateAxisData(); - // Tell the SD_Card_Stuff.ino to add accel data in the next write to SD - addAccelToSD = true; // Set false after writeDataToSDcard() + // Tell the SD_Card_Stuff.ino to add accel data in the next write to SD + addAccelToSD = true; // Set false after writeDataToSDcard() + } + } else { + addAuxToSD = true; } + // Verify the SD file is open if(SDfileOpen) { // Write to the SD card, writes aux data