|
|
'''
|
|
|
Created on Feb 15, 2016
|
|
|
|
|
|
@author: Miguel Urco
|
|
|
'''
|
|
|
import struct
|
|
|
import string
|
|
|
|
|
|
DDS_NBITS = 48
|
|
|
|
|
|
FILE_STRUCTURE = """Phase Adjust Register 1
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Phase Adjust Register 2
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Frequency Tuning Word 1
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Frequency Tuning Word 2
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Delta Frequency Word
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Update Clock
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Ramp Rate Clock
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Control Register
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Output Shaped Keying I
|
|
|
Multiplier
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Output Shaped Keying Q
|
|
|
Multiplier
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
Output Shaped Keying
|
|
|
Ramp Rate
|
|
|
-----------------------
|
|
|
00000000
|
|
|
-----------------------
|
|
|
QDAC
|
|
|
-----------------------
|
|
|
00000000
|
|
|
00000000
|
|
|
-----------------------
|
|
|
CLOCK INPUT
|
|
|
-----------------------
|
|
|
10.00000000"""
|
|
|
|
|
|
def freq_to_binary(freq, mclock):
|
|
|
|
|
|
if not mclock:
|
|
|
return None
|
|
|
|
|
|
try:
|
|
|
binary = int((float(freq)/mclock)*(2**DDS_NBITS))
|
|
|
except:
|
|
|
return 0
|
|
|
|
|
|
return binary
|
|
|
|
|
|
def binary_to_freq(binary, mclock):
|
|
|
|
|
|
if not mclock:
|
|
|
return None
|
|
|
|
|
|
try:
|
|
|
freq = (float(binary)/(2**DDS_NBITS))*mclock
|
|
|
except:
|
|
|
return 0
|
|
|
|
|
|
return freq
|
|
|
|
|
|
def phase_to_binary(phase):
|
|
|
|
|
|
try:
|
|
|
binary = int(float(phase)*8192/180.0)
|
|
|
except:
|
|
|
return 0
|
|
|
|
|
|
return binary
|
|
|
|
|
|
def binary_to_phase(binary):
|
|
|
|
|
|
try:
|
|
|
phase = float(binary)*180.0/8192
|
|
|
except:
|
|
|
return 0
|
|
|
|
|
|
return phase
|
|
|
|
|
|
def __fill_dds_dict(parms):
|
|
|
|
|
|
my_dict = {'clock' : None,
|
|
|
'multiplier' : 1,
|
|
|
'frequencyA' : 0,
|
|
|
'frequencyB' : 0,
|
|
|
'frequencyA_Mhz' : 0,
|
|
|
'frequencyB_Mhz' : 0,
|
|
|
'phaseA_degress' : 0,
|
|
|
'phaseB_degress' : 0,
|
|
|
'modulation' : 0,
|
|
|
'amplitudeI' : 0,
|
|
|
'amplitudeQ' : 0,
|
|
|
'amplitude_enabled' : 0,
|
|
|
'delta_frequency' : 0,
|
|
|
'update_clock' : 0,
|
|
|
'ramp_rate_clock' : 0,
|
|
|
'amplitude_ramp_rate' : 0,
|
|
|
'qdac' : 0
|
|
|
}
|
|
|
|
|
|
my_dict.update(parms)
|
|
|
my_dict['phaseA'] = phase_to_binary(my_dict['phaseA_degrees'])
|
|
|
my_dict['phaseB'] = phase_to_binary(my_dict['phaseB_degrees'])
|
|
|
|
|
|
pll_range = 0
|
|
|
if my_dict['clock'] >= 200:
|
|
|
pll_range = 1
|
|
|
|
|
|
pll_bypass = 0
|
|
|
if my_dict['multiplier'] < 4:
|
|
|
pll_bypass = 1
|
|
|
|
|
|
control_register = (1 << 28) + \
|
|
|
(pll_range << 22) + (pll_bypass << 21) + \
|
|
|
(my_dict['multiplier'] << 16) + \
|
|
|
(my_dict['modulation'] << 9) + \
|
|
|
(my_dict['amplitude_enabled'] << 5)
|
|
|
|
|
|
my_dict['control_register'] = control_register
|
|
|
|
|
|
return my_dict
|
|
|
|
|
|
def dds_str_to_dict(registers, clock=None):
|
|
|
|
|
|
"""
|
|
|
Output:
|
|
|
parms : Dictionary with keys
|
|
|
multiplier :
|
|
|
frequencyA :
|
|
|
frequencyB :
|
|
|
frequencyA_Mhz :
|
|
|
frequencyB_Mhz :
|
|
|
modulation :
|
|
|
phaseA_degrees :
|
|
|
phaseB_degrees :
|
|
|
amplitudeI :
|
|
|
amplitudeQ :
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not registers:
|
|
|
return {}
|
|
|
|
|
|
if len(registers) != 0x28:
|
|
|
return {}
|
|
|
|
|
|
phaseA = struct.unpack('>H', registers[0x0:0x2])[0]
|
|
|
phaseB = struct.unpack('>H', registers[0x2:0x4])[0]
|
|
|
|
|
|
frequencyA = struct.unpack('>Q', '\x00\x00' + registers[0x04:0x0A])[0]
|
|
|
frequencyB = struct.unpack('>Q', '\x00\x00' + registers[0x0A:0x10])[0]
|
|
|
|
|
|
delta_frequency = struct.unpack('>Q', '\x00\x00' + registers[0x10:0x16])[0]
|
|
|
|
|
|
update_clock = struct.unpack('>I', registers[0x16:0x1A])[0]
|
|
|
|
|
|
ramp_rate_clock = struct.unpack('>I', '\x00' + registers[0x1A:0x1D])[0]
|
|
|
|
|
|
control_register = struct.unpack('>I', registers[0x1D:0x21])[0]
|
|
|
|
|
|
amplitudeI = struct.unpack('>H', registers[0x21:0x23])[0]
|
|
|
amplitudeQ = struct.unpack('>H', registers[0x23:0x25])[0]
|
|
|
|
|
|
amp_ramp_rate = ord(registers[0x25])
|
|
|
|
|
|
qdac = struct.unpack('>H', registers[0x26:0x28])[0]
|
|
|
|
|
|
multiplier = (control_register & 0x001F0000) >> 16
|
|
|
modulation = (control_register & 0x00000E00) >> 9
|
|
|
amplitude_enabled = (control_register & 0x00000020) >> 5
|
|
|
|
|
|
frequencyA_Mhz = None
|
|
|
frequencyB_Mhz = None
|
|
|
|
|
|
if clock:
|
|
|
mclock = clock*multiplier
|
|
|
frequencyA_Mhz = binary_to_freq(frequencyA, mclock)
|
|
|
frequencyB_Mhz = binary_to_freq(frequencyB, mclock)
|
|
|
|
|
|
parms = {'clock' : clock,
|
|
|
'multiplier' : multiplier,
|
|
|
'frequencyA' : frequencyA,
|
|
|
'frequencyB' : frequencyB,
|
|
|
'frequencyA_Mhz' : frequencyA_Mhz,
|
|
|
'frequencyB_Mhz' : frequencyB_Mhz,
|
|
|
'phaseA' : phaseA,
|
|
|
'phaseB' : phaseB,
|
|
|
'phaseA_degrees' : binary_to_phase(phaseA),
|
|
|
'phaseB_degrees' : binary_to_phase(phaseB),
|
|
|
'modulation' : modulation,
|
|
|
'amplitudeI' : amplitudeI,
|
|
|
'amplitudeQ' : amplitudeQ,
|
|
|
'amplitude_enabled' : amplitude_enabled,
|
|
|
'delta_frequency' : delta_frequency,
|
|
|
'update_clock' : update_clock,
|
|
|
'ramp_rate_clock' : ramp_rate_clock,
|
|
|
'amp_ramp_rate' : amp_ramp_rate,
|
|
|
'qdac' : qdac
|
|
|
}
|
|
|
|
|
|
return parms
|
|
|
|
|
|
def dict_to_dds_str(parms):
|
|
|
"""
|
|
|
Input:
|
|
|
parms : Dictionary with keys
|
|
|
multiplier : 4 to 20
|
|
|
frequencyA : 0 to (2**48-1) equivalent to: 0 - "Master clock"
|
|
|
frequencyB : 0 to (2**48-1) equivalent to: 0 - "Master clock"
|
|
|
modulation : 0 to 3
|
|
|
phaseA_degrees : 0 - 360 degrees
|
|
|
phaseB_degrees : 0 - 360 degrees
|
|
|
amplitudeI : 0 to (2**12-1) equivalent to: 0 - 100%
|
|
|
amplitudeQ : 0 to (2**12-1) equivalent to: 0 - 100%
|
|
|
"""
|
|
|
|
|
|
my_dict = __fill_dds_dict(parms)
|
|
|
|
|
|
registers = ""
|
|
|
|
|
|
registers += struct.pack(">H", my_dict['phaseA'])
|
|
|
registers += struct.pack(">H", my_dict['phaseB'])
|
|
|
|
|
|
registers += struct.pack(">Q", my_dict['frequencyA'])[2:]
|
|
|
registers += struct.pack(">Q", my_dict['frequencyB'])[2:]
|
|
|
|
|
|
registers += struct.pack(">Q", my_dict['delta_frequency'])[2:]
|
|
|
|
|
|
registers += struct.pack(">I", my_dict['update_clock'])
|
|
|
|
|
|
registers += struct.pack(">I", my_dict['ramp_rate_clock'])[1:]
|
|
|
|
|
|
registers += struct.pack(">I", my_dict['control_register'])
|
|
|
|
|
|
registers += struct.pack(">H", my_dict['amplitudeI'])
|
|
|
|
|
|
registers += struct.pack(">H", my_dict['amplitudeQ'])
|
|
|
|
|
|
registers += chr(my_dict['amplitude_ramp_rate'])
|
|
|
|
|
|
registers += struct.pack(">H", my_dict['qdac'])
|
|
|
|
|
|
return registers
|
|
|
|
|
|
def text_to_dict(lines):
|
|
|
|
|
|
registers = ""
|
|
|
registers_v2 = []
|
|
|
|
|
|
for this_line in lines:
|
|
|
this_line = str.strip(this_line)
|
|
|
|
|
|
if str.isalpha(this_line):
|
|
|
continue
|
|
|
|
|
|
if not str.isdigit(this_line):
|
|
|
try:
|
|
|
value = float(this_line)
|
|
|
except:
|
|
|
continue
|
|
|
|
|
|
registers_v2.append(value)
|
|
|
continue
|
|
|
|
|
|
if len(this_line) != 8:
|
|
|
continue
|
|
|
|
|
|
registers += chr(string.atoi(this_line,2))
|
|
|
|
|
|
mclock = None
|
|
|
if len(registers_v2) > 0:
|
|
|
mclock = registers_v2[0]
|
|
|
|
|
|
my_dict = dds_str_to_dict(registers, mclock)
|
|
|
|
|
|
return my_dict
|
|
|
|
|
|
def dict_to_text(parms):
|
|
|
"""
|
|
|
It creates formatted DDS text using dictionary values.
|
|
|
"""
|
|
|
my_dict = __fill_dds_dict(parms)
|
|
|
|
|
|
lines = FILE_STRUCTURE.split('\n')
|
|
|
|
|
|
cad = '{0:016b}'.format(my_dict['phaseA'])
|
|
|
lines[2] = cad[0:8]
|
|
|
lines[3] = cad[8:16]
|
|
|
|
|
|
cad = '{0:016b}'.format(my_dict['phaseB'])
|
|
|
lines[7] = cad[0:8]
|
|
|
lines[8] = cad[8:16]
|
|
|
|
|
|
cad = '{0:048b}'.format(my_dict['frequencyA'])
|
|
|
lines[12] = cad[0:8]
|
|
|
lines[13] = cad[8:16]
|
|
|
lines[14] = cad[16:24]
|
|
|
lines[15] = cad[24:32]
|
|
|
lines[16] = cad[32:40]
|
|
|
lines[17] = cad[40:48]
|
|
|
|
|
|
cad = '{0:048b}'.format(my_dict['frequencyB'])
|
|
|
lines[21] = cad[0:8]
|
|
|
lines[22] = cad[8:16]
|
|
|
lines[23] = cad[16:24]
|
|
|
lines[24] = cad[24:32]
|
|
|
lines[25] = cad[32:40]
|
|
|
lines[26] = cad[40:48]
|
|
|
|
|
|
cad = '{0:048b}'.format(my_dict['delta_frequency'])
|
|
|
lines[30] = cad[0:8]
|
|
|
lines[31] = cad[8:16]
|
|
|
lines[32] = cad[16:24]
|
|
|
lines[33] = cad[24:32]
|
|
|
lines[34] = cad[32:40]
|
|
|
lines[35] = cad[40:48]
|
|
|
|
|
|
cad = '{0:032b}'.format(my_dict['update_clock'])
|
|
|
lines[39] = cad[0:8]
|
|
|
lines[40] = cad[8:16]
|
|
|
lines[41] = cad[16:24]
|
|
|
lines[42] = cad[24:32]
|
|
|
|
|
|
cad = '{0:024b}'.format(my_dict['ramp_rate_clock'])
|
|
|
lines[46] = cad[0:8]
|
|
|
lines[47] = cad[8:16]
|
|
|
lines[48] = cad[16:24]
|
|
|
|
|
|
cad = '{0:032b}'.format(my_dict['control_register'])
|
|
|
lines[52] = cad[0:8]
|
|
|
lines[53] = cad[8:16]
|
|
|
lines[54] = cad[16:24]
|
|
|
lines[55] = cad[24:32]
|
|
|
|
|
|
cad = '{0:016b}'.format(my_dict['amplitudeI'])
|
|
|
lines[60] = cad[0:8]
|
|
|
lines[61] = cad[8:16]
|
|
|
|
|
|
cad = '{0:016b}'.format(my_dict['amplitudeQ'])
|
|
|
lines[66] = cad[0:8]
|
|
|
lines[67] = cad[8:16]
|
|
|
|
|
|
cad = '{0:08b}'.format(my_dict['amplitude_ramp_rate'])
|
|
|
lines[72] = cad[0:8]
|
|
|
|
|
|
cad = '{0:016b}'.format(my_dict['qdac'])
|
|
|
lines[76] = cad[0:8]
|
|
|
lines[77] = cad[8:16]
|
|
|
|
|
|
lines[81] = '%10.8f' %my_dict['clock']
|
|
|
|
|
|
text = '\n'.join(lines)
|
|
|
|
|
|
return text
|