From d97750152a93915a137ecf0993ecc310eb10bb77 Mon Sep 17 00:00:00 2001 From: gjones Date: Wed, 26 Jun 2013 16:51:23 -0400 Subject: [PATCH 01/17] Add finally clauses to close connection on failure --- src/valon_synth.py | 171 ++++++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 65 deletions(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index 04822bf..f04ab5a 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -96,10 +96,12 @@ def get_frequency(self, synth): """ self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) ncount, frac, mod, dbf = _unpack_freq_registers(data) epdf = self._get_epdf(synth) @@ -143,17 +145,22 @@ def set_frequency(self, synth, freq, chan_spacing = 10.): mod = 1 self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - old_data = self.conn.read(24) - checksum = self.conn.read(1) + try: + self.conn.write(data) + old_data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(old_data, checksum) data = struct.pack('>B24s', 0x00 | synth, _pack_freq_registers(ncount, frac, mod, dbf, old_data)) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -163,10 +170,12 @@ def get_reference(self): """ self.conn.open() data = struct.pack('>B', 0x81) - self.conn.write(data) - data = self.conn.read(4) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(4) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) freq = struct.unpack('>I', data)[0] return freq @@ -183,9 +192,11 @@ def set_reference(self, freq): self.conn.open() data = struct.pack('>BI', 0x01, freq) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -201,10 +212,12 @@ def get_rf_level(self, synth): rfl_table = {0: -4, 1: -1, 2: 2, 3: 5} self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) _, _, _, _, reg4, _ = struct.unpack('>IIIIII', data) rfl = (reg4 >> 3) & 0x03 @@ -229,9 +242,12 @@ def set_rf_level(self, synth, rf_level): return False self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffe7 @@ -239,9 +255,11 @@ def set_rf_level(self, synth, rf_level): data = struct.pack('>BIIIIII', 0x00 | synth, reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -262,10 +280,12 @@ def get_options(self, synth): """ self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) _, _, reg2, _, _, _ = struct.unpack('>IIIIII', data) low_spur = ((reg2 >> 30) & 1) & ((reg2 >> 29) & 1) @@ -301,9 +321,12 @@ def set_options(self, synth, double = 0, half = 0, divider = 1, """ self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg2 &= 0x9c003fff @@ -313,9 +336,11 @@ def set_options(self, synth, double = 0, half = 0, divider = 1, data = struct.pack('>BIIIIII', 0x00 | synth, reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -326,10 +351,12 @@ def get_ref_select(self): """ self.conn.open() data = struct.pack('>B', 0x86) - self.conn.write(data) - data = self.conn.read(1) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(1) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) is_ext = struct.unpack('>B', data)[0] return is_ext & 1 @@ -346,9 +373,11 @@ def set_ref_select(self, e_not_i = 1): self.conn.open() data = struct.pack('>BB', 0x06, e_not_i & 1) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -363,10 +392,12 @@ def get_vco_range(self, synth): """ self.conn.open() data = struct.pack('>B', 0x83 | synth) - self.conn.write(data) - data = self.conn.read(4) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(4) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) return struct.unpack('>HH', data) @@ -388,9 +419,11 @@ def set_vco_range(self, synth, low, high): self.conn.open() data = struct.pack('>BHH', 0x03 | synth, low, high) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -405,10 +438,12 @@ def get_phase_lock(self, synth): """ self.conn.open() data = struct.pack('>B', 0x86 | synth) - self.conn.write(data) - data = self.conn.read(1) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(1) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) mask = (synth << 1) or 0x20 lock = struct.unpack('>B', data)[0] & mask @@ -425,10 +460,12 @@ def get_label(self, synth): """ self.conn.open() data = struct.pack('>B', 0x82 | synth) - self.conn.write(data) - data = self.conn.read(16) - checksum = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data) + data = self.conn.read(16) + checksum = self.conn.read(1) + finally: + self.conn.close() #_verify_checksum(data, checksum) return data @@ -447,9 +484,11 @@ def set_label(self, synth, label): self.conn.open() data = struct.pack('>B16s', 0x02 | synth, label) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -462,9 +501,11 @@ def flash(self): self.conn.open() data = struct.pack('>B', 0x40) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK From 81a35434f32d850dbb510e24870cd3e42083e0ea Mon Sep 17 00:00:00 2001 From: gjones Date: Wed, 26 Jun 2013 16:51:23 -0400 Subject: [PATCH 02/17] Add timeout parameter --- src/valon_synth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index f04ab5a..01f57b1 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -80,10 +80,11 @@ def _unpack_freq_registers(data): class Synthesizer: """A simple interface to the Valon 500x synthesizer.""" - def __init__(self, port): + def __init__(self, port, timeout=1.0): self.conn = serial.Serial(None, 9600, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE) self.conn.setPort(port) + self.conn.setTimeout(timeout) def get_frequency(self, synth): """ From 20375076e45948e278f63af638984ab03056681a Mon Sep 17 00:00:00 2001 From: gjones Date: Wed, 26 Jun 2013 17:18:43 -0400 Subject: [PATCH 03/17] add __version__ attribute to find out if correct version is installed --- src/valon_synth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index 01f57b1..0aefdc9 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -32,9 +32,9 @@ __author__ = "Patrick Brandt" __copyright__ = "Copyright 2011, Associated Universities, Inc." -__credits__ = ["Patrick Brandt, Stewart Rumley, Steven Stark"] +__credits__ = ["Patrick Brandt, Stewart Rumley, Steven Stark, Glenn Jones"] __license__ = "GPL" -#__version__ = "1.0" +__version__ = "1.0" __maintainer__ = "Patrick Brandt" From f877b9fde5a85d8d2ed73e5c8654b29f29fd9d02 Mon Sep 17 00:00:00 2001 From: Jack Hickish Date: Mon, 25 Apr 2016 17:40:30 -0700 Subject: [PATCH 04/17] Add methods to power up/down synths --- src/valon_synth.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/valon_synth.py b/src/valon_synth.py index 0aefdc9..7b2fed1 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -225,6 +225,56 @@ def get_rf_level(self, synth): rf_level = rfl_table.get(rfl) return rf_level + def rf_disable(self, synth): + """ + Disable RF output. + + @param synth : synthesizer address, 0 or 8 + @type synth : int + """ + self.conn.open() + data = struct.pack('>B', 0x80 | synth) + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + #_verify_checksum(data, checksum) + reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) + reg4 &= 0xffffffdf # RF Output power up + ref4 |= 1 << 9 # VCO power down + data = struct.pack('>BIIIIII', 0x00 | synth, + reg0, reg1, reg2, reg3, reg4, reg5) + checksum = _generate_checksum(data) + self.conn.write(data + checksum) + data = self.conn.read(1) + self.conn.close() + ack = struct.unpack('>B', data)[0] + return ack == ACK + + def rf_enable(self, synth): + """ + Enable RF output. + + @param synth : synthesizer address, 0 or 8 + @type synth : int + """ + self.conn.open() + data = struct.pack('>B', 0x80 | synth) + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + #_verify_checksum(data, checksum) + reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) + reg4 &= 0xfffff7ff # VCO power up + reg4 |= 1 << 5 # RF Output power up + data = struct.pack('>BIIIIII', 0x00 | synth, + reg0, reg1, reg2, reg3, reg4, reg5) + checksum = _generate_checksum(data) + self.conn.write(data + checksum) + data = self.conn.read(1) + self.conn.close() + ack = struct.unpack('>B', data)[0] + return ack == ACK + def set_rf_level(self, synth, rf_level): """ Set RF level From 6f7a7afa1f3da7e7a966dcf53f675790858d5ed7 Mon Sep 17 00:00:00 2001 From: Jack H Date: Wed, 1 Jun 2016 08:23:52 +0200 Subject: [PATCH 05/17] Fix typo --- src/valon_synth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index 7b2fed1..dfd7a4d 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -240,7 +240,7 @@ def rf_disable(self, synth): #_verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffdf # RF Output power up - ref4 |= 1 << 9 # VCO power down + reg4 |= 1 << 9 # VCO power down data = struct.pack('>BIIIIII', 0x00 | synth, reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) From babe0d212290fa80e68b860817587c40cff4d2f8 Mon Sep 17 00:00:00 2001 From: Jack H Date: Thu, 2 Jun 2016 00:25:45 +0200 Subject: [PATCH 06/17] Swap synth A & B lock bits get_phase_lock(synth) had the bit masks for synths A & B backwards -- get_phase_lock(SYNTH_A) would return the lock status of SYNTH_B and vice versa. This commit brings the code in line with the valon register spec. --- src/valon_synth.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index dfd7a4d..4cb5d42 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -496,7 +496,10 @@ def get_phase_lock(self, synth): finally: self.conn.close() #_verify_checksum(data, checksum) - mask = (synth << 1) or 0x20 + if synth == SYNTH_A: + mask = 1 << 4 + else: + mask = 1 << 5 lock = struct.unpack('>B', data)[0] & mask return lock > 0 From a6132a9e0657a567bf6150e2b81f8b3154c43183 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 08:32:59 +0200 Subject: [PATCH 07/17] valon_synth.py: update __credits__ --- src/valon_synth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index 4cb5d42..0246125 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -32,7 +32,8 @@ __author__ = "Patrick Brandt" __copyright__ = "Copyright 2011, Associated Universities, Inc." -__credits__ = ["Patrick Brandt, Stewart Rumley, Steven Stark, Glenn Jones"] +__credits__ = ["Patrick Brandt, Stewart Rumley, Steven Stark, Glenn Jones," + " Jack Hickish"] __license__ = "GPL" __version__ = "1.0" __maintainer__ = "Patrick Brandt" From 00f56c333886db7a4f1cd9dbc9b74699ffb7fe11 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 07:12:52 +0200 Subject: [PATCH 08/17] Serial.cc: TCFLSH -> TCI[O]FLUSH TCFLSH was removed in Linux v4.6.2. Using th TC*FLUSH ioctl value also allows compilation on BSD and Mac. --- Serial.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Serial.cc b/Serial.cc index cf2674f..f23824f 100644 --- a/Serial.cc +++ b/Serial.cc @@ -162,7 +162,7 @@ int Serial::serial_read(unsigned char *input_buffer, const int &number_of_bytes, { // Flush input buffer. #if defined (SOLARIS) || defined (LINUX) - ioctl(the_serial_port, TCFLSH, 0); + ioctl(the_serial_port, TCIFLUSH, 0); #else ioctl(the_serial_port, FIORFLUSH, 0); #endif @@ -207,7 +207,7 @@ int Serial::open_serial_port(const char *port_name) { // Flush serial port. #if defined (SOLARIS) || defined (LINUX) - ioctl(the_serial_port, TCFLSH, 0); + ioctl(the_serial_port, TCIOFLUSH, 0); #endif #if defined(VXWORKS) ioctl(the_serial_port, FIOFLUSH, 0); From 7c3b53a1fc67112c48612c39e028e814efe6f4b9 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 07:16:34 +0200 Subject: [PATCH 09/17] Remove traling whitespace --- Makefile | 12 ++++---- Serial.cc | 36 ++++++++++++------------ Serial.h | 28 +++++++++---------- ValonSynth.cc | 8 +++--- ValonSynth.h | 68 +++++++++++++++++++++++----------------------- src/__init__.py | 8 +++--- src/valon_synth.py | 8 +++--- 7 files changed, 84 insertions(+), 84 deletions(-) diff --git a/Makefile b/Makefile index fe9d66e..9069a50 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,19 @@ # Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# # Correspondence concerning GBT software should be addressed as follows: # GBT Operations # National Radio Astronomy Observatory @@ -24,7 +24,7 @@ CC = g++ AR = ar DOXY = doxygen CFLAGS = -c -Wall -fPIC -DLINUX -LDFLAGS = +LDFLAGS = SOURCES = ValonSynth.cc Serial.cc OBJECTS = $(SOURCES:.cc=.o) PLATFORM = LINUX @@ -52,4 +52,4 @@ clean: .PHONY: clobber clobber: clean - rm -rf $(STARGET) $(DTARGET) \ No newline at end of file + rm -rf $(STARGET) $(DTARGET) diff --git a/Serial.cc b/Serial.cc index f23824f..56a62d6 100644 --- a/Serial.cc +++ b/Serial.cc @@ -1,19 +1,19 @@ //# Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -//# +//# //# This program is free software; you can redistribute it and/or modify //# it under the terms of the GNU General Public License as published by //# the Free Software Foundation; either version 2 of the License, or //# (at your option) any later version. -//# +//# //# This program is distributed in the hope that it will be useful, but //# WITHOUT ANY WARRANTY; without even the implied warranty of //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //# General Public License for more details. -//# +//# //# You should have received a copy of the GNU General Public License //# along with this program; if not, write to the Free Software //# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//# +//# //# Correspondence concerning GBT software should be addressed as follows: //# GBT Operations //# National Radio Astronomy Observatory @@ -121,7 +121,7 @@ int Serial::serial_write(const unsigned char *output_buffer, } -int Serial::serial_read(unsigned char *input_buffer, const int &number_of_bytes, +int Serial::serial_read(unsigned char *input_buffer, const int &number_of_bytes, const int timeo_us) { int bytes_received = 0; @@ -156,8 +156,8 @@ int Serial::serial_read(unsigned char *input_buffer, const int &number_of_bytes, &input_buffer[bytes_received], #endif (number_of_bytes - bytes_received)); - - // was an error condition present? + + // was an error condition present? if (read_bytes < 0) { // Flush input buffer. @@ -168,7 +168,7 @@ int Serial::serial_read(unsigned char *input_buffer, const int &number_of_bytes, #endif return(read_bytes); } - + bytes_received += read_bytes; if (the_input_mode == Serial::canonical && bytes_received > 0) @@ -234,11 +234,11 @@ int Serial::update_parity(const Serial::parity_choices &parity) switch (parity) { case Serial::odd: - the_termios.c_cflag |= (PARODD | PARENB); + the_termios.c_cflag |= (PARODD | PARENB); break; case Serial::even: - the_termios.c_cflag |= PARENB; - the_termios.c_cflag &= ~(PARODD); + the_termios.c_cflag |= PARENB; + the_termios.c_cflag &= ~(PARODD); break; case Serial::none: the_termios.c_cflag &= ~PARENB; @@ -288,7 +288,7 @@ int Serial::update_baud_rate(const int &baud_rate) cerr << "Cannot set baud rate" << endl; return (-1); } - + speed_t speed; switch (baud_rate) @@ -602,7 +602,7 @@ int Serial::set_raw_input_mode() // as BS-SP-BS. the_termios.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE); the_termios.c_iflag &= ~(INPCK | ISTRIP); - + if (tcsetattr(the_serial_port, TCSAFLUSH, &the_termios) != 0) { // TBF: Error message @@ -646,7 +646,7 @@ int Serial::set_canonical_input_mode() // Enable canonical mode, enable echoing of input characters, enable // echoing of erase character as BS-SP-BS. the_termios.c_lflag |= (ICANON | ECHO | ECHOE); - + if (tcsetattr(the_serial_port, TCSAFLUSH, &the_termios) != 0) { // TBF: Error message @@ -691,19 +691,19 @@ int Serial::set_other_flags() the_termios.c_lflag &= ~IEXTEN; // input flags:- - // Send a SIGINT when a break condition is detected, map CR to NL, + // Send a SIGINT when a break condition is detected, map CR to NL, the_termios.c_iflag &= ~(BRKINT | ICRNL); - + // control flags:- // Setting CLOCAL and CREAD ensures that the program will not become // the owner of the port and the serial interface driver will read // incoming data bytes. the_termios.c_cflag |= (CLOCAL | CREAD); - + // output flags:- // Turn off the output processing the_termios.c_oflag &= ~(OPOST); - + // Set up 0 character minimum with no timeout. the_termios.c_cc[VMIN] = 0; the_termios.c_cc[VTIME] = 0; diff --git a/Serial.h b/Serial.h index af360ea..aff619f 100644 --- a/Serial.h +++ b/Serial.h @@ -1,19 +1,19 @@ //# Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -//# +//# //# This program is free software; you can redistribute it and/or modify //# it under the terms of the GNU General Public License as published by //# the Free Software Foundation; either version 2 of the License, or //# (at your option) any later version. -//# +//# //# This program is distributed in the hope that it will be useful, but //# WITHOUT ANY WARRANTY; without even the implied warranty of //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //# General Public License for more details. -//# +//# //# You should have received a copy of the GNU General Public License //# along with this program; if not, write to the Free Software //# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//# +//# //# Correspondence concerning GBT software should be addressed as follows: //# GBT Operations //# National Radio Astronomy Observatory @@ -26,13 +26,13 @@ // -// This class provides a vehicle for serial communication on the vxWorks, +// This class provides a vehicle for serial communication on the vxWorks, // Linux, and Solaris platforms. // // -//
  • The configuration of the serial port that you wish to use (i.e. -// baud rate, parity, port name, etc). +//
  • The configuration of the serial port that you wish to use (i.e. +// baud rate, parity, port name, etc). //
  • //
    @@ -41,7 +41,7 @@ // // -// This class provides a portable way to use the serial port for +// This class provides a portable way to use the serial port for // program communication. The two main member functions that enable this // communication are read and write. Other member functions are provided // to configure the serial port as needed. The default serial port @@ -69,13 +69,13 @@ // // The valid choices for input mode are raw and canonical. These are // defined via the enumeration input_choices below. Raw mode processes -// the characters as they are typed. Canonical mode handles the +// the characters as they are typed. Canonical mode handles the // characters on a line by line basis - i.e. it waits for the '/n' // character before reading/writing. // // -// To contain all serial communication needs across multiple platforms +// To contain all serial communication needs across multiple platforms // within a single class. // @@ -134,7 +134,7 @@ class Serial // -1 on failure. int set_stop_bits(const int &stop_bits); - // set_hardware_flow_control accepts either 0 = No hardware flow + // set_hardware_flow_control accepts either 0 = No hardware flow // control or 1 = Hardware flow control. If the input parameter is // neither 0 nor 1, hardware flow control is disabled. Returns 0 on // success, -1 on failure. @@ -177,7 +177,7 @@ class Serial input_choices the_input_mode; // - // These member functions set up parameters for the serial port over + // These member functions set up parameters for the serial port over // which the user of this class has no control. // int open_serial_port(const char *port_name); @@ -193,7 +193,7 @@ class Serial virtual int serial_write(const unsigned char *output_buffer, const int &number_of_bytes); virtual int serial_read(unsigned char *input_buffer, - const int &number_of_bytes, + const int &number_of_bytes, const int timeout_usec = 200000); virtual int update_parity(const parity_choices &parity); virtual int update_baud_rate(const int &baud_rate); @@ -215,7 +215,7 @@ inline int Serial::write(const unsigned char *output_buffer, } -inline int Serial::read(unsigned char *input_buffer, const int &number_of_bytes, +inline int Serial::read(unsigned char *input_buffer, const int &number_of_bytes, const int tmo_usec) { return (serial_read(input_buffer, number_of_bytes, tmo_usec)); diff --git a/ValonSynth.cc b/ValonSynth.cc index d1ca213..495503b 100644 --- a/ValonSynth.cc +++ b/ValonSynth.cc @@ -1,19 +1,19 @@ //# Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -//# +//# //# This program is free software; you can redistribute it and/or modify //# it under the terms of the GNU General Public License as published by //# the Free Software Foundation; either version 2 of the License, or //# (at your option) any later version. -//# +//# //# This program is distributed in the hope that it will be useful, but //# WITHOUT ANY WARRANTY; without even the implied warranty of //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //# General Public License for more details. -//# +//# //# You should have received a copy of the GNU General Public License //# along with this program; if not, write to the Free Software //# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//# +//# //# Correspondence concerning GBT software should be addressed as follows: //# GBT Operations //# National Radio Astronomy Observatory diff --git a/ValonSynth.h b/ValonSynth.h index 2b917ee..4afe50c 100644 --- a/ValonSynth.h +++ b/ValonSynth.h @@ -1,19 +1,19 @@ //# Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -//# +//# //# This program is free software; you can redistribute it and/or modify //# it under the terms of the GNU General Public License as published by //# the Free Software Foundation; either version 2 of the License, or //# (at your option) any later version. -//# +//# //# This program is distributed in the hope that it will be useful, but //# WITHOUT ANY WARRANTY; without even the implied warranty of //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //# General Public License for more details. -//# +//# //# You should have received a copy of the GNU General Public License //# along with this program; if not, write to the Free Software //# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//# +//# //# Correspondence concerning GBT software should be addressed as follows: //# GBT Operations //# National Radio Astronomy Observatory @@ -33,20 +33,20 @@ /** * Interface to a Valon 5007 dual synthesizer. - * + * * The reference signal, reference select, and flash commands are shared between * synthesizers. All other settings are independent, so a synthesizer must be * specified when getting and setting values. Frequency values are specified in * MegaHertz (MHz) unless otherwise noted. - * + * * \section calculations Calculations - * + * * The output frequency of the synthesizer is controlled by a number of * parameters. The relationship between these parameters may be expressed by the * following equations. \f$EPDF\f$ is the Effective Phase Detector Frequency and is * the reference frequency(?) after applying the relevant options. (doubler, * halver and divider) - * + * * \f[ * 1 \le dbf=2^n \le 16 * \f] @@ -62,11 +62,11 @@ * \f[ * mod = \lfloor\frac{EPDF}{channel\_spacing}+0.5\rfloor * \f] - * + * * \f$frac\f$ and \f$mod\f$ are a ratio, and can be reduced to the simplest * fraction after the calculations above. To compute the output frequency, use * the following equation. - * + * * \f[ * frequency = (ncount+\frac{frac}{mod})\times\frac{EPDF}{dbf} * \f] @@ -79,7 +79,7 @@ class ValonSynth * referenced. **/ enum Synthesizer { A = 0x00, B = 0x08 }; - + /** * Holds various options used to control the operation of a synthesizer. **/ @@ -90,17 +90,17 @@ class ValonSynth * this mode it is in "low noise" mode. **/ bool low_spur; - + /** * The reference frequency doubler is active. **/ bool double_ref; - + /** * The reference frequency halver is active. **/ bool half_ref; - + /** * The reference frequency divider value; **/ @@ -116,7 +116,7 @@ class ValonSynth * Minimum frequency the VCO is capable of producing. **/ uint16_t min; - + /** * Maximum frequency the VCO is capable of producing. **/ @@ -133,14 +133,14 @@ class ValonSynth * \name Methods relating to output frequency * \{ **/ - + /** * Read the current settings from the synthesizer. * @param[in] synth The synthesizer to be read. * @return Frequency in MHz. **/ float get_frequency(enum Synthesizer synth); - + /** * Read the current settings from the synthesizer. * @param[in] synth The synthesizer to be read. @@ -148,7 +148,7 @@ class ValonSynth * @return True on succesful completion. **/ bool get_frequency(enum Synthesizer synth, float &frequency); - + /** * Set the synthesizer to the desired frequency, or best approximation based * on channel spacing. See the section on \ref calculations. @@ -165,14 +165,14 @@ class ValonSynth * \name Methods relating to the reference frequency * \{ **/ - + /** * Read the current reference frequency. This is shared between the two * channels. * @return The reference frequency in Hz. **/ uint32_t get_reference(); - + /** * Read the current reference frequency. This is shared between the two * channels. @@ -180,7 +180,7 @@ class ValonSynth * @return True on successful completion. **/ bool get_reference(uint32_t &reference); - + /** * Set the synthesizer reference frequency. This does not change the actual * reference frequency of the synthesizer for either internal or external @@ -225,12 +225,12 @@ class ValonSynth /** * \} * \name Members relating to the synthesizer options - * + * * Note that although the reference frequency is shared these options are * specific to a particular synthesizer. * \{ **/ - + /** * Read the current options for a synthesizer. * @param[in] synth The synthesizer to be read. @@ -238,7 +238,7 @@ class ValonSynth * @return True on successful completion. **/ bool get_options(enum Synthesizer synth, struct options &opts); - + /** * Set the options for a synthesizer. * @param[in] synth The synthesizer to be set. @@ -252,13 +252,13 @@ class ValonSynth * \name Methods relating to the reference source * \{ **/ - + /** * Read the current reference source. * @return True if external, false if internal. **/ bool get_ref_select(); - + /** * Read the current reference source. * @param[out] e_not_i Receives the refernce source. True if external, @@ -266,7 +266,7 @@ class ValonSynth * @return True on successful completion. **/ bool get_ref_select(bool &e_not_i); - + /** * Set the reference source. * @param[in] e_not_i True for external, false for internal. @@ -279,7 +279,7 @@ class ValonSynth * \name Methods relating to the voltage controlled oscillator * \{ **/ - + /** * Read the current range of the VCO. * @param[in] synth The synthesizer to be read. @@ -287,7 +287,7 @@ class ValonSynth * @return True on successful completion. **/ bool get_vco_range(enum Synthesizer synth, vco_range &vcor); - + /** * Set the range of the VCO. This affects the allowable frequency range of * the output. See \ref calculations for details. @@ -302,7 +302,7 @@ class ValonSynth * \name Methods relating to phase lock. * \{ **/ - + /** * Read the current state of phase lock. * @param[in] synth The synthesizer to be read. @@ -323,7 +323,7 @@ class ValonSynth * \name Methods relating to synthesizer labels. * \{ **/ - + /** * Read the current label of the specified synthesizer. * @param[in] synth The synthesizer to be read. @@ -332,7 +332,7 @@ class ValonSynth * @return True on successful completion. **/ bool get_label(enum Synthesizer synth, char *label); - + /** * Set the label of the specified synthesizer. * @param[in] synth The synthesizer to be read. @@ -344,7 +344,7 @@ class ValonSynth /** * \} **/ - + /** * Copies all current settings for both synthesizers to non-volatile flash * memory. @@ -379,7 +379,7 @@ class ValonSynth void pack_short(uint16_t num, uint8_t *bytes); void unpack_int(const uint8_t *bytes, uint32_t &num); void unpack_short(const uint8_t *bytes, uint16_t &num); - + Serial s; }; diff --git a/src/__init__.py b/src/__init__.py index ebcfb4c..7b9f579 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,19 +1,19 @@ # Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# # Correspondence concerning GBT software should be addressed as follows: # GBT Operations # National Radio Astronomy Observatory diff --git a/src/valon_synth.py b/src/valon_synth.py index 0246125..d7d2ccc 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -1,19 +1,19 @@ # Copyright (C) 2011 Associated Universities, Inc. Washington DC, USA. -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# # Correspondence concerning GBT software should be addressed as follows: # GBT Operations # National Radio Astronomy Observatory From 8f8dde8fc4d36d712a80855dd1f666326fbb179d Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 08:37:06 +0200 Subject: [PATCH 10/17] valon_synth.py: update docstrings --- src/valon_synth.py | 116 ++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 38 deletions(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index d7d2ccc..e019a4f 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -20,9 +20,7 @@ # P. O. Box 2 # Green Bank, WV 24944-0002 USA -""" -Provides a serial interface to the Valon 500x. -""" +"""Provides a serial interface to the Valon 500x.""" # Python modules import struct @@ -88,8 +86,7 @@ def __init__(self, port, timeout=1.0): self.conn.setTimeout(timeout) def get_frequency(self, synth): - """ - Returns the current output frequency for the selected synthesizer. + """Returns the current output frequency for the selected synthesizer. @param synth : synthesizer this command affects (0 for 1, 8 for 2). @type synth : int @@ -110,8 +107,7 @@ def get_frequency(self, synth): return (ncount + float(frac) / mod) * epdf / dbf def set_frequency(self, synth, freq, chan_spacing = 10.): - """ - Sets the synthesizer to the desired frequency + """Sets the synthesizer to the desired frequency. Sets to the closest possible frequency, depending on the channel spacing. Range is determined by the minimum and maximum VCO frequency. @@ -167,8 +163,11 @@ def set_frequency(self, synth, freq, chan_spacing = 10.): return ack == ACK def get_reference(self): - """ - Get reference frequency in MHz + """Get reference frequency in MHz. + + @param No input parameters + + @return Int: Reference input frequency (MHz) """ self.conn.open() data = struct.pack('>B', 0x81) @@ -183,8 +182,10 @@ def get_reference(self): return freq def set_reference(self, freq): - """ - Set reference frequency in MHz + """Set reference frequency in MHz. + + For the 5007: this value must be between 5 MHz and 150 MHz, according + to the data sheet. @param freq : frequency in MHz @type freq : float @@ -203,8 +204,9 @@ def set_reference(self, freq): return ack == ACK def get_rf_level(self, synth): - """ - Returns RF level in dBm + """Returns RF level in dBm. + + The current output power level can be one of four values: -4, -1, 2, 5 @param synth : synthesizer address, 0 or 8 @type synth : int @@ -277,8 +279,10 @@ def rf_enable(self, synth): return ack == ACK def set_rf_level(self, synth, rf_level): - """ - Set RF level + """Set RF level. + + Allows user to select one of four output power levels: -4, -1, 2, 5 + These levels corresponds approximately to some preset output power. @param synth : synthesizer address, 0 or 8 @type synth : int @@ -316,8 +320,33 @@ def set_rf_level(self, synth, rf_level): return ack == ACK def get_options(self, synth): - """ - Get options tuple: + """Get options tuple: + + Output a Tuple of 4 parameters, which can be 0 (disabled) or 1(enabled) + + - double: The reference doubler is used to enable a multiply by 2 + function before the internal reference divider. + + Enable the doubler when using a 5 MHz external reference frequency. + When using the internal 10 MHz reference the doubler should be + disabled. + + - half: The reference divide by 2 is used to enable a divide by 2 + function after the intercal reference divider. + + When enabled, the input to phase-frequency detector will have a 50% + duty cycle which will allow for faster lock up time. In order to use + this mode a 20 MHz external reference would have to be available. + For normal operations set the reference div by 2 to disabled. + + - r: reference frequency divisor + + - spur: Low noise mode vs Low spur mode. + + Low noise mode affects the operation of the fractional synthesizer, + and this mode will produce the lowest phase noise but there may be + some spurious output signals. Low spur mode will reduce spurious + output response but the overall phase noise will be higher. bool double: if True, reference frequency is doubled bool half: if True, reference frequency is halved @@ -348,8 +377,7 @@ def get_options(self, synth): def set_options(self, synth, double = 0, half = 0, divider = 1, low_spur = 0): - """ - Set options. + """Set options. double and half both True is same as both False. @@ -399,7 +427,9 @@ def set_options(self, synth, double = 0, half = 0, divider = 1, def get_ref_select(self): """Returns the currently selected reference clock. - Returns 1 if the external reference is selected, 0 otherwise. + @param No input parameters + + @return: 1 if the external reference is selected, 0 otherwise. """ self.conn.open() data = struct.pack('>B', 0x86) @@ -414,8 +444,7 @@ def get_ref_select(self): return is_ext & 1 def set_ref_select(self, e_not_i = 1): - """ - Selects either internal or external reference clock. + """Selects either internal or external reference clock. @param e_not_i : 1 (external) or 0 (internal); default 1 @type e_not_i : int @@ -434,13 +463,16 @@ def set_ref_select(self, e_not_i = 1): return ack == ACK def get_vco_range(self, synth): - """ - Returns (min, max) VCO range tuple. + """Returns (min, max) VCO range tuple. + + The VCO Frequency Range information is used to limit and check the + resulting VCO output frequency, entered in the set frequency request + function. @param synth : synthesizer base address @type synth : int - @return: min,max in MHz + @return: Tuple: (lowest VCO output frequency, highest VCO output frequency) in MHz """ self.conn.open() data = struct.pack('>B', 0x83 | synth) @@ -454,8 +486,10 @@ def get_vco_range(self, synth): return struct.unpack('>HH', data) def set_vco_range(self, synth, low, high): - """ - Sets VCO range. + """Sets VCO range. + + Set the minimum and maximum frequency range of the selected synthesizer + VCO. @param synth : synthesizer base address @type synth : int @@ -480,8 +514,7 @@ def set_vco_range(self, synth, low, high): return ack == ACK def get_phase_lock(self, synth): - """ - Get phase lock status + """Get phase lock status. @param synth : synthesizer base address @type synth : int @@ -505,8 +538,7 @@ def get_phase_lock(self, synth): return lock > 0 def get_label(self, synth): - """ - Get synthesizer label or name + """Get synthesizer label or name. @param synth : synthesizer base address @type synth : int @@ -525,13 +557,12 @@ def get_label(self, synth): return data def set_label(self, synth, label): - """ - Set synthesizer label or name + """Set synthesizer label or name. @param synth : synthesizer base address @type synth : int - @param label : up to 16 data of text + @param label : up to 16 bytes of text @type label : str @return: True if success (bool) @@ -548,8 +579,13 @@ def set_label(self, synth, label): return ack == ACK def flash(self): - """ - Flash current settings for both synthesizers into non-volatile memory. + """Flash current settings for both synthesizers into non-volatile + memory. + + The next time the board is powered up, the registers will be set to the + values in the non-volatile flash memory. If the board is powered down + before the write flash command command is issued, all the data in the + registers will be lost. @return: True if success (bool) """ @@ -565,10 +601,14 @@ def flash(self): return ack == ACK def _get_epdf(self, synth): - """ - Returns effective phase detector frequency. + """Returns effective phase detector frequency. This is the reference frequency with options applied. + + @param synth : synthesizer base address + @type synth : int + + @return: frequency """ reference = self.get_reference() / 1e6 double, half, divider, _ = self.get_options(synth) From d4b56a8f0d115a3058ac9c36d8338f90fb780ce8 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 11:22:37 +0200 Subject: [PATCH 11/17] Flake8 --- src/__init__.py | 10 ++--- src/valon_synth.py | 101 ++++++++++++++++++++++++--------------------- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/__init__.py b/src/__init__.py index 7b9f579..a497480 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -15,9 +15,9 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Correspondence concerning GBT software should be addressed as follows: -# GBT Operations -# National Radio Astronomy Observatory -# P. O. Box 2 -# Green Bank, WV 24944-0002 USA +# GBT Operations +# National Radio Astronomy Observatory +# P. O. Box 2 +# Green Bank, WV 24944-0002 USA -from valon_synth import Synthesizer, SYNTH_A, SYNTH_B, INT_REF, EXT_REF +from valon_synth import Synthesizer, SYNTH_A, SYNTH_B, INT_REF, EXT_REF # noqa diff --git a/src/valon_synth.py b/src/valon_synth.py index e019a4f..ddfe84e 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -15,10 +15,10 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Correspondence concerning GBT software should be addressed as follows: -# GBT Operations -# National Radio Astronomy Observatory -# P. O. Box 2 -# Green Bank, WV 24944-0002 USA +# GBT Operations +# National Radio Astronomy Observatory +# P. O. Box 2 +# Green Bank, WV 24944-0002 USA """Provides a serial interface to the Valon 500x.""" @@ -47,14 +47,17 @@ ACK = 0x06 NACK = 0x15 + def _generate_checksum(data): "Generate a checksum for the data provided." return chr(sum([ord(b) for b in data]) % 256) + def _verify_checksum(data, checksum): "Verify a checksum for the data provided." return (_generate_checksum(data) == checksum) + def _pack_freq_registers(ncount, frac, mod, dbf, old_data): "Do bit packing for the frequency setting registers." dbf_table = {1: 0, 2: 1, 4: 2, 8: 3, 16: 4} @@ -67,6 +70,7 @@ def _pack_freq_registers(ncount, frac, mod, dbf, old_data): reg4 |= (dbf_table.get(dbf, 0)) << 20 return struct.pack('>IIIIII', reg0, reg1, reg2, reg3, reg4, reg5) + def _unpack_freq_registers(data): "Do bit unpacking for the frequency setting registers." dbf_rev_table = {0: 1, 1: 2, 2: 4, 3: 8, 4: 16} @@ -77,6 +81,7 @@ def _unpack_freq_registers(data): dbf = dbf_rev_table.get((reg4 >> 20) & 0x07, 1) return ncount, frac, mod, dbf + class Synthesizer: """A simple interface to the Valon 500x synthesizer.""" def __init__(self, port, timeout=1.0): @@ -98,19 +103,19 @@ def get_frequency(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) ncount, frac, mod, dbf = _unpack_freq_registers(data) epdf = self._get_epdf(synth) return (ncount + float(frac) / mod) * epdf / dbf - def set_frequency(self, synth, freq, chan_spacing = 10.): + def set_frequency(self, synth, freq, chan_spacing=10.): """Sets the synthesizer to the desired frequency. - Sets to the closest possible frequency, depending on the channel spacing. - Range is determined by the minimum and maximum VCO frequency. + Sets to the closest possible frequency, depending on the channel + spacing. Range is determined by the minimum and maximum VCO frequency. @param synth : synthesizer this command affects (0 for 1, 8 for 2). @type synth : int @@ -146,10 +151,10 @@ def set_frequency(self, synth, freq, chan_spacing = 10.): try: self.conn.write(data) old_data = self.conn.read(24) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(old_data, checksum) + # _verify_checksum(old_data, checksum) data = struct.pack('>B24s', 0x00 | synth, _pack_freq_registers(ncount, frac, mod, dbf, old_data)) @@ -174,10 +179,10 @@ def get_reference(self): try: self.conn.write(data) data = self.conn.read(4) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) freq = struct.unpack('>I', data)[0] return freq @@ -219,10 +224,10 @@ def get_rf_level(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) _, _, _, _, reg4, _ = struct.unpack('>IIIIII', data) rfl = (reg4 >> 3) & 0x03 rf_level = rfl_table.get(rfl) @@ -240,12 +245,12 @@ def rf_disable(self, synth): self.conn.write(data) data = self.conn.read(24) checksum = self.conn.read(1) - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) - reg4 &= 0xffffffdf # RF Output power up - reg4 |= 1 << 9 # VCO power down + reg4 &= 0xffffffdf # RF Output power up + reg4 |= 1 << 9 # VCO power down data = struct.pack('>BIIIIII', 0x00 | synth, - reg0, reg1, reg2, reg3, reg4, reg5) + reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) self.conn.write(data + checksum) data = self.conn.read(1) @@ -265,12 +270,12 @@ def rf_enable(self, synth): self.conn.write(data) data = self.conn.read(24) checksum = self.conn.read(1) - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) - reg4 &= 0xfffff7ff # VCO power up - reg4 |= 1 << 5 # RF Output power up + reg4 &= 0xfffff7ff # VCO power up + reg4 |= 1 << 5 # RF Output power up data = struct.pack('>BIIIIII', 0x00 | synth, - reg0, reg1, reg2, reg3, reg4, reg5) + reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) self.conn.write(data + checksum) data = self.conn.read(1) @@ -304,12 +309,12 @@ def set_rf_level(self, synth, rf_level): checksum = self.conn.read(1) finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffe7 reg4 |= (rfl & 0x03) << 3 data = struct.pack('>BIIIIII', 0x00 | synth, - reg0, reg1, reg2, reg3, reg4, reg5) + reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) try: self.conn.write(data + checksum) @@ -364,10 +369,10 @@ def get_options(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) _, _, reg2, _, _, _ = struct.unpack('>IIIIII', data) low_spur = ((reg2 >> 30) & 1) & ((reg2 >> 29) & 1) double = (reg2 >> 25) & 1 @@ -375,8 +380,7 @@ def get_options(self, synth): divider = (reg2 >> 14) & 0x03ff return double, half, divider, low_spur - def set_options(self, synth, double = 0, half = 0, divider = 1, - low_spur = 0): + def set_options(self, synth, double=0, half=0, divider=1, low_spur=0): """Set options. double and half both True is same as both False. @@ -407,14 +411,14 @@ def set_options(self, synth, double = 0, half = 0, divider = 1, checksum = self.conn.read(1) finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg2 &= 0x9c003fff reg2 |= (((low_spur & 1) << 30) | ((low_spur & 1) << 29) | ((double & 1) << 25) | ((half & 1) << 24) | ((divider & 0x03ff) << 14)) data = struct.pack('>BIIIIII', 0x00 | synth, - reg0, reg1, reg2, reg3, reg4, reg5) + reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) try: self.conn.write(data + checksum) @@ -436,14 +440,14 @@ def get_ref_select(self): try: self.conn.write(data) data = self.conn.read(1) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) is_ext = struct.unpack('>B', data)[0] return is_ext & 1 - def set_ref_select(self, e_not_i = 1): + def set_ref_select(self, e_not_i=1): """Selects either internal or external reference clock. @param e_not_i : 1 (external) or 0 (internal); default 1 @@ -472,17 +476,18 @@ def get_vco_range(self, synth): @param synth : synthesizer base address @type synth : int - @return: Tuple: (lowest VCO output frequency, highest VCO output frequency) in MHz + @return: Tuple: (lowest VCO output frequency, highest VCO output + frequency) in MHz """ self.conn.open() data = struct.pack('>B', 0x83 | synth) try: self.conn.write(data) data = self.conn.read(4) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) return struct.unpack('>HH', data) def set_vco_range(self, synth, low, high): @@ -526,14 +531,14 @@ def get_phase_lock(self, synth): try: self.conn.write(data) data = self.conn.read(1) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) - if synth == SYNTH_A: - mask = 1 << 4 - else: - mask = 1 << 5 + # _verify_checksum(data, checksum) + if synth == SYNTH_A: + mask = 1 << 4 + else: + mask = 1 << 5 lock = struct.unpack('>B', data)[0] & mask return lock > 0 @@ -550,10 +555,10 @@ def get_label(self, synth): try: self.conn.write(data) data = self.conn.read(16) - checksum = self.conn.read(1) + checksum = self.conn.read(1) # noqa finally: self.conn.close() - #_verify_checksum(data, checksum) + # _verify_checksum(data, checksum) return data def set_label(self, synth, label): @@ -612,10 +617,10 @@ def _get_epdf(self, synth): """ reference = self.get_reference() / 1e6 double, half, divider, _ = self.get_options(synth) - if(double): + if (double): reference *= 2.0 - if(half): + if (half): reference /= 2.0 - if(divider > 1): + if (divider > 1): reference /= divider return reference From 2ebd10d1888b562c6106a19febff6094fe6ecaca Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 11:32:56 +0200 Subject: [PATCH 12/17] valon_synth.py: update __credits__ --- src/valon_synth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index ddfe84e..ef28c08 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -31,7 +31,7 @@ __author__ = "Patrick Brandt" __copyright__ = "Copyright 2011, Associated Universities, Inc." __credits__ = ["Patrick Brandt, Stewart Rumley, Steven Stark, Glenn Jones," - " Jack Hickish"] + " Jack Hickish, Deneys Maartens"] __license__ = "GPL" __version__ = "1.0" __maintainer__ = "Patrick Brandt" From b5deb9fa4be52c6c24c3ad8a809c5ed3856577db Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 13:25:05 +0200 Subject: [PATCH 13/17] valon_synth.py: use updated pyserial API --- src/valon_synth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index ef28c08..b5ee40d 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -87,8 +87,8 @@ class Synthesizer: def __init__(self, port, timeout=1.0): self.conn = serial.Serial(None, 9600, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE) - self.conn.setPort(port) - self.conn.setTimeout(timeout) + self.conn.port = port + self.conn.timeout = timeout def get_frequency(self, synth): """Returns the current output frequency for the selected synthesizer. From 083913f33e417b51b097c8f3fda912150c51ca33 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Mon, 20 Feb 2017 11:49:58 +0200 Subject: [PATCH 14/17] commtest.py: add --- example/commtest.py | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100755 example/commtest.py diff --git a/example/commtest.py b/example/commtest.py new file mode 100755 index 0000000..1e3a7d4 --- /dev/null +++ b/example/commtest.py @@ -0,0 +1,61 @@ +#! /usr/bin/env python + +from optparse import OptionParser +import time + +import valon_synth +from valon_synth import SYNTH_B + + +# Simple example of using the Valon Synth directly +def main(port): + print """ +Connect a Valon 5007 to a spectrum analyser -- a 20dB attenuator is used. +The Valon 5007 is specified to have a range of 137 MHz to 4400MHz. +""" + raw_input('Enter to connect to Valon') + + # MTS uses only one of the available synthesizers (currently SYNTH 2) + synth = valon_synth.Synthesizer(port, timeout=None) + + if synth.get_rf_level(SYNTH_B) != -4: + synth.set_rf_level(SYNTH_B, -4) + + # Set CW signal frequency + synth.set_frequency(SYNTH_B, freq=137, chan_spacing=1.) + print 'CW frequency set to %s MHz' % synth.get_frequency(SYNTH_B) + raw_input('Enter to continue') + + print 'Setting Valon to Low Spur Mode' + synth.set_options(SYNTH_B, low_spur=1) + raw_input('Enter to continue') + + print 'Settings Valon to Low Noise Mode' + synth.set_options(SYNTH_B, low_spur=0) + raw_input('Enter to continue') + + print 'Sweep over frequencies 137MHz to 1500MHz' + for freq_mhz in range(137, 1500, 20): + synth.set_frequency(SYNTH_B, freq=freq_mhz, chan_spacing=1.) + print 'CW frequency set to %s MHz' % synth.get_frequency(SYNTH_B) + raw_input('Enter to continue') + + print 'Sweep over frequencies 137MHz to 4400MHz' + raw_input('Enter to continue') + for freq_mhz in range(137, 4400, 100): + synth.set_frequency(SYNTH_B, freq=freq_mhz, chan_spacing=1.) + print 'CW frequency set to %s MHz' % synth.get_frequency(SYNTH_B) + time.sleep(1) + + +if __name__ == '__main__': + parser = OptionParser(version="%prog 0.1") + parser.add_option('-p', '--port', + action='store', + dest='tty', + default='/dev/ttyUSB0', + help="Set Serial Port, default is '%default'.") + (opts, _) = parser.parse_args() + main(opts.tty) + +# -fin- From 13692de3dfea9a4b9d4a66c8afe22c24e631fedb Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Wed, 22 Feb 2017 19:35:58 +0200 Subject: [PATCH 15/17] valon_synth.py: more comms error handling --- src/valon_synth.py | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/valon_synth.py b/src/valon_synth.py index b5ee40d..5b6f79b 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -152,8 +152,9 @@ def set_frequency(self, synth, freq, chan_spacing=10.): self.conn.write(data) old_data = self.conn.read(24) checksum = self.conn.read(1) # noqa - finally: + except: self.conn.close() + raise # _verify_checksum(old_data, checksum) data = struct.pack('>B24s', 0x00 | synth, _pack_freq_registers(ncount, frac, mod, @@ -242,9 +243,13 @@ def rf_disable(self, synth): """ self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + except: + self.conn.close() + raise # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffdf # RF Output power up @@ -252,9 +257,11 @@ def rf_disable(self, synth): data = struct.pack('>BIIIIII', 0x00 | synth, reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -267,9 +274,13 @@ def rf_enable(self, synth): """ self.conn.open() data = struct.pack('>B', 0x80 | synth) - self.conn.write(data) - data = self.conn.read(24) - checksum = self.conn.read(1) + try: + self.conn.write(data) + data = self.conn.read(24) + checksum = self.conn.read(1) + except: + self.conn.close() + raise # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xfffff7ff # VCO power up @@ -277,9 +288,11 @@ def rf_enable(self, synth): data = struct.pack('>BIIIIII', 0x00 | synth, reg0, reg1, reg2, reg3, reg4, reg5) checksum = _generate_checksum(data) - self.conn.write(data + checksum) - data = self.conn.read(1) - self.conn.close() + try: + self.conn.write(data + checksum) + data = self.conn.read(1) + finally: + self.conn.close() ack = struct.unpack('>B', data)[0] return ack == ACK @@ -307,8 +320,9 @@ def set_rf_level(self, synth, rf_level): self.conn.write(data) data = self.conn.read(24) checksum = self.conn.read(1) - finally: + except: self.conn.close() + raise # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffe7 @@ -409,8 +423,9 @@ def set_options(self, synth, double=0, half=0, divider=1, low_spur=0): self.conn.write(data) data = self.conn.read(24) checksum = self.conn.read(1) - finally: + except: self.conn.close() + raise # _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg2 &= 0x9c003fff From 7adda0fb1de90a3142ab41517fd90c82a2eef34c Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Wed, 22 Feb 2017 19:38:53 +0200 Subject: [PATCH 16/17] valon_synth.py: add option to verify checksums --- example/commtest.py | 2 +- src/valon_synth.py | 65 ++++++++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/example/commtest.py b/example/commtest.py index 1e3a7d4..2d43317 100755 --- a/example/commtest.py +++ b/example/commtest.py @@ -16,7 +16,7 @@ def main(port): raw_input('Enter to connect to Valon') # MTS uses only one of the available synthesizers (currently SYNTH 2) - synth = valon_synth.Synthesizer(port, timeout=None) + synth = valon_synth.Synthesizer(port, timeout=None, checksum=True) if synth.get_rf_level(SYNTH_B) != -4: synth.set_rf_level(SYNTH_B, -4) diff --git a/src/valon_synth.py b/src/valon_synth.py index 5b6f79b..6bf6dcb 100644 --- a/src/valon_synth.py +++ b/src/valon_synth.py @@ -55,7 +55,10 @@ def _generate_checksum(data): def _verify_checksum(data, checksum): "Verify a checksum for the data provided." - return (_generate_checksum(data) == checksum) + if _generate_checksum(data) != checksum: + print 'checksum failure' + return False + return True def _pack_freq_registers(ncount, frac, mod, dbf, old_data): @@ -84,11 +87,12 @@ def _unpack_freq_registers(data): class Synthesizer: """A simple interface to the Valon 500x synthesizer.""" - def __init__(self, port, timeout=1.0): + def __init__(self, port, timeout=1.0, checksum=False): self.conn = serial.Serial(None, 9600, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE) self.conn.port = port self.conn.timeout = timeout + self.do_checksum = checksum def get_frequency(self, synth): """Returns the current output frequency for the selected synthesizer. @@ -103,10 +107,11 @@ def get_frequency(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) ncount, frac, mod, dbf = _unpack_freq_registers(data) epdf = self._get_epdf(synth) return (ncount + float(frac) / mod) * epdf / dbf @@ -151,11 +156,12 @@ def set_frequency(self, synth, freq, chan_spacing=10.): try: self.conn.write(data) old_data = self.conn.read(24) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) except: self.conn.close() raise - # _verify_checksum(old_data, checksum) + if self.do_checksum: + _verify_checksum(old_data, checksum) data = struct.pack('>B24s', 0x00 | synth, _pack_freq_registers(ncount, frac, mod, dbf, old_data)) @@ -180,10 +186,11 @@ def get_reference(self): try: self.conn.write(data) data = self.conn.read(4) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) freq = struct.unpack('>I', data)[0] return freq @@ -225,10 +232,11 @@ def get_rf_level(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) _, _, _, _, reg4, _ = struct.unpack('>IIIIII', data) rfl = (reg4 >> 3) & 0x03 rf_level = rfl_table.get(rfl) @@ -250,7 +258,8 @@ def rf_disable(self, synth): except: self.conn.close() raise - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffdf # RF Output power up reg4 |= 1 << 9 # VCO power down @@ -281,7 +290,8 @@ def rf_enable(self, synth): except: self.conn.close() raise - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xfffff7ff # VCO power up reg4 |= 1 << 5 # RF Output power up @@ -323,7 +333,8 @@ def set_rf_level(self, synth, rf_level): except: self.conn.close() raise - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg4 &= 0xffffffe7 reg4 |= (rfl & 0x03) << 3 @@ -383,10 +394,11 @@ def get_options(self, synth): try: self.conn.write(data) data = self.conn.read(24) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) _, _, reg2, _, _, _ = struct.unpack('>IIIIII', data) low_spur = ((reg2 >> 30) & 1) & ((reg2 >> 29) & 1) double = (reg2 >> 25) & 1 @@ -426,7 +438,8 @@ def set_options(self, synth, double=0, half=0, divider=1, low_spur=0): except: self.conn.close() raise - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) reg0, reg1, reg2, reg3, reg4, reg5 = struct.unpack('>IIIIII', data) reg2 &= 0x9c003fff reg2 |= (((low_spur & 1) << 30) | ((low_spur & 1) << 29) | @@ -455,10 +468,11 @@ def get_ref_select(self): try: self.conn.write(data) data = self.conn.read(1) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) is_ext = struct.unpack('>B', data)[0] return is_ext & 1 @@ -499,10 +513,11 @@ def get_vco_range(self, synth): try: self.conn.write(data) data = self.conn.read(4) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) return struct.unpack('>HH', data) def set_vco_range(self, synth, low, high): @@ -546,10 +561,11 @@ def get_phase_lock(self, synth): try: self.conn.write(data) data = self.conn.read(1) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) if synth == SYNTH_A: mask = 1 << 4 else: @@ -570,10 +586,11 @@ def get_label(self, synth): try: self.conn.write(data) data = self.conn.read(16) - checksum = self.conn.read(1) # noqa + checksum = self.conn.read(1) finally: self.conn.close() - # _verify_checksum(data, checksum) + if self.do_checksum: + _verify_checksum(data, checksum) return data def set_label(self, synth, label): From 36a0defadf6251005ccbaa297508b606711effe8 Mon Sep 17 00:00:00 2001 From: "Deneys S. Maartens" Date: Tue, 28 Feb 2017 09:53:25 +0200 Subject: [PATCH 17/17] Add Python README file --- README-Python.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 ++ setup.py | 2 +- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 README-Python.md create mode 100644 requirements.txt diff --git a/README-Python.md b/README-Python.md new file mode 100644 index 0000000..0216de1 --- /dev/null +++ b/README-Python.md @@ -0,0 +1,52 @@ +# Valon Synth + +## Installation + +In order to use the Python code, it is necessary to build the C++ +library first: + + $ make + +This should create a `libValonSynth.so` shared object. + +The Python software can now be installed for development use. As a +first step, create a Python virtual environment. + + $ virtualenv venv + +Optionally, activate it; the steps below assumes that the virtual +environment has not been activated. + +Use the virtual environment to setup the package: + + $ ./venv/bin/pip install -r requirements.txt + +To be able to use the package, we also need to be able to import it. +Normally the source directory name matches the package name, but +unfortunately in this instance it doesn't. We create a symbolic link to +fudge it. + + $ ln -s src valon_synth + +## Communication checks + +We provide a example script that tests basic communications. It +requires knowledge of the (USB-connected) serial port the Valon is +connected to. In Linux, plug in both USB plugs on the Valon, and do + + $ dmesg + +The last lines in the log should be similar to the following: + + usb 5-1: FTDI USB Serial Device converter now attached to ttyUSB0 + +This indicates the port we are interested in is `/dev/ttyUSB0`, which +coincidentally is the default port in the communications test example +script. + +To run the communications check, simply do: + + $ ./venv/bin/python example/commtest.py --port /dev/ttyUSB0 + +Feel free to replace `/dev/ttyUSB0` in the command shown above with your +locally identified port. diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..de620ec --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# development requirements +--editable . diff --git a/setup.py b/setup.py index dc4ec10..e80f2c5 100644 --- a/setup.py +++ b/setup.py @@ -7,5 +7,5 @@ maintainer = 'NRAO', packages = ['valon_synth'], package_dir = {'valon_synth': 'src'}, - requires = ['pyserial'], + install_requires = ['pyserial'], )