Skip to content

Commit c2e8da3

Browse files
committed
Added support for the Adafruit Feather M0 Bluefruit LE (and potentially other Bluefruit LE boards/modules that communicate with the nRF51822 via SPI) to StandardFirmataBLE
1 parent e3a2932 commit c2e8da3

File tree

4 files changed

+165
-1
lines changed

4 files changed

+165
-1
lines changed

examples/StandardFirmataBLE/StandardFirmataBLE.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ void setup()
768768
Firmata.attach(START_SYSEX, sysexCallback);
769769
Firmata.attach(SYSTEM_RESET, systemResetCallback);
770770

771-
#ifdef BLE_REQ
771+
#ifdef IS_IGNORE_BLE_PINS
772772
for (byte i = 0; i < TOTAL_PINS; i++) {
773773
if (IS_IGNORE_BLE_PINS(i)) {
774774
Firmata.setPinMode(i, PIN_MODE_IGNORE);

examples/StandardFirmataBLE/bleConfig.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
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

@@ -58,6 +59,31 @@
5859
#endif
5960

6061

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+
6187
/*
6288
* Generic settings
6389
*/
@@ -93,6 +119,12 @@ BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
93119
#endif
94120

95121

122+
#ifdef BLUEFRUIT_LE_SPI
123+
#include "utility/BluefruitLE_SPI_Stream.h"
124+
BluefruitLE_SPI_Stream stream(BLE_SPI_CS, BLE_SPI_IRQ, BLE_SPI_RST);
125+
#endif
126+
127+
96128
/*
97129
* RedBearLab BLE Nano (with default switch settings)
98130
*
@@ -133,4 +165,6 @@ BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
133165

134166
#if defined(BLE_REQ) && defined(BLE_RDY) && defined(BLE_RST)
135167
#define IS_IGNORE_BLE_PINS(p) ((p) == BLE_REQ || (p) == BLE_RDY || (p) == BLE_RST)
168+
#elif defined(BLE_SPI_CS) && defined(BLE_SPI_IRQ) && defined(BLE_SPI_RST)
169+
#define IS_IGNORE_BLE_PINS(p) ((p) == BLE_SPI_CS || (p) == BLE_SPI_IRQ || (p) == BLE_SPI_RST)
136170
#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: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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 begin();
20+
bool poll();
21+
void end();
22+
23+
// Print overrides
24+
size_t write(uint8_t byte);
25+
using Print::write; // Expose other write variants
26+
27+
// Stream overrides
28+
int available();
29+
int read();
30+
int peek();
31+
void flush();
32+
33+
private:
34+
Adafruit_BluefruitLE_SPI ble;
35+
36+
uint8_t txBuffer[SDEP_MAX_PACKETSIZE];
37+
size_t txCount;
38+
};
39+
40+
41+
BluefruitLE_SPI_Stream::BluefruitLE_SPI_Stream(int8_t csPin, int8_t irqPin, int8_t rstPin) :
42+
ble(csPin, irqPin, rstPin),
43+
txCount(0)
44+
{ }
45+
46+
void BluefruitLE_SPI_Stream::begin()
47+
{
48+
// Initialize the SPI interface
49+
ble.begin();
50+
51+
// Perform a factory reset to make sure everything is in a known state
52+
ble.factoryReset();
53+
54+
// Disable command echo from Bluefruit
55+
ble.echo(false);
56+
57+
// Change the MODE LED to indicate BLE UART activity
58+
ble.println("AT+HWMODELED=BLEUART");
59+
60+
// Set local name
61+
ble.print("AT+GAPDEVNAME=");
62+
ble.println(FIRMATA_BLE_LOCAL_NAME);
63+
64+
// Set connection interval
65+
ble.print("AT+GAPINTERVALS=");
66+
ble.print(FIRMATA_BLE_MIN_INTERVAL);
67+
ble.print(",");
68+
ble.print(FIRMATA_BLE_MAX_INTERVAL);
69+
ble.println(",,,");
70+
71+
// Disable real and simulated mode switch (i.e. "+++") command
72+
ble.println("AT+MODESWITCHEN=local,0");
73+
ble.enableModeSwitchCommand(false);
74+
75+
// Switch to data mode
76+
ble.setMode(BLUEFRUIT_MODE_DATA);
77+
}
78+
79+
bool BluefruitLE_SPI_Stream::poll()
80+
{
81+
// If there's outgoing data in the buffer, just send it. The firmware on
82+
// the nRF51822 will decide when to transmit the data in its TX FIFO.
83+
if (txCount) flush();
84+
85+
// In order to check for a connection, we would need to switch from data to
86+
// command mode and back again. However, due to the internal workings of
87+
// Adafruit_BluefruitLE_SPI, this can lead to unread incoming data being
88+
// lost. Therefore, we always return true.
89+
return true;
90+
}
91+
92+
void BluefruitLE_SPI_Stream::end()
93+
{
94+
flush();
95+
ble.end();
96+
}
97+
98+
size_t BluefruitLE_SPI_Stream::write(uint8_t byte)
99+
{
100+
txBuffer[txCount++] = byte;
101+
if (txCount == sizeof(txBuffer)) flush();
102+
return 1;
103+
}
104+
105+
int BluefruitLE_SPI_Stream::available()
106+
{
107+
return ble.available();
108+
}
109+
110+
int BluefruitLE_SPI_Stream::read()
111+
{
112+
return ble.read();
113+
}
114+
115+
int BluefruitLE_SPI_Stream::peek()
116+
{
117+
return ble.peek();
118+
}
119+
120+
void BluefruitLE_SPI_Stream::flush()
121+
{
122+
ble.write(txBuffer, txCount);
123+
txCount = 0;
124+
}
125+
126+
127+
#endif // _BLUEFRUIT_LE_SPI_STREAM_H_

0 commit comments

Comments
 (0)