Skip to content

Commit

Permalink
Python: added examples for syncing 2 M2KS
Browse files Browse the repository at this point in the history
added example for analog in interface
added example for digital in interface

Signed-off-by: Cristina Suteu <[email protected]>
  • Loading branch information
cristina-suteu committed Jan 27, 2021
1 parent 4ccbbab commit 9d1c9bf
Show file tree
Hide file tree
Showing 2 changed files with 294 additions and 0 deletions.
152 changes: 152 additions & 0 deletions bindings/python/examples/analogin_sync_2m2ks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#
# Copyright (c) 2019 Analog Devices Inc.
#
# This file is part of libm2k
# (see http://www.github.com/analogdevicesinc/libm2k).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Requirements: 2x ADALM2000
#
# This example assumes the following connections:
# W1 (1st M2K) -> 1+ (1st M2K) -> 1+ (2nd M2K)
# DIO0 (1st M2K) -> 2+ (1st M2K)
# TO (1st M2K) -> TI (2nd M2K) -> 2+ (2nd M2K)
# GND (1st M2K) -> GND (2nd M2K)
# The application will generate a square wave on W1 of the first M2K. The signal is read on Analog Input 1 of both M2Ks.
# The acquisition on the 1st M2K is triggered by toggling the DIO0 pin. This is forwarded to the TI pin (2nd M2K) via
# the TO pin(1st M2K). This results in a synchronised acquisition on both devices. The trigger can be observed on
# Analog Input 2 of both modules.

import libm2k
import matplotlib.pyplot as plt
import time
import numpy as np

DIGITAL_CH = 0

BUFFER_SIZE = 800000
AMPLITUDE = 4
SAMPLES_PER_PERIOD = 256
PLOTTED_SAMPLES = BUFFER_SIZE
OFFSET = 5

sampling_frequency_in = 10000000
sampling_frequency_out = 750000


def generate_clock_signal():
buffer = []
for i in range(256):
buffer.append(1)
for i in range(256):
buffer.append(0)

for i in range(4):
buffer.extend(buffer)
buffer = buffer * AMPLITUDE
print(buffer)
return buffer


ctx = libm2k.m2kOpen("replace with uri for 1st M2K")
ctx2 = libm2k.m2kOpen("replace with uri for 2nd M2K")

if ctx is None:
print("Connection Error: No ADALM2000 device available/connected to your PC.")
exit(1)

if ctx2 is None:
print("Connection Error: No second ADALM2000 device available/connected to your PC.")
exit(1)

ctx.calibrateADC()
ctx.calibrateDAC()
ctx2.calibrateADC()
ctx2.calibrateDAC()

# Configure 1st context
ain = ctx.getAnalogIn()
aout = ctx.getAnalogOut()
dig = ctx.getDigital()
trig = ain.getTrigger()

if trig.hasExternalTriggerOut():
trig.setAnalogExternalOutSelect(libm2k.SELECT_ANALOG_IN) # Forward Analog trigger on TO pin

ain.enableChannel(0, True)
ain.enableChannel(1, True)
ain.setSampleRate(sampling_frequency_in)
ain.setRange(0, libm2k.PLUS_MINUS_2_5V)
ain.setRange(1, libm2k.PLUS_MINUS_2_5V)
dig.setDirection(DIGITAL_CH, libm2k.DIO_OUTPUT)
dig.enableChannel(DIGITAL_CH, True)
dig.setValueRaw(DIGITAL_CH, libm2k.LOW)

# Configure 2nd context
ain2 = ctx2.getAnalogIn()
dig2 = ctx2.getDigital()
trig2 = dig2.getTrigger()
ain2.enableChannel(0, True)
ain2.enableChannel(1, True)
ain2.setSampleRate(sampling_frequency_in)
ain2.setRange(0, libm2k.PLUS_MINUS_2_5V)
ain2.setRange(1, libm2k.PLUS_MINUS_2_5V)

# Trigger settings for 1st context
trig.setAnalogSource(1) # Channel 2 as source
trig.setAnalogCondition(1, libm2k.RISING_EDGE_ANALOG)
trig.setAnalogLevel(1, 0.5) # Set trigger level at 0.5
trig.setAnalogDelay(0) # Trigger is centered
trig.setAnalogMode(1, libm2k.ANALOG) # Trigger condition specified only by analog trigger

# Trigger settings for 2nd context
trig2.setAnalogMode(0, libm2k.EXTERNAL) # Trigger condition specified only by external trigger (TI)
trig2.setAnalogSource(0)
trig2.setAnalogExternalCondition(0, libm2k.RISING_EDGE_ANALOG)
trig2.setAnalogLevel(0, 0.5) # Set trigger level at 0.5
trig2.setAnalogDelay(0) # Trigger is centered

# Configure analog out 1st context
aout.setSampleRate(0, sampling_frequency_out)
aout.setSampleRate(1, sampling_frequency_out)
aout.enableChannel(0, True)
aout.enableChannel(1, True)
aout.setCyclic(False)

ain.startAcquisition(BUFFER_SIZE)
ain2.startAcquisition(BUFFER_SIZE)

# Toggle trigger pin
dig.setValueRaw(DIGITAL_CH, libm2k.LOW)
dig.setValueRaw(DIGITAL_CH, libm2k.HIGH)

buffer = generate_clock_signal()
aout.push([buffer, buffer])

data = ain.getSamples(BUFFER_SIZE)
data2 = ain2.getSamples(BUFFER_SIZE)

# Plot routine
plt.plot(np.array(data[0]), label="Clock Signal(1st M2K)")
plt.plot(np.array(data2[0]) + OFFSET, label="Clock Signal(2nd M2K)")
plt.plot(np.array(data[1]) + 2 * OFFSET, label="Trigger Signal(1st M2K, DIO0)")
plt.plot(np.array(data2[1]) + 3 * OFFSET, label="Trigger Signal(2nd M2K, TI)")
plt.legend(loc="upper right")
plt.grid(True)
plt.show()
time.sleep(0.1)
aout.stop()
libm2k.contextClose(ctx)
libm2k.contextClose(ctx2)
142 changes: 142 additions & 0 deletions bindings/python/examples/digitalin_sync_2m2ks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#
# Copyright (c) 2019 Analog Devices Inc.
#
# This file is part of libm2k
# (see http://www.github.com/analogdevicesinc/libm2k).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Requirements: 2x ADALM2000
#
# This example assumes the following connections:
# DIO7 (1st M2K) -> DIO1 (1st M2K) -> DIO1 (2nd M2K)
# TO (1st M2K) -> TI (2nd M2K) -> DIO0 (2nd M2K)
#
# The application will generate a square wave on DIO7 of the first M2K. The signal is read on DIO1 pin of both modules.
# The acquisition on the 1st M2K is triggered by toggling the DIO0 pin. This is forwarded to the TI pin (2nd M2K) via
# the TO pin(1st M2K). This results in a synchronised acquisition on both devices.

import libm2k
import matplotlib.pyplot as plt
import time
import numpy as np

BUFFER_SIZE = 80000

DIGITAL_CH_TRIG = 0
DIGITAL_CH_READ = 1
DIGITAL_CH_PUSH = 7
SAMPLES_PER_PERIOD = 512
OFFSET = 5

sampling_frequency_in = 10000000
sampling_frequency_out = 750000


def generate_clock_signal(digital, channel, sampling_frequency):
digital.setSampleRateOut(sampling_frequency)
duty = SAMPLES_PER_PERIOD / 2 # 50%
signal = np.arange(SAMPLES_PER_PERIOD) < duty
buffer = list(map(lambda s: int(s) << channel, signal))
for i in range(2):
buffer.extend(buffer)
print(buffer)
return buffer


ctx = libm2k.m2kOpen("replace with uri for 1st M2K")
ctx2 = libm2k.m2kOpen("replace with uri for 2nd M2K")
if ctx is None:
print("Connection Error: No ADALM2000 device available/connected to your PC.")
exit(1)

if ctx2 is None:
print("Connection Error: No second ADALM2000 device available/connected to your PC.")
exit(1)

ctx.calibrateADC()
ctx.calibrateDAC()
ctx2.calibrateADC()
ctx2.calibrateDAC()

# Configure 1st M2K context
dig = ctx.getDigital()
dig.setDirection(DIGITAL_CH_TRIG, libm2k.DIO_OUTPUT) # DIO pin which the digital interface
dig.enableChannel(DIGITAL_CH_TRIG, False)
dig.setValueRaw(DIGITAL_CH_TRIG, libm2k.LOW)
dig.setDirection(DIGITAL_CH_READ, libm2k.DIO_INPUT) # DIO pin on which the clock signal is read
dig.enableChannel(DIGITAL_CH_READ, False)
dig.setDirection(DIGITAL_CH_PUSH, libm2k.DIO_OUTPUT) # DIO pin on which the clock signal is generated
dig.enableChannel(DIGITAL_CH_PUSH, True)
dig.setValueRaw(DIGITAL_CH_PUSH, libm2k.LOW)

# Configure trigger for 1st M2K context
trig = dig.getTrigger()
trig.reset()
trig.setDigitalDelay(0) # Trigger is centered
trig.setDigitalSource(libm2k.SRC_NONE) # Events on DigitalIn conditioned by internal trigger structure
trig.setDigitalCondition(DIGITAL_CH_TRIG, libm2k.RISING_EDGE_DIGITAL) # Trigger condition
if trig.hasExternalTriggerOut():
trig.setAnalogExternalOutSelect(libm2k.SELECT_DIGITAL_IN) # Forward the digital trigger on TO pin

# Configure 2nd M2K context
dig2 = ctx2.getDigital()
dig2.setDirection(DIGITAL_CH_TRIG, libm2k.DIO_INPUT) # DIO pin on which the trigger signal is read
dig2.enableChannel(DIGITAL_CH_TRIG, False)
dig2.setDirection(DIGITAL_CH_READ, libm2k.DIO_INPUT) # DIO pin on which the clock signal is read
dig2.enableChannel(DIGITAL_CH_READ, False)

# Configure trigger for 2nd M2K context
trig2 = dig2.getTrigger()
trig2.reset()
trig2.setDigitalDelay(0) # Trigger is centered
trig2.setDigitalSource(libm2k.SRC_TRIGGER_IN) # Trigger events on TI trigger the DigitalIn interface
trig2.setDigitalExternalCondition(libm2k.RISING_EDGE_DIGITAL) # Trigger condition

# Create and push buffer
buffer = generate_clock_signal(dig, DIGITAL_CH_PUSH, sampling_frequency_out)
dig.setCyclic(True)
dig.push(buffer)

dig.setSampleRateIn(sampling_frequency_in)
dig2.setSampleRateIn(sampling_frequency_in)

dig.startAcquisition(BUFFER_SIZE)
dig2.startAcquisition(BUFFER_SIZE)

# Toggle trigger pin
dig.setValueRaw(DIGITAL_CH_TRIG, libm2k.LOW)
dig.setValueRaw(DIGITAL_CH_TRIG, libm2k.HIGH)
dig.setValueRaw(DIGITAL_CH_TRIG, libm2k.LOW)

data = dig.getSamples(BUFFER_SIZE)
data2 = dig2.getSamples(BUFFER_SIZE)

# Extract data
digital_data_dio0 = list(map(lambda s: (((0x0001 << DIGITAL_CH_TRIG) & int(s)) >> DIGITAL_CH_TRIG) + 1.2, data))
digital_data_dio1 = list(map(lambda s: ((0x0001 << DIGITAL_CH_READ) & int(s)) >> DIGITAL_CH_READ, data))
digital_data2_dio0 = list(map(lambda s: (((0x0001 << DIGITAL_CH_TRIG) & int(s)) >> DIGITAL_CH_TRIG) + 1.2, data2))
digital_data2_dio1 = list(map(lambda s: ((0x0001 << DIGITAL_CH_READ) & int(s)) >> DIGITAL_CH_READ, data2))

# Plot routine
plt.plot(np.array(digital_data_dio0), label="Trigger Signal(1st M2K, DIO0)")
plt.plot(np.array(digital_data2_dio0) + OFFSET, label="Trigger Signal(2nd M2K, TI)")
plt.plot(np.array(digital_data_dio1) + 2 * OFFSET, label="Clock Signal(1st M2K)")
plt.plot(np.array(digital_data2_dio1) + 3 * OFFSET, label="Clock Signal(2nd M2K)")
plt.legend(loc="upper right")
plt.grid(True)
plt.show()
time.sleep(0.1)
libm2k.contextClose(ctx)
libm2k.contextClose(ctx2)

0 comments on commit 9d1c9bf

Please sign in to comment.