Skip to content

Commit 2d415bd

Browse files
Merge pull request #13 from nextroundwinner/macos
Macos
2 parents 5e85f3a + 4fb3b67 commit 2d415bd

13 files changed

Lines changed: 83 additions & 28 deletions

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"type": "debugpy",
1010
"request": "launch",
1111
// "program": "src/__main__.py",
12-
"module": "examples.low_level.example_low_level_plot",
12+
"module": "examples.dyscom.example_dyscom_pyplot",
1313
"justMyCode": false,
1414
// "args": ["COM3"],
1515
"console": "integratedTerminal"

HINTS.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This page describes implementation details.
2121
- Each device has an instance of a _PacketBuffer_
2222
- Should be used to read packets from connection
2323
- Handles extraction of packets from byte stream
24-
- Most functions communicating with the device are async functions, because they wait for a matching acknowledge and return values from acknowledge
24+
- Most functions communicating with the device are async functions using name schema _xxx_, because they wait for a matching acknowledge and return values from acknowledge
2525
- If no matching acknowledge or no acknowledge arrives in time, an exception is raised
2626
- The async functions connection buffer handling is always identical:
2727
- Clear buffer
@@ -30,7 +30,6 @@ This page describes implementation details.
3030
- More data remains in connection buffer
3131
- Additionally functions with naming schema _send_xxx_ are normal functions not waiting for acknowledge
3232
- The acknowledge needs to handled manually by using _PacketBuffer_ object from device
33-
- _PacketBuffer_ reads data from connection and separates packets from data stream
3433

3534
## Logging
3635
- Library creates a custom logger, see class _Logger_
@@ -40,10 +39,10 @@ This page describes implementation details.
4039
- For better performance, disable logger
4140
- `logger().disabled = True`
4241

43-
## General layer
42+
## General layer (all devices)
4443
- Contains functions to get common information like device serial or firmware version
4544

46-
## Mid level layer
45+
## Mid level layer (P24)
4746
- Contains functions for mid level stimulation
4847
- This mode is good to let the device stimulate a predefined pattern until _stop()_ is send
4948
- Usage
@@ -52,7 +51,7 @@ This page describes implementation details.
5251
- Call _get_current_data()_ every 1.5s to keep stimulation ongoing
5352
- Call _stop()_ to end stimulation and leave mid level mode
5453

55-
## Low level layer
54+
## Low level layer (P24)
5655
- Contains functions for low level stimulation
5756
- This mode is good to react to a external trigger to change stimulation pattern
5857
- Without _send_channel_config()_ the device will not stimulate
@@ -63,7 +62,7 @@ This page describes implementation details.
6362
- It stops stimulation when stimulation pattern is over
6463
- Call _stop()_ to leave low level mode
6564

66-
## Dyscom layer
65+
## Dyscom layer (I24)
6766
- Contains functions for dyscom level
6867
- This mode is used by I24 to measure EMG or BI
6968
- Usage
@@ -75,7 +74,9 @@ This page describes implementation details.
7574
- Call _power_module()_ to power off measurement module
7675
- IMPORTANT: all storage related functions are untested
7776

78-
# Using USB under Linux with Hyper-V
77+
# Platform hints
78+
79+
## Using USB under Linux with Hyper-V
7980
- On Windows
8081
- Install [usbipd-win](https://github.com/dorssel/usbipd-win)
8182
- `usbipd list`
@@ -87,6 +88,10 @@ This page describes implementation details.
8788
- In case of permission error
8889
- `sudo chmod 666 /dev/ttyACMx`
8990

91+
## Using MacOS under VirtualBox
92+
- https://www.reddit.com/r/macOSVMs/comments/1gb8egp/macos_sonoma_virtualbox_bootloop_afterduring/?rdt=48615
93+
94+
9095
# Deviation from Instruction for Use
9196

9297
## Dyscom commands

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,7 @@ Python 3.11 or higher
107107

108108
## 0.0.13
109109
- Fixed error with example keyboard utils under Linux
110-
- Enhance example low level plot to show all channels
110+
- Enhanced example low level plot to show all channels
111+
112+
## 0.0.14
113+
- Improved examples under Linux/MacOS

examples/dyscom/example_dyscom_fastplotlib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ async def device_communication() -> int:
6262
await dyscom.start()
6363

6464
# loop for some time
65-
for x in range(1000):
65+
for x in range(5000):
6666
# check if we closed window
6767
if not is_window_open:
6868
break
6969

7070
# check operation mode from time to time, this function is not waiting for response
7171
# so we have to handle it by ourself later
72-
if x % 100 == 0:
72+
if x % 500 == 0:
7373
dyscom.send_get_operation_mode()
7474

7575
live_data_counter = 0

examples/dyscom/example_dyscom_pyplot.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ async def main() -> int:
4949
# start dyscom measurement
5050
await dyscom.start()
5151

52-
for x in range(1000):
52+
# loop for some time
53+
for x in range(5000):
5354
# check operation mode from time to time
54-
if x % 100 == 0:
55+
if x % 500 == 0:
5556
dyscom.send_get_operation_mode()
5657

5758
live_data_counter = 0
@@ -88,6 +89,8 @@ async def main() -> int:
8889
# close serial port connection
8990
connection.close()
9091

92+
print("Close plot window to quit")
93+
plot_helper.loop()
9194
return 0
9295

9396

examples/dyscom/example_dyscom_write_csv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ async def device_communication() -> int:
6464
total_count = 0
6565

6666
# loop for some time
67-
for x in range(1000):
67+
for x in range(5000):
6868
# check operation mode from time to time, this function is not waiting for response
6969
# so we have to handle it by ourself later
70-
if x % 100 == 0:
70+
if x % 500 == 0:
7171
dyscom.send_get_operation_mode()
7272

7373
live_data_counter = 0

examples/low_level/example_low_level_plot.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def get_channel_color(channel: Channel) -> str:
3737
"""Retrieves color from channel"""
3838
color = channel.name
3939
if color == "WHITE":
40-
color = "PINK"
40+
color = "PURPLE"
4141
return color
4242

4343

@@ -48,7 +48,7 @@ async def main() -> int:
4848
for connector in Connector:
4949
for channel in Channel:
5050
plots_info[calc_plot_index(connector, channel)] = f"Connector {connector.name}, channel {channel.name}", get_channel_color(channel)
51-
plot_helper = PyPlotHelper(plots_info, 2500)
51+
plot_helper = PyPlotHelper(plots_info, 500)
5252

5353
# get comport from command line argument
5454
com_port = ExampleUtils.get_comport_from_commandline_argument()
@@ -74,27 +74,31 @@ async def main() -> int:
7474
send_channel_config(low_level_layer)
7575

7676
# wait for stimulation to happen
77-
await asyncio.sleep(0.25)
77+
await asyncio.sleep(1.0)
7878

7979
# process all acknowledges and append values to plot data
8080
while True:
8181
ack = low_level_layer.packet_buffer.get_packet_from_buffer()
8282
if ack:
8383
if ack.command == Commands.LOW_LEVEL_CHANNEL_CONFIG_ACK:
8484
ll_config_ack: PacketLowLevelChannelConfigAck = ack
85+
# update plot with measured values
8586
plot_helper.append_values(calc_plot_index(ll_config_ack.connector, ll_config_ack.channel),
8687
ll_config_ack.measurement_samples)
88+
plot_helper.update()
8789
else:
8890
break
8991

92+
await asyncio.sleep(0.1)
93+
9094
# call stop low level
9195
await low_level_layer.stop()
92-
# update plot with measured values
93-
plot_helper.update()
9496

9597
# close serial port connection
9698
connection.close()
9799

100+
print("Close plot window to quit")
101+
plot_helper.loop()
98102
return 0
99103

100104

examples/utils/example_utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
import threading
55
import os
6+
import asyncio
67
from typing import Callable
78
from getch import getch
89

@@ -56,3 +57,23 @@ def get_comport_from_commandline_argument() -> str:
5657

5758
com_port = sys.argv[1]
5859
return com_port
60+
61+
62+
@staticmethod
63+
async def wait_for_any_key_pressed(cb: Callable[[], None] | None):
64+
"""Helper function to wait for any key press"""
65+
66+
# keyboard func
67+
def input_callback(_input_value: str) -> bool:
68+
"""Callback call from keyboard input thread"""
69+
# quit on any key
70+
return True
71+
72+
# create keyboard input thread for non blocking console input
73+
keyboard_input_thread = KeyboardInputThread(input_callback)
74+
75+
# now we can start stimulation
76+
while keyboard_input_thread.is_alive():
77+
if cb is not None:
78+
cb()
79+
await asyncio.sleep(0.1)

examples/utils/fastplotlib_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(self, sub_plot, max_value_count: int, color: str):
2323
self._line = sub_plot.add_line(y_data, name="values", colors=color)
2424

2525
# this queue is used to synchronize data between background and main thread
26-
self._data_queue = Queue(maxsize=1)
26+
self._data_queue = Queue(maxsize=0)
2727

2828

2929
def append_value(self, value: float):

examples/utils/plot_base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ def update(self):
6565
"""Update plot"""
6666

6767

68+
def loop(self):
69+
"""Run event loop until plot window closed"""
70+
71+
6872
def _calc_layout_dimension(self, channel_count: int) -> tuple[int, int]:
6973
"""Calculates layout for a specific number of channels, tries to grow
7074
equal in both directions"""

0 commit comments

Comments
 (0)