Skip to content
Snippets Groups Projects
Commit b238f9e0 authored by schneider's avatar schneider
Browse files

feat(ecg): Experimental streaming of ECG samples via BLE

parent 7deee116
No related branches found
No related tags found
No related merge requests found
Bluetooth ECG Service
========================
.. warning::
The service is still work in progress and subject to change
The ECG service provides access to the ECG sensor of the card10
BLE Service
-----------
The current draft uses following service specification:
- Service:
UUID: ``42230300-2342-2342-2342-234223422342``
- ECG samples characteristic:
UUID: ``42230301-2342-2342-2342-234223422342``
notify
ECG samples characteristic
--------------------------
List of 16 bit samples (big endian). Enable notifications to
receive a stream of samples while the ECG app is open.
......@@ -75,6 +75,7 @@ Last but not least, if you want to start hacking the lower-level firmware, the
bluetooth/ess
bluetooth/file-transfer
bluetooth/card10
bluetooth/ecg
bluetooth/nimble
Indices and tables
......
......@@ -7,6 +7,7 @@ import max30001
import math
import struct
import itertools
import bluetooth
from ecg.settings import *
config = ecg_settings()
......@@ -43,6 +44,52 @@ sensor = 0
disp = display.open()
last_sample_count = 1
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
def ble_irq(event, data):
global ble_streaming
if event == _IRQ_CENTRAL_CONNECT:
print("BLE Connected")
elif event == _IRQ_CENTRAL_DISCONNECT:
print("BLE Disconnected")
elif event == _IRQ_GATTS_WRITE:
conn_handle, value_handle = data
if value_handle == ecg_cccd_handle:
value = b.gatts_read(value_handle)
print("New cccd value:", value)
# Value of 0 means notifcations off
if value == b"\x00\x00":
ble_streaming = False
if not config.get_option("BLE Disp"):
disp.backlight(20)
else:
ble_streaming = True
if not config.get_option("BLE Disp"):
disp.backlight(0)
b = bluetooth.BLE()
b.active(True)
b.irq(ble_irq)
_ECG_UUID = bluetooth.UUID("42230300-2342-2342-2342-234223422342")
_ECG_DATA = (
bluetooth.UUID("42230301-2342-2342-2342-234223422342"),
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)
_ECG_SERVICE = (_ECG_UUID, (_ECG_DATA,))
((ecg_data_handle,),) = b.gatts_register_services((_ECG_SERVICE,))
ecg_cccd_handle = ecg_data_handle + 1
# Disable streaming by default
ble_streaming = False
b.gatts_write(ecg_cccd_handle, "\x00\x00")
leds.dim_top(1)
COLORS = [((23 + (15 * i)) % 360, 1.0, 1.0) for i in range(11)]
......@@ -129,7 +176,20 @@ def detect_pulse(num_new_samples):
def callback_ecg(datasets):
global update_screen, history, filebuffer, write, samples_since_start_of_write
global update_screen, history, filebuffer, write, samples_since_start_of_write, ble_streaming, ecg_data_handle
if ble_streaming:
try:
b.gatts_notify(
1, ecg_data_handle, struct.pack(">" + ("h" * len(datasets)), *datasets)
)
except:
pass
# Don't update the screen if it should be off during a connection
if not config.get_option("BLE Disp"):
return
update_screen += len(datasets)
if write > 0:
samples_since_start_of_write += len(datasets)
......@@ -441,7 +501,13 @@ def main():
else:
pause_screen = -1 # hide graph
leds.clear() # disable all LEDs
if ble_streaming and not config.get_option("BLE Disp"):
disp.backlight(20)
config.run() # show config menu
if ble_streaming and not config.get_option("BLE Disp"):
disp.backlight(0)
close_sensor() # reset sensor in case mode or bias was changed TODO do not close sensor otherwise?
open_sensor()
pause_screen = 0 # start plotting graph again
......
......@@ -95,6 +95,7 @@ def ecg_settings():
config.add_option(("Filter", itertools.cycle([("HP", {"HP"}), ("off", {})])))
config.add_option(("Rate", itertools.cycle([("128Hz", 128), ("256Hz", 256)])))
config.add_option(("Window", itertools.cycle([("1x", 1), ("2x", 2), ("3x", 3)])))
config.add_option(("BLE Disp", itertools.cycle([("Off", False), ("On", True)])))
config.add_option(
(
"Log",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment