From 1252bcbdbf72d7f09240c0b872330adad9d0f39a Mon Sep 17 00:00:00 2001 From: Ayzen Date: Mon, 9 Feb 2026 10:29:52 +0300 Subject: [PATCH] added AD9833 and DS1809 support --- __pycache__/device_commands.cpython-312.pyc | Bin 21431 -> 25112 bytes __pycache__/device_conversion.cpython-312.pyc | Bin 3828 -> 3828 bytes .../device_interaction.cpython-312.pyc | Bin 8500 -> 10164 bytes __pycache__/gui.cpython-312.pyc | Bin 19159 -> 21784 bytes _device_main.py | 31 +++- device_commands.py | 139 ++++++++++++++++-- device_conversion.py | 2 +- device_interaction.py | 36 ++++- gui.py | 34 ++++- 9 files changed, 218 insertions(+), 24 deletions(-) diff --git a/__pycache__/device_commands.cpython-312.pyc b/__pycache__/device_commands.cpython-312.pyc index 1ebe2d23d174d313fa3dda28916306de9ae0f43e..cb7767e928627f78b2b5a19c6b944f6a97c5a911 100644 GIT binary patch delta 7280 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 diff --git a/__pycache__/device_conversion.cpython-312.pyc b/__pycache__/device_conversion.cpython-312.pyc index baa8aa647fd0921af07944c07adb7ec294b25fc9..c00a69fa83d4e88e4e058f77f1b8cf29e6d5d516 100644 GIT binary patch delta 25 fcmew&`$d-fG%qg~0}!0w+%l2-6rv4Y)@J=l*ukiFPD!gWhn0?Jqh`Ys?% zeSH1CjJ))OH>kAOIPMN-I>|B9ol`O#MfNIs+BYJbo-uyZ!B*n9L2u!QFM?o7gTDs2 z-=DWhrbK7_^+=+;ssT5sUC2Q%s?ADCHb^|B$5Z`%y_qad(h1eHH8pOck-$AGzj3bP zHJQ!_dV+0Goor@U4=`jvn4S#Qxeu@*YbL!N)TLru=bW7nb)jpnug=1JumT}F+rNAn zS^Gyh9-~1-o0e4vkja~ZX@l(xPyk}kPCvM6U;=XI{SMQS-;?o|pKu(u(G$*Uk7E?- zu)qR*W3_K_Jis(N9hWNF7B$3O;C`#{hpvgylU5;sCXjuQN@6O}cSb)oK%c19wI1SS zT4jPHuqP)#;|0U2*YqWNG0@3 zej^hn89j~{i;}~j--Tu{vxP^YBC@knQYc(szC}PU3R5e;pvW0ehyu`fl4Sifz~BMlaQXMT z`$=y)qvJUIHDyLiOyrYbjGL(LCd-?`*}@pbmBQ7+5XGIs4J3I|cz`5t zC8H+a##!_E7`Z1G@Q4VQF*7hsXQ<&QimKsi5GY}oEXXP|xr)DqXARS8R*<<247J>w zc?66Zff^hH6@g@uU?Ve64bS9fg1U@6lSPCyfux;KAS3JK2|{K}noN`bh|5p@E)+dk zS3+=dvT*-ocL^Ov-pTSJF?=RK?%z>44Z$K;jpNO>TZlX-=wLQ3a682*kxclf%@l*%TRtK6x-sUZ^e%0KP?AAOHXW diff --git a/__pycache__/gui.cpython-312.pyc b/__pycache__/gui.cpython-312.pyc index 85b68723c87e492d9460722a217482e2a0c3ff84..5b6048b62bade7180d03efc3a988afbeb0649650 100644 GIT binary patch delta 3307 zcmZ`*TTmO<8P-`LVNif@6)OW0<`M}bF!zhN2}wAZ;20#Zvo;|z2NbZtu$C}jFg7?e zZBsYo#BFKa(ln$_14*6A%{b$ZlXmiunNB-PqnT31lebQ%51rXeJd=mM^!&Rk0dk`m zef$64_utOh)gJx*7W&D1DEZGxNr@`@DOp+`6;7-sXES+d)%?3ft^}8GNAXdv6qj;V zY~{*u8CQTw;{fa|$N+`!pzBiDp& z-e%n7ZNbf4D{kT1aO({fXUA<6+p(RZV-{K3{|!T&4E~g&a9em7szLwM<_B}A>+ZF8 zn}oZF0wR|wD_X-`l>2RFc%W<2zR%yZ!ZZC>G!V5?rflv z$t;lV6-#3 z?JOhd$n0TOkz{_9c`IU$W%*?DUWD1uD~yqpWJ~61_6mqS>D7^#F*aHt&kzmYFhtoi zhokJ5dnV42*nNfaa-(q@duB;qL8OyEZy{nHGDgh}*~~ZHj);#;QE?_eYGxc+js$$P zXPzmD1Ry`LoBB{c88osfr?*_2uzBPsAk@8-M$)lT% zc&RQY>1Y3s9-sw}lC~qY1?O=5CL?#eJCEK}DHpg>387HER5= zT1p&fk)8Bu=+m0V;4$*sB5UgRBJFtwUzkAHPbv&7X)Df19S^(~(J(W@;0dx`Y)QQs z!%j-k7SX&!~-fp8Vw*J-P{7 zkg$NS;(5Hdb&Vi1i(ZGDUGPR^?s*N4$Jgf(y%|fJTA5wY&TGeRL2mjoUW{xCQq61K zD$9+~W%Fv>;;ydOJ3i^=z2o-r$+;x!KF_+FXvgqw>)?l{=AN?3FFJ6dO81ceLR10A zx|=NLc=%E8gwH=b_q381A*^$WR{1s8=dfB*nO*I1-aA`axf|E+4-Q)xVz%ZqMPr-} zE3NMic=>>1cE~?$wW#?#?)xR@0f|gh zI(5=&;kJ!WH{o2}iQ7yUTg*rQFX{bvO z<0b#`Q{-%&D?v<>y)^Q$VLCxfm%VK2wWf$_#QGSKmAO3Pt*7xu*()UP)_3HKMY30- zGUTl1uH|mEhFP1C-6S5B`7+w0Rqk3YGu3j}8rf@vu8E>e_Sz7%O;y_3k<4}=Xsi>D zEB&P+g*r!z+3c0#fa0H*lJ#r)aDHvL<&@CVD>S>q ztVhW16Ni+T5vk0lw#H=9r%?U~r4z>$iburO)S?qFDgF#1SHPcD{Huz-sQ6BX{1ICnbMToKpPhy&Bcwrjwsf3AUav z+xsXdZ@p`+>s{ua^M2MRhK~(`(Y`CE5(^6q%Cd|&#hkpGa13j-G(WNAvkdpR4s$Gh55)_iu zvgCTKQh7A}ns4ATp!rI^Q1V4hKqJyulcq~cFGJd(R*IYkkG-rFpO-5MahZ=j>d@OQ zjaoELzI4{0F_PgjX&2~^lwTx`uESb5O!;MU)>WqYjGD!vo38ILdgpEueGL!0N5?1q z!^itNc|C-MNa?f2#UPk)((iQV*mgE delta 1723 zcmbW1Sxg&O6ox%xJk*$_U;{QgAwn^>Nx}{R5}U=)QZ|#43<1Y*%~l7)FswBYXHT0h z^n@%`qNGyQs==jdtttmj@!DRPs|>wJ)hEr3zA|K2*JDydk8%bfo$G&v(x~ zbMKYy8~2zW*O!uw>MZHT#t%z!OzKR$SPDm zLtZ4kB-VEfru6ENK8d=Q9H*M!q5mmV=8-pQWI=T5H?`AGIsjK~C^WU_G)%v!aA zCH+1Xe4L?XW??l=%?yCMD3uA0$^Uyy9z*)!&mse3hiro>c|P1#V9Ch|hB&~Hse=uJ zCV5a?4380Zm?cBtHR_YeF6)%+@Gd(d+0k8gOtRy<>`Rh$?Xst+O@&Qktzv?>eUp%E z((9&t@^v=2rjfWE=i$NqD+Mx5rikd90k=uVEaTA^oDT26qad+l*2B=lo?GXFc8T+F z<7aWMdY*{k&Wy~%*<|_!|8J(%nC``RlTCC8V#C6a%W2ZH0nREo7D`G2F&5X1Q!f{4 zXs8Fd zl!maZ3+7R1EL&nM{;$e5-li=0;z%B()K|j8Iy3xqgk!fkxLZFP{5T8)hb8m5xd}~@r5Qe|)x!BE?f;tR zwbWsoZ!PAWZH_MFPWsLCt^A6u`p(U+?#(*emab=0dlXkz+faj*-UewxUt>K!r361h zPaVyY{G(ASDQ~K$TgZpoO?h;Qsqnz+)jW~ObT-8k2iwW$dK8;6soTS>-`i5dF=Oyq zdwI(+o=yv*l|mmIP!hp0XBVCGVn9AE3c>=8y-X2EwRW33TkN)0YrEZitjT6?=xFQc z7M8JK1*$uW758c6{H~6RZ2F-+Qv>zx}4UdtwK7My$5mKxhqo`Pa|d!Uc?zh zK0-vCL!3ukLR>&xL|jI^f_N42I^qiAHN+c;Hxa9dJ%~GqyNGuXZ^?!z0pl9t8sa+Q z2I3~-ZNx3aZ3OPe)@CnKYr4j{FPWtL~2g diff --git a/_device_main.py b/_device_main.py index 814cc0b..9d56c0c 100644 --- a/_device_main.py +++ b/_device_main.py @@ -107,6 +107,10 @@ def set_initial_params(): params['RampTriangle'] = True params['RampSramMode'] = False params['RampSramSamples'] = '' + params['RampSramAmp'] = '' + params['Ad9833Freq'] = '' + params['Ad9833Mclk'] = '25' + params['Ad9833Triangle'] = True return params def update_data_lists(): @@ -473,10 +477,30 @@ if __name__ == "__main__": triangle = values.get('-RampTriangle-', True) sram_mode = values.get('-RampSramMode-', False) sram_samples = parse_optional_int(values.get('-RampSramSamples-')) + sram_amp_val = parse_optional_float(values.get('-RampSramAmp-')) + sram_amplitude = None + if sram_amp_val is not None: + if sram_amp_val <= 1.0: + sram_amplitude = int(round(sram_amp_val * 8191.0)) + elif sram_amp_val <= 100.0: + sram_amplitude = int(round((sram_amp_val / 100.0) * 8191.0)) + else: + sram_amplitude = int(round(sram_amp_val)) dev.start_ramp_max(prt, freq_hz=freq_hz, duty=duty, saw_step=saw_step, pat_period=pat_period, pat_period_base=pat_period_base, dac_clk_hz=dac_clk_hz, triangle=triangle, - sram_mode=sram_mode, sram_samples=sram_samples) + sram_mode=sram_mode, sram_samples=sram_samples, + sram_amplitude=sram_amplitude) + elif event == '-StartRamp9833-': + freq_hz = parse_optional_float(values.get('-AD9833Freq-')) + mclk_mhz = parse_optional_float(values.get('-AD9833Mclk-')) + mclk_hz = mclk_mhz * 1e6 if mclk_mhz is not None else None + triangle = values.get('-AD9833Triangle-', True) + dev.start_ad9833_ramp(prt, freq_hz=freq_hz, mclk_hz=mclk_hz, triangle=triangle, enable=True) + elif event == '-DS1809UC-': + dev.send_ds1809_pulse(prt, uc=True, dc=False) + elif event == '-DS1809DC-': + dev.send_ds1809_pulse(prt, uc=False, dc=True) elif event == '-StopCycle-': window['-StopCycle-'].update(disabled = True) current_and_temperature_settings_available = True @@ -488,8 +512,8 @@ if __name__ == "__main__": window['-TOUT_1-'].update(gui.READ_TEMPERATURE_TEXT+' 1: '+shorten(data['Temp_1'])+' C') window['-TOUT_2-'].update(gui.READ_TEMPERATURE_TEXT+' 2: '+shorten(data['Temp_2'])+' C') - window['-IOUT_1-'].update(gui.READ_CURRENT_TEXT+' 1: '+shorten(data['I1'])+' мА') - window['-IOUT_2-'].update(gui.READ_CURRENT_TEXT+' 2: '+shorten(data['I2'])+' мА') + window['-IOUT_1-'].update(gui.READ_CURRENT_TEXT+' 1: '+shorten(data['I1'])+' мА (raw '+str(data.get('I1_raw', ''))+')') + window['-IOUT_2-'].update(gui.READ_CURRENT_TEXT+' 2: '+shorten(data['I2'])+' мА (raw '+str(data.get('I2_raw', ''))+')') window['-DateTime-'].update(data['datetime'].strftime('%d-%m-%Y %H:%M:%S:%f')[:-3]) window['-TTerm1-'].update('T терм 1: '+shorten(data['Temp_Ext_1'])+' C') window['-TTerm2-'].update('T терм 2: '+shorten(data['Temp_Ext_2'])+' C') @@ -519,4 +543,3 @@ if __name__ == "__main__": window.close() dev.close_connection(prt) - diff --git a/device_commands.py b/device_commands.py index f17eba5..7611d3e 100644 --- a/device_commands.py +++ b/device_commands.py @@ -10,15 +10,27 @@ GET_DATA_TOTAL_LENGTH = 30 # Total number of bytes when getting DATA SEND_PARAMS_TOTAL_LENGTH = 30 # Total number of bytes when sending parameters TASK_ENABLE_COMMAND_LENGTH = 32 # Total number of bytes when sending TASK_ENABLE command -AD9833_CMD_TOTAL_LENGTH = 10 # Total bytes when sending AD9102 saw command -AD9833_CMD_HEADER = "8888" +AD9102_CMD_TOTAL_LENGTH = 10 # Total bytes when sending AD9102 saw command +AD9102_CMD_HEADER = "8888" +AD9833_CMD_TOTAL_LENGTH = 10 # Total bytes when sending AD9833 command +AD9833_CMD_HEADER = "9999" +DS1809_CMD_TOTAL_LENGTH = 10 # Total bytes when sending DS1809 UC/DC pulse command +DS1809_CMD_HEADER = "AAAA" AD9102_SAW_STEP_DEFAULT = 1 AD9102_PAT_PERIOD_DEFAULT = 0xFFFF AD9102_PAT_PERIOD_BASE_DEFAULT = 0x02 AD9102_DAC_CLK_HZ = None # set to actual DAC clock if you want freq->SAW_STEP conversion AD9102_FLAG_SRAM = 0x0004 +AD9102_FLAG_SRAM_FMT = 0x0008 AD9102_SRAM_SAMPLES_DEFAULT = 16 AD9102_SRAM_HOLD_DEFAULT = 1 +AD9102_SRAM_AMP_DEFAULT = 8191 +AD9833_FLAG_ENABLE = 0x0001 +AD9833_FLAG_TRIANGLE = 0x0002 +AD9833_MCLK_HZ_DEFAULT = 25_000_000 +DS1809_FLAG_UC = 0x0001 +DS1809_FLAG_DC = 0x0002 +DS1809_PULSE_MS_DEFAULT = 2 class TaskType(IntEnum): Manual = 0x00 @@ -158,8 +170,19 @@ def send_STATE(prt): pass +def send_AD9102(prt, bytestring): + ''' Start/stop AD9102 output with saw/triangle (0x8888 + ...). + Expected device answer: STATE. + ''' + if len(bytestring) != AD9102_CMD_TOTAL_LENGTH: + print("Error. Wrong parameter string for AD9102 command.") + return None + prt.write(bytestring) + print("Sent: AD9102 ramp command.") + + def send_AD9833(prt, bytestring): - ''' Start/stop AD9833 output with triangle (ramp) mode (0x8888 + ...). + ''' Start/stop AD9833 output with triangle (0x9999 + ...). Expected device answer: STATE. ''' if len(bytestring) != AD9833_CMD_TOTAL_LENGTH: @@ -169,6 +192,17 @@ def send_AD9833(prt, bytestring): print("Sent: AD9833 ramp command.") +def send_DS1809(prt, bytestring): + ''' Pulse DS1809 UC/DC control lines (0xAAAA + ...). + Expected device answer: STATE. + ''' + if len(bytestring) != DS1809_CMD_TOTAL_LENGTH: + print("Error. Wrong parameter string for DS1809 command.") + return None + prt.write(bytestring) + print("Sent: DS1809 pulse command.") + + # ---- Getting data @@ -324,14 +358,15 @@ def calc_sram_samples_for_freq(freq_hz: float, dac_clk_hz: float, hold: int = No -def create_AD9833_ramp_command(saw_step: int = None, +def create_AD9102_ramp_command(saw_step: int = None, pat_period: int = None, pat_period_base: int = None, enable: bool = True, triangle: bool = True, sram_mode: bool = False, sram_samples: int = None, - sram_hold: int = None): + sram_hold: int = None, + sram_amplitude: int = None): flags = 0 if enable: flags |= 0x0001 @@ -341,18 +376,21 @@ def create_AD9833_ramp_command(saw_step: int = None, flags |= AD9102_FLAG_SRAM if sram_mode: + flags |= AD9102_FLAG_SRAM_FMT if sram_samples is None: sram_samples = AD9102_SRAM_SAMPLES_DEFAULT if sram_samples < 2: sram_samples = 2 if sram_samples > 4096: sram_samples = 4096 - if sram_hold is None or sram_hold <= 0: - sram_hold = AD9102_SRAM_HOLD_DEFAULT - if sram_hold > 0x0F: - sram_hold = 0x0F - param0 = sram_samples & 0xFFFF - param1 = sram_hold & 0x000F + if sram_amplitude is None: + sram_amplitude = AD9102_SRAM_AMP_DEFAULT + if sram_amplitude < 0: + sram_amplitude = 0 + if sram_amplitude > AD9102_SRAM_AMP_DEFAULT: + sram_amplitude = AD9102_SRAM_AMP_DEFAULT + param0 = int(sram_amplitude) & 0xFFFF + param1 = int(sram_samples) & 0xFFFF else: if saw_step is None: saw_step = AD9102_SAW_STEP_DEFAULT @@ -377,8 +415,78 @@ def create_AD9833_ramp_command(saw_step: int = None, crc_word = flags ^ param0 ^ param1 + data = flipfour(AD9102_CMD_HEADER) # Word 0 (header) + data += flipfour(int_to_hex(flags)) + data += flipfour(int_to_hex(param0)) + data += flipfour(int_to_hex(param1)) + data += flipfour(int_to_hex(crc_word)) + + return bytearray.fromhex(data) + + +def create_AD9833_ramp_command(freq_hz: float, + mclk_hz: float = None, + enable: bool = True, + triangle: bool = True): + if mclk_hz is None or mclk_hz <= 0: + mclk_hz = AD9833_MCLK_HZ_DEFAULT + if mclk_hz is None or mclk_hz <= 0 or freq_hz is None or freq_hz < 0: + freq_word = 0 + else: + freq_word = int(round((freq_hz * (1 << 28)) / float(mclk_hz))) + if freq_word < 0: + freq_word = 0 + if freq_word > 0x0FFFFFFF: + freq_word = 0x0FFFFFFF + + lsw = freq_word & 0x3FFF + msw = (freq_word >> 14) & 0x3FFF + + flags = 0 + if enable: + flags |= AD9833_FLAG_ENABLE + if triangle: + flags |= AD9833_FLAG_TRIANGLE + + crc_word = flags ^ lsw ^ msw + data = flipfour(AD9833_CMD_HEADER) # Word 0 (header) data += flipfour(int_to_hex(flags)) + data += flipfour(int_to_hex(lsw)) + data += flipfour(int_to_hex(msw)) + data += flipfour(int_to_hex(crc_word)) + + return bytearray.fromhex(data) + + +def create_DS1809_pulse_command(uc: bool = False, + dc: bool = False, + count: int = 1, + pulse_ms: int = None): + flags = 0 + if uc: + flags |= DS1809_FLAG_UC + if dc: + flags |= DS1809_FLAG_DC + + if count is None or count <= 0: + count = 1 + if count > 64: + count = 64 + + if pulse_ms is None: + pulse_ms = DS1809_PULSE_MS_DEFAULT + if pulse_ms < 1: + pulse_ms = 1 + if pulse_ms > 500: + pulse_ms = 500 + + param0 = int(count) & 0xFFFF + param1 = int(pulse_ms) & 0xFFFF + crc_word = flags ^ param0 ^ param1 + + data = flipfour(DS1809_CMD_HEADER) # Word 0 (header) + data += flipfour(int_to_hex(flags)) data += flipfour(int_to_hex(param0)) data += flipfour(int_to_hex(param1)) data += flipfour(int_to_hex(crc_word)) @@ -463,8 +571,12 @@ def decode_DATA(dh): data = {} data['datetime'] = datetime.now() data['Header'] = get_word(dh, 0) - data['I1'] = cnv.conv_I_N_to_mA(get_int_word(dh, 1)) #LD1_param.POWER - data['I2'] = cnv.conv_I_N_to_mA(get_int_word(dh, 2)) #LD2_param.POWER + i1_raw = get_int_word(dh, 1) + i2_raw = get_int_word(dh, 2) + data['I1_raw'] = i1_raw + data['I2_raw'] = i2_raw + data['I1'] = cnv.conv_I_N_to_mA(i1_raw) #LD1_param.POWER + data['I2'] = cnv.conv_I_N_to_mA(i2_raw) #LD2_param.POWER data['TO_LSB'] = get_int_word(dh, 3) #TO6_counter_LSB data['TO_MSB'] = get_int_word(dh, 4) #TO6_counter_MSB data['Temp_1'] = cnv.conv_T_N_to_C(get_int_word(dh, 5)) #LD1_param.LD_CURR_TEMP @@ -479,4 +591,3 @@ def decode_DATA(dh): data['CRC'] = get_word(dh, 14) return data - diff --git a/device_conversion.py b/device_conversion.py index 947b5a9..766b364 100644 --- a/device_conversion.py +++ b/device_conversion.py @@ -13,7 +13,7 @@ R4 = 30000 # Ohm R5 = 27000 # Ohm R6 = 56000 # Ohm -RREF = 10 # Ohm (current-setting resistor) @1550 nm - 28.7 Ohm; @840 nm - 10 Ohm +RREF = 30 # Ohm (current-setting resistor) @1550 nm - 28.7 Ohm; @840 nm - 10 Ohm R7 = 22000 # Ohm R8 = 22000 # Ohm diff --git a/device_interaction.py b/device_interaction.py index e7877e8..f331aba 100644 --- a/device_interaction.py +++ b/device_interaction.py @@ -112,7 +112,7 @@ def send_task_command(prt, sending_param): -def start_ramp_max(prt, freq_hz=None, duty=None, saw_step=None, pat_period=None, pat_period_base=None, dac_clk_hz=None, triangle=True, sram_mode=False, sram_samples=None, sram_hold=None): +def start_ramp_max(prt, freq_hz=None, duty=None, saw_step=None, pat_period=None, pat_period_base=None, dac_clk_hz=None, triangle=True, sram_mode=False, sram_samples=None, sram_hold=None, sram_amplitude=None): # Start AD9102 sawtooth with configurable frequency/duty or SRAM ramp mode if sram_mode: if sram_hold is None: @@ -121,8 +121,9 @@ def start_ramp_max(prt, freq_hz=None, duty=None, saw_step=None, pat_period=None, if dac_clk_hz is None: dac_clk_hz = cmd.AD9102_DAC_CLK_HZ sram_samples = cmd.calc_sram_samples_for_freq(freq_hz, dac_clk_hz, sram_hold) - hexstring = cmd.create_AD9833_ramp_command(enable=True, triangle=triangle, sram_mode=True, - sram_samples=sram_samples, sram_hold=sram_hold) + hexstring = cmd.create_AD9102_ramp_command(enable=True, triangle=triangle, sram_mode=True, + sram_samples=sram_samples, sram_hold=sram_hold, + sram_amplitude=sram_amplitude) else: if pat_period_base is None: pat_period_base = cmd.AD9102_PAT_PERIOD_BASE_DEFAULT @@ -136,8 +137,23 @@ def start_ramp_max(prt, freq_hz=None, duty=None, saw_step=None, pat_period=None, pat_period = cmd.calc_pat_period_for_duty(saw_step, duty, pat_period_base, triangle) if pat_period is None: pat_period = cmd.AD9102_PAT_PERIOD_DEFAULT - hexstring = cmd.create_AD9833_ramp_command(saw_step, pat_period, pat_period_base, + hexstring = cmd.create_AD9102_ramp_command(saw_step, pat_period, pat_period_base, enable=True, triangle=triangle) + cmd.send_AD9102(prt, hexstring) + time.sleep(WAIT_AFTER_SEND) + status = cmd.get_STATE(prt).hex() + if status is not None: + print("Received: STATE. State status:", cmd.decode_STATE(status), "("+cmd.flipfour(status)+")") + print("") + else: + print("") + + +def start_ad9833_ramp(prt, freq_hz=None, mclk_hz=None, triangle=True, enable=True): + if freq_hz is None: + freq_hz = 0.0 + hexstring = cmd.create_AD9833_ramp_command(freq_hz=freq_hz, mclk_hz=mclk_hz, + enable=enable, triangle=triangle) cmd.send_AD9833(prt, hexstring) time.sleep(WAIT_AFTER_SEND) status = cmd.get_STATE(prt).hex() @@ -148,6 +164,18 @@ def start_ramp_max(prt, freq_hz=None, duty=None, saw_step=None, pat_period=None, print("") +def send_ds1809_pulse(prt, uc=False, dc=False, count=1, pulse_ms=None): + hexstring = cmd.create_DS1809_pulse_command(uc=uc, dc=dc, count=count, pulse_ms=pulse_ms) + cmd.send_DS1809(prt, hexstring) + time.sleep(WAIT_AFTER_SEND) + status = cmd.get_STATE(prt).hex() + if status is not None: + print("Received: STATE. State status:", cmd.decode_STATE(status), "("+cmd.flipfour(status)+")") + print("") + else: + print("") + + def request_data(prt): # Request data cmd.send_TRANS_ENABLE(prt) diff --git a/gui.py b/gui.py index 8ac9c2b..bd56f19 100644 --- a/gui.py +++ b/gui.py @@ -49,6 +49,15 @@ SET_RAMP_DACCLK_TEXT = 'DAC clk (МГц):' SET_RAMP_TRI_TEXT = 'Треугольник' SET_RAMP_SRAM_MODE_TEXT = 'SRAM режим' SET_RAMP_SRAM_SAMPLES_TEXT = 'SRAM точки (samples):' +SET_RAMP_SRAM_AMP_TEXT = 'SRAM амплитуда (%):' +SET_AD9833_SECTION_TEXT = 'Настройка пилы (AD9833)' +SET_AD9833_FREQ_TEXT = 'Частота AD9833 (Гц):' +SET_AD9833_MCLK_TEXT = 'MCLK AD9833 (МГц):' +SET_AD9833_TRI_TEXT = 'Треугольник AD9833' +SET_AD9833_BUTTON_TEXT = 'Пила AD9833' +SET_DS1809_SECTION_TEXT = 'DS1809 (UC/DC)' +SET_DS1809_UC_BUTTON_TEXT = 'UC импульс' +SET_DS1809_DC_BUTTON_TEXT = 'DC импульс' GRAPH_POINTS_NUMBER = 100 # Number of most recent data points shown on charts @@ -236,9 +245,32 @@ def setup_gui(params): [sg.Text(SET_RAMP_SRAM_SAMPLES_TEXT, size=(SET_TEXT_WIDTH_NEW,1)), sg.Input(params.get('RampSramSamples', ''), size=(SET_INPUT_WIDTH,1), key='-RampSramSamples-')], + [sg.Text(SET_RAMP_SRAM_AMP_TEXT, size=(SET_TEXT_WIDTH_NEW,1)), + sg.Input(params.get('RampSramAmp', ''), size=(SET_INPUT_WIDTH,1), key='-RampSramAmp-')], + + [sg.HSeparator(pad=H_SEPARATOR_PAD)], + + [sg.Text(SET_AD9833_SECTION_TEXT, size=(SET_TEXT_WIDTH_NEW,1))], + + [sg.Text(SET_AD9833_FREQ_TEXT, size=(SET_TEXT_WIDTH_NEW,1)), + sg.Input(params.get('Ad9833Freq', ''), size=(SET_INPUT_WIDTH,1), key='-AD9833Freq-')], + + [sg.Text(SET_AD9833_MCLK_TEXT, size=(SET_TEXT_WIDTH_NEW,1)), + sg.Input(params.get('Ad9833Mclk', ''), size=(SET_INPUT_WIDTH,1), key='-AD9833Mclk-')], + + [sg.Text(SET_AD9833_TRI_TEXT, size=(SET_TEXT_WIDTH_NEW,1)), + sg.Checkbox('', default=bool(params.get('Ad9833Triangle', True)), key='-AD9833Triangle-')], + + [sg.HSeparator(pad=H_SEPARATOR_PAD)], + + [sg.Text(SET_DS1809_SECTION_TEXT, size=(SET_TEXT_WIDTH_NEW,1))], + + [sg.Button(SET_DS1809_UC_BUTTON_TEXT, key='-DS1809UC-', disabled_button_color=("Gray22", "Blue")), + sg.Button(SET_DS1809_DC_BUTTON_TEXT, key='-DS1809DC-', disabled_button_color=("Gray22", "Blue"))], + [sg.HSeparator(pad=H_SEPARATOR_PAD)], - [sg.Button(SET_START_BUTTON_TEXT, key='-StartCycle-', disabled_button_color=("Gray22", "Blue"), disabled=True), sg.Button(SET_STOP_BUTTON_TEXT, disabled_button_color=("Gray22", "Blue"), key='-StopCycle-', disabled=True), sg.Button(SET_RAMP_BUTTON_TEXT, key='-StartRamp-', disabled_button_color=("Gray22", "Blue"))]] + [sg.Button(SET_START_BUTTON_TEXT, key='-StartCycle-', disabled_button_color=("Gray22", "Blue"), disabled=True), sg.Button(SET_STOP_BUTTON_TEXT, disabled_button_color=("Gray22", "Blue"), key='-StopCycle-', disabled=True), sg.Button(SET_RAMP_BUTTON_TEXT, key='-StartRamp-', disabled_button_color=("Gray22", "Blue")), sg.Button(SET_AD9833_BUTTON_TEXT, key='-StartRamp9833-', disabled_button_color=("Gray22", "Blue"))]] layout = [[sg.Column(layout_input_col1, pad=(0,0)), sg.VSeparator(pad=(4,0)), sg.Column(layout_input_col2, pad=(0,0)), sg.VSeparator(pad=(4,0)), sg.Column(layout_input_col3, pad=(0,0))],