Source code for fmcw.adc

from __future__ import division
from fractions import Fraction
from math import ceil, log

[docs]class ADF4158(): def __init__(self): """ Define the registers expected for this ADC. """ #Register definitions: # (Register: name: (First bit, Length, [value])) self.register_def = { 0:{'ramp_on':(31, 1), 'muxout':(27, 4), 'n':(15,12), 'frac_msb':(3, 12)}, 1:{'reserved1':(28,4), 'frac_lsb':(15, 12), 'reserved2':(3, 12)}, 2:{'reserved3':(29, 3), 'csr_en':(28, 1), 'cp_current':(24, 4), 'reserved4':(23, 1), 'prescaler':(22, 1), 'rdiv2':(21, 1), 'reference_doubler':(20, 1), 'r_counter':(15, 5), 'clk1_divider':(3, 12)}, 3:{'reserved5':(16, 16), 'n_sel':(15, 1), 'sd_reset':(14, 1), 'reserved6':(12, 2), 'ramp_mode':(10, 2), 'psk_enable':(9, 1), 'fsk_enable':(8,1), 'ldp':(7,1), 'pd_polarity':(6, 1), 'power_down':(5, 1), 'cp_threestate':(4, 1), 'counter_reset':(3, 1)}, 4:{'le_sel':(31, 1), 'sd_mod_mode':(26, 5), 'reserved7':(25, 1), 'neg_bleed_current': (23, 2), 'readback_to_muxout': (21, 2), 'clk_div_mode':(19, 2), 'clk2_divider':(7, 12), 'reserved8':(3, 4)}, 5:{'reserved9':(30, 2), 'tx_ramp_clk':(29, 1), 'par_ramp':(28, 1), 'interrupt':(26, 2), 'fsk_ramp_en':(25, 1), 'ramp2_en':(24, 1), 'dev_sel':(23, 1), 'dev_offset':(19, 4), 'deviation':(3, 16)}, 6:{'reserved10':(24, 8), 'step_sel':(23, 1), 'step':(3, 20)}, 7:{'reserved11':(19, 13), 'ramp_del_fl':(18, 1), 'ramp_del':(17, 1), 'del_clk_sel':(16, 1), 'del_start_en':(15, 1), 'delay_start_divider':(3, 12)} } self.registers = [0]*8 self.modified = [False]*8 self.written_regs = [None]*8 #Check unique names keys = [] #for key in self.register_def.itervalues(): for key in self.register_def.values(): for r in key: if r in keys: raise Exception("Duplicate register {}".format(r)) keys.append(r)
[docs] def freq_to_regs(self, fstart, fpd_freq, bw, length, delay): """ Set up the ADC. :param fstart: Initial chirp frequency? :param fpd_freq: :param bw: [Hz] bandwidth :param length: :param delay: Delay to account for the start of the mixer. :return: """ self.write_value(rdiv2=1) n = int(fstart/fpd_freq) frac_msb = int( ((fstart/fpd_freq) - n)*(1 << 12) ) frac_lsb = int( (((fstart/fpd_freq) - n)*(1 << 12) - frac_msb)*(1 << 13) ) self.write_value(n=n) self.write_value(frac_msb=frac_msb) self.write_value(frac_lsb=frac_lsb) clk1 = int((fpd_freq*length/(1<<20)) + 1) if delay > 0: clk1_d = int(ceil(delay*fpd_freq/(2**12))) else: clk1_d = 1 clk1 = max(clk1, clk1_d) self.write_value(clk1_divider=clk1) self.write_value(clk2_divider=1) steps = int(fpd_freq*length/clk1) devmax = 1 << 15 fres = fpd_freq/(1 << 25) fdev = bw/steps dev_offset = int(ceil(log(fdev/(fres*devmax), 2))) dev_offset = max(dev_offset, 0) dev = int(fdev/(fres*(1 << dev_offset))) self.write_value(deviation=dev) print("[INFO] Acquisition parameters:") print('steps\t\t\t', steps) print('clk1\t\t\t', clk1) print('fres\t\t\t', fres) print('fdev\t\t\t', fdev) print('dev_offset\t', dev_offset) print('deviation\t', dev) self.write_value(step=steps) self.write_value(dev_offset=dev_offset) self.write_value(clk_div_mode=3) self.write_value(ramp_on=1) self.write_value(pd_polarity=1) self.write_value(prescaler=1) self.write_value(r_counter=1) self.write_value(csr_en=1) #Readback to muxout and negative bleed current #can't be activated simultaneously if 1: self.write_value(muxout=15) self.write_value(readback_to_muxout=3) else: self.write_value(neg_bleed_current=3) #Sawtooth self.write_value(ramp_mode=0) if delay > 0: if delay > (2**12-1)/fpd_freq: #Use clk1 for delay clock. self.write_value(del_clk_sel=1) d = int(round(delay*fpd_freq/clk1)) if d > 2**12-1: raise ValueError("Too large delay: {}".format(d)) real_delay = d*clk1/fpd_freq else: #Else the delay clock is same as fpd_freq self.write_value(del_clk_sel=0) d = int(round(delay*fpd_freq)) real_delay = d/fpd_freq self.write_value(ramp_del=1) print('d\t\t\t\t', d) print() self.write_value(delay_start_divider=d) else: real_delay = 0 return real_delay
[docs] def find_reg(self, reg): """ Finds register by name. :param reg: :return: """ #for key, val in self.register_def.iteritems(): for key, val in self.register_def.items(): if reg in val.keys(): return key, val[reg] return None, None
[docs] def write_value(self, **kw): """ Write value to register, doesn't update the device. :param kw: :return: """ #for reg, val in kw.iteritems(): for reg, val in kw.items(): #print "{} = {}".format(reg, val) reg_n, reg_def = self.find_reg(reg) if reg_n == None: raise ValueError("Register {} not found".format(reg)) reg_start = reg_def[0] reg_len = reg_def[1] if val > 2**reg_len-1 or val < 0: raise ValueError("Invalid value, got: {}, maximum {}".format(val, 2**reg_len-1)) #Clear previous value self.registers[reg_n] &= (~((((2**reg_len-1))&0xFFFFFFFF) << reg_start) & 0xFFFFFFFF) self.registers[reg_n] |= (val) << reg_start self.modified[reg_n] = True return