Skip to content

Commit

Permalink
Merge pull request #31 from BBN-Q/hotfix/labbrick_lock
Browse files Browse the repository at this point in the history
Test for Labbrick PLL lock. Closes #25.
  • Loading branch information
caryan committed Jun 22, 2015
2 parents 7f46c0d + 1198f98 commit 8d5383a
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 155 deletions.
102 changes: 71 additions & 31 deletions common/+deviceDrivers/@Labbrick/Labbrick.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
% Class-specific constant properties
properties (Constant = true)
MAX_DEVICES = 64;
MAX_RETRIES = 3;
end % end constant properties


% Class-specific private properties
properties (Access = private)
devID;
Expand All @@ -34,8 +35,19 @@
max_freq = 10; % GHz
min_freq = 5; % GHz
pulseModeEnabled = 0;

% status codes from vnx_fmssynth.h
STATUS_INVALID_DEVID = hex2dec('80000000') % MSB is set if the device ID is invalid
STATUS_DEV_CONNECTED = hex2dec('00000001') % LSB is set if a device is connected
STATUS_DEV_OPENED = hex2dec('00000002') % set if the device is opened
STATUS_SWP_ACTIVE = hex2dec('00000004') % set if the device is sweeping
STATUS_SWP_UP = hex2dec('00000008') % set if the device is sweeping up in frequency
STATUS_SWP_REPEAT = hex2dec('00000010') % set if the device is in continuous sweep mode
STATUS_SWP_BIDIRECTIONAL = hex2dec('00000020') % set if the device is in bidirectional sweep mode
STATUS_PLL_LOCKED = hex2dec('00000040') % set if the PLL lock status is TRUE (both PLL's are locked)
STATUS_FAST_PULSE_OPTION = hex2dec('00000080') % set if the fast pulse mode option is installed
end % end private properties

% Device properties correspond to instrument parameters
properties (Access = public)
output
Expand All @@ -46,19 +58,21 @@
alc
pulse
pulseSource = 'ext';


pllLocked;

% device specific
refSource
end % end device properties

methods
%Constructor
function obj = Labbrick()
% load DLL
% build library path
path = [fileparts(mfilename('fullpath')) filesep];
if ~libisloaded('vnx_fmsynth')
loadlibrary([path 'vnx_fmsynth.dll'], [path 'vnx_fmsynth.h']);
loadlibrary([path 'vnx_fmsynth.dll'], [path 'vnx_LMS_api.h']);
calllib('vnx_fmsynth', 'fnLMS_SetTestMode', false);
end
end
Expand All @@ -69,14 +83,14 @@ function delete(obj)
obj.disconnect();
end
end

% open the connection to the Labbrick with the given serial number
function connect(obj, serial)
if ~isnumeric(serial)
serial = str2double(serial);
end
obj.serialNum = serial;

% find the devID of the Labbrick with the given serial number
[devIDs, serial_nums] = obj.enumerate();
obj.devID = devIDs(serial_nums == serial);
Expand All @@ -87,15 +101,15 @@ function connect(obj, serial)
if status ~= 0
error('Could not open device with id: %i, returned error %i', [obj.devID status])
end

% populate some device properties
obj.open = 1;
obj.max_power = calllib('vnx_fmsynth', 'fnLMS_GetMaxPwr', obj.devID) / 4;
obj.min_power = calllib('vnx_fmsynth', 'fnLMS_GetMinPwr', obj.devID) / 4;
obj.max_freq = calllib('vnx_fmsynth', 'fnLMS_GetMaxFreq', obj.devID) / 1e8;
obj.min_freq = calllib('vnx_fmsynth', 'fnLMS_GetMinFreq', obj.devID) / 1e8;
end

function disconnect(obj)
if obj.open
status = calllib('vnx_fmsynth', 'fnLMS_CloseDevice', obj.devID);
Expand All @@ -106,7 +120,12 @@ function disconnect(obj)
obj.open = 0;
end
end


function flag = get_dev_status(obj, status_code)
val = calllib('vnx_fmsynth', 'fnLMS_GetDeviceStatus', obj.devID);
flag = (bitand(val, status_code) == status_code);
end

% get a list of connected Labbricks
% NB: There is a bug in the Labbrick DLL that causes
% fnLMS_GetDevInfo to only return device IDs in order until it
Expand All @@ -122,9 +141,9 @@ function disconnect(obj)
if isempty(previous_num_devices)
previous_num_devices = 0;
end

%num_devices = calllib('vnx_fmsynth','fnLMS_GetNumDevices');

%if (num_devices > previous_num_devices) || isempty(devIDs)
if isempty(devIDs)
num_devices = calllib('vnx_fmsynth','fnLMS_GetNumDevices');
Expand All @@ -141,13 +160,13 @@ function disconnect(obj)
ids = devIDs;
serials = serial_nums;
end

% get model name
function name = model_name(obj)
[~, obj.model] = calllib('vnx_fmsynth', 'fnLMS_GetModelName', obj.devID, ' ');
[~, obj.model] = calllib('vnx_fmsynth', 'fnLMS_GetModelNameA', obj.devID, ' ');
name = obj.model;
end

% Instrument parameter accessors
% getters
function val = get.frequency(obj)
Expand Down Expand Up @@ -185,17 +204,21 @@ function disconnect(obj)
%if val == true, val = 'ext'; end
val = obj.pulseSource;
end

function val = get.refSource(obj)
val = calllib('vnx_fmsynth', 'fnLMS_GetUseInternalRef', obj.devID);
if val == true, val = 'int'; end
if val == false, val = 'ext'; end
end


function val = get.pllLocked(obj)
val = obj.get_dev_status(obj.STATUS_PLL_LOCKED);
end

% property setters
function obj = set.frequency(obj, value)
% value: frequency to set in GHz

% error check that the frequency is within the bounds of
% the device
if value > obj.max_freq
Expand All @@ -205,7 +228,7 @@ function disconnect(obj)
value = obj.min_freq;
warning('Frequency out of range');
end

% write frequency in 10s of Hz
calllib('vnx_fmsynth', 'fnLMS_SetFrequency', obj.devID, value*1e8);
end
Expand All @@ -218,7 +241,7 @@ function disconnect(obj)
value = obj.min_power;
warning('Power out of range');
end

% write power as a multiple of 0.25dBm
value = int32(value*4);
%fprintf('Writing value %i\n', value);
Expand All @@ -235,10 +258,10 @@ function disconnect(obj)
function obj = set.mod(obj, ~)
%not supported by hardware
end

function obj = set.pulse(obj, value)
obj.pulseModeEnabled = obj.cast_boolean(value);

switch obj.pulseSource
case 'int'
calllib('vnx_fmsynth', 'fnLMS_SetUseExternalPulseMod', obj.devID, false);
Expand All @@ -250,7 +273,7 @@ function disconnect(obj)
disp('Labbrick: Unknown pulse source');
end
end
function obj = set.pulseSource(obj, value)
function obj = set.pulseSource(obj, value)
% Validate input
value = lower(value);
checkMapObj = containers.Map({'int','internal','ext','external'},...
Expand All @@ -263,26 +286,43 @@ function disconnect(obj)
else
obj.pulseSource = 'int';
end

if obj.pulseModeEnabled
obj.pulse = 1; % set the pulse parameter to update the device
end
end

function obj = set.refSource(obj, value)
% Validate input
checkMapObj = containers.Map({'int','internal','ext','external'},...
{true,true,false,false});
if not (checkMapObj.isKey( lower(value) ))
error('Invalid input');
end

calllib('vnx_fmsynth', 'fnLMS_SetUseInternalRef', obj.devID, checkMapObj(lower(value)));

if (strncmpi(value,'ext', 3))
% test for PLL lock to make sure external reference is there
if (~obj.pllLocked)
error('Labbrick PLL is not locked');
end
else
%Try to catch intermittent PLL-lock when external reference is applied
ct = 0;
while (ct < 5)
if (~obj.pllLocked)
error('Labbrick PLL is not locked. Make sure external reference is not applied when using internal reference.');
end
pause(0.1);
ct = ct + 1;
end
end
end
end % end instrument parameter accessors

methods (Static)

%Helper function to cast boolean inputs to 'on'/'off' strings
function out = cast_boolean(in)
if isnumeric(in)
Expand All @@ -298,7 +338,7 @@ function disconnect(obj)
error('Unable to cast to boolean');
end
end

end

end % end class definition
112 changes: 112 additions & 0 deletions common/+deviceDrivers/@Labbrick/vnx_LMS_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Include file for 64 Bit Vaunix Lab Brick LMS Synthesizer DLL
//
// 10/2013 RD 64 Bit DLL version.
//


// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the VNX_FSYNSTH_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// VNX_LMS_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.

#ifdef VNX_FMSYNTH_EXPORTS
#define VNX_LMS_API __declspec(dllexport)
#else
#define VNX_LMS_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif


// ----------- Global Equates ------------
#define MAXDEVICES 64
#define MAX_MODELNAME 32

// ----------- Data Types ----------------
#define DEVID unsigned int

// ----------- Mode Bit Masks ------------
#define MODE_RFON 0x00000010 // bit is 1 for RF on, 0 if RF is off
#define MODE_INTREF 0x00000020 // bit is 1 for internal osc., 0 for external reference
#define MODE_SWEEP 0x0000000F // bottom 4 bits are used to keep the sweep control bits
#define MODE_PWMON 0x00000100 // we keep a copy of the PWM control bits here, 1 for int PWM on
#define MODE_EXTPWM 0x00000200 // 1 for ext. PWM input enabled
#define PWM_MASK 0x00000300

// ----------- Command Equates -----------
// Status returns for commands
#define LVSTATUS int
#define STATUS_OK 0
#define BAD_PARAMETER 0x80010000 // out of range input -- frequency outside min/max etc.
#define BAD_HID_IO 0x80020000
#define DEVICE_NOT_READY 0x80030000 // device isn't open, no handle, etc.
#define F_INVALID_DEVID -1.0 // for functions that return a float
#define F_DEVICE_NOT_READY -3.0

// Status returns for DevStatus
#define INVALID_DEVID 0x80000000 // MSB is set if the device ID is invalid
#define DEV_CONNECTED 0x00000001 // LSB is set if a device is connected
#define DEV_OPENED 0x00000002 // set if the device is opened
#define SWP_ACTIVE 0x00000004 // set if the device is sweeping
#define SWP_UP 0x00000008 // set if the device is sweeping up in frequency
#define SWP_REPEAT 0x00000010 // set if the device is in continuous sweep mode
#define SWP_BIDIRECTIONAL 0x00000020 // set if the device is in bi-directional sweep mode
#define PLL_LOCKED 0x00000040 // set if the PLL lock status is TRUE (both PLL's are locked)
#define FAST_PULSE_OPTION 0x00000080 // set if the fast pulse mode option is installed

// Flags to encode pulse mode time ranges
#define PM48Mhz 0x10000000 // used to select the 48Mhz pulse mod clock
#define PM1Mhz 0x00000000 // used to select the 1Mhz pulse mod clock or sw pulsing

VNX_LMS_API void fnLMS_SetTestMode(bool testmode);
VNX_LMS_API int fnLMS_GetNumDevices();
VNX_LMS_API int fnLMS_GetDevInfo(DEVID *ActiveDevices);
VNX_LMS_API int fnLMS_GetModelNameA(DEVID deviceID, char *ModelName);
// VNX_LMS_API int fnLMS_GetModelNameW(DEVID deviceID, wchar_t *ModelName);
VNX_LMS_API int fnLMS_InitDevice(DEVID deviceID);
VNX_LMS_API int fnLMS_CloseDevice(DEVID deviceID);
VNX_LMS_API int fnLMS_GetSerialNumber(DEVID deviceID);
VNX_LMS_API int fnLMS_GetDLLVersion();
VNX_LMS_API LVSTATUS fnLMS_SetFrequency(DEVID deviceID, int frequency);
VNX_LMS_API LVSTATUS fnLMS_SetStartFrequency(DEVID deviceID, int startfrequency);
VNX_LMS_API LVSTATUS fnLMS_SetEndFrequency(DEVID deviceID, int endfrequency);
VNX_LMS_API LVSTATUS fnLMS_SetSweepTime(DEVID deviceID, int sweeptime);
VNX_LMS_API LVSTATUS fnLMS_SetPowerLevel(DEVID deviceID, int powerlevel);
VNX_LMS_API LVSTATUS fnLMS_SetRFOn(DEVID deviceID, bool on);
VNX_LMS_API LVSTATUS fnLMS_SetPulseOnTime(DEVID deviceID, float pulseontime);
VNX_LMS_API LVSTATUS fnLMS_SetPulseOffTime(DEVID deviceID, float pulseofftime);
VNX_LMS_API LVSTATUS fnLMS_EnableInternalPulseMod(DEVID deviceID, bool on);
VNX_LMS_API LVSTATUS fnLMS_SetUseExternalPulseMod(DEVID deviceID, bool external);
VNX_LMS_API LVSTATUS fnLMS_SetFastPulsedOutput(DEVID deviceID, float pulseontime, float pulsereptime, bool on);
VNX_LMS_API LVSTATUS fnLMS_SetUseInternalRef(DEVID deviceID, bool internal);
VNX_LMS_API LVSTATUS fnLMS_SetSweepDirection(DEVID deviceID, bool up);
VNX_LMS_API LVSTATUS fnLMS_SetSweepMode(DEVID deviceID, bool mode);
VNX_LMS_API LVSTATUS fnLMS_SetSweepType(DEVID deviceID, bool swptype);
VNX_LMS_API LVSTATUS fnLMS_StartSweep(DEVID deviceID, bool go);
VNX_LMS_API LVSTATUS fnLMS_SaveSettings(DEVID deviceID);
VNX_LMS_API int fnLMS_GetFrequency(DEVID deviceID);
VNX_LMS_API int fnLMS_GetStartFrequency(DEVID deviceID);
VNX_LMS_API int fnLMS_GetEndFrequency(DEVID deviceID);
VNX_LMS_API int fnLMS_GetSweepTime(DEVID deviceID);
VNX_LMS_API int fnLMS_GetRF_On(DEVID deviceID);
VNX_LMS_API int fnLMS_GetUseInternalRef(DEVID deviceID);
VNX_LMS_API int fnLMS_GetPowerLevel(DEVID deviceID);
VNX_LMS_API int fnLMS_GetAbsPowerLevel(DEVID deviceID);
VNX_LMS_API int fnLMS_GetMaxPwr(DEVID deviceID);
VNX_LMS_API int fnLMS_GetMinPwr(DEVID deviceID);
VNX_LMS_API int fnLMS_GetMaxFreq(DEVID deviceID);
VNX_LMS_API int fnLMS_GetMinFreq(DEVID deviceID);
VNX_LMS_API float fnLMS_GetPulseOnTime(DEVID deviceID);
VNX_LMS_API float fnLMS_GetPulseOffTime(DEVID deviceID);
VNX_LMS_API int fnLMS_GetPulseMode(DEVID deviceID);
VNX_LMS_API int fnLMS_GetHasFastPulseMode(DEVID deviceID);
VNX_LMS_API int fnLMS_GetUseInternalPulseMod(DEVID deviceID);
VNX_LMS_API int fnLMS_GetDeviceStatus(DEVID deviceID);

#ifdef __cplusplus
}
#endif
Binary file modified common/+deviceDrivers/@Labbrick/vnx_fmsynth.dll
Binary file not shown.
Loading

0 comments on commit 8d5383a

Please sign in to comment.