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
- 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
- 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
- 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_select(operation='set')[source]
Set whether SPI data comes from filter (‘set’) or direct (‘clear’)
Direct comes from the spi_fifo_driven data.
- 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.
Extends I2CController
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
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:
At startup write pattern for DACs using write_channels() [set_dac_write(), clear_dac_write() are called within write_channels()]
set_dac_read() # starts DAC data output to DACs via SPI and then set_adc_write() ADC data captured into DDR
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_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
- 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
- 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_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_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.
- 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_status()[source]
Get AD796x status: pll lock, FIFO full, half-full, and empty
Returns: dictionary of status
- power_down_adc()[source]
Power down single channel of the ADC.
Fails if the global enables are 010 for LVDS test patterns
- 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).