From 4d5471cc5d9e870eee4e2a74c43924cf8b0c3b2c Mon Sep 17 00:00:00 2001 From: Rob French Date: Wed, 29 Apr 2020 21:46:57 -0500 Subject: [PATCH] Updated local repository to 4.1.53 --- CHANGELOG.txt | 16 +- PKG-INFO | 2 +- __init__.py | 2 +- afedrinet/af_comp.bat.makeit | 1 + afedrinet/afedri.py | 36 ++- afedrinet/sdr_control.py | 8 +- configure.py | 8 +- docs.html | 12 +- dxcluster.py | 10 +- hermes/quisk_hardware.py | 13 +- quisk.c | 42 ++- quisk.egg-info/PKG-INFO | 2 +- quisk.egg-info/SOURCES.txt | 9 +- quisk.py | 74 +++++- quisk_conf_defaults.py | 5 + quisk_conf_openradio.py | 122 +++++++++ quisk_hardware_sdrmicron.py | 259 +++++++++++++++++++ setup.py | 2 +- soapypkg/build/import_quisk_api.o | Bin 30752 -> 29784 bytes soapypkg/build/temp.linux-x86_64-2.7/soapy.o | Bin 83640 -> 65328 bytes softrock_tune_vfo.py | 19 ++ 21 files changed, 559 insertions(+), 83 deletions(-) create mode 100755 afedrinet/af_comp.bat.makeit create mode 100755 quisk_conf_openradio.py create mode 100755 quisk_hardware_sdrmicron.py create mode 100755 softrock_tune_vfo.py diff --git a/CHANGELOG.txt b/CHANGELOG.txt index aaa1471..75e33ab 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,15 @@ +Quisk Version 4.1.53 March 2020 +================================ +I changed the Afedri radio module to be compatible with Python3. The graph Zoom feature now is available +on the Bandscope screen. Vladimyr Burdeiny provided a patch to make dx cluster work with Python 3. + +I extended the range of the Waterfall color controls Ys and Yz to accommodate hardware with a higher +noise floor such as PlutoSDR. You will have to readjust your waterfall colors. + +I added a hardware setting for the LNA gain during transmit for the HL2. I made some changes to the CW +and PTT hardware interface for the HL2. These work great with the HL2, but test the new code if you have +diferent Hermes hardware such as Red Pitaya. + Quisk Version 4.1.52 December 2019 =================================== I added an On/Off button to Quisk. When Quisk starts the button is "On". When you turn it to "Off", @@ -7,8 +19,8 @@ and to re-start your hardware after a power down. Martin Schaller found and fixed a bug in the Alsa sound system that produced sporadic crashes. Thanks Martin! Max, G7UOZ, found and fixed a bug in the Python3 SoftRock hardware_net.py code. Thanks Max! -This Quisk includes a more recent FreeDV library in both 32-bit and 64-bit versions. The SoapySDR interface -still requires 64-bit Quisk. +This Quisk includes a more recent FreeDV library in both 32-bit and 64-bit versions. The Windows +SoapySDR interface still requires 64-bit Quisk. The Config/Status screen now shows the dB level of each open sound device. The maximum level is zero dB. This is meant as an aid to configuring the sound devices. diff --git a/PKG-INFO b/PKG-INFO index 580d2ad..9163563 100755 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: quisk -Version: 4.1.52 +Version: 4.1.53 Summary: QUISK is a Software Defined Radio (SDR) transceiver that can control various radio hardware. Home-page: http://james.ahlstrom.name/quisk/ Author: James C. Ahlstrom diff --git a/__init__.py b/__init__.py index 53ccd50..d47ec66 100755 --- a/__init__.py +++ b/__init__.py @@ -1 +1 @@ -#Quisk version 4.1.52 +#Quisk version 4.1.53 diff --git a/afedrinet/af_comp.bat.makeit b/afedrinet/af_comp.bat.makeit new file mode 100755 index 0000000..5ab7034 --- /dev/null +++ b/afedrinet/af_comp.bat.makeit @@ -0,0 +1 @@ +gcc -o afedrinet_io.pyd --shared afedrinet_io.c ../is_key_down.c ../import_quisk_api.c -O3 -I"../" -I"C:\Programs\Python27\include" -L"C:\Programs\Python27\libs" -lws2_32 -lpython27 \ No newline at end of file diff --git a/afedrinet/afedri.py b/afedrinet/afedri.py index 7b96af2..ede3027 100755 --- a/afedrinet/afedri.py +++ b/afedrinet/afedri.py @@ -8,10 +8,15 @@ from __future__ import division # AFEDRI Class module # Title: afedri.py # Author: k3it + # Adopted to work with Quisk # by 4Z5LV # Last Changes: Sat Feb 02 2013 # Version: 2.2 + +# Adapted to work with Python3 +# by N2ADR +# Last Changes: January 2020 ################################################## from socket import * @@ -56,10 +61,10 @@ class afedri(object): if not self.s: return 1 __next_freq = target_freq __next_freq = struct.pack(">3) @@ -92,7 +97,7 @@ class afedri(object): __gain = (indx << 3) + 1 # special afedri calculation for the gain byte #__gain = ((__gain+10)/3 << 3) + 1 - __set_gain_cmd = "\x06\x00\x38\x00\x00" + struct.pack("B",__gain) + __set_gain_cmd = b"\x06\x00\x38\x00\x00" + struct.pack("B",__gain) self.s.send(__set_gain_cmd) __data = self.s.recv(6) __rf_gain = -10 + 3 * (struct.unpack("B",__data[5:6])[0]>>3) @@ -103,7 +108,7 @@ class afedri(object): NOT IMPLEMENTED IN AFEDRI?. DON'T USE """ if not self.s: return 1 - __get_gain_cmd = "\x05\x20\x38\x00\x00" + __get_gain_cmd = b"\x05\x20\x38\x00\x00" self.s.send(__get_gain_cmd) __data = self.s.recv(6) __rf_gain = -10 + 3 * (struct.unpack("B",__data[5:])[0]>>3) @@ -111,8 +116,8 @@ class afedri(object): def get_fe_clock(self): if not self.s: return 1 - __get_lword_cmd = "\x09\xE0\x02\x55\x00\x00\x00\x00\x00" - __get_hword_cmd = "\x09\xE0\x02\x55\x01\x00\x00\x00\x00" + __get_lword_cmd = b"\x09\xE0\x02\x55\x00\x00\x00\x00\x00" + __get_hword_cmd = b"\x09\xE0\x02\x55\x01\x00\x00\x00\x00" self.s.send(__get_lword_cmd) __data_l = self.s.recv(9) self.s.send(__get_hword_cmd) @@ -123,7 +128,7 @@ class afedri(object): def start_capture(self): #start 16-bit contiguous capture, complex numbers if not self.s: return 1 - __start_cmd="\x08\x00\x18\x00\x80\x02\x00\x00" + __start_cmd=b"\x08\x00\x18\x00\x80\x02\x00\x00" self.s.send(__start_cmd) __data = self.s.recv(8) return __data @@ -131,14 +136,15 @@ class afedri(object): def get_sdr_name(self): #Request SDR's Name string command = array.array('B',[0x4, 0x20,1,0]) if not self.s: return 1 - __start_cmd="\x04\x20\x01\x00" + __start_cmd=b"\x04\x20\x01\x00" self.s.send(__start_cmd) __data = self.s.recv(16) + __data = __data.decode('utf-8') return __data def stop_capture(self): if not self.s: return 1 - __stop_cmd="\x08\x00\x18\x00\x00\x01\x00\x00" + __stop_cmd=b"\x08\x00\x18\x00\x00\x01\x00\x00" self.s.send(__stop_cmd) __data = self.s.recv(8) return __data @@ -150,8 +156,8 @@ class afedri(object): __DISCOVER_SERVER_PORT=48321 # PC client Tx port, SDR Server Rx Port __DISCOVER_CLIENT_PORT=48322 # PC client Rx port, SDR Server Tx Port - __data="\x38\x00\x5a\xa5" # magic discovery packet - __data=__data.ljust(56,"\x00") # pad with zeroes + __data=b"\x38\x00\x5a\xa5" # magic discovery packet + __data=__data.ljust(56,b"\x00") # pad with zeroes self.s = socket(AF_INET, SOCK_DGRAM) self.s.bind(('', 0)) @@ -168,7 +174,9 @@ class afedri(object): try: __msg=self.sin.recv(256,0) __devname=__msg[5:20] + __devname=__devname.decode('utf-8') __sn=__msg[21:36] + __sn=__sn.decode('utf-8') __ip=inet_ntoa(__msg[40:36:-1]) __port=struct.unpack(" sudo apt-get install libpulse-dev
+sudo apt-get install python-dev +
sudo apt-get install libpython2.7-dev
+sudo apt-get install python3-dev +
sudo apt-get install libpython3-dev
sudo apt-get install python-usb @@ -838,14 +842,6 @@ just changing the sound card names.
-
-For more information try these articles: -
-
http://linuxplanet.com/linuxplanet/tutorials/6465/1/ -
-http://linuxplanet.com/linuxplanet/tutorials/6466/1/ -
-

Windows Names

To see what sound cards you have, use the Control Panel item Sound diff --git a/dxcluster.py b/dxcluster.py index 5a1acbe..eff52d7 100755 --- a/dxcluster.py +++ b/dxcluster.py @@ -110,17 +110,17 @@ class DxCluster(threading.Thread): for i in range(10): try: self.tn.open(conf.dxClHost, conf.dxClPort, 10) - self.tn.read_until('login:', 10) - self.tn.write(str(conf.user_call_sign) + "\n") # user_call_sign may be Unicode + self.tn.read_until(b"login:", 10) + self.tn.write(conf.user_call_sign.encode('utf-8', errors='ignore') + b"\n") # user_call_sign may be Unicode break except: time.sleep(0.5) if conf.dxClPassword: - self.tn.read_until("Password: ") - self.tn.write(str(conf.dxClPassword) + "\n") + self.tn.read_until(b"Password: ") + self.tn.write(conf.dxClPassword.encode('utf-8', errors='ignore') + b"\n") def telnetRead(self): - message = self.tn.read_until('\n', 60).decode(encoding='utf-8', errors='replace') + message = self.tn.read_until(b'\n', 60).decode(encoding='utf-8', errors='replace') if self.doQuit.isSet() == False: dxEntry = DxEntry(); if dxEntry.parseMessage(message): diff --git a/hermes/quisk_hardware.py b/hermes/quisk_hardware.py index 1b4c214..74f2576 100755 --- a/hermes/quisk_hardware.py +++ b/hermes/quisk_hardware.py @@ -71,6 +71,7 @@ class Hardware(BaseHardware): self.SetControlByte(0x10, 1, (value >> 2) & 0xFF) # cw_hang_time self.SetLowPwrEnable(conf.hermes_lowpwr_tr_enable) self.EnablePowerAmp(conf.hermes_power_amp) + self.ChangeTxLNA(conf.hermes_TxLNA_dB) self.MakePowerCalibration() def pre_open(self): # This socket is used for the Metis Discover protocol @@ -395,8 +396,10 @@ class Hardware(BaseHardware): btn = event.GetEventObject() if btn.GetValue(): QS.set_PTT(1) + QS.set_key_down(1) else: QS.set_PTT(0) + QS.set_key_down(0) def OnSpot(self, level): # level is -1 for Spot button Off; else the Spot level 0 to 1000. pass @@ -437,9 +440,9 @@ class Hardware(BaseHardware): QS.pc_to_hermes(self.pc2hermes) if DEBUG: print ("Change AGC to", value) ## Simpler LNA setting for HL2 identifying as version >=40, see HL2 wiki for details - def ChangeLNA(self, value): + def ChangeLNA(self, value): # LNA for Rx # value is -12 to +48 - if self.hermes_code_version < 40: + if self.hermes_code_version < 40: # Is this correct ?? if value < 20: self.pc2hermes[2] |= 0x08 # C0 index == 0, C3[3]: LNA +32 dB disable == 1 value = 19 - value @@ -451,6 +454,12 @@ class Hardware(BaseHardware): self.pc2hermes[4 * 10 + 3] = value # C0 index == 0x1010, C4[4:0] LNA 0-32 dB gain QS.pc_to_hermes(self.pc2hermes) if DEBUG: print ("Change LNA to", value) + def ChangeTxLNA(self, value): # LNA for Tx + # value is -12 to +48 + value = ((value+12) & 0x3f) | 0x40 | 0x80 + self.SetControlByte(0x0e, 3, value) # C0 index == 0x0e, C3 + QS.pc_to_hermes(self.pc2hermes) + if DEBUG: print ("Change Tx LNA to", value) def SetTxLevel(self): try: tx_level = self.conf.tx_level[self.band] diff --git a/quisk.c b/quisk.c index abfb9b9..385a58f 100755 --- a/quisk.c +++ b/quisk.c @@ -3347,17 +3347,15 @@ static int read_rx_udp10(complex double * samp) // Read samples from UDP using t unsigned int seq; unsigned int hlwp = 0; static unsigned int seq0; - static int key_state; static int tx_records; static int max_multirx_count=0; - int i, j, nSamples, xr, xi, index, start, want_samples, dindex, state, num_records; + int i, j, nSamples, xr, xi, index, start, want_samples, dindex, num_records; complex double c; struct timeval tm_wait; fd_set fds; if ( ! quisk_hermes_is_ready(rx_udp_socket)) { seq0 = 0; - key_state = 0; tx_records = 0; quisk_rx_udp_started = 0; multirx_fft_next_index = 0; @@ -3501,23 +3499,8 @@ static int read_rx_udp10(complex double * samp) // Read samples from UDP using t //code_version = quisk_hermes_to_pc[3]; if ((quisk_hermes_to_pc[0] & 0x01) != 0) // C1 quisk_sound_state.overrange++; - if (quisk_hermes_code_version >= 62) { - hardware_ptt = buf[start] & 0x01; // C0 bit zero is PTT - hardware_cwkey = (buf[start] & 0x02) >> 1; // C0 bit one is CW key state - } - else { - hardware_cwkey = buf[start] & 0x01; // C0 bit zero is CW key state - } - if (rxMode == CWL || rxMode == CWU) { - state = hardware_cwkey | is_PTT_down; - } - else { - state = is_PTT_down; - } - if (state != key_state) { - key_state = state; - quisk_set_key_down(state); - } + hardware_ptt = buf[start] & 0x01; // C0 bit zero is PTT + hardware_cwkey = (buf[start] & 0x04) >> 2; // C0 bit two is CW key state } else if(dindex == 1) { // temperature and forward power hermes_temperature += quisk_hermes_to_pc[4] << 8 | quisk_hermes_to_pc[5]; @@ -4548,15 +4531,19 @@ static PyObject * get_multirx_graph(PyObject * self, PyObject * args) // Called return retrn; } -static PyObject * get_bandscope(void) // Called by the GUI thread +static PyObject * get_bandscope(PyObject * self, PyObject * args) // Called by the GUI thread { - int i, j, j1, j2, L; + int i, j, j1, j2, L, clock; + double zoom, deltaf, rate, f1; static int fft_count = 0; static double the_max = 0; static double time0=0; // time of last graph double d1, d2, sample, frac, scale; PyObject * tuple2; + if (!PyArg_ParseTuple (args, "idd", &clock, &zoom, &deltaf)) + return NULL; + if (bandscopeState == 99 && bandscopePlan) { // bandscope samples are ready for (i = 0; i < bandscope_size; i++) { d1 = fabs(bandscopeSamples[i]); @@ -4577,9 +4564,12 @@ static PyObject * get_bandscope(void) // Called by the GUI thread tuple2 = PyTuple_New(graph_width); frac = (double)L / graph_width; scale = 1.0 / frac / fft_count / bandscope_size; + rate = clock / 2.0; for (i = 0; i < graph_width; i++) { // for each pixel - d1 = i * frac; - d2 = (i + 1) * frac; + f1 = deltaf + rate / 2.0 * (1.0 - zoom); // frequency at left of graph + // freq = f1 + pixel / graph_width + zoom * rate = rate * fft_index / L + d1 = L / rate * (f1 + (double)i / graph_width * zoom * rate); + d2 = L / rate * (f1 + (double)(i + 1) / graph_width * zoom * rate); j1 = floor(d1); j2 = floor(d2); if (j1 == j2) { @@ -4627,9 +4617,6 @@ static PyObject * get_graph(PyObject * self, PyObject * args) // Called by the G if (!PyArg_ParseTuple (args, "idd", &k, &zoom, &deltaf)) return NULL; - if (k == 2) { - return get_bandscope(); - } if (k != use_fft) { // change in data return type; re-initialize use_fft = k; count_fft = 0; @@ -5183,6 +5170,7 @@ static PyMethodDef QuiskMethods[] = { {"is_key_down", is_key_down, METH_VARARGS, "Check whether the key is down; return 0 or 1."}, {"get_state", get_state, METH_VARARGS, "Return a count of read and write errors."}, {"get_graph", get_graph, METH_VARARGS, "Return a tuple of graph data."}, + {"get_bandscope", get_bandscope, METH_VARARGS, "Return a tuple of bandscope data."}, {"set_multirx_mode", set_multirx_mode, METH_VARARGS, "Select demodulation mode for sub-receivers."}, {"set_multirx_freq", set_multirx_freq, METH_VARARGS, "Select how to play audio from sub-receivers."}, {"set_multirx_play_method", set_multirx_play_method, METH_VARARGS, "Select how to play audio from sub-receivers."}, diff --git a/quisk.egg-info/PKG-INFO b/quisk.egg-info/PKG-INFO index 580d2ad..9163563 100755 --- a/quisk.egg-info/PKG-INFO +++ b/quisk.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: quisk -Version: 4.1.52 +Version: 4.1.53 Summary: QUISK is a Software Defined Radio (SDR) transceiver that can control various radio hardware. Home-page: http://james.ahlstrom.name/quisk/ Author: James C. Ahlstrom diff --git a/quisk.egg-info/SOURCES.txt b/quisk.egg-info/SOURCES.txt index d858ce4..1b9bbef 100755 --- a/quisk.egg-info/SOURCES.txt +++ b/quisk.egg-info/SOURCES.txt @@ -41,6 +41,7 @@ quisk.py quisk_conf_defaults.py quisk_conf_kx3.py quisk_conf_model.py +quisk_conf_openradio.py quisk_conf_peaberry.py quisk_conf_sdr8600.py quisk_conf_sdriq.py @@ -50,10 +51,12 @@ quisk_hardware_hamlib.py quisk_hardware_model.py quisk_hardware_sdr8600.py quisk_hardware_sdriq.py +quisk_hardware_sdrmicron.py quisk_utils.py quisk_vna.py quisk_widgets.py setup.py +softrock_tune_vfo.py sound.c sound_alsa.c sound_directx.c @@ -86,6 +89,7 @@ winsound.txt ./quisk_conf_defaults.py ./quisk_conf_kx3.py ./quisk_conf_model.py +./quisk_conf_openradio.py ./quisk_conf_peaberry.py ./quisk_conf_sdr8600.py ./quisk_conf_sdriq.py @@ -95,9 +99,11 @@ winsound.txt ./quisk_hardware_model.py ./quisk_hardware_sdr8600.py ./quisk_hardware_sdriq.py +./quisk_hardware_sdrmicron.py ./quisk_utils.py ./quisk_vna.py ./quisk_widgets.py +./softrock_tune_vfo.py ./windows.txt ./winsound.txt ./afedrinet/SOURCE.txt @@ -162,12 +168,11 @@ winsound.txt ./softrock/widgets_tx.py afedrinet/SOURCE.txt afedrinet/__init__.py -afedrinet/af_comp.bat +afedrinet/af_comp.bat.makeit afedrinet/afe_library afedrinet/afe_library.mac afedrinet/afedri.py afedrinet/afedrinet_io.c -afedrinet/afedrinet_io.pyd afedrinet/quisk_conf.py afedrinet/quisk_conf_linux.py afedrinet/quisk_conf_mac.py diff --git a/quisk.py b/quisk.py index 6606517..48146e9 100755 --- a/quisk.py +++ b/quisk.py @@ -857,6 +857,7 @@ class ConfigScreen(wx.Panel): def __init__(self, parent, width, fft_size): self.y_scale = 0 self.y_zero = 0 + self.zoom_control = 0 self.finish_pages = True self.width = width wx.Panel.__init__(self, parent) @@ -920,6 +921,7 @@ class ConfigStatus(wx.ScrolledWindow): self.latencyPlay = -1 self.y_scale = 0 self.y_zero = 0 + self.zoom_control = 0 self.rate_min = -1 self.rate_max = -1 self.chan_min = -1 @@ -1779,6 +1781,7 @@ class GraphScreen(wx.Window): else: self.y_scale = conf.graph_y_scale self.y_zero = conf.graph_y_zero + self.zoom_control = 0 self.y_ticks = [] self.VFO = 0 self.filter_mode = 'AM' @@ -1879,9 +1882,10 @@ class GraphScreen(wx.Window): def ChangeYzero(self, y_zero): self.y_zero = y_zero self.doResize = True - def ChangeZoom(self, zoom, deltaf): + def ChangeZoom(self, zoom, deltaf, zoom_control): self.zoom = zoom self.zoom_deltaf = deltaf + self.zoom_control = zoom_control self.doResize = True def MakeYScale(self): chary = self.chary @@ -2491,14 +2495,19 @@ class WaterfallDisplay(wx.Window): #T('graph start') row = bytearray(0) # Make a new row of pixels for a one-line image gain = self.rf_gain + # y_scale and y_zero range from zero to 160. + # y_zero controls the center position of the colors. Set to a bit over the noise level. + # y_scale controls how much the colors change when the sample deviates from y_zero. for x in data: # x is -130 to 0, or so (dB) - l = int((x - gain + y_zero // 3 + 100) * y_scale / 10) + yz = 40.0 + y_zero * 0.69 # -yz is the color center in dB + l = int((x - gain + yz) * (y_scale + 10) * 0.10 + 128) l = max(l, 0) l = min(l, 255) row.append(self.red[l]) row.append(self.green[l]) row.append(self.blue[l]) row.append(255) + #print ('OnGraphData yz %.0f, slope %.3f, l %4d' % (yz, (y_scale + 10) * 0.10, l)) #T('graph string') if wxVersion in ('2', '3'): bmp = wx.BitmapFromBufferRGBA(len(row) // 4, 1, row) @@ -2523,15 +2532,17 @@ class WaterfallDisplay(wx.Window): dc.DrawLine(tune_tx, self.margin, tune_tx, self.height) self.tune_tx = tune_tx self.tune_rx = tune_rx - def ChangeZoom(self, zoom, deltaf): + def ChangeZoom(self, zoom, deltaf, zoom_control): self.zoom = zoom self.zoom_deltaf = deltaf + self.zoom_control = zoom_control class WaterfallScreen(wx.SplitterWindow): """Create a splitter window with a graph screen and a waterfall screen""" def __init__(self, frame, width, data_width, graph_width): self.y_scale = conf.waterfall_y_scale self.y_zero = conf.waterfall_y_zero + self.zoom_control = 0 wx.SplitterWindow.__init__(self, frame) self.SetSizeHints(width, -1, width) self.SetSashGravity(0.50) @@ -2576,6 +2587,11 @@ class WaterfallScreen(wx.SplitterWindow): self.pane2.OnGraphData(data) def ChangeRfGain(self, gain): # Set the correction for RF gain self.pane2.display.rf_gain = gain + def ChangeZoom(self, zoom, deltaf, zoom_control): + self.zoom_control = zoom_control + self.pane1.ChangeZoom(zoom, deltaf, zoom_control) + self.pane2.ChangeZoom(zoom, deltaf, zoom_control) + self.pane2.display.ChangeZoom(zoom, deltaf, zoom_control) class WaterfallPane(GraphScreen): """Create a waterfall screen with an X axis and a waterfall display.""" @@ -2583,6 +2599,7 @@ class WaterfallPane(GraphScreen): GraphScreen.__init__(self, frame, data_width, graph_width) self.y_scale = conf.waterfall_y_scale self.y_zero = conf.waterfall_y_zero + self.zoom_control = 0 self.oldVFO = self.VFO self.filter_mode = 'AM' self.filter_bandwidth = 0 @@ -3004,6 +3021,7 @@ class ScopeScreen(wx.Window): self.horizPen = wx.Pen(conf.color_gl, 1, wx.SOLID) self.y_scale = conf.scope_y_scale self.y_zero = conf.scope_y_zero + self.zoom_control = 0 self.yscale = 1 self.running = 1 self.doResize = False @@ -3136,8 +3154,11 @@ class ScopeScreen(wx.Window): class BandscopeScreen(WaterfallScreen): def __init__(self, frame, width, data_width, graph_width, clock): + self.zoom = 1.0 + self.zoom_deltaf = 0 + self.zoom_control = 0 WaterfallScreen.__init__(self, frame, width, data_width, graph_width) - self.pane1.sample_rate = self.pane2.sample_rate = int(clock) // 2 + self.sample_rate = self.pane1.sample_rate = self.pane2.sample_rate = int(clock) // 2 self.VFO = clock // 4 self.SetVFO(self.VFO) def SetTxFreq(self, tx_freq, rx_freq): @@ -3146,6 +3167,26 @@ class BandscopeScreen(WaterfallScreen): def SetFrequency(self, freq): # freq is 7000000, not the offset from VFO freq = freq - self.VFO WaterfallScreen.SetTxFreq(self, freq, freq) + def ChangeZoom(self, zoom_control): # zoom_control is the slider value 0 to 1000 + self.zoom_control = zoom_control + if zoom_control < 50: + zoom = 1.0 + zoom_deltaf = 0 + else: + zoom = 1.0 - zoom_control / 1000.0 * 0.95 + freq = application.rxFreq + application.VFO + srate = int(self.sample_rate * zoom) # reduced (zoomed) sample rate + if freq - srate // 2 < 0: + zoom_deltaf = srate // 2 - self.VFO + elif freq + srate // 2 > self.sample_rate: + zoom_deltaf = self.VFO - srate // 2 + else: + zoom_deltaf = freq - self.VFO + self.zoom = zoom + self.zoom_deltaf = zoom_deltaf + self.pane1.ChangeZoom(zoom, zoom_deltaf, zoom_control) + self.pane2.ChangeZoom(zoom, zoom_deltaf, zoom_control) + self.pane2.display.ChangeZoom(zoom, zoom_deltaf, zoom_control) class FilterScreen(GraphScreen): """Create a graph of the receive filter response.""" @@ -3153,6 +3194,7 @@ class FilterScreen(GraphScreen): GraphScreen.__init__(self, parent, data_width, graph_width) self.y_scale = conf.filter_y_scale self.y_zero = conf.filter_y_zero + self.zoom_control = 0 self.VFO = 0 self.txFreq = 0 self.data = [] @@ -3199,6 +3241,7 @@ class AudioFFTScreen(GraphScreen): GraphScreen.__init__(self, parent, data_width, graph_width) self.y_scale = conf.filter_y_scale self.y_zero = conf.filter_y_zero + self.zoom_control = 0 self.VFO = 0 self.txFreq = 0 self.sample_rate = sample_rate @@ -3216,6 +3259,7 @@ class HelpScreen(wx.html.HtmlWindow): wx.html.HtmlWindow.__init__(self, parent, -1, size=(width, height)) self.y_scale = 0 self.y_zero = 0 + self.zoom_control = 0 if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() self.SetFonts("", "", [10, 12, 14, 16, 18, 20, 22]) @@ -4907,6 +4951,7 @@ The new code supports multiple corrections per band.""") self.vertBox.Layout() # This destroys the initialized sash position! self.sliderYs.SetValue(self.screen.y_scale) self.sliderYz.SetValue(self.screen.y_zero) + self.sliderZo.SetValue(self.screen.zoom_control) if name == 'WFall': self.screen.SetSashPosition(sash) def OnBtnFileRecord(self, event): @@ -4929,14 +4974,21 @@ The new code supports multiple corrections per band.""") elif self.multi_rx_screen.rx_zero == self.graph: self.graphScaleZ[self.lastBand] = (self.graph.y_scale, self.graph.y_zero) def OnChangeZoom(self, event): - x = self.sliderZo.GetValue() - if x < 50: + zoom_control = self.sliderZo.GetValue() + if self.screen == self.bandscope_screen: + self.bandscope_screen.ChangeZoom(zoom_control) + self.bandscope_screen.SetTxFreq(self.txFreq, self.rxFreq) + return + # The display runs from f1 to f2. The original sample rate is "rate". + # The new effective sample rate is rate * zoom. + # f1 = deltaf + rate * (1 - zoom) / 2 + if zoom_control < 50: self.zoom = 1.0 # change back to not-zoomed mode self.zoom_deltaf = 0 self.zooming = False else: a = 1000.0 * self.sample_rate / (self.sample_rate - 2500.0) - self.zoom = 1.0 - x / a + self.zoom = 1.0 - zoom_control / a if not self.zooming: # set deltaf when zoom mode starts center = self.multi_rx_screen.graph.filter_center freq = self.rxFreq + center @@ -4944,10 +4996,8 @@ The new code supports multiple corrections per band.""") self.zooming = True zoom = self.zoom deltaf = self.zoom_deltaf - self.graph.ChangeZoom(zoom, deltaf) - self.waterfall.pane1.ChangeZoom(zoom, deltaf) - self.waterfall.pane2.ChangeZoom(zoom, deltaf) - self.waterfall.pane2.display.ChangeZoom(zoom, deltaf) + self.graph.ChangeZoom(zoom, deltaf, zoom_control) + self.waterfall.ChangeZoom(zoom, deltaf, zoom_control) self.screen.SetTxFreq(self.txFreq, self.rxFreq) self.station_screen.Refresh() def OnLevelVOX(self, event): @@ -5851,7 +5901,7 @@ The new code supports multiple corrections per band.""") self.SetPTT(False) self.timer = time.time() if self.bandscope_clock: # Hermes UDP protocol - data = QS.get_graph(2, 1.0, 0) + data = QS.get_bandscope(self.bandscope_clock, self.bandscope_screen.zoom, float(self.bandscope_screen.zoom_deltaf)) if data and self.screen == self.bandscope_screen: self.screen.OnGraphData(data) if self.screen == self.scope: diff --git a/quisk_conf_defaults.py b/quisk_conf_defaults.py index a3c6437..3298d3e 100755 --- a/quisk_conf_defaults.py +++ b/quisk_conf_defaults.py @@ -429,6 +429,11 @@ Hware_Hl2_EepromMAC = '0xA1 0x6B' Hware_Hl2_EepromMACUse = 'Ignore' #Hware_Hl2_EepromMACUse = 'Set address' +## hermes_TxLNA_dB LNA during Tx dB, integer +# During transmit the low noise Rx amplifier gain changes to this value (in dB) if the hardware supports it. +# Changes are immediate (no need to restart). +hermes_TxLNA_dB = 21 + # These are known power meter calibration tables. This table is not present in the JSON settings file. power_meter_std_calibrations = {} power_meter_std_calibrations['HL2FilterE3'] = [[ 0, 0.0 ], [ 25.865384615384617, 0.0025502539351328003 ], [ 101.02453987730061, 0.012752044999999998 ], diff --git a/quisk_conf_openradio.py b/quisk_conf_openradio.py new file mode 100755 index 0000000..18f6f63 --- /dev/null +++ b/quisk_conf_openradio.py @@ -0,0 +1,122 @@ +# OpenRadio v1.1 Quisk Configuration File +# +# IMPORTANT: To be able to control the OpenRadio board from within Quisk, +# you will need to compile and upload the 'openradio_quisk' firmware, which +# is available from: https://github.com/darksidelemm/open_radio_miniconf_2015 +# +# You will also need to install the pyserial package for python. +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + + +# SOUND CARD SETTINGS +# +# Uncomment these if you wish to use PortAudio directly +#name_of_sound_capt = "portaudio:(hw:2,0)" +#name_of_sound_play = "portaudio:(hw:1,0)" + +# Uncomment these lines if you wish to use Pulseaudio +name_of_sound_capt = "pulse" +name_of_sound_play = "pulse" + +# SERIAL PORT SETTINGS +# Set this as appropriate for your OS. +openradio_serial_port = "/dev/ttyUSB0" +openradio_serial_rate = 57600 + + +# OpenRadio Frequency limits. +# These are just within the limits set in the openradio_quisk firmware. +openradio_lower = 100001 +openradio_upper = 29999999 + +# OpenRadio Hardware Control Class +# +import serial,time +from quisk_hardware_model import Hardware as BaseHardware + +class Hardware(BaseHardware): + def open(self): + # Called once to open the Hardware + # Open the serial port. + self.or_serial = serial.Serial(openradio_serial_port,openradio_serial_rate,timeout=3) + print("Opened Serial Port.") + # Wait for the Arduino Nano to restart and boot. + time.sleep(2) + # Poll for version. Should probably confirm the response on this. + version = str(self.get_parameter("VER")) + print(version) + # Return an informative message for the config screen + t = version + ". Capture from sound card %s." % self.conf.name_of_sound_capt + return t + + def close(self): + # Called once to close the Hardware + self.or_serial.close() + + def ChangeFrequency(self, tune, vfo, source='', band='', event=None): + # Called whenever quisk requests a frequency change. + # This sends the FREQ command to set the centre frequency of the OpenRadio, + # and will also move the 'tune' frequency (the section within the RX passband + # which is to be demodulated) if it falls outside the passband (+/- sample_rate/2). + print("Setting VFO to %d." % vfo) + if(vfoopenradio_upper): + vfo = openradio_upper + print("Outside range! Setting to %d" % openradio_upper) + + success = self.set_parameter("FREQ",str(vfo)) + + # If the tune frequency is outside the RX bandwidth, set it to somewhere within that bandwidth. + if(tune>(vfo + sample_rate/2) or tune<(vfo - sample_rate/2)): + tune = vfo + 10000 + print("Bringing tune frequency back into the RX bandwidth.") + + if success: + print("Frequency change succeeded!") + else: + print("Frequency change failed.") + + return tune, vfo + +# +# Serial comms functions, to communicate with the OpenRadio board +# + + def get_parameter(self,string): + self.or_serial.write(string+"\n") + return self.get_argument() + + def set_parameter(self,string,arg): + self.or_serial.write(string+","+arg+"\n") + if self.get_argument() == arg: + return True + else: + return False + + def get_argument(self): + data1 = self.or_serial.readline() + # Do a couple of quick checks to see if there is useful data here + if len(data1) == 0: + return -1 + + # Maybe we didn't catch an OK line? + if data1.startswith('OK'): + data1 = self.or_serial.readline() + + # Check to see if we have a comma in the string. If not, there is no argument. + if data1.find(',') == -1: + return -1 + + data1 = data1.split(',')[1].rstrip('\r\n') + + # Check for the OK string + data2 = self.or_serial.readline() + if data2.startswith('OK'): + return data1 diff --git a/quisk_hardware_sdrmicron.py b/quisk_hardware_sdrmicron.py new file mode 100755 index 0000000..b9c31ac --- /dev/null +++ b/quisk_hardware_sdrmicron.py @@ -0,0 +1,259 @@ +# -*- coding: cp1251 -*- +# +# It provides support for the SDR Micron + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + +import sys, wx, traceback + +import ftd2xx as d2xx +import time + +from quisk_hardware_model import Hardware as BaseHardware + +DEBUG = 0 + +# https://github.com/Dfinitski/SDR-Micron +# +# RX control, to device, 32 bytes total +# Preamble + 'RX0' + enable + rate + 4 bytes frequency + attenuation + 14 binary zeroes +# +# where: +# Preamble is 7*0x55, 0xd5 +# bytes: +# enable - binary 0 or 1, for enable receiver +# rate: +# binary +# 0 for 48 kHz +# 1 for 96 kHz +# 2 for 192 kHz +# 3 for 240 kHz +# 4 for 384 kHz +# 5 for 480 kHz +# 6 for 640 kHz +# 7 for 768 kHz +# 8 for 960 kHz +# 9 for 1536 kHz +# 10 for 1920 kHz +# +# frequency - 32 bits of tuning frequency, MSB is first +# attenuation - binary 0, 10, 20, 30 for needed attenuation +# +# RX data, to PC, 508 bytes total +# Preamble + 'RX0' + FW1 + FW2 + CLIP + 2 zeroes + 492 bytes IQ data +# +# Where: +# FW1 and FW2 - char digits firmware version number +# CLIP - ADC overflow indicator, 0 or 1 binary +# IQ data for 0 - 7 rate: +# 82 IQ pairs formatted as "I2 I1 I0 Q2 Q1 Q0.... ", MSB is first, 24 bits per sample +# IQ data for 8 - 10 rate: +# 123 IQ pairs formatted as "I1 I0 Q1 Q0..... ", MSB is first, 16 bits per sample +# +# Band Scope control, to device, 32 bytes total +# Preamble + 'BS0' + enable + period + 19 binary zeroes +# +# Where period is the full frame period in ms, from 50 to 255ms, 100ms is recommended +# for 10Hz refresh rate window. +# +# Band Scope data, to PC, 16384 16bit samples, 32768 bytes by 492 in each packet +# Preamble + 'BS0' + FW1 + FW2 + CLIP + PN + 1 zero + 492 bytes BS data +# +# Where PN is packet number 0, 1, 2, ..., 66 +# BS data in format "BS1, BS0, BS1, BS0, ...", MSB is first +# +# 66 packets with PN = 0 - 65 contain 492 bytes each, and 67-th packet with PN = 66 contains +# the remaining 296 bytes of data and junk data to full 492 bytes size +# + +class Hardware(BaseHardware): + sample_rates = [48, 96, 192, 240, 384, 480, 640 ,768, 960, 1536, 1920] + def __init__(self, app, conf): + BaseHardware.__init__(self, app, conf) + self.device = None + self.usb = None + self.rf_gain_labels = ('RF +10', 'RF 0', 'RF -10', 'RF -20') + self.index = 1 + self.enable = 0 + self.rate = 0 + self.att = 10 + self.freq = 7220000 + self.old_freq = 0 + self.sdrmicron_clock = 76800000 + self.sdrmicron_decim = 1600 + self.bscope_data = bytearray(0) + self.fw_ver = None + self.frame_msg = '' + + if conf.fft_size_multiplier == 0: + conf.fft_size_multiplier = 3 # Set size needed by VarDecim + + rx_bytes = 3 # rx_bytes is the number of bytes in each I or Q sample: 1, 2, 3, or 4 + rx_endian = 1 # rx_endian is the order of bytes in the sample array: 0 == little endian; 1 == big endian + self.InitSamples(rx_bytes, rx_endian) # Initialize: read samples from this hardware file and send them to Quisk + bs_bytes = 2 + bs_endian = 1 + self.InitBscope(bs_bytes, bs_endian, self.sdrmicron_clock, 16384) # Initialize bandscope + + def open(self): # This method must return a string showing whether the open succeeded or failed. + enum = d2xx.createDeviceInfoList() # quantity of FTDI devices + if(enum==0): + return 'Device was not found' + for i in range(enum): # Searching and openinq needed device + a = d2xx.getDeviceInfoDetail(i) + if(a['description']==b'SDR-Micron'): + try: self.usb = d2xx.openEx(a['serial']) + except: + return 'Device was not found' + Mode = 64 # Configure FT2232H into 0x40 Sync FIFO Mode + self.usb.setBitMode(255, 0) # reset + time.sleep(0.1) + self.usb.setBitMode(255, Mode) #configure FT2232H into Sync FIFO mode + self.usb.setTimeouts(100, 100) # read, write + self.usb.setLatencyTimer(2) + self.usb.setUSBParameters(32, 32) # in_tx_size, out_tx_size + time.sleep(1.5) # waiting for initialisation device + data = self.usb.read(self.usb.getQueueStatus()) # clean the usb data buffer + self.device = 'Opened' + self.frame_msg = a['description'].decode('utf-8') + ' S/N - ' + a['serial'].decode('utf-8') + return self.frame_msg + return 'Device was not found' + + def close(self): + if(self.usb): + if(self.device=='Opened'): + enable = 0 + self.device = None + self.rx_control_upd() + time.sleep(0.5) + self.usb.setBitMode(255, 0) # reset + self.usb.close() + + def OnButtonRfGain(self, event): + btn = event.GetEventObject() + n = btn.index + self.att = n * 10 + self.rx_control_upd() + + def ChangeFrequency(self, tune, vfo, source='', band='', event=None): + if vfo: + self.freq = (vfo - self.transverter_offset) + if(self.freq!=self.old_freq): + self.old_freq = self.freq + self.rx_control_upd() + return tune, vfo + + def ChangeBand(self, band): + # band is a string: "60", "40", "WWV", etc. + BaseHardware.ChangeBand(self, band) + btn = self.application.BtnRfGain + if btn: + if band in ('160', '80', '60', '40'): + btn.SetLabel('RF -10', True) + elif band in ('20',): + btn.SetLabel('RF 0', True) + else: + btn.SetLabel('RF +10', True) + + def VarDecimGetChoices(self): # Return a list/tuple of strings for the decimation control. + return list(map(str, self.sample_rates)) # convert integer to string + + def VarDecimGetLabel(self): # return a text label for the control + return "Sample rate ksps" + + def VarDecimGetIndex(self): # return the current index + return self.index + + def VarDecimSet(self, index=None): # return sample rate + if index is None: # initial call to set the sample rate before the call to open() + rate = self.application.vardecim_set + try: + self.index = self.sample_rates.index(rate // 1000) + except: + self.index = 0 + else: + self.index = index + rate = self.sample_rates[self.index] * 1000 + self.rate = self.index + if(rate>=960000): + rx_bytes = 2 + rx_endian = 1 + self.InitSamples(rx_bytes, rx_endian) + else: + rx_bytes = 3 + rx_endian = 1 + self.InitSamples(rx_bytes, rx_endian) + self.rx_control_upd() + return rate + + def VarDecimRange(self): # Return the lowest and highest sample rate. + return (48000, 1920000) + + def StartSamples(self): # called by the sound thread + self.enable = 1 + self.rx_control_upd() + self.bscope_control_upd() + + def StopSamples(self): # called by the sound thread + self.enable = 0 + self.rx_control_upd() + self.bscope_control_upd() + + def rx_control_upd(self): + if(self.device=='Opened'): + work = self.freq + freq4 = work & 0xFF + work = work >> 8 + freq3 = work & 0xFF + work = work >> 8 + freq2 = work & 0xFF + work = work >> 8 + freq1 = work & 0xFF + if sys.version_info.major <= 2: + MESSAGE = 7*chr(0x55) + chr(0xd5) + 'RX0' + chr(self.enable) + chr(self.rate) + MESSAGE += chr(freq1) + chr(freq2) + chr(freq3) + chr(freq4) + chr(self.att) + 14*chr(0) + else: + MESSAGE = b"\x55\x55\x55\x55\x55\x55\x55\xd5RX0" + MESSAGE += bytes((self.enable, self.rate, freq1, freq2, freq3, freq4, self.att)) + MESSAGE += bytes(14) + try: self.usb.write(MESSAGE) + except: print('Error while rx_control_upd') + + def bscope_control_upd(self): + if self.device == 'Opened': + if sys.version_info.major <= 2: + MESSAGE = 7*chr(0x55) + chr(0xd5) + 'BS0' + chr(self.enable) + chr(100) + 19 * chr(0) + else: + MESSAGE = b"\x55\x55\x55\x55\x55\x55\x55\xd5BS0" + MESSAGE += bytes((self.enable, 100)) + MESSAGE += bytes(19) + try: self.usb.write(MESSAGE) + except: None + + def GetRxSamples(self): # Read all data from the SDR Micron and process it. + if self.device == None: + return + while (self.usb.getQueueStatus() >= 508): + data = self.usb.read(508) + data = bytearray(data) + if data[8:11] == bytearray(b'RX0'): # Rx I/Q data + if data[13]: + self.GotClip() + if self.fw_ver is None: + self.fw_ver = chr(data[11]) + '.' + chr(data[12]) + self.frame_msg += ' F/W version - ' + self.fw_ver + self.application.main_frame.SetConfigText(self.frame_msg) + self.AddRxSamples(data[16:]) + elif data[8:11] == bytearray(b'BS0'): # bandscope data + packet_number = data[14] + if packet_number == 0: # start of a block of data + self.bscope_data = data[16:] # 492 bytes + elif packet_number < 66: + self.bscope_data += data[16:] # 492 bytes + else: # end of a block of data, 296 bytes + self.bscope_data += data[16:312] + self.AddBscopeSamples(self.bscope_data) + + diff --git a/setup.py b/setup.py index 1df95e5..e5cfc8c 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ import struct # You must define the version here. A title string including # the version will be written to __init__.py and read by quisk.py. -Version = '4.1.52' +Version = '4.1.53' fp = open("__init__.py", "w") # write title string fp.write("#Quisk version %s\n" % Version) diff --git a/soapypkg/build/import_quisk_api.o b/soapypkg/build/import_quisk_api.o index d2ca2b1d0859ac35e98fa0783c04608b847327ab..54621fe55af212f6143216680d2c9e8cbe0b81a7 100755 GIT binary patch literal 29784 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 Cbpu%d literal 30752 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 diff --git a/soapypkg/build/temp.linux-x86_64-2.7/soapy.o b/soapypkg/build/temp.linux-x86_64-2.7/soapy.o index 5c1cead719de00a50261e33b21c83340ba8d3814..68657d4f83f9b377d90afdc7b3e13c3b6d5d2c98 100755 GIT binary patch literal 65328 zcmdtL37AyH)dqa;%z({0!zQaRE+8n&up^)jFav{Z0|SVPHqA`WBC|2w4KseCD4>iZ z3K|Wr5H(5?QQQ(07t}-`CW?s>OkzTe3y5(;jWH_!drqC|TXUdIzI@;J{QvXc2fC}? zI(6#QsZ*y;)xEdp^8D$O(|q5vm+zhB1v!g)UhO}EbS@`zy{_Kz-n@dwcM6(X5K^$} zgV4p^geNFH;c-URwWF^miDALIkqkBNJiy{crJGe<2HuA7CknE&O_9ahy%7}FgE z1x?FK)8zaX?=9e43? zW>!WTKIW!nWcJ^MgrMg=cR2HWH~&2HJC3QV4k75NnQm@AH06Iu$xZnO3YunoSyC{( zEgN0D1*^l%A#0M2iPutC<(eId*6b$^_D#d!u$s*fo$-A9B9n5>6?3M4^ASrmiw|Ka z+}VEgTs7RmvE`~2uX&e?9Csv*wWt z6=ZHln=zShVW<>C8`$whyO76BJm1Ck0DB(T4w0g19<28_1<$>ej`?snvqK2~b2C=u ze*pXcU|jxdmtKGH1+)tx*~r;y3eI?bSzD>!nE&yimMFz{Q~t*TK;}$9rshd9-Dn9U zN6i(?lLP<8Jo#+ZiqE`;?kU}NQ~qb;@;{DuZ<+@|K0C(hL8Fs-{qQ44j+lk$yUZ;c z9`HaxV`9Iyw{`PAgYVcMtX#qB1RFe#bB7i{01R~7!1o{OX9pelcepG|1uwg<(6_n9 zESpL#^A#WLz%UgwK3#wg7BoJVi?5@Ee{3NYu3NW&ziwJYUrlR>bZR5~m9g{2oz40r z_B;^w3|g*Y{a53fa^kS+Y5MXqSHDaWG#R$**3?p2(&;_3lErg)H?1Kt$e~_^qQGj< z3bU0dv4&(e>7*8D4JyPMRIskyAOA@`>N4>k^fmIDFX`*dOa6{JaLLT*8E}VUB*w5@ zsqIx?rY8yG z1nY)tuPdagX#0@AKIwJ~A?V`}belG%ru=Q+Z7=7-UY;fHqC%Q8`MU}lUu*^*DA<|5 zho}ywf!>mS40Io%hb}E>nzyH*aZdr9h`$GmH{2qth;mK2(9^tq;=9Nkl7sx>ch?Iw ztA`xiQsbuujV~uTtjgbq>GvINdj)6Y@5{WBClp)`SnMxw0!8A;lbA*d%ps{k;3c}4 zbS~P>%|Rn5-V1A8mA?l~LPuxh@5#LKV-9oX?E(Tv6hxrZPHNM-;sXj6;03;<>Wz;P z7d>?A9_tU=hZo4^ubaBjSJN6I{g+TLLA(U;L(uWybVd2vk+0Farr zf+qMGT+QYa?VHw69V+SLGPM4O?Es1zi?wVG30s=^(eBdB!OvaN+NR=}fpb0h`wZ8A z9DE7crZp@a#bqL`W?qjH(g3E=Y6x;OD#3RV()1YjNaSyPwOLe8LSGD8vDN2L$7q9l zJ+%=gZsWXXcEN;UQGq)>nDg(5mbqp%Rdn?Ck8~D}RME7qnQ%89z_5{;=$i!%jF?1y z7B&AfQP-g6zt$qQU^lT?uFg0{Drh`fHaopYvcCVZWQQok`&Z+8v=SdhH7o6ZPl=bH z=6|Nd+WO$0QXMaPi3?|&@yA&B#DNPR1l(QH}urJv|%eF^q3?1&C!Y2-gK zj(FrhGK@o~HTN6eS0{06ECiyE!FsAZmF_4 z#%;>aDrn5#4_)N%m#!ePXqt!rdf@>?VX28dctvAGRy3rOD;nY%TG5*FyZs;XhW!6G za@+7H8B*87hOn5{;_IlzbjIp}b@SF^Euqq2b_6~j>X8uopCQ<7{%Y(1+9gLSf7_up zP6jGl4}RActede`mek#!gYT*p+q}%xw=sijc?U&wYDvpn^CC>XS$y?)Q(`UnZ3f?M z+I2vE8xd%2K^<%>L9r3TzU5fa6k?Jljzka&x{(NAYYaEp_X_baTNvG~0~n;|G6x9O)@#HxuKVpd55aEqA2_nV0QAr}m+2UqR!V0t^UE zar$Pq(!`^^qu0!_k? zA@~m32_H#(d?bNGAr$UBF!O5~|DR`rA9&`gApm5D0DY$+U_^!h>EsZgSPwzwl~c)R z!SrCb<#+4+%wy|(ZT_m2D^_{&%xB@v%^G>IGgt+xIN0J}aGoB}LI;mG&4a;GjGNdd zVT9dJq3c>V!)Wuzx&G`SDX4Ca6tD65yv*}Oq>~~Dn|AyJTiFhzD zg@Z3s_?epX|6hFFdlVpkS2wQ*L7*0zAdnI@M3FmBJ;oJ#s1Az?cnL~N=jY-&NBBuR302^^QAP@T%Fh?D%bX( zXmr#U|C<`c=|iwIXI{AzyGdBmv6kmUqtU9d2S_A;MMrUatMlI+auZ@dqt!-*x@JU9M%DGa%0fc%rr_UKfp2WtT=OD#vE`jkUJrb5oXUzJ}lOx{7%8XlBXw-11m? zOjk#X65OR~q~qqSGz#VRViNs-!kqAr?UT31sAd5pA0d2{lj%PNYa;i||Il!>sO z7mJm6G3rlva^3<-p<5HG>UeW-Momf7i`ONh0bCTRs;!L9iNvFiGqS=L+BNyB%=}Z3LC;xt1IHrSEABbY_#M=mS{4pmn=M9lU-3& zOEaOirUC|A2V*6p4=+tr#FpTO_}?De{P!2PorOxXq$}QzBY)1FHOTW2U*QU|i)m{M z?f2!qY|8TxCg5Y=7<{IOu+PDlAEK{}vnicspbY-Xn8U>g%&7#?t>?AKXaUi@mNbs( zA%>V^`nB~yOmZD1j|-X1W0VPnwh+C~oH8ig3je)*8J~{;623NqCQ&%y5=%hslie zZ$UdhHzU>JxJN<8=8|zMk4U$S&D39`)gMq&(sxnMWkl|!j%Q&|CleMT9_?sMsR!-J zun0XH8Ag9((N10_6=l&!#@RmMCY|e~CvZ9xdXR{I0}}l6yp~hGkIxRAyqY92$+bbU zF_}EB2Z`5iAE^2uTIlFybjBA~IIbrlCfS>)OtMcB4Gp@>qM^Z*6cd-3!u@Fg3+`nf zBYvxs(&z|06e4==P^(iIVdkw*NpfsGEZJo1(Lr(?i%a_Zt>t{V>2;f*y_p6PGI(yM zhxm&dXnT-{lt(PoZo~;F;Sp;$ig-zyo5+A%UxIBXqG?B>j6s6M_f7BHZ=$^!%i4Z( zQmXbpplNH+djo<80)hvLfTd~QEs!QF^WvXaX)>2khm16tOA6poLSAP8-daC1&!;?_ zWM;n4bT-3;HbW&@CNtS5bLeI=Q@BpHo9S;d)BL6F?ex!_?q7$@7*jICe-@cslbPv% zf=q$Q%<}ugGz(3p&>w-!0+X5RcSj!=nan)D4>IK@GvDuvOs&bB@8_aUy~$kQ--Eub zG?|6WZLP^%=)Z$T*PF~melOJ7XfhH1ba2~jG9^Cgc8kfBa<{jc%*Fm^80g1MrpkXA z?d&j_rG5n5c9~3^wX?@$>iug`vd?51{Ef)$H3>)H05}t0rovU%AQ=j+$0t*f4KS4 zA{xMe$faES22=i-C~4AtXep(+#(!}65h`cD5wb#=magdzAQb9@Pp&_l%99@`p$-_* zb$LvB4v`Xi5s^}&E6+7)!%9Jk69ZSjxXN zr=-?hmE8CNlYeT-+ra;6<%L4DScXE>uo3)@lRy><^~WbGYC^IW^Cu=kc_&etN}J9_ zG8DQHpIm7v5~e9ip@ixh(#=;g=~_$rgCr^Qr=`IJJBu>!ISZ4w+u}s2m-#~y)9Y5V z_+l^fUQ$V@TV=G`%e;>&nP4Y#3#Co4llf!nP&PaH%%4#D6qCOHE~NXL^j4BB$D|*i z^ca(VkkYv(y^TaDFzJU$h6P?bYGx)NSrtsT9-)4i+n198n)ExAHbG71yOb8qzej1&`~ga58~THk7Hz*z z6I`@?=scuF+aFLm*UeB7kJq4W-u{+80a zO!^3=Wl8aT%E*%9^KvIkN*b5Ql9J9DSyD1MBTGsP&e$cTCFkst(wcL2Nom75yQH+` zT(&swcAT?IN|sMO!ZWTtd7L}=WDLCuGdubBVerkm*4ZaNDw!@^J!DFb_s@VXvrMKd zXS$h8H=i70w#jt&$?^3!nI1m*wj7h`>65LGF_{yXb*{z_CH1&Mu|iHMQA1zD#d4aimSTvlrn|G{1sfdiV7*t;+ZEk zhx@m3;bwgD)O^Acbmf$I4ch)0ZX^7cxWcPcp#h^rp^}-)chP_vs*ye|vnD;t|AuR% zBX-~>D4q&xxYCUFY3(r8#`xrZO!^F;)^?K~>rY4hP-qUZqX3KoDwoMPzlsTBL_iW! zTxHs$TvzUr;Wggjd!~~<%clUq(46halIG0{K5q%9Dv zu|yQC8d7rV=nVP2P>3c#C`9HK3X$EAxp>)GeJT8dE?^@4D7KdLskb0X4;j2abt=oG zPviI-EQX>Q+9hsrB$-?P4s9r8WXcY0dBnQm^u_DYjvlfOb;D7K*P;D3q_et})D(Li zGKr>}q0b_#$_Bg3!NO?gHlJcKWYN?U{>w<1^pj3{JEwbPWrosD!dAu1hE{1bc9Ln$ znUL^ollEZGvRmAjus!wCw{l zGe~9y$qqrXW033=Bs&MmEL%GMAUJ`N+^^0*;t_5)8NeZQ5PSLk_%dbV zTM(4ptxMMdoy73EbYrt;qw3O)HU#1LTcKO0B%AJolF1%jlF6QS!A7J>sBkxX(#R+UxOrF#_NVZ8PPaYQ} z$0w6n?J3Fn&gw`m+aw2)>tM~E5-{uAKUuBsq#&7>O!hnVUnEaGIZ1HpIPy~5ME}#1 z=l~u7@mc-hgqYy8?n#2vTagQ3^z@zq8ra7`?hq3U3MB~!1?b=t2<2{e2;EFRFLXOT z*)5aXGtT=avOq)BYC97>M?_@tzfThJYQmJYLGlHnH&D}v;eL2^})Tpc9W1j(y{>uhEknmpo2GaiB_%yRFA(LdL6}D(%Gtz1M43eCUZ!py zrA4gCT~JrVnnGz2tH2R!sw37kN*5SD(CtB zZ_*c#JS$E5LQ1bT=`hi(HR(mPgsnH}#YD5wq>G7WGt~4~sEIwx(7vQGlN^*ynhEv8 zCp#HZl<`EQCJtFS3!2s_GL_1R67s`QhKcA4Twr_&lD9UP8ib26#t6kWg-Xohcv2r>S}iwZO>{qmm3q%wnP%^vQn9e0JiqVsqKRHw z-+A~k|Jm(h3f46jAs`~`Epmi@RQe}?$8Ro|&I^1RlZZo{8#`LmsoVeHwLfxFvW zepf`$OkzHLPN(r_x>P#nZ>V%CHC3KAc6uSgX;$3W884utlAcNFmHmlm>?~e*eUmAq z211gVO(j{9nL{JrO)^E4=_Q%Dr1@;g%%e^0^}<{~OtAQ|=*3nf!bC5t3eLYWfDL@84)nNrGBN~Vl5wUQ~P zOk6S*l&P1@#gw^JGD|44QZkj4SuL5WImoP)Of_Y$l}rs~)=Q?AGT)QTQW~|5lBpxT zZIMij25y^V;?zz~ni;tS?UzPKW*L>tmCSO=ERak+xsZjDX&}~%(y*Pww;0Wq^s$$I zk!=lSg<~|AIYx6i@$^KFm6XYl%oUUgN#;t*w3W;%>SC5;R#T?4WY$oon`Ew{jJ2(+ zi9xoMtfkB;l4+z&f5}`!nSqjNqD+otuBFTf$*iNy7|C2m-5D>L>nZb;WHxY#=;#J6 zk<5*x1X3CUE=KGW>m&``WR7&O+%G65cRvL?X$=pWmtdz{{ zM7BA-nIqUV5KmI1as-TL@MjC-NXOnwL&`pN>@(-WxFk6PTtcA$c$S(nWjli8b3yX? zAo)U&{5g3+Q|%W4`XVjV2Hi=WGs#^+a(6)c%OLquko;9Z`|ALGIY_=j1np=o>V1+d zHIt;BJ?(*T(HXX=lN7x=0Em(1H)L!k`P(4*T9Eu*kbFI8cVCcv<0N=Y!{PUYhC(!X z(~$DUezO$~g+h4S1o>)X2kV7UT)Z~sq7a`#oEBpDjCMl`VS^3FfoV^mE+UO}6Nlw&)2d8uz3vddC)>Ek)yh zXN$=Gnc-7XbmqslsHZKuT8hqU1B68!Ws9~-(b@fM(QI3^RElyZ*rG~XG)jslECj-% zJZ@sLA2(R48>DE`m6pL)TT~}Sd3V^NUAE{mDawD`7X8&0MWkr*Z*9@Hw&-Ljn)0D7 z>fTorGg*oXS^+V_PCeJ^=xj?hREo|S0)%yR0TMjKBkV9vJI9tSv(<2dNoF%{dZ{hi zV2kdPq8V4%qWf*pnNl?Kc3ZRy32yAqwy{}1vt@7FvN7pWukg3FjJzG!J1$MiW`AVM zdZLU?<5DS_L(!BOe_Ql-DJtp*#B^mYb>%ebmES1>v{gE#=?aA|f=4q&otqaKu*(KT zU!9~szIle+&;PBzy_w(x z8HI(&MNXJ5|8|bz{n`93{*AH<$?xMf!#Vmo?Atzs$5ammlFt-|(5r zf2s0cOMV_dBbUBm<>jXSe18oFCw;@(%ZF5W{<-}4S^9>JQfl+-CBMKY$kWl?oRrKEkbVdkE{GP$zR};O{Q|hMu&E(BUoXt(ZKB;L%*gC&p8b_%pEN_UN3z=~LQdbXU$Rdb z+uV1Vh;p|p%A?6{9ZrhE1W<&LL~^3pACe$x8%l&1?|6iTSHreV)Baxg3sXBz(G}*E z#31)k4Ecatnsn;Vz#oD`{4?2;)l5+{_d{uCapC zW21EWx0A;-qD~gUsjULj)?C9+a-xu_BpOEDl$~QJ7ns~Mkz5UoWwYQv+=z+hS@b%C@zwVd3`u zshy}s`xC);2nsVhq3ZbV2v4xap7+C6hR>Z_NgeL4l@4}y4wD7wzqI& z!ahOU*w9KX=6525309GRsrv=JN!-?nVfifvOaIklFcOLN;r*gwu1w%17^aiV(R7O|aHRjQNruE5YNO2wo7bvsh?mz?4;wtX zIee5{v4-YchS(Q6yupZx_zjl9#iW5)yrd*rI=I|JU%7E4p*eK8qQ)dAPo18R6kHEz z8HAd^KOC*AqjyRS6*ARS0cDA5pd}`ary^=<7mOBL$|$;B;vyx{SaF>TAdUA)Dh=n_hLY&wM48Dzo?^VF#WnPfQ@u-5M{gjxKrCKY(VR_Hw5q1A!KK0Dk)_dQ-B{cZ zk4Eb1BF)I~qFQA$-lTVzPf0~_vwXBVQRSB7ffP4e#joYKNNJ+F*v%JLMq)7+D6MEN zK{M*whT=$V3~%}vg~#h6#nHu);w2^}bd0c-_oo(6?BkHZU?XW9kysrnoq|EFwl?UOy5T24a~N(>ySlxilS- zgnKY=;F&bPqJ$)z3-ki%O&Y77tnRdC`qR_KcM7dKe>;EWgx*c-*J;?aP1{57gjPLZ zK69UZKeQ@sK&Q~w4T-(m&)@#e17%)XM*0T&NE_GzUw+GTTE28RZCa}~Bo3_66McV0|L6r6mh?a-W44t{@0jkq7w7z9%LukXMulo)A^!?D*O?yMr zc5`nxp*THlxshc-OA>jAsj-Xrv<&5QZb8d84L*$-U-#{Y}DNw@lr$gr@g>4y{_FcKNq0@G6Lz+#AUv3SRJs3K?H?((CXm_%{>FgBg?A@Uu zH-xr__J*Ef!rgn*hIc|fg=UC!RoT1mhPLkwB|_W(lbZjAIEVM{J)D#P-6iV|M56xh z-M!c85s}PxNw|yY^`Ud5lj*Hr4-KgZEekZ7o)w>#*1yyCp&PcJl$M6YxUgXg-i)Nl z=<(FcD~nIYyc;oQQcbiJckLU(>~hG7d0}U1^1_MgL@Zh|%nOtMs;=?y!BpbFvrB3c ziz|ieganqiGe#Mn<#S#)hkP~9DXkEObrrL;FjF&7SdeRr;E!{{l79{FJMRjc@ zTr`@hjYiPa^a-eutSJ?gx2o z&GKlSS5;9Qu1Unh%W5hURiwB{@ba#FQ>#nx`fwzWkZM%adhvSm-ZZr*0)@lT>SYym zHPxQ<0zMnB7(<14RTyDNv{nYDr~w@7&yCboOV315wh}Utk;C(bngQjQ2Z2a+X+@cR ziI)0LfL~=z@ev%iXjN^zA#9=_FHCExS-Ghu0;!t1a7o3o3PjAN>oYhgVtJ=l;q_Fgf~S?oF(?l$YYwxBT#eCN5rs&kvASp#URy5#+hr9oF=%c8C5Y2u zZA@9%FoT0`V-0}>!$#B&HxiKCbMfjwrf;G+?hZy(qB34lTiM`Ycq-!Y$YM0onoIB^5cHAMML2#5{T={FVHk^}b$QWJq|H3!SIUW-v7A{&#>(L{ z$;!|MSsi}PAuJ|?Ab4*5BzW@bXl2afflbt6A7-i-LObvpdC^+*oAqZ06!O4X)6WSc zs!P~qU|UkW1gQkQs4n&AAcJj-tyFA&IDohtlb&A@U2c?D3C-ij6^#3ec``O^6UAW| z9j#56BVJzq{BYi!sq^#agbU|QFUp@VFK_BB@dLGRk4V4vT<;kCsFanDNP;Paku7O>SsXGC` zt5J?0ji@L#)nUyTYP0x3({pL3F%dfrqv+Z6(*ee8?I=&=9hR*O3yRfZDzo`v4QwD& z3A6vl>Vw50&cEp34#ccEbImx^Y4a+h!HX{Q!o}sN`KL&=T$EzYoA_I9H}(gGTsqm%A3p5QhKSu z3<`oV@;Ehh`Soy9v{KScwR$JFa6UG4;ufqQF%!8cx|H0N5ucm`J4!EFR~N2|l^I(n zS3PvZh&*vKSe4jKAY4lJI+pA)`Ho7gsubCopS_rqKWWySyzra}GFdCaR1d>LD#sNM19wU}8zBQe-i zZ7qj8#;Dj%*p^E;3@vOZq7Apm$iF5MvrZ%~p+uN{kOvEPf{>XtarjyDD=*O!V+4yU zk`og0m0|5gcb36ODB>|uV3_@NEV3*r%sm2Pt~Z-7y=VdyV?BB@=8aKb`2+puez0R9 z0~j_UCvT)#XP}b`_!9}CU@8b9>Y`;B2Q0`G!-(07$s6B<*_bFHe-x>UM@t;_j~Z>& z4+n>}y^h-@qvd@+ylf@Mv(3bU!>z8Vz64h7#mW=$5)8D}q_{5X2__kMB1DLi3-$Pj z3bTeAC~P>l4&z1(TC)30fEr9-+y(pyiBb@Wl@~>eafbmsc~y_GTjh0*f0BjPfSTs3 zE^RDK=Z#~oMDNT%%P*{82x#koi3#&D_CfxEhmPV(ucor35KghM#u^Nk)OeygO3UHW z6uj}nK?uz$;xn$?SQbT^c0EC}9OH5@`Lq$d*l^A*`;cK-I;Sk?JMMg&rP)|Iw4O(2h9)w>kM&^J zNI^S=d=cz%u$h4r#c=cdBS0oVC9mAf>}uiQX@`NTbxSysLUe8VKNGXUG=(7#ehdgd z`&3q47OCT);_ zQ9cE;GUBY)I=k1SWshuxeMdOVlMSYh-6j8+l<7XL6!>3dL70ZGR_H=aW#?HLNn}H2a<$baYb9gr9Hs&Y=39M^U z?C_kNJUN3%V%WtFGrkb>tYldYxp%XntgELHw3{H(oi&UJRfXkwxZHBF8TcIz*)jYO zce3nXd94{19*V)HI514d{rGM!nYd)EF?KcP5lq@2#myzl!tr``W06>KMMZddIUG@} z7Lgjx4Pahql>7m0uBh@PcET#SGGds#RHLEv9ueK7WPw4XC`95y-|1IQT~XI?{@K{6`0Yl9m&O-j_& z(eI#{#W-euISn3=*Jg1BXv3T;IDE+&%d z;ZiBUuAxm(gwFBcvFqX<_uMS6<|GWE7HylzuE`5?&>f~9qhP+Wzv8(S#>Si67p4L4 zDS5F*jLrRm%OTe?2O`zsd@-qM>{M`{%9yd)=JC1;0jnUJv3uvhLs~VIX8pv^$wkX} zVAuu6FA0~#;^fVwHZ96`~c z$Y)l@@1ZhQ#9)wVWwcveI=ZVjWOQpRo9xzjuH=sd(hm^A*x^#}(|)+Ihux&z$)nN|saPz=aRHIeIpWHUv;fOJI zPA-Y!?kmrH&|~9;{)=Cw15#Q**vq(wJLLJN!pn<)rFo2ZM`STELSuh4)MNF_p|$B3 zwjSaI&CmwMLF*3BK3F@(#W*PV1?<(pxd;=cqS#%hU`sSQF?Yc>VU9IP;z4)g`1Yfj z%q&ndhX#YA>0!=f&{vuhUM=0v{No4DKjP$`@`>63TH&TOiv4%0L%rz2Gr z7a;&~&ZL8AFNWBzg374pvJtRB2#y1*@RO?8$iY_ahCD3hOcK)Uhx-r5andeE$wNc4 z8H*dAn^+OZ8BdEziUg7GwypGMzI zV{xTeV_-bwFUd`#=Fnkd&@D7+Du^=(Y@A0IGZ44w;S-&ug2G|)y}^X=mCQVmri%J*z_GX=3W&xO{@ZE zpUoU>5Mh`63OZ<@GjTE|+@3SKpct3OotEX9?CFyS-Z~IQd>#%b&paWB8=~8wXWDWW z7=3^dP=qA?v+*0E$vWqp#&y!}Da*`RGxOp3a1xBOOc@RE*gJk-OJ`xR&s`&M_0J}f7eGaRkb1e}E# zg$9-z+hnuA_Hrcg2=cw+)r$tnjK*{?#Eb>==L#)fxnW^`!PYkqi8g$)2%q-oP^ zS51pp-LPqlBBU}?k9`iEel+tBh8FGe4%95c$5{64%^N7Z7V|&`APm2UcoO$Saj@&Q z#Y;di)7Xqn4_FUHwKZ`Q@jBKU+`5@Eb6)nOp+mDr4<0!0VL3gj>d{>T+|AEu3oiML7i1zsoHB`y74352|1~(%4;E?UlcmbX{@Udnu zVoiW7K+bWhi#U2U^LgTgNz=$WBa35DDeh;PU9j9%t;O?XGIVfUd|LwkFp7H`*bUOU zK?h0+v7aDBpqpWsrYPrVi4Iy>4vy-u(;8uxGz7hLd!mwjC$?;?Z0=1?VEH4)-~eiv zRDhQ}I-CyYA(}jwel47)F^SL0a0VHUPESQ^-2&&D+y*fBCo}&DLkrSQBil4`dHytw#RolCm=4{7tX0#KQ0mWY19KG9+ z5OwW_3-K4bYYEYC40pd}JK_s$+hZJOk!I{kkVIMtNT7Ax?Ugl?7wTsF6Rd=^#x-~GbgxGy z3R`lV&*|KaGsnC<7WO^?o-zaf`(87qP9k;Vs1NqznX$(y0v18Ig4l8# z-N-E`UVy}03n^;l=rLLctA&1yO?p!%O&Xisf8Jso6eY}JGiZ2%b3-p1I%aUrhye!0 z``q$8wSUPR&#%w&d$v6;v>p!?6Sh44x-?t=QYq)RLXzbdC(Cb_a()BFmZv?K~u{ib(i29LkKMP*3aKO-l z^Nt?GU3-VXVuufPf&knz^d0m-GC-%mWMEZu8& z6h=V0`H`BV%H$2|W8fmZDhaGMD0mJ1vU4#&J@5S#cnduGek}TPF-4Ds_fA1SHU+*Q z1zw*5Cp$e>yLY6(A4!4#ItBh#3jA;i{L2*hkra536nZ;71wJ+fJ}(7+Q40Lh6!=Xk z@Y_@1_ocvhq`+TFf$vX&f0zO%H*&0TZ=V7`J_VkW0-v4&FHeDAo&vuk1^##n{C6qv z11azfENREmLyr{rs1*3QDe!m-d{qj3Qwsd46!@P~;QvU0cf>kztp1J!-Vq*pP%q=f z=7=*pI|cph6!`oUc=G8=v-y!N15Pq=lU|+%Q@D*c^t6$9YyE< z0ucs(-D=;Zg}p5iFi<6|1CB!wtqiP7vTwzxY_90Ly$Zp z5!%Et1|C|Wr=e9DZ@_W*VhD689>1pzddhOvj#TBo@I#NPi9|L10XfZ@#!G4@kFVW3 zH+VdU4hr#b(vmR!?KzJhj;75$ZsDmGc%X$@VZ(&FGTcPP9ddq^g*VSL@lX!R>49-o zl|(}c>cFI{&C@=b2Kt+ssG1Z!B_#(s^ClIIptJ2NFrX(BVt7ajH}&Od&6#*gM>R$- zNYXQ`v^}Q-<}lGnvM9>u&B97}Ou%Lz=S`N4IkKnwRPy*KTErtj)NnO@TRItc*oyt5 zd`FiAf7kBlvdPK6%y)Dd{k6GcG(>Q|{H?xYSDHajFC1M|#7<|9Q3^jHz$(o%uSh9+ zIth|41%IW`s4ONbQ8h4jDSPUcne)PE_Xm1ck?} zj)PcYeJll%LZ~dzMlk1{Au()&C!cYGH5Jb%fg@g@9f6n2J=_7u@fANTDG&8UYAf)g zld^6hT*Pk4^Y90-`O0?iE)Gtwz|&>v+nTKTtr4V&2mL&bG5{=@L!;+cY5ITr~3 z9tyYo`=!7KDctfuTX1T3xYO=rMQ{1fP`Kr@z~M8(;S*N$_B`Wagr1Iv~Q-%%5TquK6Y?yX*{dX zuN|D`#r;%>%lxHD!-pWtKc5)mviui{J2FcErQf7*OaEhqTX`N*xRrmm;PmDCz27K$%jXS+ zTRw*zKCU18MA2J0+hBi5m$jcuWgc}^_-esVPJy2;I5k6O*j66eXVazmk57T0@MQ`P~(!t5zo)SB|IR*YB2PauApEnh5*RO*qa3A|)x@^DfId2;WCsFLY?&{#w z?zN)NQxtB;_jH9@J>)6e%0FFj;yoV!E&W9f?#2n_4jPi2&Y^eXghoXlH{{-p zDd>Od;O;zqSMj-B_#AfV&je=WZzF-A)w5mqyD6OdP1h+Y@PUF8o$JqsD|%*vkFx|P ze@K6n*~&9L1wKCoezD-xuB(S91*d+I{_n(px^_DBt{&cYaQYEoD^CXrBrKo1mveyl;KX}^)9xmR50%+C`5}c{zxoS>Qysc~ z`JZ+0DGvP+2QP5&1#&-#e10;HC!}hnk!mT}wb#T(>YxqysM8S#2Irwk+lsoiP zX5+x+De&(*IPw1z{?oO|;Xe&|%YU~+@5=v%LqFZ2f7iiX`^=DAT2^l#QKPty7o2$K z;=gTon45*EC1^b?#lm}!^hQg%S>+eC_i?R;I_Z`8<~8a=Fq$HPj%>BJ(oN5 zg^rvF2Or|#H#&S=Ie+NT=Q{MyDSEm;PSxA;_tkK3;c9Qs^`ez~Hz&#us4JEV*FyZyS$p{MoKw)?2UsUBVQ zhZpJ6{d(8oKL_QO&qogK_N$%T-?w)15p%_#AQYV1%XRpiq3GkH|7j`c@w;k#5ub?; zpK8HR1Lnq2m!`n4N`c?%@ORgvCmp=VY4=qJch|e)JAw!o$?4J$a&VWv&cR*!MhAE4 zzY*N(d6Vd^bti6?+jZB+eu5J{$z;cIxWcK7u8SR2G&%cO1VK-0GA5h%sFm z@<1N(cjf8r;1{CIwma0p-SNszfzKD*wmVtcy~v?=+pTqQw_n#g_(hI9KXdSj4*s%( zyLvdeJBV;mf9K)9?bn%tTRG>8ocRvDE9bcm?#dZWf!8YjmBK&a(7W)@{Zzjtug zo=@*Vy)ylB=^Gr})!X+R+?AjHex2px%CpDNWxx&F+`qv%Y)&Ki~ zlUm4C#6>@!IrKRW|9=Xu*WXsXK!i)RXoFx?O z;3{yL?cUFLImIw`|S@--MI=cZ;6; zOF7{L+2=CHI5^QiDD=4se_n7JYq~5S``qUO12ay1UJ?353a97s=qfi~Nj~N`=#NcXX{aUr9dpxzCLbPJH?c{bq$v5PXY+lZf_t)5jg0_{vlT`hndH@R-8KiGrU~_*SvcUn{&M+W>DUJWKezqwvQ?&QBEnki=)-DEuqx z2rm0vx9!(pImbVqCLAt{KPdgO&pliG6KU7(r!9WIoKu{s_~d0XTkjl&^Ph=Fk=?&q zK5fM>mnix>#eSA5+}hb?3SV-PX}3w?*PUqajSAo1+u%P`_(x(__IYtD=LVsBR?$bq zu70KP7e#MxDEv8D7vEL*QaSH9tnghz&rTL1TX|j)yq(yW#p$og($z!Z>%~q^Rrnc( z+#9Lzo-*Ha6+TwZbEhc$8JTxQ3eT5wim<|WivwGt@GfExKUR2==-I9(w!dwqzuOi4 zGZG)~RCuYh`zM7TC+p%th2JRi;xmP3i(j($ovl2}gnw(1*WxuN8%6h3_!{xsISOxi zqM;wB@PRU3lNG-91XD0u;cMC$oSyrp%gQtIB$JOSe4WgTOB8OOSGZQ;Z;2n+sPL}R zue%lAN!oot;WNcPpHTP^(erBxUnTnai^3CPp9d8FsMyut6#k~nyMHLWxA1Qv>!;OQ zZeOFf4hsKD#G(1 zsKgcazQ677`=+~|y}xhq-V(6fulPJEdVEshmd{RwTRyKT{C#Q&*IyKVs@TJa3eS*n z`KQ7c$h-~7I9U0w5IMUje6`sBNeaK$h~o`W_%pIj+57mG|DT0!s-izt>}tNk^CgZd zR`^ZQ-&%!-WL~dO_*-Hp*C@QV*va=5exKm?D7=r@^Fs)96KgHPwaln z%5$^$pI<8a8p-cd_*&n{W1nZRe9Ygm^t{g${SMJ*n%JGC&y#tPrSOwPpVodY{oS%I z+vgc9{&!h_$0|OnB~F;7@M#jCoUial?LI=`m&m;Pp~4SH{uPDaC~?R~3O`5uNv8M@ zEB}KsE@KrQ7rz}=_&$-RQQ=FZzmF*Vu*}D|6#hpN09QA$BP-8^GQTD&yiD{qL*aju z@vT?*P8qMe6#kUpzft%@;!pmh@Le*m?ehj!&Qj^`7m9wXjANSg&(iM|KiOX4Ps+UO zq44Q4F8vh#Q_<%zg|EqGb$YWD{v(;c=PUeek^dTn?-alB6NS&}YxwU`IK8(;*XIhq zO6;(|*b5a8!2e$oF|H8`e@^<9tMEHzK2BG72eAkH9EIg?pJOXg^f@BGeZIod-zNU# zQbm7(@L#L&*TsImr||aK+%0dj!mp5dbicwM75zM}@Jf;A=L+vEkm;6pp2BYxecI<|EPwt(iKr7(^o_!2rNT>Oy;-Ml`+Wbc3b*eSY*Bbj z=KIqMze~pPmkPK3eXqjpI%l85vHiMQ_NQMd`T?T<<7B^R=|2^F=&bNdWSu%u;WtWt zu)?#&KE^40fy@j0JdbU+QsT6EivBvW!#ah}5_`K|;Vp#E4uyXydVW{oA4$JHRrvAZ zzfKT8XXT8Geg-J~ZfSRNou=wYd3b*H9*DCyWv7e_DK1%%RD++Hd2A;$=#?ZMQ`HMGuAV5Oe(*J6O-z@nC zg>R5?T&?hL#NMt~_-Wz?ZdLgC!smwyxADL>h4&OWw=2AdtWz&4{3o)GzN+v!qPIUP z{7cc#dkX(l?Br90)9=90^^L+8ivB}lcXk{jl)%+V;iF`Hdn^2Yp&y{|<0S4Hq42J< zE}X6KZnCbOqwqoEf95GXOZ?p;g+JmO`IjhsmyG)|g-;j#U!icr1@FBne1^#RkivV& zeEEaIUyyj_U4@U6c0W=0tJ3h-3jc-Z;W!z8J6<8_S4V|!6ni^C;in4U{tBNX@()*d z3!%63(ze@A>~pH3?=1Et@wY1#-bcp0N#R3;{$_=j zh<*M*;nSqQ_bYt3=;vn&|AX*(Ug25d|9`FU$>KlvDf|*?_pcfkd-zb{1G7!RKNP-G z=6QyUj~%aPC9ca<_;17y*ym9#{o|tlzKVX4*kO*spAmZ-r*Qim#$<&Lko9Y}!cUMm zcA>)CNk7XJo<{=Xs#EwvnO`duexcamT7@r_ak)|9bHzUIRQM$6?~fE-AbNgO;fqE7 zXBD0&>&`C~K2rST?-c&J=xx8k?Q^S#6uv&g=;sTCzas0JFLACNcl$hRTZPXOd+w_6 zPGbKjDg1h&AEfXwCMkTjtZOqB9um8aD*SbkXQ{$3ly!N9!oQGlY*hHC zvcBA;@V|)OexPvs-p*Eq_sBN-e?s9eh@8JrcuQF?URAg+_VcmAZGXR3c%_VcNam9r z-)}|#ofUqM*nhUd?R!rH6@Hn_yD|~+BCy5^`SNP8*A6NKS z;{R7Fe1zckxofM37GiH375xL^_wG@+ea?QH!fzHmJf-j}rC+-gK1KMyrtp!1?^pQk zvhVvq;a7@1f2r`FioLZFecS$)_BD2RyuyXOH%;O8If?lSzf8urOyL<~Z&xckU;OP2 z3Xh3B-=*+JWnTPB;p+u|Q{j7L{vJ^HpG2O+3O`Ngzg76Rg13@&-s26^m-yrjg)bI=^|r#V5kK>Hg`XvUCSCUHw%z-M&hFza-d^<9OVK|jaorGw+y0JI z_=93^QxtBW@1Lviy^;?r+`dI@n@B)$Nh{Aiydfh_4?fBM;y|q#JV-ja} zQ22Y|SGy_v5|RI8g})_sW$(Y)cI`YGujp6Ex>KO=m~o%pJcV0-v{>PL#4pzZM`h1+p|N8#JW4}7ZdmqkBE6kaOvYTIn1SUc`^{&rXRPb9wTr||P7 zE*-A$d}%jV;nv<}DEu!HXP&R{-$bO<9JZv_saPFUE#|`KOtF9>^SbF1g`c9 zA0&8Zh4+A;->>kGMV~)Y`0vD@KdDADU+P*DLzJ zi@&{5;Rj`Xc|hUs%XsZpc!kW1w-vrQ+q8Q`;l~Mm5AmZ`&f6p&u>RHJ5yQr_?>Sj~ zsqkN@_}D*{v|Qo#_b6{rxV?Y8RpEWaZ|qk1^D-{)DEv*4-|uGxwsMNvyj}`lA@(_1 z;eVBJnW*rX%##@ke@*7~d4l_BK0|ayU*(EEPwXMC=*6viD-^wbo~%*Pi( zRFkmd_(P%37M!{%OCS>tQ1sVI;Yf#`_}jnNb(W&Haq>A1J?X*fxk%C9A$kit^u)hJ ze!sL_(Qgrd6j${2cO6$K`rD}ExEd9`{XM`N6#eLyhW<`PZ~so%eTx417KZ*2MQ{Ip z*sm0Qf6@ON4n3(j+pzK8QuKSpj~#UA$@J~tU-??mzasPfxc-JAjW5yL-&^P{xV48j z#h(vWc#f<`XDNKaafa_qg})s#_(cl0``&7W+w+{u6#k$%n%fm_f4}m6g&&ml?kR=$ z6#ONHUoH0Y2ZcW`@xUR4w-tZ&PldOUIHAn|({HQK{$dY36#lKuqk#&4+f?^PEBt*K zm$L-7<7oem+B`*X+bvPJ?Qcxsw!fdqv);uJfd)GKhG=N+R3X5 zw|25$;q4{v`bgoMW&QeA;n$G!z}4jJC z7KI;@h5uo}ZNKb$p1T#j?blv~+kU;HaNDoX6#j;c@u+Vc-2Y+|HLB3b+1YzrwA*;vZN-nU&M};cV)VgWGi~SK)TuT%>Rt7p+vdjjz1Hv4$%A z{b+p0>&$n#P1Qv!BZK47`nWfk{yLmDcyTP|4Q7<`lp2gb>J_O3SYs$mVRUh#EL>4t zT7!z5jx1hW7hPuS8mKN(U4}nFF8mm)tf-FKDiFdOTwGIC6~&)pA6#7%j}D$PbKW5S z+hS5FS{^ok?Aoa4fApD++N2_Dca~YMBE0-8~hN>=6GVZc=Im^({ctnt1B^`=$Oy*>70-Y@3kpQTQggQq|utboMLT zCggi4zK_-a1NR#OYk$-a3L$m>Cj+DQ-8qV^w?o#wT}m)ppJ?bR!hby`gs(l3K2a`y z#^jEsor!{D$zT3}sj;uXe3Sgtwr$^zUl`c2+W!MF#`PQ3F-=A1Rq2yTd=lO)I zfaAE#py;^IxP3bAql4SHjLtZYjyjIxEG{tW=-~P}D*yMKI(2V#CDHHup5OEQ?*rYZ z-a2*a)TvWdr|RDH-BMICC*Zn{zFg-t$4_b0ai*N^qxlTyJI6c6IR)iQi#t9o3wQh> z-0{sp%IF9dJl!LkxWg5}_Ai5*kJ`Ga=aJS#&oj;}Sp5X(Zz3(9;_KT)+K&#T-FKj% zqepi8DZ%&unl`KuWzPTLODfv&MR@ll5?2}C)nnu+hPG!@1-S>pyGydu!@J9~LnXTl zvopEY9S733I{_5jwJAG9c|F1%?;bqs$dM!AT|G(8uM4xYoG`In1>M5!GYNFkwm*zi z$*vMA#L$C%0GD+9_LG~^u6TUwpPcP4rERaK5*3j7;4#P)M(~8&zd9zIw(z;|)MttP zv8}H=+n-I_J__sw4`dK)`&Str`(sq1Gxu|>&Q}>F9ghhsF%fUF)QyTS^}$qMhpsuV zRGb4I9PoXd?<&rI5BB>W&K;G+xhp|-S7sukesa^UiP_!DE?i2vv)k3c=piLZ;u>F8ihohGMxdK{c(*_H*G1oM08g?H|B- zxT;d>{mh3T*?I68d^}1Yxd)hc#i~QIQ7&y5$vd2u4sXkSHd*cne3gKL$)mUv}ym=Z3!JtJBC}5tk^{)vJY!d z3BEyNU?4Pj91+8ba=<-iF3mp zPZi~U$o?u#JkN28JDyBT$bCcX65dsm9^N(MHI=_>X{e;*z3{Gye+qXz9&UfaRq)g^ zoeh61>3FxK;|m6g+s9Z9SQp;e{=LyA0gX{g5WqiKMG7SIGQ$6PXTfk^^ z&Gzgo0nm&ulRakjzlnZn+tYbY!hElk+HnA0m$v;O(rR~Ib~?}M;?21S9^49C`7=@Q zQ7*NsM>h5P3xKG(;oV37EQQJss376HCp}NRyJy~rRl#U<$8mt24z_}}z%J)VX=(1~ zaB>#hJ|jCARvd{{y0-AHecU2++)(bgmNl5pZhL1CSVxQuWKtRTNKo%??%i4kgy z&+?^@9Ng+Sm`45s-^?;PpC;P_rgg)+XhCzT(mpz%40|~3kX-zsDRX+~KaQ@d+SwY&u52)8KM81v$5 z|IdArw(0=>KTECp7$1uchNr&R^5UUkyuvuJP1+?Hpbh(I>ySToWtT($z+xivK>OA# zsOkFJ=6-nSNxjw>^H(?Xc}N<+Op99@MmJ~X_GM=ziq4MFq+BF0g~ znH}DpKyY&MXE4%^H`2EMn=&g3f$xGC70?+$TE`#5?O$df0(*u7wfwXzex1MdFHZh; z^x%n96uAaF@u5g^O!r&Gm-%2O`o~}KyWo5hoCPW{X#cXmu$FW@OER?zegwMke^~#& zda$1TNsx-`SXd`Ld%<*Q&)^3Kf1jRTtD5bIvWph|RB@(1nErh-uUA?Qd~jfQoCk(F z+tHmTVgn#+ckU4^(rVID4a4%xNvx~I9Z%`tq`1A_L3C2Qs|XA3M_6#t)mdSTt^8b= z_AiK%!W~!{l^}{4u_`CBSLpu-zxkX(wkNZ&i0e7N^CFJ088S<nv-WeL*bxpFz)MYl_Pi15 z_{+jwJtT(eLjBYJC+f4V6oeoENxSe2HQp&y6uGEx1!lMYvP;ACR>fWWWQ`Gxc=3lC ze1|UhTHpIg)iHnPJ-+sTZ7hfr>{8e?$cLtKufG5#_cQ^d{Pyt#XvEZ+0 zYLvxP??1+p@x$#!j(cc0w{MN*i669VRF8{E__fVC|>MC)s~h zlw-%>)SJZ!&q}7&Wl!1glS5Nbp=v*--BVOT#m~v@p+OdcQT+AJ)9imKjmsA<|05uPUI9c(5mu zfrzP8ae4c<@8R21u#C2LOUpVwf!=62*O?RyU~|WF>@18|6+o(R5c}4tk0(yr@luD1 zfRyrS+nd2BN^|9kn*s0o7O^+>)mSD%wqh$9;GVc3D9Z!vZB3$u|G?DySnMAq^-B{A`_XQmX z-2>q(OIfjkj$aq;_yLxmlO&58H@i)r7Yw;f9JLlfh5 zKq^`Az-L%;R4wRz5IB*(up@lo7y6C z3Regfk0lBk60wGcs53I2RTZtRo0c^)-p9|K6>X^8P+OU(@u4}*v2$8t4Ha!ZG&fq? zken*2i`B;(63O6##>$wJXl{x5a9OmzsV=r8nus}0trM@Ub!JDK5-rWKtg7b5dg$Vm zk;-L-OA2G_Yb#=r`sh03iJ~YVqUvhnx+QUes$&UTdlOm`ZK&3Y0H4!RS6A2qU0VI( z)GUk5&{x?KMSaXwtl60xOJqf}bbn;|8StWrpDOE)OMxhK8&LRLE|~B@{oY=GE~(;9t^8RkSp9GN0JC{Co0E+sA7fn-i)x zre}?;%$k9ZKF%CCAvtQIF{`$|i8z`XYcZIbF_6f2Bj>c##@9K{5~$JK0Lzg{vl^>> z3#yKa>oNMj{Kgdio!9^0`Q0hE`@?&${o>bmoksZwj=YtRuSJ>o#MTH`h}G`PwDIvG z9VE*Y2r+B0M^Bhr6$`#L2bqD;QN$8(L-f^i0nq^k_293bYY1|C;S)L72|7-%iA0B( zX0bgk-U39CyNNtXRoCNQN`ykcz-RAU@gZ`0544&6}s=OkC?{}6jf z;a?M-uIO)w&Q$cbL}w}b2+^b120a~@5;-d2a$<@~1UQke5AGoLHd} zA-5eGu2G3TZU+)ID$&;^g_~3&of8R_=;vO5oK}?>=&nR!t4a)V>yX%{5}ED~Agx^` zhPwNa*r^gD-MwJjqY`7?eMnrX65}{=txAmN#4Re3!->08BF~+UG7qT41lH|YTUPq+RKc$vSkK9BJPe;!#AuL2PQmId=1!?3~ zgw98T(R($Tfik%0Hk#A(beC{N=NohZ)1lDA#Pk=i^rjDXuA}B&1CZ`kIY(Vc>L_xj zPj+}@=vdM*^=)wFAUeo!dXB^w7YGd@M3Ki6mm-IGXz#J)K#cYtN2EBr3>I$GMG(PF z9j4mQ=Y+uJfI=bS=T`N}W`xD0WP1`*^1LcjPW8#@tnM#R_-!qDi)wY>`~QVT1bVOu zSn|<_xI?+WLa7r^LJs#=>SPikG|TP*g#yU#O+2Zj!z>W2x2qbMwm%ODE17n!r%u{+ zG;$Sslh1I6&u}L(ur_I#zBcLUXWt8PtWEklYKf+oU^WRk{Q)>T-Sk42((I7wMK1H{ z1T*Rc<)o{`9GCncQzhndnJhCgN+ssI=i(M=j!KlcS0XV*B^J2PB9X5W3*G-95mt#s zZeE(>l&VCjdm0ieRHED+0he8)5=-6DNYtprGIu-@O)9a5kH)Ww{tk<@NZHA(6c_K{Xe?RD3{+*@4?74lvD zLyPM6c;t=-YH%ol&wiMm59T~XoHXdZ)SOaXM-U5kDAXID18IT%qQo9#2 zYdNtJT0^Wv4B~OAm@bJkQ=4YGG>OUN+C?>lg64cbnUiWa zoAkranf+_cKA^YOla*z`p%5*Vp%7K96u){5*g~N^e6peDd!<-D2@%d~h*K5X9|ai- zRpXNjoeM&lgec@tS;czo#msuCX8pOx%JOMVP@&G6^c%t$yqRlTs+{y2NlhoSaqZbo z`c0&HD6=ls;H2M7g;c1Mehbkm)JgvtH7H9>t3M|?ThX`O3VM{HZztVy6nzKLQxttC z(fNwLi&O|J`fk!;1(rxuvjVWJ3aVN6P&*WPZv!&n|M=t%-3>w+gDKJm*(5>n-**l3 z-+<4-zewU0hF5>Z3{T;c1-|Yv8P4(A+syP&%|sKQs+CQrs(QUQni2}7;gcniB@`3O zWX@x!xan^UMu?+Y{dNaAprYR)T7@*}?-DJRe~)Of{6V6{@`s2PYyXo5xLEuB3eaNh z4~Q0Pe@L`g`(HHHOI5ue5xzpvACt^AivBmzHHtn=bd#b#A-Yx3pAx-Q(Vx+%->K-& zN#-6!e?jz>ivE)5YZd+9MBk$5uZX@&(O;9y2NeAc(FYX$Ez!>?`Uugoq&O}mWJz&( zxsxR&z&Wy{1UVr~N)JxRlG2kCdP(WUDZQj1#D;Laq@-|4FDZRFl_eAR(VWstO1eue z!tKr>(9-k__rK8jYF+E^(mX1O0bD$!at6AyVas%t7{rN8mB@5yLd;T$ z!7fdFqg3Kpm*%z{l^EiZuTN2l<5+aQN*vG9!lKtOcO=vqnwdV_{g?|%9geXoiP0`iaMGxg-DOBfqfT+pM?xAk#;t(1(x|cS z50Mxpb&PYrLLJJ8x$fDhCKPJI=U|Gf2Jw(mnR)JooVlAaDbC`NCnYDiH*n_9@X15- z3C%EwDVa6$5z;AX6Wv$1z#CMc9lb=Mk{ZjmQim$8NiHq3ik|Eqg{UDEIvSr`1;tZ- z2~(R>U0OR-u_-Q1KZ>5}(%P=*Y3?!>x0=LJ07e0oDP+34ff>#t2GWq?Dpen)262;= ztQm&fnFf8DO96o5Io;4H-=GWJzi>5g>uM-c8bndCUzdoO<@QFHhWQVltPusPij^jH z6iKt==99W#tNrj8u4T*{&e!H zEQsrX2xXn0xD<=={v!QB_ch>(e#oF7W_oCPdMGdkxoR}@4p84oq7NrRA~Pir0-KW4 zmy0O6Hn;-TRdk%`RBCoLkPLy(53WW^v3wS!Tt$B#q^=L7^KvvaGb6=)0vW7HMql?+ zVp55tIibd7Mk+_f>3Dz^S5`(J&O5%k!pTT;FGZPQglD9?WAUZvW896ZLrFYaD5D=& zMKw4X{oQ`ptA#>eA<3Jz{u}`*vNx%#$UZ)q;*))S@@SuA8>nJwKAP^6$M|GFpUm*d z{ysUtCwZtUxx7VJ-Pxr|g9(hbEkvuAn=|@wxBFE6w!ImBA z3p;U?SM0>uK3V9IC!O>?H*rOK}yWPw~)`xdTu)4U#-eLdJ$pPs=pzsma@qUHkQZikW^xOyu!z zdrZ8VFelg7Z;n@Azqvjc_Q_(OTayL*#Tt#lHPqz8wMxQ*_CpY=z zc|N(tC%5|K`98VLC)<5;yHD=$$qRh)LZ95}lN~;Jkx%aO$%}n*w@+T;lRxmuJwCbD zColEMANu5FKKUb`yxb?R@X0HE@+zPFu}}WQC-?c}4L-?RL)Ak!`{>Vn^5;Hzn@`^E zlXv*!oj!S&PyUxr-tCk35IH?%yiV~xExN}S16sl8YPbX67 z84GdX1t>iLO!fVxpTAT}E`PqR$|GwkrBeqPHtLLOeSay@r;sJ&ImSJXb2Zf_Scl znLdP>c>2j3NfuM&*ptaJp&WejBtwQ$GZC4ILsm|Lr$4e(p=uJvUYED!Y%X8!kVNbOF^HI?z!OcNx$K1VDZ)E}ROR%y1zbfnFgaC1zMBIv-Yu^RrusOPA#B1Qmeu6 z2r!8odfu+{r}QP5L!38_{1?3Z!349YDaR6-l{vNl$f2Uy)PWQuDlMlDB3fxSHIrzG zc%}~iQk5HerdRIx>3+FkeB**!G&PH8U2b>|_}M3>4UL231yrSnwd-^?2|B9B8hlRA z`2gt1*~?4#bE)HwEGe7i1V%2!XK-Y}0;k8wISX(nrf5aE)9XYo$e$tp>^-u0L7~%! z=@kC#%b!Op9j2eY6VlDlt^MV<&;W-XN_`6oJBb+B*AmVYDrX3&KgNnQle54 zF-p`(qKXoAlBlLclO$>=k&r|!C0ZqMHYGMmVjU&6N}`Su+a*!I28o@LXrRQ!l4zvF z9!WG&;xb8`L%nvTB$~-?w@4yR9e0-`5>!u4K=oV;?UyD>Vm;-QOJV~hR!E|irjXT= zXd}^U0@%)xYbd9=B{+SPGh92$d4|($Hk@V)$#g`It(52?iSsEDlEgMj^p!;W8YI#s zv7HkAC9#7NnUc7G656*eBmr5Hvy&3plIWnsC`nvIi7}GcMTs0qTuh0HlGsg&DU!H^ znlnQZKcK`fC9#)t#738LjwF6aMxGH=7Qc+7t(L@(D6vKoms6rr5?4^7MiN(2qD~T5 zQKCr_Kc>EDmBde|o~@GDM{L&ylO}@wlhH-pO$3bh;Lo0FBAtE{bt%uO(;tn(xrAH} zG!*iIUr|*m?|@G}=97>6W$mzeI07Pl?(i%^(KltR!KKY7I{?V`Z zHJ^Na3}#Fv>`#P-LNs`J&6xhp{irAudIX;XDew0n2Hiv-l#){4-Ua~66{h0j-GiWU zaD`7U(07C`z!a5IMMEKKxhgfxJsxbKP&Pif)XdJM)Dgn;Ecee4&BqDThr9j2r|8)( z-4;qEndboHHM@^WZ$o^^}#~O0)Hu4Gr!VVBX!n=l6BeuAgp4(&bnQ)PS4RqDIt zm8>~$>a5U6Y5fSvn){{B8lki1NLDxlh*GvVs%=!PxpF0I-c%rLqZkP8;)%K&=a=ie zt-2UaFyREwjFKju^%I?Svt%vUrL*qSSu-VT;Y~X0B@kTMTe`AEkLkRB>AWdHDOdWY z&Z8)a%N-Svyv6^m^F|_%U1O7EEg1kr^}o*gLbA$ofT*UFQ&Uc+R=FALfc6d&O;;#X zgBeX_^-s=H;DDc4{H-4Uz~n5&&ylJx{}igk<&ZV?JxHSe+_?9)I)M{hxZ~Dp4UY{1@rA3BLuj(FK|XZ!L8S&CKdM6faFCy`K;D1ebHaI*POueJO z<2Y|o?@It6nJP&)K`C@-F*kfJI-W+4Guf4tXIyD9tHP)y*W9(bxU%3yQG)$lYPOx zJ0-o$rTtED@18BE);jKTS6f$=R_Wm0E4NHxZC1FX8C@#9l27RU^eV4CD*yY^XSg(& z=u-8qc4=c5+g83Ghj;@24pk!vQ8n-?+I+ed0J?2ObNC zY7_-i@DsN@i49#x_Ce>7S^Y9&(PtNOneyP?t;h%4_AP$?NXWcK$#ip);d?v7IpBU- z!M@k{rDh=eu*wc>f|})l^AHf|_VvO@h3bTPO`3}mrzpI~-h-QaQJFZn;DSEW3oz$w zDZI%jOw~mNU(eMc*Q>6jixOohah2dyjdFK#6~8vJ$X$vDN_Yc+n(nDhHNWA>C#AO- zHGd>Iz`PO>l;{tCfdRg|p<@&i?B^Gz>gEaFxuIuuQDPlRY*0826JHdy?h=(@ns`0n zyG4#=nC>m`rW8;r#SIJm+Y{y2ybV>*YDO*~Rrr~^kvURjy171lCE!_B8Bd=Zkm=c% z+Epb24A;36@I}c2c!<~?eqHCHJbFcF`Hc4I< z`Cb`kk@;+;t0e~`(JMj1wrOFZPQtG3R@g7P5%xPRES-dTix+98I#sm7Z&Fe7zcOQm zTO~Gi_gw=8PfupBl2}Gi{A=nwEL@wDlG`Qu4c#@wvM0%JRdSCck6GBvpk7k}r3vdv@Oc^Qt@-ps?Xa$Vc~d6E;9?gbjP}wSw&Bdk;kqPjb=nzy=7Q z;K9iL0+Qe0Y%HXHDH>;=N`RHu2H4jYiHVvAdYOVxMBaRz=NHKX zytXrZ8sN6h@I1hKJlLBYcy#lv`a6)xTa%~7hu=1RxQC2(ci%}c4rIYqJO(S7&$;jF z;wt%`PAZo^NZu6Od)Jl%gtDBVLIr0V303Y8)khc9Qx|nCo#uAcu|5~g)>{>qY0G8M z^=b{1+irl}wd5!=y+qQqS%;k8sbZZ%ln({p42{YuR|X0!1l4JF0Oo1G0g?s_zQw4H zJ0cXKn;x@BANP-1tNB8>`!4oO|3@10bU_;N4#5!+T~^W?tJ{#F<|#*d_kP_URIJMD z-A7KR#G|4jU+R$w=&5}lTo-ED}mKl;r+7sY)Q zQs$^M9ncC%^{J}Y6N7Ib1@fI0AH?1Tt!b@;qt3;Q)JCNh#^l^)JQCOmMLa~OKVdFA z$1@s|BV~BH`|g>l?K6jzql>1zu;y0Ua5AvBM5T&Jjlka0eByTJX;zh-uao-Qp(?xt znaZ>Aok-k>TzH+|RQO(Ky%WmH4rQH)ae`WN-Ib`#m%+V0iz~+{QP+j??d}_aS;ed2 zVbt(}szJ_Bd@)a(su1Gchvb1=A9-W zI#XA7rwN?}jC~dY_%x}H#Ao=E!0(mgHT)0Ixd$|}2PH>9rmawV3skczHShw|kB;xqvk_ZMQe=^q0{A@|2OBHQy3bho;?^N}PW$7vz^ zKL1|`fp-Te4p>6lJijBpfbBic3Fc#dKx;Aa^~J1=VMrr!LblJ5297XuEJo}=WAr?H zk`E<)Qh}&PTT5RblOUfW7-2g8TFW_ZF7CP)}SXE^oa(YZ_wpF zefk8y{ihG{>1o%vj(dzdGBqP5m^vi&7`NY1>4PxFvz?Tb(*R+b5;BD8cAyhXot82^ zr8onBZGECcU%e*r7yh^+B?adb^hI#*QyK1);RaJvQmBjzH05Ydz!Y%zm1NK23`!oY z#pA%vb&E5oMA~r38IR2L3>2L)7&l!fDj6tr`d|X^IJwqJ0U5*L4gI<1o~XGe$r)f& z)f2aR2e>Bc(Rh$f1_8{No1chH~WCm5m!6Hf$@O2kQC zLs{e~sSIVNprNDLejrZvtrW;aXyqqyKfyOC<&7QZo<5jO+ViBr{o<^%4Aj*U9P&TST&nFg_=3f>sW4CR?0-~)%j?$Qv&(o|Bka@oY>Oq`GphF z(TEmOkg;?S2`f#3A0RfM3~D@{aRUKSWs}kMc!Fx2L&LElRSnJtOeIT`A;(#k1i(v| z`v7#hrN5fiACT`}&S3>upG|!futC0EXQ?K)^D`RsOvxwi(*0IBM;F}Y6)e}}O&+vV zlcuclPO=J)R?-*9cfiTnuj$VObDcA*VF$X-k#Azt^!5A=i`6f0^|4cBj<%t#Y<(t?vy+tros$}_}pNl^9mveNvPU*jd?BxkBReApB@xpR~ zS1S6gR?n*|>hmk=>b~mxI{8LjnhbbmS++vR)gDx;N#A(O!cudIr$MPEecLS?B}$F) zo1#hIbjzNR+~<8RP5#S+mW_~xo#ZvJRFl4ay@g!2{eEfdqkfw;sXYgsw_cp*JkNTt+>l?jV9N6 zs;|~$wFi}I(r?Y`v!&-6{T|e$--BiIqyrXt9Z{-DzXv<%`M8X1zq+zh#X{PMu2ZHh zqz4_KS49~;zyRrLv=ISmbLek-B*U@oQ42_O>u+8CbD~)v$KNAs9`Cz{qB7(g)1M}H zdC)RV?iNVRh&pw-{Ok{G?pgg91mhkFG}H96aZ$}~C8gGx17=RswfjC)Y2CNJ`! zGEH9WK})svKk}eX=GT^8C3?d+n*47uY1eCmE~sZJ*D2SecNF6+)ubt_^V*Oir&0ao zJJmVI2~EikO*s*J&z#Yn){?u0?;ZL6uHLtKgHGs~ZUx>i0(&^PL9$<`-V_wJ(WI_f zG1{H~f>`cT`Tj2bY~C*Q(@ZaUT|)Zl)V~CUewx%Zcdg&G;tw}_ez8=OHz3NOtLskJ z1@HC>mTU5P4_c~8Qre_IM1^a_@0vQ?CDowJlS{^!w>rC!s)Ypy1nyi%Q3>W`(4 z|HwBj@S66Eo#|JjD7!K$rfWOZtF26vGXx4c@h$sxVwTTmi?_AHJg1fNEfBFw>9j09 zh&q;Pa;)UJ4*zuorE&yP{i##)eMX@=eQB8(*P0yfm0GPyEs(^Qd#97W_)a~c>(Me@ zXR#*7c;d@6X^LOmh4@a>S$;1iq)5JD98KPIl*;Pbvvt7|uVA?*H+axeO`5Vgd-fhF zaI06aRFmUG2`q&3g>9X^L0>Er6{>YzQ0Qoo3~3%Y^E;iyi3N{{oXiRs>!LI{#|Wubiqfx zg5{cg)q|F5(v;P?$MbReLsy-A!|gPAy4?9hk85(aK*|$!D(3B|I(hX6BDR+lqYeD~Lp^H4>%QX32 z!s!>W=(tiQ&3f)pPN0YjR-Imo1y8VVJVq%JJ%c`dPpELU@dbxam z*ErfLJTJ;OTu+mGGL#soqRApTDp0PcQ>z69qb8$CjJ|4$(v|+mtF&B`x+eI$CUrGx zk37$P%kI$tapa)*Xe^EYndkh=|RiVq}f_Y zUD`H))v!?e;;$lZ8P!s;`4haRE~T>CES2w7@*S0Ly@+g; zv{{yDJ=zwEe=U*kHS%rq#{^$5-y7w7OE>)5S8~MgbLIPE`A!%6h2`6>PapH$Df#!v z_knKsHU6~Z|3<#Mv)@XXIp8!RGj|}Pqa1RSIEselM>^b+7dO5 z4SC~EO@=$^6>m$HGG6~=xHE1X9!I6$b01ehR*oksYa8>%)lgeOSH`M9!}VAZ1*2uP zjf$L8Tv7xIs}Pq136r6&NUXV;ep*{`A<;kukk`@xv{KRd`KHFEM5Lk-KZDNoHMP-C zc7sN&Q6EjzD7HjxJ>?^C5ej1PyN0m}%^8CUDovy^7O!YF0nqq4@H!>AsjV`$wxwDn zpic#U0pDcC4_KSYwT+E+X1cDiq1sGW)ip+w3RE=G&*!(AJk9jG_9hTdG}k7JsgKn+ zHn*8P_#MZpSW+|Awk2ZG=H_S;8-7o{E=e}o-IP;VTalEGHMG>5`S|55Gg;5SUT-2* zEe#cBx}q)`kDEYMZL$VQ+)Zs2(WW?l5MLQQ(HyOat&LW!Q^|N8ULat~s)*GknH#^h zpJapTScA#FAr@WN9IG;+rZ)InV{=^hc07SM8K?x>7H?_tolK3M=9UJPT@hO!6(>=@ z9xpH)L<_5+ai9|AG&DhC3RUkxP&EI-JV?wSunV+T^o+GFNR6#+;3u0UEcY{N(NfZWK6QRkWyFw?#SML2&AUiWKeqdnS zz`&@1fs@t0j8NX%=YwgX6)nLPp?<;9hwq@`!Fhp^ZgAsarjOYc93Gn2BM`i3^9p3W z=>{g_-dhhhFe;V4LLZ>`+kq1^UfmIF3f%_2pKL~HaBd9*PI4dl;qB9Bwi9Eos$ToM zraAX^`i!j%UcTk<-NB8CsxO~wSw3@R@yt(F;=z$Xk09j-Ls!%1eEL{k!zFqpkO=g; zIW%~CFcCPx4fb6TylqRU-@Mb$`Rug|9$tCp9l`aXc^?P+&U^GMh)skhhA!PdeJ0dA zvbhRMw!49o-8<)pZr$Hf{p|kYmSCT8?a2IKGh`uque$=NkGSP~-2~G!fM4W>ZVR>? z4yJCqBKVKZZ<?e-E$PE5E<(L<^K7z0}ErkqdNmM$6clE8{a) z>aI!j+8^2xV;j+ZV!!LzVe;W@K<#{x-N9Pmk+K$uVCwK!9JmRHw7=<62Ol% zw!AWP(UHfs+P?K7F+~xc(t%c)%ggo*(K5deS_QMSlb}-2#uU`ZGM}%S%Ifr~IZml>ON| zE8F)5Yan$x1i8%nzo9t_f}oy$wkVNz%~31bl>M1P=s4 zGcsP8A1b&ES>JBjgS>4)a; zj8)+Wk=i0WNz%0IM2yAMiL^Ad#AB6tPK0LMhDP<;4F5eWn904@n;@SB$ZC{T+1RqS zPAV*D!5TkxvZ}5IZ<9erXNSVVu@5FDp05jFQai9)<&Y0l@L1@FJp-%3Ta7JZH~;sii#CHf_b~5Apw?h zTEbMO)XOqU+h#@Mu|>Spt6ZgIK|CI7PSiFwC{-))!VjqKEi8DOO|$~5E487vp{Wk* z4XSF2MNw5r!OBQk!Gh9~qB7F3E?!exg%{%Zj1`Ry6<|aQYvU38U}A*dGeSS94ECnR z4S3~BeQiagu_X~%-&ogDPllU~CCk*WxSNGunws$|nx$=v$|6f*QLIo6u{m%^ zYE-Fur3$pHi&m4rf~UBlsU;C^Y+UD1I8_meBT%WRiBv=@YGO`9td+W%9ISYeu2uU* zmG}%I4bj=tw9Np#V10RM&!<>KZH7LGB!i=foM6lQ;4}f=ZRKD1ws; z_8dfk4y(*v#iQ1L_s>LZ3Y-Z17Xe!V1#FR6eN&<>qLzIpLP3NISx6Ql$j0VKW$pS} zyoyPgX#q!r+_vI|c)}^1TOKKK)>hHD=^sq|7u z**4Nl?{#9gDQPmN9X(NSJj+c}b+8{qB31PXd%7{-ro=DVX+n23A+SwUMJj5@mXU>x zOEFf<;CqF&&4}0$;yRVlL`%K2Q#O#wSf;%F1OFNs@h=WA%7vR3*e(jz@38g5wo5V_dASjms$Fx={!_ z9k@6PDQ#Q8+ZN?$zH)gJnQHR~euE;13g1i9EiYAIHKVa4>{6y{VYnsiYEa9M3^gX*C=^gLd#rY7dNBfh~t zSplDKqy-rx+9@nr7Aag(ysT(Rq;zRXSy92#!s10T!!==%YK+vxn(HyK!Hcl);^kn8 zXfu{7=``*ROfqaXo(t7@jmFy=Dk50sysdh5Z5?}(*M1q^>it#NXTv+Ov7wDPmUB!S zNiPvIqYCAnO0CG+M!c9TQd>!ipx+!?S=E}P`bW&E`nWRMR##hHcMc!|RTi}f$T?{zbKWYLmx)gjHcS5{Lm#@0JMKiYidfx zB+^nz(`d9g5vw#hX7Z`JW8j#GjheY$8ZCUhgjJ%BcN$4*VZmr#>*c!<$Uokc`)}rXzx@f~X zgfL1GiM_BKHpD6HP@@1=FQj8@6};iKn>YrbtriOLSSmorBA!6cN3l=Eh7>wgU>)Ok zovMukEh|Y5+JuFQc8L(wypH@dfqjrtVj;$lsu*72zvL4ycdc%yj@DBYM@yv&;!4{J zF+(X!i2<;cNi;UZW+$5K$Q5LBqaq2M`3o0^ava9kGd3M!tM{^Eno}Wyc!bOr5;mw< zm#Sz*m_uVER*i{aeN2UDs<}Mjb#`v!^|DGIgq&;z*&i*at)O1>&t)XwRm+EZ%PZL{ zQi!b^?K#AGxQm+gW}nu6ayOo$ums8|#qk2abywMrmOlKiS8Y^{qT?T}v|7C!bv7Tz z)PqebFBy>tMYkJaYA8azfUuxdVggzqu(S78Rn@Z;E@+pU#Q_zHRK$5msEskk^qj(F z*l*U?$rc~;e*@-fLYF!f60Sfz-3T!EF&yV8uZR@$L5cWCWHF`*40j5l*w$p&2{}21 zatP&NIL63RQ?71$p?b$K+>rc1-eJ6iUlfc{UAexI)*N-{(A-KMpf|r{UhQ}V^`$k1 zxXgUz+2G-vLQjb_+_jPBZ@}sm z=ZQc?FFHf4hb6$U9hYqQd0sN zyB;s%w#>S_*0j#|L+KZY2+tp@QY&biP_ z*lN&z)=BWJh|MCj^9F|>kd$F6$AMxq)?w;Nyb2lvG@hX7j8DuaPsAW5%i`W!LM+=D zYp$T32RRV!3;2Z1q4PD=%R3zG$T4jFA)DN4E(k00kqGNlTwhrdTMtL_G%RnOvW{&r zi#iEomJW#PELV2SJjNq9%AuJS z!;#MvIDEl&huekOk!HaqP^lTmkpov#XQ`mwSA|{H!y~{RGq*b{HM`8%O)J@6=&&}Nbw7)dA_ezI3 zbn=KU1)Rx?pkthyw z*F%>0FkbYH`|UV1&>MF0k@{$}3QGJ_OxE3qQ=@cC0p4Q-2&hg)LX~y&;`1swBBlsS zwnTg&VfL&a2*O+Fpp@nsTFaL4JJ?k}>I0biT1-L+ZFHc*Jf5*4rHIL*)iK012|9Gf z2w`X7ZmVrTt%%pTZuZiNQ}l>k7sCS*JY|3%J7lz9W`8>BrlQ!#=R%^XH>(n%ach~d4}&>w8HY>#b80Vs+kbe3U=M7 zx(ws3w!&PI;fmCKaWgbg(V+Hdl0kRTX|9*KfE7xbD&em*y3~;#j6p-nX`<&4_@ub8 z0jH6WLsOaR*}~fD+C;Q&No($+mIRgn8rVD+@VJk`8_+fCK>*wy*uZEbOplvUFD`m6Q}?ZCp~ilop(3VC zgki0w5%GVlXc#(`WZ`-!V_L?W{CMh6YfWuKRU@mWlI&w}p{7Qh`%(mo4S$WA=IU_j zD(7$75S&3Xv~G+yEvpk}8Zb*@I4~u3m48zZQ-F(g;Z0{#OC1DDBUBu%9L75a=aPI2 zL1lDtu!`a|*UH&%WlMd18*MK*yyVX0tqVrOR27)14pzsos!n|ej?Q~!8IIRPk%-6Y zs>q6D35T6Mk75+HOW9Cc2`9qRKx>LRi||JsjLZYdcr|HAvji5ANCNkk#5cKzXw+kg zgzP|Y%OhHuOLsn^_@NyB!o43#O>*Q$6MWxr5s4A$@B?S)xVsZY53Bit{6P(DeIJSr z-wV~PTbYotj={rd)}^HYa&z;huprrh$&BF-1m!%y}xW6nZ)ySln zfsFN&rWZaN((|c&Fnh4xjLp7*Fm7@ZH|>6q2Y)C zaN-66@w^$P)4on`nygg}HjwC)npJ{D5L+?KJG>@PuOh7Chm~*?MDek@|H~tXr+RcK zEU)hBVrv@jVydR7S-MH`j^zC_5w2N>J~B8F(_mJi8$jf|xB;%LOPc}qGYTda z@(SeL-LZEJ*xf`T-jO>RU~X`|$2#0CC+&RRZhk%NF}Q>}yP z(>~kdC6_+()T+YXG{M^;!n8PMFwa-=a^g7?pa#tVi!h{7;|Asa?0MMGPa+w5N3V@m z#wSj3Ir#MkLA|WOXbR8zFnP0jU;tgnJ7-ztu_h;<2i0TuLqkDnqK*xe9$0&^d5;~mG;Jwf)XOIU4zI^uEXw*`C;Fuc15o-Yg6SB+G9FIAeGIcMUZA|zHS;J@ zEnw@EH8mzwIByIN|4t_bQi!Y~@pD?}j%$MNJJX#aZN)-wqh7|L?GnV7YUrRO-FJ-e za)liSKhc2}^Eo0|DjRWoo{w|co7619;{Y?X+7IdeqwbRvv<6j;8r8E3X3r;Ii>{5M z<+vZCP6XsJgeE*pDi+4X#`m}|fyZ!z3_Dg@cv#1@?TSmmlrJ09pRESV^Iqsar zXslAJ*hWSdb&l>)dJaxRDbkT>SFK-|Z0eh^7T01Kz&00KM(nsKYV;3Wz0)K(A02jz z)e5kUt6dAbdY-AC?0|lyZ4=g+(Is1`yfuu&S_((?7O4c!hO{)P;wYtO^a$AW78FyB zdfv!roD4W^9_3FI2+hVt1}`^lsrSGL!qr2#%Dusc;|KH30-8)W)tlOI6E%&9Z%!??jMO5&h>^4O}<;@RD1^V91*Fsx3+ z!#~NJW;m7fEssd}5{0&e#$$Xkid9IR2*jBo&RcTKKYaHtPB(z@*aSAvaCZbMv>&44 z)TPRfs&{zHvrIi}h8FRyBpy9>I7?eY#9%l+iF2e%URES0b`q;1XoG)Hm%;x0Ua`atgME-0Q&U4vs{j0#72G){i7wqqWQZ@_Vz+*0LrRR&=x?GY@`si5s2W*ppq zR+f)7W0=COY7jbeXV0FNHEQWvocpz?0WdbVg;TkkbEk~UnK&+Yw89Y#75D6kIN7Nl^y`_o_M;Nl;|^>tgE zdcX~Q<|#KPg>08Eycbe|!qoJ@wp2X8?cim01juiI`nH=xwws%pANW_F)GV}EnQ%_Z zvefXx)Y6ry;rXfg&M#2zN-58;82P@oUh4*{1F5&Tb5rkf3sWD!{{wDu>a}j*=B~iy zUD~BMB{INCQm(wv zF$tr;jtv-c^k4B4Q;_~lsf#N}f2w3%_^~UNQz|%*JJ2KX-$e_qJPLmZf=jm)zs|}y z`9575p9|VW%{r~W=?@WEPbJ3TaSALd__c!Tp9DWgaQz40Jg$Ik#(&ahkEPG0f{(&C zT_Vo86*SeGFHP1zN`0^3`j2Au&x}5+`9*R4o4bD&{4V)>L>`~O$S+C$9{E88_ETU% zbS>FIUs|7jjQ4PMTKW$We5-|1`5^rTk9B1Wf41OSejei?=YZha{`6u6vRl63`BG0A zaMEA@YM6cnQB?TTEjiVKX9=$BZ53SCr}2vf7k1Atu47ztJD$G8=X;MXrM`pey|l?7 z^QUye2nafTyTRoLh^*Y8lV%|*8FcioT_k4*@fP~7uAsLHCg%p7fyscRg1mxs&I&sC zy+rG}19rpjR9dLx+#|TQyJmPmaJ$8i2tGzL%J<`fpKjq#3%^B4-rUCi>tKb(~_`8gEp2t2A{%bA%!-8LD;a>`Vy@h`(_{|pHgV%wc&ixkN zhjIDM03$D*@y`A^P~^O9@De#x@K-JT1i}Al;iClq#=^%5K7iZdXHFD+w1rO-e1?VR z3tnpBa|Exo@Djn#weTf^@3Qa}g429pUS~1h%lj!DomVORc)?`Sb++)YNkZ{9Rl&Df z_a?uj&Th)D2EQc-NJl*L8#csvG>RZt$Z;z+-QY#t;AeG%pWh9BMK}08-QWkh!Qbo#|DYQ@gr%s<_I868c7s=SgSU5sU(*f# zP&fE%-QaI_gTLJkegt?wiW_CazeXmf-UwB@vcr&W@G;%s{-2Q~J#T}P7u>j{za^tn zA9Y|QM>qP$T+(0f;MCAO+2PY!b%z&6KyoinJw(rEAcBbCCZpow(=+eJW2Yx&<%GunE6t?yI%=wVSb%Qa#I3&&fwic`zU|Z> zUU^4;`k8&>Zuhv{iIXPeb^7}#hI7@Q6X-MFaV4{J9DL-`M;?7lq>oATF_}J2rH?7} zF_k_h&_}K+!ew%~P_DwcY%Ukh<4Qh8h|k4xoosXQ))d(WsV zPgTohCvaJ`j1=Lr6S(XIE<1tCPT;Z=xaK zl=Q#?Kj~eT^n9x>_wiJj`yL?sw+x)&(KQ%S+Z%G{Vh8Y9bG?&T@S}?XobW`y95r!IS?-f4ybZ zYTc8e=PC4`)>)jqZb(=Ae_w`sB*l1A84bcO)bO8ecYZK|{w_)`z0XHj=Fo2fe|2mi2n@y*ZemUh>Q3s?=m?rdWb+=8rLTvFDRJt9MD?M=LVi@;3H-K zLvr#AT<~T z;3os4-@DcLbq0UL!0#~dH3t5u;Pf@c!2e|MM-BYH4ScPE55qo%F4DgO|Fu4+8+fIG zuNIud(OItM-)Z1Pl03RDHRQyQ*8IOT@G1j;#gH@2z~49c&357a=zLLq)dqjMC_rB| z27bJO*Bba#12_5S8o0^7*1%2vCIdJ5?+~2qMlY_?c6ip{H^xhzuDgR z41Ut-VwpGoZSXf5a=x_q^|^Qu`wP14@pXdWqz}o@!hgCZ2~L=)f7sxki9D@;!r(Xc zzreto4F2m4IrIZrTFx&Ge$$^nH26(DzqD{YuYPObG!(S_p4cDJMRuTjA{rkcILU4{ z@GQZ#ePny)oNVx${90R|>z~>tH^9CL^@Xrmr*ub;o)*$IK&%oyy_y@LGfaJpc!$8ED}$4LZkJxVGC=L;e~=e!jt9YT(gs_-hRQ#RmUg12^q+mxX7c3|;qG z_)rBqPj!PoZ{gYwe-WJOya4~T-QKqNvqb(^7Ea~pqPHH>rTaz8Nf(^>F2sM054QNV zoRJ3qPJ@4p#joW|G4Le@|7-&%*_!{NZt$xNoZ?K)e}jRO9PMvEw{UIGM+GO|4nxjs z7QgnlV`O7R{A&#UOu@;XWd?qd!Edf3;|%_Cga7ny_!k&>+~6-W7Xy8i?e77NImw{hl;1?VC&kZ@t4EzZLUvA)IyYc5T12^q=K4}a7HW9c&>I-)`)!5L_59;R~HUG!LpJniqoFF*>u2JgClcS$!q_aM{ zv>f%EkRR`Be1ymeD|S!LwbaSDR;Vw=j{^O%q}LcY=`%s()EGEH`nf+^9|4a%zPCfPs_h`I08x=<0+2Co!cy^f)7Y4F30*Oj%x-pYWL> z#XmrOd3c7LE76{aE^3#k!s*fcsp>sNX!^=AaFYMl@d}t>;rgYW#TI_uu?o=k(E4W* zforw;^7L#G#VaiQno$a9wD3!XpZ1J&Y5676plu5F@FkfFxX{AK&}510QuXEWpEXbc z`z`!GV)*+lJa32s9<%U*p$d4x!s$6Ax?WdbUcGnHB!uf7_2uCMMb5u1e2eJ$jfJ-k zQb2F&a9r9xH;6;&=ixMdz4*xq7XQ7{uJIQBfYhs>lhblek+`|o;{SoPYng?gCi78+ zg`X<^)@0%PdaL%FXW_FH?9g+zbZLFkPgLnEEWGbXh3oq!nm=-a!vD+SKU@6jQ4814 z$Nk2_FBiXh&BAw!-QKbA-yWyxRnKSo`p-&N_z{c$72)qIex&vPv*3d*{2zj!XyMDn zPxQQ~5^H=D%LXUBs$)ri`O?7Ji)g!v+h_7k{|V z!u5Tchb?@twD)NXzg{N7KUnyU65o7e;d#SUyS}pUt7KgClz!Ij)$grIxA1#K{tyel zM&|R$7TzxNd4Yv*&sO@BSUAnmbS<~=fx{KP*21SrKQ>zUlQJ&WTX^mXO3p3|*Ka?) z+QRRVc|iaDgtkv#Y1c0-{=HJ~uPl6k_~&yL{zvhXcP!i$IfpI$zr;Vku<&2X_zFrK zq4nG+c22YKhh-iZV&RX8p8BP@TF#ZSurIXur)4R7uC(wHiRUUU{BoK9=}kv;Y5C8J zJvUmo)_;eEN90^)uZ16x{=M45d&<0XtA)QK?YhsxT}eM_;abk`EnLg_i-qryb?SW! z|E=`EB;l_}w!9ylml&lY~B%qIse{I@c$Keh0roa)!iYCJ>wCC8G}Q|vjz!e1Pr>eKJ0)pD{&E4Cr2!No%ms%%%hY&2LInt>Nuxac)GM}o`ny|QU#V-_{S1Q zt+nu9$^6`4;XfDsH(L08GM`*v;j6^oF17GKi~n3>;VZ@dKeO=3GLG)E@T{(~weI;($V&U|6adcf|;XPy>x!l6_`<{Po;crU3{knyR zWW2v);X}p#|F&?v!=A5iEc{*>kNsr*)OK4f_%I7!F6-A=3x8DlajJ#CB=difg}Wku zv4x)_^I?sJ|5f7NgoV!&e*OG|*8db)moKsS)1`m+S@_X1Kiq2Jmx-P4v+#{#XZ`$x zuJ=iqC;x2m9})h87JjwF$@;#Bma|jV)1$=iH2%88U4t!rlJsk~g|8Ps9B<+7Ny;Cl zS$L7Ox5&cl#cxY3{1frdGc3GL>|ABxZ%V!ASoo7!N}o*@K2hqu(88YnyxJi`ktE zEWBLg@3nCHdwaU}S@>ER?>Ad`huH0I3m+_Ye#F8rk^Xwd!u9jwf3Wb!B~JK@h2J6b z%pnV(C3Zey;qOVi`iQ=|f74`s9$?`kW!=xR@ZZaLKgGg-Ed4my!q1cVzreze7XK@; z@S!q(ms|LLvBO#mA0g{$y@h`v&OijuAkSr z)53K;@Q{W7UG#j)!fzFSd(pz57Q4M+;VZ;$?^^hqVxNCocpvGnuPwZXjH9DOFYPC< zXYsIb`dRqbVxQwIe4NaCqbz)`_|*gpSHJ(_IHy_o09hA`ExcORwQ>u8Rpdu3{C;WY z*%q$Sb>*wTlS-7%}<6LgxKNme8w(ugc|2r1mD)G$67QS5i{XZ7| zfmGZ};z6yyevbJV3oj%FTth80#h4+(r z_&y6iOYHNQg?}z`p11HrEEkD&tGv$I$kB|TKHUe6NhY>P=rifiNzFy=EwD5s)Uu3w2 ztKaRy8MTF13;(GWzD&mZEDPTw@znwgKTG1D6&AiDOWC2(!v8Jf@mvefmhp3;h5tnC z|3eGEM&{-H7CuSr_Hzr@`=9$QJSOAx2@C&===nPfe^|!X8y5bqq`$Io-QHf}U%DS( z7C-4{;ca67<1IWa{(rKCuaWUP`Tr~J-s5a4*EoPLm&wSuG2;?OW=4oageZNeL@9&ZQX+SWIm&6&gvK?wOuC$iaXT`Fg|?f4}5F7%UrxbhH*EOTtA1ikUSsfozKa)V&3_Yyc)()0eJ}e zTQQ7Rt>@#o-Y83c0M}PF$fMBik>rigj`8GrybqDTf&TU=`I{I3y~sNUY`YI6Uxsm) z>Eolw>)|?NqL05!J_YTyjeHo!R}Oh2_)cZ!Kh`b%@A%T1* z`e8@%b!f+@$cJG3CX+Wu{~1a?0R46}c{yDFOeWWH^alACXy5tdJyHG@g`dKV{F)z5pk?Z#{JwUz{^Fv2+{R;eEa`Fj?Uq_x6Ve9Ab2)=Fe2}Xk6DlL;f1(vC-sH zF<(t051>EKAU}$6J(qkj&KDn%XW+Q<$WLM19U*Uv>$*zVzt;0z=%3BW>jrE^wy;7Y`nk9l$t$6L-X(90`q@A}5BuFi9*c2NK>iz!zcjAj^>}xppG1(4Lw~-D zd<@2szHdeIY)1Zm6hAz~ZZMv_;!W1)lINlP>&efe-|it#M7x|J--hy+!FbYgqB^}u z^3ACKmgLuP9_&C~9qZl5^DwUU?-Iq#VU{#M`hS7aDPBMKI2Nw)`h8rJDgI}Si`OY$ zzYlN$#oPbe;dv`4UcZNJJ;j&6b^hm0d5~kXtSIlpMdklWhcLc zCP=VZ^z-Z5UJDT)sB0gW`jM`dZCAZ0xW>1{{M^Kem;84kzB$F~^>8~UUXE9n$0wwArT9TN*+k1I9;aV#8^uSW zo_9I%7}CK+2PwV|2GTJnzPO3h@45ezd?{X^ERKed_KG$?`Q}HKijHeriC4plw7cZr zfINC#AYRJ+;wU~_Ul)bzek;g^W_i?c>5@m91=-WU#eLD?w{ef zlye65JH>H{*Z+U=rsHlsuXJ4Uyn{Sj;M&hupdoiqynatbKEbrxxPM@K%Rp0-4l*Wc|Njfyk3q= z`4^*qrjdtWKG(lTN%sY(F*Vu8XnkACZEQyZG_}Uv( z^Bu^JOZm_$7R3zf0_0YiG$=4%(5BWFnOXT{wh4OdZc)b5ce0}l~xNeUp*Uv2^lHZB=O!7|f@#H<> z^T-FoSCdbKe-6Ld9ENn^YxZ!wo#dBr{jiVn1fSfPZB9|Vo<}Z|>-q7fSi2+HubfBf z;=EJFaVd|UAFDbp@pBO$4%hip{;!xUP08!PJColHA3)v=K7m}{Z!n*{2jbU~%l{#h zWjA>y{5QDPzrHW$BE=`#G+tOkdq?B-x~{6@Qa`Qaq-2(G$E7~?y6z6gCH{HDM>{U@ zdi@qpuGepE$d8pX8=0jWdCYCr`;lKmJq#z;>$Gu>OF4I-oG&>p<;)A%{Bz*iA3ni# z)LJKA^8A53TgdN_iw?7VN!|{gOZoNvR2LnW)VO^1O5Pnz=V^Jq!F5^yuKj-w@<)+x zhu=+p5*|nS&meyv#}OJV$RNk1YNpuYd6OMS)dU||?6|})K>T)c{XVI~;`RMwr5fAqv>*Np@nMcj zypH$V9hdykrS0~y7QBVN0z4@mo9P` z@#D!)z~3X+_o*%?zXRu&4dnO3cawL77m)Xc7jF_Q?)7YzL_u(;c?Qb>lcZ9|i zZ?k${dy3cR(On#udj1{t{G{X3E;`SrI4<#BqyT0a=(yV-G8~uqHHaSx*LJKJ%;I^k zI`NXH8YarOC_Vv`&np7<+x^GzweWO2LFisIQ$d1*2DAI?;*#foa<$$ zX8GB1Dd$KWSFyO@!@+SUw9u}4wH=rEsfe#nULN~xMy~(Iz8$&#-}`Rl388k!DdgiY zFw)3tV87GIW8e$PpMUhpV-&CB?u6sgz9D7paTPdT-;iEs z7CJ8R%@Kdqaf#P)SLPm@Puu+<=EJ&mjR}O_WTo z*JDG-Ti-=TPZ z@v!5Pzb*Q6qT>>ui})^ZJ>K1@=w$LA;6usv`>G~7E?ptp{K&G{ap{NpeIRS#+TZ@f zd0`X9>%8$T`5}zo)8wb&f09>5`K#U=EY|hwjk@p%xR&Q|c^el^@jAafMBWVZRYxaJ zv`LX*(|A1{zth-v$e%=c^mB+K9G64tgFKTQ57sC4JKf1I`+WxS^PG6eGY-DYamn)n z@@#e7jsMDViU0H#o9LM1GOqRSt>+wIpnJ`nJp%-gnpGvuJK3US`T`@D|F(epXmFA zirsJPP0AzwTm`#c%W-MynY`39ml0V==Vr};JEY$jo(iBm!mviQT&6I%|>R)cU<~^mY`WK zIWGAtR|>LM5`P!ff;s2zsESL?Bn6&v+uC^Yx{U4d2yV7qkX&~`F!bI zW@+N%&B!}pe6{rPHso*P`Bw)Y?@V3=aK|r z`TP+d??%2EuWR-2@nrIAf3wHi&&P+5e~)=)n2(PnZ;$ei@$m`duhq2Wne5}Qk>}!h z?(07OHhCoa`FlRTh&&JHon=10lKk-!w)|^+d^7oyx;8%B$8*Sk(C4{6zL&fW#>+t; z&nNGT_@8|I6nSQKTmG{?UPwL+^T`z-FPUKT>HH9a_6qg!3goM+*zGI(IJ$4}dygYc z=mK2dltVv~>pB^tvF1k>{Tz(A6uq{fSw6%#)_AL)cPp;5G=2#l(Elf+z8-!K&&$Q7 z>x9Bj;rXKG?*rHGNz*)fJ*?kvrtw*bM|EF6Ua*JDm+Q}q)yLpGCVAw#SC;_ph`HW@ zJQ3?-$n`~_mE>92-xYFw{jItb#4NgBeLcJtxxQ}DlU!fVnMg-{iy1t$Z_;3WFs5%t=JiNfX{_O?$;12i9+=i|sM%rgeo}IBdg`+` zJZw_ku%48jl-57hl*?|RYj*#^B!dU0rRu|`)Lu;Ap+knGrkSHk8=9FK)4Efa1{s-2 zeFq_J>VV$;(vyay+V=Z@e+NtgX+rJKnlAx&^nI!7+P`%@+}x3_mY{&!-J9*5Sj-y| zC;QQHi0RFfxk4P%ySZnV3fPYKr`v0syf!Ds+Xt|H7XE*=#s~BcZX23g+5g?-y8U?c zOMO^kWzpLN+~@7}dvz*mploCoEx+<3#^gTj#>++p{jcNiiS7CL^Ra!7dE8wB?uxnJ z&HNPAeqNpp9EXBR`$^fg{MvqljY&vF^W!c{ah>m1e$6w=Y*f_t8?Zg5vFoXIU2msh z`|AO?vl-jhOt|q89L{x|WbPGp{Nwi6kc0vDR*qjzL0WD-{R)0%FkaO5!+O~b4p7B%>>?9ZRQa>-vyo@9Un#$w`ndd?jB!rcq|Gq-{onJoUHfb7 zTJu0r`(KHF%od9cW&iTjmG{5HSW){QiTx+ggS6@$_St?zx_Q7XPw5Wr>REm$(&IFDgG-gs_O^U905@8Gy}e+(sO=-9Va+1*o4e?CdMoF5 zz3;{)Vtd!*KF8i-K#b=f-M)|>(Bs#aP&>7r+js{$xn%_F8{M?OSrUSt`HH x--GdbQ%!SUh7@lvPs@1jGvv*dj%k*LxSq6YMI66*ps4MuH@5{3NBRA>{|}k@!>9lN diff --git a/softrock_tune_vfo.py b/softrock_tune_vfo.py new file mode 100755 index 0000000..ca78d93 --- /dev/null +++ b/softrock_tune_vfo.py @@ -0,0 +1,19 @@ +# This is a replacement hardware file for the Softrock and similar radios. + +# Normally Quisk will change the VFO (center frequency) by large amounts, and perform +# fine tuning within the returned bandwidth. This hardware file does all tuning with the VFO. +# This creates a constant offset between the VFO and the tuning frequency. Specify this file +# as your hardware file on the Config/radio/Hardware screen. + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + +import softrock +from softrock.hardware_usb import Hardware as BaseHardware + +class Hardware(BaseHardware): + def ChangeFrequency(self, tx_freq, vfo_freq, source='', band='', event=None): + vfo_freq = tx_freq - 10000 + tx, vfo = BaseHardware.ChangeFrequency(self, tx_freq, vfo_freq, source, band, event) + return tx, vfo