diff --git a/docs/api/stream_daq.md b/docs/api/stream_daq.md index f2065d9..4ba5dfd 100644 --- a/docs/api/stream_daq.md +++ b/docs/api/stream_daq.md @@ -19,6 +19,19 @@ A window displaying the image transferred from the Miniscope and a graph plottin ## Device configuration A YAML file is used to configure Stream DAQ based on the device configuration. The device configuration needs to match the imaging and data capture hardware for proper operation. This file is used to set up hardware, define data formats, and set data preambles. The contents of this YAML file will be parsed into a model [miniscope_io.models.stream](../api/models/stream.md), which then configures the Stream DAQ. +### FPGA (Opal Kelly) configuration +The `bitstream` field in the device configuration yaml file specifies the image that will be uploaded to the opal kelly board. This file needs to be placed in `miniscope_io.devices`. + + +#### Bitstream file nomenclature +Name format of the bitstream files and directory: +`[DEVICE_DIR]/USBInterface-[CLOCK_FREQUENCY]-[INPUT_PIN]_[IO_VOLTAGE]-[ENCODING_POLARITY]` +- **DEVICE_DIR**: FPGA module name. The current package supports XEM7310-A75 (Opal kelly). +- **CLOCK_FREQUENCY**: Manchester encoding clock frequency. For the current FPGA (XEM7310-A75), this frequency can be configured to 100 / *i* MHz where *i* is an integer. +- **INPUT_PIN**: Signal input pin. `J2_2` means signal goes into second pin of J2 pin headers in the hardware module. +- **IO_VOLTAGE**: I/O voltage of the FPGA `INPUT_PIN`. The current package supports 3.3V input. +- **ENCODING_POLARITY**: Manchester encoding convention, which corresponds to bit polarity. The current package supports IEEE convention Manchester encoding. + ### Example device configuration Below is an example configuration YAML file. More examples can be found in `miniscope_io.data.config`. @@ -26,8 +39,8 @@ Below is an example configuration YAML file. More examples can be found in `mini # capture device. "OK" (Opal Kelly) or "UART" device: "OK" -# The configuration bitstream file to upload to the Opal Kelly board. This uploads a Manchester decoder HDL and different bitstream files are required to configure different data rates and bit polarity. This is a binary file synthesized using Vivado, and details for generating this file will be provided in later updates. -bitstream: "USBInterface-6mhz-3v3-INVERSE.bit" +# bitstream file to upload to Opal Kelly board +bitstream: "XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit" # COM port and baud rate is only required for UART mode port: null @@ -46,6 +59,7 @@ header_len: 384 # 12 * 32 (in bits) buffer_block_length: 10 block_size: 512 num_buffers: 32 +dummy_words: 10 # Flags to flip bit/byte order when recovering headers and data. See model document for details. reverse_header_bits: True @@ -53,6 +67,27 @@ reverse_header_bytes: True reverse_payload_bits: True reverse_payload_bytes: True +adc_scale: + ref_voltage: 1.1 + bitdepth: 8 + battery_div_factor: 5 + vin_div_factor: 11.3 + +runtime: + serial_buffer_queue_size: 10 + frame_buffer_queue_size: 5 + image_buffer_queue_size: 5 + csv: + buffer: 100 + plot: + keys: + - timestamp + - buffer_count + - frame_buffer_count + - battery_voltage + - input_voltage + update_ms: 1000 + history: 500 ``` ```{eval-rst} diff --git a/miniscope_io/data/config/WLMS_v02_200px.yml b/miniscope_io/data/config/WLMS_v02_200px.yml index 731abae..e5ef3cf 100644 --- a/miniscope_io/data/config/WLMS_v02_200px.yml +++ b/miniscope_io/data/config/WLMS_v02_200px.yml @@ -2,7 +2,7 @@ device: "OK" # bitstream file to upload to Opal Kelly board -bitstream: "USBInterface-8mhz-3v3-INVERSE.bit" +bitstream: "XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit" # COM port and baud rate is only required for UART mode port: null diff --git a/miniscope_io/data/config/example.yml b/miniscope_io/data/config/example.yml deleted file mode 100644 index 3900dfe..0000000 --- a/miniscope_io/data/config/example.yml +++ /dev/null @@ -1,29 +0,0 @@ -# capture device. "OK" (Opal Kelly) or "UART" -device: "OK" - -# bitstream file to upload to Opal Kelly board -bitstream: "USBInterface-8mhz-3v3-INVERSE.bit" - -# COM port and baud rate is only required for UART mode -port: null -baudrate: null - -# Preamble for each data buffer. -preamble: 0x12345678 - -# Image format. StreamDaq will calculate buffer size, etc. based on these parameters -frame_width: 200 -frame_height: 200 -pix_depth: 8 - -# Buffer data format. These have to match the firmware value -header_len: 384 # 12 * 32 (in bits) -buffer_block_length: 10 -block_size: 512 -num_buffers: 32 - -# Flags to flip bit/byte order when recovering headers and data. See model document for details. -reverse_header_bits: True -reverse_header_bytes: True -reverse_payload_bits: True -reverse_payload_bytes: True \ No newline at end of file diff --git a/miniscope_io/devices/USBInterface-6mhz-3v3-INVERSE.bit b/miniscope_io/devices/USBInterface-6mhz-3v3-INVERSE.bit deleted file mode 100644 index 98812f7..0000000 Binary files a/miniscope_io/devices/USBInterface-6mhz-3v3-INVERSE.bit and /dev/null differ diff --git a/miniscope_io/devices/USBInterface-6mhz-3v3-J2_2.bit b/miniscope_io/devices/USBInterface-6mhz-3v3-J2_2.bit deleted file mode 100644 index e37cf5a..0000000 Binary files a/miniscope_io/devices/USBInterface-6mhz-3v3-J2_2.bit and /dev/null differ diff --git a/miniscope_io/devices/USBInterface-6mhz-3v3-dbg.bit b/miniscope_io/devices/USBInterface-6mhz-3v3-dbg.bit deleted file mode 100644 index 247edf8..0000000 Binary files a/miniscope_io/devices/USBInterface-6mhz-3v3-dbg.bit and /dev/null differ diff --git a/miniscope_io/devices/USBInterface-8mhz-3v3-INVERSE.bit b/miniscope_io/devices/USBInterface-8mhz-3v3-INVERSE.bit deleted file mode 100644 index f58c3e4..0000000 Binary files a/miniscope_io/devices/USBInterface-8mhz-3v3-INVERSE.bit and /dev/null differ diff --git a/miniscope_io/devices/USBInterface-10mhz-3v3-dbg.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-10mhz-J2_2-3v3-IEEE.bit similarity index 51% rename from miniscope_io/devices/USBInterface-10mhz-3v3-dbg.bit rename to miniscope_io/devices/XEM7310-A75/USBInterface-10mhz-J2_2-3v3-IEEE.bit index a5f1430..2cff2fa 100644 Binary files a/miniscope_io/devices/USBInterface-10mhz-3v3-dbg.bit and b/miniscope_io/devices/XEM7310-A75/USBInterface-10mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/XEM7310-A75/USBInterface-12_5mhz-J2_2-3v3-IEEE.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-12_5mhz-J2_2-3v3-IEEE.bit new file mode 100644 index 0000000..94e6d72 Binary files /dev/null and b/miniscope_io/devices/XEM7310-A75/USBInterface-12_5mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/XEM7310-A75/USBInterface-14_3mhz-J2_2-3v3-IEEE.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-14_3mhz-J2_2-3v3-IEEE.bit new file mode 100644 index 0000000..79e95cf Binary files /dev/null and b/miniscope_io/devices/XEM7310-A75/USBInterface-14_3mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/USBInterface-8mhz-3v3-dbg.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-3_03mhz-J2_2-3v3-IEEE.bit similarity index 51% rename from miniscope_io/devices/USBInterface-8mhz-3v3-dbg.bit rename to miniscope_io/devices/XEM7310-A75/USBInterface-3_03mhz-J2_2-3v3-IEEE.bit index afc6d9b..fe5c594 100644 Binary files a/miniscope_io/devices/USBInterface-8mhz-3v3-dbg.bit and b/miniscope_io/devices/XEM7310-A75/USBInterface-3_03mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/USBInterface-12mhz-3v3-dbg.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-5mhz-J2_2-3v3-IEEE.bit similarity index 51% rename from miniscope_io/devices/USBInterface-12mhz-3v3-dbg.bit rename to miniscope_io/devices/XEM7310-A75/USBInterface-5mhz-J2_2-3v3-IEEE.bit index 983aed4..51e1a86 100644 Binary files a/miniscope_io/devices/USBInterface-12mhz-3v3-dbg.bit and b/miniscope_io/devices/XEM7310-A75/USBInterface-5mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/XEM7310-A75/USBInterface-6_67mhz-J2_2-3v3-IEEE.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-6_67mhz-J2_2-3v3-IEEE.bit new file mode 100644 index 0000000..ad013de Binary files /dev/null and b/miniscope_io/devices/XEM7310-A75/USBInterface-6_67mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/devices/USBInterface-15mhz-3v3-dbg.bit b/miniscope_io/devices/XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit similarity index 51% rename from miniscope_io/devices/USBInterface-15mhz-3v3-dbg.bit rename to miniscope_io/devices/XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit index 2cce432..a1e8f87 100644 Binary files a/miniscope_io/devices/USBInterface-15mhz-3v3-dbg.bit and b/miniscope_io/devices/XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit differ diff --git a/miniscope_io/models/stream.py b/miniscope_io/models/stream.py index ce68794..5c482aa 100644 --- a/miniscope_io/models/stream.py +++ b/miniscope_io/models/stream.py @@ -291,3 +291,12 @@ def resolve_relative(cls, value: Path) -> Path: if not value.is_absolute(): value = DEVICE_DIR / value return value + + @field_validator("bitstream", mode="after") + def ensure_exists(cls, value: Optional[Path]) -> Optional[Path]: + """If a bitstream file has been provided, ensure it exists""" + if isinstance(value, Path): + assert ( + value.exists() + ), f"Configured to use bitstream file {value}, but it does not exist" + return value diff --git a/miniscope_io/stream_daq.py b/miniscope_io/stream_daq.py index 9afe17f..ecb7190 100644 --- a/miniscope_io/stream_daq.py +++ b/miniscope_io/stream_daq.py @@ -297,6 +297,7 @@ def _fpga_recv( """ locallogs = init_logger("streamDaq.fpga_recv") if not HAVE_OK: + serial_buffer_queue.put(None) raise RuntimeError( "Couldnt import OpalKelly device. Check the docs for install instructions!" ) @@ -307,9 +308,10 @@ def _fpga_recv( # set up fpga devices BIT_FILE = self.config.bitstream if not BIT_FILE.exists(): + serial_buffer_queue.put(None) raise RuntimeError(f"Configured to use bitfile at {BIT_FILE} but no such file exists") - # set up fpga devices + # set up fpga devices dev = self._init_okdev(BIT_FILE) # read loop diff --git a/tests/data/config/preamble_hex.yml b/tests/data/config/preamble_hex.yml index 3900dfe..4fce97f 100644 --- a/tests/data/config/preamble_hex.yml +++ b/tests/data/config/preamble_hex.yml @@ -2,7 +2,7 @@ device: "OK" # bitstream file to upload to Opal Kelly board -bitstream: "USBInterface-8mhz-3v3-INVERSE.bit" +bitstream: "XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit" # COM port and baud rate is only required for UART mode port: null diff --git a/tests/data/config/stream_daq_test_200px.yml b/tests/data/config/stream_daq_test_200px.yml index 6f417c1..2e9fe91 100644 --- a/tests/data/config/stream_daq_test_200px.yml +++ b/tests/data/config/stream_daq_test_200px.yml @@ -2,7 +2,7 @@ device: "OK" # bitstream file to upload to Opal Kelly board -bitstream: "USBInterface-8mhz-3v3-INVERSE.bit" +bitstream: "XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit" # Preamble for each data buffer. preamble: 0x12345678 diff --git a/tests/data/config/wireless_example.yml b/tests/data/config/wireless_example.yml index d76c2df..4249616 100644 --- a/tests/data/config/wireless_example.yml +++ b/tests/data/config/wireless_example.yml @@ -2,7 +2,7 @@ device: "OK" # bitstream file to upload to Opal Kelly board -bitstream: "USBInterface-6mhz-3v3-INVERSE.bit" +bitstream: "XEM7310-A75/USBInterface-8_33mhz-J2_2-3v3-IEEE.bit" # COM port and baud rate rquired for UART mode port: null diff --git a/tests/test_stream_daq.py b/tests/test_stream_daq.py index 880195c..41febdf 100644 --- a/tests/test_stream_daq.py +++ b/tests/test_stream_daq.py @@ -1,8 +1,10 @@ -import pdb +import re +from pathlib import Path import pytest import pandas as pd +from miniscope_io import BASE_DIR from miniscope_io.stream_daq import StreamDevConfig, StreamDaq from miniscope_io.utils import hash_video, hash_file from .conftest import DATA_DIR, CONFIG_DIR @@ -137,3 +139,12 @@ def test_metadata_plotting(tmp_path, default_streamdaq): len(default_streamdaq._header_plotter.index) == default_streamdaq.config.runtime.plot.history ) + + +def test_bitfile_names(): + """ + Bitfile names should have no periods or whitespace in the filenames (except for the .bit extension) + """ + pattern = re.compile(r"\.(?!bit$)|\s") + for path in Path(BASE_DIR).glob("**/*.bit"): + assert not pattern.search(str(path.name))