from builtins import range
from ...core.devio import SCPI, units #@UnresolvedImport
from ...core.utils import numerical,general,funcargparse #@UnresolvedImport
_depends_local=["...core.devio.SCPI"]
[docs]class CBDX1(SCPI.SCPIDevice):
"""
CBDX1 controller for the PurePhotonics PPCL200 laser.
"""
def __init__(self, addr, read_echo=True, comm_delay=.5, mode_wait_time=5., offset_wait_time=5., connect_on_operation=True):
backend_params={"connect_on_operation":connect_on_operation}
SCPI.SCPIDevice.__init__(self,(addr,115200),backend="serial",backend_params=backend_params)
self.instr.set_timeout(6.)
self.instr.term_read=[";","\r","\n"]
self.max_wavelength_step=50E-12
self.power_range=(4E-3,63E-3)
self._ask_delay=comm_delay
self._set_delay=comm_delay
self._wait_poll_period=comm_delay*2
self._read_echo_delay=comm_delay
self._mode_wait_time=mode_wait_time
self._offset_wait_time=offset_wait_time
self._read_echo=read_echo
self._add_settings_node("power_on",self.get_output,None)
self._add_settings_node("power",self.get_output_level,self.set_output_level)
self._add_settings_node("wavelength",self.get_wavelength,self.set_wavelength)
self._add_settings_node("offset",self.get_offset,self.set_offset)
self._add_settings_node("offset_wavelength",self.get_offset_wavelength,None)
self._add_settings_node("mode",self.get_mode,self.set_mode)
self.initialize()
[docs] def initialize(self):
with self.instr.single_op():
self.write("pass coherent",read_echo=True,read_echo_delay=self._read_echo_delay)
self.flush()
[docs] def reset_output(self):
with self.instr.single_op():
mode=self.get_mode()
on=self.get_output()
self._set_output_raw(False,wait=True)
self.set_mode("standard",wait=True)
self._set_output_raw(on,wait=True)
self.set_mode(mode,wait=True)
[docs] def ensure_output(self):
with self.instr.single_op():
on=self.get_output()
if not on:
self._set_output_raw(True,wait=True)
mode=self.get_mode()
if mode!="whisper":
self.set_mode("whisper",wait=True)
[docs] def write_register(self, addr, value):
value=int(value)
value=min((2<<15)-1,max(-(2<<15),value))
command="byp 1,1,1,1,{:02x},{:02x},{:02x}".format(int(addr)&0xFF,(value>>8)&0xFF,value&0xFF)
with self.instr.single_op():
self.write(command,read_echo=True,read_echo_delay=self._read_echo_delay)
self.flush()
[docs] def read_register(self, addr):
command="byp 1,1,1,0,{:02x},0,0".format(addr&0xFF)
with self.instr.single_op():
resp=self.ask(command,delay=self._ask_delay,read_echo=self._read_echo)
reg=[int(d.strip(),base=16) for d in resp.split(",")[2:]]
return reg[0]*(1<<8)+reg[1]
[docs] def is_busy(self):
with self.instr.single_op():
return self.ask("BUSY?","bool",delay=self._ask_delay,read_echo=self._read_echo)
[docs] def wait_sync(self, timeout=None):
timeout=self._wait_sync_timeout if timeout is None else timeout
countdown=general.Countdown(timeout)
while True:
if not self.is_busy():
return True
if countdown.passed():
return False
self.sleep(self._wait_poll_period)
[docs] def get_mode(self):
mode=self.read_register(0x90)
if mode==0:
return "standard"
elif mode==1:
return "no_dither"
elif mode==2:
return "whisper"
else:
raise self.instr.Error("can't recognize mode {} returned py the device".format(mode))
_modes={"standard":0,"no_dither":1,"whisper":2}
[docs] def set_mode(self, mode, wait=True):
funcargparse.check_parameter_range(mode,"mode",self._modes)
self.write_register(0x90,self._modes[mode])
if wait:
self.sleep(self._set_delay)
self.wait_sync()
def _check_mode(self):
mode=self.get_mode()
if mode!="standard":
self.set_mode("standard")
self.sleep(self._mode_wait_time/2.)
return mode
[docs] def get_output(self):
return bool(self.read_register(0x32)&0x08)
def _set_output_raw(self, enabled=True, wait=True):
self.write_register(0x32,8 if enabled else 0)
if wait:
self.sleep(self._set_delay)
self.wait_sync()
[docs] def set_output(self, enabled=True, wait=True):
if enabled and wait:
mode=self.get_mode()
self.set_mode("standard",wait=True)
self._set_output_raw(enabled=enabled,wait=wait)
self.set_mode(mode,wait=True)
else:
self._set_output_raw(enabled=enabled,wait=wait)
return self.get_output()
[docs] def get_output_level(self):
with self.instr.single_op():
value,unit=self.ask("POWER?","value",delay=self._ask_delay,read_echo=self._read_echo)
return units.convert_power_units(value,unit or "dBm","W",case_sensitive=False)
[docs] def set_output_level(self, level, wait=True, check_mode=True):
wait=wait or check_mode
if level is None:
self._set_output_raw(False,wait=wait)
return None
else:
with self.instr.single_op():
if check_mode:
is_on=self.get_output()
mode=self._check_mode()
level=numerical.limit_to_range(level,*self.power_range)
level=units.convert_power_units(level,"W","dBm")
self.write("POWER",level,"float",read_echo=True,read_echo_delay=self._read_echo_delay)
self.flush()
if wait:
self.sleep(self._set_delay)
self.wait_sync()
if check_mode and (mode!="standard"):
self.set_mode(mode)
self.sleep(self._mode_wait_time)
if is_on:
self.ensure_output()
return self.get_output_level()
[docs] def get_wavelength(self):
with self.instr.single_op():
value,unit=self.ask("WAVELENGTH?","value",delay=self._ask_delay,read_echo=self._read_echo)
return units.convert_length_units(value,unit or "nm","m",case_sensitive=False)
[docs] def set_wavelength(self, wavelength, wait=True, check_mode=True):
wait=wait or check_mode
with self.instr.single_op():
wavelength=units.convert_length_units(wavelength,"m","nm")
if check_mode:
mode=self._check_mode()
self.write("WAVELENGTH",wavelength,"float",read_echo=True,read_echo_delay=self._read_echo_delay)
self.flush()
if wait:
self.sleep(self._set_delay)
self.wait_sync()
if check_mode and (mode!="standard"):
self.set_mode(mode)
self.sleep(self._mode_wait_time)
self.ensure_output()
return self.get_wavelength()
[docs] def get_offset(self):
with self.instr.single_op():
value,unit=self.ask("OFFSET?","value",delay=self._ask_delay,read_echo=self._read_echo)
return units.convert_frequency_units(value,unit or "GHz","Hz",case_sensitive=True)
[docs] def set_offset(self, offset, wait=True):
with self.instr.single_op():
offset=units.convert_frequency_units(offset,"Hz","MHz")
if wait:
self.sleep(self._set_delay)
self.wait_sync()
self.write_register(0x62,offset)
if wait:
self.sleep(self._set_delay)
self.wait_sync()
self.sleep(self._offset_wait_time)
return self.get_offset()
[docs] def step_wavelength(self, step):
if abs(step)<=self.max_wavelength_step:
return self.set_wavelength(self.get_wavelength()+step)
else:
return self.get_wavelength()
[docs] def sweep_wavelength(self, start, step_size, steps_number, delay):
self.set_wavelength(start)
for _ in range(steps_number):
self.sleep(delay)
self.step_wavelength(step_size)
return self.get_wavelength()
[docs] def cycle_wavelength(self, step):
self.step_wavelength(step)
return self.step_wavelength(-step)
[docs] def step_offset(self, step):
return self.set_offset(self.get_offset()+step)
[docs] def get_offset_wavelength(self):
with self.instr.single_op():
wavelength=self.get_wavelength()
freq=3E8/wavelength
offset=self.get_offset()
return 3E8/(freq+offset)
[docs] def apply_settings(self, settings):
if "power_on" in settings and not settings["power_on"]:
self.set_output(False)
SCPI.SCPIDevice.apply_settings(self,settings)
if "power_on" in settings and settings["power_on"]:
self.set_output(True)
return self.get_settings()