function codeChips = codeGenerateGlonassG3Pilot( prn, varargin )

%==============================================================================%
%                                                                              %
%   codeChips = codeGenerateGlonassG3Pilot( prn, varargin )                    %
%                                                                              %
%   Generate 10230 chips of the GLONASS/G3-Pilot code sequence                 %
%   David S. De Lorenzo                                                        %
%   09 November 2017                                                           %
%                                                                              %
%------------------------------------------------------------------------------%
%                                                                              %
%   Reference GLONASS CDMA Open Service Navigation Signal in L3, Edition 1.0   %
%     -- L3OC Signal Structure is in Section 2 on pages 9-14.                  %
%                                                                              %
%   The code generator can be checked with the following code:                 %
%{                                                                         
  % The first & last 32 chips of the L3 PRN codes, from the ICD
  %                        Table 2.1 on pg. 12       Table 2.2 on pg. 13
  %                           L3OC - data               L3OC - pilot
  %                       first 32     last 32      first 32     last 32
  L3_validation_table = {'1CB31510',  '213B0657',  '1EBF3DE2',  '1BA445DE'; ...
                         '9DB50169',  'BC74A793',  '9FB9299B',  '86EBE41A'; ...
                         '5D360B55',  '72D37771',  '5F3A23A7',  '484C34F8'; ...
                         'DC301F2C',  'EF9CD6B5',  'DE3C37DE',  'D503953C'; ...
                         '3C719A32',  '88CF3EC4',  '3E7DB2C0',  'B2507D4D'; ...
                         'BD778E4B',  '15809F00',  'BF7BA6B9',  '2F1FDC89'; ...
                         '7DF48477',  'DB274FE2',  '7FF8AC85',  'E1B80C6B'; ...
                         'FCF2900E',  '4668EE26',  'FEFEB8FC',  '7CF7ADAF'; ...
                         '0CD25281',  'F5C11A1E',  '0EDE7A73',  'CF5E5997'; ...
                         '8DD446F8',  '688EBBDA',  '8FD86E0A',  '5211F853'; ...
                         '4D574CC4',  'A6296B38',  '4F5B6436',  '9CB628B1'; ...
                         'CC5158BD',  '3B66CAFC',  'CE5D704F',  '01F98975'; ...
                         '2C10DDA3',  '5C35228D',  '2E1CF551',  '66AA6104'; ...
                         'AD16C9DA',  'C17A8349',  'AF1AE128',  'FBE5C0C0'; ...
                         '6D95C3E6',  '0FDD53AB',  '6F99EB14',  '35421022'; ...
                         'EC93D79F',  '9292F26F',  'EE9FFF6D',  'A80DB1E6'; ...
                         '1483B6D8',  'CB460873',  '168F9E2A',  'F1D94BFA'; ...
                         '9585A2A1',  '5609A9B7',  '97898A53',  '6C96EA3E'; ...
                         '5506A89D',  '98AE7955',  '570A806F',  'A2313ADC'; ...
                         'D400BCE4',  '05E1D891',  'D60C9416',  '3F7E9B18'; ...
                         '344139FA',  '62B230E0',  '364D1108',  '582D7369'; ...
                         'B5472D83',  'FFFD9124',  'B74B0571',  'C562D2AD'; ...
                         '75C427BF',  '315A41C6',  '77C80F4D',  '0BC5024F'; ...
                         'F4C233C6',  'AC15E002',  'F6CE1B34',  '968AA38B'; ...
                         '04E2F149',  '1FBC143A',  '06EED9BB',  '252357B3'; ...
                         '85E4E530',  '82F3B5FE',  '87E8CDC2',  'B86CF677'; ...
                         '4567EF0C',  '4C54651C',  '476BC7FE',  '76CB2695'; ...
                         'C461FB75',  'D11BC4D8',  'C66DD387',  'EB848751'; ...
                         '24207E6B',  'B6482CA9',  '262C5699',  '8CD76F20'; ...
                         'A5266A12',  '2B078D6D',  'A72A42E0',  '1198CEE4'; ...
                         '65A5602E',  'E5A05D8F',  '67A948DC',  'DF3F1E06'; ...
                         'E4A37457',  '78EFFC4B',  'E6AF5CA5',  '4270BFC2'; ...
                         '18AB44F4',  '54058145',  '1AA76C06',  '6E9AC2CC'; ...
                         '99AD508D',  'C94A2081',  '9BA1787F',  'F3D56308'; ...
                         '592E5AB1',  '07EDF063',  '5B227243',  '3D72B3EA'; ...
                         'D8284EC8',  '9AA251A7',  'DA24663A',  'A03D122E'; ...
                         '3869CBD6',  'FDF1B9D6',  '3A65E324',  'C76EFA5F'; ...
                         'B96FDFAF',  '60BE1812',  'BB63F75D',  '5A215B9B'; ...
                         '79ECD593',  'AE19C8F0',  '7BE0FD61',  '94868B79'; ...
                         'F8EAC1EA',  '33566934',  'FAE6E918',  '09C92ABD'; ...
                         '08CA0365',  '80FF9D0C',  '0AC62B97',  'BA60DE85'; ...
                         '89CC171C',  '1DB03CC8',  '8BC03FEE',  '272F7F41'; ...
                         '494F1D20',  'D317EC2A',  '4B4335D2',  'E988AFA3'; ...
                         'C8490959',  '4E584DEE',  'CA4521AB',  '74C70E67'; ...
                         '28088C47',  '290BA59F',  '2A04A4B5',  '1394E616'; ...
                         'A90E983E',  'B444045B',  'AB02B0CC',  '8EDB47D2'; ...
                         '698D9202',  '7AE3D4B9',  '6B81BAF0',  '407C9730'; ...
                         'E88B867B',  'E7AC757D',  'EA87AE89',  'DD3336F4'; ...
                         '109BE73C',  'BE788F61',  '1297CFCE',  '84E7CCE8'; ...
                         '919DF345',  '23372EA5',  '9391DBB7',  '19A86D2C'; ...
                         '511EF979',  'ED90FE47',  '5312D18B',  'D70FBDCE'; ...
                         'D018ED00',  '70DF5F83',  'D214C5F2',  '4A401C0A'; ...
                         '3059681E',  '178CB7F2',  '325540EC',  '2D13F47B'; ...
                         'B15F7C67',  '8AC31636',  'B3535495',  'B05C55BF'; ...
                         '71DC765B',  '4464C6D4',  '73D05EA9',  '7EFB855D'; ...
                         'F0DA6222',  'D92B6710',  'F2D64AD0',  'E3B42499'; ...
                         '00FAA0AD',  '6A829328',  '02F6885F',  '501DD0A1'; ...
                         '81FCB4D4',  'F7CD32EC',  '83F09C26',  'CD527165'; ...
                         '417FBEE8',  '396AE20E',  '4373961A',  '03F5A187'; ...
                         'C079AA91',  'A42543CA',  'C2758263',  '9EBA0043'; ...
                         '20382F8F',  'C376ABBB',  '2234077D',  'F9E9E832'; ...
                         'A13E3BF6',  '5E390A7F',  'A3321304',  '64A649F6'; ...
                         '61BD31CA',  '909EDA9D',  '63B11938',  'AA019914'; ...
                         'E0BB25B3',  '0DD17B59',  'E2B70D41',  '374E38D0'};
  for jj = 0:63
      codeChips = codeGenerateGlonassG3Pilot( jj, 'NEW' );
      % First & last 32 symbols
      first_32 = lower(dec2hex(bin2dec(sprintf('%d',codeChips(1:32))),8));
      last_32 = lower(dec2hex(bin2dec(sprintf('%d',codeChips(end-31:end))),8));
      % Print first 32 symbols and last 32 symbols
      fprintf('     %2d   |  %s  |  %s\n', jj, upper(first_32), upper(last_32));
      % Check the first & last 32 symbols against the validation table
      if ~strcmpi(first_32, L3_validation_table(jj+1,3)) ...
              || ~strcmpi(last_32, L3_validation_table(jj+1,4))
          error( 'Code generation error for jj = %d!!', jj );
      end
  end
  disp( 'ALL PASSED!!' );
%}
%                                                                              %
%==============================================================================%
%                       GPS Software Receiver in Matlab                        %
%     Copyright (c) 2003-2017 David S. De Lorenzo / 2018-2023 Trimble Inc.     %
%==============================================================================%

if (nargin == 1)
    % do nothing - "normal" handling
elseif (nargin == 2)
    FORCE_ICD_VERSION = varargin{1};
else
    error('Invalid number of input arguments!!');
end

num_chips = 10230;

% Taps for the DC1 & DC3 linear feedback shift registers
dc1_taps = [4 8 13 14];
dc3_taps = [6 7];

% Initial state for the DC1 & DC3 LFSRs
dc1_IC = '00110100111000';
if (exist('FORCE_ICD_VERSION', 'var') == 1)
    if strcmpi(FORCE_ICD_VERSION, 'OLD') && (prn >= 1 && prn <= 31)
        dc3_IC = dec2bin(prn+32,7);
    elseif strcmpi(FORCE_ICD_VERSION, 'NEW') && (prn >= 0 && prn <= 63)
        dc3_IC = dec2bin(prn+64,7);
    else
        error('Invalid version string!!');
    end
elseif (prn == 21)
    % DSD - as of 11/13/2017, the GLONASS-M+ satellite equipped with the L3
    %       transmitter, GLONASS # 755 and NORAD # 40001, conforms to the
    %       'new' Edition 1.0 of the GLONASS L3 ICD, where the Pilot channel
    %       DC3 shift register initial state is equal to 'prn + 64'.
    %       Currently satellite '755' employs PRN 21.
    dc3_IC = dec2bin(prn+64,7);
elseif (prn == 9 || prn == 26)
    % DSD - as of 11/13/2017, the GLONASS-K1 satellites, GLONASS #s 701K &
    %       702K and NORAD #s 37372 & 40315, conform to the 'old' revision 1
    %       of the GLONASS L3 ICD (dated 2010), where the Pilot channel DC3
    %       shift register initial state is equal to 'prn + 32'
    %       Currently satellite '701K' employs PRN 26 - it's undergoing test.
    %       Currently satellite '702K' employs PRN 09 - it's active & healthy.
    dc3_IC = dec2bin(prn+32,7);
else
    error('You need to update this function for more GLONASS satellites!!');
end

% Convert a binary text string to a decimal vector of 1's and 0's
dc1reg = logical(reshape(bin2dec(reshape(dc1_IC,[],1)),1,[]));
dc3reg = logical(reshape(bin2dec(reshape(dc3_IC,[],1)),1,[]));

% Change to shift registers:  1 --> -1 and 0 --> +1
dc1reg = 1 - (2 * dc1reg);
dc3reg = 1 - (2 * dc3reg);

% Initialize the output
codeChips = zeros(1, num_chips);

% Generate all PRN code chips based on the feedback polynomials
%   This calculates the code sequences with "+1" rather than "0"
%   and "-1" rather than "1", since it is thus possible to use
%   traditional multiplication rather than XOR operations.
for ii = 1:num_chips
    codeChips(ii) = dc1reg(end) * dc3reg(end);
    dc1reg = [prod(dc1reg(dc1_taps)) dc1reg(1:end-1)];
    dc3reg = [prod(dc3reg(dc3_taps)) dc3reg(1:end-1)];
end

% Change the output:  -1 --> 1 and +1 --> 0
codeChips = (1 - codeChips) / 2;

return
%===============================================================================