disp('NOTE: This program uses a LOT of memory, if youre running this on a computer with low memory, using a large pagefile on an SSD will make this run multitudes faster!')
disp('e.g. it took me 18 minutes to generate 120 seconds of data on my system with 16GB of RAM, and a pagefile on an SSD.')
secondsToGenerate = 20;
systemTime = 654480013; % GPS Time, UTC (https://www.andrews.edu/~tzs/timeconv/timeconvert.php)
channelSID = 2;
channelNID = 1;
channelNum = 777; % See CDMA C.S0057 to find how to calculate the channel number. Channel 384 corresponds to 881.52MHz. 777 cooresponds to 893.31MHz (make sure you change the frequency in GNU Radio too!)
                  % https://www.arib.or.jp/english/html/overview/doc/STD-T64v6_80/Specification/ARIB_STD-T64-C.S0057-Ev1.0.pdf

fManualConfig.SpreadingRate          = 'SR1';                           % Spreading Rate 1 or 3 (--EDITED--)
fManualConfig.Diversity              = 'NTD';                           % No Transmit Diversity (other options are 'OTD', 'STS')
fManualConfig.QOF                    = 'QOF1';                          % Quasi-orthogonal function 1, 2 or 3
fManualConfig.PNOffset               = 0;                               % PN offset of Base station
fManualConfig.LongCodeState          = hex2dec("10000000000");           % Initial long code state
fManualConfig.PowerNormalization     = 'Off';                           % Power normalization: 'Off', 'NormalizeTo0dB' or 'NoiseFillTo0dB'
fManualConfig.OversamplingRatio      = 4;                               % Upsampling factor
fManualConfig.FilterType             = 'cdma2000Long';                  % Filter coefficients: 'cdma2000Long', 'cdma2000Short', 'Custom' or 'Off'
fManualConfig.InvertQ                = 'Off';                           % Negate the imaginary part of the waveform
fManualConfig.EnableModulation       = 'Off';                           % Enable carrier modulation
fManualConfig.ModulationFrequency    = 0;                               % Modulation frequency (Hz)
fManualConfig.NumChips               = 1.2288e6 * secondsToGenerate;    % Number of chips in the waveform

fpich.Enable                = 'On';                     % Enable the F-PICH channel
fpich.Power                 = 1;                        % Relative channel power (dBW)
fManualConfig.FPICH         = fpich;                    % Add the channel to the waveform configuration

fapich.Enable               = 'On';                     % Enable the F-APICH channel
fapich.Power                = 0;                        % Relative channel power (dBW)
fapich.WalshCode            = 10;                       % Unique Walsh code number
fapich.WalshLength          = 64;                       % Walsh code length
fManualConfig.FAPICH        = fapich;                   % Add the channel to the waveform configuration

ftdpich.Enable              = 'On';                     % Enable the F-TDPICH channel
ftdpich.Power               = 0;                        % Relative channel power (dBW)
fManualConfig.FTDPICH       = ftdpich;                  % Add the channel to the waveform configuration

fatdpich.Enable             = 'On';                     % Enable the F-ATDPICH channel
fatdpich.Power              = 0;                        % Relative channel power (dBW)
fatdpich.WalshCode          = 11;                       % Unique Walsh code number
fatdpich.WalshLength        = 64;                       % Walsh code length
fManualConfig.FATDPICH      = fatdpich;                 % Add the channel to the waveform configuration

fpch.Enable                 = 'On';                     % Enable the F-PCH channel
fpch.Power                  = 0;                        % Relative channel power (dBW)
fpch.LongCodeMask           = 0;                        % Long code mask
fpch.DataRate               = 4800;                     % Data rate (bps)
fpch.EnableCoding           = 'On';                     % Enable channel coding
fpch.DataSource             = 'PagingMessage1';               % Input message: {'PNX', Seed} or numerical vector
fpch.WalshCode              = 1;                        % Unique Walsh code number
fManualConfig.FPCH          = fpch;                     % Add the channel to the waveform configuration

fbcch.Enable                = 'On';                     % Enable the F-BCCH channel
fbcch.Power                 = 0;                        % Relative channel power (dBW)
fbcch.LongCodeMask          = 0;                        % Long code mask
fbcch.DataRate              = 4800;                     % Data rate (bps)
fbcch.FrameLength           = 160;                      % Frame length (ms)
fbcch.EnableCoding          = 'On';                     % Enable channel coding
fbcch.DataSource            = {'PN9-ITU', 1};               % Input message: {'PNX', Seed} or numerical vector
fbcch.WalshCode             = 2;                        % Unique Walsh code number
fbcch.CodingType            = 'conv';                   % Coding type: 'conv' or 'turbo'
fManualConfig.FBCCH         = fbcch;                    % Add the channel to the waveform configuration

fcach.Enable                = 'On';                     % Enable the F-CACH channel
fcach.Power                 = 0;                        % Relative channel power (dBW)
fcach.LongCodeMask          = 0;                        % Long code mask
fcach.EnableCoding          = 'On';                     % Enable channel coding
fcach.DataSource            = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
fcach.WalshCode             = 3;                        % Unique Walsh code number
fcach.CodingType            = 'conv';                   % Coding type: 'conv' or 'turbo'
fManualConfig.FCACH         = fcach;                    % Add the channel to the waveform configuration

fccch.Enable                = 'On';                     % Enable the F-CCCH channel
fccch.Power                 = 0;                        % Relative channel power (dBW)
fccch.LongCodeMask          = 0;                        % Long code mask
fccch.DataRate              = 9600;                     % Data rate (bps)
fccch.FrameLength           = 20;                       % Frame length (ms)
fccch.EnableCoding          = 'On';                     % Enable channel coding
fccch.DataSource            = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
fccch.WalshCode             = 4;                        % Unique Walsh code number
fccch.CodingType            = 'conv';                   % Coding type: 'conv' or 'turbo'
fManualConfig.FCCCH         = fccch;                    % Add the channel to the waveform configuration

fcpcch.Enable               = 'On';                     % Enable the F-CPCCH channel
fcpcch.Power                = 0;                        % Relative channel power (dBW)
fcpcch.LongCodeMask         = 0;                        % Long code mask
fcpcch.EnableCoding         = 'On';                     % Enable channel coding
fcpcch.DataSource           = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
fcpcch.WalshCode            = 5;                        % Unique Walsh code number
fManualConfig.FCPCCH        = fcpcch;                   % Add the channel to the waveform configuration

fqpch.Enable                = 'On';                     % Enable the F-QPCH channel
fqpch.Power                 = 0;                        % Relative channel power (dBW)
fqpch.LongCodeMask          = 0;                        % Long code mask
fqpch.DataRate              = 2400;                     % Data rate (bps)
fqpch.EnableCoding          = 'On';                     % Enable channel coding
fqpch.DataSource            = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
fqpch.WalshCode             = 6;                        % Unique Walsh code number
fManualConfig.FQPCH         = fqpch;                    % Add the channel to the waveform configuration

ffch.Enable                 = 'On';                     % Enable the F-FCH channel
ffch.Power                  = 0;                        % Relative channel power (dBW)
ffch.RadioConfiguration     = 'RC4';                    % Radio Configuration: 1-9
ffch.DataRate               = 9600;                     % Data rate (bps)
ffch.FrameLength            = 20;                       % Frame length (ms)
ffch.LongCodeMask           = 0;                        % Long code mask
ffch.EnableCoding           = 'On';                     % Enable channel coding
ffch.DataSource             = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
ffch.WalshCode              = 7;                        % Unique Walsh code number
ffch.EnableQOF              = 'Off';                    % Enable QOF spreading
ffch.PowerControlEnable     = 'Off';                    % Enable the Power Control Subchannel
fManualConfig.FFCH          = ffch;                     % Add the channel to the waveform configuration

focns.Enable                = 'On';                     % Enable the F-OCNS channel
focns.Power                 = -30;                      % Relative channel power (dBW)
focns.WalshCode              = 12;                      % Unique Walsh code number
focns.WalshLength           = 128;                      % Walsh code length
fManualConfig.FOCNS         = focns;                    % Add the channel to the waveform configuration

fdcch.Enable                = 'On';                     % Enable the F-DCCH channel
fdcch.Power                 = 0;                        % Relative channel power (dBW)
fdcch.RadioConfiguration    = 'RC4';                    % Radio Configuration: 1-9
fdcch.LongCodeMask          = 0;                        % Long code mask
fdcch.DataRate              = 9600;                     % Data rate (bps)
fdcch.FrameLength           = 5;                        % Frame length (ms)
fdcch.EnableCoding          = 'On';                     % Enable channel coding
fdcch.DataSource            = {'PN9-ITU', 1};               % Input message: {'PNX', Seed} or numerical vector
fdcch.WalshCode             = 8;                        % Unique Walsh code number
fdcch.EnableQOF             = 'off';                    % Enable QOF spreading
fManualConfig.FDCCH         = fdcch;                    % Add the channel to the waveform configuration

fsch.Enable                 = 'On';                     % Enable the F-SCH channel
fsch.Power                  = 0;                        % Relative channel power (dBW)
fsch.RadioConfiguration     = 'RC4';                    % Radio Configuration: 1-9
fsch.DataRate               = 9600;                     % Data rate (bps)
fsch.FrameLength            = 20;                       % Frame length (ms)
fsch.LongCodeMask           = 0;                        % Long code mask
fsch.EnableCoding           = 'On';                     % Enable channel coding
fsch.DataSource             = {'PN9', 1};               % Input message: {'PNX', Seed} or numerical vector
fsch.WalshCode              = 9;                        % Unique Walsh code number
fsch.EnableQOF              = 'Off';                    % Enable QOF spreading
fsch.CodingType             = 'conv';                   % Coding type: 'conv' or 'turbo'
fManualConfig.FSCH          = fsch;                     % Add the channel to the waveform configuration

fsync.Enable                = 'On';                     % Enable the F-SYNC channel
fsync.Power                 = 1;                        % Relative channel power (dBW)
fsync.EnableCoding          = 'On';                     % Enable channel coding
sm = {};
fsync.DataSource            = 'SyncMessage';            % Input message: {'PNX', Seed}, numerical vector or 'SyncMessage'
sm.P_REV                    = 6;                        % Protocol Revision field
sm.MIN_P_REV                = 6;                        % Minimum Protocol Revision field
sm.SID                      = channelSID;               % System Identifier field 
sm.NID                      = channelNID;               % Network Identification field
sm.PILOT_PN                 = 0;                        % Pilot PN Offset field
sm.LC_STATE                 = hex2dec('10000000000');   % Long Code State field
sm.SYS_TIME                 = systemTime * 12.5;    % System Time field
sm.LP_SEC                   = 0;                        % Leap Second field
sm.LTM_OFF                  = 0;                        % Local Time Offset field
sm.DAYLT                    = 0;                        % Daylight Savings Time Indicator field
sm.PRAT                     = 1;                        % Paging Channel Data Rate field
sm.CDMA_FREQ                = channelNum;               % CDMA Frequency field
sm.EXT_CDMA_FREQ            = channelNum;               % Extended CDMA Frequency field
fsync.SyncMessage           = sm;                       % Sync channel message substructure, used if 'SyncMessage' is the data sou
fManualConfig.FSYNC         = fsync;                    % Add the channel to the waveform configuration



disp('Generating waveform...')
disp('(this may take a while)')
tic
forwardManualWaveform2 = cdma2000ForwardWaveformGenerator(fManualConfig);
elapsedTime = toc
dataSize = size(forwardManualWaveform2, 1);
iqData = zeros(dataSize*2, 1);

disp('Interleaving data to IQ format... (sorry, this might run really slow if you had to dig into pagefile memory)')
i = 1:1:dataSize;
iqData((2*i)-1, 1) = real(forwardManualWaveform2(i, 1));
iqData((2*i), 1)   = imag(forwardManualWaveform2(i, 1));


disp('Normalizing IQ data...')
if abs(min(iqData)) > max(iqData)
      iqData = iqData / min(iqData);
  else
      iqData = iqData / max(iqData);
end

disp('Writing output...')
fileID = fopen('output-a.iq', 'wb');
fwrite(fileID, iqData, 'float32');
fclose(fileID);

disp('Done!')