peripherals

The pyripherals.peripherals subpackage contains a few base controllers and several specific controllers for different peripherals. The base controllers are used to reduce code repetition as many peripherals use common communication methods. Specific peripheral classes that use these communication methods are derived from the more general base classes.

Base Controllers

class pyripherals.peripherals.I2CController.I2CController(fpga, addr_pins, endpoints, i2c={'m_nDataStart': 7, 'm_pBuf': []})[source]

Class for controllers on the FPGA using I2C protocol.

I2C_MAX_TIMEOUT_MS

Maximum wait time until transmission timeout in milliseconds.

Type:

int

i2c

Dictionary of I2C memory buffer and data start location.

Type:

dict

fpga

FPGA instance this controller uses to communicate.

Type:

FPGA

endpoints

Endpoints on the FPGA this controller uses to communicate.

Type:

dict

classmethod create_chips(fpga, addr_pins, endpoints)[source]

Instantiate a number of new I2C chips.

The FPGA and endpoints will be the same for all instantiated chips.

Parameters:
  • fpga (FPGA) – The fpga instance for the chip to connect with.

  • addr_pins (list) – The list of addr_pins assigned to the new chips.

Returns:

A list of the newly instantiated chips in the same order addr_pins was given in.

Return type:

list

i2c_configure(preamble_length, starts, stops, preamble)[source]

Configure the buffer for the next transmission.

i2c_read_long(devAddr, regAddr, data_length, data_transfer='wire')[source]

Read data_length bytes from regAddr on devAddr.

Parameters:
  • devAddr (int) – 8 bit address (don’t set the read bit (LSB) since this is done in this function)

  • regAddr (int) – Written to device (this is a list and must be even if length 1)

  • data_length (int) – Number of bytes expected to receive

  • data_transfer (str) – The form of the data transfer. Either ‘wire’ and ‘pipe’. Defaults to ‘wire’.

Returns:

data or buf, e – The data or a bytearray and error code, depending on whether data_transfer was ‘wire’ or ‘pipe’.

Return type:

list or bytearray, int

i2c_receive(data_length, data_transfer='wire')[source]

Take in data from the SCL and SDA lines.

Parameters:
  • data_length (int) – Number of bytes expected to receive.

  • data_transfer (str) – The form of the data transfer. Either ‘wire’ and ‘pipe’. Defaults to ‘wire’.

Returns:

data or buf, e – The data or a bytearray and error code, depending on whether data_transfer was ‘wire’ or ‘pipe’.

Return type:

list or bytearray, int

i2c_transmit(data, data_length)[source]

Send data along the SCL and SDA lines.

i2c_write_long(devAddr, regAddr, data_length, data)[source]

Send a write command with given data to regAddr on devAddr.

regAddr must be given in a list.

reset_device()[source]

Reset the I2C controller using an OK TriggerIn.

class pyripherals.peripherals.SPIFifoDriven.SPIFifoDriven(fpga, endpoints, master_config, data_mux={'DDR': 0, 'DDR_norepeat': 3, 'ad7961_ch0': 4, 'ad7961_ch1': 5, 'ad7961_ch2': 6, 'ad7961_ch3': 7, 'ads8686_chA': 2, 'host': 1})[source]

Class for SPI controllers on the FPGA driven by a FIFO.

default_data_mux

Class attribute. Default data_mux dictionary.

Type:

dict

fpga

FPGA instance this controller uses to communicate.

Type:

FPGA

endpoints

Endpoints on the FPGA this controller uses to communicate.

Type:

dict

master_config

Value of the CTRL register in the Wishbone.

Type:

int

data_mux

Name to select value dictionary for source data MUX.

Type:

dict

current_data_mux

Name of the current MUX data source.

Type:

str

classmethod create_chips(fpga, number_of_chips, endpoints=None, master_config=None)[source]

Instantiate a number of new chips.

The number must be an integer greater than zero. The endpoints between each instance will be incremented. If the endpoints argument is left as None, then we will use copies of the endpoints_from_defines dictionary for the endpoints for each instance, and update that original dictionary when we increment the endpoints. This way, the endpoints there are ready for another instantiation if needed.

filter_downsample(operation='set')[source]

Set whether filter output data is downsampled

filter_select(operation='set')[source]

Set whether SPI data comes from filter (‘set’) or direct (‘clear’)

Direct comes from the spi_fifo_driven data.

filter_sum(operation='set')[source]

Set whether Cmd data is summed with filter output

set_clk_divider(divide_value)[source]

Set clock divider to configure rate of SPI updates.

Tupdate = Tclk * divide_value

set_ctrl_reg(reg_value)[source]

Configures the SPI Wishbone control register over the registerBridge.

HDL default is ctrlValue = 16’h3010 (initialized in the HDL)

set_data_mux(source, filter_data=False)[source]

Configure the MUX that routes data source to the SPI output.

Parameters:

source (str) – See SPIFifoDriven.data_mux dict for options and conversion.

set_spi_sclk_divide(divide_value=1)[source]

Configures the SPI Wishbone clock divider register over the registerBridge.

HDL default is 8’h13 (initialized in the HDL)

write(data)[source]

Host write 24 bits of data to the chip over SPI.

Extends I2CController

class pyripherals.peripherals.DAC53401.DAC53401(fpga, addr_pins, endpoints, i2c={'m_nDataStart': 7, 'm_pBuf': []})[source]

Class for the I2C DAC chip DAC53401.

Subclass of the I2CController class. Attributes and methods below are differences in this class from I2CController only.

ADDRESS_HEADER

7-bit device address with R/W bit space and 4 MSBs filled in specific to this chip. The rest is left as 0 to be filled in later.

Type:

int

registers

Name-Register pairs for the internal registers of the TCA9555 chip.

Type:

dict

addr_pins

3 LSBs of the 7-bit device address formed alongside the address header used to differentiate between different instances of the TCA9555 chip.

Type:

int

config_func(function_name)[source]

Configure the function generator.

‘triangle’: Triangle wave between MARGIN_HIGH code to MARGIN_LOW code

with slope defined by SLEW_RATE.

‘sawtooth_falling’: Saw-Tooth wave between MARGIN_HIGH code to

MARGIN_LOW code with slope defined by SLEW_RATE and immeidate falling edge.

‘sawtooth_rising’: Saw-Tooth wave between MARGIN_HIGH code to

MARGIN_LOW code with slope defined by SLEW_RATE and immeidate rising edge.

‘square’: Square wave between MARGIN_HIGH code to MARGIN_LOW code with

pulse high and low period defined by defined by SLEW_RATE.

config_margins(margin_high=None, margin_low=None)[source]

Configure margin high and low values.

config_rate(rate)[source]

Configure the rate to step through each bit.

config_step(step)[source]

Configure the number of bits to step through.

enable_internal_reference()[source]

Enable the DAC’s internal reference.

This is necessary to set the gain value.

get_gain()[source]

Return the DAC’s current output gain value.

get_id()[source]

Return the device ID and version ID as one integer.

lock()[source]

Lock the registers of the device so they cannot be changed.

power_down_10k()[source]

Power down the DAC output to 10K ohms.

power_down_high_impedance()[source]

Power down the DAC output to high impedance (default).

power_up()[source]

Power up the DAC output.

read(register_name='DAC_DATA')[source]

Return data from any register on the chip.

reset()[source]

Reset the chip using a software reset.

set_gain(gain)[source]

Set the DAC’s output gain value.

Gain can be set to 1.5x, 2x, 3x, or 4x the internal reference. Internal reference must be enabled.

start_func()[source]

Start function generation.

Waveform configured through config_func() and config_margins() functions.

stop_func()[source]

Stop function generation.

unlock()[source]

Unlock the registers of the device so they can be changed again.

write(data, register_name='DAC_DATA')[source]

Write data to any register on the chip.

write_voltage(voltage)[source]

Write a voltage output from the DAC.

class pyripherals.peripherals.TMF8801.TMF8801(fpga, addr_pins, endpoints, i2c={'m_nDataStart': 7, 'm_pBuf': []})[source]

Class for the Time-of-flight I2C device

Subclass of the I2CController class. Attributes and methods below are differences in this class from I2CController only.

ADDRESS

7-bit device address with R/W bit space

Type:

int

registers

Name-Register pairs for the internal registers of the chip.

Type:

dict

factory_calibration(filename=None)[source]

Perform factory calibration and return 14 bytes of data See AN000597 – Factor Calibration 8.1

Calibration Environment: Device has to be in the final (correct) optical stack Clear glass (no smudge on the glass) No target in front of the device within 40 cm (see datasheet) Dark room or low ambient light

get_id()[source]

Return the device ID and rev ID as one integer.

power_down_high_impedance()[source]

Power down the DAC output to high impedance (default).

read(register_name, number_of_bytes=None)[source]

Return data from any register on the chip.

read_data()[source]

For correctly updating of these registers by TMF8801, an I2C block read starting from address 0x1D until 0x27 shall be done. 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27

write(data, register_name)[source]

Write data to any register on the chip. first reads to enable writing of (just) bit-fields within the register

Extends SPIController

Extends SPIFifoDriven

class pyripherals.peripherals.AD5453.AD5453(fpga, master_config=12304, endpoints=None, data_mux={'DDR': 0, 'DDR_norepeat': 3, 'ad7961_ch0': 4, 'ad7961_ch1': 5, 'ad7961_ch2': 6, 'ad7961_ch3': 7, 'ads8686_chA': 2, 'host': 1})[source]
read_coeff_debug()[source]

Read two wire outs for coefficients a3 section1, scale 3 debug wires available for filters 0, 1

set_clk_rising_edge()[source]

Set the signals we write to use the rising edge of the clock.

Default is falling edge. To return to the falling edge, the chip requires a power cycle (turn it off and back on).

set_ctrl_reg(reg_value=12304)[source]

Configures the SPI Wishbone control register over the registerBridge.

reg_value=0x3010 sets CHAR_LEN=16, ASS, IE

Miscellaneous

class pyripherals.peripherals.DDR3.DDR3(fpga, endpoints=None, data_version='TIMESTAMPS')[source]

The DDR is divided into 2 buffers. Each buffer has an incoming and outgoing FIFO.

1st buffer:

  • Function generator like data that provides a data-stream to the DACs

  • Write from the host when DAC_WRITE_ENABLE is set (clear dac read and clear adc read and write)

  • Organized into groups of 16 bits to 8 channels

  • Read to the DACs with set_dac_read

  • 6 AD5453 (14 bits each)

  • 2 DAC80508 (16 bits each)

  • DAC80508 channel data in the MSBs of the AD5453 stream

  • FIFO: OpalKelly in -> out to DDR [32bits x 1024words = 4096 bytes]

  • FIFO: DDR in -> DAC data out [out: 256bits x 256 = 8192 bytes]

2nd buffer:

  • Buffering for ADC data (AD7961; ADS8686), DAC outgoing data, timestamps.

  • ADC data writes to the DDR set_adc_write()

  • ADC data in DDR can be read to the host with set_adc_read()

  • The DDR througput is sufficient for 1st buffer reading while reading and writing to the 2nd buffer

  • FIFO: OpalKelly in -> out to DDR [in: 32bits x 1024words = 4096 bytes]

  • FIFO: DDR in -> OpalKelly out [256bits x 128 = 4096 bytes] OpalKelly block size is half this.

Expected sequence of operations:

  1. At startup write pattern for DACs using write_channels() [set_dac_write(), clear_dac_write() are called within write_channels()]

  2. set_dac_read() # starts DAC data output to DACs via SPI and then set_adc_write() ADC data captured into DDR

  3. set_adc_read() # allows host to read PipeOut as PipeOut is continuously filled if emptied

ADC data ordering and saving:

  • deswizzle()

  • save_data()

DDR configuration bits:

  • DAC_WRITE_ENABLE

  • DAC_READ_ENABLE

  • ADC_WRITE_ENABLE

  • ADC_TRANSFER_ENABLE

adc_single()[source]

Set ADC read address to the ADC write address.

Emulates an immediate “trigger” of an oscilloscope.

clear_adc_debug()[source]

Clear the ADC debug bit.

DDR ADC data will be from the ADC.

clear_adc_read()[source]

Clear DDR / FIFO read enable DDR data from the ADCs out via a PipeOut.

clear_adc_write()[source]

Clear DDR / FIFOs write enable ADC data into DDR.

clear_adcs_connected()[source]

AD7961s are not connected to the FPGA so the DDR3 write enable signal is emulated by the global_timing module.

clear_dac_read()[source]

Clear DDR / FIFOs read enable. Stops DDR data from going to the DACs and ADC data into DDR

clear_dac_write()[source]

Clear DDR / FIFOs write enable into DDR via Pipe.

static closest_frequency(freq)[source]

Determine closest frequency so the waveform evenly divides into the length of the DDR3

Parameters:

freq (float) – Desired frequency

Returns:

new_frequency – The closest possible frequency

Return type:

float

data_to_names(chan_data, bitfile_version=None)[source]

Put deswizzled data into dictionaries with names that match with the data sources. Complete twos complement conversion where necessary. Check timestamps for skips. Check the constant values for errors.

This supports 2 versions of the FPGA code: ‘ADC_NO_TIMESTAMPS’: DDR data is only the fast ADC. AD7961 ‘TIMESTAMPS’: DDR data is numerous. AD7961, AD5453 out, ADS8686, timestamps, readcheck

Parameters:
  • chan_data (dict of np.arrays) – data from reading DDR (minimally processed into 2 byte containers)

  • bitfile_version (int) – The bitfile version that the .h5 file which held chan_data was created with. Defaults to the bitfile version of the FPGA

Returns:

  • adc_data (dict) – fast adc data (double format @ 5 MSPS)

  • timestamp (np.array) – timestamps

  • dac_data (dict) – DAC output data

  • ads (dict) – ADS8686 ADC data (double format @ 1 MSPS)

  • ads_seq_cnt (dict) – two keys 0, 1. Each value is an array of sequence counts (counts from 0 to 23) the first key will have 0,2,4,6, … , 22 (or similar) the second key will have 1,3,5, …, 23 (or similar)

  • error (boolean) –

    if True the constant read values were wrong

    or the timestamp steps are not all the same

deswizzle(d, convert_twos=True)[source]

Reorder DDR data to match the ADC channels. Shift MSBytes up by 8 and combine with LSBytes. Swap channels to match ADC channel numbering.

Parameters:
  • d (array) – array of bytes.

  • convert_twos (Boolean) – if true converts data to signed

Returns:

chan_data – dictionary of data arrays (keys are channel numbers)

Return type:

dict

fifo_status()[source]

Check the empty, full, and count status of the DDR interfacing FIFOs

Returns:

fifo_status – dictionary of fifo status (‘EMPTY’, ‘FULL’, ‘ADC_DATA_COUNT’) for ‘IN’, ‘OUT’, and channels 1, 2

Return type:

dict

static make_flat_voltage(amplitude)[source]

Return a constant unit16 array of value amplitude.

Array length based on the sample_size parameter. The conversion from float or int voltage to int digital (binary) code should take place BEFORE this function.

Parameters:

amplitude (int) – Digital (binary) value of the flat voltage

Returns:

amplitude – to be assigned to DDR data array

Return type:

numpy.ndarray

static make_ramp(start, stop, step, actual_length=True)[source]

Create a ramp signal to write to the DDR.

The conversion from float or int voltage to int digital (binary) code should take place BEFORE this function.

Parameters:
  • start (int) – Digital (binary) value to start the ramp at

  • stop (int) – Digital (binary) value to stop the ramp at

  • step (int) – Digital (binary) code to step by

Returns:

ddr_seq – to be assigned to DDR data array

Return type:

numpy.ndarray

static make_sine_wave(amplitude, frequency, offset=8192, actual_frequency=True)[source]

Return a sine-wave array for writing to DDR.

The conversion from float or int voltage to int digital (binary) code should take place BEFORE this function.

Parameters:
  • amplitude (int) – Digital (binary) value of the sine wave.

  • frequency (float) – Desired frequency in Hz.

  • offset (int) – Digital (binary) value offset.

  • actual_frequency (bool) – Decide whether closest frequency that fits an integer number of periods is used.

Returns:

  • ddr_seq (numpy.ndarray) – to be assigned to DDR data array

  • frequency (float) – actual frequency after closest_frequency

static make_step(low, high, length, actual_length=True, duty=50)[source]

Return a step signal (square wave) to write to the DDR.

The conversion from float or int voltage to int digital (binary) code should take place BEFORE this function.

Parameters:
  • low (int) – Digital (binary) code for the low value of the step.

  • high (int) – Digital (binary) code for the high value of the step.

  • length (TODO add type for length) – TODO add description for length

  • actual_length (bool) – TODO add description for actual_length

  • duty (int or float) – Duty cycle percentage. Enter as a percentage [0.0, 100.0].

Returns:

ddr_seq – to be assigned to DDR data array

Return type:

numpy.ndarray

print_fifo_status(fifo_status)[source]

Print the FIFO status dictionary.

Parameters:

fifo_status (dict) – Dictionary of fifo status.

read_adc(blk_multiples=2048)[source]

read DDR data into a numpy buffer of bytes

Parameters:

blk_multiples (int) – total size of the read is blk_multiples * block_size

Returns:

  • d (bytearray) – data as uint32

  • bytes_read_error (int) – bytes read or error code

read_adc_block(sample_size=None, source='ADC', DEBUG_PRINT=False)[source]

Read ADC (and other) DDR data. Block size must be a power of two from 16 to 16384 will automatically perform multiple transfers to complete the full LENGTH. The length must be an integer multiple of 16 for USB3.0 and the length must be an Integer multiple of Block Size. see https://docs.opalkelly.com/fpsdk/frontpanel-api/ section 3.3.1

Parameters:
  • sample_size (int) – Length of read in bytes. If none uses DDR parameter ‘sample_size.’

  • source (str) – FIFO output buffer to read. Either ‘ADC’ or ‘FG’. ‘FG’ just reads back what is written for DACs (as function generator) so not so useful.

Returns:

  • data_buf (byearray) – adc data read as a bytearray

  • read_cnt (int) – The count (or error code) read from the OpalKelly interface

repeat_setup()[source]

Setup for reading new data without writing to the DDR again.

reset_fifo(name)[source]

Reset FIFO interfaces to DDR .

reset_mig_interface()[source]

Reset user interface to the MIG (memory interface generator). Resets the DDR address pointers for read/write of both buffers (does not reset the MIG controller).

save_data(data_dir, file_name, num_repeats=4, blk_multiples=40, append=False)[source]

read and save DDR data to an hdf file

Parameters:
  • data_dir (string) – directory for data

  • file_name (string) – filename to save data (does not append extension).

  • num_repeats (int) – total data read is 2048 bytes * num_repeats * blk_multiples

  • blk_multiples (int) – number of blocks read by adc_read. adc_read is a single OpalKelly API call

Returns:

new_data – The new data saved in the h5 file.

Return type:

np.ndarray

set_adc_dac_simultaneous()[source]

Set DDR / FIFOs read enable. Enables DDR data going to the DACs and ADC data into DDR

set_adc_debug()[source]

Set the ADC debug bit.

That bit multiplexes a counter to ADC channel 0 and bits 47:0 of the DAC data to ADC channels 1,2,3.

Not supported in all versions of the FPGA design.

set_adc_read()[source]

Set DDR / FIFO read enable DDR data from the ADCs out via a PipeOut.

set_adc_write()[source]

Set DDR / FIFOs write enable ADC data into DDR.

set_adcs_connected()[source]

Set that AD7961s are connected to the FPGA so that DDR3 write enable comes from the AD7961.v module.

set_dac_read()[source]

Set DDR / FIFOs read enable. Enables DDR data going to the DACs and ADC data into DDR

set_dac_write()[source]

Set DDR / FIFOs write enable into DDR via Pipe.

set_index(factor, factor2=None)[source]

No longer used. Index (the DDR address that wraps-around to 0). This is now fixed to improve timing performance.

write_buf(buf, set_ddr_read=True)[source]

Write a bytearray to the DDR3.

Parameters:

buf (bytearray) – bytearray to write to the DDR

Returns:

  • block_pipe_return (int) – length of the buffer written to the DDR (or error code if unsuccessful)

  • speed_MBs (float) – speed of the write in MB/s

write_channels(set_ddr_read=True)[source]

Write the channels as striped data to the DDR.

write_setup(data_driven_clock=True)[source]

Set up DDR for writing.

class pyripherals.peripherals.AD7961.AD7961(fpga, endpoints=None)[source]

An interface to the AD7961 ADC Passed the FPGA object Allows for multiple channels read status flags (FIFO full, empty, count and PLL) configures FPGA internal resets configures chip specific and global enables Formats data returned from the wire out

static create_chips(fpga, number_of_chips, endpoints=None)[source]

Instantiate a given number of new chips.

We increment the endpoints between each instantiation as well. The number must be greater than 0. If the endpoints argument is left as None, then we will use copies of the endpoints_from_defines dictionary for the endpoints for each instance, and update that original dictionary when we increment the endpoints. This way, the endpoints there are ready for another instantiation if needed.

get_fifo_status()[source]

Get fullness status of the FIFO.

get_pll_status()[source]

Get status of the phase locked loop.

get_status()[source]

Get AD796x status: pll lock, FIFO full, half-full, and empty

Returns: dictionary of status

get_timing_pll_status()[source]

Get status of the timing of the phase locked loop.

power_down_adc()[source]

Power down single channel of the ADC.

Fails if the global enables are 010 for LVDS test patterns

power_down_all()[source]

Power down all channels of the ADC.

power_down_fpga()[source]

Power down the FPGA controller through WireIn.

reset_pll()[source]

Reset the phase locked loop.

reset_trig()[source]

Reset the FPGA controller for the ADC.

Common to synchronize timing (resets ad7961_timing module AND the ads8686 timing)

reset_wire(value)[source]

Set the value of the wire to reset the FPGA controller for the ADC.

Uses the Opal Kelly WireIn (the trigger can’t hold the reset).

Parameters:

value (int) – value = 1 is reset value = 0 releases reset

set_enables(value=0, global_enables=True)[source]

Set the EN0 specific to this channel (LSB in values).

Optionally also modify the global enables (all channels).

setup(reset_pll=False)[source]
  1. put ADC controller into reset

  2. optionally reset the ADC PLL and wait for lock

    (only need to reset PLL on first channel)

  3. power up adc

  4. release ADC controller reset

  5. reset fifo

  6. check and return status (PLL and fifo)

test_pattern()[source]

Enable PRBS test pattern on the LVDS interface.