diff --git a/spirack/U2_module.py b/spirack/U2_module.py index d51f021..d7a25dc 100644 --- a/spirack/U2_module.py +++ b/spirack/U2_module.py @@ -149,7 +149,7 @@ def select_mux(self, mux): mux (int): select mux 1 to the maximum number of switches based on the amount of shift registers """ if mux not in range(1, (self.no_shift_reg*8)+1): - raise ValueError('Mux {} not allowed. Possible values are 1 to {}}'.format(mux, self.no_shift_reg*8)) + raise ValueError('Mux {} not allowed. Possible values are 1 to {}'.format(mux, self.no_shift_reg*8)) self.active_mux = mux self.active_mux_array = [] @@ -175,7 +175,7 @@ def select_multiple_mux(self, mux): """ for m in mux: if m not in range(1,8*self.no_shift_reg+1): - raise ValueError('Mux {} not allowed. Possible values are 1 to {}'.format(mux, num_shift_registers*8)) + raise ValueError('Mux {} not allowed. Possible values are 1 to {}'.format(mux, self.no_shift_reg*8)) self.active_mux_array = mux self.active_mux = np.NaN @@ -189,8 +189,6 @@ def select_multiple_mux(self, mux): for mux_component in range(self.no_shift_reg): s_data.insert(0, (data >> (mux_component*8))&0xFF) - #print('data: {}\ndata bin: {}\ns_data: {}'.format(data,bin(data),s_data)) - self.spi_rack.write_data(self.module, 7, CRYOMUX_MODE, CRYOMUX_SPEED, s_data) def get_active_mux(self): @@ -198,3 +196,28 @@ def get_active_mux(self): return self.active_mux_array else: return self.active_mux + + def write_bulk_data(self, data, SPI_mode=CRYOMUX_MODE): + """Write bulk data to the shift registers/cryo mux + + Allows the writing of an arbitrary amount of data. + + Args: + data (int list): list of bytes to be written, values from 0-255 + SPI_mode (int: 0-3): SPI mode to use. Defaults to CRYOMUX_MODE. + """ + self.spi_rack.write_bulk_data(self.module, 7, SPI_mode, CRYOMUX_SPEED, data) + + def read_bulk_data(self, data, SPI_mode=CRYOMUX_MODE): + """Read bulk data from the shift registers + + Allows the reading of an arbitrary amount of data. + + Args: + data (int list): list of bytes to be written, values from 0-255 + SPI_mode (int: 0-3): SPI mode to use. Defaults to CRYOMUX_MODE. + + Returns: + Bytes received from shift register (int list) + """ + return self.spi_rack.read_bulk_data(self.module, 7, SPI_mode, CRYOMUX_SPEED, data) diff --git a/spirack/chip_mode.py b/spirack/chip_mode.py index 4102e56..01ce472 100644 --- a/spirack/chip_mode.py +++ b/spirack/chip_mode.py @@ -5,7 +5,7 @@ The speeds are set by a divisor: 84MHz/value (range 14..255), these are the numbers in the list below. Zero is a special value which sets the SPI speed to -1kHz (software SPI) +5kHz (software SPI) """ # ADC AD7175_MODE = 3 @@ -36,4 +36,4 @@ MCP320x_SPEED = 84 # 1MHz BICPINS_SPEED = 84 # 1MHz ADT7301_SPEED = 84 # 1MHz -CRYOMUX_SPEED = 0 # 1kHz +CRYOMUX_SPEED = 0 # 5kHz diff --git a/spirack/spi_rack.py b/spirack/spi_rack.py index 6e07142..af9d15b 100644 --- a/spirack/spi_rack.py +++ b/spirack/spi_rack.py @@ -3,6 +3,7 @@ import threading import serial import logging +import numpy as np from .chip_mode import MCP320x_MODE, MCP320x_SPEED, ADT7301_SPEED, ADT7301_MODE @@ -129,6 +130,7 @@ def read_data(self, module, chip, SPI_mode, SPI_speed, data): module: number of the module to send data to (int) chip: chip in module to send data to (int) SPI_mode: SPI mode of the chip to be activated (int) + SPI_speed: SPI clock speed of the chip to be activated (int) data: data to be send to chip for reading (bytearray) Returns: @@ -143,14 +145,105 @@ def read_data(self, module, chip, SPI_mode, SPI_speed, data): self.write(data) r_data = self.read(read_length) - if len(r_data) < read_length: - print("Received fewer bytes than expected") - logger.warning("SPI Rack: received fewer bytes than expected. Received: %d bytes. Expected %d bytes.", len(r_data), read_length) + if len(r_data) < read_length: + print("Received fewer bytes than expected") + logger.warning("SPI Rack: received fewer bytes than expected. Received: %d bytes. Expected %d bytes.", len(r_data), read_length) + + if version_info[0] < 3: + return [ord(c) for c in r_data] + + return r_data + + def write_bulk_data(self, module, chip, SPI_mode, SPI_speed, data): + """Writes bulk data to the selected module/chip combination + + This functiona allows for the writing of large amount of data. The control + of the chip select line is done by the PC, which makes it uncertain. The data + is split in chunks of 60 bytes, as this is the maximum amount that can be send + in one transfer to the controller. This also adds a slight uncertainty in the timing + between the packets of 60 bytes. Use with caution. + + Args: + module (int:0-15) : number of the module to send data to (int) + chip (int:0-7) : chip in module to send data to (int) + SPI_mode (int:0-3) : SPI mode of the chip to be activated (int) + SPI_speed (int:0, 6-84) : SPI clock speed of the chip to be activated (int) + data (bytearray) : array of data to be send (bytearray) + """ + with self._tlock: + if(self.active_module != module or self.active_chip != chip + or self.active_speed != SPI_speed): + self._set_active(module, chip, SPI_mode, SPI_speed) + + # Write bulk data in chunks of 60 bytes (maximum for buffer size in controller) + data = np.asarray(data, dtype=np.uint8) + split_data = np.split(data, np.arange(60, len(data), 60)) + + # Set chip select low + s_data = bytearray([ord('m'), ord('s')]) + self.write(s_data) + + for group in split_data: + s_data = bytearray([ord('m'), ord('w')]) + group.tobytes() + self.write(s_data) + + # Set chip select high + s_data = bytearray([ord('m'), ord('d')]) + self.write(s_data) + + def read_bulk_data(self, module, chip, SPI_mode, SPI_speed, data): + """Reads bulk data from the selected module/chip combination + + This functiona allows for the reading of large amount of data. The control + of the chip select line is done by the PC, which makes it uncertain. The data + is split in chunks of 60 bytes, as this is the maximum amount that can be send + in one transfer to the controller. This also adds a slight uncertainty in the timing + between the packets of 60 bytes. Use with caution. + + Args: + module (int:0-15) : number of the module to send data to (int) + chip (int:0-7) : chip in module to send data to (int) + SPI_mode (int:0-3) : SPI mode of the chip to be activated (int) + SPI_speed (int:0, 6-84) : SPI clock speed of the chip to be activated (int) + data (bytearray) : array of data to be send (bytearray) + + Returns: + Bytes received from module/chip (int list) + """ + with self._tlock: + if(self.active_module != module or self.active_chip != chip + or self.active_speed != SPI_speed): + self._set_active(module, chip, SPI_mode, SPI_speed) + + read_length = len(data) + read_data = [] + + # Write bulk data in chunks of 60 bytes (maximum for buffer size in controller) + data = np.asarray(data, dtype=np.uint8) + split_data = np.split(data, np.arange(60, len(data), 60)) + + # Set chip select low + s_data = bytearray([ord('m'), ord('s')]) + self.write(s_data) + + for group in split_data: + s_data = bytearray([ord('m'), ord('r')]) + group.tobytes() + self.write(s_data) + r_data = self.read(len(group)) + read_data += r_data + + # Set chip select high + s_data = bytearray([ord('m'), ord('d')]) + self.write(s_data) - if version_info[0] < 3: - return [ord(c) for c in r_data] + if len(read_data) < read_length: + print("Received fewer bytes than expected") + logger.warning("SPI Rack: received fewer bytes than expected. Received: %d bytes. Expected %d bytes.", len(r_data), read_length) - return r_data + if version_info[0] < 3: + return [ord(c) for c in read_data] + + return read_data def trigger_now(self): """ Sends trigger signal immediately diff --git a/spirack/version.py b/spirack/version.py index fc79d63..020ed73 100644 --- a/spirack/version.py +++ b/spirack/version.py @@ -1 +1 @@ -__version__ = '0.2.1' +__version__ = '0.2.2'