Repository: adafruit/Adafruit_BluefruitLE_nRF51 Branch: master Commit: 16412c28c5d2 Files: 84 Total size: 447.8 KB Directory structure: gitextract_kl7q1fgt/ ├── .github/ │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── Adafruit_ATParser.cpp ├── Adafruit_ATParser.h ├── Adafruit_BLE.cpp ├── Adafruit_BLE.h ├── Adafruit_BLEBattery.cpp ├── Adafruit_BLEBattery.h ├── Adafruit_BLEEddystone.cpp ├── Adafruit_BLEEddystone.h ├── Adafruit_BLEGatt.cpp ├── Adafruit_BLEGatt.h ├── Adafruit_BLEMIDI.cpp ├── Adafruit_BLEMIDI.h ├── Adafruit_BluefruitLE_SPI.cpp ├── Adafruit_BluefruitLE_SPI.h ├── Adafruit_BluefruitLE_UART.cpp ├── Adafruit_BluefruitLE_UART.h ├── README.md ├── SDEP.md ├── changelog.md ├── changelog_firmware.md ├── examples/ │ ├── atcommand/ │ │ ├── BluefruitConfig.h │ │ └── atcommand.ino │ ├── battery/ │ │ ├── BluefruitConfig.h │ │ └── battery.ino │ ├── beacon/ │ │ ├── BluefruitConfig.h │ │ └── beacon.ino │ ├── bleuart_cmdmode/ │ │ ├── BluefruitConfig.h │ │ └── bleuart_cmdmode.ino │ ├── bleuart_datamode/ │ │ ├── BluefruitConfig.h │ │ └── bleuart_datamode.ino │ ├── callbacks/ │ │ ├── BluefruitConfig.h │ │ └── callbacks.ino │ ├── callbacks_dfuirq/ │ │ ├── BluefruitConfig.h │ │ └── callbacks_dfuirq.ino │ ├── controller/ │ │ ├── BluefruitConfig.h │ │ ├── controller.ino │ │ └── packetParser.cpp │ ├── cplay_neopixel_picker/ │ │ ├── BluefruitConfig.h │ │ ├── cplay_neopixel_picker.ino │ │ └── packetParser.cpp │ ├── eddystone/ │ │ ├── BluefruitConfig.h │ │ └── eddystone.ino │ ├── factoryreset/ │ │ ├── BluefruitConfig.h │ │ └── factoryreset.ino │ ├── feathertester/ │ │ ├── BluefruitConfig.h │ │ └── feathertester.ino │ ├── healththermometer/ │ │ ├── BluefruitConfig.h │ │ ├── IEEE11073float.cpp │ │ ├── IEEE11073float.h │ │ └── healththermometer.ino │ ├── heartratemonitor/ │ │ ├── BluefruitConfig.h │ │ └── heartratemonitor.ino │ ├── hidcontrolkey/ │ │ ├── BluefruitConfig.h │ │ └── hidcontrolkey.ino │ ├── hidkeyboard/ │ │ ├── BluefruitConfig.h │ │ └── hidkeyboard.ino │ ├── hidmouse/ │ │ ├── BluefruitConfig.h │ │ └── hidmouse.ino │ ├── midi/ │ │ ├── BluefruitConfig.h │ │ └── midi.ino │ ├── ndof_bno055/ │ │ ├── BluefruitConfig.h │ │ ├── README.md │ │ └── ndof_bno055.ino │ ├── neopixel/ │ │ ├── BluefruitConfig.h │ │ └── neopixel.ino │ ├── neopixel_picker/ │ │ ├── BluefruitConfig.h │ │ ├── neopixel_picker.ino │ │ └── packetParser.cpp │ ├── nvmdata/ │ │ ├── BluefruitConfig.h │ │ └── nvmdata.ino │ ├── throughput/ │ │ ├── BluefruitConfig.h │ │ └── throughput.ino │ └── uribeacon/ │ ├── BluefruitConfig.h │ └── uribeacon.ino ├── keywords.txt ├── library.properties └── utility/ ├── Adafruit_FIFO.cpp ├── Adafruit_FIFO.h ├── TimeoutTimer.h ├── common_header.h ├── errors.h └── sdep.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ Thank you for opening an issue on an Adafruit Arduino library repository. To improve the speed of resolution please review the following guidelines and common troubleshooting steps below before creating the issue: - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use the forums at http://forums.adafruit.com to ask questions and troubleshoot why something isn't working as expected. In many cases the problem is a common issue that you will more quickly receive help from the forum community. GitHub issues are meant for known defects in the code. If you don't know if there is a defect in the code then start with troubleshooting on the forum first. - **If following a tutorial or guide be sure you didn't miss a step.** Carefully check all of the steps and commands to run have been followed. Consult the forum if you're unsure or have questions about steps in a guide/tutorial. - **For Arduino projects check these very common issues to ensure they don't apply**: - For uploading sketches or communicating with the board make sure you're using a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes very hard to tell the difference between a data and charge cable! Try using the cable with other devices or swapping to another cable to confirm it is not the problem. - **Be sure you are supplying adequate power to the board.** Check the specs of your board and plug in an external power supply. In many cases just plugging a board into your computer is not enough to power it and other peripherals. - **Double check all soldering joints and connections.** Flakey connections cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. - **Ensure you are using an official Arduino or Adafruit board.** We can't guarantee a clone board will have the same functionality and work as expected with this code and don't support them. If you're sure this issue is a defect in the code and checked the steps above please fill in the following fields to provide enough troubleshooting information. You may delete the guideline and text above to just leave the following details: - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO VERSION HERE** - List the steps to reproduce the problem below (if possible attach a sketch or copy the sketch code in too): **LIST REPRO STEPS BELOW** ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ Thank you for creating a pull request to contribute to Adafruit's GitHub code! Before you open the request please review the following guidelines and tips to help it be more easily integrated: - **Describe the scope of your change--i.e. what the change does and what parts of the code were modified.** This will help us understand any risks of integrating the code. - **Describe any known limitations with your change.** For example if the change doesn't apply to a supported platform of the library please mention it. - **Please run any tests or examples that can exercise your modified code.** We strive to not break users of the code and running tests/examples helps with this process. Thank you again for contributing! We will try to test and integrate the change as soon as we can, but be aware we have many GitHub repositories to manage and can't immediately respond to every request. There is no need to bump or check in on a pull request (it will clutter the discussion of the request). Also don't be worried if the request is closed or not integrated--sometimes the priorities of Adafruit's GitHub code (education, ease of use) might not match the priorities of the pull request. Don't fret, the open source community thrives on forks and GitHub makes it easy to keep your changes in a forked repo. After reviewing the guidelines above you can delete this text from the pull request. ================================================ FILE: Adafruit_ATParser.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_ATParser.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_ATParser.h" static inline char digit2ascii(uint8_t digit) { return ( digit + ((digit) < 10 ? '0' : ('A'-10)) ); } /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_ATParser::Adafruit_ATParser(void) { _mode = BLUEFRUIT_MODE_COMMAND; _verbose = false; } /******************************************************************************/ /*! @brief Read the whole response and check if it ended up with OK. @return true if response is ended with "OK". Otherwise it could be "ERROR" */ /******************************************************************************/ bool Adafruit_ATParser::waitForOK(void) { if (_verbose) SerialDebug.print( F("\n<- ") ); // Use temp buffer to avoid overwrite returned result if any char tempbuf[BLE_BUFSIZE+1]; while ( readline(tempbuf, BLE_BUFSIZE) ) { if ( strcmp(tempbuf, "OK") == 0 ) return true; if ( strcmp(tempbuf, "ERROR") == 0 ) return false; // Copy to internal buffer if not OK or ERROR strcpy(this->buffer, tempbuf); } return false; } /******************************************************************************/ /*! @brief @param */ /******************************************************************************/ bool Adafruit_ATParser::send_arg_get_resp(int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]) { // Command arguments according to its type for(uint8_t i=0; iprint( (char const*) args[i] ); break; case AT_ARGTYPE_BYTEARRAY: { uint8_t count = lowByte(argtype[i]); this->printByteArray( (uint8_t const*) args[i], count ); } break; case AT_ARGTYPE_UINT32: print( (uint32_t) args[i] ); break; case AT_ARGTYPE_INT32: print( (int32_t) args[i] ); break; case AT_ARGTYPE_UINT16: print( (uint16_t) args[i] ); break; case AT_ARGTYPE_INT16: print( (int16_t) args[i] ); break; case AT_ARGTYPE_UINT8: print( (uint8_t) ((uint32_t)args[i]) ); break; case AT_ARGTYPE_INT8: print( (int8_t) ((int32_t) args[i]) ); break; default: break; } if (i != argcount-1) print(','); } println(); // execute command // parse integer response if required if (reply) { if (_verbose) SerialDebug.print( F("\n<- ") ); (*reply) = readline_parseInt(); } // check OK or ERROR status return waitForOK(); } /******************************************************************************/ /*! @brief @param */ /******************************************************************************/ bool Adafruit_ATParser::atcommand_full(const char cmd[], int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]) { bool result; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter and get response print(cmd); result = this->send_arg_get_resp(reply, argcount, argtype, args); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result; } /******************************************************************************/ /*! @brief @param */ /******************************************************************************/ bool Adafruit_ATParser::atcommand_full(const __FlashStringHelper *cmd, int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]) { bool result; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter and get response print(cmd); result = this->send_arg_get_resp(reply, argcount, argtype, args); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result; } /******************************************************************************/ /*! @brief Send an AT command and get multiline string response into user-provided buffer. @param[in] cmd Command @param[in] buf Provided buffer @param[in] bufsize buffer size @param[in] timeout timeout in milliseconds */ /******************************************************************************/ uint16_t Adafruit_ATParser::atcommandStrReply(const char cmd[], char* buf, uint16_t bufsize, uint16_t timeout) { uint16_t result_bytes; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter and get response println(cmd); result_bytes = this->readline(buf, bufsize, timeout, true); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result_bytes; } uint16_t Adafruit_ATParser::atcommandStrReply(const __FlashStringHelper *cmd, char* buf, uint16_t bufsize, uint16_t timeout) { uint16_t result_bytes; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter and get response println(cmd); result_bytes = this->readline(buf, bufsize, timeout, true); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result_bytes; } /******************************************************************************/ /*! @brief Send an AT command and process a multiline string response by a user-provided callback executed per line. @param[in] cmd Command @param[in] linebuf Buffer to hold text of each line at a time @param[in] bufsize buffer size @param[in] timeout timeout in milliseconds to wait for each line @param[in] line_callback function called for each line @param[in] callback_data user-provided state for callback */ /******************************************************************************/ uint16_t Adafruit_ATParser::atcommandStrReplyPerLine( const char cmd[], char* linebuf, uint16_t bufsize, uint16_t timeout, void (*line_callback)(void*, char*, uint16_t), void* callback_data) { uint16_t result_bytes; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter, get response, process line-by-line println(cmd); do { result_bytes = this->readline(linebuf, bufsize, timeout, false); if (0 == strncmp(linebuf, "OK", 2) || 0 == strncmp(linebuf, "ERROR", 5)) break; (*line_callback)(callback_data, linebuf, result_bytes); } while (result_bytes > 0); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result_bytes; } uint16_t Adafruit_ATParser::atcommandStrReplyPerLine( const __FlashStringHelper *cmd, char* linebuf, uint16_t bufsize, uint16_t timeout, void (*line_callback)(void*, char*, uint16_t), void* callback_data) { uint16_t result_bytes; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // Execute command with parameter, get response, process line-by-line println(cmd); do { result_bytes = this->readline(linebuf, bufsize, timeout, false); if (0 == strncmp(linebuf, "OK", 2) || 0 == strncmp(linebuf, "ERROR", 5)) break; (*line_callback)(callback_data, linebuf, result_bytes); } while (result_bytes > 0); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result_bytes; } /******************************************************************************/ /*! @brief Get a line of response data (see \ref readline) and try to interpret it to an integer number. If the number is prefix with '0x', it will be interpreted as hex number. This function also drop the rest of data to the end of the line. */ /******************************************************************************/ int32_t Adafruit_ATParser::readline_parseInt(void) { uint16_t len = readline(); if (len == 0) return 0; // also parsed hex number e.g 0xADAF int32_t val = strtol(buffer, NULL, 0); return val; } /******************************************************************************/ /*! @brief Get a line of response data into provided buffer. @param[in] buf Provided buffer @param[in] bufsize buffer size @param[in] timeout timeout in milliseconds @param[in] multiline Read multiple line if true, otherwise only read 1 line @note '\r' and '\n' are not included in returned buffer. */ /******************************************************************************/ uint16_t Adafruit_ATParser::readline(char * buf, uint16_t bufsize, uint16_t timeout, boolean multiline) { uint16_t replyidx = 0; while (timeout--) { while(available()) { char c = read(); //SerialDebug.println(c); if (c == '\r') continue; if (c == '\n') { // the first '\n' is ignored if (replyidx == 0) continue; if (!multiline) { timeout = 0; break; } } buf[replyidx] = c; replyidx++; // Buffer is full if (replyidx >= bufsize) { //if (_verbose) { SerialDebug.println("*overflow*"); } // for my debuggin' only! timeout = 0; break; } } // delay if needed if (timeout) delay(1); } buf[replyidx] = 0; // null term // Print out if is verbose if (_verbose && replyidx > 0) { SerialDebug.print(buf); if (replyidx < bufsize) SerialDebug.println(); } return replyidx; } /******************************************************************************/ /*! @brief Get raw binary data to internal buffer, only stop when encountering either "OK\r\n" or "ERROR\r\n" or timed out. Buffer does not contain OK or ERROR @param[in] timeout Timeout for each read() operation @return The number of bytes read excluding OK, ERROR ending. 0 usually means error */ /******************************************************************************/ uint16_t Adafruit_ATParser::readraw(uint16_t timeout) { uint16_t replyidx = 0; while (timeout--) { while(available()) { char c = read(); if (c == '\n') { // done if ends with "OK\r\n" if ( (replyidx >= 3) && !strncmp(this->buffer + replyidx-3, "OK\r", 3) ) { replyidx -= 3; // chop OK\r timeout = 0; break; } // done if ends with "ERROR\r\n" else if ((replyidx >= 6) && !strncmp(this->buffer + replyidx-6, "ERROR\r", 6)) { replyidx -= 6; // chop ERROR\r timeout = 0; break; } } this->buffer[replyidx] = c; replyidx++; // Buffer is full if (replyidx >= BLE_BUFSIZE) { //if (_verbose) { SerialDebug.println("*overflow*"); } // for my debuggin' only! timeout = 0; break; } } if (timeout == 0) break; delay(1); } this->buffer[replyidx] = 0; // null term // Print out if is verbose // if (_verbose && replyidx > 0) // { // SerialDebug.print(buffer); // if (replyidx < BLE_BUFSIZE) SerialDebug.println(); // } return replyidx; } /******************************************************************************/ /*! @brief Print a buffer to BYTE ARRAY format e.g 11-22-33-44-55 @param bytearray buffer to print @param size number of byte @return number of printed characters */ /******************************************************************************/ int Adafruit_ATParser::printByteArray(uint8_t const bytearray[], int size) { while(size--) { uint8_t byte = *bytearray++; write( digit2ascii((byte & 0xF0) >> 4) ); write( digit2ascii(byte & 0x0F) ); if ( size!=0 ) write('-'); } return (size*3) - 1; } ================================================ FILE: Adafruit_ATParser.h ================================================ /**************************************************************************/ /*! @file Adafruit_ATParser.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_ATPARSER_H_ #define _ADAFRUIT_ATPARSER_H_ #include #include "utility/sdep.h" // Class to facilitate sending AT Command and check response #define BLUEFRUIT_MODE_COMMAND HIGH #define BLUEFRUIT_MODE_DATA LOW #define BLE_BUFSIZE 4*SDEP_MAX_PACKETSIZE #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) #define SerialDebug SERIAL_PORT_USBVIRTUAL #else #define SerialDebug Serial #endif // High byte is type, Low byte is datacount // datacount is needed when passing ByteArray argument enum { AT_ARGTYPE_STRING = 0x0100, AT_ARGTYPE_BYTEARRAY = 0x0200, AT_ARGTYPE_INT32 = 0x0300, AT_ARGTYPE_UINT32 = 0x0400, AT_ARGTYPE_INT16 = 0x0500, AT_ARGTYPE_UINT16 = 0x0600, AT_ARGTYPE_INT8 = 0x0700, AT_ARGTYPE_UINT8 = 0x0800, }; class Adafruit_ATParser : public Stream { protected: uint8_t _mode; bool _verbose; // internal function bool send_arg_get_resp(int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]); public: Adafruit_ATParser(void); char buffer[BLE_BUFSIZE+1]; uint8_t getMode(void) { return _mode; } virtual bool setMode(uint8_t mode) = 0; // Auto print out TX & RX data to normal Serial void verbose(bool enable) { _verbose = enable; } bool atcommand_full(const char cmd[] , int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]); bool atcommand_full(const __FlashStringHelper *cmd , int32_t* reply, uint8_t argcount, uint16_t argtype[], uint32_t args[]); //--------------------------------------------------------------------+ // Without Reply //--------------------------------------------------------------------+ bool atcommand(const char cmd[] ) { return this->atcommand_full(cmd, NULL, 0, NULL, NULL); } bool atcommand(const __FlashStringHelper *cmd ) { return this->atcommand_full(cmd, NULL, 0, NULL, NULL); } //------------- One integer argument -------------// bool atcommand(const char cmd[] , int32_t para1) { uint16_t type[] = { AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1 }; return this->atcommand_full(cmd, NULL, 1, type, args); } bool atcommand(const __FlashStringHelper *cmd, int32_t para1) { uint16_t type[] = { AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1 }; return this->atcommand_full(cmd, NULL, 1, type, args); } //------------- Two integer arguments -------------// bool atcommand(const char cmd[] , int32_t para1, int32_t para2) { uint16_t type[] = { AT_ARGTYPE_INT32, AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1, (uint32_t) para2 }; return this->atcommand_full(cmd, NULL, 2, type, args); } bool atcommand(const __FlashStringHelper *cmd, int32_t para1, int32_t para2) { uint16_t type[] = { AT_ARGTYPE_INT32, AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1, (uint32_t) para2 }; return this->atcommand_full(cmd, NULL, 2, type, args); } //------------- One ByteArray arguments -------------// bool atcommand(const char cmd[] , const uint8_t bytearray[], uint16_t count) { uint16_t type[] = { (uint16_t) (AT_ARGTYPE_BYTEARRAY+count) }; uint32_t args[] = { (uint32_t) bytearray }; return this->atcommand_full(cmd, NULL, 1, type, args); } bool atcommand(const __FlashStringHelper *cmd, const uint8_t bytearray[], uint16_t count) { uint16_t type[] = { (uint16_t) (AT_ARGTYPE_BYTEARRAY+count) }; uint32_t args[] = { (uint32_t) bytearray }; return this->atcommand_full(cmd, NULL, 1, type, args); } //------------- One String argument -------------// bool atcommand(const char cmd[] , const char* str) { uint16_t type[] = { AT_ARGTYPE_STRING }; uint32_t args[] = { (uint32_t) str }; return this->atcommand_full(cmd, NULL, 1, type, args); } bool atcommand(const __FlashStringHelper *cmd, const char* str) { uint16_t type[] = { AT_ARGTYPE_STRING }; uint32_t args[] = { (uint32_t) str }; return this->atcommand_full(cmd, NULL, 1, type, args); } //--------------------------------------------------------------------+ // With Reply //--------------------------------------------------------------------+ bool atcommandIntReply(const char cmd[], int32_t* reply) { return this->atcommand_full(cmd, reply, 0, NULL, NULL); } bool atcommandIntReply(const __FlashStringHelper *cmd, int32_t* reply) { return this->atcommand_full(cmd, reply, 0, NULL, NULL); } uint16_t atcommandStrReply(const char cmd[], char* buf, uint16_t bufsize, uint16_t timeout); uint16_t atcommandStrReply(const __FlashStringHelper *cmd, char* buf, uint16_t bufsize, uint16_t timeout); uint16_t atcommandStrReplyPerLine(const char cmd[], char* linebuf, uint16_t bufsize, uint16_t timeout, void (*line_callback)(void*, char*, uint16_t), void* callback_data); uint16_t atcommandStrReplyPerLine(const __FlashStringHelper *cmd, char* linebuf, uint16_t bufsize, uint16_t timeout, void (*line_callback)(void*, char*, uint16_t), void* callback_data); //------------- One integer argument -------------// bool atcommandIntReply(const char cmd[] , int32_t* reply, int32_t para1) { uint16_t type[] = { AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1 }; return this->atcommand_full(cmd, reply, 1, type, args); } bool atcommandIntReply(const __FlashStringHelper *cmd, int32_t* reply, int32_t para1) { uint16_t type[] = { AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1 }; return this->atcommand_full(cmd, reply, 1, type, args); } //------------- Two integer arguments -------------// bool atcommandIntReply(const char cmd[] , int32_t* reply, int32_t para1, int32_t para2) { uint16_t type[] = { AT_ARGTYPE_INT32, AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1, (uint32_t) para2 }; return this->atcommand_full(cmd, reply, 2, type, args); } bool atcommandIntReply(const __FlashStringHelper *cmd, int32_t* reply, int32_t para1, int32_t para2) { uint16_t type[] = { AT_ARGTYPE_INT32, AT_ARGTYPE_INT32 }; uint32_t args[] = { (uint32_t) para1, (uint32_t) para2 }; return this->atcommand_full(cmd, reply, 2, type, args); } //------------- One ByteArray arguments -------------// bool atcommandIntReply(const char cmd[] , int32_t* reply, const uint8_t bytearray[], uint16_t count) { uint16_t type[] = { (uint16_t) (AT_ARGTYPE_BYTEARRAY+count) }; uint32_t args[] = { (uint32_t) bytearray }; return this->atcommand_full(cmd, reply, 1, type, args); } bool atcommandIntReply(const __FlashStringHelper *cmd, int32_t* reply, const uint8_t bytearray[], uint16_t count) { uint16_t type[] = { (uint16_t) (AT_ARGTYPE_BYTEARRAY+count) }; uint32_t args[] = { (uint32_t) bytearray }; return this->atcommand_full(cmd, reply, 1, type, args); } //------------- One String argument -------------// bool atcommandIntReply(const char cmd[] , int32_t* reply, const char* str) { uint16_t type[] = { AT_ARGTYPE_STRING }; uint32_t args[] = { (uint32_t) str }; return this->atcommand_full(cmd, reply, 1, type, args); } bool atcommandIntReply(const __FlashStringHelper *cmd, int32_t* reply, const char* str) { uint16_t type[] = { AT_ARGTYPE_STRING }; uint32_t args[] = { (uint32_t) str }; return this->atcommand_full(cmd, reply, 1, type, args); } //--------------------------------------------------------------------+ // RESPONSE PROCESSING //--------------------------------------------------------------------+ bool waitForOK(void); // Read one line of response into internal buffer TODO use below API // Read one line of response into provided buffer uint16_t readline(char * buf, uint16_t bufsize, uint16_t timeout, boolean multiline = false); uint16_t readline(uint8_t * buf, uint16_t bufsize, uint16_t timeout, boolean multiline = false) { return readline( (char*) buf, bufsize, timeout, multiline ); } uint16_t readline(char * buf, uint16_t bufsize) { return readline(buf, bufsize, _timeout, false); } uint16_t readline(uint8_t * buf, uint16_t bufsize) { return readline(buf, bufsize, _timeout, false); } uint16_t readline(uint16_t timeout, boolean multiline = false) { return readline(this->buffer, BLE_BUFSIZE, timeout, multiline); } uint16_t readline(void) { return this->readline(this->buffer, BLE_BUFSIZE, _timeout, false); } // read one line and convert the string to integer number int32_t readline_parseInt(void); uint16_t readraw(uint16_t timeout); uint16_t readraw(void) { return readraw(_timeout); } //--------------------------------------------------------------------+ // HELPER //--------------------------------------------------------------------+ int printByteArray(uint8_t const bytearray[], int size); }; #endif /* _ADAFRUIT_ATPARSER_H_ */ ================================================ FILE: Adafruit_BLE.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BLE.c @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2014, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BLE.h" #include "Adafruit_BLEMIDI.h" #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif enum { EVENT_SYSTEM_CONNECT = 0, EVENT_SYSTEM_DISCONNECT = 1, EVENT_SYSTEM_BLE_UART_RX = 8, // 9 reserved EVENT_SYSTEM_BLE_MIDI_RX = 10, // 11 reserved }; enum { NVM_USERDATA_SIZE = 256 }; /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_BLE::Adafruit_BLE(void) { _timeout = BLE_DEFAULT_TIMEOUT; _reset_started_timestamp = 0; _disconnect_callback = NULL; _connect_callback = NULL; _ble_uart_rx_callback = NULL; _ble_midi_rx_callback = NULL; _ble_gatt_rx_callback = NULL; } /******************************************************************************/ /*! @brief Helper to install callback @param */ /******************************************************************************/ void Adafruit_BLE::install_callback(bool enable, int8_t system_id, int8_t gatts_id) { uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); print( enable ? F("AT+EVENTENABLE=0x") : F("AT+EVENTDISABLE=0x") ); print( (system_id < 0) ? 0 : bit(system_id), HEX ); if ( gatts_id >= 0 ) { print( F(",0x") ); println( bit(gatts_id), HEX ); } println(); waitForOK(); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); } /******************************************************************************/ /*! @brief Performs a system reset using AT command @param blocking blocking until bluefruit is ready, will take 1 second mostly */ /******************************************************************************/ bool Adafruit_BLE::reset(boolean blocking) { bool isOK; // println(); for (uint8_t t=0; t < 5; t++) { isOK = atcommand(F("ATZ")); if (isOK) break; } if (! isOK) { // ok we're going to get desperate delay(50); setMode(BLUEFRUIT_MODE_COMMAND); delay(50); for (uint8_t t=0; t < 5; t++) { isOK = atcommand(F("ATZ")); if (isOK) break; } if (!isOK) return false; } _reset_started_timestamp = millis(); // Bluefruit need 1 second to reboot if (blocking) { delay(1000); } // flush all left over flush(); return isOK; } /******************************************************************************/ /*! @brief Performs a factory reset */ /******************************************************************************/ bool Adafruit_BLE::factoryReset(boolean blocking) { println( F("AT+FACTORYRESET") ); bool isOK = waitForOK(); _reset_started_timestamp = millis(); // Bluefruit need 1 second to reboot if (blocking) { delay(1000); } // flush all left over flush(); return isOK; } /******************************************************************************/ /*! @brief Check if the reset process is completed, should be used if user reset Bluefruit with non-blocking aka reset(false) */ /******************************************************************************/ bool Adafruit_BLE::resetCompleted(void) { return millis() > (_reset_started_timestamp + 1000); } /******************************************************************************/ /*! @brief Enable or disable AT Command echo from Bluefruit @parma[in] enable true to enable (default), false to disable */ /******************************************************************************/ bool Adafruit_BLE::echo(bool enable) { return atcommand(F("ATE"), (int32_t) enable); } /******************************************************************************/ /*! @brief Check connection state, returns true is connected! */ /******************************************************************************/ bool Adafruit_BLE::isConnected(void) { int32_t connected = 0; atcommandIntReply(F("AT+GAPGETCONN"), &connected); return connected; } /******************************************************************************/ /*! @brief Disconnect if currently connected */ /******************************************************************************/ void Adafruit_BLE::disconnect(void) { atcommand( F("AT+GAPDISCONNECT") ); } /******************************************************************************/ /*! @brief Print Bluefruit's information retrieved by ATI command */ /******************************************************************************/ void Adafruit_BLE::info(void) { uint8_t current_mode = _mode; bool v = _verbose; _verbose = false; SerialDebug.println(F("----------------")); // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); println(F("ATI")); while ( readline() ) { if ( !strcmp(buffer, "OK") || !strcmp(buffer, "ERROR") ) break; SerialDebug.println(buffer); } // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); SerialDebug.println(F("----------------")); _verbose = v; } /**************************************************************************/ /*! @brief Checks if firmware is equal or later than specified version */ /**************************************************************************/ bool Adafruit_BLE::isVersionAtLeast(const char * versionString) { uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // requesting version number println(F("ATI=4")); readline(); bool result = ( strcmp(buffer, versionString) >= 0 ); waitForOK(); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return result; } /******************************************************************************/ /*! @brief Get (multiple) lines of response data into internal buffer. @param[in] period_ms period in milliseconds between each event scanning @return None */ /******************************************************************************/ void Adafruit_BLE::update(uint32_t period_ms) { static TimeoutTimer tt; if ( tt.expired() ) { tt.set(period_ms); bool v = _verbose; _verbose = false; uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); println( F("AT+EVENTSTATUS") ); readline(); waitForOK(); // parse event status system_event, gatts_event uint8_t tempbuf[BLE_BUFSIZE+1]; uint32_t system_event, gatts_event; char * p_comma = NULL; system_event = strtoul(this->buffer, &p_comma, 16); gatts_event = strtoul(p_comma+1, NULL, 16); //--------------------------------------------------------------------+ // System Event //--------------------------------------------------------------------+ if ( this->_connect_callback && bitRead(system_event, EVENT_SYSTEM_CONNECT ) ) this->_connect_callback(); if ( this->_disconnect_callback && bitRead(system_event, EVENT_SYSTEM_DISCONNECT) ) this->_disconnect_callback(); if ( this->_ble_uart_rx_callback && bitRead(system_event, EVENT_SYSTEM_BLE_UART_RX) ) { // _verbose = true; println( F("AT+BLEUARTRX") ); uint16_t len = readline(tempbuf, BLE_BUFSIZE); waitForOK(); this->_ble_uart_rx_callback( (char*) tempbuf, len); } if ( this->_ble_midi_rx_callback && bitRead(system_event, EVENT_SYSTEM_BLE_MIDI_RX) ) { // _verbose = true; while(1) { // use RAW command version println( F("AT+BLEMIDIRXRAW") ); // readraw swallow OK/ERROR already uint16_t len = readraw(); // break if there is no more MIDI event if ( len == 0 ) break; // copy to internal buffer for other usage ! memcpy(tempbuf, this->buffer, len); Adafruit_BLEMIDI::processRxCallback(tempbuf, len, this->_ble_midi_rx_callback); } } //--------------------------------------------------------------------+ // Gatt Event //--------------------------------------------------------------------+ if ( this->_ble_gatt_rx_callback && gatts_event ) { // _verbose = true; for(uint8_t charid=1; charid < 30; charid++) { if ( bitRead(gatts_event, charid-1) ) { print( F("AT+GATTCHARRAW=") ); // use RAW command version println(charid); uint16_t len = readraw(); // readraw swallow OK/ERROR already memcpy(tempbuf, this->buffer, len); this->_ble_gatt_rx_callback(charid, tempbuf, len); } } } // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); _verbose = v; } } /******************************************************************************/ /*! @brief Set custom ADV data packet @param */ /******************************************************************************/ bool Adafruit_BLE::setAdvData(uint8_t advdata[], uint8_t size) { return this->atcommand(F("AT+GAPSETADVDATA"), advdata, size); } /******************************************************************************/ /*! @brief Save user information to NVM section, current size limit is 256 bytes @param data buffer holding data @param size number of bytes @param offset relative offset in the NVM section */ /******************************************************************************/ bool Adafruit_BLE::writeNVM(uint16_t offset, uint8_t const data[], uint16_t size) { VERIFY_(offset + size <= NVM_USERDATA_SIZE ); uint16_t type[] = { AT_ARGTYPE_UINT16, AT_ARGTYPE_UINT8, (uint16_t) (AT_ARGTYPE_BYTEARRAY + size) }; uint32_t args[] = { offset, BLE_DATATYPE_BYTEARRAY, (uint32_t) data }; return this->atcommand_full(F("AT+NVMWRITE"), NULL, 3, type, args); } /******************************************************************************/ /*! @brief Save String to NVM section, current size limit is 256 bytes @param data buffer holding data @param size number of bytes @param offset relative offset in the NVM section */ /******************************************************************************/ bool Adafruit_BLE::writeNVM(uint16_t offset, char const* str) { VERIFY_(offset + strlen(str) <= NVM_USERDATA_SIZE ); uint16_t type[] = { AT_ARGTYPE_UINT16, AT_ARGTYPE_UINT8, AT_ARGTYPE_STRING }; uint32_t args[] = { offset, BLE_DATATYPE_STRING, (uint32_t) str }; return this->atcommand_full(F("AT+NVMWRITE"), NULL, 3, type, args); } /******************************************************************************/ /*! @brief Save an 32-bit number to NVM @param number Number to be saved @param offset relative offset in the NVM section */ /******************************************************************************/ bool Adafruit_BLE::writeNVM(uint16_t offset, int32_t number) { VERIFY_(offset + 4 <= NVM_USERDATA_SIZE ); uint16_t type[] = { AT_ARGTYPE_UINT16, AT_ARGTYPE_UINT8, AT_ARGTYPE_INT32 }; uint32_t args[] = { offset, BLE_DATATYPE_INTEGER, (uint32_t) number }; return this->atcommand_full(F("AT+NVMWRITE"), NULL, 3, type, args); } /******************************************************************************/ /*! @brief Read an number of bytes from NVM at offset to buffer @param */ /******************************************************************************/ bool Adafruit_BLE::readNVM(uint16_t offset, uint8_t data[], uint16_t size) { VERIFY_(offset < NVM_USERDATA_SIZE); uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND); // use RAW command version print( F("AT+NVMREADRAW=") ); print(offset); print(','); println(size); uint16_t len = readraw(); // readraw swallow OK/ERROR already // Check for an error reading if ( len != size ) return false; // skip if NULL is entered if (data) memcpy(data, this->buffer, min(size, BLE_BUFSIZE)); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA); return true; } /******************************************************************************/ /*! @brief Read a string from NVM at offset to buffer @param */ /******************************************************************************/ bool Adafruit_BLE::readNVM(uint16_t offset, char* str, uint16_t size) { VERIFY_(offset < NVM_USERDATA_SIZE); uint16_t type[] = { AT_ARGTYPE_UINT16, AT_ARGTYPE_UINT16, AT_ARGTYPE_UINT8 }; uint32_t args[] = { offset, size, BLE_DATATYPE_STRING}; bool isOK = this->atcommand_full(F("AT+NVMREAD"), NULL, 3, type, args); // skip if NULL is entered if ( isOK && str ) strncpy(str, this->buffer, min(size, BLE_BUFSIZE)); return isOK; } /******************************************************************************/ /*! @brief Read an 32-bit number from NVM @param */ /******************************************************************************/ bool Adafruit_BLE::readNVM(uint16_t offset, int32_t* number) { return this->readNVM(offset, (uint8_t*)number, 4); } /** * * @param buffer * @param size * @return */ int Adafruit_BLE::writeBLEUart(uint8_t const * buffer, int size) { uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_COMMAND ) setMode(BLUEFRUIT_MODE_DATA); size_t n = write(buffer, size); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_COMMAND ) setMode(BLUEFRUIT_MODE_COMMAND); return n; } /** * * @param buffer * @param size * @return */ int Adafruit_BLE::readBLEUart(uint8_t* buffer, int size) { uint8_t current_mode = _mode; // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_COMMAND ) setMode(BLUEFRUIT_MODE_DATA); size_t n = readBytes(buffer, size); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_COMMAND ) setMode(BLUEFRUIT_MODE_COMMAND); return n; } /******************************************************************************/ /*! @brief Set handle for connect callback @param[in] fp function pointer, NULL will discard callback */ /******************************************************************************/ void Adafruit_BLE::setConnectCallback( void (*fp) (void) ) { this->_connect_callback = fp; install_callback(fp != NULL, EVENT_SYSTEM_CONNECT, -1); } /******************************************************************************/ /*! @brief Set handle for disconnection callback @param[in] fp function pointer, NULL will discard callback */ /******************************************************************************/ void Adafruit_BLE::setDisconnectCallback( void (*fp) (void) ) { this->_disconnect_callback = fp; install_callback(fp != NULL, EVENT_SYSTEM_DISCONNECT, -1); } /******************************************************************************/ /*! @brief Set handle for BLE Uart Rx callback @param[in] fp function pointer, NULL will discard callback */ /******************************************************************************/ void Adafruit_BLE::setBleUartRxCallback( void (*fp) (char data[], uint16_t len) ) { this->_ble_uart_rx_callback = fp; install_callback(fp != NULL, EVENT_SYSTEM_BLE_UART_RX, -1); } /******************************************************************************/ /*! @brief Set handle for BLE MIDI Rx callback @param[in] fp function pointer, NULL will discard callback */ /******************************************************************************/ void Adafruit_BLE::setBleMidiRxCallback( midiRxCallback_t fp ) { this->_ble_midi_rx_callback = fp; install_callback(fp != NULL, EVENT_SYSTEM_BLE_MIDI_RX, -1); } /******************************************************************************/ /*! @brief Set handle for BLE Gatt Rx callback @param[in] fp function pointer, NULL will discard callback */ /******************************************************************************/ void Adafruit_BLE::setBleGattRxCallback(int32_t chars_idx, void (*fp) (int32_t, uint8_t[], uint16_t) ) { if ( chars_idx == 0) return; this->_ble_gatt_rx_callback = fp; install_callback(fp != NULL, -1, chars_idx-1); } ================================================ FILE: Adafruit_BLE.h ================================================ /**************************************************************************/ /*! @file Adafruit_BLE.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2014, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _Adafruit_BLE_H_ #define _Adafruit_BLE_H_ #include #include #include "utility/common_header.h" #include "utility/errors.h" #include "utility/TimeoutTimer.h" #include "Adafruit_ATParser.h" #define BLE_DEFAULT_TIMEOUT 250 enum BLEDataType_t { BLE_DATATYPE_AUTO = 0, BLE_DATATYPE_STRING, BLE_DATATYPE_BYTEARRAY, BLE_DATATYPE_INTEGER, }; class Adafruit_BLE : public Adafruit_ATParser { protected: enum { BLUEFRUIT_TRANSPORT_INVALID, BLUEFRUIT_TRANSPORT_HWUART, BLUEFRUIT_TRANSPORT_SWUART, BLUEFRUIT_TRANSPORT_HWSPI, BLUEFRUIT_TRANSPORT_SWSPI, }; // uint8_t _mode; // uint16_t _timeout; uint8_t _physical_transport; uint32_t _reset_started_timestamp; public: typedef void (*midiRxCallback_t) (uint16_t timestamp, uint8_t status, uint8_t byte1, uint8_t byte2); // Constructor Adafruit_BLE(void); // Functions implemented in this base class bool reset(boolean blocking = true); bool factoryReset(boolean blocking = true); bool resetCompleted(void); void info(void); bool echo(bool enable); bool isConnected(void); bool isVersionAtLeast(const char * versionString); void disconnect(void); bool setAdvData(uint8_t advdata[], uint8_t size); bool writeNVM(uint16_t offset, uint8_t const data[], uint16_t size); bool writeNVM(uint16_t offset, char const* str); bool writeNVM(uint16_t offset, int32_t number); bool readNVM(uint16_t offset, uint8_t data[], uint16_t size); bool readNVM(uint16_t offset, char * str , uint16_t size); bool readNVM(uint16_t offset, int32_t* number); // helper with bleuart int writeBLEUart(uint8_t const * buffer, int size); int writeBLEUart(char const * str) { return writeBLEUart( (uint8_t const*) str, strlen(str)); } int readBLEUart(uint8_t* buffer, int size); // No parameters bool sendCommandCheckOK(const __FlashStringHelper *cmd) { return this->atcommand(cmd); } bool sendCommandCheckOK(const char cmd[]) { return this->atcommand(cmd); } bool sendCommandWithIntReply(const __FlashStringHelper *cmd, int32_t *reply) { return this->atcommandIntReply(cmd, reply); } bool sendCommandWithIntReply(const char cmd[] , int32_t *reply) { return this->atcommandIntReply(cmd, reply); } // Physical transportation checking bool isTransportHwUart (void) { return _physical_transport == BLUEFRUIT_TRANSPORT_HWUART; } bool isTransportSwUart (void) { return _physical_transport == BLUEFRUIT_TRANSPORT_SWUART; } bool isTransportUart (void) { return isTransportHwUart() || isTransportSwUart(); } bool isTransportHwSpi (void) { return _physical_transport == BLUEFRUIT_TRANSPORT_HWSPI; } bool isTransportSwSpi (void) { return _physical_transport == BLUEFRUIT_TRANSPORT_SWSPI; } bool isTransportSpi (void) { return isTransportHwSpi() || isTransportSwSpi(); } ///////////////////// // callback functions ///////////////////// void update(uint32_t period_ms = 200); void handleDfuIrq(void) { this->update(0); } void setDisconnectCallback( void (*fp) (void) ); void setConnectCallback ( void (*fp) (void) ); void setBleUartRxCallback( void (*fp) (char data[], uint16_t len) ); void setBleMidiRxCallback( midiRxCallback_t fp ); void setBleGattRxCallback( int32_t chars_idx, void (*fp) (int32_t, uint8_t[], uint16_t) ); protected: // helper void install_callback(bool enable, int8_t system_id, int8_t gatts_id); void (*_disconnect_callback) (void); void (*_connect_callback) (void); void (*_ble_uart_rx_callback) (char data[], uint16_t len); midiRxCallback_t _ble_midi_rx_callback; void (*_ble_gatt_rx_callback) (int32_t chars_id, uint8_t data[], uint16_t len); }; //--------------------------------------------------------------------+ // DEBUG HELPER //--------------------------------------------------------------------+ #ifndef DBG_ENABLE #define DBG_ENABLE 0 #endif #if DBG_ENABLE #define DBG_LOCATION() Serial.printf("%s: %d: \r\n", __PRETTY_FUNCTION__, __LINE__) #define DBG_INT(x) do { Serial.print(#x " = "); Serial.println(x); } while(0) #define DBG_HEX(x) do { Serial.print(#x " = "); Serial.println(x, HEX); } while(0) #define DBG_STR(x) Serial.printf(#x " = %s\r\n", (char*)(x) ) #define DBG_BUFFER(buf, n) \ do {\ uint8_t* p8 = (uint8_t*) (buf);\ Serial.print(#buf ": ");\ for(uint32_t i=0; i<(n); i++) Serial.printf("%02x ", p8[i]);\ Serial.print("\r\n");\ }while(0) #endif #endif /* _Adafruit_BLE_H_ */ ================================================ FILE: Adafruit_BLEBattery.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BLEBatterry.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BLEBattery.h" /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_BLEBattery::Adafruit_BLEBattery(Adafruit_BLE& ble) : _ble(ble) { } /******************************************************************************/ /*! @brief Enable Battery service if not already enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEBattery::begin(bool reset) { int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+BLEBATTEN"), &enabled) ); if ( enabled ) return true; VERIFY_( _ble.atcommand( F("AT+BLEBATTEN=1") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Stop Battery service if it is enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEBattery::stop(bool reset) { int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+BLEBATTEN"), &enabled) ); if ( !enabled ) return true; VERIFY_( _ble.atcommand( F("AT+BLEBATTEN=0") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Update Battery level value @param percent Battery value in percentage 0-100 */ /******************************************************************************/ bool Adafruit_BLEBattery::update(uint8_t percent) { VERIFY_( is_within(0, percent, 100) ); return _ble.atcommand( F("AT+BLEBATTVAL"), percent ) ; } ================================================ FILE: Adafruit_BLEBattery.h ================================================ /**************************************************************************/ /*! @file Adafruit_BLEBatterry.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_BLEBATTERY_H_ #define _ADAFRUIT_BLEBATTERY_H_ #include #include "Adafruit_BLE.h" class Adafruit_BLEBattery { private: Adafruit_BLE& _ble; public: Adafruit_BLEBattery(Adafruit_BLE& ble); bool begin(bool reset = true); bool stop (bool reset = true); bool update(uint8_t percent); }; #endif /* _ADAFRUIT_BLEBATTERY_H_ */ ================================================ FILE: Adafruit_BLEEddystone.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BLEEddystone.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BLEEddystone.h" #define EDDYSTONE_MINIMUM_FIRMWARE_VERSION "0.7.0" /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_BLEEddystone::Adafruit_BLEEddystone(Adafruit_BLE& ble) : _ble(ble) { } /******************************************************************************/ /*! @brief Enable Eddystone service if not already enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEEddystone::begin(bool reset) { VERIFY_( _ble.isVersionAtLeast(EDDYSTONE_MINIMUM_FIRMWARE_VERSION) ); int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+EDDYSTONESERVICEEN"), &enabled) ); if ( enabled ) return true; VERIFY_( _ble.atcommand( F("AT+EDDYSTONESERVICEEN=1") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Stop Eddystone service if it is enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEEddystone::stop(bool reset) { int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+EDDYSTONESERVICEEN"), &enabled) ); if ( !enabled ) return true; VERIFY_( _ble.atcommand( F("AT+EDDYSTONESERVICEEN=0") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Change Bluefruit's URL setting in NVM @param url URL to be advertized @param broadcastEvenConnect Keep broadcasting even Bluefruit is connected @param rssi_at_0m RSSI value at 0m (check out EddyStone specs) */ /******************************************************************************/ bool Adafruit_BLEEddystone::setURL(const char* url, bool broadcastEvenConnect, int8_t rssi_at_0m) { bool result; uint8_t current_mode = _ble.getMode(); // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_COMMAND); // send command and integer parameters separated by comma _ble.print( F("AT+EDDYSTONEURL=") ); _ble.print(url); _ble.print(','); _ble.print(broadcastEvenConnect, DEC); _ble.print(','); _ble.print(rssi_at_0m); _ble.println(); // execute command result = _ble.waitForOK(); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_DATA); return result; } /******************************************************************************/ /*! @brief Start Broadcasting (advertising) specified URL */ /******************************************************************************/ bool Adafruit_BLEEddystone::startBroadcast(void) { return _ble.atcommand( F("AT+EDDYSTONEBROADCAST=1") ); } /******************************************************************************/ /*! @brief Stop Broadcasting (advertising) specified URL */ /******************************************************************************/ bool Adafruit_BLEEddystone::stopBroadcast(void) { return _ble.atcommand( F("AT+EDDYSTONEBROADCAST=0") ); } /******************************************************************************/ /*! @brief Broadcast (advertising) specified URL */ /******************************************************************************/ bool Adafruit_BLEEddystone::startConfigMode(uint32_t seconds) { return _ble.atcommand( F("AT+EDDYSTONECONFIGEN"), (int32_t) seconds ); } ================================================ FILE: Adafruit_BLEEddystone.h ================================================ /**************************************************************************/ /*! @file Adafruit_BLEEddystone.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_BLEEDDYSTONE_H_ #define _ADAFRUIT_BLEEDDYSTONE_H_ #include #include "Adafruit_BLE.h" #define EDDYSTONE_DEFAULT_RSSI0M (-18) class Adafruit_BLEEddystone { private: Adafruit_BLE& _ble; public: Adafruit_BLEEddystone(Adafruit_BLE& ble); bool begin(bool reset = true); bool stop (bool reset = true); bool setURL(const char* url, bool broadcastEvenConnect = false, int8_t rssi_at_0m = EDDYSTONE_DEFAULT_RSSI0M); bool startBroadcast(void); bool stopBroadcast(void); bool startConfigMode(uint32_t seconds); }; #endif /* _ADAFRUIT_BLEEDDYSTONE_H_ */ ================================================ FILE: Adafruit_BLEGatt.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BLEGatt.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BLEGatt.h" /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_BLEGatt::Adafruit_BLEGatt(Adafruit_BLE& ble) : _ble(ble) { this->buffer = _ble.buffer; } /******************************************************************************/ /*! @brief Clear all GATT data */ /******************************************************************************/ bool Adafruit_BLEGatt::clear(void) { return _ble.atcommand( F("AT+GATTCLEAR") ); } /******************************************************************************/ /*! @brief Add a service with 16-bit UUID @return Service ID (starting from 1). If failed 0 is returned */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::addService(uint16_t uuid16) { int32_t service_id; VERIFY_RETURN_( _ble.atcommandIntReply( F("AT+GATTADDSERVICE=UUID"), &service_id, uuid16), 0 ); return (uint8_t) service_id; } /******************************************************************************/ /*! @brief Add a service with 128-bit UUID @return Service ID (starting from 1). If failed 0 is returned */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::addService(uint8_t uuid128[]) { int32_t service_id; VERIFY_RETURN_( _ble.atcommandIntReply( F("AT+GATTADDSERVICE=UUID128"), &service_id, uuid128, 16), 0 ); return (uint8_t) service_id; } /******************************************************************************/ /*! @brief Internal function to add Characteristic @return Chars ID (starting from 1). If failed 0 is returned */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::addChar_internal(uint8_t uuid[], uint8_t uuid_len, uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description, const GattPresentationFormat* presentFormat) { bool isOK; int32_t chars_id; uint8_t current_mode = _ble.getMode(); // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_COMMAND); // Standard UUID or UUID128 if ( uuid_len == 2 ) { uint16_t uuid16; memcpy(&uuid16, uuid, 2); _ble.print( F("AT+GATTADDCHAR=UUID=") ); _ble.print(uuid16); }else { _ble.print( F("AT+GATTADDCHAR=UUID128=") ); _ble.printByteArray(uuid, 16); } _ble.print( F(",PROPERTIES=") ); _ble.print(properties); _ble.print( F(",MIN_LEN=") ); _ble.print(min_len); _ble.print( F(",MAX_LEN=") ); _ble.print(max_len); _ble.print( F(",DATATYPE=") ); _ble.print((uint8_t) datatype); if (description) { _ble.print( F(",DESCRIPTION=") ); _ble.print(description); } if (presentFormat && presentFormat->format) { // presentation format is packed 7 bytes, use tempbuf to avoid mis-aligned memory uint8_t tempbuf[7]; memcpy(tempbuf, presentFormat, 5); memcpy(tempbuf+5, &presentFormat->desc, 2); _ble.print( F(",PRESENTATION=") ); _ble.printByteArray(tempbuf, 7); } _ble.println(); // execute command // if (_verbose) SerialDebug.print( F("\n<- ") ); chars_id = _ble.readline_parseInt(); isOK = _ble.waitForOK(); // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_DATA); return isOK ? chars_id : 0; } /******************************************************************************/ /*! @brief Add a characteristics with UUID16 to a newly added service @param @return Chars ID (starting from 1). If failed 0 is returned */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::addCharacteristic(uint16_t uuid16, uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description, const GattPresentationFormat* presentFormat) { return addChar_internal((uint8_t*) &uuid16, 2, properties, min_len, max_len, datatype, description, presentFormat); } /******************************************************************************/ /*! @brief Add a characteristics with UUID128 to a newly added service @param @return Chars ID (starting from 1). If failed 0 is returned */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::addCharacteristic(uint8_t uuid128[], uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description, const GattPresentationFormat* presentFormat) { return addChar_internal(uuid128, 16, properties, min_len, max_len, datatype, description, presentFormat); } /******************************************************************************/ /*! @brief Set Characteristics value with data buffer @param */ /******************************************************************************/ bool Adafruit_BLEGatt::setChar(uint8_t charID, uint8_t const data[], uint8_t size) { uint16_t argtype[] = { AT_ARGTYPE_UINT8, (uint16_t) (AT_ARGTYPE_BYTEARRAY+ size) }; uint32_t args[] = { charID, (uint32_t) data }; return _ble.atcommand_full(F("AT+GATTCHAR"), NULL, 2, argtype, args); } /******************************************************************************/ /*! @brief Set Characteristics value with data buffer @param */ /******************************************************************************/ bool Adafruit_BLEGatt::setChar(uint8_t charID, char const* str) { uint16_t argtype[] = { AT_ARGTYPE_UINT8, AT_ARGTYPE_STRING }; uint32_t args[] = { charID, (uint32_t) str }; return _ble.atcommand_full(F("AT+GATTCHAR"), NULL, 2, argtype, args); } /******************************************************************************/ /*! @brief Read Characteristics value to internal buffer @param charID Characteristics ID @return number of bytes copied to buffer (up to bufsize). 0 usually means error. */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::getChar(uint8_t charID) { uint8_t current_mode = _ble.getMode(); // switch mode if necessary to execute command if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_COMMAND); // use RAW command version _ble.print( F("AT+GATTCHARRAW=") ); _ble.println(charID); uint16_t len = _ble.readraw(); // readraw swallow OK/ERROR already // switch back if necessary if ( current_mode == BLUEFRUIT_MODE_DATA ) _ble.setMode(BLUEFRUIT_MODE_DATA); return len; } /******************************************************************************/ /*! @brief Read Characteristics value to user's buffer @param charID Characteristics ID @param buf buffer to hold data @param bufsize size of buffer @return number of bytes copied to buffer (up to bufsize). 0 usually means error. */ /******************************************************************************/ uint8_t Adafruit_BLEGatt::getChar(uint8_t charID, uint8_t* buf, uint8_t bufsize) { uint8_t len = this->getChar(charID); len = min(len, bufsize); memcpy(buf, _ble.buffer, len); return len; } ================================================ FILE: Adafruit_BLEGatt.h ================================================ /**************************************************************************/ /*! @file Adafruit_BLEGatt.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_BLEGATT_H_ #define _ADAFRUIT_BLEGATT_H_ #include #include "Adafruit_BLE.h" #define GATT_CHARS_PROPERTIES_BROADCAST bit(0) #define GATT_CHARS_PROPERTIES_READ bit(1) #define GATT_CHARS_PROPERTIES_WRITE_WO_RESP bit(2) #define GATT_CHARS_PROPERTIES_WRITE bit(3) #define GATT_CHARS_PROPERTIES_NOTIFY bit(4) #define GATT_CHARS_PROPERTIES_INDICATE bit(5) struct GattPresentationFormat { uint8_t format; int8_t exponent; uint16_t unit; uint8_t name_space; uint16_t desc; }; class Adafruit_BLEGatt { private: Adafruit_BLE& _ble; uint8_t addChar_internal(uint8_t uuid[], uint8_t uuid_len, uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description, const GattPresentationFormat* presentFormat); public: char* buffer; // alias to ble's buffer Adafruit_BLEGatt(Adafruit_BLE& ble); bool clear(void); uint8_t addService(uint16_t uuid16); uint8_t addService(uint8_t uuid128[]); uint8_t addCharacteristic(uint16_t uuid16 , uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description = NULL, const GattPresentationFormat* presentFormat = NULL); uint8_t addCharacteristic(uint8_t uuid128[], uint8_t properties, uint8_t min_len, uint8_t max_len, BLEDataType_t datatype, const char* description = NULL, const GattPresentationFormat* presentFormat = NULL); //------------- Get Characteristic -------------// uint8_t getChar(uint8_t charID); uint8_t getChar(uint8_t charID, uint8_t* buf, uint8_t bufsize); uint8_t getCharInt8(uint8_t charID) { if ( this->getChar(charID) < sizeof(uint8_t) ) return 0; uint8_t result; memcpy(&result, this->buffer, sizeof(result)); return result; } uint16_t getCharInt16(uint8_t charID) { if ( this->getChar(charID) < sizeof(uint16_t) ) return 0; uint16_t result; memcpy(&result, this->buffer, sizeof(result)); return result; } uint32_t getCharInt32(uint8_t charID) { if ( this->getChar(charID) < sizeof(uint32_t) ) return 0; uint32_t result; memcpy(&result, this->buffer, sizeof(result)); return result; } char* getCharStr(uint8_t charID) { if ( this->getChar(charID) == 0 ) return NULL; return this->buffer; } //------------- Set Characteristic -------------// bool setChar(uint8_t charID, uint8_t const data[], uint8_t size); bool setChar(uint8_t charID, char const * str); bool setChar(uint8_t charID, uint8_t data8 ) { return this->setChar(charID, (uint8_t*) &data8, 1); } bool setChar(uint8_t charID, int8_t data8 ) { return this->setChar(charID, (uint8_t*) &data8, 1); } bool setChar(uint8_t charID, uint16_t data16) { return this->setChar(charID, (uint8_t*) &data16, 2); } bool setChar(uint8_t charID, int16_t data16) { return this->setChar(charID, (uint8_t*) &data16, 2); } bool setChar(uint8_t charID, uint32_t data32) { return this->setChar(charID, (uint8_t*) &data32, 4); } bool setChar(uint8_t charID, int32_t data32) { return this->setChar(charID, (uint8_t*) &data32, 4); } }; enum { GATT_PRESENT_FORMAT_BOOLEAN = 0x01, GATT_PRESENT_FORMAT_2BIT = 0x02, GATT_PRESENT_FORMAT_4BIT = 0x03, GATT_PRESENT_FORMAT_UINT8 = 0x04, GATT_PRESENT_FORMAT_UINT12 = 0x05, GATT_PRESENT_FORMAT_UINT16 = 0x06, GATT_PRESENT_FORMAT_UINT24 = 0x07, GATT_PRESENT_FORMAT_UINT32 = 0x08, GATT_PRESENT_FORMAT_UINT48 = 0x09, GATT_PRESENT_FORMAT_UINT64 = 0x0A, GATT_PRESENT_FORMAT_UINT128 = 0x0B, GATT_PRESENT_FORMAT_SINT8 = 0x0C, GATT_PRESENT_FORMAT_SINT12 = 0x0D, GATT_PRESENT_FORMAT_SINT16 = 0x0E, GATT_PRESENT_FORMAT_SINT24 = 0x0F, GATT_PRESENT_FORMAT_SINT32 = 0x10, GATT_PRESENT_FORMAT_SINT48 = 0x11, GATT_PRESENT_FORMAT_SINT64 = 0x12, GATT_PRESENT_FORMAT_SINT128 = 0x13, GATT_PRESENT_FORMAT_FLOAT32 = 0x14, GATT_PRESENT_FORMAT_FLOAT64 = 0x15, GATT_PRESENT_FORMAT_SFLOAT = 0x16, GATT_PRESENT_FORMAT_FLOAT = 0x17, GATT_PRESENT_FORMAT_DUINT16 = 0x18, GATT_PRESENT_FORMAT_UTF8S = 0x19, GATT_PRESENT_FORMAT_UTF16S = 0x1A, GATT_PRESENT_FORMAT_STRUCT = 0x1B, }; /* See https://developer.bluetooth.org/gatt/units/Pages/default.aspx */ enum { GATT_PRESENT_UNIT_NONE = 0x2700, GATT_PRESENT_UNIT_LENGTH_METRE = 0x2701, GATT_PRESENT_UNIT_MASS_KILOGRAM = 0x2702, GATT_PRESENT_UNIT_TIME_SECOND = 0x2703, GATT_PRESENT_UNIT_ELECTRIC_CURRENT_AMPERE = 0x2704, GATT_PRESENT_UNIT_THERMODYNAMIC_TEMPERATURE_KELVIN = 0x2705, GATT_PRESENT_UNIT_AMOUNT_OF_SUBSTANCE_MOLE = 0x2706, GATT_PRESENT_UNIT_LUMINOUS_INTENSITY_CANDELA = 0x2707, GATT_PRESENT_UNIT_AREA_SQUARE_METRES = 0x2710, GATT_PRESENT_UNIT_VOLUME_CUBIC_METRES = 0x2711, GATT_PRESENT_UNIT_VELOCITY_METRES_PER_SECOND = 0x2712, GATT_PRESENT_UNIT_ACCELERATION_METRES_PER_SECOND_SQUARED = 0x2713, GATT_PRESENT_UNIT_WAVENUMBER_RECIPROCAL_METRE = 0x2714, GATT_PRESENT_UNIT_DENSITY_KILOGRAM_PER_CUBIC_METRE = 0x2715, GATT_PRESENT_UNIT_SURFACE_DENSITY_KILOGRAM_PER_SQUARE_METRE = 0x2716, GATT_PRESENT_UNIT_SPECIFIC_VOLUME_CUBIC_METRE_PER_KILOGRAM = 0x2717, GATT_PRESENT_UNIT_CURRENT_DENSITY_AMPERE_PER_SQUARE_METRE = 0x2718, GATT_PRESENT_UNIT_MAGNETIC_FIELD_STRENGTH_AMPERE_PER_METRE = 0x2719, GATT_PRESENT_UNIT_AMOUNT_CONCENTRATION_MOLE_PER_CUBIC_METRE = 0x271A, GATT_PRESENT_UNIT_MASS_CONCENTRATION_KILOGRAM_PER_CUBIC_METRE = 0x271B, GATT_PRESENT_UNIT_LUMINANCE_CANDELA_PER_SQUARE_METRE = 0x271C, GATT_PRESENT_UNIT_REFRACTIVE_INDEX = 0x271D, GATT_PRESENT_UNIT_RELATIVE_PERMEABILITY = 0x271E, GATT_PRESENT_UNIT_PLANE_ANGLE_RADIAN = 0x2720, GATT_PRESENT_UNIT_SOLID_ANGLE_STERADIAN = 0x2721, GATT_PRESENT_UNIT_FREQUENCY_HERTZ = 0x2722, GATT_PRESENT_UNIT_FORCE_NEWTON = 0x2723, GATT_PRESENT_UNIT_PRESSURE_PASCAL = 0x2724, GATT_PRESENT_UNIT_ENERGY_JOULE = 0x2725, GATT_PRESENT_UNIT_POWER_WATT = 0x2726, GATT_PRESENT_UNIT_ELECTRIC_CHARGE_COULOMB = 0x2727, GATT_PRESENT_UNIT_ELECTRIC_POTENTIAL_DIFFERENCE_VOLT = 0x2728, GATT_PRESENT_UNIT_CAPACITANCE_FARAD = 0x2729, GATT_PRESENT_UNIT_ELECTRIC_RESISTANCE_OHM = 0x272A, GATT_PRESENT_UNIT_ELECTRIC_CONDUCTANCE_SIEMENS = 0x272B, GATT_PRESENT_UNIT_MAGNETIC_FLEX_WEBER = 0x272C, GATT_PRESENT_UNIT_MAGNETIC_FLEX_DENSITY_TESLA = 0x272D, GATT_PRESENT_UNIT_INDUCTANCE_HENRY = 0x272E, GATT_PRESENT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_CELSIUS = 0x272F, GATT_PRESENT_UNIT_LUMINOUS_FLUX_LUMEN = 0x2730, GATT_PRESENT_UNIT_ILLUMINANCE_LUX = 0x2731, GATT_PRESENT_UNIT_ACTIVITY_REFERRED_TO_A_RADIONUCLIDE_BECQUEREL = 0x2732, GATT_PRESENT_UNIT_ABSORBED_DOSE_GRAY = 0x2733, GATT_PRESENT_UNIT_DOSE_EQUIVALENT_SIEVERT = 0x2734, GATT_PRESENT_UNIT_CATALYTIC_ACTIVITY_KATAL = 0x2735, GATT_PRESENT_UNIT_DYNAMIC_VISCOSITY_PASCAL_SECOND = 0x2740, GATT_PRESENT_UNIT_MOMENT_OF_FORCE_NEWTON_METRE = 0x2741, GATT_PRESENT_UNIT_SURFACE_TENSION_NEWTON_PER_METRE = 0x2742, GATT_PRESENT_UNIT_ANGULAR_VELOCITY_RADIAN_PER_SECOND = 0x2743, GATT_PRESENT_UNIT_ANGULAR_ACCELERATION_RADIAN_PER_SECOND_SQUARED = 0x2744, GATT_PRESENT_UNIT_HEAT_FLUX_DENSITY_WATT_PER_SQUARE_METRE = 0x2745, GATT_PRESENT_UNIT_HEAT_CAPACITY_JOULE_PER_KELVIN = 0x2746, GATT_PRESENT_UNIT_SPECIFIC_HEAT_CAPACITY_JOULE_PER_KILOGRAM_KELVIN = 0x2747, GATT_PRESENT_UNIT_SPECIFIC_ENERGY_JOULE_PER_KILOGRAM = 0x2748, GATT_PRESENT_UNIT_THERMAL_CONDUCTIVITY_WATT_PER_METRE_KELVIN = 0x2749, GATT_PRESENT_UNIT_ENERGY_DENSITY_JOULE_PER_CUBIC_METRE = 0x274A, GATT_PRESENT_UNIT_ELECTRIC_FIELD_STRENGTH_VOLT_PER_METRE = 0x274B, GATT_PRESENT_UNIT_ELECTRIC_CHARGE_DENSITY_COULOMB_PER_CUBIC_METRE = 0x274C, GATT_PRESENT_UNIT_SURFACE_CHARGE_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274D, GATT_PRESENT_UNIT_ELECTRIC_FLUX_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274E, GATT_PRESENT_UNIT_PERMITTIVITY_FARAD_PER_METRE = 0x274F, GATT_PRESENT_UNIT_PERMEABILITY_HENRY_PER_METRE = 0x2750, GATT_PRESENT_UNIT_MOLAR_ENERGY_JOULE_PER_MOLE = 0x2751, GATT_PRESENT_UNIT_MOLAR_ENTROPY_JOULE_PER_MOLE_KELVIN = 0x2752, GATT_PRESENT_UNIT_EXPOSURE_COULOMB_PER_KILOGRAM = 0x2753, GATT_PRESENT_UNIT_ABSORBED_DOSE_RATE_GRAY_PER_SECOND = 0x2754, GATT_PRESENT_UNIT_RADIANT_INTENSITY_WATT_PER_STERADIAN = 0x2755, GATT_PRESENT_UNIT_RADIANCE_WATT_PER_SQUARE_METRE_STERADIAN = 0x2756, GATT_PRESENT_UNIT_CATALYTIC_ACTIVITY_CONCENTRATION_KATAL_PER_CUBIC_METRE = 0x2757, GATT_PRESENT_UNIT_TIME_MINUTE = 0x2760, GATT_PRESENT_UNIT_TIME_HOUR = 0x2761, GATT_PRESENT_UNIT_TIME_DAY = 0x2762, GATT_PRESENT_UNIT_PLANE_ANGLE_DEGREE = 0x2763, GATT_PRESENT_UNIT_PLANE_ANGLE_MINUTE = 0x2764, GATT_PRESENT_UNIT_PLANE_ANGLE_SECOND = 0x2765, GATT_PRESENT_UNIT_AREA_HECTARE = 0x2766, GATT_PRESENT_UNIT_VOLUME_LITRE = 0x2767, GATT_PRESENT_UNIT_MASS_TONNE = 0x2768, GATT_PRESENT_UNIT_PRESSURE_BAR = 0x2780, GATT_PRESENT_UNIT_PRESSURE_MILLIMETRE_OF_MERCURY = 0x2781, GATT_PRESENT_UNIT_LENGTH_ANGSTROM = 0x2782, GATT_PRESENT_UNIT_LENGTH_NAUTICAL_MILE = 0x2783, GATT_PRESENT_UNIT_AREA_BARN = 0x2784, GATT_PRESENT_UNIT_VELOCITY_KNOT = 0x2785, GATT_PRESENT_UNIT_LOGARITHMIC_RADIO_QUANTITY_NEPER = 0x2786, GATT_PRESENT_UNIT_LOGARITHMIC_RADIO_QUANTITY_BEL = 0x2787, GATT_PRESENT_UNIT_LENGTH_YARD = 0x27A0, GATT_PRESENT_UNIT_LENGTH_PARSEC = 0x27A1, GATT_PRESENT_UNIT_LENGTH_INCH = 0x27A2, GATT_PRESENT_UNIT_LENGTH_FOOT = 0x27A3, GATT_PRESENT_UNIT_LENGTH_MILE = 0x27A4, GATT_PRESENT_UNIT_PRESSURE_POUND_FORCE_PER_SQUARE_INCH = 0x27A5, GATT_PRESENT_UNIT_VELOCITY_KILOMETRE_PER_HOUR = 0x27A6, GATT_PRESENT_UNIT_VELOCITY_MILE_PER_HOUR = 0x27A7, GATT_PRESENT_UNIT_ANGULAR_VELOCITY_REVOLUTION_PER_MINUTE = 0x27A8, GATT_PRESENT_UNIT_ENERGY_GRAM_CALORIE = 0x27A9, GATT_PRESENT_UNIT_ENERGY_KILOGRAM_CALORIE = 0x27AA, GATT_PRESENT_UNIT_ENERGY_KILOWATT_HOUR = 0x27AB, GATT_PRESENT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_FAHRENHEIT = 0x27AC, GATT_PRESENT_UNIT_PERCENTAGE = 0x27AD, GATT_PRESENT_UNIT_PER_MILLE = 0x27AE, GATT_PRESENT_UNIT_PERIOD_BEATS_PER_MINUTE = 0x27AF, GATT_PRESENT_UNIT_ELECTRIC_CHARGE_AMPERE_HOURS = 0x27B0, GATT_PRESENT_UNIT_MASS_DENSITY_MILLIGRAM_PER_DECILITRE = 0x27B1, GATT_PRESENT_UNIT_MASS_DENSITY_MILLIMOLE_PER_LITRE = 0x27B2, GATT_PRESENT_UNIT_TIME_YEAR = 0x27B3, GATT_PRESENT_UNIT_TIME_MONTH = 0x27B4, GATT_PRESENT_UNIT_CONCENTRATION_COUNT_PER_CUBIC_METRE = 0x27B5, GATT_PRESENT_UNIT_IRRADIANCE_WATT_PER_SQUARE_METRE = 0x27B6 }; #endif /* _ADAFRUIT_BLEGATT_H_ */ ================================================ FILE: Adafruit_BLEMIDI.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BLEMIDI.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BLEMIDI.h" #define MIDI_MINIMUM_FIRMWARE_VERSION "0.7.0" /******************************************************************************/ /*! @brief Constructor */ /******************************************************************************/ Adafruit_BLEMIDI::Adafruit_BLEMIDI(Adafruit_BLE& ble) : _ble(ble) { } /******************************************************************************/ /*! @brief Set callback */ /******************************************************************************/ void Adafruit_BLEMIDI::setRxCallback(midiRxCallback_t fp) { _ble.setBleMidiRxCallback(fp); } /******************************************************************************/ /*! @brief Enable MIDI service if not already enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEMIDI::begin(bool reset) { VERIFY_( _ble.isVersionAtLeast(MIDI_MINIMUM_FIRMWARE_VERSION) ); int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+BLEMIDIEN"), &enabled) ); if ( enabled ) return true; VERIFY_( _ble.atcommand( F("AT+BLEMIDIEN=1") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Stop MIDI service if it is enabled @param reset true will reset Bluefruit */ /******************************************************************************/ bool Adafruit_BLEMIDI::stop(bool reset) { int32_t enabled = 0; VERIFY_( _ble.atcommandIntReply( F("AT+BLEMIDIEN"), &enabled) ); if ( !enabled ) return true; VERIFY_( _ble.atcommand( F("AT+BLEMIDIEN=0") ) ); // Perform Bluefruit reset if needed if (reset) _ble.reset(); return true; } /******************************************************************************/ /*! @brief Send a MIDI event data @param bytes MIDI event data */ /******************************************************************************/ bool Adafruit_BLEMIDI::send(const uint8_t bytes[3]) { return _ble.atcommand( F("AT+BLEMIDITX"), bytes, 3); } /******************************************************************************/ /*! @brief Send multiple MIDI event which shared the same status @param status MIDI status @param bytes MIDI events data @param count number of data in bytes (must be multiple of 2) @note count + 1 must less than (20-3) --> count <= 16 */ /******************************************************************************/ bool Adafruit_BLEMIDI::send_n(uint8_t status, const uint8_t bytes[], uint8_t count) { VERIFY_(count <= 16); uint8_t data[17] = { status }; memcpy(data+1, bytes, count); return _ble.atcommand( F("AT+BLEMIDITX"), data, count+1); } /******************************************************************************/ /*! @brief @param */ /******************************************************************************/ void Adafruit_BLEMIDI::processRxCallback(uint8_t data[], uint16_t len, Adafruit_BLE::midiRxCallback_t callback_func) { if ( len < 3 ) return; // First 3 bytes is always : Header + Timestamp + Status midi_header_t header; uint16_t tstamp = 0; uint8_t status = 0; header.byte = *data++; len--; while (len) { /* event : 0x00 - 0x7F status: 0x80 - 0xEF sysex : 0xF0 - 0xFF */ if ( bitRead(data[0], 7) ) { // Start of new full event midi_timestamp_t timestamp; timestamp.byte = *data++; tstamp = (header.timestamp_hi << 7) | timestamp.timestamp_low; status = *data++; // Status must have 7th-bit set, must have something wrong if ( !bitRead(status, 7) ) return; callback_func( tstamp, status, data[0], data[1]); len -= 4; data += 2; } else { // Running event callback_func( tstamp, status, data[0], data[1]); len -= 2; data += 2; } } } ================================================ FILE: Adafruit_BLEMIDI.h ================================================ /**************************************************************************/ /*! @file Adafruit_BLEMIDI.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_BLEMIDI_H_ #define _ADAFRUIT_BLEMIDI_H_ #include #include "Adafruit_BLE.h" typedef struct ATTR_PACKED { union { struct { uint8_t timestamp_hi : 6; uint8_t reserved : 1; uint8_t start_bit : 1; }; uint8_t byte; }; } midi_header_t; ASSERT_STATIC_ ( sizeof(midi_header_t) == 1 ); typedef struct ATTR_PACKED { union { struct { uint8_t timestamp_low : 7; uint8_t start_bit : 1; }; uint8_t byte; }; } midi_timestamp_t; ASSERT_STATIC_ ( sizeof(midi_timestamp_t) == 1 ); class Adafruit_BLEMIDI { private: Adafruit_BLE& _ble; public: typedef Adafruit_BLE::midiRxCallback_t midiRxCallback_t; Adafruit_BLEMIDI(Adafruit_BLE& ble); bool begin(bool reset = true); bool stop (bool reset = true); bool send(const uint8_t bytes[3]); bool send(uint8_t status, const uint8_t bytes[2]) { uint8_t buffer[3] = { status, bytes[0], bytes[1] }; return send(buffer); } bool send(uint8_t status, uint8_t byte1, uint8_t byte2) { uint8_t buffer[3] = { status, byte1, byte2 }; return send(buffer); } bool send_n(uint8_t status, const uint8_t bytes[], uint8_t count); void setRxCallback(midiRxCallback_t fp); static void processRxCallback(uint8_t data[], uint16_t len, Adafruit_BLE::midiRxCallback_t callback_func); }; #endif /* _ADAFRUIT_BLEMIDI_H_ */ ================================================ FILE: Adafruit_BluefruitLE_SPI.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BluefruitLE_SPI.cpp @author hathach, ktown (Adafruit Industries) @section LICENSE Software License Agreement (BSD License) Copyright (c) 2015, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BluefruitLE_SPI.h" #include #include #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif SPISettings bluefruitSPI(4000000, MSBFIRST, SPI_MODE0); /******************************************************************************/ /*! @brief Instantiates a new instance of the Adafruit_BluefruitLE_SPI class @param[in] csPin The location of the CS pin for the SPI interface @param[in] irqPin The location of the HW IRQ pin (pin 2 or pin 3 on the Arduino Uno). This must be a HW interrupt pin! @param[in] rstPin */ /******************************************************************************/ Adafruit_BluefruitLE_SPI::Adafruit_BluefruitLE_SPI(int8_t csPin, int8_t irqPin, int8_t rstPin) : m_rx_fifo(m_rx_buffer, sizeof(m_rx_buffer), 1, true) { _physical_transport = BLUEFRUIT_TRANSPORT_HWSPI; m_cs_pin = csPin; m_irq_pin = irqPin; m_rst_pin = rstPin; m_miso_pin = m_mosi_pin = m_sck_pin = -1; m_tx_count = 0; m_mode_switch_command_enabled = true; } /******************************************************************************/ /*! @brief Instantiates a new instance of the Adafruit_BluefruitLE_SPI class using software SPI @param[in] clkPin The location of the SCK/clock pin for the SPI interface @param[in] misoPin The location of the MISO pin for the SPI interface @param[in] mosiPin The location of the MOSI pin for the SPI interface @param[in] csPin The location of the CS pin for the SPI interface @param[in] irqPin The location of the HW IRQ pin (pin 2 or pin 3 on the Arduino Uno). This must be a HW interrupt pin! @param[in] rstPin */ /******************************************************************************/ Adafruit_BluefruitLE_SPI::Adafruit_BluefruitLE_SPI(int8_t clkPin, int8_t misoPin, int8_t mosiPin, int8_t csPin, int8_t irqPin, int8_t rstPin) : m_rx_fifo(m_rx_buffer, sizeof(m_rx_buffer), 1, true) { _physical_transport = BLUEFRUIT_TRANSPORT_SWSPI; m_sck_pin = clkPin; m_miso_pin = misoPin; m_mosi_pin = mosiPin; m_cs_pin = csPin; m_irq_pin = irqPin; m_rst_pin = rstPin; m_tx_count = 0; m_mode_switch_command_enabled = true; } /******************************************************************************/ /*! @brief Initialize the HW to enable communication with the BLE module @return Returns 'true' if everything initialised correctly, otherwise 'false' if there was a problem during HW initialisation. If 'irqPin' is not a HW interrupt pin false will be returned. */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::begin(boolean v, boolean blocking) { _verbose = v; pinMode(m_irq_pin, INPUT); // Set CS pin to output and de-assert by default pinMode(m_cs_pin, OUTPUT); digitalWrite(m_cs_pin, HIGH); if (m_sck_pin == -1) { // hardware SPI SPI.begin(); } else { pinMode(m_sck_pin, OUTPUT); digitalWrite(m_sck_pin, LOW); pinMode(m_miso_pin, INPUT); pinMode(m_mosi_pin, OUTPUT); } bool isOK; // Always try to send Initialize command to reset // Bluefruit since user can define but not wiring RST signal isOK = sendInitializePattern(); // use hardware reset if available if (m_rst_pin >= 0) { // pull the RST to GND for 10 ms pinMode(m_rst_pin, OUTPUT); digitalWrite(m_rst_pin, HIGH); digitalWrite(m_rst_pin, LOW); delay(10); digitalWrite(m_rst_pin, HIGH); isOK= true; } _reset_started_timestamp = millis(); // Bluefruit takes 1 second to reboot if (blocking) { delay(1000); } return isOK; } /******************************************************************************/ /*! @brief Uninitializes the SPI interface */ /******************************************************************************/ void Adafruit_BluefruitLE_SPI::end(void) { if (m_sck_pin == -1) { SPI.end(); } } /******************************************************************************/ /*! @brief Handle direct "+++" input command from user. User should use setMode instead */ /******************************************************************************/ void Adafruit_BluefruitLE_SPI::simulateSwitchMode(void) { _mode = 1 - _mode; char ch = '0' + _mode; m_rx_fifo.write(&ch); m_rx_fifo.write_n("\r\nOK\r\n", 6); } /******************************************************************************/ /*! @brief Simulate "+++" switch mode command */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::setMode(uint8_t new_mode) { // invalid mode if ( !(new_mode == BLUEFRUIT_MODE_COMMAND || new_mode == BLUEFRUIT_MODE_DATA) ) return false; // Already in the wanted mode if ( _mode == new_mode ) return true; // SPI use different SDEP command when in DATA/COMMAND mode. // --> does not switch using +++ command _mode = new_mode; // If we're entering DATA mode, flush any old response, so that it isn't // interpreted as incoming UART data if (_mode == BLUEFRUIT_MODE_DATA) flush(); return true; } /******************************************************************************/ /*! @brief Enable/disable recognition of "+++" switch mode command. Usage of setMode is not affected. */ /******************************************************************************/ void Adafruit_BluefruitLE_SPI::enableModeSwitchCommand(bool enabled) { m_mode_switch_command_enabled = enabled; } /******************************************************************************/ /*! @brief Send initialize pattern to Bluefruit LE to force a reset. This pattern follow the SDEP command syntax with command_id = SDEP_CMDTYPE_INITIALIZE. The command has NO response, and is expected to complete within 1 second */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::sendInitializePattern(void) { return sendPacket(SDEP_CMDTYPE_INITIALIZE, NULL, 0, 0); } /******************************************************************************/ /*! @brief Send out an packet with data in m_tx_buffer @param[in] more_data More Data bitfield, 0 indicates this is not end of transfer yet */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::sendPacket(uint16_t command, const uint8_t* buf, uint8_t count, uint8_t more_data) { // flush old response before sending the new command, but only if we're *not* // in DATA mode, as the RX FIFO may containg incoming UART data that hasn't // been read yet if (more_data == 0 && _mode != BLUEFRUIT_MODE_DATA) flush(); sdepMsgCommand_t msgCmd; msgCmd.header.msg_type = SDEP_MSGTYPE_COMMAND; msgCmd.header.cmd_id_high = highByte(command); msgCmd.header.cmd_id_low = lowByte(command); msgCmd.header.length = count; msgCmd.header.more_data = (count == SDEP_MAX_PACKETSIZE) ? more_data : 0; // Copy payload if ( buf != NULL && count > 0) memcpy(msgCmd.payload, buf, count); // Starting SPI transaction if (m_sck_pin == -1) SPI.beginTransaction(bluefruitSPI); SPI_CS_ENABLE(); TimeoutTimer tt(_timeout); // Bluefruit may not be ready while ( ( spixfer(msgCmd.header.msg_type) == SPI_IGNORED_BYTE ) && !tt.expired() ) { // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself SPI_CS_DISABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } bool result = !tt.expired(); if ( result ) { // transfer the rest of the data spixfer((void*) (((uint8_t*)&msgCmd) +1), sizeof(sdepMsgHeader_t)+count-1); } SPI_CS_DISABLE(); if (m_sck_pin == -1) SPI.endTransaction(); return result; } /******************************************************************************/ /*! @brief Print API. Either buffer the data internally or send it to bus if possible. \r and \n are command terminators and will force the packet to be sent to the Bluefruit LE module. @param[in] c Character to send */ /******************************************************************************/ size_t Adafruit_BluefruitLE_SPI::write(uint8_t c) { if (_mode == BLUEFRUIT_MODE_DATA) { sendPacket(SDEP_CMDTYPE_BLE_UARTTX, &c, 1, 0); getResponse(); return 1; } // Following code handle BLUEFRUIT_MODE_COMMAND // Final packet due to \r or \n terminator if (c == '\r' || c == '\n') { if (m_tx_count > 0) { // +++ command to switch mode if (m_mode_switch_command_enabled && memcmp(m_tx_buffer, "+++", 3) == 0) { simulateSwitchMode(); }else { sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 0); } m_tx_count = 0; } } // More than max packet buffered --> send with more_data = 1 else if (m_tx_count == SDEP_MAX_PACKETSIZE) { sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 1); m_tx_buffer[0] = c; m_tx_count = 1; } // Not enough data, continue to buffer else { m_tx_buffer[m_tx_count++] = c; } if (_verbose) SerialDebug.print((char) c); return 1; } /******************************************************************************/ /*! */ /******************************************************************************/ size_t Adafruit_BluefruitLE_SPI::write(const uint8_t *buf, size_t size) { if ( _mode == BLUEFRUIT_MODE_DATA ) { if (m_mode_switch_command_enabled && (size >= 3) && !memcmp(buf, "+++", 3) && !(size > 3 && buf[3] != '\r' && buf[3] != '\n') ) { simulateSwitchMode(); }else { size_t remain = size; while(remain) { size_t len = min(remain, SDEP_MAX_PACKETSIZE); remain -= len; sendPacket(SDEP_CMDTYPE_BLE_UARTTX, buf, (uint8_t) len, remain ? 1 : 0); buf += len; } getResponse(); } return size; } // Command mode else { size_t n = 0; while (size--) { n += write(*buf++); } return n; } } /******************************************************************************/ /*! @brief Check if the response from the previous command is ready @return 'true' if a response is ready, otherwise 'false' */ /******************************************************************************/ int Adafruit_BluefruitLE_SPI::available(void) { if (! m_rx_fifo.empty() ) { return m_rx_fifo.count(); } if ( _mode == BLUEFRUIT_MODE_DATA ) { // DATA Mode: query for BLE UART data sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0); // Waiting to get response from Bluefruit getResponse(); return m_rx_fifo.count(); }else { return (digitalRead(m_irq_pin)); } } /******************************************************************************/ /*! @brief Get a byte from response data, perform SPI transaction if needed @return -1 if no data is available */ /******************************************************************************/ int Adafruit_BluefruitLE_SPI::read(void) { uint8_t ch; // try to grab from buffer first... if (!m_rx_fifo.empty()) { m_rx_fifo.read(&ch); return (int)ch; } if ( _mode == BLUEFRUIT_MODE_DATA ) { // DATA Mode: query for BLE UART data sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0); // Waiting to get response from Bluefruit getResponse(); }else { // COMMAND Mode: Only read data from Bluefruit if IRQ is raised if ( digitalRead(m_irq_pin) ) getResponse(); } return m_rx_fifo.read(&ch) ? ((int) ch) : EOF; } /******************************************************************************/ /*! @brief Get a byte from response without removing it, perform SPI transaction if needed @return -1 if no data is available */ /******************************************************************************/ int Adafruit_BluefruitLE_SPI::peek(void) { uint8_t ch; // try to grab from buffer first... if ( m_rx_fifo.peek(&ch) ) { return (int)ch; } if ( _mode == BLUEFRUIT_MODE_DATA ) { // DATA Mode: query for BLE UART data sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0); // Waiting to get response from Bluefruit getResponse(); }else { // Read data from Bluefruit if possible if ( digitalRead(m_irq_pin) ) getResponse(); } return m_rx_fifo.peek(&ch) ? ch : EOF; } /******************************************************************************/ /*! @brief Flush current response data in the internal FIFO @return -1 if no data is available */ /******************************************************************************/ void Adafruit_BluefruitLE_SPI::flush(void) { m_rx_fifo.clear(); } /******************************************************************************/ /*! @brief Try to perform an full AT response transfer from Bluefruit, or execute as many SPI transaction as internal FIFO can hold up. @note If verbose is enabled, all the received data will be print to Serial @return - true : if succeeded - false : if failed */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::getResponse(void) { // Try to read data from Bluefruit if there is enough room in the fifo while ( m_rx_fifo.remaining() >= SDEP_MAX_PACKETSIZE ) { // Get a SDEP packet sdepMsgResponse_t msg_response; memclr(&msg_response, sizeof(sdepMsgResponse_t)); if ( !getPacket(&msg_response) ) return false; // Write to fifo if ( msg_response.header.length > 0) { m_rx_fifo.write_n(msg_response.payload, msg_response.header.length); } // No more packet data if ( !msg_response.header.more_data ) break; // It takes a bit since all Data received to IRQ to get LOW // May need to delay a bit for it to be stable before the next try // delayMicroseconds(SPI_DEFAULT_DELAY_US); } return true; } /******************************************************************************/ /*! @brief Perform a single SPI SDEP transaction and is used by getReponse to get a full response composed of multiple packets. @param[in] buf Memory location where payload is copied to @return number of bytes in SDEP payload */ /******************************************************************************/ bool Adafruit_BluefruitLE_SPI::getPacket(sdepMsgResponse_t* p_response) { // Wait until IRQ is asserted, double timeout since some commands take long time to start responding TimeoutTimer tt(2*_timeout); while ( !digitalRead(m_irq_pin) ) { if (tt.expired()) return false; } sdepMsgHeader_t* p_header = &p_response->header; if (m_sck_pin == -1) SPI.beginTransaction(bluefruitSPI); SPI_CS_ENABLE(); tt.set(_timeout); do { if ( tt.expired() ) break; p_header->msg_type = spixfer(0xff); if (p_header->msg_type == SPI_IGNORED_BYTE) { // Bluefruit may not be ready // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself SPI_CS_DISABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } else if (p_header->msg_type == SPI_OVERREAD_BYTE) { // IRQ may not be pulled down by Bluefruit when returning all data in previous transfer. // This could happen when Arduino MCU is running at fast rate comparing to Bluefruit's MCU, // causing an SPI_OVERREAD_BYTE to be returned at stage. // // Walkaround: Disable & Re-enable CS with a bit of delay and keep waiting // TODO IRQ is supposed to be OFF then ON, it is better to use GPIO trigger interrupt. SPI_CS_DISABLE(); // wait for the clock to be enabled.. // while (!digitalRead(m_irq_pin)) { // if ( tt.expired() ) break; // } // if (!digitalRead(m_irq_pin)) break; delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } } while (p_header->msg_type == SPI_IGNORED_BYTE || p_header->msg_type == SPI_OVERREAD_BYTE); bool result=false; // Not a loop, just a way to avoid goto with error handling do { // Look for the header // note that we should always get the right header at this point, and not doing so will really mess up things. while ( p_header->msg_type != SDEP_MSGTYPE_RESPONSE && p_header->msg_type != SDEP_MSGTYPE_ERROR && !tt.expired() ) { p_header->msg_type = spixfer(0xff); } if ( tt.expired() ) break; memset( (&p_header->msg_type)+1, 0xff, sizeof(sdepMsgHeader_t) - 1); spixfer((&p_header->msg_type)+1, sizeof(sdepMsgHeader_t) - 1); // Command is 16-bit at odd address, may have alignment issue with 32-bit chip uint16_t cmd_id = word(p_header->cmd_id_high, p_header->cmd_id_low); // Error Message Response if ( p_header->msg_type == SDEP_MSGTYPE_ERROR ) break; // Invalid command if (!(cmd_id == SDEP_CMDTYPE_AT_WRAPPER || cmd_id == SDEP_CMDTYPE_BLE_UARTTX || cmd_id == SDEP_CMDTYPE_BLE_UARTRX) ) { break; } // Invalid length if(p_header->length > SDEP_MAX_PACKETSIZE) break; // read payload memset(p_response->payload, 0xff, p_header->length); spixfer(p_response->payload, p_header->length); result = true; }while(0); SPI_CS_DISABLE(); if (m_sck_pin == -1) SPI.endTransaction(); return result; } /******************************************************************************/ /*! */ /******************************************************************************/ void Adafruit_BluefruitLE_SPI::spixfer(void *buff, size_t len) { uint8_t *p = (uint8_t *)buff; while (len--) { p[0] = spixfer(p[0]); p++; } } /******************************************************************************/ /*! */ /******************************************************************************/ uint8_t Adafruit_BluefruitLE_SPI::spixfer(uint8_t x) { if (m_sck_pin == -1) { uint8_t reply = SPI.transfer(x); //SerialDebug.println(reply, HEX); return reply; } // software spi uint8_t reply = 0; for (int i=7; i>=0; i--) { reply <<= 1; digitalWrite(m_sck_pin, LOW); digitalWrite(m_mosi_pin, x & (1< #include #include "utility/Adafruit_FIFO.h" #define SPI_CS_ENABLE() digitalWrite(m_cs_pin, LOW) #define SPI_CS_DISABLE() digitalWrite(m_cs_pin, HIGH) #define SPI_IGNORED_BYTE 0xFEu /**< SPI default character. Character clocked out in case of an ignored transaction. */ #define SPI_OVERREAD_BYTE 0xFFu /**< SPI over-read character. Character clocked out after an over-read of the transmit buffer. */ #define SPI_DEFAULT_DELAY_US 50 #define memclr(buffer, size) memset(buffer, 0, size) class Adafruit_BluefruitLE_SPI : public Adafruit_BLE { private: // Hardware Pin int8_t m_cs_pin; int8_t m_irq_pin; int8_t m_rst_pin; // software SPI pins int8_t m_sck_pin; int8_t m_mosi_pin; int8_t m_miso_pin; // TX uint8_t m_tx_buffer[SDEP_MAX_PACKETSIZE]; uint8_t m_tx_count; // RX uint8_t m_rx_buffer[BLE_BUFSIZE]; Adafruit_FIFO m_rx_fifo; bool m_mode_switch_command_enabled; // Low level transportation I/O functions bool sendInitializePattern(void); bool sendPacket(uint16_t command, const uint8_t* buffer, uint8_t count, uint8_t more_data); bool getPacket(sdepMsgResponse_t* p_response); bool getResponse(void); void simulateSwitchMode(void); // bool handleSwitchCmdInDataMode(uint8_t ch); uint8_t spixfer(uint8_t x); void spixfer(void *x, size_t len); public: // Constructor Adafruit_BluefruitLE_SPI(int8_t csPin, int8_t irqPin, int8_t rstPin = -1); Adafruit_BluefruitLE_SPI(int8_t clkPin, int8_t misoPin, int8_t mosiPin, int8_t csPin, int8_t irqPin, int8_t rstPin); // HW initialisation bool begin(boolean v = false, boolean blocking = true); void end(void); bool setMode(uint8_t new_mode); void enableModeSwitchCommand(bool enabled); // Class Print virtual function Interface virtual size_t write(uint8_t c); virtual size_t write(const uint8_t *buffer, size_t size); // pull in write(str) and write(buf, size) from Print using Print::write; // Class Stream interface virtual int available(void); virtual int read(void); virtual void flush(void); virtual int peek(void); }; #endif ================================================ FILE: Adafruit_BluefruitLE_UART.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_BluefruitLE_UART.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2015, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_BluefruitLE_UART.h" /******************************************************************************/ /*! @brief Instantiates a new instance of the Adafruit_BluefruitLE_UART class */ /******************************************************************************/ Adafruit_BluefruitLE_UART::Adafruit_BluefruitLE_UART(HardwareSerial &port, int8_t mode_pin, int8_t cts_pin, int8_t rts_pin) : _mode_pin(mode_pin), _cts_pin(cts_pin), _rts_pin(rts_pin) { _physical_transport = BLUEFRUIT_TRANSPORT_HWUART; #if SOFTWARE_SERIAL_AVAILABLE ss = 0; #endif hs = &port; mySerial = &port; } #if SOFTWARE_SERIAL_AVAILABLE /******************************************************************************/ /*! @brief Instantiates a new instance of the Adafruit_BluefruitLE_UART class using software serial */ /******************************************************************************/ Adafruit_BluefruitLE_UART::Adafruit_BluefruitLE_UART(SoftwareSerial &port, int8_t mode_pin, int8_t cts_pin, int8_t rts_pin) : _mode_pin(mode_pin), _cts_pin(cts_pin), _rts_pin(rts_pin) { _physical_transport = BLUEFRUIT_TRANSPORT_SWUART; hs = 0; ss = &port; mySerial = &port; } #endif /******************************************************************************/ /*! @brief Class's Destructor */ /******************************************************************************/ Adafruit_BluefruitLE_UART::~Adafruit_BluefruitLE_UART() { end(); } /******************************************************************************/ /*! @brief Initialize the HW to enable communication with the BLE module @return Returns 'true' if everything initialised correctly, otherwise 'false' if there was a problem during HW initialisation. If 'irqPin' is not a HW interrupt pin false will be returned. */ /******************************************************************************/ bool Adafruit_BluefruitLE_UART::begin(boolean debug, boolean blocking) { _verbose = debug; _intercharwritedelay = 0; // If hardware mode pin is enabled, set it to CMD first if ( _mode_pin >= 0) { pinMode(_mode_pin, OUTPUT); digitalWrite(_mode_pin, BLUEFRUIT_MODE_COMMAND); // A bit of delay to make sure mode change take effect delay(1); } // Bluefruit baudrate is fixed to 9600 if (hs) { hs->begin(9600); #ifdef ARDUINO_STM32_FEATHER hs->enableFlowControl(); #endif } else { #if SOFTWARE_SERIAL_AVAILABLE ss->begin(9600); #endif } if (_cts_pin > 0) { pinMode(_cts_pin, OUTPUT); digitalWrite(_cts_pin, HIGH); // turn off txo } if (_rts_pin > 0) { pinMode(_rts_pin, INPUT); } mySerial->setTimeout(_timeout); // reset Bluefruit module upon connect return reset(blocking); } /******************************************************************************/ /*! @brief Uninitializes the SPI interface */ /******************************************************************************/ void Adafruit_BluefruitLE_UART::end(void) { if (hs) { hs->end(); } else { #if SOFTWARE_SERIAL_AVAILABLE ss->end(); #endif } } /******************************************************************************/ /*! @brief Set the hardware MODE Pin if it is enabled, or performs a SW based mode switch if no MODE pin is available (SPI Friend, etc.) @param[in] mode The mode to change to, either BLUEFRUIT_MODE_COMMAND or BLUEFRUIT_MODE_DATA @return true if the mode switch was successful, otherwise false */ /******************************************************************************/ bool Adafruit_BluefruitLE_UART::setMode(uint8_t new_mode) { // invalid mode if ( !(new_mode == BLUEFRUIT_MODE_COMMAND || new_mode == BLUEFRUIT_MODE_DATA) ) return false; bool isOK; if ( _mode_pin >= 0 ) { // Switch mode using hardware pin digitalWrite(_mode_pin, new_mode); delay(1); isOK = true; } else { // Switch mode using +++ command, at worst switch 2 times int32_t updated_mode; isOK = atcommandIntReply(F("+++"), &updated_mode); if ( isOK ) { // Ahhh, we are already in the wanted mode before sending +++ // Switch again. This is required to make sure it is always correct if ( updated_mode != new_mode ) { isOK = atcommandIntReply(F("+++"), &updated_mode); // Still does not match -> give up if ( updated_mode != new_mode ) return false; } } } _mode = new_mode; return isOK; } /******************************************************************************/ /*! @brief Print API. Either buffer the data internally or send it to bus if possible. \r and \n are command terminators and will force the packet to be sent to the Bluefruit LE module. @param[in] c Character to send */ /******************************************************************************/ size_t Adafruit_BluefruitLE_UART::write(uint8_t c) { // flush left-over before a new command // if (c == '\r') flush(); if (_verbose) SerialDebug.print((char) c); if (_rts_pin >= 0) { while (digitalRead(_rts_pin)) { delay(1); } } else { delay(_intercharwritedelay); } delayMicroseconds(50); return mySerial->write(c); } /******************************************************************************/ /*! @brief Check if the response from the previous command is ready @return 'true' if a response is ready, otherwise 'false' */ /******************************************************************************/ int Adafruit_BluefruitLE_UART::available(void) { if (! mySerial->available() & (_cts_pin > 0)) { // toggle flow control to get more byteses digitalWrite(_cts_pin, LOW); delay(1); digitalWrite(_cts_pin, HIGH); } return mySerial->available(); } /******************************************************************************/ /*! @brief Get a byte from response data, perform SPI transaction if needed @return -1 if no data is available */ /******************************************************************************/ int Adafruit_BluefruitLE_UART::read(void) { int c = mySerial->read(); return c; } /******************************************************************************/ /*! @brief Get a byte from response without removing it, perform SPI transaction if needed @return -1 if no data is available */ /******************************************************************************/ int Adafruit_BluefruitLE_UART::peek(void) { return mySerial->peek(); } /******************************************************************************/ /*! @brief Flush current response data in the internal FIFO @return -1 if no data is available */ /******************************************************************************/ void Adafruit_BluefruitLE_UART::flush(void) { mySerial->flush(); } ================================================ FILE: Adafruit_BluefruitLE_UART.h ================================================ /**************************************************************************/ /*! @file Adafruit_BluefruitLE_UART.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2015, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _ADAFRUIT_BLE_UART_H_ #define _ADAFRUIT_BLE_UART_H_ #include "Arduino.h" #include #define SOFTWARE_SERIAL_AVAILABLE ( ! (defined (_VARIANT_ARDUINO_DUE_X_) || defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_STM32_FEATHER)) ) #if SOFTWARE_SERIAL_AVAILABLE #include #endif class Adafruit_BluefruitLE_UART : public Adafruit_BLE { private: // Hardware Pins int8_t _mode_pin, _cts_pin, _rts_pin; Stream *mySerial; #if SOFTWARE_SERIAL_AVAILABLE SoftwareSerial *ss; #endif HardwareSerial *hs; boolean _debug; uint8_t _intercharwritedelay; public: // Software Serial Constructor (0, 1, 2, or 3 pins) Adafruit_BluefruitLE_UART(HardwareSerial &port, int8_t mode_pin = -1, int8_t cts_pin = -1, int8_t rts_pin = -1); #if SOFTWARE_SERIAL_AVAILABLE Adafruit_BluefruitLE_UART(SoftwareSerial &port, int8_t mode_pin = -1, int8_t cts_pin = -1, int8_t rts_pin = -1); #endif void setInterCharWriteDelay(uint8_t x) { _intercharwritedelay = x; }; virtual ~Adafruit_BluefruitLE_UART(); // HW initialisation bool begin(boolean debug = false, boolean blocking = true); void end(void); bool setMode(uint8_t new_mode); // Class Print virtual function Interface virtual size_t write(uint8_t c); // pull in write(str) and write(buf, size) from Print using Print::write; // Class Stream interface virtual int available(void); virtual int read(void); virtual void flush(void); virtual int peek(void); }; #endif ================================================ FILE: README.md ================================================ This library is for all nRF51 based Adafruit Bluefruit LE modules that use SPI or UART. Current nRF51 based Bluefruit LE products include: * [Bluefruit LE Friend](https://www.adafruit.com/product/2267) * [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479) * [Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633) * [Bluefruit LE Shield](https://www.adafruit.com/products/2746) * [Bluefruit LE Micro](https://www.adafruit.com/product/2661) * [Feather 32u4 Bluefruit LE](https://www.adafruit.com/product/2829) * [Feather M0 Bluefruit LE](https://www.adafruit.com/products/2995) # AT Commands The Bluefruit LE modules this library talks to use AT-style commands and responses. If you are using a UART board, the commands are sent directly as text using a SW serial transport. If your are using an SPI board, the AT commands are wrapped in a thin **[SDEP](SDEP.md)** (Simple Data Exchange Protocol) wrapper to transmit and received text data over the binary SPI transport. Details of this SPI transport layer are detailed in [SDEP.md](SDEP.md) in this same folder. # Hardware Setup There are two variants of the nRF51 Bluefruit LE modules. One uses SPI to communicate, the other uses UART with flow control (TXD, RXD, CTS, RTS). The wiring you use will depend on the module you are trying to connect. On both boards, power should be connected as shown below: Bluefruit LE | Arduino Uno -------------|------------ VIN | 5V (assuming a 5V board) GND | GND ## Software UART Pinout If you are using a UART Bluefruit LE board, your Arduino should be connected to the Bluefruit LE UART module using the following pinout: Bluefruit LE UART | Arduino Uno ------------------|------------ RTS | 8 RXI | 9 TXO | 10 CTS | 11 Optional Pins Bluefruit LE UART | Arduino Uno ------------------|------------ MODE | 12 ## SPI Pinout If you are using an SPI Bluefruit LE board, your Arduino should be connected to the Bluefruit LE SPI module using the following pinout: Bluefruit LE SPI | Arduino Uno -----------------|------------ SCLK | 13 MISO | 12 MOSI | 11 CS | 8 IRQ | 7 Optional Pins (enable these in the sample sketches) Bluefruit LE SPI | Arduino Uno -----------------|------------ RESET | 6 ================================================ FILE: SDEP.md ================================================ # SPI AT Command Transport Layer (SDEP) This library transmits AT-style commands to the Bluefruit LE module over SPI using a custom protocol we've defined called SDEP, which stands for the **_Simple Data Exchange Protocol_**. SDEP is used to handle messages and responses, including error responses, and was designed to be _bus neutral_, meaning that we can use SDEP regardless of the transport mechanism (USB HID, SPI, I2C, Wireless data over the air, etc.). SDEP messages have a four byte header, and up to a 16 byte payload, and larger messages are broken into several message chunks which are rebuilt at either end of the transport bus. The 20 byte limit (4 byte header + 16 byte payload) was chosen to take into account the size limitations present in some transport layers. # SPI Setup The SPI interface uses the standard four SPI pins (MISO, MOSI, SCK and CS/SSEL), as well as an additional **IRQ** line (output from the nRF51822 to the SPI Master MCU). ## IRQ Pin The IRQ line is asserted as long as an entire SDEP packet is available in the buffer on the nRF51822, at which point you should read the packet, keeping the CS line asserted for the entire transaction (as detailed below). The IRQ line will remain asserted as long as one or more packets are available, so the line may stay high after reading a packet, meaning that more packets are still available in the FIFO on the SPI slave side. ## SPI Bus Hardware Requirements The SPI peripheral block on the nRF51822 MCU has some specific limitations that need to be taken into account when communicating with it as an SPI slave: * The SPI clock should run <=2MHz * A 100us delay should be added between the moment that the CS line is asserted, and before any data is transmitted on the SPI bus * The CS line should remain asserted for the entire packet, rather than toggling CS every byte ## SDEP Packet and SPI Error Identifier Once CS has been asserted and the mandatory 100us delay has passed, a single byte should be read from the SPI bus which will indicate the type of payload available on the nRF51822 (see **Message Type Indicator** below for more information on SDEP message types). Keep CS asserted after this byte has been read in case you need to continue reading the rest of the frame. If a standard SDEP message type indicators (0x10, 0x20, 0x40 or 0x80) is encountered, keep reading as normal. There are two other indicators that should be taken into account, though, which indicate a problem on the nRF51822 SPI slave side: * **0xFE**: Slave device not ready (wait a bit and try again) * **0xFF**: Slave device read overflow indicator (you've read more data than is available) ## Sample Transaction The following image shows a sample SDEP response that is spread over two packets (since the response is > 20 bytes in size). Notice that the IRQ line stays asserted between the packets since more than one was available in the FIFO on the nRF51822 side: ![sdepexample_twopackets](https://cloud.githubusercontent.com/assets/181073/8234310/646b7498-15db-11e5-9c69-6366c5dd433a.png) # SDEP (Simple Data Exchange Protocol) The Simple Data Exchange Protocol (SDEP) can be used to send and receive binary messages between two connected devices using any binary serial bus (USB HID, USB Bulk, SPI, I2C, Wireless, etc.), exchanging data using one of four distinct message types (Command, Response, Alert and Error messages). The protocol is designed to be flexible and extensible, with the only requirement being that **individual messages are 20 bytes or smaller**, and that the first byte of every message is a one byte (U8) identifier that indicates the message type, which defines the format for the remainder of the payload. ## Endianness All values larger than 8-bits are encoded in little endian format. Any deviation from this rule should be clearly documented. ## Message Type Indicator The first byte of every message is an 8-bit identifier called the **Message Type Indicator**. This value indicates the type of message being sent, and allows us to determine the format for the remainder of the message. | Message Type | ID (U8) | Description | | ------------ | ------- | ----------- | | Command | 0x10 | | | Response | 0x20 | | | Alert | 0x40 | | | Error | 0x80 | | ## SDEP Data Transactions Either connected device can initiate SDEP transactions, though certain transport protocols imposes restrictions on who can initiate a transfer. The _master_ device, for example, always initiates transactions with Bluetooth Low Energy or USB, meaning that _slave_ devices can only reply to incoming commands. Every device that receives a _Command Message_ must reply with a _Response Message_, _Error Message_ or _Alert message_. The following diagram illustrates how an SDEP exchange typically takes place. A Command Message is sent, and a reply will be generated based on whether the command was accepted (in which case a Response Message will be sent in reply), if the command was invalid or rejected (in which case an Error Message reply will be sent), or if the command was valid but some specific condition occurred that should be indicated to the master device (in which case an Alert Message will be sent): **ToDo: Insert two line master/slave chart showing message flow in different scenarios** ## Message Types ### Command Messages Command messages (Message Type = 0x10) have the following structure: | Name | Type | Meaning | | --------------- | ---- | ------------------------------------------------- | | Message Type | U8 | Always '0x10' | | Command ID | U16 | Unique command identifier | | Payload Length | U8 | [7] More data
[6-5] Reserved
[4-0] Payload length (0..16) | | Payload | ... | Optional command payload (parameters, etc.) | **Command ID** (bytes 1-2) and **Payload Length** (byte 3) are mandatory in any command message. The message payload is optional, and will be ignored if Payload Length is set to 0 bytes. When a message payload is present, it’s length can be anywhere from 1..16 bytes, to stay within the 20-byte maximum message length. A long command (>16 bytes payload) must be divided into multiple packets. To facilitate this, the **More data** field (bit 7 of byte 3) is used to indicate whether additional packets are available for the same command. The SDEP receiver must continue to reads packets until it finds a packet with **More data == 0**, then assemble all sub-packets into one command if necessary. The contents of the payload are user defined, and can change from one command to another. A sample command message would be: | 0: Message Type (U8) | 1+2: Command ID (U16) | 3: Payload Len (U8) | 4: Payload (...) | | -------------------- | --------------------- | ------------------- | ---------------- | | 10 | 34 12 | 01 | FF | - The first byte is the Message Type (0x10), which identifies this as a command message. - The second and third bytes are 0x1234 (34 12 in little-endian notation), which is the unique command ID. This value will be compared against the command lookup table and redirected to an appropriate command handler function if a matching entry was found. - The fourth byte indicates that we have a message payload of 1 byte - The fifth byte is the 1 byte payload: 0xFF ### Response Messages Response messages (Message Type = 0x20) are generated in response to an incoming command, and have the following structure: | Name | Type | Meaning | | --------------- | ---- | ------------------------------------------------- | | Message Type | U8 | Always '0x20' | | Command ID | U16 | Command ID of the command this message is a response to, to correlated responses and commands | | Payload Length | U8 | [7] More data
[6-5] Reserved
[4-0] Payload length (0..16) | | Payload | ... | Optional response payload (parameters, etc.) | By including the **Command ID** that this response message is related to, the recipient can more easily correlate responses and commands. This is useful in situations where multiple commands are sent, and some commands may take a longer period of time to execute than subsequent commands with a different command ID. Response messages can only be generate in response to a command message, so the Command ID field should always be present. A long response (>16 bytes payload) must be divided into multiple packets. Similar to long commands, the **More data** field (bit 7 of byte 3) is used to indicate whether additional packets are available for the same response. On responses that span more than one packet, the **More data** bit on the final packet will be set to `0` to indicate that this is the last packet in the sequence. The SDEP receiver must re-assemble all sub-packets in into one payload when necessary. If more precise command/response correlation is required a custom protocol should be developed, where a unique message identifier is included in the payload of each command/response, but this is beyond the scope of this high-level protocol definition. A sample response message would be: | 0: Message Type (U8) | 1+2: Command ID (U16) | 3: Payload Len (U8) | 4: Payload (...) | | -------------------- | --------------------- | ------------------- | ---------------- | | 20 | 34 12 | 01 | FF | - The first byte is the Message Type (0x20), which identifies this as a response message. - The second and third bytes are 0x1234, which is the unique command ID that this response is related to. - The fourth byte indicates that we have a message payload of 1 byte. - The fifth byte is the 1 byte payload: 0xFF ### Alert Messages Alert messages (Message Type = 0x40) are sent whenever an alert condition is present on the system (low battery, etc.), and have the following structure: | Name | Type | Meaning | | --------------- | ---- | ------------------------------------------------- | | Message Type | U8 | Always '0x40' | | Alert ID | U16 | Unique ID for the alert condition | | Payload Length | U8 | Payload length (0..16) | | Payload | ... | Optional response payload (parameters, etc.) | A sample alert message would be: | 0: Message Type (U8) | 1+2: Alert ID (U16) | 3: Payload Len (U8) | 4+5+6+7: Payload | | -------------------- | --------------------- | ------------------- | ----------------- | | 40 | CD AB | 04 | 42 07 00 10 | - The first byte is the Message Type (0x40), which identifies this as an alert message. - The second and third bytes are 0xABCD, which is the unique alert ID. - The fourth byte indicates that we have a message payload of 4 bytes. - The last four bytes are the actual payload: `0x10000742` in this case, assuming we were transmitting a 32-bit value in little-endian format. #### Standard Alert IDs Alert IDs in the range of 0x0000 to 0x00FF are reserved for standard SDEP alerts, and may not be used by custom alerts. The following alerts have been defined as a standard part of the protocol: | ID | Alert Description | Description | | ------ | ----------------- | ------------------------------------ | | 0x0000 | Reserved | Reserved for future use | | 0x0001 | System Reset | The system is about the reset | | 0x0002 | Battery Low | The battery level is low | | 0x0003 | Battery Critical | The battery level is critically low | ### Error Messages Error messages (Message Type = 0x80) are returned whenever an error condition is present on the system, and have the following structure: | Name | Type | Meaning | | --------------- | ---- | ------------------------------------------------- | | Message Type | U8 | Always '0x80' | | Error ID | U16 | Unique ID for the error condition | | Reserved | U8 | Reserved for future use | Whenever an error condition is present and the system needs to be alerted (such as a failed request, an attempt to access a non-existing resource, etc.) the system can return a specific error message with an appropriate Error ID. A sample error message would be: | 0: Message Type (U8) | 1+2: Error ID (U16) | 3: Reserved (U8) | | -------------------- | --------------------- | ---------------- | | 80 | 01 00 | 00 | - The first byte is the Message Type (0x80), which identifies this as an error message. - The second and third bytes are 0x0001 (01 00 in little-endian notation), which indicates that the supplied Command ID was invalid (see Standard Error IDs below). - The last byte is reserved and should be 0x00 and ignored. #### Standard Error IDs Error IDs in the range of 0x0000 to 0x00FF are reserved for standard SDEP errors, and may not be used by custom errors. The following errors have been defined as a standard part of the protocol: | ID | Error Description | Description | | ------ | ----------------- | ----------------------------------------------- | | 0x0000 | Reserved | Reserved for future use | | 0x0001 | Invalid Cmd ID | The command ID wasn't found in the lookup table | | 0x0003 | Invalid Payload | The message payload was invalid | ================================================ FILE: changelog.md ================================================ # Arduino Changelog ## 1.10 - Add non-blokcing option for .reset(blocking) & .factoryReset(blocking). The reset progress can be polled by .resetCompleted() - Add callback using dfu as irq pin example, .handleDfuIrq() is expected to be call in loop() ## 1.9 ### Features - Added **Adafruit_ATParser** helper class to facilitate sending and receiving AT commands: - `.atcommand()` : Send a command without reply (several variants defined for various input parameters) - `.atcommandIntReply()` : Send a command with integer reply (several variants defined for various input parameters) - `.atcommand_full()` : General purpose command execution with a pointer to the reply buffer - `.printByteArray()` : Outputs a byte array in the `AA-BB-CC` format from a buffer. Useful for executing AT commands. - `.waitForOK()` : Uses a separate temporary buffer to avoid overwriting response content. - Callback support in **Adafruit_BLE** class - Supported Events are: - **Connect**: Set using `setConnectCallback()` - **Disconnect**: Set using `setDisconnectCallback()` - **BLE UART RX**: Set using `.setBleUartRxCallback()` - **MIDI RX**: Set using `.setBleMidiRxCallback()` - **GATT Characteristic RX**: Set using `.setBleGattRxCallback()` - `.update(ms)` must be placed in the loop() function to fire the callbacks, where `ms` is the interval in milliseconds to poll for new events - See 'examples/callbacks' for more details - Added **Adafruit_BLEGatt** helper class to make working with custom GATT services and characteristics easier: - Helpers to add custom GATT services and characteristics - Helpers to read/write previously defined characteristics - Callback support for characteristic updates - Added **User Description** and **Presentation Format** support for GATT characteristics - Add `BLEDataType_t` typedef for GATT characteristics - See 'example/healththermometer' for an example of using the Adafruit_BLEGatt class - Added BLE MIDI service support with the **Adafruit_BLEMIDI** class - See 'examples/midi' for details - Added BLE Battery service support via the **Adafruit_BLEBattery** class - See 'example/battery' for more details - Added BLE Eddystone helper class to facilitate using Eddystone beacon - See 'example/eddystone' for more details - Add a 256 byte user NVM data section that can be accessed via `.writeNVM()` and `.readNVM()` in **Adafruit_BLE**. User can use this small chunk of NVM memory to store application specific data. - See 'example/nvmdata' for more details - Additional **Adafruit_BLE** class changes: - Added a `setAdvData()` helper to advertise custom data payloads ================================================ FILE: changelog_firmware.md ================================================ # Firmware Changelog ## 0.8.0 - improve stability of nvm ## 0.7.7 ### Features - Add `AT+BLEUARTTXF` (F for force) to immediately send data as it is in an BLE Packet - Adjust bleuart sending interval based on min connection interval - Add `AT+DFUIRQ` to enable using DFU Pin for IRQ purpose when there is new events from nrf51 - Enable CS pull up for Bluefruit SPI - Add `AT+MODESWITCHEN` to enable/disable +++ mode switch from local (serial/spi) or bleuart. Default local = enabled, ble = disable. Command can only be executed via local interface. - Implement '\+' escape to immediate send '+' without trigger +++ waiting - Add `AT+BLEHIDGAMEPADEN` to separately enable HID Gamepad, since iOS/OSX conflict with gamepad device that cause the HID keyboard not working properly. ### Bug fixes - fix factory reset after a long time no reset in app_error_handler() - fix Strings truncated at 64 chars in UART - fix HID keyboard does not work with iOS 9 & 10 ## 0.7.0 ### Features - BTLE UART speed and stability improvements - HW UART - `AT+Baudrate` to change HW UART baud rate - `AT+uartflow` to enable/disable HW UART flow control - MIDI (work in progress) - `AT+BLEMIDIEN=on/off/0/1` to enable/disable MIDI service, requires a reset to take affect - `AT+BLEMIDITX=midi event` to send MIDI event(s) - `AT+BLEMIDIRX` to receive MIDI event(s) - GATT server - Added `DATATYPE` option to `AT+GATTADDCHAR`. Valid options are : AUTO (0, default), STRING (1), BYTEARRAY (2), INTEGER (3) - Added `AT+GATTCHARRAW` (read-only) to read binary data (instead of ascii) from a characteristic. It is non-printable but has less overhead and is easier to use when writing libraries for Arduino. - Reworked memory management for Service & Characteristics in NVM - Increased MAX_LEN for each characteristic from 20 to 32 bytes - Added Characteristic User Description support via the `DESCRIPTION` flag - Added Characteristic Presentation Format support via the `PRESENTATION` flag - NVM user data allowing users to store data in a dedicated NVM section (up to 256 bytes) - `AT+NVMWRITE=offset,datatype,data` where datatype must be STRING (1), BYTEARRAY (2), or INTEGER (3) - `AT+NVMREAD=offset,size,datatype` to read data back - `AT+NVMREADRAW=offset,size` binary data (instead of ascii) is returned ended with OK\r\n. It is non-printable but less overhead and easier to use when writing libraries in Arduino. - Simple callback implementation (work in progress) - BLTE UART rx - GATT chars rx - MIDI rx - Connect/Disconnect - HID Service: - Added pre-defined consumer "EJECT" which can be used to hide/show keyboard layout on iOS - Added HID Gamepad `at+blehidgamepad=x,y.buttons` where - X corresponds to LEFT, RIGHT: X=-1 means LEFT is pressed, X=1 means RIGHT is pressed, X=0 nothing pressed - Y corresponds to UP, DOWN: Y=-1 means UP, Y=1 means DOWN, Y=0 nothing pressed - Button [0x00-0xFF] is a bit mask for 8 buttons, 0-7 - GAP: changed default parameters - ADV interval = 20 ms - Min connection interval = 20 ms - Max connection interval = 40 ms - Added `AT+GAPCONNECTABLE=on/off/1/0` to allow/disallow connection to device. - Added LOW Power Adv Interval to `AT+GAPINTERVALS=min_conn,max_conn,adv_interval,adv_timeout,adv_lowpower_interval`, default is 417.5 ms - Increased maximum number of CCCD records saved to flash from 8 to 16 - EddyStone Service - Eddystone config service disabled by default - Removed AT+EDDYSTONEENABLE to avoid confusion due to name (use AT+EDDYSTONESERVICEEN) - Added AT+EDDYSTONESERVICEEN to add/remove EddyStone service to GATT table (requires a reset) - Added AT+EDDYSTONEBROADCAST=on/off/0/1 to start/stop broadcasting url using nvm saved setting - Changed adv timeout for Eddystone to unlimited - Battery Service - Added `AT+BLEBATTEN=on/off/1/0` to enable Battery service. Reset required. - Added `AT+BLEBATTVAL=percent` to update the Battery level, percent is 0 to 100 ### Bug Fixes - Fixed a bug where 'Write-No-Response' characteristic properties weren't being handled properly - Fixed timing constraints to meet Apple design guidelines - Corrected systick to ms calculation, optimized 64bit division by using shifter - Fixed all the tests with google Eddystone validator except for writing tx_power = 1 dB (not valid on nrf51) - Fixed a big where writing from a central does not update value on characteristic correctly - Fixed an issue with HID examples, where when paired with a central, a disconnect then reconnect meant you could not send reports anymore. ## 0.6.7 ### Features - EddyStone/Uribeacon - Add TX Power to AT+EddyStoneUrl: `AT+EDDYSTONEURL=URL,[ADVWHENCONNECTED=0],[RSSI@0M=-18]` - Enable reading the current url: `AT+EDDYSTONEURL` - Increase FIFO size for - AT command fifo from 160 to 256 byte - BLE UART TX fifo from 160 to 1024 bytes - SPI RX fifo from 160 to 1024 bytes - Add command to return free FIFO size for BLE UART: AT+BLEUARTFIFO 0,1024 AT+BLEUARTFIFO=TX 0 AT+BLEUARTFIFO=RX 1024 - Keep URI UUID - AT+BLEURIBEACON will use the legacy uuid 0xFED8 - AT+EDDYSTONEURL will use the eddystone uuid 0xFEAA - Add escape '\' when sending A SINGLE '?' due to conflict with AT command existence test mode - AT+BLEUARTTX=\? - AT+BLEKEYBOARD=\? ### Bug Fixes - Fix and improve BLE UART TX fifo overflow, wait up to 200 ms for fifo to free up some spaces, return ERROR if timed out. Note: a single BLE UART TX command can have ~200 bytes, the command may need to wait several turns (each is 200ms timeout), thus the total timeout can be longer depending on the FIFO state and the sending rate from the Central/Host device. Arudino's library has its own timer and can be timeout before the sending is done !!!!! - Fix the factory reset issue if the Bluefruit is running for a long time (> 4 hours). - fix a problem with gatt server: incorrect value_len parsing for characteristics's integer with max_len >4 ## 0.6.6 ### Features - Added basic [Eddystone](https://github.com/google/eddystone) support (currently [URL mode](https://github.com/google/eddystone/tree/master/eddystone-url) only): - AT+EDDYSTONEURL : Update the url for the beacon and go to beacon mode - AT+EDDYSTONEENABLE : Enable/disable beacon mode using the configured url - AT+EDDYSTONECONFIGEN : Enable the Eddystone configuration service - AT+HWMODELED enhancements. The MODE LED can now be set to: - DISABLE - No LED activity (to save power) - UART/DATA Mode - Indicate current operating mode (command or DATA) - DEFAULT - HWUART - LED toggles on HW UART activity - BLEUART - LED toggles on nRF/BLE UART activity (the Nordic UART Service) - SPI - LED toggles on SPI activity - MANUAL - Allows manual control of the LED via a second ON/OFF/TOGGLE parameter - Added HID Keyboard Consumer Control support via AT+BLECONTROLKEY - Added HID mouse support: - AT+BLEHIDEN=on/off/0/1 added to enable all HID devices (including keyboard & mouse). - AT+BLEKEYBOARDEN is now an alias to AT+BLEHIDEN - AT+BLEMOUSEMOVE to move the cursor (does not affect mouse buttons) - AT+BLEMOUSEBUTTON to perform button actions - Added `uuid128` option for AT+GATTADDCHAR: Custom characteristics can now have a different UUID base than the parent service UUID. - Lower requirement of at+blekeyboardcode to minimum 1 parameter instead of 2 ### Bug Fixes - Fixed #156 UriBeacon Resets After n Hours - Fixed issues with long beacon URLs, e.g at+bleuribeacon=http://www.adafruit.com/012345678 - Fixed big endian issue in at+blebeacon for major & minor number ### Known Issues - It seems Windows 10 has a limited number of characteristics for DIS service. We had to disable the Serial Number characteristic to enable HID support with windows 10. ## 0.6.5 * **AT Parser**: Fixed https://github.com/adafruit/Adafruit_BluefruitLE_nRF51/issues/2 (When resetting, dynamic GATT characteristics always use min_len when repopulating char values, not the actual value length.) * **SDEP/SPIS**: rework SPI slave communication implementation to increase performance and stability. ================================================ FILE: examples/atcommand/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 160 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/atcommand/atcommand.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS ? ? FACTORYRESET_ENABLE? ? Perform a factory reset when running this sketch ? ? ? ? Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so ? ? running this at least once is a good idea. ? ? ? ? When deploying your project, however, you will want to disable factory reset by setting this value to 0.? If you are making changes to your ? ? Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.? Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values. ? ? ? ? ? ? Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit AT Command Example")); Serial.println(F("-------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Display command prompt Serial.print(F("AT > ")); // Check for user input and echo it back if anything was found char command[BUFSIZE+1]; getUserInput(command, BUFSIZE); // Send command ble.println(command); // Check response status ble.waitForOK(); } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/battery/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/battery/battery.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "Adafruit_BLEBattery.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); Adafruit_BLEBattery battery(ble); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } int value = 100; /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit AT Command Example")); Serial.println(F("-------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // Enable Battery service and reset Bluefruit battery.begin(true); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Should get Battery value from LIPO and update Serial.print("Update battery level = "); Serial.println(value); battery.update(value); value--; if (value == 0) value = 100; delay(5000); } ================================================ FILE: examples/beacon/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/beacon/beacon.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. BEACON_MANUFACTURER_ID Company Identifier assigned by Bluetooth SIG Full list of Manufacturer ID can be found here https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers BEACON_UUID 16-bytes UUID in hex format AA-BB-... BEACON_MAJOR 16-bit major nunber BEACON_MINOR 16-bit minor nunber BEACON_RSSI_1M -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MANUFACTURER_APPLE "0x004C" #define MANUFACTURER_NORDIC "0x0059" #define BEACON_MANUFACTURER_ID MANUFACTURER_APPLE #define BEACON_UUID "01-12-23-34-45-56-67-78-89-9A-AB-BC-CD-DE-EF-F0" #define BEACON_MAJOR "0x0000" #define BEACON_MINOR "0x0000" #define BEACON_RSSI_1M "-54" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Beacon Example")); Serial.println(F("---------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); Serial.println(F("Setting beacon configuration details: ")); // AT+BLEBEACON=0x004C,01-12-23-34-45-56-67-78-89-9A-AB-BC-CD-DE-EF-F0,0x0000,0x0000,-54 ble.print("AT+BLEBEACON=" ); ble.print(BEACON_MANUFACTURER_ID ); ble.print(','); ble.print(BEACON_UUID ); ble.print(','); ble.print(BEACON_MAJOR ); ble.print(','); ble.print(BEACON_MINOR ); ble.print(','); ble.print(BEACON_RSSI_1M ); ble.println(); // print line causes the command to execute // check response status if (! ble.waitForOK() ) { error(F("Didn't get the OK")); } Serial.println(); Serial.println(F("Open your beacon app to test")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { } ================================================ FILE: examples/bleuart_cmdmode/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/bleuart_cmdmode/bleuart_cmdmode.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features MODE_LED_BEHAVIOUR LED activity, valid options are "DISABLE" or "MODE" or "BLEUART" or "HWUART" or "SPI" or "MANUAL" -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.6.6" #define MODE_LED_BEHAVIOUR "MODE" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(Serial1, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Command Mode Example")); Serial.println(F("---------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); Serial.println(F("Please use Adafruit Bluefruit LE app to connect in UART mode")); Serial.println(F("Then Enter characters to send to Bluefruit")); Serial.println(); ble.verbose(false); // debug info is a little annoying after this point! /* Wait for connection */ while (! ble.isConnected()) { delay(500); } // LED Activity command is only supported from 0.6.6 if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { // Change Mode LED Activity Serial.println(F("******************************")); Serial.println(F("Change LED activity to " MODE_LED_BEHAVIOUR)); ble.sendCommandCheckOK("AT+HWModeLED=" MODE_LED_BEHAVIOUR); Serial.println(F("******************************")); } } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Check for user input char inputs[BUFSIZE+1]; if ( getUserInput(inputs, BUFSIZE) ) { // Send characters to Bluefruit Serial.print("[Send] "); Serial.println(inputs); ble.print("AT+BLEUARTTX="); ble.println(inputs); // check response stastus if (! ble.waitForOK() ) { Serial.println(F("Failed to send?")); } } // Check for incoming characters from Bluefruit ble.println("AT+BLEUARTRX"); ble.readline(); if (strcmp(ble.buffer, "OK") == 0) { // no data return; } // Some data was found, its in the buffer Serial.print(F("[Recv] ")); Serial.println(ble.buffer); ble.waitForOK(); } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ bool getUserInput(char buffer[], uint8_t maxSize) { // timeout in 100 milliseconds TimeoutTimer timeout(100); memset(buffer, 0, maxSize); while( (!Serial.available()) && !timeout.expired() ) { delay(1); } if ( timeout.expired() ) return false; delay(2); uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && (Serial.available()) ); return true; } ================================================ FILE: examples/bleuart_datamode/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/bleuart_datamode/bleuart_datamode.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features MODE_LED_BEHAVIOUR LED activity, valid options are "DISABLE" or "MODE" or "BLEUART" or "HWUART" or "SPI" or "MANUAL" -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.6.6" #define MODE_LED_BEHAVIOUR "MODE" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Command <-> Data Mode Example")); Serial.println(F("------------------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); Serial.println(F("Please use Adafruit Bluefruit LE app to connect in UART mode")); Serial.println(F("Then Enter characters to send to Bluefruit")); Serial.println(); ble.verbose(false); // debug info is a little annoying after this point! /* Wait for connection */ while (! ble.isConnected()) { delay(500); } Serial.println(F("******************************")); // LED Activity command is only supported from 0.6.6 if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { // Change Mode LED Activity Serial.println(F("Change LED activity to " MODE_LED_BEHAVIOUR)); ble.sendCommandCheckOK("AT+HWModeLED=" MODE_LED_BEHAVIOUR); } // Set module to DATA mode Serial.println( F("Switching to DATA mode!") ); ble.setMode(BLUEFRUIT_MODE_DATA); Serial.println(F("******************************")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Check for user input char n, inputs[BUFSIZE+1]; if (Serial.available()) { n = Serial.readBytes(inputs, BUFSIZE); inputs[n] = 0; // Send characters to Bluefruit Serial.print("Sending: "); Serial.println(inputs); // Send input data to host via Bluefruit ble.print(inputs); } // Echo received data while ( ble.available() ) { int c = ble.read(); Serial.print((char)c); // Hex output too, helps w/debugging! Serial.print(" [0x"); if (c <= 0xF) Serial.print(F("0")); Serial.print(c, HEX); Serial.print("] "); } } ================================================ FILE: examples/callbacks/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 6 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/callbacks/callbacks.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /* This example demonstrates how to use Bluefruit callback API : * - setConnectCallback(), setDisconnectCallback(), setBleUartRxCallback(), * setBleGattRxCallback() are used to install callback function for specific * event. * - Furthermore, update() must be called inside loop() for callback to * be executed. * * The sketch will add an custom service with 2 writable characteristics, * and install callback to execute when there is an update from central device * - one hold string * - one hold a 4-byte integer */ /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.7.0" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); int32_t charid_string; int32_t charid_number; // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } void connected(void) { Serial.println( F("Connected") ); } void disconnected(void) { Serial.println( F("Disconnected") ); } void BleUartRX(char data[], uint16_t len) { Serial.print( F("[BLE UART RX]" ) ); Serial.write(data, len); Serial.println(); } void BleGattRX(int32_t chars_id, uint8_t data[], uint16_t len) { Serial.print( F("[BLE GATT RX] (" ) ); Serial.print(chars_id); Serial.print(") "); if (chars_id == charid_string) { Serial.write(data, len); Serial.println(); }else if (chars_id == charid_number) { int32_t val; memcpy(&val, data, len); Serial.println(val); } } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Callbacks Example")); Serial.println(F("-------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { error( F("Callback requires at least 0.7.0") ); } Serial.println( F("Adding Service 0x1234 with 2 chars 0x2345 & 0x6789") ); ble.sendCommandCheckOK( F("AT+GATTADDSERVICE=uuid=0x1234") ); ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2345,PROPERTIES=0x08,MIN_LEN=1,MAX_LEN=6,DATATYPE=string,DESCRIPTION=string,VALUE=abc"), &charid_string); ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x6789,PROPERTIES=0x08,MIN_LEN=4,MAX_LEN=4,DATATYPE=INTEGER,DESCRIPTION=number,VALUE=0"), &charid_number); ble.reset(); /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); /* Set callbacks */ ble.setConnectCallback(connected); ble.setDisconnectCallback(disconnected); ble.setBleUartRxCallback(BleUartRX); /* Only one BLE GATT function should be set, it is possible to set it multiple times for multiple Chars ID */ ble.setBleGattRxCallback(charid_string, BleGattRX); ble.setBleGattRxCallback(charid_number, BleGattRX); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { ble.update(200); } ================================================ FILE: examples/callbacks_dfuirq/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 6 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/callbacks_dfuirq/callbacks_dfuirq.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "Adafruit_BLEGatt.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /* This example demonstrates how to use Bluefruit callback API : - setConnectCallback(), setDisconnectCallback(), setBleUartRxCallback(), setBleGattRxCallback() are used to install callback function for specific event. - Furthermore, update() must be called inside loop() for callback to be executed. The sketch will add an custom service with 2 writable characteristics, and install callback to execute when there is an update from central device - one hold string - one hold a 4-byte integer */ /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.7.1" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); Adafruit_BLEGatt gatt(ble); int32_t charid_string; int32_t charid_number; // Wire DFU pin to interruptable pin int irq_pin = 1; // use boolean variable to signal loop() to call ble.update() // You could call ble.update() is ISR but it will increase ISR lattency volatile boolean irq_event_available = false; // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } void connected(void) { Serial.println( F("Connected") ); } void disconnected(void) { Serial.println( F("Disconnected") ); } void BleUartRX(char data[], uint16_t len) { Serial.print( F("[BLE UART RX]" ) ); Serial.write(data, len); Serial.println(); } void BleGattRX(int32_t chars_id, uint8_t data[], uint16_t len) { Serial.print( F("[BLE GATT RX] (" ) ); Serial.print(chars_id); Serial.print(") "); if (chars_id == charid_string) { Serial.write(data, len); Serial.println(); } else if (chars_id == charid_number) { int32_t val; memcpy(&val, data, len); Serial.println(val); } } void DfuIrqHandle(void) { // signal loop() to handle event irq_event_available = true; } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Callback with DFU IRQ Example")); Serial.println(F("-------------------------------------")); pinMode(irq_pin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(irq_pin), DfuIrqHandle, FALLING); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ) { error(F("Couldn't factory reset")); } } if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { error( F("Callback with DFU Pin as IRQ requires at least 0.7.1") ); } Serial.println( F("Adding Service 0x1234 with 2 chars 0x2345 & 0x6789") ); gatt.addService(0x1234); charid_string = gatt.addCharacteristic(0x2345, GATT_CHARS_PROPERTIES_WRITE, 1, 6, BLE_DATATYPE_STRING, "string"); charid_number = gatt.addCharacteristic(0x6789, GATT_CHARS_PROPERTIES_WRITE, 4, 4, BLE_DATATYPE_INTEGER, "number"); /* Reset the device for the new service setting changes to take effect */ Serial.print(F("Performing a SW reset (service changes require a reset): ")); ble.reset(); /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); /* Change DFU Pin to IRQ mode */ Serial.println( F("Change DFU Pin to IRQ Mode") ); ble.sendCommandCheckOK( F("AT+DFUIRQ=on") ); /* Set callbacks */ ble.setConnectCallback(connected); ble.setDisconnectCallback(disconnected); ble.setBleUartRxCallback(BleUartRX); /* Only one BLE GATT function should be set, it is possible to set it multiple times for multiple Chars ID */ ble.setBleGattRxCallback(charid_string, BleGattRX); ble.setBleGattRxCallback(charid_number, BleGattRX); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { if (irq_event_available) { // Registered callbacks for the event will be fired accordingly ble.handleDfuIrq(); } } ================================================ FILE: examples/controller/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output #define BLE_READPACKET_TIMEOUT 500 // Timeout in ms waiting to read a response // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/controller/controller.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features MODE_LED_BEHAVIOUR LED activity, valid options are "DISABLE" or "MODE" or "BLEUART" or "HWUART" or "SPI" or "MANUAL" -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.6.6" #define MODE_LED_BEHAVIOUR "MODE" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } // function prototypes over in packetparser.cpp uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout); float parsefloat(uint8_t *buffer); void printHex(const uint8_t * data, const uint32_t numBytes); // the packet buffer extern uint8_t packetbuffer[]; /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit App Controller Example")); Serial.println(F("-----------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode")); Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!")); Serial.println(); ble.verbose(false); // debug info is a little annoying after this point! /* Wait for connection */ while (! ble.isConnected()) { delay(500); } Serial.println(F("******************************")); // LED Activity command is only supported from 0.6.6 if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { // Change Mode LED Activity Serial.println(F("Change LED activity to " MODE_LED_BEHAVIOUR)); ble.sendCommandCheckOK("AT+HWModeLED=" MODE_LED_BEHAVIOUR); } // Set Bluefruit to DATA mode Serial.println( F("Switching to DATA mode!") ); ble.setMode(BLUEFRUIT_MODE_DATA); Serial.println(F("******************************")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { /* Wait for new data to arrive */ uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT); if (len == 0) return; /* Got a packet! */ // printHex(packetbuffer, len); // Color if (packetbuffer[1] == 'C') { uint8_t red = packetbuffer[2]; uint8_t green = packetbuffer[3]; uint8_t blue = packetbuffer[4]; Serial.print ("RGB #"); if (red < 0x10) Serial.print("0"); Serial.print(red, HEX); if (green < 0x10) Serial.print("0"); Serial.print(green, HEX); if (blue < 0x10) Serial.print("0"); Serial.println(blue, HEX); } // Buttons if (packetbuffer[1] == 'B') { uint8_t buttnum = packetbuffer[2] - '0'; boolean pressed = packetbuffer[3] - '0'; Serial.print ("Button "); Serial.print(buttnum); if (pressed) { Serial.println(" pressed"); } else { Serial.println(" released"); } } // GPS Location if (packetbuffer[1] == 'L') { float lat, lon, alt; lat = parsefloat(packetbuffer+2); lon = parsefloat(packetbuffer+6); alt = parsefloat(packetbuffer+10); Serial.print("GPS Location\t"); Serial.print("Lat: "); Serial.print(lat, 4); // 4 digits of precision! Serial.print('\t'); Serial.print("Lon: "); Serial.print(lon, 4); // 4 digits of precision! Serial.print('\t'); Serial.print(alt, 4); Serial.println(" meters"); } // Accelerometer if (packetbuffer[1] == 'A') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Accel\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); } // Magnetometer if (packetbuffer[1] == 'M') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Mag\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); } // Gyroscope if (packetbuffer[1] == 'G') { float x, y, z; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); Serial.print("Gyro\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.println(); } // Quaternions if (packetbuffer[1] == 'Q') { float x, y, z, w; x = parsefloat(packetbuffer+2); y = parsefloat(packetbuffer+6); z = parsefloat(packetbuffer+10); w = parsefloat(packetbuffer+14); Serial.print("Quat\t"); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.print(z); Serial.print('\t'); Serial.print(w); Serial.println(); } } ================================================ FILE: examples/controller/packetParser.cpp ================================================ #include #include #include #if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_) && not defined(__SAMD51__) #include #endif #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #define PACKET_ACC_LEN (15) #define PACKET_GYRO_LEN (15) #define PACKET_MAG_LEN (15) #define PACKET_QUAT_LEN (19) #define PACKET_BUTTON_LEN (5) #define PACKET_COLOR_LEN (6) #define PACKET_LOCATION_LEN (15) // READ_BUFSIZE Size of the read buffer for incoming packets #define READ_BUFSIZE (20) /* Buffer to hold incoming characters */ uint8_t packetbuffer[READ_BUFSIZE+1]; /**************************************************************************/ /*! @brief Casts the four bytes at the specified address to a float */ /**************************************************************************/ float parsefloat(uint8_t *buffer) { float f; memcpy(&f, buffer, 4); return f; } /**************************************************************************/ /*! @brief Prints a hexadecimal value in plain characters @param data Pointer to the byte data @param numBytes Data length in bytes */ /**************************************************************************/ void printHex(const uint8_t * data, const uint32_t numBytes) { uint32_t szPos; for (szPos=0; szPos < numBytes; szPos++) { Serial.print(F("0x")); // Append leading 0 for small values if (data[szPos] <= 0xF) { Serial.print(F("0")); Serial.print(data[szPos] & 0xf, HEX); } else { Serial.print(data[szPos] & 0xff, HEX); } // Add a trailing space if appropriate if ((numBytes > 1) && (szPos != numBytes - 1)) { Serial.print(F(" ")); } } Serial.println(); } /**************************************************************************/ /*! @brief Waits for incoming data and parses it */ /**************************************************************************/ uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout) { uint16_t origtimeout = timeout, replyidx = 0; memset(packetbuffer, 0, READ_BUFSIZE); while (timeout--) { if (replyidx >= 20) break; if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN)) break; if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN)) break; if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN)) break; if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN)) break; if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN)) break; if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN)) break; if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN)) break; while (ble->available()) { char c = ble->read(); if (c == '!') { replyidx = 0; } packetbuffer[replyidx] = c; replyidx++; timeout = origtimeout; } if (timeout == 0) break; delay(1); } packetbuffer[replyidx] = 0; // null term if (!replyidx) // no data or timeout return 0; if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning return 0; // check checksum! uint8_t xsum = 0; uint8_t checksum = packetbuffer[replyidx-1]; for (uint8_t i=0; i #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include // Configuration (you don't need to change these, but can!): #define FACTORYRESET_ENABLE 1 // Set to 1 to factory reset the Bluefruit LE // module. In general this is a smart idea to // put the module into a known good state. // A value of 1 means perform a factory reset // on start, and 0 means no factory reset. #define NUMPIXELS 10 // Number of NeoPixels on the board. #define BRIGHTNESS 255 // NeoPixel brightness (0...255, low to max brightness) /*=========================================================================*/ // Create the bluefruit object, for Circuit Playground this needs to be // hardware serial. Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } // function prototypes over in packetparser.cpp uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout); float parsefloat(uint8_t *buffer); void printHex(const uint8_t * data, const uint32_t numBytes); // the packet buffer extern uint8_t packetbuffer[]; // Offset that controls which pixels are turned on/off. // Pressing the left/right controller button moves this offset // up/down and 'slides' the chain of 10 pixels around. int currentOffset = 0; // Last selected color. uint8_t currentRed, currentGreen, currentBlue; // Light up a chain of 10 pixels starting at offset global variable value. void lightPixels(uint8_t red, uint8_t green, uint8_t blue, int offset) { CircuitPlayground.strip.clear(); for (int i = offset; i < offset+NUMPIXELS; ++i) { if ((i >= 0) && (i < NUMPIXELS)) { CircuitPlayground.strip.setPixelColor(i, red, green, blue); } } CircuitPlayground.strip.show(); } void setup() { // Wait for serial port before starting. Not required but helps with debugging. //while (!Serial); //delay(500); // Initialize Circuit Playground library and turn off the Pixels. CircuitPlayground.begin(BRIGHTNESS); CircuitPlayground.clearPixels(); // Initialize serial output. Serial.begin(115200); Serial.println(F("Adafruit Circuit Playground Bluefruit Neopixel Color Picker Example")); Serial.println(F("-------------------------------------------------------------------")); // Initialise the module Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in DATA mode & check wiring....")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { // Perform a factory reset to make sure everything is in a known state Serial.println(F("Performing a factory reset: ")); if (!ble.factoryReset()) { Serial.println(F("Couldn't factory reset, making another attempt...")); delay(1000); if (!ble.factoryReset()) { error(F("Couldn't factory reset!")); } } } // Disable command echo from Bluefruit ble.echo(false); Serial.println("Requesting Bluefruit info:"); // Print Bluefruit information ble.info(); // Change advertised name to Circuit_Playground_BLE ble.println("AT+GAPDEVNAME=CPlay_BLE"); delay(100); ble.println("ATZ"); delay(100); Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode")); Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!")); Serial.println(); ble.verbose(false); // debug info is a little annoying after this point! // Wait for connection while (! ble.isConnected()) { delay(500); } Serial.println(F("***********************")); // Set Bluefruit to DATA mode Serial.println( F("Switching to DATA mode!") ); ble.setMode(BLUEFRUIT_MODE_DATA); Serial.println(F("***********************")); } void loop() { /* Wait for new data to arrive */ uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT); if (len == 0) { return; } /* Got a packet! */ //printHex(packetbuffer, len); // Color if (packetbuffer[1] == 'C') { // Parse out the red, green, blue values and save them. uint8_t red = packetbuffer[2]; uint8_t green = packetbuffer[3]; uint8_t blue = packetbuffer[4]; // Change the color. currentRed = red; currentGreen = green; currentBlue = blue; } // Left/right adjust the offset that turns on/off pixels. if (packetbuffer[1] == 'B') { if (memcmp(packetbuffer, "!B705", 5) == 0) { // Left button release. currentOffset -= 1; } else if (memcmp(packetbuffer, "!B804", 5) == 0) { // Right button release. currentOffset += 1; } currentOffset = constrain(currentOffset, -NUMPIXELS, NUMPIXELS); } // Update the pixels again since either the color or offset position // must have changed above. lightPixels(currentRed, currentGreen, currentBlue, currentOffset); } ================================================ FILE: examples/cplay_neopixel_picker/packetParser.cpp ================================================ #include #include #include #if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_) #include #endif #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #define PACKET_ACC_LEN (15) #define PACKET_GYRO_LEN (15) #define PACKET_MAG_LEN (15) #define PACKET_QUAT_LEN (19) #define PACKET_BUTTON_LEN (5) #define PACKET_COLOR_LEN (6) #define PACKET_LOCATION_LEN (15) // READ_BUFSIZE Size of the read buffer for incoming packets #define READ_BUFSIZE (20) /* Buffer to hold incoming characters */ uint8_t packetbuffer[READ_BUFSIZE+1]; /**************************************************************************/ /*! @brief Casts the four bytes at the specified address to a float */ /**************************************************************************/ float parsefloat(uint8_t *buffer) { float f = ((float *)buffer)[0]; return f; } /**************************************************************************/ /*! @brief Prints a hexadecimal value in plain characters @param data Pointer to the byte data @param numBytes Data length in bytes */ /**************************************************************************/ void printHex(const uint8_t * data, const uint32_t numBytes) { uint32_t szPos; for (szPos=0; szPos < numBytes; szPos++) { Serial.print(F("0x")); // Append leading 0 for small values if (data[szPos] <= 0xF) { Serial.print(F("0")); Serial.print(data[szPos] & 0xf, HEX); } else { Serial.print(data[szPos] & 0xff, HEX); } // Add a trailing space if appropriate if ((numBytes > 1) && (szPos != numBytes - 1)) { Serial.print(F(" ")); } } Serial.println(); } /**************************************************************************/ /*! @brief Waits for incoming data and parses it */ /**************************************************************************/ uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout) { uint16_t origtimeout = timeout, replyidx = 0; memset(packetbuffer, 0, READ_BUFSIZE); while (timeout--) { if (replyidx >= 20) break; if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN)) break; if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN)) break; if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN)) break; if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN)) break; if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN)) break; if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN)) break; if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN)) break; while (ble->available()) { char c = ble->read(); if (c == '!') { replyidx = 0; } packetbuffer[replyidx] = c; replyidx++; timeout = origtimeout; } if (timeout == 0) break; delay(1); } packetbuffer[replyidx] = 0; // null term if (!replyidx) // no data or timeout return 0; if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning return 0; // check checksum! uint8_t xsum = 0; uint8_t checksum = packetbuffer[replyidx-1]; for (uint8_t i=0; i #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "Adafruit_BLEEddystone.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS FACTORYRESET_ENABLE Perform a factory reset when running this sketch Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so running this at least once is a good idea. When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values. Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features URL The URL that is advertised. It must not longer than 17 bytes (excluding http:// and www.). Note: ".com/" ".net/" count as 1 -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.7.0" #define URL "http://www.adafruit.com" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); Adafruit_BLEEddystone eddyBeacon(ble); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit EddyStone Example")); Serial.println(F("------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // EddyStone commands are added from firmware 0.6.6 if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { error(F("EddyStone is only available from 0.6.6. Please perform firmware upgrade")); } // Enable Eddystone beacon service and reset Bluefruit if needed eddyBeacon.begin(true); /* Set EddyStone URL beacon data */ Serial.println(F("Setting EddyStone-url to Adafruit website: ")); if ( !eddyBeacon.setURL(URL) ) { error(F("Couldnt set, is URL too long !?")); } Serial.println(F("**************************************************")); Serial.println(F("Please use Google Physical Web application to test")); Serial.println(F("**************************************************")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Print user's option Serial.println(F("Please choose:")); Serial.println(F("0 : Stop broadcasting EddyStone URL")); Serial.println(F("1 : Start broadcasting EddyStone URL")); Serial.println(F("2 : Put EddyStone URL to Config Mode")); // Get User's input char option[BUFSIZE+1]; getUserInput(option, BUFSIZE); // Proccess option switch ( option[0] - '0' ) { case 0: eddyBeacon.stopBroadcast(); break; case 1: eddyBeacon.startBroadcast(); break; case 2: Serial.println(F("EddyStone config's mode is enabled for 300 seconds")); Serial.println(F("Please use Physical Web app to edit URL")); eddyBeacon.startConfigMode(300); break; default: Serial.print(F("Invalid input; ")); Serial.println(option); break; } } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/factoryreset/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/factoryreset/factoryreset.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Factory Reset Example")); Serial.println(F("------------------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if (! ble.factoryReset() ){ error(F("Couldn't factory reset")); } Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); Serial.println(F("DONE!")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { } ================================================ FILE: examples/feathertester/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 160 // Size of the read buffer for incoming data #define VERBOSE_MODE false // If set to 'true' enables debug output // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/feathertester/feathertester.ino ================================================ /* Bluefruit Feather Tester This sketch provides a simple tester for Bluefruit Feather boards from Adafruit created 31 Jan. 2016 by K. Townsend (KTOWN) */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /**************************************************************************/ /*! */ /**************************************************************************/ void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! */ /**************************************************************************/ void setup() { Serial.begin(115200); // Wait for the Serial Monitor to open while (!Serial) { yield(); } // Initialise the BLE module if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } // Display the test suite selection menu display_menu(); } /**************************************************************************/ /*! Reads and prints the AT response buffer until we reach OK or ERROR Returns 'true' if an error occurred, otherwise 'false' */ /**************************************************************************/ bool display_response(void) { // Read the response until we get OK or ERROR while (ble.readline()) { Serial.print(ble.buffer); if ( strcmp(ble.buffer, "OK") == 0 ) { return false; } if ( strcmp(ble.buffer, "ERROR") == 0 ) { return true; } } return true; } /**************************************************************************/ /*! */ /**************************************************************************/ void display_menu() { delay(500); // Short delay for cosmetic reasons Serial.println(""); Serial.println("Bluefruit Feather Tester"); Serial.println("-------------------------------------------------------------------------------"); Serial.println("Select a menu option below:"); Serial.println(""); Serial.println("[1] - System Info"); Serial.println("[2] - AT+HELP"); Serial.println(""); Serial.println("Enter your selection in the Serial Monitor and press "); Serial.println(""); } /**************************************************************************/ /*! */ /**************************************************************************/ void loop() { String user_input = ""; int selection = 0; // Wait for user feedback, then parse feedback one byte at a time while((Serial.available()) && !selection) { char incoming = Serial.read(); if (isdigit(incoming)) { // Append the current digit to the string placeholder user_input += (char)incoming; } // Parse the string on new-line if (incoming == '\n') { selection = user_input.toInt(); } delay(2); } // Run the appropriate test suite if we have a number if (selection) { bool error = false; switch(selection) { case 1: ble.info(); break; case 2: ble.println("AT+HELP"); error = display_response(); break; default: Serial.print("Invalid selection: "); Serial.println(selection); break; } // Catch any error responses here if (error) Serial.println("ERROR!"); // Display the main menu again Serial.println(""); display_menu(); } } ================================================ FILE: examples/healththermometer/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN 8 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/healththermometer/IEEE11073float.cpp ================================================ /**************************************************************************/ /*! @file IEEE11073float.h */ /**************************************************************************/ /** * \file bytelib.c * \brief Byte manipulation module implementation. * Copyright (C) 2010 Signove Tecnologia Corporation. * All rights reserved. * Contact: Signove Tecnologia Corporation (contact@signove.com) * * $LICENSE_TEXT:BEGIN$ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation and appearing * in the file LICENSE included in the packaging of this file; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * $LICENSE_TEXT:END$ * * \author Walter Guerra, Mateus Lima * \date Jun 14, 2010 */ #include #include "IEEE11073float.h" uint32_t float2IEEE11073(double data, uint8_t output[4]) { uint32_t result = MDER_NaN; if (isnan(data)) { goto finally; }/* else if (data > MDER_FLOAT_MAX) { result = MDER_POSITIVE_INFINITY; goto finally; } else if (data < MDER_FLOAT_MIN) { result = MDER_NEGATIVE_INFINITY; goto finally; } else if (data >= -MDER_FLOAT_EPSILON && data <= MDER_FLOAT_EPSILON) { result = 0; goto finally; }*/ double sgn; sgn = data > 0 ? +1 : -1; double mantissa; mantissa = fabs(data); int32_t exponent; exponent = 0; // Note: 10**x exponent, not 2**x // scale up if number is too big while (mantissa > MDER_FLOAT_MANTISSA_MAX) { mantissa /= 10.0; ++exponent; if (exponent > MDER_FLOAT_EXPONENT_MAX) { // argh, should not happen if (sgn > 0) { result = MDER_POSITIVE_INFINITY; } else { result = MDER_NEGATIVE_INFINITY; } goto finally; } } // scale down if number is too small while (mantissa < 1) { mantissa *= 10; --exponent; if (exponent < MDER_FLOAT_EXPONENT_MIN) { // argh, should not happen result = 0; goto finally; } } // scale down if number needs more precision double smantissa; smantissa = round(mantissa * MDER_FLOAT_PRECISION); double rmantissa; rmantissa = round(mantissa) * MDER_FLOAT_PRECISION; double mdiff; mdiff = abs(smantissa - rmantissa); while (mdiff > 0.5 && exponent > MDER_FLOAT_EXPONENT_MIN && (mantissa * 10) <= MDER_FLOAT_MANTISSA_MAX) { mantissa *= 10; --exponent; smantissa = round(mantissa * MDER_FLOAT_PRECISION); rmantissa = round(mantissa) * MDER_FLOAT_PRECISION; mdiff = abs(smantissa - rmantissa); } uint32_t int_mantissa; int_mantissa = (int) round(sgn * mantissa); result = (exponent << 24) | (int_mantissa & 0xFFFFFF); finally: if ( output ) memcpy(output, &result, 4); return result; } ================================================ FILE: examples/healththermometer/IEEE11073float.h ================================================ /**************************************************************************/ /*! @file IEEE11073float.h */ /**************************************************************************/ /** * \file bytelib.c * \brief Byte manipulation module implementation. * Copyright (C) 2010 Signove Tecnologia Corporation. * All rights reserved. * Contact: Signove Tecnologia Corporation (contact@signove.com) * * $LICENSE_TEXT:BEGIN$ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation and appearing * in the file LICENSE included in the packaging of this file; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * $LICENSE_TEXT:END$ * * \author Walter Guerra, Mateus Lima * \date Jun 14, 2010 */ #ifndef _IEEE11073FLOAT_H_ #define _IEEE11073FLOAT_H_ #include typedef enum { MDER_POSITIVE_INFINITY = 0x007FFFFE, MDER_NaN = 0x007FFFFF, MDER_NRes = 0x00800000, MDER_RESERVED_VALUE = 0x00800001, MDER_NEGATIVE_INFINITY = 0x00800002 } ReservedFloatValues; static const int32_t FIRST_RESERVED_VALUE = MDER_POSITIVE_INFINITY; // (2 ** 23 - 3) #define MDER_FLOAT_MANTISSA_MAX 0x007FFFFD // 2 ** 7 - 1 #define MDER_FLOAT_EXPONENT_MAX 127 #define MDER_FLOAT_EXPONENT_MIN -128 // (2 ** 23 - 3) * 10 ** 127 #define MDER_FLOAT_MAX 8.388604999999999e+133 // -(2 ** 23 - 3) * 10 ** 127 #define MDER_FLOAT_MIN (-MDER_FLOAT_MAX) // 10 ** -128 #define MDER_FLOAT_EPSILON 1e-128 // 10 ** upper(23 * log(2) / log(10)) // precision for a number 1.0000xxx #define MDER_FLOAT_PRECISION 10000000 typedef enum { MDER_S_POSITIVE_INFINITY = 0x07FE, MDER_S_NaN = 0x07FF, MDER_S_NRes = 0x0800, MDER_S_RESERVED_VALUE = 0x0801, MDER_S_NEGATIVE_INFINITY = 0x0802 } ReservedSFloatValues; static const uint32_t FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY; // (2 ** 11 - 3) #define MDER_SFLOAT_MANTISSA_MAX 0x07FD // 2 ** 3 - 1 #define MDER_SFLOAT_EXPONENT_MAX 7 #define MDER_SFLOAT_EXPONENT_MIN -8 // (2 ** 11 - 3) * 10 ** 7 #define MDER_SFLOAT_MAX 20450000000.0 // -(2 ** 11 - 3) * 10 ** 7 #define MDER_SFLOAT_MIN (-MDER_SFLOAT_MAX) // 10 ** -8 #define MDER_SFLOAT_EPSILON 1e-8 // 10 ** upper(11 * log(2) / log(10)) #define MDER_SFLOAT_PRECISION 10000 uint32_t float2IEEE11073(double data, uint8_t output[4]); #endif /* _IEEE11073FLOAT_H_ */ ================================================ FILE: examples/healththermometer/healththermometer.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* Please note the long strings of data sent mean the *RTS* pin is required with UART to slow down data sent to the Bluefruit LE! */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "Adafruit_BLEGatt.h" #include "IEEE11073float.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); Adafruit_BLEGatt gatt(ble); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /* The service information */ int32_t htsServiceId; int32_t htsMeasureCharId; /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); boolean success; Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Health Thermometer Example")); Serial.println(F("--------------------------------------------")); randomSeed(micros()); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if (! ble.factoryReset() ){ error(F("Couldn't factory reset")); } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // this line is particularly required for Flora, but is a good idea // anyways for the super long lines ahead! // ble.setInterCharWriteDelay(5); // 5 ms /* Add the Heart Rate Service definition */ /* Service ID should be 1 */ Serial.println(F("Adding the Health Thermometer Service definition (UUID = 0x1809): ")); htsServiceId = gatt.addService(0x1809); if (htsServiceId == 0) { error(F("Could not add Thermometer service")); } /* Add the Temperature Measurement characteristic which is composed of * 1 byte flags + 4 float */ /* Chars ID for Measurement should be 1 */ Serial.println(F("Adding the Temperature Measurement characteristic (UUID = 0x2A1C): ")); htsMeasureCharId = gatt.addCharacteristic(0x2A1C, GATT_CHARS_PROPERTIES_INDICATE, 5, 5, BLE_DATATYPE_BYTEARRAY); if (htsMeasureCharId == 0) { error(F("Could not add Temperature characteristic")); } /* Add the Health Thermometer Service to the advertising data (needed for Nordic apps to detect the service) */ Serial.print(F("Adding Health Thermometer Service UUID to the advertising payload: ")); uint8_t advdata[] { 0x02, 0x01, 0x06, 0x05, 0x02, 0x09, 0x18, 0x0a, 0x18 }; ble.setAdvData( advdata, sizeof(advdata) ); /* Reset the device for the new service setting changes to take effect */ Serial.print(F("Performing a SW reset (service changes require a reset): ")); ble.reset(); Serial.println(); } /** Send randomized heart rate data continuously **/ void loop(void) { double temp = random(0, 100) / 10.0; Serial.print(F("Updating Temperature value to ")); Serial.print(temp); Serial.println(F(" Fahrenheit")); // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml // Chars value is 1 flag + 4 float value. Tempearature is in Fahrenheit unit uint8_t temp_measurement [5] = { bit(0) }; float2IEEE11073(temp, temp_measurement+1); // TODO temperature is not correct due to Bluetooth use IEEE-11073 format gatt.setChar(htsMeasureCharId, temp_measurement, 5); /* Delay before next measurement update */ delay(1000); } ================================================ FILE: examples/heartratemonitor/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN 8 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/heartratemonitor/heartratemonitor.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* Please note the long strings of data sent mean the *RTS* pin is required with UART to slow down data sent to the Bluefruit LE! */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /* The service information */ int32_t hrmServiceId; int32_t hrmMeasureCharId; int32_t hrmLocationCharId; /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); boolean success; Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Heart Rate Monitor (HRM) Example")); Serial.println(F("---------------------------------------------------")); randomSeed(micros()); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if (! ble.factoryReset() ){ error(F("Couldn't factory reset")); } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // this line is particularly required for Flora, but is a good idea // anyways for the super long lines ahead! // ble.setInterCharWriteDelay(5); // 5 ms /* Change the device name to make it easier to find */ Serial.println(F("Setting device name to 'Bluefruit HRM': ")); if (! ble.sendCommandCheckOK(F("AT+GAPDEVNAME=Bluefruit HRM")) ) { error(F("Could not set device name?")); } /* Add the Heart Rate Service definition */ /* Service ID should be 1 */ Serial.println(F("Adding the Heart Rate Service definition (UUID = 0x180D): ")); success = ble.sendCommandWithIntReply( F("AT+GATTADDSERVICE=UUID=0x180D"), &hrmServiceId); if (! success) { error(F("Could not add HRM service")); } /* Add the Heart Rate Measurement characteristic */ /* Chars ID for Measurement should be 1 */ Serial.println(F("Adding the Heart Rate Measurement characteristic (UUID = 0x2A37): ")); success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40"), &hrmMeasureCharId); if (! success) { error(F("Could not add HRM characteristic")); } /* Add the Body Sensor Location characteristic */ /* Chars ID for Body should be 2 */ Serial.println(F("Adding the Body Sensor Location characteristic (UUID = 0x2A38): ")); success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2A38, PROPERTIES=0x02, MIN_LEN=1, VALUE=3"), &hrmLocationCharId); if (! success) { error(F("Could not add BSL characteristic")); } /* Add the Heart Rate Service to the advertising data (needed for Nordic apps to detect the service) */ Serial.print(F("Adding Heart Rate Service UUID to the advertising payload: ")); ble.sendCommandCheckOK( F("AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18") ); /* Reset the device for the new service setting changes to take effect */ Serial.print(F("Performing a SW reset (service changes require a reset): ")); ble.reset(); Serial.println(); } /** Send randomized heart rate data continuously **/ void loop(void) { int heart_rate = random(50, 100); Serial.print(F("Updating HRM value to ")); Serial.print(heart_rate); Serial.println(F(" BPM")); /* Command is sent when \n (\r) or println is called */ /* AT+GATTCHAR=CharacteristicID,value */ ble.print( F("AT+GATTCHAR=") ); ble.print( hrmMeasureCharId ); ble.print( F(",00-") ); ble.println(heart_rate, HEX); /* Check if command executed OK */ if ( !ble.waitForOK() ) { Serial.println(F("Failed to get response!")); } /* Delay before next measurement update */ delay(1000); } ================================================ FILE: examples/hidcontrolkey/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // HARDWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno, etc. // This should be used with nRF51822 based Bluefruit LE modules that use SPI. // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused ================================================ FILE: examples/hidcontrolkey/hidcontrolkey.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* This example shows how to send HID Consumer Control Keys, ncluding the following control key definitions: System Control (works on most systems: Windows/OS X/Android/iOS) - Sound Mute - Brightness Increase, decrease Media Control (works on most systems) - PlayPause - MediaNext Application Launchers (works mainly on Windows 8/10) - EmailReader - Calculator Browser Specific (Firefox, file explorer: mainly on Windows 8/10) - Back - Forward - Refresh - Search */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 0 #define MINIMUM_FIRMWARE_VERSION "0.6.6" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // Required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit HID Control Key Example")); Serial.println(F("---------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Factory reset failed!")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // This demo only works with firmware 0.6.6 and higher! // Request the Bluefruit firmware rev and check if it is valid if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { error(F("This sketch requires firmware version " MINIMUM_FIRMWARE_VERSION " or higher!")); } /* Enable HID Service */ Serial.println(F("Enable HID Services (including Control Key): ")); if (! ble.sendCommandCheckOK(F( "AT+BLEHIDEN=On" ))) { error(F("Failed to enable HID (firmware >=0.6.6?)")); } /* Adding or removing services requires a reset */ Serial.println(F("Performing a SW reset (service changes require a reset): ")); if (! ble.reset() ) { error(F("Couldn't reset??")); } Serial.println(); Serial.println(F("**********************************************************")); Serial.println(F("Go to your phone's Bluetooth settings to pair your device")); Serial.println(F("Some Control Key works system-wide: mute, brightness ...")); Serial.println(F("Some are application specific: Media play/pause")); Serial.println(F("**********************************************************")); // Print pre-defined control keys printDefinedControlKey(); Serial.println(); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Display prompt Serial.print(F("Control (? for help) > ")); // Check for user input and echo it back if anything was found char keys[BUFSIZE+1]; getUserInput(keys, BUFSIZE); Serial.println(keys); if ( keys[0] == '?') { printDefinedControlKey(); }else { ble.print("AT+BleHidControlKey="); ble.println(keys); if( ble.waitForOK() ) { Serial.println( F("OK!") ); }else { Serial.println( F("FAILED!") ); // Failed, probably pairing is not complete yet Serial.println( F("Please make sure Bluefruit is paired and try again") ); } } } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } /**************************************************************************/ /*! @brief Print pre-defined control keys */ /**************************************************************************/ void printDefinedControlKey(void) { Serial.println(); Serial.println(F("You can send a raw 16-bit (e.g 0x1234) usage key from the USB" "\n" "HID Consumer Control Page or use one of the the following keys:")); Serial.println(F("List of pre-defined control keys:")); Serial.print(F( "- BRIGHTNESS+" "\n" "- BRIGHTNESS-" "\n" "- PLAYPAUSE" "\n" "- MEDIANEXT" "\n" "- MEDIAPREVIOUS" "\n" "- MEDIASTOP" "\n" "- VOLUME" "\n" "- MUTE" "\n" "- BASS" "\n" "- TREBLE" "\n" "- BASS_BOOST" "\n" "- VOLUME+" "\n" "- VOLUME-" "\n" "- BASS+" "\n" "- BASS-" "\n" "- TREBLE+" "\n" "- TREBLE-" "\n" "- EMAILREADER" "\n" "- CALCULATOR" "\n" "- FILEBROWSER" "\n" "- SEARCH" "\n" "- HOME" "\n" "- BACK" "\n" "- FORWARD" "\n" "- STOP" "\n" "- REFRESH" "\n" "- BOOKMARKS" "\n" )); } ================================================ FILE: examples/hidkeyboard/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // HARDWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno, etc. // This should be used with nRF51822 based Bluefruit LE modules that use SPI. // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused ================================================ FILE: examples/hidkeyboard/hidkeyboard.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* This example shows how to send HID (keyboard/mouse/etc) data via BLE Note that not all devices support BLE keyboard! BLE Keyboard != Bluetooth Keyboard */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 0 #define MINIMUM_FIRMWARE_VERSION "0.6.6" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit HID Keyboard Example")); Serial.println(F("---------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); /* Change the device name to make it easier to find */ Serial.println(F("Setting device name to 'Bluefruit Keyboard': ")); if (! ble.sendCommandCheckOK(F( "AT+GAPDEVNAME=Bluefruit Keyboard" )) ) { error(F("Could not set device name?")); } /* Enable HID Service */ Serial.println(F("Enable HID Service (including Keyboard): ")); if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { if ( !ble.sendCommandCheckOK(F( "AT+BleHIDEn=On" ))) { error(F("Could not enable Keyboard")); } }else { if (! ble.sendCommandCheckOK(F( "AT+BleKeyboardEn=On" ))) { error(F("Could not enable Keyboard")); } } /* Add or remove service requires a reset */ Serial.println(F("Performing a SW reset (service changes require a reset): ")); if (! ble.reset() ) { error(F("Couldn't reset??")); } Serial.println(); Serial.println(F("Go to your phone's Bluetooth settings to pair your device")); Serial.println(F("then open an application that accepts keyboard input")); Serial.println(); Serial.println(F("Enter the character(s) to send:")); Serial.println(F("- \\r for Enter")); Serial.println(F("- \\n for newline")); Serial.println(F("- \\t for tab")); Serial.println(F("- \\b for backspace")); Serial.println(); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Display prompt Serial.print(F("keyboard > ")); // Check for user input and echo it back if anything was found char keys[BUFSIZE+1]; getUserInput(keys, BUFSIZE); Serial.print("\nSending "); Serial.println(keys); ble.print("AT+BleKeyboard="); ble.println(keys); if( ble.waitForOK() ) { Serial.println( F("OK!") ); }else { Serial.println( F("FAILED!") ); } } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/hidmouse/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // HARDWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno, etc. // This should be used with nRF51822 based Bluefruit LE modules that use SPI. // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused ================================================ FILE: examples/hidmouse/hidmouse.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* This example shows how to send HID (keyboard/mouse/etc) data via BLE Note that not all devices support BLE Mouse! - OSX, Windows 10 both work - Android has limited support - iOS completely ignores mouse */ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 0 #define MINIMUM_FIRMWARE_VERSION "0.6.6" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit HID Mouse Example")); Serial.println(F("---------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // This demo only available for firmware from 0.6.6 if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) ) { error(F("This sketch requires firmware version " MINIMUM_FIRMWARE_VERSION " or higher!")); } /* Enable HID Service (including Mouse) */ Serial.println(F("Enable HID Service (including Mouse): ")); if (! ble.sendCommandCheckOK(F( "AT+BleHIDEn=On" ))) { error(F("Failed to enable HID (firmware >=0.6.6?)")); } /* Add or remove service requires a reset */ Serial.println(F("Performing a SW reset (service changes require a reset): ")); if (! ble.reset() ) { error(F("Could not reset??")); } Serial.println(); Serial.println(F("Go to your phone's Bluetooth settings to pair your device")); Serial.println(F("then open an application that accepts mouse input")); Serial.println(); Serial.println(F("The example will try to draw a rectangle using the left mouse button with your input")); Serial.println(F("Parameters are a pair of 8-bit signed numbers (x,y) e.g:")); Serial.println(F(" 100,100 : draw toward bottom right corner")); Serial.println(F(" -100,-100: draw toward top left corner")); Serial.println(); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { Serial.println(F("x,y = ")); // Check for user input and echo it back if anything was found char input[BUFSIZE+1]; getUserInput(input, BUFSIZE); Serial.println(input); // Press (and hold) the Left mouse's button if ( ble.sendCommandCheckOK(F("AT+BleHidMouseButton=L,press")) ) { // delay a bit delay(250); // Mouse moves according to the user's input ble.print(F("AT+BleHidMouseMove=")); ble.println(input); if( ble.waitForOK() ) { Serial.println( F("OK!") ); }else { Serial.println( F("FAILED!") ); } // Way for user to release left button Serial.println( F("Enter anything to release Left Button") ); getUserInput(input, BUFSIZE); // Release the Left mouse's button ble.sendCommandCheckOK(F("AT+BleHidMouseButton=0")); }else { // Failed, probably pairing is not complete yet Serial.println( F("Please make sure Bluefruit is paired and try again") ); } } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/midi/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN 12 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN -1 // Set to -1 if unused // HARDWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno, etc. // This should be used with nRF51822 based Bluefruit LE modules that use SPI. // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 6 // Optional but recommended, set to -1 if unused ================================================ FILE: examples/midi/midi.ino ================================================ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "Adafruit_BLEMIDI.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" #define FACTORYRESET_ENABLE 1 #define MINIMUM_FIRMWARE_VERSION "0.7.0" // This app was tested on iOS with the following apps: // // https://itunes.apple.com/us/app/midimittr/id925495245?mt=8 // https://itunes.apple.com/us/app/igrand-piano-free-for-ipad/id562914032?mt=8 // // To test: // - Run this sketch and open the Serial Monitor // - Open the iGrand Piano Free app // - Open the midimittr app on your phone and under Clients select "Adafruit Bluefruit LE" // - When you see the 'Connected' label switch to the Routing panel // - Set the Destination to 'iGrand Piano' // - Switch to the iGrand Piano Free app and you should see notes playing one by one // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); Adafruit_BLEMIDI midi(ble); bool isConnected = false; int current_note = 60; // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } // callback void connected(void) { isConnected = true; Serial.println(F(" CONNECTED!")); delay(1000); } void disconnected(void) { Serial.println("disconnected"); isConnected = false; } void BleMidiRX(uint16_t timestamp, uint8_t status, uint8_t byte1, uint8_t byte2) { Serial.print("[MIDI "); Serial.print(timestamp); Serial.print(" ] "); Serial.print(status, HEX); Serial.print(" "); Serial.print(byte1 , HEX); Serial.print(" "); Serial.print(byte2 , HEX); Serial.print(" "); Serial.println(); } void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit MIDI Example")); Serial.println(F("---------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ) { error(F("Couldn't factory reset")); } } //ble.sendCommandCheckOK(F("AT+uartflow=off")); ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); /* Set BLE callbacks */ ble.setConnectCallback(connected); ble.setDisconnectCallback(disconnected); // Set MIDI RX callback midi.setRxCallback(BleMidiRX); Serial.println(F("Enable MIDI: ")); if ( ! midi.begin(true) ) { error(F("Could not enable MIDI")); } ble.verbose(false); Serial.print(F("Waiting for a connection...")); } void loop(void) { // interval for each scanning ~ 500ms (non blocking) ble.update(500); // bail if not connected if (! isConnected) return; Serial.print("Sending pitch "); Serial.println(current_note, HEX); // send note on midi.send(0x90, current_note, 0x64); delay(500); // send note off midi.send(0x80, current_note, 0x64); delay(500); // increment note pitch current_note++; // only do one octave if(current_note > 72) current_note = 60; } ================================================ FILE: examples/ndof_bno055/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/ndof_bno055/README.md ================================================ # NDOF BNO055 Example This example is intended to be used with a board like the [Bluefruit LE Micro](https://www.adafruit.com/product/2661). It will read data samples from the [BNO055](https://www.adafruit.com/products/2472) at a fixed rate, and transmit the data over the air using the BLE UART service. # Requirements To use this example, you will also need the following libraries installed on your system: - [Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor) - [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055) ## Wiring Connect your Bluefruit LE Micro to the BNO055 breakout using I2C as follows: - VIN on the BNO055 to USB on the Bluefruit LE Micro - GND on the BNO055 to GND on the Bluefruit LE Micro - SDA on the BNO055 to SDA on the Bluefruit LE Micro - SCL on the BNO055 to SCL on the Bluefruit LE Micro ================================================ FILE: examples/ndof_bno055/ndof_bno055.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include #include #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* Set the delay between fresh samples (not too fast, BLE UART is slow!) */ /* Firware <=0.6.6 should use 500ms, >=0.6.7 can use 200ms */ #define BNO055_SAMPLERATE_DELAY_MS (500) Adafruit_BNO055 bno = Adafruit_BNO055(55); /**************************************************************************/ /*! @brief A small helper function for error messages */ /**************************************************************************/ void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /* Displays some basic information on this sensor from the unified sensor API sensor_t type (see Adafruit_Sensor for more information) */ /**************************************************************************/ void displaySensorDetails(void) { sensor_t sensor; bno.getSensor(&sensor); Serial.println("------------------------------------"); Serial.print ("Sensor: "); Serial.println(sensor.name); Serial.print ("Driver Ver: "); Serial.println(sensor.version); Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx"); Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx"); Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx"); Serial.println("------------------------------------"); Serial.println(""); delay(500); } /**************************************************************************/ /* Display some basic info about the sensor status */ /**************************************************************************/ void displaySensorStatus(void) { // Get the system status values (mostly for debugging purposes) uint8_t system_status, self_test_results, system_error; system_status = self_test_results = system_error = 0; bno.getSystemStatus(&system_status, &self_test_results, &system_error); // Display the results in the Serial Monitor Serial.print("System Status: 0x"); Serial.println(system_status, HEX); Serial.print("Self Test: 0x"); Serial.println(self_test_results, HEX); Serial.print("System Error: 0x"); Serial.println(system_error, HEX); Serial.println(""); delay(500); } /**************************************************************************/ /* Display sensor calibration status */ /**************************************************************************/ void displayCalStatus(void) { // Get the four calibration values (0..3) // 3 means 'fully calibrated" uint8_t system, gyro, accel, mag; system = gyro = accel = mag = 0; bno.getCalibration(&system, &gyro, &accel, &mag); // The data should be ignored until the system calibration is > 0 Serial.print("\t"); if (!system) { Serial.print("! "); } // Display the individual values Serial.print("Sys:"); Serial.print(system, DEC); Serial.print(" G:"); Serial.print(gyro, DEC); Serial.print(" A:"); Serial.print(accel, DEC); Serial.print(" M:"); Serial.print(mag, DEC); } /**************************************************************************/ /* Sends sensor calibration status out over BLE UART */ /**************************************************************************/ void transmitCalStatus(void) { uint8_t system, gyro, accel, mag; system = gyro = accel = mag = 0; // Get the four calibration values (0..3) // 3 means 'fully calibrated" bno.getCalibration(&system, &gyro, &accel, &mag); /* Prepare the AT command */ ble.print("AT+BLEUARTTX="); // Transmit individual values // Note: The values are abbreviated compared to the Serial Monitor // to save space since BLE UART is quite slow */ ble.print(","); ble.print(system, DEC); ble.print(gyro, DEC); ble.print(accel, DEC); ble.println(mag, DEC); if (! ble.waitForOK() ) { Serial.println(F("Failed to send?")); } } /**************************************************************************/ /*! @brief Initializes the one wire temperature sensor */ /**************************************************************************/ void initSensor(void) { if(!bno.begin()) { // There was a problem detecting the BNO055 ... check your connections Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!"); while(1); } delay(1000); // Display some basic information on this sensor displaySensorDetails(); // Optional: Display current status displaySensorStatus(); bno.setExtCrystalUse(true); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Command Mode Example")); Serial.println(F("---------------------------------------")); // Initialise the module Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); // Perform a factory reset to make sure everything is in a known state Serial.println(F("Performing a factory reset: ")); if (! ble.factoryReset() ){ error(F("Couldn't factory reset")); } // Disable command echo from Bluefruit ble.echo(false); Serial.println("Requesting Bluefruit info:"); // Print Bluefruit information ble.info(); ble.verbose(false); // debug info is a little annoying after this point! // Setup the BNO055 sensor initSensor(); Serial.println("Waiting for a BLE connection to continue ..."); // Wait for connection to finish while (! ble.isConnected()) { delay(5000); } Serial.println(F("CONNECTED!")); Serial.println(F("**********")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Check for user input char inputs[BUFSIZE+1]; // Send sensor data out if (ble.isConnected()) { // Get Quaternion data (no 'Gimbal Lock' like with Euler angles) imu::Quaternion quat = bno.getQuat(); // Display the full data in Serial Monitor Serial.print("qW: "); Serial.print(quat.w(), 4); Serial.print(" qX: "); Serial.print(quat.y(), 4); Serial.print(" qY: "); Serial.print(quat.x(), 4); Serial.print(" qZ: "); Serial.print(quat.z(), 4); displayCalStatus(); Serial.println(""); // Send abbreviated integer data out over BLE UART ble.print("AT+BLEUARTTX="); ble.print(quat.w(), 4); ble.print(","); ble.print(quat.y(), 4); ble.print(","); ble.print(quat.x(), 4); ble.print(","); ble.println(quat.z(), 4); if (! ble.waitForOK() ) { Serial.println(F("Failed to send?")); } // Optional: Send the calibration data as well transmitCalStatus(); // Send a new line character for the next record ble.println("AT+BLEUARTTX=\\r\\n"); if (! ble.waitForOK() ) { Serial.println(F("Failed to send?")); } /* // Display the buffer size (firmware 0.6.7 and higher only!) ble.println("AT+BLEUARTFIFO=TX"); ble.readline(); Serial.print("TX FIFO: "); Serial.println(ble.buffer); */ // Wait a bit ... delay(BNO055_SAMPLERATE_DELAY_MS); } // Check for incoming characters from Bluefruit if (ble.isConnected()) { ble.println("AT+BLEUARTRX"); ble.readline(); if (strcmp(ble.buffer, "OK") == 0) { // no data return; } // Some data was found, its in the buffer Serial.print(F("[Recv] ")); Serial.println(ble.buffer); ble.waitForOK(); } } ================================================ FILE: examples/neopixel/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output #define BLE_READPACKET_TIMEOUT 500 // Timeout in ms waiting to read a response // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/neopixel/neopixel.ino ================================================ /********************************************************************* This is an example for our nRF51 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ // This sketch is intended to be used with the NeoPixel control // surface in Adafruit's Bluefruit LE Connect mobile application. // // - Compile and flash this sketch to a board connected to/bundled with a nRF51 // - Open the Bluefruit LE Connect app // - Switch to the NeoPixel utility // - Click the 'connect' button to establish a connection and // send the meta-data about the pixel layout // - Use the NeoPixel utility to update the pixels on your device /* NOTE: This sketch required at least version 1.1.0 of Adafruit_Neopixel !!! */ #include #include #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" #define FACTORYRESET_ENABLE 1 #define NEOPIXEL_VERSION_STRING "Neopixel v2.0" #define PIN 6 /* Pin used to drive the NeoPixels */ #define MAXCOMPONENTS 4 uint8_t *pixelBuffer = NULL; uint8_t width = 0; uint8_t height = 0; uint8_t stride; uint8_t componentsValue; bool is400Hz; uint8_t components = 3; // only 3 and 4 are valid values Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(); // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } void serial_printf(const char * format, ...) { char buffer [48]; va_list args; va_start(args, format); vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); Serial.print(buffer); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { Serial.begin(115200); Serial.println("Adafruit Bluefruit Neopixel Test"); Serial.println("--------------------------------"); Serial.println(); Serial.println("Please connect using the Bluefruit Connect LE application"); // Config Neopixels neopixel.begin(); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); ble.verbose(false); // debug info is a little annoying after this point! /* Wait for connection */ while (! ble.isConnected()) { delay(500); } Serial.println(F("***********************")); // Set Bluefruit to DATA mode Serial.println( F("Switching to DATA mode!") ); ble.setMode(BLUEFRUIT_MODE_DATA); Serial.println(F("***********************")); } void loop() { // Echo received data if ( ble.isConnected() ) { int command = ble.read(); switch (command) { case 'V': { // Get Version commandVersion(); break; } case 'S': { // Setup dimensions, components, stride... commandSetup(); break; } case 'C': { // Clear with color commandClearColor(); break; } case 'B': { // Set Brightness commandSetBrightness(); break; } case 'P': { // Set Pixel commandSetPixel(); break; } case 'I': { // Receive new image commandImage(); break; } } } } void swapBuffers() { uint8_t *base_addr = pixelBuffer; int pixelIndex = 0; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { if (components == 3) { neopixel.setPixelColor(pixelIndex, neopixel.Color(*base_addr, *(base_addr+1), *(base_addr+2))); } else { neopixel.setPixelColor(pixelIndex, neopixel.Color(*base_addr, *(base_addr+1), *(base_addr+2), *(base_addr+3) )); } base_addr+=components; pixelIndex++; } pixelIndex += stride - width; // Move pixelIndex to the next row (take into account the stride) } neopixel.show(); } void commandVersion() { Serial.println(F("Command: Version check")); sendResponse(NEOPIXEL_VERSION_STRING); } void commandSetup() { Serial.println(F("Command: Setup")); width = ble.read(); height = ble.read(); stride = ble.read(); componentsValue = ble.read(); is400Hz = ble.read(); neoPixelType pixelType; pixelType = componentsValue + (is400Hz ? NEO_KHZ400 : NEO_KHZ800); components = (componentsValue == NEO_RGB || componentsValue == NEO_RBG || componentsValue == NEO_GRB || componentsValue == NEO_GBR || componentsValue == NEO_BRG || componentsValue == NEO_BGR) ? 3:4; serial_printf("\tsize: %dx%d\n", width, height); serial_printf("\tstride: %d\n", stride); serial_printf("\tpixelType %d\n", pixelType); serial_printf("\tcomponents: %d\n", components); if (pixelBuffer != NULL) { delete[] pixelBuffer; } uint32_t size = width*height; pixelBuffer = new uint8_t[size*components]; neopixel.updateLength(size); neopixel.updateType(pixelType); neopixel.setPin(PIN); // Done sendResponse("OK"); } void commandSetBrightness() { Serial.println(F("Command: SetBrightness")); // Read value uint8_t brightness = ble.read(); // Set brightness neopixel.setBrightness(brightness); // Refresh pixels swapBuffers(); // Done sendResponse("OK"); } void commandClearColor() { Serial.println(F("Command: ClearColor")); // Read color uint8_t color[MAXCOMPONENTS]; for (int j = 0; j < components;) { if (ble.available()) { color[j] = ble.read(); j++; } } // Set all leds to color int size = width * height; uint8_t *base_addr = pixelBuffer; for (int i = 0; i < size; i++) { for (int j = 0; j < components; j++) { *base_addr = color[j]; base_addr++; } } // Swap buffers Serial.println(F("ClearColor completed")); swapBuffers(); if (components == 3) { serial_printf("\tclear (%d, %d, %d)\n", color[0], color[1], color[2] ); } else { serial_printf("\tclear (%d, %d, %d, %d)\n", color[0], color[1], color[2], color[3] ); } // Done sendResponse("OK"); } void commandSetPixel() { Serial.println(F("Command: SetPixel")); // Read position uint8_t x = ble.read(); uint8_t y = ble.read(); // Read colors uint32_t pixelOffset = y*width+x; uint32_t pixelDataOffset = pixelOffset*components; uint8_t *base_addr = pixelBuffer+pixelDataOffset; for (int j = 0; j < components;) { if (ble.available()) { *base_addr = ble.read(); base_addr++; j++; } } // Set colors uint32_t neopixelIndex = y*stride+x; uint8_t *pixelBufferPointer = pixelBuffer + pixelDataOffset; uint32_t color; if (components == 3) { color = neopixel.Color( *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2) ); serial_printf("\tcolor (%d, %d, %d)\n",*pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2) ); } else { color = neopixel.Color( *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2), *(pixelBufferPointer+3) ); serial_printf("\tcolor (%d, %d, %d, %d)\n", *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2), *(pixelBufferPointer+3) ); } neopixel.setPixelColor(neopixelIndex, color); neopixel.show(); // Done sendResponse("OK"); } void commandImage() { serial_printf("Command: Image %dx%d, %d, %d\n", width, height, components, stride); // Receive new pixel buffer int size = width * height; uint8_t *base_addr = pixelBuffer; for (int i = 0; i < size; i++) { for (int j = 0; j < components;) { if (ble.available()) { *base_addr = ble.read(); base_addr++; j++; } } /* if (components == 3) { uint32_t index = i*components; Serial.printf("\tp%d (%d, %d, %d)\n", i, pixelBuffer[index], pixelBuffer[index+1], pixelBuffer[index+2] ); } */ } // Swap buffers Serial.println(F("Image received")); swapBuffers(); // Done sendResponse("OK"); } void sendResponse(char const *response) { serial_printf("Send Response: %s\n", response); ble.write(response, strlen(response)*sizeof(char)); } ================================================ FILE: examples/neopixel_picker/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output #define BLE_READPACKET_TIMEOUT 500 // Timeout in ms waiting to read a response // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/neopixel_picker/neopixel_picker.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. PIN Which pin on the Arduino is connected to the NeoPixels? NUMPIXELS How many NeoPixels are attached to the Arduino? -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define PIN 5 #define NUMPIXELS 1 /*=========================================================================*/ Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUMPIXELS, PIN); // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } // function prototypes over in packetparser.cpp uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout); float parsefloat(uint8_t *buffer); void printHex(const uint8_t * data, const uint32_t numBytes); // the packet buffer extern uint8_t packetbuffer[]; /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); // turn off neopixel pixel.begin(); // This initializes the NeoPixel library. for(uint8_t i=0; i #include #include #if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_) #include #endif #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #define PACKET_ACC_LEN (15) #define PACKET_GYRO_LEN (15) #define PACKET_MAG_LEN (15) #define PACKET_QUAT_LEN (19) #define PACKET_BUTTON_LEN (5) #define PACKET_COLOR_LEN (6) #define PACKET_LOCATION_LEN (15) // READ_BUFSIZE Size of the read buffer for incoming packets #define READ_BUFSIZE (20) /* Buffer to hold incoming characters */ uint8_t packetbuffer[READ_BUFSIZE+1]; /**************************************************************************/ /*! @brief Casts the four bytes at the specified address to a float */ /**************************************************************************/ float parsefloat(uint8_t *buffer) { float f = ((float *)buffer)[0]; return f; } /**************************************************************************/ /*! @brief Prints a hexadecimal value in plain characters @param data Pointer to the byte data @param numBytes Data length in bytes */ /**************************************************************************/ void printHex(const uint8_t * data, const uint32_t numBytes) { uint32_t szPos; for (szPos=0; szPos < numBytes; szPos++) { Serial.print(F("0x")); // Append leading 0 for small values if (data[szPos] <= 0xF) { Serial.print(F("0")); Serial.print(data[szPos] & 0xf, HEX); } else { Serial.print(data[szPos] & 0xff, HEX); } // Add a trailing space if appropriate if ((numBytes > 1) && (szPos != numBytes - 1)) { Serial.print(F(" ")); } } Serial.println(); } /**************************************************************************/ /*! @brief Waits for incoming data and parses it */ /**************************************************************************/ uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout) { uint16_t origtimeout = timeout, replyidx = 0; memset(packetbuffer, 0, READ_BUFSIZE); while (timeout--) { if (replyidx >= 20) break; if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN)) break; if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN)) break; if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN)) break; if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN)) break; if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN)) break; if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN)) break; if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN)) break; while (ble->available()) { char c = ble->read(); if (c == '!') { replyidx = 0; } packetbuffer[replyidx] = c; replyidx++; timeout = origtimeout; } if (timeout == 0) break; delay(1); } packetbuffer[replyidx] = 0; // null term if (!replyidx) // no data or timeout return 0; if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning return 0; // check checksum! uint8_t xsum = 0; uint8_t checksum = packetbuffer[replyidx-1]; for (uint8_t i=0; i #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /* This demo perform factory reset on the first run then * - Write a defined magic number at offset 0 * - Write a DATE string at offset 16 * - Dump the whole NVM section, User's NVM is started at 0x0640 */ #define MAGIC_NUMBER 0xC0FFEE #define MAGIC_STRING __DATE__ /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit NVM DATA Example")); Serial.println(F("-------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); /* Disable command echo from Bluefruit */ // ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); int32_t magic_number; ble.readNVM(0, &magic_number); if ( magic_number != MAGIC_NUMBER ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Magic not found: performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } // Write data to NVM Serial.println( F("Write defined data to NVM") ); ble.writeNVM(0 , MAGIC_NUMBER); ble.writeNVM(16, MAGIC_STRING); }else { Serial.println(F("Magic found")); } // Read from NVM and print out ble.readNVM(0, &magic_number); Serial.print( F("Magic Number: ") ); Serial.println( magic_number ); char magic_str[32]; ble.readNVM(16, magic_str, sizeof(magic_str)); Serial.print( F("Magic String: ") ); Serial.println( magic_str ); // Dump the whole NVM section Serial.println(); Serial.println("Dumping the whole NVM contents"); ble.atcommand(F("AT+DBGNVMRD")); Serial.println("User NVM data is at offset 0x0640"); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { // Display command prompt Serial.print(F("AT > ")); // Check for user input and echo it back if anything was found char command[BUFSIZE+1]; getUserInput(command, BUFSIZE); // Send command ble.atcommand(command); } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/throughput/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/throughput/throughput.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" /*========================================================================= APPLICATION SETTINGS     FACTORYRESET_ENABLE    Perform a factory reset when running this sketch         Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so     running this at least once is a good idea.         When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your     Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values.             Some sketches that require you to bond to a central device (HID mouse, keyboard, etc.) won't work at all with this feature enabled since the factory reset will clear all of the bonding data stored on the chip, meaning the central device won't be able to reconnect. -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // String to send in the throughput test #define TEST_STRING "01234567899876543210" // Number of total data sent ( 1024 times the test string) #define TOTAL_BYTES (1024 * strlen(TEST_STRING)) // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit Throughput Tester")); Serial.println(F("------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); /* Switch to DATA mode to have a better throughput */ Serial.println("Switch to DATA mode to have a better throughput ..."); /* Wait for a connection before starting the test */ Serial.println("Waiting for a BLE connection to continue ..."); ble.setMode(BLUEFRUIT_MODE_DATA); ble.verbose(false); // debug info is a little annoying after this point! // Wait for connection to finish while (! ble.isConnected()) { delay(5000); } // Wait for the connection to complete delay(1000); Serial.println(F("CONNECTED!")); Serial.println(F("**********")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { uint32_t start, stop, sent; uint32_t remaining = TOTAL_BYTES; start = stop = sent = 0; if (ble.isConnected()) { // Wait for user input before trying again Serial.println("Connected. Send a key and press enter to start test"); char command[BUFSIZE+1]; getUserInput(command, BUFSIZE); Serial.print("Sending "); Serial.print(remaining); Serial.println(" bytes ..."); start = millis(); while (remaining > 0) { // ble.print("AT+BLEUARTTX="); // ble.println(TEST_STRING); // if (! ble.waitForOK() ) // { // Serial.println(F("Failed to send?")); // } ble.writeBLEUart(TEST_STRING); sent += strlen(TEST_STRING); remaining -= strlen(TEST_STRING); // Only print every 1KB sent if ( (sent % 2000) == 0 ) { Serial.print("Sent: "); Serial.print(sent); Serial.print(" Remaining: "); Serial.println(remaining); } /* Optional: Test for lost connection every packet */ /* Note that this will slow things down a bit! */ /* if (!ble.isConnected()) { Serial.println("Connection lost"); remaining = 0; } */ } stop = millis() - start; Serial.print("Sent "); Serial.print(sent); Serial.print(" bytes in "); Serial.print(stop/1000.0F, 2); Serial.println(" seconds."); Serial.println("Speed "); Serial.print( (sent/1000.0F) / (stop/1000.0F), 2); Serial.println(" KB/s.\r\n"); } } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: examples/uribeacon/BluefruitConfig.h ================================================ // COMMON SETTINGS // ---------------------------------------------------------------------------------------------- // These settings are used in both SW UART, HW UART and SPI mode // ---------------------------------------------------------------------------------------------- #define BUFSIZE 128 // Size of the read buffer for incoming data #define VERBOSE_MODE true // If set to 'true' enables debug output // SOFTWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins that will be used for 'SW' serial. // You should use this option if you are connecting the UART Friend to an UNO // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SWUART_RXD_PIN 9 // Required for software serial! #define BLUEFRUIT_SWUART_TXD_PIN 10 // Required for software serial! #define BLUEFRUIT_UART_CTS_PIN 11 // Required for software serial! #define BLUEFRUIT_UART_RTS_PIN -1 // Optional, set to -1 if unused // HARDWARE UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the HW serial port you are using. Uncomment // this line if you are connecting the BLE to Leonardo/Micro or Flora // ---------------------------------------------------------------------------------------------- #ifdef Serial1 // this makes it not complain on compilation if there's no Serial1 #define BLUEFRUIT_HWSERIAL_NAME Serial1 #endif // SHARED UART SETTINGS // ---------------------------------------------------------------------------------------------- // The following sets the optional Mode pin, its recommended but not required // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_UART_MODE_PIN 12 // Set to -1 if unused // SHARED SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for HW and SW SPI communication. // SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when // using HW SPI. This should be used with nRF51822 based Bluefruit LE modules // that use SPI (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_CS 8 #define BLUEFRUIT_SPI_IRQ 7 #define BLUEFRUIT_SPI_RST 4 // Optional but recommended, set to -1 if unused // SOFTWARE SPI SETTINGS // ---------------------------------------------------------------------------------------------- // The following macros declare the pins to use for SW SPI communication. // This should be used with nRF51822 based Bluefruit LE modules that use SPI // (Bluefruit LE SPI Friend). // ---------------------------------------------------------------------------------------------- #define BLUEFRUIT_SPI_SCK 13 #define BLUEFRUIT_SPI_MISO 12 #define BLUEFRUIT_SPI_MOSI 11 ================================================ FILE: examples/uribeacon/uribeacon.ino ================================================ /********************************************************************* This is an example for our nRF51822 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include #include #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #if SOFTWARE_SERIAL_AVAILABLE #include #endif #include "BluefruitConfig.h" /*========================================================================= APPLICATION SETTINGS FACTORYRESET_ENABLE Perform a factory reset when running this sketch Enabling this will put your Bluefruit LE module in a 'known good' state and clear any config data set in previous sketches or projects, so running this at least once is a good idea. When deploying your project, however, you will want to disable factory reset by setting this value to 0.  If you are making changes to your Bluefruit LE device via AT commands, and those changes aren't persisting across resets, this is the reason why.  Factory reset will erase the non-volatile memory where config data is stored, setting it back to factory default values. -----------------------------------------------------------------------*/ #define FACTORYRESET_ENABLE 1 #define URL "http://www.adafruit.com" /*=========================================================================*/ // Create the bluefruit object, either software serial...uncomment these lines /* SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN); Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN); */ /* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */ // Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN); /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */ Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); /* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */ //Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO, // BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS, // BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST); // A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); } /**************************************************************************/ /*! @brief Sets up the HW an the BLE module (this function is called automatically on startup) */ /**************************************************************************/ void setup(void) { while (!Serial); // required for Flora & Micro delay(500); Serial.begin(115200); Serial.println(F("Adafruit Bluefruit UriBeacon Example")); Serial.println(F("------------------------------------")); /* Initialise the module */ Serial.print(F("Initialising the Bluefruit LE module: ")); if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") ); if ( FACTORYRESET_ENABLE ) { /* Perform a factory reset to make sure everything is in a known state */ Serial.println(F("Performing a factory reset: ")); if ( ! ble.factoryReset() ){ error(F("Couldn't factory reset")); } } /* Disable command echo from Bluefruit */ ble.echo(false); Serial.println("Requesting Bluefruit info:"); /* Print Bluefruit information */ ble.info(); // Prompt user to migrate to EddyStone Serial.println(F("Please consider to migrate to EddyStone since Google has retired uribeacon")); /* Set EddyStone URL beacon data */ Serial.println(F("Setting uri beacon to Adafruit website: ")); // Older firmware use AT+BLEURIBEACON command if (! ble.sendCommandCheckOK(F( "AT+BLEURIBEACON=" URL ))) { error(F("Couldnt set, is URL too long !?")); } Serial.println(F("**************************************************")); Serial.println(F("Please use Google Physical Web application to test")); Serial.println(F("**************************************************")); } /**************************************************************************/ /*! @brief Constantly poll for new command or response data */ /**************************************************************************/ void loop(void) { } /**************************************************************************/ /*! @brief Checks for user input (via the Serial Monitor) */ /**************************************************************************/ void getUserInput(char buffer[], uint8_t maxSize) { memset(buffer, 0, maxSize); while( Serial.available() == 0 ) { delay(1); } uint8_t count=0; do { count += Serial.readBytes(buffer+count, maxSize); delay(2); } while( (count < maxSize) && !(Serial.available() == 0) ); } ================================================ FILE: keywords.txt ================================================ ####################################### # Syntax Coloring Map For Bluefruit ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### Adafruit_BLE KEYWORD1 Adafruit_BluefruitLE_SPI KEYWORD1 Adafruit_BluefruitLE_UART KEYWORD1 Adafruit_ATParser KEYWORD1 Adafruit_BLEBattery KEYWORD1 Adafruit_BLEEddystone KEYWORD1 Adafruit_BLEGatt KEYWORD1 Adafruit_BLEMIDI KEYWORD1 Adafruit_FIFO KEYWORD1 TimeoutTimer KEYWORD1 ####################################### # Adafruit_BLE ####################################### reset KEYWORD2 factoryReset KEYWORD2 info KEYWORD2 echo KEYWORD2 isConnected KEYWORD2 isVersionAtLeast KEYWORD2 disconnect KEYWORD2 setAdvData KEYWORD2 writeNVM KEYWORD2 readNVM KEYWORD2 update KEYWORD2 writeBLEUart KEYWORD2 readBLEUart KEYWORD2 setDisconnectCallback KEYWORD2 setConnectCallback KEYWORD2 setBleUartRxCallback KEYWORD2 setBleMidiRxCallback KEYWORD2 setBleGattRxCallback KEYWORD2 sendCommandCheckOK KEYWORD2 sendCommandWithIntReply KEYWORD2 ####################################### # Adafruit_ATParser ####################################### atcommand KEYWORD2 atcommandIntReply KEYWORD2 atcommand_full KEYWORD2 getMode KEYWORD2 setMode KEYWORD2 verbose KEYWORD2 readline KEYWORD2 readline_parseInt KEYWORD2 waitForOK KEYWORD2 readraw KEYWORD2 printByteArray KEYWORD2 ####################################### # Adafruit_BLEBattery ####################################### update KEYWORD2 ####################################### # Adafruit_BLEEddystone ####################################### setURL KEYWORD2 startBroadcast KEYWORD2 stopBroadcast KEYWORD2 startConfigMode KEYWORD2 ####################################### # Adafruit_BLEGatt ####################################### addService KEYWORD2 addCharacteristic KEYWORD2 getChar KEYWORD2 getCharInt8 KEYWORD2 getCharInt16 KEYWORD2 getCharInt32 KEYWORD2 getCharStr KEYWORD2 setChar KEYWORD2 # Constants (LITERAL1) GATT_CHARS_PROPERTIES_BROADCAST LITERAL1 GATT_CHARS_PROPERTIES_READ LITERAL1 GATT_CHARS_PROPERTIES_WRITE_WO_RESP LITERAL1 GATT_CHARS_PROPERTIES_WRITE LITERAL1 GATT_CHARS_PROPERTIES_NOTIFY LITERAL1 GATT_CHARS_PROPERTIES_INDICATE LITERAL1 ####################################### # Adafruit_BLEMIDI ####################################### send KEYWORD2 send_n KEYWORD2 setRxCallback KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### BLUEFRUIT_MODE_COMMAND LITERAL1 BLUEFRUIT_MODE_DATA LITERAL1 ================================================ FILE: library.properties ================================================ name=Adafruit BluefruitLE nRF51 version=1.10.0 author=Adafruit maintainer=Adafruit sentence=Arduino library for nRF51822-based Adafruit Bluefruit LE modules paragraph=Arduino library for nRF51822-based Adafruit Bluefruit LE modules category=Communication url=https://github.com/adafruit/Adafruit_BluefruitLE_nRF51 architectures=* ================================================ FILE: utility/Adafruit_FIFO.cpp ================================================ /**************************************************************************/ /*! @file Adafruit_FIFO.cpp @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2015, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #include "Adafruit_FIFO.h" #include /******************************************************************************/ /*! @brief Constructor @param[in] buffer Memory location to store data @param[in] depth Maximum number of items can be hold in buffer @param[in] item_size Number of bytes of each item @param[in] overwrite Should the buffer is overwitten to the first item when it is full */ /******************************************************************************/ Adafruit_FIFO::Adafruit_FIFO(void* buffer, uint16_t depth, uint8_t item_size, bool overwrite) { m_buffer = (uint8_t*) buffer; m_depth = depth; m_item_size = item_size; m_overwritable = overwrite; m_count = m_wr_idx = m_rd_idx = 0; } /******************************************************************************/ /*! @brief Clear the FIFO */ /******************************************************************************/ void Adafruit_FIFO::clear(void) { m_rd_idx = m_wr_idx = m_count = 0; } /******************************************************************************/ /*! @brief Write an item to the FIFO @param[in] item Memory address of the item */ /******************************************************************************/ bool Adafruit_FIFO::write(void const* item) { if ( full() && !m_overwritable ) return false; memcpy( m_buffer + (m_wr_idx * m_item_size), item, m_item_size); m_wr_idx = (m_wr_idx + 1) % m_depth; if ( full() ) { m_rd_idx = m_wr_idx; // keep the full state (rd == wr && len = size) } else { m_count++; } return true; } /******************************************************************************/ /*! @brief Write array of items to the FIFO @param[in] data Memory address of the item's array @param[in] n Number of items to write @return Number of written items */ /******************************************************************************/ uint16_t Adafruit_FIFO::write_n(void const * data, uint16_t n) { if ( n == 0 ) return 0; uint8_t* buf = (uint8_t*) data; uint16_t len = 0; while( (len < n) && write(buf) ) { len++; buf += m_item_size; } return len; } /******************************************************************************/ /*! @brief Read an item from FIFO @param[in] buffer Memory address to store item */ /******************************************************************************/ bool Adafruit_FIFO::read(void* buffer) { if( empty() ) return false; memcpy(buffer, m_buffer + (m_rd_idx * m_item_size), m_item_size); m_rd_idx = (m_rd_idx + 1) % m_depth; m_count--; return true; } /******************************************************************************/ /*! @brief Read multiple items to an array @param[in] buffer Memory address of the item's array @param[in] n Number of items to read @return Number of read items */ /******************************************************************************/ uint16_t Adafruit_FIFO::read_n (void * buffer, uint16_t n) { if( n == 0 ) return 0; uint8_t* buf = (uint8_t*) buffer; uint16_t len = 0; while( (len < n) && read(buf) ) { len++; buf += m_item_size; } return len; } /******************************************************************************/ /*! @brief Read an item without removing it from the FIFO @param[in] buffer Memory address to store item */ /******************************************************************************/ bool Adafruit_FIFO::peek(void* buffer) { if( empty() ) return false; memcpy(buffer, m_buffer + (m_rd_idx * m_item_size), m_item_size); return true; } /******************************************************************************/ /*! @brief Read an item without removing it from the FIFO at the specific index @param[in] position Position to read from in the FIFO buffer @param[in] buffer Memory address to store item */ /******************************************************************************/ bool Adafruit_FIFO::peekAt(uint16_t position, void * p_buffer) { if( empty() || (position >= m_count) ) return false; uint16_t index = (m_rd_idx + position) % m_depth; // rd_idx is position=0 memcpy(p_buffer, m_buffer + (index * m_item_size), m_item_size); return true; } ================================================ FILE: utility/Adafruit_FIFO.h ================================================ /**************************************************************************/ /*! @file Adafruit_FIFO.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2015, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _Adafruit_FIFO_H_ #define _Adafruit_FIFO_H_ #include #include class Adafruit_FIFO { private: uint8_t* m_buffer ; ///< buffer pointer uint16_t m_depth ; ///< max items uint8_t m_item_size ; ///< size of each item bool m_overwritable ; volatile uint16_t m_count ; ///< number of items in queue volatile uint16_t m_wr_idx ; ///< write pointer volatile uint16_t m_rd_idx ; ///< read pointer public: // Constructor Adafruit_FIFO(void* buffer, uint16_t depth, uint8_t item_size, bool overwrite); void clear(void); bool peek(void* buffer); bool peekAt(uint16_t position, void * p_buffer); bool write(void const* item); uint16_t write_n(void const * data, uint16_t n); bool read(void* buffer); uint16_t read_n (void * buffer, uint16_t n); inline bool empty(void) { return m_count == 0; } inline bool full(void) { return m_count == m_depth; } inline uint16_t count(void) { return m_count; } inline uint16_t remaining(void) { return m_depth - m_count; } }; #endif /* _Adafruit_FIFO_H_ */ ================================================ FILE: utility/TimeoutTimer.h ================================================ /**************************************************************************/ /*! @file TimeoutTimer.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2014, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ /** * @{ */ #ifndef _TIMEOUT_TIMER_H_ #define _TIMEOUT_TIMER_H_ class TimeoutTimer { private: uint32_t start; uint32_t interval; public: TimeoutTimer() { start = millis(); interval = 0; } TimeoutTimer(uint32_t msec) { set(msec); } void set(uint32_t msec) { start = millis(); interval = msec; } bool expired(void) const { return (millis() - start) >= interval; } void restart(void) { start = millis(); } void reset(void) { start += interval; } // used for periodic invoke to prevent drift }; #endif /* _TIMEOUT_TIMER_H_ */ /** @} */ ================================================ FILE: utility/common_header.h ================================================ /**************************************************************************/ /*! @file common_header.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2016, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ #ifndef _COMMON_HEADER_H_ #define _COMMON_HEADER_H_ #include #include //--------------------------------------------------------------------+ // COMPILER //--------------------------------------------------------------------+ #define STRING_(x) #x // stringify without expand #define XSTRING_(x) STRING_(x) // expand then stringify #define STRING_CONCAT_(a, b) a##b // concat without expand #define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat #define ATTR_PACKED __attribute__ ((packed)) //--------------------------------------------------------------------+ // ASSERT & VERIFY //--------------------------------------------------------------------+ //#define ASSERT(condition, err) if ( !(condition) ) return err; //------------- Compile-time Assert -------------// #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ #define _ASSERT_COUNTER __COUNTER__ #else #define _ASSERT_COUNTER __LINE__ #endif #define ASSERT_STATIC_(const_expr) enum { XSTRING_CONCAT_(static_assert_, _ASSERT_COUNTER) = 1/(!!(const_expr)) } #define VERIFY_(condition) if ( !(condition) ) return false; #define VERIFY_RETURN_(condition, error) if ( !(condition) ) return error; //--------------------------------------------------------------------+ // INLINE FUNCTION //--------------------------------------------------------------------+ static inline bool is_within(uint32_t lower, uint32_t value, uint32_t upper) { return (lower <= value) && (value <= upper); } #endif /* _COMMON_HEADER_H_ */ ================================================ FILE: utility/errors.h ================================================ /******************************************************************************/ /*! @file errors.h @section LICENSE Software License Agreement (BSD License) Copyright (c) 2014, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /******************************************************************************/ #ifndef _ERRORS_H_ #define _ERRORS_H_ #ifdef __cplusplus extern "C" { #endif /******************************************************************************/ /*! @brief Standard error codes used throughout this codebase */ /******************************************************************************/ typedef enum { /*======================================================================= CUSTOM GLOBAL ERRORS 0x8000 .. 0x801F ----------------------------------------------------------------------- Custom global errors (not defined by Nordic) -----------------------------------------------------------------------*/ ERROR_INITFAILED = 0x8001, ///< Function or driver initialisation failed ERROR_NOT_INITIALISED = 0x8002, ///< Attempted to call a function in an unitialised device/driver ERROR_I2C_XFER_FAILED = 0x8003, ///< I2C transfer failure /*=======================================================================*/ /*======================================================================= SIMPLE BINARY PROTOCOL ERRORS 0x8020 .. 0x803F ----------------------------------------------------------------------- Errors relating to the simple binary protocol -----------------------------------------------------------------------*/ ERROR_SDEP_INVALIDMSGTYPE = 0x8021, ///< Unexpected msg type encountered ERROR_SDEP_INVALIDCOMMANDID = 0x8022, ///< Unknown or out of range command ID ERROR_SDEP_INVALIDPAYLOAD = 0x8023, ///< Message payload has a problem (invalid len, etc.) /*=======================================================================*/ /*======================================================================= COMMAND LINE INTERFACE ERRORS 0x8040 .. 0x805F ----------------------------------------------------------------------- Errors relating to the simple binary protocol -----------------------------------------------------------------------*/ ERROR_CLI_UNKNOWN_COMMAND = 0x8041, ///< Unknown Command entered ERROR_CLI_TOO_FEW_ARGUMENTS = 0x8042, ///< Too Few Arguments ERROR_CLI_TOO_MANY_ARGUMENTS = 0x8043, ///< Too Few Arguments /*=======================================================================*/ /*======================================================================= AT PARSER ERRORS 0x8060 .. 0x807F ----------------------------------------------------------------------- Errors relating to AT Command -----------------------------------------------------------------------*/ ERROR_AT_INVALID_INPUT = 0x8060, ERROR_AT_UNKNOWN_COMMAND = 0x8061, ERROR_AT_INVALID_PARAMETER = 0x8062, /*=======================================================================*/ /*======================================================================= NVM ERRORS 0x8080 .. 0x809F ----------------------------------------------------------------------- Errors relating to the NVM -----------------------------------------------------------------------*/ ERROR_NVM_BUSY = 0x8060, /*=======================================================================*/ /*======================================================================= OS Abstraction Layer 0x80A0 .. 0x80BF ----------------------------------------------------------------------- Errors relating to the NVM -----------------------------------------------------------------------*/ ERROR_OSAL_WAITING = 0x80A0, /*=======================================================================*/ /*======================================================================= NORDIC GLOBAL ERRORS 0x0000 .. 0x00FF ----------------------------------------------------------------------- Errors mapped from nrf_error.h -----------------------------------------------------------------------*/ ERROR_NONE = 0x0000, ///< Successful command ERROR_SVC_HANDLER_MISSING = 0x0001, ///< SVC handler is missing ERROR_SOFTDEVICE_NOT_ENABLED = 0x0002, ///< SoftDevice has not been enabled ERROR_INTERNAL = 0x0003, ///< Internal Error ERROR_NO_MEM = 0x0004, ///< No Memory for operation ERROR_NOT_FOUND = 0x0005, ///< Not found ERROR_NOT_SUPPORTED = 0x0006, ///< Not supported ERROR_INVALID_PARAM = 0x0007, ///< Invalid Parameter ERROR_INVALID_STATE = 0x0008, ///< Invalid state, operation disallowed in this state ERROR_INVALID_LENGTH = 0x0009, ///< Invalid Length ERROR_INVALID_FLAGS = 0x000A, ///< Invalid Flags ERROR_INVALID_DATA = 0x000B, ///< Invalid Data ERROR_DATA_SIZE = 0x000C, ///< Data size exceeds limit ERROR_TIMEOUT = 0x000D, ///< Operation timed out ERROR_NULL = 0x000E, ///< Null Pointer ERROR_FORBIDDEN = 0x000F, ///< Forbidden Operation ERROR_INVALID_ADDR = 0x0010, ///< Bad Memory Address ERROR_BUSY = 0x0011, ///< Busy /*=======================================================================*/ /*======================================================================= NORDIC SDM ERRORS 0x1000 .. 0x1FFF ----------------------------------------------------------------------- Errors based on Nordic's SDM nrf_error_sdm.h -----------------------------------------------------------------------*/ ERROR_SDM_LFCLK_SOURCE_UNKNOWN = 0x1000, ///< Unknown lfclk source ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION = 0x1001, ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts) ERROR_SDM_INCORRECT_CLENR0 = 0x1002, ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing) /*=======================================================================*/ /*======================================================================= NORDIC SOC ERRORS 0x2000 .. 0x2FFF ----------------------------------------------------------------------- Errors based on Nordic's nrf_error_soc.h -----------------------------------------------------------------------*/ /* Mutex Errors */ ERROR_SOC_MUTEX_ALREADY_TAKEN = 0x2000, ///< Mutex already taken /* NVIC errors */ ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE = 0x2001, ///< NVIC interrupt not available ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED = 0x2002, ///< NVIC interrupt priority not allowed ERROR_SOC_NVIC_SHOULD_NOT_RETURN = 0x2003, ///< NVIC should not return /* Power errors */ ERROR_SOC_POWER_MODE_UNKNOWN = 0x2004, ///< Power mode unknown ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN = 0x2005, ///< Power POF threshold unknown ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN = 0x2006, ///< Power off should not return /* Rand errors */ ERROR_SOC_RAND_NOT_ENOUGH_VALUES = 0x2007, ///< RAND not enough values /* PPI errors */ ERROR_SOC_PPI_INVALID_CHANNEL = 0x2008, ///< Invalid PPI Channel ERROR_SOC_PPI_INVALID_GROUP = 0x2009, ///< Invalid PPI Group /*=======================================================================*/ /*======================================================================= NORDIC BLE ERRORS 0x3000 .. 0x3FFF ----------------------------------------------------------------------- Errors based on Nordic's ble_err.h -----------------------------------------------------------------------*/ ERROR_BLE_NOT_ENABLED = 0x3001, ERROR_BLE_INVALID_CONN_HANDLE = 0x3002, ///< Invalid connection handle. ERROR_BLE_INVALID_ATTR_HANDLE = 0x3003, ///< Invalid attribute handle. ERROR_BLE_NO_TX_BUFFERS = 0x3004, ///< Buffer capacity exceeded. /* L2CAP */ ERROR_BLE_L2CAP_CID_IN_USE = 0x3100, ///< CID already in use. /* GAP */ ERROR_BLE_GAP_UUID_LIST_MISMATCH = 0x3200, ///< UUID list does not contain an integral number of UUIDs. ERROR_BLE_GAP_DISCOVERABLE_WITH_WHITELIST = 0x3201, ///< Use of Whitelist not permitted with discoverable advertising. ERROR_BLE_GAP_INVALID_BLE_ADDR = 0x3202, ///< The upper two bits of the address do not correspond to the specified address type. /* GATTC */ ERROR_BLE_GATTC_PROC_NOT_PERMITTED = 0x3300, /* GATTS */ ERROR_BLEGATTS_INVALID_ATTR_TYPE = 0x3400, ///< Invalid attribute type. ERROR_BLEGATTS_SYS_ATTR_MISSING = 0x3401, ///< System Attributes missing. /*=======================================================================*/ } err_t; #ifdef __cplusplus } #endif #endif /* _ERROR_H_ */ ================================================ FILE: utility/sdep.h ================================================ /******************************************************************************/ /*! @file sdep.h @author hathach @section LICENSE Software License Agreement (BSD License) Copyright (c) 2013, K. Townsend (microBuilder.eu) Copyright (c) 2014, Adafruit Industries (adafruit.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /******************************************************************************/ #ifndef _SDEP_H_ #define _SDEP_H_ #include "common_header.h" #define SDEP_MAX_PACKETSIZE 16 // Maximum payload per packet /******************************************************************************/ /*! This enumeration is used to make sure that each command has a unique ID, and is used to create the command lookup table enum further down */ /******************************************************************************/ typedef enum { SDEP_CMDTYPE_INITIALIZE = 0xBEEF, /**< Controls the on board LED(s) */ SDEP_CMDTYPE_AT_WRAPPER = 0x0A00, SDEP_CMDTYPE_BLE_UARTTX = 0x0A01, SDEP_CMDTYPE_BLE_UARTRX = 0x0A02, } sdepCmdType_t; /******************************************************************************/ /*! The first byte of every transfer defines the message type */ /******************************************************************************/ typedef enum { SDEP_MSGTYPE_COMMAND = 0x10, SDEP_MSGTYPE_RESPONSE = 0x20, SDEP_MSGTYPE_ALERT = 0x40, SDEP_MSGTYPE_ERROR = 0x80 } sdepMsgType_t; /******************************************************************************/ /*! 4-byte header for SDEP messages */ /******************************************************************************/ typedef struct ATTR_PACKED { uint8_t msg_type; // 8-bit message type indicator (sdepMsgType_t) union { uint16_t cmd_id; // 16-bit command ID struct { uint8_t cmd_id_low; uint8_t cmd_id_high; }; }; struct ATTR_PACKED { uint8_t length : 7; // Payload length (for this packet) uint8_t more_data : 1; // 'more' bit for multiple packet transfers }; } sdepMsgHeader_t; /******************************************************************************/ /*! SDEP command message */ /******************************************************************************/ typedef struct ATTR_PACKED { sdepMsgHeader_t header; uint8_t payload[SDEP_MAX_PACKETSIZE]; } sdepMsgCommand_t; /******************************************************************************/ /*! Response message struct (same as sdepMsgCommand_t) */ /******************************************************************************/ typedef sdepMsgCommand_t sdepMsgResponse_t; /******************************************************************************/ /*! Alert message struct */ /******************************************************************************/ typedef sdepMsgCommand_t sdepMsgAlert_t; #endif