%=========================================================================
function [buf, config] = read_buf(instclass, fid, params, config)

id = params.id;
out = params.out;
yearbase = params.yearbase;

if nargin == 3, config.yearbase = yearbase; end % initializes config
start = ftell(fid);
[ss, count] = fread(fid, 2, 'uint16');

if count ~= 2,
   buf = sprintf('error 1, only %d bytes at start of buffer\n', count);
   return
end

if ss(1) ~= id.header,    % 7F7F
   buf = 'error 2, Header ID/Data Source not found in read_buf';
   return
end

config.nbytes = ss(2);  % Total bytes up to, not including, checksum.
fseek(fid, start, 'bof');
[rec, count] = fread(fid, config.nbytes, 'uint8');
if count ~= config.nbytes,
   buf = sprintf('error 3, only %d bytes read, %d expected\n', ...
                     count, config.nbytes);
   return
end
test_cs = mod(sum(rec), 65536);
cs = fread(fid, 1, 'uint16');
if test_cs ~= cs,
   buf = ['error 4, Checksum failure; CS is ', ...
          int2str(cs), ' versus calculated ', ...
            int2str(test_cs)];
   return
end

if nargin == 3,
   config.ndata = rec(6);
   ii = 7 + 2 * (0:(config.ndata-1));
   config.offsets = rec(ii) + 256 * rec(ii+1);
   config.ids = rec(config.offsets + 1) + rec(config.offsets + 2) * 256;

   %%% fixed leader:
   ofs = config.offsets(find(config.ids == id.flead));
   config.nbeams_used = rec(ofs + 9);
   config.ncells = rec(ofs + 10);
   config.cell = 0.01 * (rec(ofs + 13) + 256 * rec(ofs + 14));
   config.blank = 0.01 * (rec(ofs + 15) + 256 * rec(ofs + 16));
   config.mode = rec(ofs + 17);
   config.code_reps = rec(ofs + 19);
   config.EZ = rec(ofs + 31);
   config.bin1distance = 0.01 * (rec(ofs + 33) + 256 * rec(ofs + 34));
   config.pulse = 0.01 * (rec(ofs + 35) + 256 * rec(ofs + 36));
   config.lag = 0.01 * (rec(ofs + 41) + 256 * rec(ofs + 42));
   config.head_align = 0.01 * (rec(ofs + 27) + 256 * rec(ofs + 28));
   config.head_bias = 0.01 * (rec(ofs + 29) + 256 * rec(ofs + 30));
   lsb = rec(ofs + 5);
   msb = rec(ofs + 6);
   config.sysconfig = decode_sysconfig(lsb, msb);
end


if (isempty(config.ncells)) %"second_set" was probably specified in error
   buf = [];
   return;
end


%otherwise, continue.
  
%%% fixed leader, but possibly variable data:
ofs = config.offsets(find(config.ids == id.flead));
buf.num_pings = rec(ofs + 11) + 256 * rec(ofs + 12);

%%% variable leader:
ofs = config.offsets(find(config.ids == id.vlead));
if nargin == 3,
   config.tr_depth = (rec(ofs + 17) + 256 * rec(ofs + 18))/10;
end
buf.ens_num = rec(ofs + 3) + 256 * rec(ofs + 4) + 65536 * rec(ofs + 12);

tt = rec(ofs + (5:11));
tt(1) = tt(1) + 1900;
if (tt(1) < 1980)  tt(1) = tt(1) + 100; end

if ~config.yearbase, config.yearbase = tt(1); end
buf.dday = to_day( config.yearbase, tt(1:6).') + tt(7) / 8640000;
buf.ymdhmsh = tt;

if out.ts
   buf.heading = (rec(ofs + 19) + 256 * rec(ofs + 20));
   buf.pitch   = (rec(ofs + 21) + 256 * rec(ofs + 22));
   buf.roll    = (rec(ofs + 23) + 256 * rec(ofs + 24));
   
   buf.temperature = rec(ofs + 27) + 256 * rec(ofs + 28);
   buf.soundspeed = rec(ofs + 15) + 256 * rec(ofs + 16);
end

% In the following blocks, the "min" should not be needed
% when finding the offsets; we may eliminate it.
% The empty check is needed, however.

%%% velocity:
if out.vel
   ofs = min(config.offsets(find(config.ids == id.vel)));
   ii = 2 + (1:2:(config.ncells*8));
   if isempty(ofs),
      a = NaN * ii;
   else
      a = rec(ofs + ii) + 256 * rec(ofs + 1 + ii);
   end
   buf.vel = reshape(a, 4, config.ncells).';
   % We are deferring the handling of negative numbers and NaNs.
end
   
%%% correlation:
if out.cor
   ofs = min(config.offsets(find(config.ids == id.cor)));
   ii = 2 + (1:(config.ncells*4));
   if isempty(ofs)
      buf.cor = reshape(NaN * ii, 4, config.ncells).';
   else
      buf.cor = reshape(rec(ofs + ii), 4, config.ncells).';
   end
end

%%% amp:
if out.amp
   ofs = min(config.offsets(find(config.ids == id.amp)));
   ii = 2 + (1:(config.ncells*4));
   if isempty(ofs)
      buf.amp = reshape(NaN * ii, 4, config.ncells).';
   else
      buf.amp = reshape(rec(ofs + ii), 4, config.ncells).';
   end
end

%%% pg:
if out.pg
   ofs = min(config.offsets(find(config.ids == id.pg)));
   ii = 2 + (1:(config.ncells*4));
   if isempty(ofs)
      buf.pg = reshape(NaN * ii, 4, config.ncells).';
   else
      buf.pg = reshape(rec(ofs + ii), 4, config.ncells).';
   end
end

%% BT:
if out.bt
   ofs = min(config.offsets(find(config.ids == id.bt)));
   if isempty(ofs)

      config.bt.BP = NaN;
      config.bt.BC = NaN;
      config.bt.BA = NaN;
      config.bt.BX = NaN;

      ii = (0:2:6);
      buf.bt.range = NaN*ii;
      buf.bt.vel =   NaN*ii;
      buf.bt.cor =   NaN*ii;
      buf.bt.amp =   NaN*ii;
      buf.bt.pg =    NaN*ii;
      buf.bt.rssi =  NaN*ii;

   else
      config.bt.BP = rec(ofs + 3) + 256 * rec(ofs + 4);
      config.bt.BC = rec(ofs + 7);
      config.bt.BA = rec(ofs + 8);
      config.bt.BX = rec(ofs + 71) + 256 * rec(ofs + 72);

      ii = (0:2:6); iii = 0:3;
      buf.bt.range = rec(ofs + ii + 17) + 256 * rec(ofs + ii + 18) + ...
                     65536 * rec(ofs + iii + 78);

      buf.bt.vel = rec(ofs + ii + 25) + 256 * rec(ofs + ii + 26);
      buf.bt.cor = rec(ofs + iii + 33);
      buf.bt.amp = rec(ofs + iii + 37);
      buf.bt.pg  = rec(ofs + iii + 41);
      buf.bt.rssi = rec(ofs + iii + 73);
   end
end

%% nav:

if out.nav
   ofs = min(config.offsets(find(config.ids == id.nav)));
   if isempty(ofs)
      buf.nav.sec_pc_minus_utc = NaN;
      buf.nav.txy1 = NaN * ones(3,1);
      buf.nav.txy2 = buf.nav.txy1;
   else
      buf.nav.sec_pc_minus_utc = 1e-3 * buf_long(rec(ofs + (11:14)));

      %why are we doing this when buf.ymdhms is already defined above?
      %yymd = [config.yearbase, rec(ofs + 5) + 256 * rec(ofs + 6),...
      %        rec(ofs + 4) , rec(ofs + 3)];
      day_base = to_day(config.yearbase, buf.ymdhmsh(1:3)');
      t1d = day_base + (1e-4 / 86400) * buf_long(rec(ofs + (7:10)));
      t2d = day_base + (1e-4 / 86400) * buf_long(rec(ofs + (23:26)));

      buf.nav.txy1(1) = t1d + round(buf.dday - t1d);
      buf.nav.txy2(1) = t2d + round(buf.dday - t2d);
      buf.nav.txy1(2:3) = decode_fix(rec(ofs + (15:22)));
      buf.nav.txy2(2:3) = decode_fix(rec(ofs + (27:34)));
   end
end

%--------------------------------------------------------
function c = decode_sysconfig(l, m)

freqs = [75, 150, 300, 600, 1200, 2400, 38];
freqbits = bitand(l, 7);
c.frequency = freqs(1 + freqbits);
c.up =  bitand(bitshift(l, -7), 1);
c.convex = bitand(bitshift(l, -3), 1);

angles = [15, 20, 30, NaN];
anglebits = bitand(m, 3);
c.angle = angles(1 + anglebits);



%---------------------------------------------
function s = to_signed(u)
s = u;
ineg = u > 32767;
s(ineg) = s(ineg) - 65536;
ibad = s == -32768;
s(ibad) = NaN;

%---------------------------------------------
function s = to_signed_long(u)
s = u;
ineg = u > 2147483647 ;
s(ineg) = s(ineg) - 4294967296;
ibad = s == -2147483648;
s(ibad) = NaN;

%---------------------------------------------
function s = buf_long(a)
s = a(1) + 256 * a(2) + 65536 * a(3) + 16777216 * a(4);
s = to_signed_long(s);

%---------------------------------------------
function xy = decode_fix(r)
xy = [buf_long(r(5:8)); buf_long(r(1:4))] * 180 / 2147483648;

