Skip to content

Commit 2dc1846

Browse files
author
Kevin Townsend
committed
Added TX/RX stubs
1 parent a864e8d commit 2dc1846

File tree

2 files changed

+121
-57
lines changed

2 files changed

+121
-57
lines changed

adafruit_bluefruitspi.py

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,10 @@
4848
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BluefruitSPI.git"
4949

5050
import time
51-
import digitalio
51+
from digitalio import Direction, Pull
5252
from adafruit_bus_device.spi_device import SPIDevice
5353
from micropython import const
54-
try:
55-
from struct import pack_into, unpack
56-
except ImportError:
57-
from ustruct import pack_into, unpack
54+
import struct
5855

5956

6057
class MsgType: #pylint: disable=too-few-public-methods,bad-whitespace
@@ -125,30 +122,28 @@ class ErrorCode: #pylint: disable=too-few-public-methods,bad-whitespace
125122
class BluefruitSPI:
126123
"""Helper for the Bluefruit LE SPI Friend"""
127124

128-
def __init__(self, spi, cs, irq, debug=False):
129-
self._cs = cs
125+
def __init__(self, spi, cs, irq, reset, debug=False):
130126
self._irq = irq
131-
self._spi = spi
132-
self._ble = SPIDevice(self._spi, self._cs)
133127
self._buf_tx = bytearray(20)
134128
self._buf_rx = bytearray(20)
135129
self._debug = debug
136130

137-
# CS is an active low output, so set pullup
138-
self._cs.switch_to_output(value=True,
139-
drive_mode=digitalio.DriveMode.PUSH_PULL)
131+
# Reset
132+
reset.direction = Direction.OUTPUT
133+
reset.value = False
134+
time.sleep(0.01)
135+
reset.value = True
136+
time.sleep(0.5)
140137

141-
# irq line is active high input, so set a pulldown as a precaution
142-
self._irq.switch_to_input(pull=digitalio.Pull.DOWN)
143-
144-
# Check out the SPI bus
145-
while not self._spi.try_lock():
146-
pass
138+
# CS is an active low output
139+
cs.direction = Direction.OUTPUT
140+
cs.value = True
147141

148-
# Configure SPI for 4MHz
149-
self._spi.configure(baudrate=4000000, phase=0, polarity=0)
142+
# irq line is active high input, so set a pulldown as a precaution
143+
self._irq.direction = Direction.INPUT
144+
self._irq.pull = Pull.DOWN
150145

151-
self._spi.unlock()
146+
self._spi_device = SPIDevice(spi, cs)
152147

153148
def cmd(self, cmd):
154149
"""
@@ -165,25 +160,22 @@ def cmd(self, cmd):
165160
print("ERROR: Command too long.")
166161
raise ValueError('Command too long.')
167162

168-
# Check out the SPI bus
169-
while not self._spi.try_lock():
170-
pass
171-
172-
# Send the packet across the SPI bus
173-
pack_into("<BHB16s", self._buf_tx, 0,
174-
MsgType.COMMAND, SDEPCommand.ATCOMMAND,
175-
len(cmd), cmd)
163+
# Construct the SDEP packet
164+
struct.pack_into("<BHB16s", self._buf_tx, 0,
165+
MsgType.COMMAND, SDEPCommand.ATCOMMAND,
166+
len(cmd), cmd)
176167
if self._debug:
177168
print("Writing: ", [hex(b) for b in self._buf_tx])
178-
self._cs.value = False
179-
self._spi.write(self._buf_tx, end=len(cmd) + 4)
180-
self._cs.value = True
169+
170+
# Send out the SPI bus
171+
with self._spi_device as spi:
172+
spi.write(self._buf_tx, end=len(cmd) + 4)
181173

182174
# Wait up to 200ms for a response
183175
timeout = 0.2
184-
while timeout > 0.0 and self._irq is False:
185-
time.sleep(0.005)
186-
timeout -= 0.005
176+
while timeout > 0 and not self._irq.value:
177+
time.sleep(0.01)
178+
timeout -= 0.01
187179
if timeout <= 0:
188180
if self._debug:
189181
print("ERROR: Timed out waiting for a response.")
@@ -197,24 +189,33 @@ def cmd(self, cmd):
197189
while self._irq.value is True:
198190
# Read the current response packet
199191
time.sleep(0.01)
200-
self._cs.value = False
201-
self._spi.readinto(self._buf_rx)
202-
self._cs.value = True
192+
with self._spi_device as spi:
193+
spi.readinto(self._buf_rx)
203194

204195
# Read the message envelope and contents
205-
msgtype, rspid, rsplen = unpack('>BHB', self._buf_rx)
196+
msgtype, rspid, rsplen = struct.unpack('>BHB', self._buf_rx)
206197
if rsplen >= 16:
207198
rsp += self._buf_rx[4:20]
208199
else:
209200
rsp += self._buf_rx[4:rsplen+4]
210201
if self._debug:
211202
print("Reading: ", [hex(b) for b in self._buf_rx])
212203

213-
# Release the SPI bus
214-
self._spi.unlock()
215-
216204
# Clean up the response buffer
217205
if self._debug:
218206
print(rsp)
219207

220208
return msgtype, rspid, rsp
209+
210+
def uarttx(self, txt):
211+
"""
212+
Sends the specific string out over BLE UART.
213+
:param txt: The new-line terminated string to send.
214+
"""
215+
return self.cmd("AT+BLEUARTTX="+txt+"\n")
216+
217+
def uartrx(self):
218+
"""
219+
Reads data from the BLE UART FIFO.
220+
"""
221+
return self.cmd("AT+BLEUARTRX\n")

examples/bluefruitspi_simpletest.py

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,85 @@
11
import busio
2-
import digitalio
2+
from digitalio import DigitalInOut, Direction
33
import board
4-
4+
import time
55
from adafruit_bluefruitspi import BluefruitSPI, MsgType
66

77
spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
8-
cs = digitalio.DigitalInOut(board.A5)
9-
irq = digitalio.DigitalInOut(board.A4)
10-
bluefruit = BluefruitSPI(spi_bus, cs, irq, debug=True)
8+
cs = DigitalInOut(board.D8)
9+
irq = DigitalInOut(board.D7)
10+
rst = DigitalInOut(board.D4)
11+
bluefruit = BluefruitSPI(spi_bus, cs, irq, rst, debug=False)
12+
13+
def send_command(string):
14+
try:
15+
msgtype, msgid, rsp = bluefruit.cmd(string+"\n")
16+
if msgtype == MsgType.ERROR:
17+
raise RuntimeError("Error (id:{0})".format(hex(msgid)))
18+
if msgtype == MsgType.RESPONSE:
19+
return rsp
20+
except RuntimeError as error:
21+
raise RuntimeError("AT command failure: " + repr(error))
22+
23+
def command_check_OK(string):
24+
ret = send_command(string)
25+
if not ret or not ret[-4:]:
26+
raise RuntimeError("Not OK")
27+
if ret[-4:] != b'OK\r\n':
28+
raise RuntimeError("Not OK")
29+
if ret[:-4]:
30+
return str(ret[:-4], 'utf-8')
31+
32+
def uarttx(string):
33+
try:
34+
msgtype, msgid, rsp = bluefruit.uarttx(string)
35+
if msgtype == MsgType.ERROR:
36+
raise RuntimeError("Error (id:{0})".format(hex(msgid)))
37+
except RuntimeError as error:
38+
raise RuntimeError("UARTTX command failure: " + repr(error))
39+
if not rsp or not rsp[-4:]:
40+
raise RuntimeError("Not OK")
41+
if rsp[-4:] != b'OK\r\n':
42+
raise RuntimeError("Not OK")
43+
if rsp[:-4]:
44+
return str(ret[:-4], 'utf-8')
45+
46+
def uartrx():
47+
try:
48+
msgtype, msgid, rsp = bluefruit.uartrx()
49+
if msgtype == MsgType.ERROR:
50+
raise RuntimeError("Error (id:{0})".format(hex(msgid)))
51+
except RuntimeError as error:
52+
raise RuntimeError("UARTRX command failure: " + repr(error))
53+
if not rsp or not rsp[-4:]:
54+
raise RuntimeError("Not OK")
55+
if rsp[-4:] != b'OK\r\n':
56+
raise RuntimeError("Not OK")
57+
if rsp[:-4]:
58+
return str(ret[:-4], 'utf-8')
1159

1260
# Send the ATI command
13-
try:
14-
msgtype, msgid, rsp = bluefruit.cmd("ATI\n")
15-
if msgtype == MsgType.ERROR:
16-
print("Error (id:{0})".format(hex(msgid)))
17-
if msgtype == MsgType.RESPONSE:
18-
print("Response:")
19-
print(rsp)
20-
except RuntimeError as error:
21-
print("AT command failure: " + repr(error))
22-
exit()
61+
print(command_check_OK("AT+FACTORYRESET"))
62+
time.sleep(1)
63+
print(command_check_OK("ATI"))
64+
#print(command_check_OK("AT+GAPDEVNAME=ColorLamp"))
65+
66+
while True:
67+
# our main loop, if not connected, wait till we are
68+
connected = False
69+
dotcount = 0
70+
print("Waiting for a connection to Bluefruit LE Connect ...")
71+
while not connected:
72+
connected = int(command_check_OK("AT+GAPGETCONN")) == 1
73+
dotcount += 1
74+
if dotcount == 79:
75+
print(".")
76+
dotcount = 0
77+
else:
78+
print(".", end="")
79+
time.sleep(0.5)
80+
# Yay!
81+
print("\nConnected!")
82+
while connected:
83+
uarttx("1")
84+
connected = int(command_check_OK("AT+GAPGETCONN")) == 1
85+
print("Connection lost.")

0 commit comments

Comments
 (0)