Skip to content

Commit

Permalink
Fix calibration. Fix trigger.
Browse files Browse the repository at this point in the history
  • Loading branch information
n.danilyuk committed Dec 14, 2021
1 parent ec3ebaa commit cde6ebb
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 42 deletions.
2 changes: 1 addition & 1 deletion examples/lg_counter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"\n",
"# set output amplitude, offset and enable it\n",
"lg.enable = 0xffff # all pins have outputs enabled (for both output values 0/1)\n",
"lg.mode = 0x0000 # all bits come from ASG, none are constants\n",
"lg.mask = 0x0000 # all bits come from ASG, none are constants\n",
"lg.value = 0x0000 # the constant pin values are irrelevant since they are not used\n",
"\n",
"# reset, start and trigger generator to get the first burst\n",
Expand Down
77 changes: 66 additions & 11 deletions redpitaya/drv/clb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@


class clb(uio):
_filters_dafault = { 1 : (0x7D93, 0x437C7, 0x2666,0xd9999a),
20: (0x4C5F, 0x2F38B, 0x2666,0xd9999a)}
channels_dac = range(2)
channels_adc = range(2)

_MAGIC = 0xAABBCCDD
_MAGIC2 = 0xDDCCBBAA
_eeprom_device = "/sys/bus/i2c/devices/0-0050/eeprom"
_eeprom_offset_user = 0x0008
_eeprom_offset_factory = 0x1c08
Expand All @@ -25,7 +28,11 @@ class _clb_t(Structure):
class _clb_range_t(Structure):
class _clb_channel_t(Structure):
_fields_ = [('gain' , c_float), # multiplication
('offset', c_float)] # summation
('offset', c_float),
('fil_aa', c_uint32),
('fil_bb', c_uint32),
('fil_pp', c_uint32),
('fil_kk', c_uint32)] # summation
_fields_ = [('lo', _clb_channel_t), # 1.0V range
('hi', _clb_channel_t)] # 20.0V range
_fields_ = [('dac', _clb_range_t._clb_channel_t * 2), # generator
Expand All @@ -39,7 +46,9 @@ class _eeprom_t(Structure):
('dac_gain' , c_uint32 * 2),
('dac_offset' , c_int32 * 2),
('magic' , c_uint32 ),
('adc_hi_offset', c_int32 * 2)]
('adc_hi_offset', c_int32 * 2),
('low_filt' , c_uint32 * 8),
('hi_filt' , c_uint32 * 8)]

def __init__(self, uio: str = '/dev/uio/clb'):
super().__init__(uio)
Expand All @@ -49,6 +58,9 @@ def __init__(self, uio: str = '/dev/uio/clb'):
self.adc = [self.ADC(self.regset.adc[ch]) for ch in self.channels_adc]

def __del__(self):
del(self.regset)
del(self.dac)
del(self.adc)
super().__del__()

def default(self):
Expand Down Expand Up @@ -170,26 +182,46 @@ def eeprom_parse(self, eeprom_struct):

# convert EEPROM values into local float values
for ch in self.channels_adc:
if (eeprom_struct.magic == self._MAGIC):
if (eeprom_struct.magic == self._MAGIC or eeprom_struct.magic == self._MAGIC2):
clb_struct.adc[ch].lo.gain = self.FullScaleToVoltage(eeprom_struct.adc_lo_gain [ch]) / 20.0
clb_struct.adc[ch].hi.gain = self.FullScaleToVoltage(eeprom_struct.adc_hi_gain [ch])
else:
clb_struct.adc[ch].lo.gain = self.FullScaleToVoltage(eeprom_struct.adc_hi_gain [ch])
clb_struct.adc[ch].hi.gain = self.FullScaleToVoltage(eeprom_struct.adc_lo_gain [ch]) / 20.0
clb_struct.adc[ch].lo.offset = eeprom_struct.adc_lo_offset[ch] / (2**13-1)
if (eeprom_struct.magic == self._MAGIC):
clb_struct.adc[ch].hi.offset = eeprom_struct.adc_hi_offset[ch] / (2**13-1) * 20.0
clb_struct.adc[ch].lo.offset = (eeprom_struct.adc_lo_offset[ch] * 4) #/ (2**13-1) * 0
if (eeprom_struct.magic == self._MAGIC or eeprom_struct.magic == self._MAGIC2):
clb_struct.adc[ch].hi.offset = (eeprom_struct.adc_hi_offset[ch] * 4) # / (2**13-1) * 20.0
else:
clb_struct.adc[ch].hi.offset = clb_struct.adc[ch].lo.offset
clb_struct.adc[ch].hi.offset = clb_struct.adc[ch].lo.offset
for ch in self.channels_dac:
clb_struct.dac[ch].gain = self.FullScaleToVoltage (eeprom_struct.dac_gain [ch])
clb_struct.dac[ch].offset = eeprom_struct.dac_offset [ch] / (2**13-1)
clb_struct.dac[ch].gain = 1 / self.FullScaleToVoltage (eeprom_struct.dac_gain [ch])
clb_struct.dac[ch].offset = (eeprom_struct.dac_offset [ch] * 4) # / (2**13-1)

# missing magic number means a deprecated EEPROM structure was still not updated
if (eeprom_struct.magic != self._MAGIC):
if (eeprom_struct.magic != self._MAGIC and eeprom_struct.magic != self._MAGIC2):
for ch in self.channels_adc:
clb_struct.adc[ch].hi.offset = clb_struct.adc[ch].lo.offset

if (eeprom_struct.magic == self._MAGIC2):
for ch in self.channels_adc:
clb_struct.adc[ch].lo.fil_aa = eeprom_struct.low_filt[ch * 4]
clb_struct.adc[ch].lo.fil_bb = eeprom_struct.low_filt[ch * 4 + 1]
clb_struct.adc[ch].lo.fil_pp = eeprom_struct.low_filt[ch * 4 + 2]
clb_struct.adc[ch].lo.fil_kk = eeprom_struct.low_filt[ch * 4 + 3]
clb_struct.adc[ch].hi.fil_aa = eeprom_struct.hi_filt[ch * 4]
clb_struct.adc[ch].hi.fil_bb = eeprom_struct.hi_filt[ch * 4 + 1]
clb_struct.adc[ch].hi.fil_pp = eeprom_struct.hi_filt[ch * 4 + 2]
clb_struct.adc[ch].hi.fil_kk = eeprom_struct.hi_filt[ch * 4 + 3]
else:
for ch in self.channels_adc:
clb_struct.adc[ch].lo.fil_aa = self._filters_dafault[1][0]
clb_struct.adc[ch].lo.fil_bb = self._filters_dafault[1][1]
clb_struct.adc[ch].lo.fil_pp = self._filters_dafault[1][2]
clb_struct.adc[ch].lo.fil_kk = self._filters_dafault[1][3]
clb_struct.adc[ch].hi.fil_aa = self._filters_dafault[20][0]
clb_struct.adc[ch].hi.fil_bb = self._filters_dafault[20][1]
clb_struct.adc[ch].hi.fil_pp = self._filters_dafault[20][2]
clb_struct.adc[ch].hi.fil_kk = self._filters_dafault[20][3]

return clb_struct

def calib_show (self, clb_struct):
Expand All @@ -198,10 +230,33 @@ def calib_show (self, clb_struct):
print('adc[{}].hi.gain = {}'.format(ch, clb_struct.adc[ch].hi.gain))
print('adc[{}].lo.offset = {}'.format(ch, clb_struct.adc[ch].lo.offset))
print('adc[{}].hi.offset = {}'.format(ch, clb_struct.adc[ch].hi.offset))
print('adc[{}].lo.filter_aa = {}'.format(ch, clb_struct.adc[ch].lo.fil_aa))
print('adc[{}].lo.filter_bb = {}'.format(ch, clb_struct.adc[ch].lo.fil_bb))
print('adc[{}].lo.filter_pp = {}'.format(ch, clb_struct.adc[ch].lo.fil_pp))
print('adc[{}].lo.filter_kk = {}'.format(ch, clb_struct.adc[ch].lo.fil_kk))
print('adc[{}].hi.filter_aa = {}'.format(ch, clb_struct.adc[ch].hi.fil_aa))
print('adc[{}].hi.filter_bb = {}'.format(ch, clb_struct.adc[ch].hi.fil_bb))
print('adc[{}].hi.filter_pp = {}'.format(ch, clb_struct.adc[ch].hi.fil_pp))
print('adc[{}].hi.filter_kk = {}'.format(ch, clb_struct.adc[ch].hi.fil_kk))
for ch in self.channels_dac:
print('dac[{}].gain = {}'.format(ch, clb_struct.dac[ch].gain))
print('dac[{}].offset = {}'.format(ch, clb_struct.dac[ch].offset))

def calib_dac_apply (self, clb_struct):
for ch in self.channels_dac:
self.dac[ch].gain = clb_struct.dac[ch].gain
self.dac[ch].offset = clb_struct.dac[ch].offset

def calib_adc_apply (self, clb_struct, ch: int, input_range: float):
if (input_range == 1):
self.adc[ch].gain = clb_struct.adc[ch].lo.gain
self.adc[ch].offset = clb_struct.adc[ch].lo.offset
elif (input_range == 20):
self.adc[ch].gain = clb_struct.adc[ch].hi.gain
self.adc[ch].offset = clb_struct.adc[ch].hi.offset
else:
raise ValueError("ADC range can be one of [ 1, 20 ].")

def calib_apply (self, clb_struct, adc_range = ['lo', 'lo']):
for ch in self.channels_adc:
if (adc_range[ch] == 'lo'):
Expand Down
24 changes: 10 additions & 14 deletions redpitaya/drv/lg_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class lg_out (object):
"""Logic generator output control.
+----------------+----------------+-------------+----------------+-------------+-------------------------------+
| ``cfg_oen[0]`` | ``cfg_oen[1]`` | ``cfg_mod`` | ``cfg_val`` | **output** | **output** |
| ``cfg_oen[0]`` | ``cfg_oen[1]`` | ``cfg_msk`` | ``cfg_val`` | **output** | **output** |
| out enable 0 | out enable 1 | out mask | value/polarity | **enable** | **equation** |
+================+================+=============+================+=============+===============================+
| 0 | 0 | x | x | Hi-Z | ``z`` |
Expand All @@ -27,22 +27,22 @@ class lg_out (object):

class _regset_t (Structure):
_fields_ = [('cfg_oen', c_uint32 *2), # output enable [0,1]
('cfg_mod', c_uint32 ), # mask
('cfg_msk', c_uint32 ), # mask
('cfg_val', c_uint32 )] # value/polarity

def default(self):
"""Set registers into default (power-up) state."""
self.regset.out.cfg_oen[0] = 0
self.regset.out.cfg_oen[1] = 0
self.regset.out.cfg_mod = 0
self.regset.out.cfg_msk = 0
self.regset.out.cfg_val = 0

def show_regset(self):
"""Print FPGA module register set for debugging purposes."""
print(
"cfg_oen[0] = 0x{reg:08x} = {reg:10d} # output enable 0\n".format(reg=self.regset.out.cfg_oen[0]) +
"cfg_oen[1] = 0x{reg:08x} = {reg:10d} # output enable 1\n".format(reg=self.regset.out.cfg_oen[1]) +
"cfg_mod = 0x{reg:08x} = {reg:10d} # output mask \n".format(reg=self.regset.out.cfg_mod) +
"cfg_msk = 0x{reg:08x} = {reg:10d} # output mask \n".format(reg=self.regset.out.cfg_msk) +
"cfg_val = 0x{reg:08x} = {reg:10d} # value/polarity \n".format(reg=self.regset.out.cfg_val)
)

Expand All @@ -59,17 +59,13 @@ def enable(self, value: tuple):
self.regset.out.cfg_oen[1] = value[1]

@property
def mode(self) -> int:
"""Output mode.
Each bit controls one of the output signals:
0 - output data comes from ASG
1 - output data comes from cfg_val register
"""
return self.regset.out.cfg_mod
def mask(self) -> int:
"""Output mask."""
return self.regset.out.cfg_msk

@mode.setter
def mode(self, value: int):
self.regset.out.cfg_mod = value
@mask.setter
def mask(self, value: int):
self.regset.out.cfg_msk = value

@property
def value(self) -> int:
Expand Down
28 changes: 14 additions & 14 deletions redpitaya/drv/osc_trg.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,52 @@ class osc_trg(object):
_edges = {'pos': 0, 'neg': 1}

class _regset_t(Structure):
_fields_ = [('cfg_low', c_int32), # negative level
('cfg_upp', c_int32), # positive level
_fields_ = [('cfg_neg', c_int32), # negative level
('cfg_pos', c_int32), # positive level
('cfg_edg', c_uint32)] # edge (0-pos, 1-neg)

def default(self):
"""Set registers into default (power-up) state."""
self.regset.trg.cfg_low = 0
self.regset.trg.cfg_upp = 0
self.regset.trg.cfg_neg = 0
self.regset.trg.cfg_pos = 0
self.regset.trg.cfg_edg = 0

def show_regset(self):
"""Print FPGA module register set for debugging purposes."""
print(
"cfg_low = 0x{reg:08x} = {reg:10d} # lower level \n".format(reg=self.regset.trg.cfg_low) +
"cfg_upp = 0x{reg:08x} = {reg:10d} # upper level \n".format(reg=self.regset.trg.cfg_upp) +
"cfg_neg = 0x{reg:08x} = {reg:10d} # negative level \n".format(reg=self.regset.trg.cfg_neg) +
"cfg_pos = 0x{reg:08x} = {reg:10d} # positive level \n".format(reg=self.regset.trg.cfg_pos) +
"cfg_edg = 0x{reg:08x} = {reg:10d} # edge (0-pos, 1-neg)\n".format(reg=self.regset.trg.cfg_edg)
)

@property
def level(self) -> float:
"""Trigger level in vols, or a pair of values [lower, upper] if a hysteresis is desired."""
"""Trigger level in vols, or a pair of values [neg, pos] if a hysteresis is desired."""
scale = self.input_range / self._DWr
return [self.regset.trg.cfg_low * scale, self.regset.trg.cfg_upp * scale]
return [self.regset.trg.cfg_neg * scale, self.regset.trg.cfg_pos * scale]

@level.setter
def level(self, value: tuple):
scale = self._DWr / self.input_range
if isinstance(value, float):
value = [value]*2
if (-1.0 <= value[0] <= 1.0):
self.regset.trg.cfg_low = int(value[0] * scale)
self.regset.trg.cfg_neg = int(value[0] * scale)
else:
raise ValueError("Trigger lower level should be inside [{},{}]".format(self.input_range))
raise ValueError("Trigger negative level should be inside [{},{}]".format(self.input_range))
if (-1.0 <= value[1] <= 1.0):
self.regset.trg.cfg_upp = int(value[1] * scale)
self.regset.trg.cfg_pos = int(value[1] * scale)
else:
raise ValueError("Trigger upper level should be inside [{},{}]".format(self.input_range))
raise ValueError("Trigger positive level should be inside [{},{}]".format(self.input_range))

@property
def edge(self) -> str:
"""Trigger edge/slope as a string 'pos'/'neg'"""
"""Trigger edge as a string 'pos'/'neg'"""
return ('pos', 'neg')[self.regset.trg.cfg_edg]

@edge.setter
def edge(self, value: str):
if (value in self._edges):
self.regset.trg.cfg_edg = self._edges[value]
else:
raise ValueError("Trigger edge/slope should be one of {}".format(list(self._edges.keys())))
raise ValueError("Trigger edge should be one of {}".format(list(self._edges.keys())))
2 changes: 1 addition & 1 deletion redpitaya/drv/uio.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def _uio_mmap(self, uio_map: _uio_map):
return uio_mmap

def __del__(self):
print('UIO __del__ was activated.')
# print('UIO __del__ was activated.')
# close memory mappings
for uio_mmap in self.uio_mmaps:
uio_mmap.close()
Expand Down
20 changes: 19 additions & 1 deletion redpitaya/overlay/mercury.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __init__(self, port, pin, direction="preserve"):
class analog_in():
channels = {0: 'vaux8', 1: 'vaux0', 2: 'vaux1', 3: 'vaux9'}
ctx = iio.Context()
dev = ctx.devices[3]
dev = ctx.devices[0]
# resistor divider
resdiv = 4.99 / (30.0 + 4.99)

Expand Down Expand Up @@ -106,6 +106,11 @@ class clb(clb):

class gen(gen):
def __init__(self, index: int):
self.calib = clb()
self.eeprom_user = self.calib.eeprom_read()
self.calib_user = self.calib.eeprom_parse(self.eeprom_user)
self.calib.calib_dac_apply(self.calib_user)
del(self.calib)
if index in range(mercury._MNG):
super().__init__(index=index)
self.sync_src = mercury.sync_src['gen'+str(index)]
Expand All @@ -114,10 +119,23 @@ def __init__(self, index: int):

class osc(osc):
def __init__(self, index: int, input_range: float):
self.calib = clb()
self.eeprom_user = self.calib.eeprom_read()
self.calib_user = self.calib.eeprom_parse(self.eeprom_user)
self.calib.calib_adc_apply(self.calib_user,index,input_range)
#self.calib.calib_show(self.calib_user)
del(self.calib)
if index in range(mercury._MNO):
super().__init__(index=index, input_range=input_range)
self.sync_src = mercury.sync_src['osc'+str(index)]
self.trig_src = mercury.trig_src['osc'+str(index)]
if (input_range == 1.0):
fil_cof = self.calib_user.adc[index].lo
self.filter_coeficients = (fil_cof.fil_aa,fil_cof.fil_bb,fil_cof.fil_kk,fil_cof.fil_pp)
else:
fil_cof = self.calib_user.adc[index].hi
self.filter_coeficients = (fil_cof.fil_aa,fil_cof.fil_bb,fil_cof.fil_kk,fil_cof.fil_pp)
# self.show_regset()
else:
raise ValueError("Oscilloscope index should be one of {}".format(range(mercury._MNO)))

Expand Down

0 comments on commit cde6ebb

Please sign in to comment.