Skip to content

Commit

Permalink
Added U2 bulk data transfer
Browse files Browse the repository at this point in the history
U2 now allows for writing and reading arbitrary amount of data.
  • Loading branch information
mtiggelman committed Mar 12, 2020
1 parent fc44031 commit 0455127
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 13 deletions.
31 changes: 27 additions & 4 deletions spirack/U2_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand All @@ -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
Expand All @@ -189,12 +189,35 @@ 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):
if np.isnan(self.active_mux):
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)
4 changes: 2 additions & 2 deletions spirack/chip_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -36,4 +36,4 @@
MCP320x_SPEED = 84 # 1MHz
BICPINS_SPEED = 84 # 1MHz
ADT7301_SPEED = 84 # 1MHz
CRYOMUX_SPEED = 0 # 1kHz
CRYOMUX_SPEED = 0 # 5kHz
105 changes: 99 additions & 6 deletions spirack/spi_rack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion spirack/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.2.1'
__version__ = '0.2.2'

0 comments on commit 0455127

Please sign in to comment.