Skip to content

Commit 69e786c

Browse files
Merge pull request #287 from andreagilardoni/ble-vhci-over-spi
Changing BLE hci transport
2 parents 0788453 + 31616ac commit 69e786c

File tree

5 files changed

+345
-1
lines changed

5 files changed

+345
-1
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
Repeating WiFi Web Client + BLE Led
3+
4+
This sketch connects to a a web server and makes a request
5+
using a WiFi equipped Arduino board.
6+
7+
Additionally this example creates a Bluetooth® Low Energy peripheral with service that contains a
8+
characteristic to control an LED.
9+
10+
You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
11+
nRF Connect (Android), to interact with the services and characteristics
12+
created in this sketch.
13+
14+
This code is in the public domain.
15+
*/
16+
17+
#include <SPI.h>
18+
#include <WiFiNINA.h>
19+
#include "arduino_secrets.h"
20+
21+
#include <ArduinoBLE.h>
22+
#include <utility/HCI.h>
23+
24+
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // Bluetooth® Low Energy LED Service
25+
26+
// Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
27+
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
28+
const int ledPin = LED_BUILTIN; // pin to use for the LED
29+
30+
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
31+
char ssid[] = SECRET_SSID; // your network SSID (name)
32+
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
33+
int keyIndex = 0; // your network key index number (needed only for WEP)
34+
35+
int status = WL_IDLE_STATUS;
36+
37+
// Initialize the WiFi client library
38+
WiFiClient client;
39+
40+
// server address:
41+
char server[] = "example.org";
42+
//IPAddress server(64,131,82,241);
43+
44+
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
45+
const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds
46+
47+
void setup() {
48+
//Initialize serial and wait for port to open:
49+
Serial.begin(9600);
50+
while (!Serial) {
51+
; // wait for serial port to connect. Needed for native USB port only
52+
}
53+
54+
// set LED pin to output mode
55+
pinMode(ledPin, OUTPUT);
56+
57+
// begin initialization
58+
if (!BLE.begin()) {
59+
Serial.println("starting Bluetooth® Low Energy module failed!");
60+
61+
while (1);
62+
}
63+
64+
// set advertised local name and service UUID:
65+
BLE.setLocalName("LED");
66+
BLE.setAdvertisedService(ledService);
67+
68+
// add the characteristic to the service
69+
ledService.addCharacteristic(switchCharacteristic);
70+
71+
// add service
72+
BLE.addService(ledService);
73+
74+
// set the initial value for the characeristic:
75+
switchCharacteristic.writeValue(0);
76+
77+
// start advertising
78+
BLE.advertise();
79+
80+
Serial.println("BLE LED Peripheral");
81+
82+
// check for the WiFi module:
83+
if (WiFi.status() == WL_NO_MODULE) {
84+
Serial.println("Communication with WiFi module failed!");
85+
// don't continue
86+
while (true);
87+
}
88+
89+
String fv = WiFi.firmwareVersion();
90+
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
91+
Serial.println("Please upgrade the firmware");
92+
}
93+
94+
// attempt to connect to WiFi network:
95+
while (status != WL_CONNECTED) {
96+
Serial.print("Attempting to connect to SSID: ");
97+
Serial.println(ssid);
98+
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
99+
status = WiFi.begin(ssid, pass);
100+
101+
// wait 10 seconds for connection:
102+
delay(10000);
103+
}
104+
// you're connected now, so print out the status:
105+
printWifiStatus();
106+
}
107+
108+
void loop() {
109+
// if there's incoming data from the net connection.
110+
// send it out the serial port. This is for debugging
111+
// purposes only:
112+
while (client.available()) {
113+
char c = client.read();
114+
Serial.write(c);
115+
}
116+
117+
// if ten seconds have passed since your last connection,
118+
// then connect again and send data:
119+
if (millis() - lastConnectionTime > postingInterval) {
120+
httpRequest();
121+
}
122+
123+
// listen for Bluetooth® Low Energy peripherals to connect:
124+
BLEDevice central = BLE.central();
125+
126+
// if a central is connected to peripheral:
127+
if (central) {
128+
Serial.print("Connected to central: ");
129+
// print the central's MAC address:
130+
Serial.println(central.address());
131+
132+
// while the central is still connected to peripheral:
133+
while (central.connected()) {
134+
// if the remote device wrote to the characteristic,
135+
// use the value to control the LED:
136+
if (switchCharacteristic.written()) {
137+
if (switchCharacteristic.value()) { // any value other than 0
138+
Serial.println("LED on");
139+
digitalWrite(ledPin, HIGH); // will turn the LED on
140+
} else { // a 0 value
141+
Serial.println(F("LED off"));
142+
digitalWrite(ledPin, LOW); // will turn the LED off
143+
}
144+
}
145+
}
146+
147+
// when the central disconnects, print it out:
148+
Serial.print(F("Disconnected from central: "));
149+
Serial.println(central.address());
150+
}
151+
}
152+
153+
// this method makes a HTTP connection to the server:
154+
void httpRequest() {
155+
// close any connection before send a new request.
156+
// This will free the socket on the NINA module
157+
client.stop();
158+
159+
// if there's a successful connection:
160+
if (client.connect(server, 80)) {
161+
Serial.println("connecting...");
162+
// send the HTTP GET request:
163+
client.println("GET / HTTP/1.1");
164+
client.println("Host: example.org");
165+
client.println("User-Agent: ArduinoWiFi/1.1");
166+
client.println("Connection: close");
167+
client.println();
168+
169+
// note the time that the connection was made:
170+
lastConnectionTime = millis();
171+
} else {
172+
// if you couldn't make a connection:
173+
Serial.println("connection failed");
174+
}
175+
}
176+
177+
178+
void printWifiStatus() {
179+
// print the SSID of the network you're attached to:
180+
Serial.print("SSID: ");
181+
Serial.println(WiFi.SSID());
182+
183+
// print your board's IP address:
184+
IPAddress ip = WiFi.localIP();
185+
Serial.print("IP Address: ");
186+
Serial.println(ip);
187+
188+
// print the received signal strength:
189+
long rssi = WiFi.RSSI();
190+
Serial.print("signal strength (RSSI):");
191+
Serial.print(rssi);
192+
Serial.println(" dBm");
193+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""

src/utility/wifi_drv.cpp

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ void WiFiDrv::wifiDriverInit()
113113

114114
void WiFiDrv::wifiDriverDeinit()
115115
{
116-
SpiDrv::end();
117116
}
118117

119118
int8_t WiFiDrv::wifiSetNetwork(const char* ssid, uint8_t ssid_len)
@@ -1663,5 +1662,141 @@ PreferenceType WiFiDrv::prefGetType(const char * key) {
16631662
return type;
16641663
}
16651664

1665+
int WiFiDrv::bleBegin() {
1666+
WAIT_FOR_SLAVE_SELECT();
1667+
1668+
SpiDrv::sendCmd(BLE_BEGIN, PARAM_NUMS_0);
1669+
1670+
SpiDrv::spiSlaveDeselect();
1671+
//Wait the reply elaboration
1672+
SpiDrv::waitForSlaveReady();
1673+
SpiDrv::spiSlaveSelect();
1674+
1675+
uint8_t len = 1;
1676+
uint8_t result = 0;
1677+
SpiDrv::waitResponseCmd(BLE_BEGIN, PARAM_NUMS_1, (uint8_t*)&result, &len);
1678+
SpiDrv::spiSlaveDeselect();
1679+
1680+
return result == 0;
1681+
}
1682+
1683+
void WiFiDrv::bleEnd() {
1684+
WAIT_FOR_SLAVE_SELECT();
1685+
1686+
SpiDrv::sendCmd(BLE_END, PARAM_NUMS_0);
1687+
1688+
SpiDrv::spiSlaveDeselect();
1689+
//Wait the reply elaboration
1690+
SpiDrv::waitForSlaveReady();
1691+
SpiDrv::spiSlaveSelect();
1692+
1693+
uint8_t len = 1;
1694+
uint8_t result = 0;
1695+
SpiDrv::waitResponseCmd(BLE_END, PARAM_NUMS_1, (uint8_t*)&result, &len);
1696+
SpiDrv::spiSlaveDeselect();
1697+
}
1698+
1699+
int WiFiDrv::bleAvailable() {
1700+
WAIT_FOR_SLAVE_SELECT();
1701+
uint16_t result = 0;
1702+
1703+
SpiDrv::sendCmd(BLE_AVAILABLE, PARAM_NUMS_0);
1704+
1705+
SpiDrv::spiSlaveDeselect();
1706+
//Wait the reply elaboration
1707+
SpiDrv::waitForSlaveReady();
1708+
SpiDrv::spiSlaveSelect();
1709+
1710+
uint8_t len = 2;
1711+
SpiDrv::waitResponseCmd(BLE_AVAILABLE, PARAM_NUMS_1, (uint8_t*)&result, &len);
1712+
SpiDrv::spiSlaveDeselect();
1713+
1714+
return result;
1715+
}
1716+
1717+
int WiFiDrv::bleRead(uint8_t data[], size_t length) {
1718+
WAIT_FOR_SLAVE_SELECT();
1719+
1720+
SpiDrv::sendCmd(BLE_READ, PARAM_NUMS_1);
1721+
1722+
int commandSize = 7; // 4 for the normal command length + 3 for the parameter
1723+
uint16_t param = length; // TODO check length doesn't exceed 2^16
1724+
SpiDrv::sendParam((uint8_t*)&param, sizeof(param), LAST_PARAM);
1725+
1726+
// pad to multiple of 4
1727+
while (commandSize % 4 != 0) {
1728+
SpiDrv::readChar();
1729+
commandSize++;
1730+
}
1731+
1732+
SpiDrv::spiSlaveDeselect();
1733+
//Wait the reply elaboration
1734+
SpiDrv::waitForSlaveReady();
1735+
SpiDrv::spiSlaveSelect();
1736+
1737+
uint16_t res_len = 0;
1738+
SpiDrv::waitResponseData16(BLE_READ, data, (uint16_t*)&res_len);
1739+
1740+
SpiDrv::spiSlaveDeselect();
1741+
1742+
return res_len;
1743+
}
1744+
1745+
int WiFiDrv::blePeek(uint8_t data[], size_t length) {
1746+
WAIT_FOR_SLAVE_SELECT();
1747+
1748+
SpiDrv::sendCmd(BLE_PEEK, PARAM_NUMS_1);
1749+
1750+
int commandSize = 7; // 4 for the normal command length + 3 for the parameter
1751+
uint16_t param = length; // TODO check length doesn't exceed 2^16
1752+
SpiDrv::sendParam((uint8_t*)&param, sizeof(param), LAST_PARAM);
1753+
1754+
// pad to multiple of 4
1755+
while (commandSize % 4 != 0) {
1756+
SpiDrv::readChar();
1757+
commandSize++;
1758+
}
1759+
1760+
SpiDrv::spiSlaveDeselect();
1761+
//Wait the reply elaboration
1762+
SpiDrv::waitForSlaveReady();
1763+
SpiDrv::spiSlaveSelect();
1764+
1765+
uint16_t res_len = 0;
1766+
SpiDrv::waitResponseData16(BLE_READ, data, (uint16_t*)&res_len);
1767+
1768+
SpiDrv::spiSlaveDeselect();
1769+
1770+
return res_len;
1771+
}
1772+
1773+
size_t WiFiDrv::bleWrite(const uint8_t* data, size_t len) {
1774+
WAIT_FOR_SLAVE_SELECT();
1775+
1776+
int commandSize = 4;
1777+
SpiDrv::sendCmd(BLE_WRITE, PARAM_NUMS_1);
1778+
1779+
SpiDrv::sendBuffer((uint8_t*)data, len, LAST_PARAM);
1780+
commandSize += len+2;
1781+
1782+
// pad to multiple of 4
1783+
while (commandSize % 4 != 0) {
1784+
SpiDrv::readChar();
1785+
commandSize++;
1786+
}
1787+
1788+
SpiDrv::spiSlaveDeselect();
1789+
//Wait the reply elaboration
1790+
SpiDrv::waitForSlaveReady();
1791+
SpiDrv::spiSlaveSelect();
1792+
1793+
uint8_t res_len = 1;
1794+
uint16_t res = 0;
1795+
SpiDrv::waitResponseCmd(BLE_WRITE, PARAM_NUMS_1, (uint8_t*)&res, &res_len);
1796+
SpiDrv::spiSlaveDeselect();
1797+
1798+
return res;
1799+
}
1800+
16661801

16671802
WiFiDrv wiFiDrv;

src/utility/wifi_drv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ class WiFiDrv
336336
static size_t prefGet(const char * key, PreferenceType type, uint8_t value[], size_t len);
337337
static PreferenceType prefGetType(const char * key);
338338

339+
static int bleBegin();
340+
static void bleEnd();
341+
static int bleAvailable();
342+
static int bleRead(uint8_t data[], size_t length);
343+
static int blePeek(uint8_t data[], size_t length);
344+
static size_t bleWrite(const uint8_t* data, size_t length);
345+
339346
static void applyOTA();
340347

341348
friend class WiFiUDP;

src/utility/wifi_spi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ enum {
9999
GET_DATABUF_TCP_CMD = 0x45,
100100
INSERT_DATABUF_CMD = 0x46,
101101

102+
BLE_BEGIN = 0x4A,
103+
BLE_END = 0x4B,
104+
BLE_AVAILABLE = 0x4C,
105+
BLE_PEEK = 0x4D,
106+
BLE_READ = 0x4E,
107+
BLE_WRITE = 0x4F,
108+
102109
// regular format commands
103110
SET_PIN_MODE = 0x50,
104111
SET_DIGITAL_WRITE = 0x51,

0 commit comments

Comments
 (0)