From 8a7e798e01c7651b54d1067d276f5e5f0b393bdb Mon Sep 17 00:00:00 2001 From: Reed Foster Date: Sun, 8 Oct 2023 21:59:44 -0400 Subject: [PATCH] update with new pynq python code --- pynq/dds_loopback.py | 3 - pynq/dds_loopback_overlay.ipynb | 185 ++++++++++++++-- pynq/noise_buffer_overlay.py | 55 ++++- pynq/noise_buffer_test.ipynb | 360 ++++++++++++++++++++++---------- 4 files changed, 466 insertions(+), 137 deletions(-) diff --git a/pynq/dds_loopback.py b/pynq/dds_loopback.py index f31dc1d..71da5d0 100644 --- a/pynq/dds_loopback.py +++ b/pynq/dds_loopback.py @@ -24,9 +24,6 @@ def __init__(self, bitfile_name=None, dbg=False, plot=False, n_buffers=1, phase_ time.sleep(0.5) # get IPs self.dma_recv = self.axi_dma_0.recvchannel - self.capture_trig = self.axi_gpio_capture.channel1[0] - self.trigger_mode = self.axi_gpio_trigger_sel.channel1[0] - self.adc_select = self.axi_gpio_adc_sel.channel1[0] self.pinc = [self.dds_hier_0.axi_fifo_pinc_0, self.dds_hier_1.axi_fifo_pinc_1] self.cos_scale = [self.dds_hier_0.axi_fifo_scale_0, self.dds_hier_1.axi_fifo_scale_1] self.timer = self.axi_timer_0 diff --git a/pynq/dds_loopback_overlay.ipynb b/pynq/dds_loopback_overlay.ipynb index f66fc97..2230bb0 100644 --- a/pynq/dds_loopback_overlay.ipynb +++ b/pynq/dds_loopback_overlay.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "id": "324a325c-5d95-466d-90e2-dcf2a57de200", "metadata": {}, "outputs": [], @@ -19,17 +19,10 @@ }, { "cell_type": "code", - "execution_count": 2, - "id": "a3829ad0-0297-4923-8cc6-f2479660e698", + "execution_count": 5, + "id": "696ef386-adbb-4a9f-bb05-59140dc43762", "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "loading bitfile hw/top_biastini_750kHz_SPI.bit\n" - ] - }, { "data": { "application/javascript": [ @@ -69,16 +62,174 @@ "output_type": "display_data" }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "loaded bitstream\n", - "set clocks\n" - ] + "data": { + "text/plain": [ + "\u001b[0;31mType:\u001b[0m NoiseOverlay\n", + "\u001b[0;31mString form:\u001b[0m \n", + "\u001b[0;31mFile:\u001b[0m /home/xilinx/jupyter_notebooks/dds_test/noise_buffer_overlay.py\n", + "\u001b[0;31mDocstring:\u001b[0m \n", + "Default documentation for overlay hw/top_biastini_32bitDDS_noise_buffer.bit. The following\n", + "attributes are available on this overlay:\n", + "\n", + "IP Blocks\n", + "----------\n", + "axi_dma_0 : pynq.lib.dma.DMA\n", + "noise_tracker/axi_fifo_noise_buf_cfg : axitxfifo.AxiStreamFifoDriver\n", + "dds_hier_0/axi_fifo_pinc_0 : axitxfifo.AxiStreamFifoDriver\n", + "dds_hier_0/axi_fifo_scale_0 : axitxfifo.AxiStreamFifoDriver\n", + "rf_data_converter : pynq.overlay.DefaultIP\n", + "lmh6401_hier/axi_fifo_lmh6401 : axitxfifo.AxiStreamFifoDriver\n", + "axi_timer_0 : axitimer.AxiTimerDriver\n", + "dds_hier_0/axi_fifo_dac_scale_0 : axitxfifo.AxiStreamFifoDriver\n", + "dds_hier_1/axi_fifo_dac_scale_1 : axitxfifo.AxiStreamFifoDriver\n", + "dds_hier_1/axi_fifo_pinc_1 : axitxfifo.AxiStreamFifoDriver\n", + "dds_hier_1/axi_fifo_scale_1 : axitxfifo.AxiStreamFifoDriver\n", + "axi_gpio_adcio : pynq.lib.axigpio.AxiGPIO\n", + "zynq_ultra_ps_e_0 : pynq.overlay.DefaultIP\n", + "\n", + "Hierarchies\n", + "-----------\n", + "dds_hier_0 : pynq.overlay.DefaultHierarchy\n", + "dds_hier_1 : pynq.overlay.DefaultHierarchy\n", + "lmh6401_hier : pynq.overlay.DefaultHierarchy\n", + "noise_tracker : pynq.overlay.DefaultHierarchy\n", + "dds_hier_0/dac_prescaler_wrapper_0 : pynq.overlay.DefaultHierarchy\n", + "dds_hier_0/dds_wrapper_0 : pynq.overlay.DefaultHierarchy\n", + "dds_hier_1/dac_prescaler_wrapper_1 : pynq.overlay.DefaultHierarchy\n", + "dds_hier_1/dds_wrapper_1 : pynq.overlay.DefaultHierarchy\n", + "lmh6401_hier/lmh6401_spi_wrapper_0 : pynq.overlay.DefaultHierarchy\n", + "noise_tracker/adc00_energy_downsample : pynq.overlay.DefaultHierarchy\n", + "noise_tracker/adc00_energy_downsample/axis_x2_wrapper_0 : pynq.overlay.DefaultHierarchy\n", + "noise_tracker/adc02_energy_downsample : pynq.overlay.DefaultHierarchy\n", + "noise_tracker/adc02_energy_downsample/axis_x2_wrapper_0 : pynq.overlay.DefaultHierarchy\n", + "noise_tracker/noise_event_tracker_0 : pynq.overlay.DefaultHierarchy\n", + "\n", + "Interrupts\n", + "----------\n", + "None\n", + "\n", + "GPIO Outputs\n", + "------------\n", + "None\n", + "\n", + "Memories\n", + "------------\n", + "PSDDR : Memory\n", + "\u001b[0;31mClass docstring:\u001b[0m\n", + "This class keeps track of a single bitstream's state and contents.\n", + "\n", + "The overlay class holds the state of the bitstream and enables run-time\n", + "protection of bindings.\n", + "\n", + "Our definition of overlay is: \"post-bitstream configurable design\".\n", + "Hence, this class must expose configurability through content discovery\n", + "and runtime protection.\n", + "\n", + "The overlay class exposes the IP and hierarchies as attributes in the\n", + "overlay. If no other drivers are available the `DefaultIP` is constructed\n", + "for IP cores at top level and `DefaultHierarchy` for any hierarchies that\n", + "contain addressable IP. Custom drivers can be bound to IP and hierarchies\n", + "by subclassing `DefaultIP` and `DefaultHierarchy`. See the help entries\n", + "for those class for more details.\n", + "\n", + "This class stores four dictionaries: IP, GPIO, interrupt controller\n", + "and interrupt pin dictionaries.\n", + "\n", + "Each entry of the IP dictionary is a mapping:\n", + "'name' -> {phys_addr, addr_range, type, config, state}, where\n", + "name (str) is the key of the entry.\n", + "phys_addr (int) is the physical address of the IP.\n", + "addr_range (int) is the address range of the IP.\n", + "type (str) is the type of the IP.\n", + "config (dict) is a dictionary of the configuration parameters.\n", + "state (str) is the state information about the IP.\n", + "\n", + "Each entry of the GPIO dictionary is a mapping:\n", + "'name' -> {pin, state}, where\n", + "name (str) is the key of the entry.\n", + "pin (int) is the user index of the GPIO, starting from 0.\n", + "state (str) is the state information about the GPIO.\n", + "\n", + "Each entry in the interrupt controller dictionary is a mapping:\n", + "'name' -> {parent, index}, where\n", + "name (str) is the name of the interrupt controller.\n", + "parent (str) is the name of the parent controller or '' if attached\n", + "directly to the PS.\n", + "index (int) is the index of the interrupt attached to.\n", + "\n", + "Each entry in the interrupt pin dictionary is a mapping:\n", + "'name' -> {controller, index}, where\n", + "name (str) is the name of the pin.\n", + "controller (str) is the name of the interrupt controller.\n", + "index (int) is the line index.\n", + "\n", + "Attributes\n", + "----------\n", + "bitfile_name : str\n", + " The absolute path of the bitstream.\n", + "dtbo : str\n", + " The absolute path of the dtbo file for the full bitstream.\n", + "ip_dict : dict\n", + " All the addressable IPs from PS. Key is the name of the IP; value is\n", + " a dictionary mapping the physical address, address range, IP type,\n", + " parameters, registers, and the state associated with that IP:\n", + " {str: {'phys_addr' : int, 'addr_range' : int, 'type' : str, 'parameters' : dict, 'registers': dict, 'state' : str}}.\n", + "gpio_dict : dict\n", + " All the GPIO pins controlled by PS. Key is the name of the GPIO pin;\n", + " value is a dictionary mapping user index (starting from 0),\n", + " and the state associated with that GPIO pin:\n", + " {str: {'index' : int, 'state' : str}}.\n", + "interrupt_controllers : dict\n", + " All AXI interrupt controllers in the system attached to\n", + " a PS interrupt line. Key is the name of the controller;\n", + " value is a dictionary mapping parent interrupt controller and the\n", + " line index of this interrupt:\n", + " {str: {'parent': str, 'index' : int}}.\n", + " The PS is the root of the hierarchy and is unnamed.\n", + "interrupt_pins : dict\n", + " All pins in the design attached to an interrupt controller.\n", + " Key is the name of the pin; value is a dictionary\n", + " mapping the interrupt controller and the line index used:\n", + " {str: {'controller' : str, 'index' : int}}.\n", + "pr_dict : dict\n", + " Dictionary mapping from the name of the partial-reconfigurable\n", + " hierarchical blocks to the loaded partial bitstreams:\n", + " {str: {'loaded': str, 'dtbo': str}}.\n", + "device : pynq.Device\n", + " The device that the overlay is loaded on\n", + "\u001b[0;31mInit docstring:\u001b[0m \n", + "Return a new Overlay object.\n", + "\n", + "An overlay instantiates a bitstream object as a member initially.\n", + "\n", + "Parameters\n", + "----------\n", + "bitfile_name : str\n", + " The bitstream name or absolute path as a string.\n", + "dtbo : str\n", + " The dtbo file name or absolute path as a string.\n", + "download : bool\n", + " Whether the overlay should be downloaded.\n", + "ignore_version : bool\n", + " Indicate whether or not to ignore the driver versions.\n", + "device : pynq.Device\n", + " Device on which to load the Overlay. Defaults to\n", + " pynq.Device.active_device\n", + "gen_cache: bool\n", + " if true generates a pickeled cache of the metadata\n", + "\n", + "Note\n", + "----\n", + "This class requires a HWH file to be next to bitstream file\n", + "with same name (e.g. `base.bit` and `base.hwh`).\n" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "ol = DDSOverlay(bitfile_name='hw/top_biastini_750kHz_SPI.bit',dbg=True,plot=True,n_buffers=1,download=True)" + "ol = DDSOverlay(bitfile_name='hw/top_biastini_750_kHz_SPI.bit',download=True)" ] }, { diff --git a/pynq/noise_buffer_overlay.py b/pynq/noise_buffer_overlay.py index ec1dd49..54057b8 100644 --- a/pynq/noise_buffer_overlay.py +++ b/pynq/noise_buffer_overlay.py @@ -30,6 +30,7 @@ def __init__(self, bitfile_name=None, dbg=False, plot=False, **kwargs): self.timer = self.axi_timer_0 self.lmh6401 = self.lmh6401_hier.axi_fifo_lmh6401 self.noise_buffer = self.noise_tracker.axi_fifo_noise_buf_cfg + self.adc_gain = [self.noise_tracker.adc00_energy_downsample.axi_fifo_adc_gain, self.noise_tracker.adc02_energy_downsample.axi_fifo_adc_gain] xrfclk.set_ref_clks(lmk_freq=122.88, lmx_freq=409.6) if dbg: @@ -40,18 +41,21 @@ def __init__(self, bitfile_name=None, dbg=False, plot=False, **kwargs): self.timer.start_tmr() self.axi_mm_width_words = 8 # 128-bit / 16 bit/word self.noise_buffer_sample_depth = 2**15 - self.noise_buffer_tstamp_depth = 2**10 - self.dma_frame_size = (self.noise_buffer_sample_depth + self.noise_buffer_tstamp_depth) * self.axi_mm_width_words + self.dma_frame_size = self.noise_buffer_sample_depth * self.axi_mm_width_words self.dma_frame_shape = (self.dma_frame_size,) # we can use unsigned types since the noise will always be a positive number + # actually this is not quite true, since we're applying a lowpass filter after squaring the signal, we could end up with some close-to-zero values going below zero self.dma_buffer = allocate(shape=self.dma_frame_shape, dtype=np.uint16) self.dbg = dbg self.plot = plot - self.t_sleep = 0.008 # seems like there are sometimes AXI transaction reorderings, so add a delay as a # sort of "manual fence" # having a single AXI-slave device with multiple registers instead of # separate AXI GPIOs should prevent issues arising from transaction reordering + self.t_sleep = 0.008 + # thresholds for sample discriminator + self.threshold_low = 0 + self.threshold_high = 0 def set_freq_hz(self, freq_hz, channel = 0): pinc = int((freq_hz/self.f_samp)*(2**self.phase_bits)) @@ -94,8 +98,51 @@ def set_vga_atten_dB(self, atten_dB, channel = 0): print(f'packet = {hex(packet)}') self.lmh6401.send_tx_pkt([packet]) time.sleep(self.t_sleep) + + def set_adc_digital_gain(self, gain, channel = 0): + # scale is 2Q16, so quantize appropriately + quant = int(gain * 2**16) + if (quant >> 16) > 1 or (quant >> 16) < -2: + raise ValueError(f'cannot quantize {gain} to 2Q16') + if quant < 0: + quant += 2**18 + # write to fifo + if self.dbg: + print(f'setting adc_gain scale_factor to {quant / 2**16 - (0 if quant < 2**17 else 4)} ({quant:05x})') + self.adc_gain[channel].send_tx_pkt([quant]) + time.sleep(self.t_sleep) + def dma(self): time.sleep(self.t_sleep) self.dma_recv.transfer(self.dma_buffer) - time.sleep(self.t_sleep) \ No newline at end of file + time.sleep(self.t_sleep) + + def set_discriminator_threshold(self, thresh_high, thresh_low = None): + # configuration packet is 34 bits, so we need two words + # {mode, start, stop, threshold_high, threshold_low} + # always capture start: {1, 0, 16'b0, 16'b1} + # always capture stop: {0, 1, 16'b0, 16'b1} + if thresh_low is None: + thresh_low = thresh_high + self.threshold_low = int(thresh_low * 2**16) + self.threshold_high = int(thresh_high * 2**16) + packet = [(((self.threshold_high & 0xffff) << 16) | (self.threshold_low & 0xffff)), 0x0] + if self.dbg: + print(f'setting discriminator thresholds {thresh_low}-{thresh_high}') + print(f'packet = {[hex(p) for p in packet]}') + self.noise_buffer.send_tx_pkt(packet) + + def start_capture(self): + packet = [(((self.threshold_high & 0xffff) << 16) | (self.threshold_low & 0xffff)), 0x2] + if self.dbg: + print(f'sending start command with discriminator thresholds {self.threshold_high & 0xffff}:{self.threshold_low & 0xffff}') + print(f'packet = {[hex(p) for p in packet]}') + self.noise_buffer.send_tx_pkt(packet) + + def stop_capture(self): + packet = [(((self.threshold_high & 0xffff) << 16) | (self.threshold_low & 0xffff)), 0x1] + if self.dbg: + print(f'sending stop command with discriminator thresholds {self.threshold_high & 0xffff}:{self.threshold_low & 0xffff}') + print(f'packet = {[hex(p) for p in packet]}') + self.noise_buffer.send_tx_pkt(packet) \ No newline at end of file diff --git a/pynq/noise_buffer_test.ipynb b/pynq/noise_buffer_test.ipynb index b853fc5..8fadbb9 100644 --- a/pynq/noise_buffer_test.ipynb +++ b/pynq/noise_buffer_test.ipynb @@ -19,7 +19,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 2, "id": "6a8ca05a-7041-41cb-826d-24af876405c0", "metadata": {}, "outputs": [ @@ -27,198 +27,332 @@ "name": "stdout", "output_type": "stream", "text": [ - "loading bitfile hw/top_biastini_32bitDDS_noise_buffer_ILA.bit\n", - "loaded bitstream\n", - "set clocks\n" - ] - } - ], - "source": [ - "ol = NoiseOverlay(bitfile_name='hw/top_biastini_32bitDDS_noise_buffer_ILA.bit',download=True,dbg=True,plot=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "id": "bb84e069-b754-4a9b-8f1c-a3bbf31e8e06", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "setting dac_prescale scale_factor to 0.5 (08000)\n", - "setting dac_prescale scale_factor to 0.5 (08000)\n", - "setting cos_scale to 3 (18dB attenuation)\n", - "setting cos_scale to 3 (18dB attenuation)\n", - "setting vga attenuation to 18dB\n", - "packet = 0x212\n", - "setting vga attenuation to 18dB\n", - "packet = 0x10212\n", - "setting pinc to 996147 (9.500e+05Hz)\n", - "setting pinc to 996147 (9.500e+05Hz)\n" + "loading bitfile hw/top_biastini_noise_buffer_corrected_fp.bit\n" ] - } - ], - "source": [ - "ol.set_dac_scale_factor(0.5,0)\n", - "ol.set_dac_scale_factor(0.5,1)\n", - "ol.set_dac_atten_dB(18,0)\n", - "ol.set_dac_atten_dB(18,1)\n", - "ol.set_vga_atten_dB(18,0)\n", - "ol.set_vga_atten_dB(18,1)\n", - "ol.set_freq_hz(950e3,0)\n", - "ol.set_freq_hz(950e3,1)" - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "id": "d7c3e2e2-4340-4bcd-91f2-b3a99a31c66b", - "metadata": {}, - "outputs": [ + }, { "data": { - "text/plain": [ - "[]" + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" ] }, - "execution_count": 88, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" }, { "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "loaded bitstream\n", + "set clocks\n" + ] } ], "source": [ - "# configure noise buffer and capture some data\n", - "# configuration packet is 35 bits, so we need two words\n", - "# {mode, start, stop, threshold_high, threshold_low}\n", - "# always capture start: {0, 1, 0, 16'b0, 16'b1}\n", - "# always capture stop: {0, 0, 1, 16'b0, 16'b1}\n", - "start_pkt = [0x00ff, 0x2]\n", - "stop_pkt = [0x00ff, 0x1]\n", - "ol.noise_buffer.send_tx_pkt(start_pkt)\n", - "time.sleep(0.01)\n", - "ol.noise_buffer.send_tx_pkt(stop_pkt)\n", - "ol.dma()\n", - "plt.plot(ol.dma_buffer)" + "ol = NoiseOverlay(bitfile_name='hw/top_biastini_noise_buffer_corrected_fp.bit',download=True,dbg=True,plot=False)" ] }, { "cell_type": "code", - "execution_count": 89, - "id": "873c1e9b-b3ca-4bcf-a419-96e241055783", + "execution_count": 3, + "id": "c62826b6-ec86-4605-b93f-baba47fe36bb", "metadata": {}, "outputs": [ { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "/tmp/ipykernel_1330/1042108181.py:8: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.\n", - " data = np.array([ch0, ch1])\n" + "setting dac_prescale scale_factor to 0.0 (00000)\n", + "setting dac_prescale scale_factor to 0.0 (00000)\n", + "setting vga attenuation to 0dB\n", + "packet = 0x200\n", + "setting vga attenuation to 0dB\n", + "packet = 0x10200\n", + "setting adc_gain scale_factor to 1.0 (10000)\n", + "setting adc_gain scale_factor to 1.0 (10000)\n" ] } ], "source": [ - "ch0 = []\n", - "ch1 = []\n", - "for samp in ol.dma_buffer[:1000]:\n", - " if samp & 0x4:\n", - " ch1.append(samp & 0xf8)\n", - " else:\n", - " ch0.append(samp & 0xf8)\n", - "data = np.array([ch0, ch1])" + "ol.set_dac_scale_factor(0,0)\n", + "ol.set_dac_scale_factor(0,1)\n", + "ol.set_vga_atten_dB(0,0)\n", + "ol.set_vga_atten_dB(0,1)\n", + "# to keep full scale, multiply by 0.5, but we can always adjust to improve dynamic range\n", + "ol.set_adc_digital_gain(1,0)\n", + "ol.set_adc_digital_gain(1,1)" ] }, { "cell_type": "code", - "execution_count": 71, - "id": "0340d655-b8c4-4e99-807f-b08996446212", + "execution_count": 123, + "id": "3604e022-82dc-4972-b9ce-6bcc926a5dcd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "750\n", - "250\n" + "setting discriminator thresholds 0.16-0.16\n", + "packet = ['0x1470147', '0x0']\n", + "sending start command with discriminator thresholds 327:327\n", + "packet = ['0x1470147', '0x2']\n", + "sending stop command with discriminator thresholds 327:327\n", + "packet = ['0x1470147', '0x1']\n" ] } ], "source": [ - "print(len(ch0))\n", - "print(len(ch1))" + "# configure noise buffer and capture some data\n", + "ol.set_discriminator_threshold(0.005*32)\n", + "ol.start_capture()\n", + "time.sleep(10)\n", + "ol.stop_capture()\n", + "time.sleep(0.1)\n", + "ol.dma()" ] }, { "cell_type": "code", - "execution_count": 75, - "id": "bb0e95a7-33e2-4302-b13a-09d63b7dd295", + "execution_count": 135, + "id": "d7c3e2e2-4340-4bcd-91f2-b3a99a31c66b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['010', '010', '001', '000', '000', '100', '100', '000', '010', '010', '001', '000', '000', '100', '100', '000', '010', '010', '001', '000', '000', '100', '100', '000', '010', '010', '001', '000', '000', '100', '100', '000']\n" + " processing channel\n", + "n_timestamps = [ 0 1 2 3 5 6 7 8 10 11 12 13 15 16 17 18 20 21 22 23 25 26 27 28\n", + " 30 31 32 33 35 36]\n", + "raw channel data = ['0x57b6', '0xb682', '0xc12', '0x2', '0x19c', '0xbdd2', '0xb686', '0xc12', '0x2', '0x14c', '0xf916', '0xb686', '0xc12', '0x2', '0x14c', '0x47a2', '0xb696', '0xc12', '0x2', '0x15c', '0x5ab2', '0xb69e', '0xc12', '0x2', '0x184', '0x2b26', '0xb6aa', '0xc12', '0x2', '0x154', '0x4b02', '0xb6b2', '0xc12', '0x2', '0x16c', '0x5ad6', '0xb6b2', '0xc12', '0x2', '0x15c']\n", + "bad timestamp near raw channel data index [58631 58632 58633 58635]\n", + "bad timestamp near raw channel data index [58636 58637 58638 58640]\n", + "bad timestamp near raw channel data index [58641 58642 58643 58645]\n", + "bad timestamp near raw channel data index [58646 58647 58648 58650]\n", + "bad timestamp near raw channel data index [58651 58652 58653 58656]\n", + "bad timestamp near raw channel data index [58657 58658 58659 58661]\n", + "bad timestamp near raw channel data index [58662 58663 58664 58666]\n", + "bad timestamp near raw channel data index [58667 58668 58669 58671]\n", + "bad timestamp near raw channel data index [58672 58673 58674 58676]\n", + "bad timestamp near raw channel data index [58677 58678 58679 58681]\n", + "additional errors suppressed\n", + "raw channel data = [('0x0', 't', 58620), ('0x2e', 's', 58621), ('0x2c9d', 't', 58622), ('0x39e5', 't', 58623), ('0x305', 't', 58624), ('0x0', 't', 58625), ('0x29', 's', 58626), ('0x1757', 't', 58627), ('0x39ea', 't', 58628), ('0x305', 't', 58629), ('0x0', 't', 58630), ('0xdf7', 't', 58631), ('0x14e', 't', 58632), ('0x0', 't', 58633), ('0x1c', 's', 58634), ('0x326f', 't', 58635), ('0xdf7', 't', 58636), ('0x14e', 't', 58637), ('0x0', 't', 58638), ('0x22', 's', 58639)]\n", + "type(t_0) = \n", + "raw_timestamp_words_grouped = [[0x15ed 0x2da0 0x304 0x0]\n", + " [0x2f74 0x2da1 0x304 0x0]\n", + " [0x3e45 0x2da1 0x304 0x0]\n", + " ...\n", + " [0x1003 0x14e 0x0 0xb42]\n", + " [0x1003 0x14e 0x0 0xd7c]\n", + " [0x1003 0x14e 0x0 0xee2]]\n", + "timestamps[-1][0] = 0x304b6815ed\n", + "timestamps[-1][-1] = 0x3b880000539003\n", + "type(timestamps[-1][-1]) = \n", + "n_t_update = [-1 4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 84 89 94]\n", + "timestamps = [ 0 22919 26712 80891 114879 160988 195795 196808 298922 345244\n", + " 392821 450321 489239 575160 617463 641107 679228 731606 738372 756861]\n" + ] + }, + { + "ename": "ValueError", + "evalue": "could not broadcast input array from shape (5,) into shape (0,)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [135]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 82\u001b[0m lower \u001b[38;5;241m=\u001b[39m n_t_update[n] \u001b[38;5;28;01mif\u001b[39;00m n_0 \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;241m4\u001b[39m\n\u001b[1;32m 83\u001b[0m \u001b[38;5;66;03m# subtract extra 4 to offset for the timestamp samples\u001b[39;00m\n\u001b[0;32m---> 84\u001b[0m \u001b[43mtvec_raw\u001b[49m\u001b[43m[\u001b[49m\u001b[43mlower\u001b[49m\u001b[43m:\u001b[49m\u001b[43mn_t_update\u001b[49m\u001b[43m[\u001b[49m\u001b[43mn\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m=\u001b[39m timestamps[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m][n] \u001b[38;5;241m-\u001b[39m t_0 \u001b[38;5;241m-\u001b[39m np\u001b[38;5;241m.\u001b[39mfloat128(\u001b[38;5;241m4\u001b[39m) \u001b[38;5;241m+\u001b[39m np\u001b[38;5;241m.\u001b[39marange(n_t_update[n\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m-\u001b[39m n_t_update[n], dtype\u001b[38;5;241m=\u001b[39mnp\u001b[38;5;241m.\u001b[39mfloat128)\n\u001b[1;32m 85\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m n_0 \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 86\u001b[0m \u001b[38;5;66;03m# we need to correct the first element, since it is 4 too small\u001b[39;00m\n\u001b[1;32m 87\u001b[0m tvec_raw[lower] \u001b[38;5;241m=\u001b[39m timestamps[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m][n] \u001b[38;5;241m-\u001b[39m t_0\n", + "\u001b[0;31mValueError\u001b[0m: could not broadcast input array from shape (5,) into shape (0,)" ] } ], "source": [ - "print([f'{(i & 0x7):03b}' for i in ol.dma_buffer[:32]])" + "# process data to separate out channels and timestamp vs sample data\n", + "# first check to see if we have any full timestamps\n", + "# if we do, throw out all data until the sample before the first timestamp for each channel (since we don't know when it occurred)\n", + "# if we don't, proceed\n", + "ch = [np.take(ol.dma_buffer, np.asarray(ol.dma_buffer & 1 == i).nonzero()[0]) for i in range(2)]\n", + "data = []\n", + "tvec = []\n", + "timestamps = []\n", + "for c in ch:\n", + " print(f' processing channel')\n", + " # find the number of timestamps\n", + " n_timestamps = np.asarray(c & 2 == 2).nonzero()[0]\n", + " valid_timestamp = False\n", + " n_0 = 0\n", + " print(f'n_timestamps = {n_timestamps[:30]}')\n", + " print(f'raw channel data = {[hex(i) for i in c[:40]]}')\n", + " if len(n_timestamps) >= 4:\n", + " # find first valid timestamp\n", + " while True:\n", + " if n_0 + 3 > len(n_timestamps) - 1:\n", + " break\n", + " if (n_timestamps[n_0+3] == n_timestamps[n_0]+3):\n", + " # since n_timestamps is strictly increasing and takes on integer values,\n", + " # n_timestamps[n_0+3] == n_timestamps[n_0]+3 is equivalent to n_timestamps[n_0:n_0+4] = [i, i+1, i+2, i+3] for some i\n", + " valid_timestamp = True\n", + " break\n", + " n_0 += 1\n", + " # check for errors\n", + " n = n_0\n", + " err_count = 0\n", + " while True:\n", + " if n + 3 > len(n_timestamps) - 1:\n", + " break\n", + " error = False\n", + " for i in range(4):\n", + " if n_timestamps[n+i] != n_timestamps[n] + i:\n", + " error = True\n", + " if error and err_count < 10:\n", + " print(f'bad timestamp near raw channel data index {n_timestamps[n:n+4]}')\n", + " err_count += 1\n", + " if err_count == 10:\n", + " print(f'additional errors suppressed')\n", + " err_count += 1\n", + " n += 4\n", + " \n", + " print(f\"raw channel data = {[(hex(x >> 2),'t',n+58620) if x & 2 == 2 else (hex(x >> 3),'s',n+58620) for n,x in enumerate(c[58620:58640])]}\")\n", + " # now n_timestamps[n_0] holds the index into c for the first valid timestamp\n", + " # extract the data\n", + " if (n_timestamps[n_0] == 0) or (not valid_timestamp):\n", + " # just ignore the existence of timestamps; we have a contiguous block of data\n", + " data.append(np.take(np.right_shift(c.astype(np.int16), 3)/2**13, np.asarray(c & 2 == 0).nonzero()[0]))\n", + " else:\n", + " # n_timestamps[n_0] > 0 and we have a valid timestamp\n", + " # trim all data up to the point before the first timestsamp\n", + " data.append(np.take(np.right_shift(c[n_timestamps[n_0]-1:].astype(np.int16), 3)/2**13, np.asarray(c[n_timestamps[n_0]-1:] & 2 == 0).nonzero()[0]))\n", + " # by default, no need to do anything fancy if we have no timestamps: we assume all data is consecutive\n", + " \n", + " if not valid_timestamp:\n", + " timestamps.append(np.array([], dtype=np.float64))\n", + " tvec.append(np.arange(data[-1].shape[0], dtype=np.float64))\n", + " else:\n", + " tvec_raw = np.zeros(c.shape[0], dtype=np.float64)\n", + " # update tvec with timestamp info\n", + " # now extrapolate between the supplied timestamps to get the timestamp for each data point\n", + " # index into original raw channel data for datapoints which should have a tvec update:\n", + " n_t_update = n_timestamps[n_0::4] - 1\n", + " raw_timestamp_words = np.take(np.right_shift(c.astype(np.uint16), 2), n_timestamps[n_0:])\n", + " raw_timestamp_words_grouped = raw_timestamp_words[:4*(len(raw_timestamp_words) // 4)].reshape((len(raw_timestamp_words)//4,4))\n", + " concat_timestamps = np.inner(raw_timestamp_words_grouped, 2**(14*np.arange(4, dtype=np.uint64)))\n", + " timestamps.append(concat_timestamps)\n", + " t_0 = timestamps[-1][0]\n", + " print(f'type(t_0) = {type(t_0)}')\n", + " print(f'raw_timestamp_words_grouped = {np.array2string(raw_timestamp_words_grouped, formatter={\"int\":lambda x: hex(x)})}')\n", + " print(f'timestamps[-1][0] = {hex(timestamps[-1][0])}')\n", + " print(f'timestamps[-1][-1] = {hex(timestamps[-1][-1])}')\n", + " print(f'type(timestamps[-1][-1]) = {type(timestamps[-1][-1])}')\n", + " #for i, timestamp in enumerate(timestamps):\n", + " print(f'n_t_update = {n_t_update[:20]}')\n", + " print(f'timestamps = {timestamps[-1][:20] - t_0}')\n", + " for n in range(len(n_t_update)-1):\n", + " # if n_0 == 0, then n_t_update will contain -1 for the first iteration\n", + " lower = n_t_update[n] if n_0 >= 0 else 4\n", + " # subtract extra 4 to offset for the timestamp samples\n", + " tvec_raw[lower:n_t_update[n+1]] = timestamps[-1][n] - t_0 - np.float128(4) + np.arange(n_t_update[n+1] - n_t_update[n], dtype=np.float128)\n", + " if n_0 >= 0:\n", + " # we need to correct the first element, since it is 4 too small\n", + " tvec_raw[lower] = timestamps[-1][n] - t_0\n", + " # update the end of the vector\n", + " tvec_raw[n_t_update[-1]:] = timestamps[-1][-1] - t_0 - 4 + np.arange(len(tvec_raw)-n_t_update[-1], dtype=np.float128)\n", + " tvec_raw[n_t_update[-1]] = timestamps[-1][-1] - t_0\n", + " # take only valid entries\n", + " tvec.append(np.take(tvec_raw[n_timestamps[n_0]-1:], np.asarray(c[n_timestamps[n_0]-1:] & 2 == 0).nonzero()[0]))\n", + " print(f'tvec = {tvec[-1][:20]}')" ] }, { "cell_type": "code", - "execution_count": 105, - "id": "e2881afc-2332-4606-aa81-add4d2e7fbc9", + "execution_count": 85, + "id": "0340d655-b8c4-4e99-807f-b08996446212", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "['0000', '6594', '40dc', '0006', '0000', '59de', '40dc', '0006']\n", - "['02aa', '0026', '0332', '0006', '03aa', '0026', '03fa', '0086']\n" - ] + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZgAAAEGCAYAAABYV4NmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABIu0lEQVR4nO3deXhU5dnA4d+TyUoICWEnCYQl7CC7KGoVtAgVQVTE1rrUulStW0XRtlY/q+KG1dZqtVq1WhERERVFFMUVZAn7vpOEsCchkH3e748zEybJbElmJiHz3NeVK5mzvufM5Dzz7mKMQSmllAq0iIZOgFJKqaZJA4xSSqmg0ACjlFIqKDTAKKWUCgoNMEoppYIisqETEArJCbGma89+td7v6IlSWjaLDlg6fB7vxBFolhyw89XlmMfzDhCf1NbtunrdDw/pCNU9PnqilOMlFaS2jAvYMX2tq4u6nisY1+3ps+ArHYD79V4+i1lHi9ym0dNyf9Z7S7/HNHpx9EQpLSms9f+ox/t14oj129vx3N2zvD2Q1KlWaQDv98pTGlesWHHIGNOm1idzMsY0+Z/+qc1NXcz4fHOd9qvz8RY9FtDz1eWYP/z7Dx7X1et+eEhHqO7xjM83m8kv/RDQY/paF8pzBeO6PX0WfKXD43ovn0VPafSVdm/rvaW/Lu/bjM831+l/1Ov98HU8d+tfG1vrNBjj/V55SiOw3NTj2atFZEoppYJCA4xSSqmgCGqAEZELRWSziGwTkWlu1ouIPO9Yv0ZEBvvaV0QGisgSEVklIstFZHgwr0EppVTdBK2SX0RswAvABUAWsExE5hljNrhsNhbIcPycDrwInO5j3yeBh40xn4rIOMfrc2ubvrKyMrKysiguLva4zZmtyti4cWNtD1334yWdBwE8n3XMc4nduZPU1FSioqICe2yllPIimK3IhgPbjDE7AERkJjABcA0wE4A3HZVJS0QkSUQ6AOle9jVAC8f+iUBOXRKXlZVFQkIC6enpiIjbbfYXFNOuRWxdDl+34xXsgxYdAnY+AJOfw+GyaLKysujSpUtAj62UUt4EM8CkAHtdXmdh5VJ8bZPiY987gQUi8jRWEd+ZdUlccXGx1+DSVIgIrVq14uDBgw2dFKVUmAlmHYy7J3f1oZs9beNt398Bdxlj0oC7gFfdnlzkRkcdzXJ7hd19Apt4cHEKl+tUSjUuwQwwWUCay+tUahZnedrG277XAHMcf7+HVRRXgzHmZWPMUGPM0AibNpZTSqlQC+aTdxmQISJdRCQamALMq7bNPOBqR2uyEUC+MWafj31zgJ85/h4FbA3iNQRVbm4uU6ZMoVu3bvTp04dxl13Fli1b2LVrF/36VR154KGHHuLpp5+ucYySkhKuuOIKunfvzumnn86uXbtClHqllPIuaHUwxphyEbkNWADYgNeMMetF5GbH+peA+cA4YBtwArjO276OQ98APCcikUAxcGOwrsHV3MxsnlqwmZy8IjomxTF1TE8mDkqp8/GMMVxyySVcc801zJw5E4BV3y1k//79pKWl+dj7pFdffZWWLVuybds2Zs6cyX333ce7775b53QppVSgBHUsMmPMfKwg4rrsJZe/DXCrv/s6ln8HDAlsSr2bm5nN/XPWUlRWAUB2XhH3z1kLUOcg89VXXxEVFcXNN99cuWzggH7QokOtciEffvghDz30EACXXXYZt912G8YYrXdRSjW4sBjs0peHP1rPhpyCGsvLKuxE2SLI3JNHabWGAkVlFdw7ew3v/LTH7TH7dGzBX8b39XjOdevWMWSI5zi5fft2Bg4cWPk6NzeXe+65p8Z22dnZlTmeyMhIEhMTOXz4MK1bt/Z4bKWUCgUNMH6oHlx8LQ+Ebt26sWrVqsrXzlxKdVYmsCrNvSilGgMNMOAxp+HsGDly+iKy84pqrE9JiuPdm86o0zn79u3L7Nmz67Svq9TUVPbu3Utqairl5eXk5+eTnBzgIf+VUqoOtP2uH6aO6UlclK3KsrgoG1PH9KzzMUeNGkVJSQmvvPJK5bJlK1axePHiWh3n4osv5o033gBg9uzZjBo1SnMwSqlGQQOMHyYOSuHxSf1JSYpDsHIuj0/qX69WZCLCBx98wMKFC+nWrRt9+/bloenP0LFjx1od5/rrr+fw4cN0796dGTNmMH369DqnSSmlAkmLyPw0cVBKvQKKOx07dmTWrFknF7iMRbZu3boq23qqg4mNjeW9994LaLqUUioQNAejlFIqKDTAKKWUCgoNMEoppYJCA4xSSqmg0ACjlFIqKDTAKKWUCgoNMA0oEMP1f/PNNwwePJjIyMiAjAyglFKBogHGX2tmwbP94KEk6/eaWT538cY5XP+5557L9u3b2bBhA489OI39+/fX6jidOnXi9ddf55e//GW90qOUUoGmHS39sWYWfHQ7lDnGI8vfa70GGDC5TocM1HD96enpAERE6HcFpVTjogEG4NNpkLu2xuKWFXawRUDWMqgoqbqyrAg+vA1WvOH+mO37w1jPw7YEarh+pZRqrDTA+KN6cPG1PAD8Ha5fKaUaKw0w4DGncdQxXD/P9rOKxapLTIPrPqnTKQM1XL9SSjVWWnDvj9EPQlRc1WVRcdbyOgrUcP1KKdVYaYDxx4DJMP55K8eCWL/HP1/nCn4I3HD9y5YtIzU1lffee4+bbrqJvn09T9OslFKhpEVk/howuV4BxZ1ADNc/bNgwsrKyApoupZQKBM3BKKWUCgoNMEoppYIirAOMMaahkxAS4XKdSqnGJWwDTGxsLIcPH27yD19jDIcPHyY2Nrahk6KUCjNhW8mfmppKVlYWBw8e9LhNQVEZR+KiAnZOn8crzofYvICdzzpmHrFJ7UlNTQ3scZVSyoewDTBRUVF06dLF6zbPLtzCXRf0CNg5fR7vq8fhvPsDdr7KYw4K8DGVUsoPYVtEppRSKrg0wCillAoKDTBKKaWCQgOMUkqpoAhqgBGRC0Vks4hsE5FpbtaLiDzvWL9GRAb72ldE3hWRVY6fXSKyKpjXoJRSqm6C1opMRGzAC8AFQBawTETmGWM2uGw2Fshw/JwOvAic7m1fY8wVLud4BsgP1jUopZSqu2DmYIYD24wxO4wxpcBMYEK1bSYAbxrLEiBJRDr4s6+ICDAZeCeI16CUUqqOghlgUgDXWbqyHMv82caffc8G9htjtro7uYjcKCLLRWS5vcJeh+QrpZSqj2AGGHGzrPq4LJ628WffK/GSezHGvGyMGWqMGRph07YMSikVasHsyZ8FpLm8TgVy/Nwm2tu+IhIJTAKGBDC9SimlAiiYX+2XARki0kVEooEpwLxq28wDrna0JhsB5Btj9vmx7/nAJmOMzrSllFKNVNACjDGmHLgNWABsBGYZY9aLyM0icrNjs/nADmAb8Apwi7d9XQ4/Ba3cV8qruZnZvPbdTpbuPMLI6YuYm5nd0ElSYSaog10aY+ZjBRHXZS+5/G2AW/3d12XdtYFLpVJNz9zMbO6fs5aisgoAsvOKuH/OWgAmDqreXkap4NDab6WaoKcWbK4MLk5FZRU8tWBzA6VIhSMNMEo1QTl5RbVarlQwaIBRqgnqmBRXq+VKBYMGGKWaoKljehIbVfXfOy7KxtQxPRsoRSoche2Mlko1ZRMHpVBcVs60OesASEmKY+qYnlrBr0JKczBKNVFj+3cErGExvp82SoOLCjkNMEo1UVYvAKUajgYYpZoou8YX1cA0wCjVRGkORjU0DTBKNVGag1ENTQOMUk2U5mBUQ9MAo1QTpTkY1dC0H4xSTZRxzNEXijgzNzObpxZsJjuviISYSLq0jtdm0UoDjFJNVahyMNVHbj5WUq4jNytAi8iUarLsIYowOnKz8kQDjFJNVKjq+HXkZuWJBhilmih7iCKMjtysPNEAo1QTFapGZFPH9CTKJlWW6cjNCjTAKNVkhSoHM3FQCuf2aFP5OiEmkscn9dcKfqWtyJRqqkLZ0bJFXDQAQzq35KzurTW4KEBzMEo1WaHsaJlbYFXol1fYQ3dS1ehpgFGqiQrlSDG5+cUAlGmAUS48FpGJyN1+7H/cGPOvAKZHKRUgoaqDAdhfUAJAWYWOT+PkOrrB7BVZYTmjqLcczFSgOZDg5ecPwU6gUqpuQhVgCkvKKSwpB6DcrjkYODm6QbajL1B2XhH3z1nL3MzsBk5ZaHmr5P+vMeb/vO0sIvEBTo9SKkBClYFxFo+B5mCcvI1uEE65GI85GGPMvb529mcbpVTDCFWA2V9gBZiYyAitg3HQ0Q0sHgOMiIwXkc4urx8UkdUiMk9EuoQmeUqpugpVEZkzB5PeKp5yzcEAOrqBk7c6mEeBgwAichFwFfAbYB7wUvCTppSqj5AFGEcOpkvreM3BOLgb3QDg8qGpDZCahuMtwBhjzAnH35OAV40xK4wx/wbaeNlPKdUIhKofTG5+MYlxUbSMj9I6GIeJg1Jo3yK2Msh0SIwlKS6KeatyKCqt8LF30+EtwIiINBeRCGA08KXLutjgJkspVX+hy8G0bxFLXFSktiJz2Lr/GHuPFjFtbG/uGJ3Bj/eP5p9XDWbHoeNM/3RjQycvZLwFmL8Bq4DlwEZjzHIAERkE7PPn4CJyoYhsFpFtIjLNzXoRkecd69eIyGB/9hWR3zvWrReRJ/1Ji1LhJlQ5mP0FxbRLjKVZtM2Rg9FczPsrs7FFCBef1rFy2ZndWnP9WV1448fdfLv1YAOmLnS8tSJ7DfgZcD0wzmVVLnCdrwOLiA14ARgL9AGuFJE+1TYbC2Q4fm4EXvS1r4icB0wABhhj+gJP+7xKFdbmZmbz2nc7WbrzCCOnLwqbvgihmnAsN7+Y9i1iiIu2AVAeyjFq3Jibmc3I6YtYuvNwg7zfFXbD3MxsftajDW0SYqqsmzqmJ93bNmfqe2soLmv6RWXeWpE9ZozJNsZkYhWRAWCM2WeM2ePHsYcD24wxO4wxpcBMrMDgagLwprEsAZJEpIOPfX8HTDfGlDjSc8C/S1XhyNnh7ZijI2A4dXgLxXO+vMLOocISRxGZI8A0YD1MY+jg+OP2w+QWFDNpcM3+LrFRNp6dPJBDhSV8vbnpP7q8FZFd6PL3E3U4dgqw1+V1lmOZP9t427cHcLaILBWRxSIyrA5pU2EinKfzNSEoqjpYWILdUFlEBg07HlljeL/nrMwiITaS83u3c7u+f2oit4/OYNP+Y2zZfyxk6WoIwRzssmYbvZqFs5628bZvJNASGIE1nM0sEamxvYjcKCLLRWS5XZtOhq1w7vAWilbKzj4w7VvENooisoZ+v4+XlPPpulwuGtCRWEeOzp1bzu1GuxaxLNp0gAMFxR63O9V5CzBtReRuEfmDy9+VP34cOwtIc3mdCuT4uY23fbOAOY5itZ8AO9C6+smNMS8bY4YaY4ZG2HTQ6HAVzh3eQtEPxtmLv33iySKyhszBNPT7/dm6XIrKKrjUTfGYq0hbBGP6tqfcbufe99eEdO6eUPL25H0Fa0DL5i5/u/74sgzIEJEuIhINTMHqpOlqHnC1ozXZCCDfGLPPx75zgVEAItIDiAYO+ZEeVUfOStPnvtx6ylWSTx3Ts/LB5xQu0/mGIiOxzyUH0yzaGtqwIfvCTB3TE1tEw03fPCczi07JzRjSuaXPbZObRXNW9zZ8vfkg7/y01+f2pyKPg10aYx6uz4GNMeUichuwALABrxlj1ovIzY71LwHzsVqobQNO4Gid5mlfx6FfA14TkXVAKXCNaarhvxFwVpo6y7WdlabAKTFonzONd727qrLs9cHxvU+JtNdXKP4tcguKibZFkBwffbKIrAFzMBMHpfDY/I0cOGZNH9AhMZb7LuwVkvc7J6+IH7Yf5o7RGbgptXfrtNREziptzV8/2cDI7q3o3KppjR/srRXZjb529rWNMWa+MaaHMaabMeZRx7KXHMEFRzHXrY71/Z19bTzt61heaoy5yhjTzxgz2BizyJ8LVXXTGCpN62vioBRaxEUSExmBAUrKwqNOLhRfu/bnF9O2RQwi0iiKyHLzizlwrISR3VsB8NyUQSH7MvFBZjbGwKRB/g8HIyI8dfkAbBHC3bNWU9HATbwDzVsR2TQRmeTl51LgjlAlVDWMhq40DRRjoHmMjdNSE3lr6Z4mW+btKhR1MM5e/IBLK7KGu7ffb7NKy38z0hqPd3OIWmkZY5izMoth6S3p1KpZrfbtkBjHIxP6sWL3UV7+ZkeQUtgwvAWYxcB4Lz8XAQuDnUDVsBq60jRQrEee8KsRndl2oJClO480cIqCLxRfhvcXlNAusWqAacjhYr7bdohW8dGc17MtNhG25IYmwKzJymf7weNMGly3wSwnDOzIL/p3YMbCzWzIKQhw6hqOt5781/nxc2cI0xoyp3KldqC5qzSNiYw49SrJjVX/Mn5AR1rERvL2Un/6Cp/agp1LM8Y4evFbASa2gXMwxhi+23aI37fJJOK5/txme5/b11wCa2YF/dxzVmYRHRnBuP4d6rS/iPDIxH4kNYvm7lmrKClv+F7+czOziWqT3r8+x9D2u9U0hp7AjcnEQSkkx0cRE2l9VCIE2reIqTLG0qnAOCJMXLSNy4ak8dm6fRx0VAQ3VcHOwRQUl1NUVnGyiCyqYSv5tx4o5IzjX3LVwWcgfy8CtLEfwHx0e1CDTGm5nXmrc7igTzsS46LqfJzk+GieuLQ/m3KPMWPhlgCmsPacz0GxRUbX5zgaYKppCpXagZR19AQHj5UydUxP7hidwdOXn8buI0X876dTKwfg+mX+VyM6UVZhmLW8aTYNdQp2DsbZB8ZZRBZpiyBCGi4H8+3WQ9wbOYvIiqodF6WsCL70Ovt7vXy9+QBHT5RxWR2Lx1yN6tWOK4d34uVvdrBsV8MV47p7DtaFzwDjbvbKpjyjZVOp1A6U77ZalaY/62FNAXTJoBTO7NaKJz7bxIFjp04PZNfhIbq1ac6Z3Vrxv6V7mlyrHVfBvjRnH5gOiSdn74iMkAZrRfb9tkN0jDjsfmV+VtDOO2dlNq2bR3N2Ro3+3nXyp1/0Jq1lM+6etYrSBrqXgXre+ZODed/NstkBOXsj1FQqtQPlm60Had8ilu5tmwNWWfFfJ/ajpMzOIx+fOvNaVP8yf9WIzmTnFbF4S9MdcDDYrcj2u3SydIqyRTTIYJdlFXaW7DhMYWSy+w0SgzOTZN6JUr7ctJ8JA1OIDNCIIfExkcyYfBpZR4v4ZkvDDOsfqOedt34wvRxNkROrNU++liY84djUMT2JrFapHX0qVmoHQIXd8N3WQ5zTo3WVjmNd2zTn1vO689HqHBY30D9A7Rlc+75d0KcdbRNieGvJqVXUVxt1fsyvmQXP9mPE3lfg2X4e6y+cUyW3bWENST83M5sTpRWs31cQ8sYxmXvy6FS2k2bmBNWHMjQAZ/4+KOf9aM0+yiqM25GT62NoejI3ndONdTn5LNq0P6DH9oe7ETDqwlvI7YnVFDmJqs2TBwM31PvMjdTEQSkMTEvE5ngaRUYIsZERnNsz/GaJXp2VR0FxOWdn1Lz2m8/tStc28fxp7tpTYgpYZzNlpyhbBFOGpfHV5gPsPXLC026ntDrVwayZBR/dXllJTv5e67WbIJNbUExyfDQxkbbKSmHnGUPdOGbj6iW8Hf0oEc1awpi/QmIaBjgS0YoybLD5UwhC8+n3V2TRq30CfTq0CPix77ogg9bxMdw7ey1HjpcG/PjeTByUwuOT+mMqyut1Ym/NlD80xlwHXFStafLtxpgf6nPSxi4iIoIhnVtyx+gM5t46kqKyCu5rwgPSefLtlkOIwFnda5Ytx0TaeHRif/YeKeLvi7Y2QOpqx91bN2V4JwR45xRrsOCvWheRFR6Az+6Hsmrl7x4qyffnF9POUTzWoI1jDmxi4uqbwRZNxLUfwxm3wV3rWJJ2A8+dNo/HzW9gx1fw08sBPe32g4Ws2pvHpMEpfg8NUxsxkTbG9GtPflEpf/xgbcifPxMHpVB2cNfa+hzDn0LDG0Xkteo/9TlpY5d9tIiOSdY/Tr+URO4d04sF6/c32QHpPPl260EGpCTSMt59S8UzurXisiGpvPzNjkY/r4UxpsYcEB2T4hjdux2zlu+ltLzpDR/j9Qt7eSlkr4AlL8Hs6+Fv/eHpDDjhYdxYN5XkVi9+q3isoRrHdCzfi/2N8ZTYhbkDXoJW3aqs79E+gf+UnEtx+mj44i9wYFPAzv3BymwiBCYMDN5QNG2ax3D3BT35dF0uc1edel0l/AkwHwOfOH6+BFoAhcFMVEMqr7CTW1BMSsuTlVzXn9WFszNa838fr2fbgcb9IA2UguIyMvfmuS0ec/XAuN4kxEbywJy1IZuit87cfMm8akRnDhWW8tn63NCnJ8iqvBsFObB+Liz4I7z6c3g8FV4ZBZ/dB3t+hI6D4OePQnxb9wdzU0m+v6CY9o4WZA3SOObQNv58+D7KKuxcWfpH+vQfUmOTHu0SAGHFaY9AdDx8cCMR9rJ6n9puN3yQmc1ZGW0qc3HBcuM5XRnauSUPfrj+lGvN6jPAGGPed/l5G5gM9At+0hrGgWMlVNgNKUknxxOKiBCemXwa8dGR/P6dxtHLNth+2HaYCrvhnB7eA0xyfDQPjOvN8t1HebcR9ysxxv0sdmd3b03nVs14a8nukKcpaMqKYe9PdN/+Ov+Ieo4fYm6DGb3hvWvgp1esbYbfAJe/AXdtgLs3wOQ34czbYMyjEOUmKHQ9t8rL0nI7hwpLKx+uniqFz+/tIWA5OEfNWLrzSO0aBhzeDm9chI0K/t3lOXIiOzG4c1KNzXq0tWYWWVsQC+Ofg32rrcYL9bR05xGy84p8zvvilqMRBYunw5J/+uwEanM8fyrshqmzV4dkENNAqUu7ugygU6AT0lg4e/A7i8ic2ibE8tTlA9i4r4AnPm36nS6/2XqQ+Ggbgzol+dz2siGpnN4lmcfnb2y0veM9/U9GRAi/HN6Jn3YeafTFfG4ZA3l76HHwc/h0Grwy2sqdvHoBAzc8xWmyg+X2nnDhE/DbRXB/Flz/uRVI+k6ExGoPyAGTYfzzlZXkJKZC2z6weibsWVq5WeVEY44A46wUToixZgDpmBhLl1bNeGfZXo8dBus8asaRHfD6RVBRyiPJTzAnqznDuyQTE1kzwCU2i6J9i1hrTLLe42HgVQzLeoOOBat931sv5qzMonlMJD/v0752O7o0ogCgpMBjIwpXnVvF86df9OH7bYcr7/2pwJ+OlsdEpMD5G/gIuC/4SWsYzixoasua3+JG9WrHtWem89r3O/lqc9PtP2GM4ZstBzmjW2ui/GjbLyI8ekl/isoqePSTDSFIYe0ZatbBOF0+NI1oWwRvnwq5mNITsPsH+O5vMPNX8ExP+Ft/frHlj7DidYiMgTNuhSve5oPRX3F26XPcXvZ7GHEzpA4Bf0b+GDC5spKcu9bDdfMhKQ3evQryrYd/9V78YAWZ35zVhTtGZ/DD/aOZc8tIUpLiuOHN5Ww/WLNUvU4NA47ugtfHQ3kxXD2P7ZLG9oPH3TZEccpo15wtzqLtCx/nWEx7xmz9C5TU7QtFUWkF89fuY1z/9pVz4Pjty//zuxFFdVcOT+O8nm3YffQE2w6cGrUU/hSRJRhjWrj87mGMcdf5sknIOurMwbgvO542the92icw9b3Vjfbben3tOnyCrKNF/KyH/z2Tu7dtzu/O7c7cVTl8u7Xx9Y0xrl35q0mOj2Zc//bMWZnN8ZLykKbLK2Osb+ur34VP7uGXq66G6Wnwn7GOCusNVtHVuKd5+7T/wv17rWBwwcPQ+yKKogPTs5y4ljDlHetB+O6vsFUUV/aBce3FX13L+Ghev24YNhGu/c9PHC+tem9r3TDg6G4ruJQWwtUfQvt+5BdZxxzpJcD0bJfA1v2F1qgNsS1YkPEQicU5sOABb1ft0ecbcjleWlG3kZM9jSjgx0gDIsITlw7AJsIfZq1q0Hl3/OVXEZmjg+UMEXlGRCYGOU0BF11xwmuHMVfZeUW0bBZVOf1rdbFRNp6/chDHisu5573Vjb9iuw6cAcJXBX91t5zbjS6t4/nz3HUUB2Aco8Dz3JT0qhGdOVZSzrzVOSFMTzUlhaTmLYdvnob/TYGnusPzg+CDG2H1O5RExsPIO+HKd2Hqdrg9k7ld/sLIRd3441IbI5/6tkrxUkB78rftBZe+AjmruGD7Y+Q6gkB7HxXcnVvF8+q1wzh4rIR5q3I44RJkatUwIG8vvDEeSvLh6g+Zm9uKkdMXsePQcSIENu/zPMR9j/YJlJTb2XPkBHMzs3lkbRIvlo+HlW+yZP5//bj4qt5fmU1KUhzD0z2MGuBNjIf+MnG+p1gGaNsili6t41mdlc8/v9pe+/OHmD9FZP8EbgbWAuuAm0XkhWAnLOC8dBhzlZNXVKUFmTs92iXwp4v6sHjLQf7zw64AJrJx+GbLITolNyO9de2mb42NsvHXif3YdfgEL3y1LUipqxtPlfxOQzq3pFf7BN5asjs0/Q2MgUNbIfNt+OhOePEsmJ7G5et/B4segSPboccYuOhvcPP3MG0P7/d7EUb/GXpeCPGtfdZhBPw6eo6FUX+k98FPSd/6H2IiI/waPXhgWhJ/v3IwB44Vc/s7mZXjv7lrGBAXZas5akZ+NrxxERTlwa/nMnd/myrXbTfwwNx1HutuerazKvrf/HEX989Zy7GScp4tv4wN9s5kLH2AT3/0vz6msKSc77YeZNLgFCIiatH3xRj48hErQLr7JJYW+j3ic6v4aCYO7MjfF21lTVae/2loAP7kYH4GjDHG/McY8x9gHHBuUFMVLH6UdWYfLaJjou+mlVed3onze7fjiU83sT4nP1ApbHDGGH7cfqjOA/eN7N6aSYNSeGnx9kbVpNvXo1bEmoxsfU4Bq/bmBT4BxfmwfRF8/QS8dRk8kQ7/GAof3gLr5kDzNnDOvczp8xzcuxNuWwYT/wlDr4P2/SCiZlm/rzqMoGSuz76HLa3OZ9TeFxgfv9HvDoYX9GnHuT3b8sXGAzw0bz3GmMqGAdEu9Xz3XtizyhTHLSsOW8HlxBH49RxIGVzruhvnOHqzV2RV7ldGJHeU3UpzikhY+Ae/55felFuA3ViDvvrNGPj8T/Dt0zD4Gve5lYrSWo34/PDF/WjdPIa73l3VSEsLLP4EmM1UbTWWBqwJTnJCIH8vvHyuVWH52f3w4wuw4UPIXoE5lsu+vOM+czBgPZCevGwALeOjuP2dzCpZ/1NZYXE5x0sral085uqBX/SmWXQkD8xZ17iKEH08Cy8ZlEJ8tK3+45PZ7XBgI6x4Az68DV4YAdM7w38vga8fh4Js6HMxXPwPuGUp3LcLfv0BnHc/u1ueCc38K3rxVYfhmoMJWG5GhAUZD7InsjMPlT5jNRf202mpSdx0Tlf+u2Q3r3xrTQ08cVAKXdvEV843VKVRybFcHjx8rzXCwFXvQ+pQoPZ1N/ExkaQlx3GsuOr/6FaTyhPlUzjLvgxWvuHHFRg27itgUKckurZp7sf2gN3OeTuegh//AcNvsppKFx11v20tRnxObBbFU5cPYPvB4zz5WeNt1eq+oqGqVsBGEfnJ8XoY8KOIzAMwxlwcrMQFRVQ8xCXDwS2wbRGUHa9cJcAKiaR4Qwc4nM7PT7QAWx+rqWZiKiSmQYsUiLE+XMnx0cyYPJCrXl3KIx9v5PFJ9Zr8rVHIKyrDFiGc2b1VnY/RunkMD4zrxX3vr2X2iiwmD0sLYAprz/lw9fVdu3lMJBMHpTB7RRZ/vqg3Sc38nGvpxBGrV/zenyBrmfV3iaNOIK4lpA6DfpOs3ymDITax7hfjomNSXGUxUfXlUDUHU2E3RNoCM5xJuS2OeyOn8ZqZCu9cCb/9AmL9G4vrvgt7kZ1XxGPzN9EhMY7xp3XkWHE5zWMiadcikkWbDnDViM5wbD+8MZ5k+2G45kNIG17l+rxdtzs92yWwL6+Y8mpfeP5TMYbRESsZ+sk0Ntj6c9qAwR6Lvg4cK0GOlzLpPD8r9+0V8NEdDMx9D868HS74PxCxniX5bvqM1XLE57Mz2nDNGZ157fudnN+7LWd6aejQUPwJMA8GPRWhEhUH4/9mNcMEK+tadNT6RpmfRc7urcz75icublVBYsVh0vKWw7efgqnWWiOuJbSwgs7IxFRe6x7DnOU/sCR5DyMGnQbN24PNn1vrsGaWlT3O3wur3obRD55MY4jMzczmqQWbubywCJsIizYeqFJUUVuXD0nj/RXZPPbpRkb3bkvdw1X9zM3M5skF1vAg+/KLmZuZ7fW6rhrRmbeX7mH2iix+e3bXmhtUlMPBjY5gspxrNn8H3ztyPBIB7fpC/8usYJI63Bq6JAjjVIFVhzF19uoqE3xFRkhlHYZr+fw5T37FvRf2qtd7epJhVWEic/s9zlWbb4c5N8KU/0GE7wKRiAjh6ctP40BBCX+YtZot+4+Rk1+EMVBcXkH25hMUHc2l7LVxRB3L4pqSe8n+3wmmjjn5vk0d05P756ytUkzmtu7GRUa7BL7ceIDYyAiKXYYFirJF8ma7e+l38Bbsc27iZ/Mf4xeDOnHJoBR6trfqbpz/G9l5RdwZCX7F6YpymPs7WDuLJWm/ZYQzuID1//3R7VWbK4vNWl5L08b25tuth7jnvdV8dtc5tIit+4yaweDzKWiMWRyKhARdQgfrG4Trg1vEKo5olgzt+7OufBDTy7tx5oUj6ZiaxKsLt3DXqK5wbJ+Vfc3PsoKAIyCRvxf2/MB5xfmcFw18/Q/4GuvD0qKjS84nFVqk0OVIBOSWWq9jE63zOzteOT9szsYIELIg46wsLiqrgEgorbBz/xxrjLu6PpAiIoRHL+nHuOe/5dH5G5nRAINRV7kurG/0vq6rd4cWDOnckreX7uE3I7sQceIQXY98A1+848idrDyZ623WmqPN+pA88lormHQcVJm7DYXxp3Xk0U82cPREGeV2Q7NoG0WlFfTt2IK5mdl8vGZf5bY5+cX1fk+disrslJbbKUkdCV2fgPn3wNePwag/+bV/bJSNl68ews+fXczfF51sDHK8pIJkCjj0zzG0Ls3hurJ7+cn0BkfjBWfanel/8MN1FBSX0zEx1mfw7NkuAQP85qwu/PNrq1gvJSmOqWOsOp+SzBKGfHgjdzb7hHu/HcNLi7fTu0MLMtrE8/mG/VWC0iMfb6RZdKTn81WUwfvXW0Xvox/kx+LxjHD9kuH8v/7kD1ZONzbRqqM7VvvhiuKibcy4YiCXvvgDD81bz4zJA2t9jGDyGWBEZBLwBNAWq5RBAGOMCfz41MF0/UKrs5gXJ3vxu2S1bZHWft72LS4ga/c2/u/tzxna8ji/7R9NRIEjIO39yRoDyl7GRADnHF3RCVagObrT6jTmytkYIUQBxlulaX0eRhntErjpnG7846tt3DXsBKEuKKv1dVWUwf51PNj2W3asWkzJjN8TV7iHCQARkdC+Pwz6lSN3MgxapjPvi63cdXaPkFxPdR+vyeFgYSn//NVgNuce4+ozOjPqmcU8+OF69hw5XqM4KBDvKVj1dOBootz/t5C7Br55ysq90devYyQ1i67RQCCJY7wd/RhtSvfxm7KpLLH38Zj2iYNS2HnoOM99uZXvp43y2digh6MlWQtHq7fze7fl39cMq1wfM+gK2L6ASze8xejf/JK5+9syd1UO81yCtKe0VFFeAu9dC5vnw5jH4YxbYOGWmtsNmHyy/urcadYwPl/8BToMqDEsjy8D05K49dxuPL9oGz/v044L+3Wo1f4eHdlZ70P4U47zJDDeGHPqTF/oToTvS83JKyImMoJWHkYP9ii2Bak9B3PBxW2YOnsNZQN7cuuk7ifX2+1w/ADvLPyBK3uKS24oyypucSeIU7yCda3Ldh1h2a4jbsuzndvU122juvPRmhwWbTrAFWUVxAZgEiN/+awMPpZr5UocxV3kZEJ5EacBHW0t2WT6MeiC3/JubgeuGH8RRDdze7yGYLcbXvhqGxltm3Nh3/Zszj1Gq+YxTB3Tkz/NXedxv0C8p87OqO0TY61c+Lin4eBmmHsLrfu+wqF4/wLugYKTHZUTKeTt6MfoKvu4vuwefrDXHO6wetqdHQ39acnWtU08tghhXbbV4tPmrp5l3NOw+0eSPruNa29czLUju9Bl2iduWyC6vY+lJ6zGQ9u/hF88A8N+6zNdjguACS9Y9/C96+CmxZBUu9G4fj86g0WbD/DAB+sY0jmZNgkxtdq/UuEBWP+BVbKSvbxux3DhTyuy/ad8cAG/Akx2XhEpSXF1ntvhsiGpjD+tIzMWbiFzj0tLkYgISGhPbkI/6HuJNbve2CdgyttWwwFP6V31jjWsej3Z7YYt+4/x1pLd3Dkzk5HTF3Hm9EXcMXMVH6zMrmzBU10gRsJ19o05WlTKi1+HtmNYy/iT5dHRlDFQtvEb26e80uyfVsfbZ3paD4SlL4G9zGoSfNlrcOc6/j1sPpcdvYX9/W8ip8XARhVcABasz2XL/kJuG9W9SqX0lcM70T8lEU9dNBLjourdoqzQNcCANTzN5P9CbBIXb7yH2LI8v47j/Hy1oJC3oh+ju2RzQ9ndfGd331gmJiqCAy7jcJVV2H023HCKjbLRuVUz1udYjS9s7v7HmyVbTcMPbYEvHqqSRk9pr1RSCP+bbDVFn/CC/8HFKSYBrngb7OXw7q9rDifjQ5QtgmcnD6SwpJz759Ry7qriAvoc+Nhq5fhMT/j0Xisndv7DtbsGN/zJwSwXkXeBuUDlVw5jzJx6nz2UXv4ZnP+Q12Kn7KO+O1l645yvfuXuo9w+M5P5t59Ngq9KN3cVfrZoaNYa5t5sFZWN+B0Mudbvljql5XbWZuexbNdROqzK5sFvFpJfZA1R3iYhhmHpLfnt2V0Ylp5Mr/YJfLxmX60rTWvj7Iw2FLZL4I6vt3PxwI5087eJZy24VsS+t2Iv57QtYUTRjwyO3MqgiG30k13EiHUP8mxtIXWkdV9Th1tFX1FVe6T/csRx/vXtTs6fsZhjxeXMXpFVWV7f0IwxPL9oG11bx3PRgI5V1tkihEcm9mPiC9/X2C9CrFaCN7y5gumX9qd187p9yy0sKUcE2rp+S05oB1PeJv7VC7lo0zQYswBs3j/7U8f05LE5S3hFptNDsrip7C5+ihgEdjuREVKliC8yQigrtzP6mcXcO7YXzaNs/O+nPRhg5PRFfr03Pdsl8Ok6q57DbQ4GoNt5cPrvYOmL0GMMU8f08v2/UZwPb19u5YInvQIDLveaDo9ad4dL/gUzr4T/TrLqY2vR8CejXQL3XdiLRz7ewHvLfbTeLC+BrZ/D2vdgywLGlBdDUmc4626rkUrb3o4N76rbtTj4E2BaACeAn7ssM8CpFWAKsn1WnmfnFdO7nlOfJsZF8dyUgUz+1488+OF6nr1ioPcdnGlxtiJLTLM+TP0vh21fwPfPwcI/W2XcQ661Hootqj5UCorLWLn7KMt3HeWnXUdYvTePEkel5MMJZVzYtz1D01syvEsynZKb1cihOf8xn1qwGQqrVn4Gyjk92hB7OII/frCWd24YEdAZAOct386sDz9inH0zg6K2MahoGx32HIFoKJNoVlWk83rFz8m0Z5Bp705BRRse797f6/Vl7skjQqjsO5FdraK5IX2x8QAb9xXw9OWnuX1Q7jp0HFuEVPaYB6vi9MphaXRp05wnF2xmzLPfMP3SAVzQp12tz19YUk6r+JiaA6GmDGZhtwcYu/Uv1jhf457yepyJvRM4p/XfSDi6h5tL72BrizOZPqYn//lhF3nHSzh6oqxKJf5paUn88YO1/HnuOkRO9o30973p4RJgvPbCP/8vVk5k7i1MvOVHmNS/8stLQkwUj1/k8tk5cQTemgS56+Dy/0CfCd5vni+9xkGvi2DTxyeX1aLhz3VnprNwQy4Pf7SeM7q1Ii35ZM5bTAXsWGwFlQ3zrFEF4tvA4Gt4p/h0rrxkUsBbPPrTiuy6gJ6xIXmpPC8uq+BQYUlAioWGpidz++gM/vbFVs7p0ZpLBvlo3z5gsvXz1eNw3v0nl2dcYP1kr4Qf/m511lryIkW9JvFTh1+y6Ehrlu06Wtm72BYh9OvYgqtGdGZYejJD01vSetkaOG+AzzQ7W+f8+Op87rx+VD3vQE3x0ZFMG9ubBz5Yy/srs7lsSB0GCgTH8PS7rW+Ljn4nY3PWcLGtHGywx96GpfZeZNozyIrvyzZJZ3d+tU6wflR2P7Vgc42e8IGqJK8PYwx/X7SVtOQ4Jgzs6HabpxZsrhJcwPpG+PWWQzw6aQDn9GjDnTNXccOby5k8NJUHx/eleYz/zeoLS8ppn+g+97Op7TjaHN/K0J9ehnb9YMg17g9ScgzeupTk/A0w5U0KFyfz/U1nALDnyAme/WILlw9JZdbyrCqV+G//9nQGP7KQoyeqThrmz3vjrOgHLzkYsLozTHoZ/j0aPr6LiZe/zsRBKTy7cAvXR3YB5zmOH4I3J8KhzXDFW9YQPoGwb1XNZX42/HE2Ax/7t2/5w6zVvHPD6dhyV8Ha2fzzwDvw5hGIbm5NXdD/MuhyLtgiyV24JSjN6T1+qkTkXmPMkyLyd9yMtGGMuT3gqQkFD5Xn+/Ktst2UAM3Ad9t53fl+2yH+PHc9Qzol06lV3crwjTFsj+rBss4Ps71kMr12/Zdx6+fysw3vImYg0W2u5ILzzmN411YMTEsivhYPilCbMiyN91dm8egnGxjVqy3J/jSmKD1uVb47K+KzlsFxa6qEsohYtkf1YFH5ODLt3cm0Z3CIk50YpQDA/QgLviq7G2oKYF++3nKQNVn5TJ/U3+NUCr7S3qNdAnNvHcnfvtjCS4u38+OOw8yYPJBhfg7eWFhcTkZbz8Wc36XfxtC4HKsZbpte0On0qhuUFFpFStkr4PLXodcvYPGPlatH9WrLjIVb+GxdLraIqpX4IkJeteDi67qderY/mWa3dTCuOg6E8x6wHupr36v5YD+WC29OsEZ4/uW70C2AX8ryPcyH42fDn9SWzXhqVDwbP3+FY8/cRNKJ3WCLZlvUUIZffCP0uND9pHJB4O1p5KzYr39TgsbEQ2/ZbB/D9NdWpC2CZ68YyNjnvuX2mZm8d/MZfu1XVmFnfU4By3ZaLbyW7z7KkeNWRX+r+GiGpt9NUco9nF/4MWdvfpNzDt0HUQOhw+8hcmJA0h4sERHCY5f05xfPf8vj8zfy1OWnVd3AOTx9ZcuuZbB/PRir/PtITBqrpT9fV3RmWXl3Nps0urZNJLuoiBNuZhl1vpe17fXtXO9uv1bNa9nCMKAMf/9yKylJcV6Hivenp3t0ZAT3XtiLUb3acves1Uz+14/ceE5X7r6gh9uJu1wVlpR7nSbYiM1qLPHKKKsRxY1fn5zYrPS4VRm+9ye47FVryJxq+nZsQbsWMewvKCHaTa/GuvTkB2tk52hbBKUVdu85GKeRd8KWBfDJPdDJ5f83PwveuBgK98NVsyH9LN/Hqo269vQv2Afr58Da97gwJ5OfRwlLC/vQ5bwnaT9iMs+8uYl3+/r3HAoUjwHGGPOR47c/g/S4JSIXAs8BNuDfxpjp1daLY/04rHqea40xK73tKyIPATcAzklHHjDGzPcrQVFxHnvLZuedANxPNFZXqS2b8fik/tz2v0wG/99CjpXUrCw+XlLOyj1HWbbrKJ1WZ/GnRQsoLrPqTzq3asaoXm0Zlt6SYenJdGkd7/JtbjCU3Qur37GKzt6/Hr58GEbcCoN/DZs+qd3oAI7RBEbk74VnPwvcaALVRinoOfpBbjhnAC9+vZ2fNu0ipWgTLy/dxcWtsmlfsBaKrNkPyyLj2R3biyVRl/JlYWdW2btRWJbIgNQkhp7Wkrs7JzOkc0taxkfX6FAJVSti69KAwV1vcQEOFZby5Geb6No6nme/2Ep2XlFAGgC4NlKofjzXdQCXDU4h2kPLP09p93TNQ9OT+fSOs/nrJxv41+IdLN58kIsHduTtJXu4vPAw97hUoM/NzObJzzZRUm5n3uochqUne75m5xwy/z7fmr/GXgEFWfDds1BRYgWgvpe43VVE6No6nv0FJZRWmBqV+HXpyQ/wyZp9lVMYzFudw4iurby/ZxE2q9L9pbPgrUu5/lg+lORa9aERUXDtR1WGsAkYdw1/wCpHejjZ+sL1cLJVJzv6Qdj4EaydBTu/tTbqMBB+/ih5XS7i969upfwbO8c+/4EKA93un8+Vp6fx14lWSz1fn7uoNun1Gv8qaOUpImIDXgAuALKAZSIyzxjjOuXhWKwpmDOA04EXgdP92PdZY8zTtUqQs/LcSwW/iEvTywAprzDYRDhWcrKy+N7Zq/lgZRZHTpSxYV8BFXZDhMBfkyqYMqwTw7skM7RzS9r6mGuDqFirae3ga6yOXT88D5/dZzWxtJdZTR7BdyWhy2gC4s/2/nI3SsGHt3Bt4iAmRO+jR3kWEdEGymFbbgpfxA5hqa0b35xIZ2txKvHl0Qzt3JKh6cn8Lj2ZAamJbvvRuDZScDY1r/7A//PcdRwrKfe7AYO7Y/5+VDcy9+Tzz6+3W72NHdvWtwFA9QDpejyoGSA/XruPszLaeDxX9bRH24THJ3lu1BAfE8njkwZwfu923DEz8+TgiZEn07J89xHeX5FdmY5jxeW+r7ltL6sO5sd/nFxWUWK1krR7HgF4bmY2K3bnVb6ufn/9eb/dHfP+OWsrW6adKK3w7z1L7gL9LoWVb1DZ/MdUgERas2sGI8DUaPiTCuVlUOCSqzEVsPxVWP4aYCC5K/zsPqtepXWGlXSgb4f9LN56qHK3CmMqB3Md2jnZ5+dObP5MgepZMAvshwPbjDE7AERkJjABcA0wE4A3jdVoe4mIJIlIByDdj339VmprBnd57nwGVhFZu4RYv6YIro2nFmymolqb9NIKw+KthxjRNZlbz+3G0PRkBnVKIuHHNXCefz2hq4iIgN4XWT97llplw/bqFdtFMPcWa/To6vavtwKSj+1/WVACO2rRtNXdcSvKaHNkGZtMfz6tGE6m6c4qe3cKiMdWKow/rQO/Tk9mWHoyGW2b+z3nhvPB8+zCLdx1QY8a63YeOs6SHYd59yb/iwjcHXPKcFi4cX9lsaVTUVkFU2ev5tXvat/7eVNuQZXxxFyPB9RYV1xm91mh7Zr2JTsO+xX4RvduR/PYKApLao5+4G6Eab8aPWz4sOYy59D0Hr68PLVgM6XVZmt015N/4qAUrvjXj369p/UarWL7oprLykuCO9pG9YY/D3upH7thEXQc7LaS/rtth93u8taSPby7bG+tPnd1EcwAkwK4FiRmYeVSfG2T4se+t4nI1Vj1Q38wxtQY/1pEbgRuBOjbwXcFuz8TjdWFp4pHAWbeGITy0E6n1xx6xsleBs3dNEt112rFzfbHi49D81pMQubpuMZwTdm0mqczhr9NGeT/8RvI0WrBxamswtSpB/XabPf/yN7+wYPV2GB/vofPTl3TUYcpgoPRwKJex6zHNMcBYzzl+AykDPG4W/Uvt648fb4CEVicvLUiexLYYYx5qdryu4D2xpj7fBzb3VfP6in3tI23fV8EHnG8fgR4BvhNjY2NeRl4GWBAWoLPO5adV8RpaUm+Nqu1ulZI1ovHSsI0+JWbWfOe7efX9h+6yR145eG4B8T9yJdBvScB5Ok9TUmK47Vrh7nZw7uR0xd5PB7UrZFCXXm6NpuI24eVz3TUocI6GP8z9TpmgIbXrxexuQ8y4r1Bhqf3zSZC+8TYWn/uastbedBFOB7Q1TwH/MKPY2dBlfENU4HqE5572sbjvsaY/caYCmOMHXgFqyiuXux2w778ooA1UXbl97SwgTT6wZrNEL00cKj19vVMx97BU0N/TwIo0O+pt+OF+vPj6XxXnp5Wt3TU4bMVjGuu1zGD9f9RG0Ourd1yhytPd9+b/8rT02r9uasLb0VkxvEQr77QLv51w14GZIhIFyAbmAL8sto287CKu2ZiFYHlG2P2ichBT/uKSAdjjHOI00sA75UrfjhYWEJZhQlKEVldKiTrzdPoAJ7Ki122N/l7EV/b1zMdwwZM5vG07NDekwAK9Hvqz/FCda+8jeowtHNy7dNR288iwfmfqX7MhJhIa0gdf47pSGvBJ3+mRUmuX9cQcBfNsH6veN3RyMBmBRfncg+crcXeWbqXCmM1OHJtRQbe7/Pkf9VzMERjjNsfHAHCzfIMYLmn/aptOw7YAmwH/uhYdjNws+NvwWotth1YCwz1tq9j+X8d267BClAdfKWjf2pz483yXUdM5/s+Nl9uzK2yfMbnm73uV1s+j7fosYCery7H/OHff/C4rl73w0M6QnWPZ3y+2Ux+6YeAHtPXulCeKxjX7emz4CsdHtd7+Sx6SqOvtHtb7y39dXnfZny+uU7/o17vh6/juVv/2thap8EY7/fKUxr9fdZ7+vGWg3kQ+FRE/gqscCwbCtwP3Oln8JoPzK+27CWXvw1wq7/7Opb/2p9z14azoi8lqXGNmKuUUqcybx0tPxWRicBU4PeOxeuBS40xaz3tdyo6OdFYYPvAKKVUOPPaTNkYsw7wMFpd05GTV0SL2EjfQ+srpZTym9dehSJyjYisEJHjjp/ljv4nTUr20aJTpomsUkqdKrz1g7kaq67lbmAlVoX8YOApEcEY82ZIUhgC2XlFAR2DTCmllPcczC3AJcaYr4wx+caYPGPMIuBSx7omw9lETymlVOB4CzAtjDG7qi90LKvftI+NSEFxGceKy7WITCmlAsxbgPE2TkDDzroUQJVNlLWITCmlAspbK7LeIrLGzXIBugYpPSEX6InGlFJKWbwGmJClogE5+8CkaoBRSqmA8tbRcre75SIyEmtcMLc98E811oRMEbRuXvth1pVSSnnm13wwIjIQK6hMBnYCc4KYppDKPlpEh6RYvye2Ukop5R9v/WB6YI1ifCVwGHgXEGPMeSFKW0jkaBNlpZQKCm+tyDYBo4HxxpizjDF/BzxPpH2Kys7TXvxKKRUM3gLMpUAu8JWIvCIio3E/0+Qpq7TczoFjJZqDUUqpIPAYYIwxHxhjrgB6AV8DdwHtRORFEfl5iNIXVLn5xRijfWCUUioYvA52CWCMOW6MedsYcxHW1MWrgGnBTlgoZOWdANAcjFJKBYHPAOPKGHPEGPMvY8yoYCUolHLyigENMEopFQy1CjBNjbMXf/tEnWhMKaUCLbwDTN4J2iTEEBtla+ikKKVUkxPWASYnr1iLx5RSKkjCOsDoPDBKKRU8YRtgjDFWgNEmykopFRRhG2AOFZZSWm6no1bwK6VUUIRtgMmunGisWQOnRCmlmqawDTCVM1lqHYxSSgVF2AYYZx8YDTBKKRUc4Rtg8opoHhNJizi/psRRSilVS2EdYDomxSLSpAaIVkqpRiN8A8xR7QOjlFLBFLYBJidf+8AopVQwBTXAiMiFIrJZRLaJSI0h/sXyvGP9GhEZXIt97xERIyKta5uu4yXl5J0o05kslVIqiIIWYETEBrwAjAX6AFeKSJ9qm40FMhw/NwIv+rOviKQBFwB76pI2baKslFLBF8wczHBgmzFmhzGmFJgJTKi2zQTgTWNZAiSJSAc/9n0WuBcwdUlYlgYYpZQKumAGmBRgr8vrLMcyf7bxuK+IXAxkG2NW1zVhlX1gtA5GKaWCJpgBxl373+o5Dk/buF0uIs2APwIP+jy5yI0islxEltsr7FXW5eQVERkhtE3QcciUUipYghlgsoA0l9epQI6f23ha3g3oAqwWkV2O5StFpH31kxtjXjbGDDXGDI2wVb3M7Lwi2ifGYovQPjBKKRUswQwwy4AMEekiItHAFGBetW3mAVc7WpONAPKNMfs87WuMWWuMaWuMSTfGpGMFosHGmNzaJCxH54FRSqmgC9o4KcaYchG5DVgA2IDXjDHrReRmx/qXgPnAOGAbcAK4ztu+gUpb9tEiRnRtFajDKaWUciOoA3EZY+ZjBRHXZS+5/G2AW/3d18026bVNU1mFndyCYq3gV0qpIAu7nvz7C4qxG22irJRSwRZ2AcbZRFl78SulVHCFXYDJydc+MEopFQphF2AqczCJGmCUUiqYwi/A5BXRKj6auGhbQydFKaWatDAMMNqCTCmlQiH8AszRE1o8ppRSIRBWAcYYQ47mYJRSKiTCKsAcPVFGUVmFNlFWSqkQCKsAUzlMvwYYpZQKuvAKMDrRmFJKhUx4Bhitg1FKqaALqwCTk1dEXJSNls2iGjopSinV5IVVgMk+WkTHpFhEdKIxpZQKtrAKMDn5RaS0bNbQyVBKqbAQVgEm+2gRKUmxDZ0MpZQKC2ETYIpKKzh8vFRbkCmlVIiETYDRYfqVUiq0wibA6DD9SikVWmETYHK0D4xSSoVU2ASY7LwiIgTatdBKfqWUCoXwCTBHi2jfIpYoW9hcslJKNaiwedpm5xVp8ZhSSoVQWAUYHaZfKaVCJ2wCTG5+sfaBUUqpEAqbAFNuN5qDUUqpEAqLAGOM9VvrYJRSKnTCI8A4fqdqDkYppUImLAKMMwujRWRKKRU6YRFgDJDULIr4mMiGTopSSoWNsAkwOgaZUkqFVlADjIhcKCKbRWSbiExzs15E5HnH+jUiMtjXviLyiGPbVSLyuYh09JkQoxX8SikVakELMCJiA14AxgJ9gCtFpE+1zcYCGY6fG4EX/dj3KWPMAGPMQOBj4EFfaTGgfWCUUirEgpmDGQ5sM8bsMMaUAjOBCdW2mQC8aSxLgCQR6eBtX2NMgcv+8ZxsJOaF0QCjlFIhFswAkwLsdXmd5VjmzzZe9xWRR0VkL/ArPORgRORGEVkuIssBXvx6G3Mzs+t4KUoppWormAFG3CyrntvwtI3XfY0xfzTGpAFvA7e5O7kx5mVjzFBjzFCAIyfKuH/OWg0ySikVIsEMMFlAmsvrVCDHz2382Rfgf8Cl/iaoqKyCpxZs9ndzpZRS9RDMALMMyBCRLiISDUwB5lXbZh5wtaM12Qgg3xizz9u+IpLhsv/FwKbaJMo5s6VSSqngClrPQ2NMuYjcBiwAbMBrxpj1InKzY/1LwHxgHLANOAFc521fx6Gni0hPwA7sBm6uTbq0N79SSoVGULu2G2PmYwUR12UvufxtgFv93dex3O8iseriomxMHdOzrrsrpZSqhbAZOyUlKY6pY3oycVD1hmxKKaWCISwCTJQtgu+njWroZCilVFgJi7HIlFJKhZ4GGKWUUkGhAUYppVRQaIBRSikVFBpglFJKBYUY48dgxKc4ETkG6BgxltbAoYZORCOh9+IkvRcn6b04qacxJqGuO4dFM2Vgs3PQy3AnIsv1Xlj0Xpyk9+IkvRcnOUejrystIlNKKRUUGmCUUkoFRbgEmJcbOgGNiN6Lk/RenKT34iS9FyfV616ERSW/Ukqp0AuXHIxSSqkQ0wCjlFIqKJp8gBGRC0Vks4hsE5FpDZ2eUBKRNBH5SkQ2ish6EbnDsTxZRBaKyFbH75YNndZQEBGbiGSKyMeO1+F6H5JEZLaIbHJ8Ns4I43txl+N/Y52IvCMiseFyL0TkNRE5ICLrXJZ5vHYRud/xHN0sImP8OUeTDjAiYgNeAMYCfYArRaRPw6YqpMqBPxhjegMjgFsd1z8N+NIYkwF86XgdDu4ANrq8Dtf78BzwmTGmF3Aa1j0Ju3shIinA7cBQY0w/rNlzpxA+9+J14MJqy9xeu+O5MQXo69jnn47nq1dNOsAAw4FtxpgdxphSYCYwoYHTFDLGmH3GmJWOv49hPUhSsO7BG47N3gAmNkgCQ0hEUoFfAP92WRyO96EFcA7wKoAxptQYk0cY3guHSCBORCKBZkAOYXIvjDHfAEeqLfZ07ROAmcaYEmPMTqxp7of7OkdTDzApwF6X11mOZWFHRNKBQcBSoJ0xZh9YQQho24BJC5W/AfcCdpdl4XgfugIHgf84igv/LSLxhOG9MMZkA08De4B9QL4x5nPC8F648HTtdXqWNvUAI26WhV27bBFpDrwP3GmMKWjo9ISaiFwEHDDGrGjotDQCkcBg4EVjzCDgOE23CMgrR/3CBKAL0BGIF5GrGjZVjVadnqVNPcBkAWkur1OxssBhQ0SisILL28aYOY7F+0Wkg2N9B+BAQ6UvREYCF4vILqxi0lEi8hbhdx/A+p/IMsYsdbyejRVwwvFenA/sNMYcNMaUAXOAMwnPe+Hk6drr9Cxt6gFmGZAhIl1EJBqrkmpeA6cpZEREsMraNxpjZrismgdc4/j7GuDDUKctlIwx9xtjUo0x6VifgUXGmKsIs/sAYIzJBfaKSE/HotHABsLwXmAVjY0QkWaO/5XRWPWU4XgvnDxd+zxgiojEiEgXIAP4ydfBmnxPfhEZh1X+bgNeM8Y82rApCh0ROQv4FljLybqHB7DqYWYBnbD+yS43xlSv7GuSRORc4B5jzEUi0oowvA8iMhCrsUM0sAO4DuvLZjjei4eBK7BaXGYCvwWaEwb3QkTeAc7Fmp5gP/AXYC4erl1E/gj8Bute3WmM+dTnOZp6gFFKKdUwmnoRmVJKqQaiAUYppVRQaIBRSikVFBpglFJKBYUGGKWUUkGhAUYppVRQaIBRqp4cw9/f4mFduogUiciqAJynm4isEpHC+h5LqVDQAKNU/SUBbgOMw3ZjzMD6nsQYE5DjKBUqGmCUqr/pgDN38ZS3DR05mk2OUYzXicjbInK+iHzvmORpuGO7nzmOt8ox6nFCSK5EqQCKbOgEKNUETAP61SJ30R24HLgRa7y8XwJnARdjDeUzEbgHuNUY871jNOziAKdZqaDTHIxSobfTGLPWGGMH1mPNIGiwxoxLd2zzPTBDRG4Hkowx5Q2TVKXqTgOMUqFX4vK33eW1HUepgjFmOtbAi3HAEhHpFdIUKhUAWkSmVP0dAwJaRyIi3Ywxa4G1InIG0AvYFMhzKBVsmoNRqp6MMYeB7x2V9l4r+WvhTsfxVgNFgM+h0ZVqbHS4fqWCSETSgY+NMf0CeMxCY0zzQB1PqWDRHIxSwVUBJAayoyXW5FBKNXqag1FKKRUUmoNRSikVFBpglFJKBYUGGKWUUkGhAUYppVRQ/D9OhISTVQxUNgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" } ], "source": [ - "print([f'{i:04x}' for i in ol.dma_buffer[8184:8192]])\n", - "print([f'{i:04x}' for i in ol.dma_buffer[8192:8200]])\n", - "#008603fa002603aa00060332002602aa" + "colors = plt.rcParams['axes.prop_cycle'].by_key()['color']\n", + "for c in range(2):\n", + " plt.plot(tvec[c][:500]/32e3, data[c][:500], 'o-', label=f'CH {c}')\n", + " for thi in timestamps[c][:100] - timestamps[c][0]:\n", + " plt.axvline(x=thi/32e3, linewidth=0.5, color=colors[c])\n", + "#plt.ylim(-0.1, 0.6)\n", + "plt.xlim(-0.1, 100)\n", + "#plt.xlim(5.8, 7)\n", + "plt.xlabel(\"t [ms]\")\n", + "plt.ylabel(\"ADC input [FS]\")\n", + "plt.legend()" ] }, { "cell_type": "code", - "execution_count": 103, - "id": "e561a515-d08d-4ac8-9ee0-e0a0591bf8ec", + "execution_count": 122, + "id": "e6e7d26c-dbfb-4c6c-9207-83be1488fe80", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[]" + "[]" ] }, - "execution_count": 103, + "execution_count": 122, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -230,13 +364,13 @@ } ], "source": [ - "plt.plot(ol.dma_buffer[8180:8200])" + "plt.plot(timestamps[0][:11000])" ] }, { "cell_type": "code", "execution_count": null, - "id": "15c25477-aa73-4685-8f5c-b148f210be65", + "id": "d6544897-d967-4b02-845e-03b77724089d", "metadata": {}, "outputs": [], "source": []