__init__.py 6.24 KB
Newer Older
Daniel Hoffend's avatar
Daniel Hoffend committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
import os
import display
import utime
import buttons
import max30001
import math
import struct

WIDTH = 160
HEIGHT = 80
OFFSET = 50
ECG_RATE = 128
HISTORY_MAX = ECG_RATE * 2
DRAW_AFTER_SAMPLES = 5
SCALE_FACTOR = 30
MODE_USB = "USB"
MODE_FINGER = "Finger"
FILEBUFFERBLOCK = 4096
COLOR_BACKGROUND = [0, 0, 0]
COLOR_LINE = [255, 255, 255]
COLOR_TEXT = [255, 255, 255]
COLOR_MODE_FINGER = [0, 255, 0]
COLOR_MODE_USB = [0, 0, 255]
COLOR_WRITE_FG = [255, 255, 255]
COLOR_WRITE_BG = [255, 0, 0]

current_mode = MODE_FINGER
history = []
filebuffer = bytearray()
write = 0
bias = True
update_screen = 0
pause_screen = 0
sensor = 0
disp = display.open()


def callback_ecg(datasets):
    global update_screen, history, filebuffer, write
    if len(datasets) > 0:
        for value in datasets:
            history.append(value)
        update_screen += len(datasets)
    if len(history) > HISTORY_MAX:
        r = len(history) - HISTORY_MAX
        for i in range(r):
            history.pop(0)

    # buffer for writes
    if write > 0:
        if len(datasets) > 0:
            for value in datasets:
                filebuffer.extend(struct.pack("h", value))
                if len(filebuffer) >= FILEBUFFERBLOCK:
                    write_filebuffer()

    # don't update on every callback
    if update_screen >= DRAW_AFTER_SAMPLES:
        # print("history: %i, filebuffer: %i" % (len(history), len(filebuffer)))
        draw_histogram()
        update_screen = 0


def write_filebuffer():
    global write, filebuffer
    # write to file
    chars = ""
    lt = utime.localtime(write)
    filename = "/ecg-%04d-%02d-%02d_%02d%02d%02d.log" % (
        lt[0],
        lt[1],
        lt[2],
        lt[3],
        lt[4],
        lt[5],
    )

    # write stuff to disk
    # print("Write %i bytes to %s" % (len(filebuffer), filename))
    try:
        f = open(filename, "ab")
        f.write(filebuffer)
        f.close()
    except OSError as e:
        print("Please check the file or filesystem", e)
        write = 0
        pause_screen = -1
        disp.clear(COLOR_BACKGROUND)
        disp.print("IO Error", posy=0, fg=COLOR_TEXT)
        disp.print("Please check", posy=20, fg=COLOR_TEXT)
        disp.print("your", posy=40, fg=COLOR_TEXT)
        disp.print("filesystem", posy=60, fg=COLOR_TEXT)
        disp.update()
        close_sensor()
    except:
        print("Unexpected error, stop writeing logfile")
        write = 0

    filebuffer = bytearray()
    return


def open_sensor():
    global sensor
    sensor = max30001.MAX30001(
        usb=(False if current_mode == MODE_FINGER else True),
        bias=bias,
        sample_rate=ECG_RATE,
        callback=callback_ecg,
    )


def close_sensor():
    global sensor
    sensor.close()


def toggle_mode():
    global current_mode
    close_sensor()
    current_mode = MODE_USB if current_mode == MODE_FINGER else MODE_FINGER
    open_sensor()


def toggle_bias():
    global bias
    close_sensor()
    bias = False if bias == True else True
    open_sensor()
    return


def toggle_write():
    global write, disp, pause_screen
    pause_screen = utime.time_ms() + 1000
    disp.clear(COLOR_BACKGROUND)
    if write > 0:
        write_filebuffer()
        write = 0
        disp.print("Stop", posx=50, posy=20, fg=COLOR_TEXT)
        disp.print("logging", posx=30, posy=40, fg=COLOR_TEXT)
    else:
        filebuffer = bytearray()
        write = utime.time()
        disp.print("Start", posx=45, posy=20, fg=COLOR_TEXT)
        disp.print("logging", posx=30, posy=40, fg=COLOR_TEXT)

    disp.update()
    return


def draw_histogram():
    global disp, history, current_mode, bias, write, pause_screen

    # skip rendering due to message beeing shown
    if pause_screen == -1:
        return
    elif pause_screen > 0:
        t = utime.time_ms()
        if t > pause_screen:
            pause_screen = 0
        else:
            return

    disp.clear(COLOR_BACKGROUND)

    # get max value and calc scale
    value_max = 0
    for value in history:
        if abs(value) > value_max:
            value_max = abs(value)
    scale = SCALE_FACTOR / (value_max if value_max > 0 else 1)

    # draw histogram
    old = False
    x = 0
    samples = len(history)
    for i, value in enumerate(history):
        if old == False:
            old = (x, int(value * scale) + OFFSET)
            x += 1
            continue
        elif i > samples - WIDTH:
            disp.line(old[0], old[1], x, int(value * scale) + OFFSET, col=COLOR_LINE)
            old = (x, int(value * scale) + OFFSET)
            x += 1

    # draw text: mode/bias/write
    disp.print(
        current_mode + ("+Bias" if bias else ""),
        posx=0,
        posy=0,
        fg=(COLOR_MODE_FINGER if current_mode == MODE_FINGER else COLOR_MODE_USB),
    )

    # announce writing ecg log
    if write > 0:
        t = utime.time()
        if write > 0 and t % 2 == 0:
            disp.print("LOG", posx=0, posy=60, fg=COLOR_WRITE_FG, bg=COLOR_WRITE_BG)

    disp.update()


def main():
    # show button layout
    disp.clear(COLOR_BACKGROUND)
    disp.print("  BUTTONS  ", posx=0, posy=0, fg=COLOR_TEXT)
    disp.print("Finger/USB>", posx=0, posy=20, fg=COLOR_MODE_FINGER)
    disp.print("     Bias >", posx=0, posy=40, fg=COLOR_MODE_USB)
    disp.print("< Write Log", posx=0, posy=60, fg=COLOR_WRITE_BG)
    disp.update()
    utime.sleep(3)

    # start ecg
    open_sensor()
    while True:
        button_pressed = False
        while True:
            v = buttons.read(
                buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT
            )
            if v == 0:
                button_pressed = False

            if not button_pressed and v & buttons.BOTTOM_LEFT != 0:
                button_pressed = True
                toggle_write()

            elif not button_pressed and v & buttons.BOTTOM_RIGHT != 0:
                button_pressed = True
                toggle_bias()

            elif not button_pressed and v & buttons.TOP_RIGHT != 0:
                button_pressed = True
                toggle_mode()

        pass


if __name__ == "__main__":
    main()