Skip to content

File acq_private.h

File List > acq > acq_private.h

Go to the documentation of this file

#ifndef ACQ_PRIVATE_H
#define ACQ_PRIVATE_H

#include "doppler/acq/acq_core.h"

#include <math.h>
#include <stddef.h>

static inline int
acq_rate_better (size_t h, float stat, float best)
{
  return h == 0 || stat > best;
}

/* The tile-edge alias (doppler#1270). A tile de-rotates by its own
 * centre, so an emitter near the edge between two tiles leaves half a
 * span of residual inside the epoch in both, and the slow-time transform
 * folds modulo the epoch rate: the two neighbours read the emitter at the
 * same row index and, measured on the pool's grid at 45 dB-Hz, within
 * 0.03 dB of each other -- the pick is the noise's, one tile low or high,
 * half the time on the edge and one time in six 68 Hz inside it. The
 * block can tell when it is asked at the ROW's frequency: the raw epochs
 * mixed by the row's own frequency correlate with the replica at the
 * pick's code phase with under half a row of residual, and mixed by that
 * frequency one span off the residual is exactly one cycle per epoch, a
 * correlation of zero. Three hypotheses -- the row, one span down, one
 * span up -- summed over the block's epochs non-coherently (a data
 * transition inside an epoch costs every hypothesis the same), each
 * epoch's column walked by the hypothesis's own code rate as
 * acq_tile_epoch walks the tile's. Returns the native row that wins;
 * the pick's own row when the engine is not block-coherent and tiled. */
static inline size_t
acq_resolve_tile_alias (const dp_acq_state_t *st, size_t row, size_t col)
{
  const size_t D = st->coherent_bins, nx = st->code_bins;
  const size_t W = st->window_bins, rows = W * D;
  if (!st->blk_raw || W <= 1 || D <= 1)
    return row;
  const double f0 = (double)dp_fftfreq_index (row, rows) * st->doppler_res_hz;
  const double span = st->fs / (double)nx;
  double       best = -1.0;
  long         win  = 0;
  for (long h = -1; h <= 1; h++)
    {
      const double f = f0 + (double)h * span;
      /* The code-rate walk of this hypothesis, samples per epoch: a
         positive Doppler runs the chip clock fast and the peak sits
         EARLIER each epoch (acq_tile_epoch's convention). */
      const double d  = st->carrier_freq_hz > 0.0
                            ? f / st->carrier_freq_hz * (double)nx
                            : 0.0;
      double       pw = 0.0;
      for (size_t e = 0; e < D; e++)
        {
          const long sh = lround (((double)e - 0.5 * (double)(D - 1)) * d);
          const long c0 = (((long)col - sh) % (long)nx + (long)nx) % (long)nx;
          const double _Complex acc = dp_acq_cell_corr (
              st, st->blk_raw + e * nx, (size_t)c0, f, (double)(e * nx));
          pw += creal (acc) * creal (acc) + cimag (acc) * cimag (acc);
        }
      if (pw > best)
        {
          best = pw;
          win  = h;
        }
    }
  return (size_t)(((long)row + win * (long)D + (long)rows) % (long)rows);
}

#endif /* ACQ_PRIVATE_H */