Skip to content

Commit 240e564

Browse files
Merge pull request firmata#393 from cstawarz/bluefruit_le_spi
Add support for Adafruit Feather M0 Bluefruit LE to StandardFirmataBLE
2 parents a1a3067 + 5b8b9f0 commit 240e564

File tree

4 files changed

+235
-23
lines changed

4 files changed

+235
-23
lines changed

examples/StandardFirmataBLE/StandardFirmataBLE.ino

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@
5656
// the minimum interval for sampling analog input
5757
#define MINIMUM_SAMPLING_INTERVAL 1
5858

59-
// min cannot be < 0x0006. Adjust max if necessary
60-
#define FIRMATA_BLE_MIN_INTERVAL 0x0006 // 7.5ms (7.5 / 1.25)
61-
#define FIRMATA_BLE_MAX_INTERVAL 0x0018 // 30ms (30 / 1.25)
62-
6359
/*==============================================================================
6460
* GLOBAL VARIABLES
6561
*============================================================================*/
@@ -777,9 +773,9 @@ void setup()
777773
// set the BLE connection interval - this is the fastest interval you can read inputs
778774
stream.setConnectionInterval(FIRMATA_BLE_MIN_INTERVAL, FIRMATA_BLE_MAX_INTERVAL);
779775
// set how often the BLE TX buffer is flushed (if not full)
780-
stream.setFlushInterval(FIRMATA_BLE_MAX_INTERVAL);
776+
stream.setFlushInterval(FIRMATA_BLE_TXBUFFER_FLUSH_INTERVAL);
781777

782-
#ifdef BLE_REQ
778+
#ifdef IS_IGNORE_BLE_PINS
783779
for (byte i = 0; i < TOTAL_PINS; i++) {
784780
if (IS_IGNORE_BLE_PINS(i)) {
785781
Firmata.setPinMode(i, PIN_MODE_IGNORE);

examples/StandardFirmataBLE/bleConfig.h

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,37 @@
55
* need a unique ble local name (see below). If you are using another supported BLE board or shield,
66
* follow the instructions for the specific board or shield below.
77
*
8-
* Make sure you have the Intel Curie Boards package v1.0.6 or higher installed via the Arduino
8+
* Make sure you have the Intel Curie Boards package v2.0.2 or higher installed via the Arduino
99
* Boards Manager.
1010
*
1111
* Supported boards and shields:
1212
* - Arduino 101 (recommended)
1313
* - RedBearLab BLE Shield (v2) ** to be verified **
1414
* - RedBearLab BLE Nano ** works with modifications **
15+
* - Adafruit Feather M0 Bluefruit LE
1516
*
1617
*================================================================================================*/
1718

1819
// change this to a unique name per board if running StandardFirmataBLE on multiple boards
1920
// within the same physical space
2021
#define FIRMATA_BLE_LOCAL_NAME "FIRMATA"
2122

23+
/*
24+
* Arduino 101
25+
*
26+
* Make sure you have the Intel Curie Boards package v2.0.2 or higher installed via the Arduino
27+
* Boards Manager.
28+
*
29+
* Test script: https://gist.github.com/soundanalogous/927360b797574ed50e27
30+
*/
31+
#ifdef _VARIANT_ARDUINO_101_X_
32+
// After conversion to units of 1.25ms, both values must be between
33+
// 0x0006 (7.5ms) and 0x0c80 (4s)
34+
#define FIRMATA_BLE_MIN_INTERVAL 8 // ( 8 * 1000) / 1250 == 0x06 -> 7.5ms
35+
#define FIRMATA_BLE_MAX_INTERVAL 30 // (30 * 1000) / 1250 == 0x18 -> 30ms
36+
#endif
37+
38+
2239
/*
2340
* RedBearLab BLE Shield
2441
*
@@ -36,37 +53,76 @@
3653
//#define REDBEAR_BLE_SHIELD
3754

3855
#ifdef REDBEAR_BLE_SHIELD
39-
#include <SPI.h>
40-
#include <BLEPeripheral.h>
41-
#include "utility/BLEStream.h"
42-
4356
#define BLE_REQ 9
4457
#define BLE_RDY 8
4558
#define BLE_RST 4 // 4 or 7 via jumper on shield
59+
#endif
4660

47-
BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
61+
62+
/*
63+
* Adafruit Feather M0 Bluefruit LE
64+
*
65+
* If you are using an Adafruit Feather M0 Bluefruit LE, uncomment the define below.
66+
* This configuration should also work with other Bluefruit LE boards/modules that communicate
67+
* with the nRF51822 via SPI (e.g. Bluefruit LE SPI Friend, Bluefruit LE Shield), although
68+
* you may need to change the values of BLE_SPI_CS, BLE_SPI_IRQ, and/or BLE_SPI_RST below.
69+
*
70+
* You will need to install a lightly-modified version of the Adafruit BluefruitLE nRF51
71+
* package, available at:
72+
* https://github.com/cstawarz/Adafruit_BluefruitLE_nRF51/archive/firmata_fixes.zip
73+
*/
74+
//#define BLUEFRUIT_LE_SPI
75+
76+
#ifdef BLUEFRUIT_LE_SPI
77+
// Both values must be between 10ms and 4s
78+
#define FIRMATA_BLE_MIN_INTERVAL 10 // 10ms
79+
#define FIRMATA_BLE_MAX_INTERVAL 20 // 20ms
80+
81+
#define BLE_SPI_CS 8
82+
#define BLE_SPI_IRQ 7
83+
#define BLE_SPI_RST 4
84+
#endif
85+
86+
87+
/*
88+
* Generic settings
89+
*/
90+
#if !defined(FIRMATA_BLE_MIN_INTERVAL) && !defined(FIRMATA_BLE_MAX_INTERVAL)
91+
// These values apply to all devices using the Arduino BLEPeripheral library
92+
// with a Nordic nRF8001 or nRF51822. Both values must be between
93+
// 0x0006 (7.5ms) and 0x0c80 (4s).
94+
#define FIRMATA_BLE_MIN_INTERVAL 0x0006 // 7.5ms (7.5 / 1.25)
95+
#define FIRMATA_BLE_MAX_INTERVAL 0x0018 // 30ms (30 / 1.25)
96+
#endif
97+
98+
#if !defined(FIRMATA_BLE_TXBUFFER_FLUSH_INTERVAL)
99+
#define FIRMATA_BLE_TXBUFFER_FLUSH_INTERVAL 30 // 30ms
48100
#endif
49101

50102

51103
/*==================================================================================================
52104
* END BLE CONFIGURATION - you should not need to change anything below this line
53105
*================================================================================================*/
54106

55-
/*
56-
* Arduino 101
57-
*
58-
* Make sure you have the Intel Curie Boards package v1.0.6 or higher installed via the Arduino
59-
* Boards Manager.
60-
*
61-
* Test script: https://gist.github.com/soundanalogous/927360b797574ed50e27
62-
*/
63107
#ifdef _VARIANT_ARDUINO_101_X_
64-
#include <CurieBLE.h>
65108
#include "utility/BLEStream.h"
66109
BLEStream stream;
67110
#endif
68111

69112

113+
#ifdef REDBEAR_BLE_SHIELD
114+
#include <SPI.h>
115+
#include "utility/BLEStream.h"
116+
BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
117+
#endif
118+
119+
120+
#ifdef BLUEFRUIT_LE_SPI
121+
#include "utility/BluefruitLE_SPI_Stream.h"
122+
BluefruitLE_SPI_Stream stream(BLE_SPI_CS, BLE_SPI_IRQ, BLE_SPI_RST);
123+
#endif
124+
125+
70126
/*
71127
* RedBearLab BLE Nano (with default switch settings)
72128
*
@@ -81,7 +137,6 @@ BLEStream stream;
81137
* the pins are currently mapped in Firmata only for the default (factory) jumper settings.
82138
*/
83139
// #ifdef BLE_NANO
84-
// #include <BLEPeripheral.h>
85140
// #include "utility/BLEStream.h"
86141
// BLEStream stream;
87142
// #endif
@@ -96,7 +151,6 @@ BLEStream stream;
96151
*/
97152
// #if defined(BLEND_MICRO) || defined(BLEND)
98153
// #include <SPI.h>
99-
// #include <BLEPeripheral.h>
100154
// #include "utility/BLEStream.h"
101155

102156
// #define BLE_REQ 6
@@ -109,4 +163,6 @@ BLEStream stream;
109163

110164
#if defined(BLE_REQ) && defined(BLE_RDY) && defined(BLE_RST)
111165
#define IS_IGNORE_BLE_PINS(p) ((p) == BLE_REQ || (p) == BLE_RDY || (p) == BLE_RST)
166+
#elif defined(BLE_SPI_CS) && defined(BLE_SPI_IRQ) && defined(BLE_SPI_RST)
167+
#define IS_IGNORE_BLE_PINS(p) ((p) == BLE_SPI_CS || (p) == BLE_SPI_IRQ || (p) == BLE_SPI_RST)
112168
#endif

utility/BluefruitLE_SPI_Stream.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
* Implementation is in BluefruitLE_SPI_Stream.h to avoid linker issues.
3+
*/

utility/BluefruitLE_SPI_Stream.h

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
BluefruitLE_SPI_Stream.h
3+
4+
Documentation for the various AT commands used below is available at
5+
https://learn.adafruit.com/adafruit-feather-m0-bluefruit-le/at-commands
6+
*/
7+
8+
#ifndef _BLUEFRUIT_LE_SPI_STREAM_H_
9+
#define _BLUEFRUIT_LE_SPI_STREAM_H_
10+
11+
#include <Adafruit_BluefruitLE_SPI.h>
12+
13+
14+
class BluefruitLE_SPI_Stream : public Stream
15+
{
16+
public:
17+
BluefruitLE_SPI_Stream(int8_t csPin, int8_t irqPin, int8_t rstPin);
18+
19+
void setLocalName(const char *localName);
20+
void setConnectionInterval(unsigned short minConnInterval, unsigned short maxConnInterval);
21+
void setFlushInterval(int flushInterval);
22+
23+
void begin();
24+
bool poll();
25+
void end();
26+
27+
// Print overrides
28+
size_t write(uint8_t byte);
29+
using Print::write; // Expose other write variants
30+
31+
// Stream overrides
32+
int available();
33+
int read();
34+
int peek();
35+
void flush();
36+
37+
private:
38+
Adafruit_BluefruitLE_SPI ble;
39+
40+
String localName;
41+
unsigned short minConnInterval;
42+
unsigned short maxConnInterval;
43+
44+
uint8_t txBuffer[SDEP_MAX_PACKETSIZE];
45+
size_t txCount;
46+
};
47+
48+
49+
BluefruitLE_SPI_Stream::BluefruitLE_SPI_Stream(int8_t csPin, int8_t irqPin, int8_t rstPin) :
50+
ble(csPin, irqPin, rstPin),
51+
minConnInterval(0),
52+
maxConnInterval(0),
53+
txCount(0)
54+
{ }
55+
56+
void BluefruitLE_SPI_Stream::setLocalName(const char *localName)
57+
{
58+
this->localName = localName;
59+
}
60+
61+
void BluefruitLE_SPI_Stream::setConnectionInterval(unsigned short minConnInterval, unsigned short maxConnInterval)
62+
{
63+
this->minConnInterval = minConnInterval;
64+
this->maxConnInterval = maxConnInterval;
65+
}
66+
67+
void BluefruitLE_SPI_Stream::setFlushInterval(int flushInterval)
68+
{
69+
// Not used
70+
}
71+
72+
void BluefruitLE_SPI_Stream::begin()
73+
{
74+
// Initialize the SPI interface
75+
ble.begin();
76+
77+
// Perform a factory reset to make sure everything is in a known state
78+
ble.factoryReset();
79+
80+
// Disable command echo from Bluefruit
81+
ble.echo(false);
82+
83+
// Change the MODE LED to indicate BLE UART activity
84+
ble.println("AT+HWMODELED=BLEUART");
85+
86+
// Set local name
87+
if (localName.length() > 0) {
88+
ble.print("AT+GAPDEVNAME=");
89+
ble.println(localName);
90+
}
91+
92+
// Set connection interval
93+
if (minConnInterval > 0 && maxConnInterval > 0) {
94+
ble.print("AT+GAPINTERVALS=");
95+
ble.print(minConnInterval);
96+
ble.print(",");
97+
ble.print(maxConnInterval);
98+
ble.println(",,,");
99+
}
100+
101+
// Disable real and simulated mode switch (i.e. "+++") command
102+
ble.println("AT+MODESWITCHEN=local,0");
103+
ble.enableModeSwitchCommand(false);
104+
105+
// Switch to data mode
106+
ble.setMode(BLUEFRUIT_MODE_DATA);
107+
}
108+
109+
bool BluefruitLE_SPI_Stream::poll()
110+
{
111+
// If there's outgoing data in the buffer, just send it. The firmware on
112+
// the nRF51822 will decide when to transmit the data in its TX FIFO.
113+
if (txCount) flush();
114+
115+
// In order to check for a connection, we would need to switch from data to
116+
// command mode and back again. However, due to the internal workings of
117+
// Adafruit_BluefruitLE_SPI, this can lead to unread incoming data being
118+
// lost. Therefore, we always return true.
119+
return true;
120+
}
121+
122+
void BluefruitLE_SPI_Stream::end()
123+
{
124+
flush();
125+
ble.end();
126+
}
127+
128+
size_t BluefruitLE_SPI_Stream::write(uint8_t byte)
129+
{
130+
txBuffer[txCount++] = byte;
131+
if (txCount == sizeof(txBuffer)) flush();
132+
return 1;
133+
}
134+
135+
int BluefruitLE_SPI_Stream::available()
136+
{
137+
return ble.available();
138+
}
139+
140+
int BluefruitLE_SPI_Stream::read()
141+
{
142+
return ble.read();
143+
}
144+
145+
int BluefruitLE_SPI_Stream::peek()
146+
{
147+
return ble.peek();
148+
}
149+
150+
void BluefruitLE_SPI_Stream::flush()
151+
{
152+
ble.write(txBuffer, txCount);
153+
txCount = 0;
154+
}
155+
156+
157+
#endif // _BLUEFRUIT_LE_SPI_STREAM_H_

0 commit comments

Comments
 (0)