% 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.
%

%
% \file excite_test.m adapted from excite_test.c
% \brief The example program tests the excitation portion of the RadioProcessor.
%  This program will produce a 1MHz signal on the oscilloscope that is on
%  for 10 microseconds, off for 1 milisecond, and the repeat this pattern.
% \ingroup RP
%
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;
DO_TRIGGER = 1;
NO_TRIGGER = 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('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: %.2lfMHz\n\n', CLOCK_FREQ);
fprintf(['The example program tests the excitation portion of the '...
	    'RadioProcessor.  This program will produce a 1MHz signal on the '...
	    'RF connector that is on for 10 microseconds, off for 1 '...
	    'milisecond, and will then repeat this pattern.\nAll TTL flags '...
	    'will be high during the RF signal and low while it is off.\n\n']);

% Write 1 MHz to the first frequency register
pb_start_programming(FREQ_REGS);
pb_set_freq(1.0 * MHz);
pb_stop_programming();

% Write 0.0 degrees to the first phase register of all channels
pb_start_programming(TX_PHASE_REGS);
pb_set_phase(0.0);
pb_stop_programming();

pb_start_programming(COS_PHASE_REGS);
pb_set_phase(0.0);
pb_stop_programming();

pb_start_programming(SIN_PHASE_REGS);
pb_set_phase(0.0);
pb_stop_programming();

% Write the pulse program
pb_start_programming(PULSE_PROGRAM);

% This instruction enables a 1 MHz analog output
start = pb_inst_radio(0, 0, 0, 0, TX_ENABLE, NO_PHASE_RESET, NO_TRIGGER, '3F', CONTINUE, 0, 10.0 * us);

% This instruction disables the analog output (and resets the phase in
% preparation for the next instruction)
pb_inst_radio(0, 0, 0, 0, TX_DISABLE, PHASE_RESET, NO_TRIGGER, 0, BRANCH, start, 1.0 * ms);
pb_stop_programming();

% Trigger program
pb_reset();
pb_start();

% print warning and wait for user to press a key while board runs
fprintf(['***WARNING***\nIf the program is closed without a preceeding '...
		'key press, the board will continue to run until excite_test is run'...
		' again and allowed to complete properly.\n']);


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

% Stop the program
pb_stop();

% Release control of the board
pb_close();

% 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 