function [inl,dnl] = inldnl(x, delta)
% INLDNL   compute INL and DNL from converter output x
%      x        output from ADC
%      delta    spacing between codes. Default: 1
%
% Assumptions & limitations:
%      - uniform quantizer
%      - TUT input to produce x: linear ramp

if nargin == 0
   error('must specify ADC output');
end
if nargin == 1
   delta = 1;
end

% compute histogram
[counts,centers] = hist(x, min(x):delta:max(x));

% eliminate end bins
counts(1)   = [];
counts(end) = [];

dnl = counts/mean(counts) - 1;
inl = cumsum(dnl);
inl = inl - linspace(inl(1), inl(end), length(inl));

if nargout==0
   % plot result
   N = length(dnl);
   if N > 16
      fmt = 'r-';
   else
      fmt = 'ro:';
   end
   subplot(2,1,1);
   plot(1:N, dnl, fmt, [1 N], [1 -1; 1 -1], 'b:');
   fixfig;
   xlabel('bin');  ylabel('DNL  [in LSB]');
   maxdnl = ceil(max(dnl));
   axis([1 N floor(min(dnl)) maxdnl+1]);
   text(0.1*N+1, maxdnl+0.2, ...
      sprintf('avg=%.2g,   std.dev=%.2g,   range=%.2g', ...
      mean(dnl),  std(dnl),  max(dnl)-min(dnl)));
   title(sprintf('DNL and INL of %.1g Bit converter (from histogram testing)', ...
      log2(N)));
   subplot(2,1,2);
   plot(1:N, inl, fmt, [1 N], [1 -1; 1 -1], 'b:');
   fixfig;
   xlabel('bin');  ylabel('INL  [in LSB]');
   maxinl = ceil(max(inl));
   axis([1 N floor(min(inl)) maxinl+1]);
   text(0.1*N+1, maxinl+0.2, ...
      sprintf('avg=%.2g,   std.dev=%.2g,   range=%.2g', ...
      mean(inl),  std(inl),  max(inl)-min(inl)));
end
