% Copyright (c) 2023 SpinCore Technologies, Inc.
% http://www.spincore.com
% 
% This software is provided 'as-is', without any express or implied warranty. 
% In no event will the authors be held liable for any damages arising from the 
% use of this software.
% 
% Permission is granted to anyone to use this software for any purpose, 
% including commercial applications, and to alter it and redistribute it
% freely, subject to the following restrictions:
% 
% 1. The origin of this software must not be misrepresented; you must not
% claim that you wrote the original software. If you use this software in a
% product, an acknowledgment in the product documentation would be appreciated
% but is not required.
% 2. Altered source versions must be plainly marked as such, and must not be
% misrepresented as being the original software.
% 3. This notice may not be removed or altered from any source distribution.
%

%
% pbdds_i_300_excite_test.m adapted from pbdds_i_300_excite_test.c
% This program executes an excitation test on the PulseBlasterDDS-I-300. This test will produce a 1 MHz signal on the 
% RF connector for 10 microseconds then turn off for 1 millisecond. It will then repeat this pattern 
% indefinitely.
% pbddsI
%
clc; clear;

global SPINAPI_DLL_NAME

SPINAPI_DLL_NAME = 'spinapi64';

addpath('../MATLAB_SpinAPI'); % MATLAB_SpinAPI Folder path address

SpinAPI_Drive = 'C:'; % Modify to the hard drive letter that contains SpinAPI

% Loads spinapi64 library and headers
% All files are located in SpinAPI folder
if ~libisloaded('spinapi64')  % Needs the MinGW-w64 add-on
    loadlibrary([SpinAPI_Drive,'\SpinCore\SpinAPI\lib\spinapi64.dll'], ...
                 [SpinAPI_Drive,'\SpinCore\SpinAPI\include\spinapi.h'], 'addheader',...
                 [SpinAPI_Drive,'\SpinCore\SpinAPI\include\pulseblaster.h'], 'addheader',...
                 [SpinAPI_Drive,'\SpinCore\SpinAPI\include\radioprocessor.h'], 'addheader',...
                 [SpinAPI_Drive,'\SpinCore\SpinAPI\include\dds.h']);
end

% Load constants to the workspace as variables
load('CONST.mat');

CLOCK_FREQ = 75.0;

% User friendly names for the control bits
TX_ENABLE = 1;
TX_DISABLE = 0;
PHASE_RESET = 1;
NO_PHASE_RESET = 0;


% Uncommenting the line below will generate a debug log in your current
% directory that can help debug any problems that you may be experiencing   
% pb_set_debug(1);

fprintf('Copyright (c) 2023 SpinCore Technologies, Inc.\n\n');

fprintf('Using SpinAPI library version %s \n', pb_get_version());

numBoards = detect_boards(); % If there is more than one board in the system, have the user specify.
if numBoards > 1
    select_boards(numBoards) % Request the board numbet to use from the user
end

if pb_init() ~= 0
  error('Error initializing board: %s\n', pb_get_error());
end

pb_set_defaults();
pb_core_clock(CLOCK_FREQ);

fprintf('Clock frequency: %.2fMHz\n\n', CLOCK_FREQ);
fprintf(['This example executes an excitation test on the PBDDS-I-300. This test\n'...
        'will produce a 1 MHz signal on for 10 microseconds then turn off for 1\n'... 
        'millisecond. The program will repeat this pattern indefinitely. The TTL\n'...
        'outputs are enabled during the pulse and can be used to trigger your\n' ...
        'oscilloscope.\n\n']);

% Program the first 2 frequency registers
pb_start_programming(FREQ_REGS);
pb_set_freq(1.0 * MHz); 	% Frequency Register 0
pb_set_freq(1.0 * MHz);	    % Frequency Register 1
pb_stop_programming();

% Program the first 2 phase registers
pb_start_programming(TX_PHASE_REGS);
pb_set_phase(0.0);		% Register 0
pb_set_phase(0.0);		% Register 1
pb_stop_programming();

% Write the pulse program
pb_start_programming(PULSE_PROGRAM);

%pb_inst_dds(freq, tx_phase, tx_enable, phase_reset, flags, inst, inst_data, length)
start = pb_inst_dds(1, 1, TX_ENABLE, NO_PHASE_RESET, '1FF', CONTINUE, 0, 10.0 * us);
pb_inst_dds(1, 1, TX_DISABLE, PHASE_RESET, 0, BRANCH, start, 1.0 * ms);

pb_stop_programming();

% Trigger program
pb_reset();
pb_start();

% Release control of the board
pb_close();

fprintf('Press enter to continue...\n')
pause; 

% Unload library and free memory
unloadlibrary('spinapi64');


function numBoards = detect_boards()
    numBoards = pb_count_boards();
    if numBoards < 1
        error(['No Boards were detected in your system. Verify that the board is', ...
            ' firmly secured in the PCI slot.']);
    end
end

function select_boards(numBoards)
    while true
        fprintf('Found %d boards in your system. ', numBoards);
        fprintf('Which board should be used? (0-%d): ', (numBoards-1));
        choice = input('');
        if choice < 0 || choice > numBoards-1
            fprintf('Invalid Board Number (%d).\n', choice);
        else 
            pb_select_board(choice);
            fprintf('Board %d selected.\n',choice);
            break
        end 
    end 
end 