void _lowpass_filter_step(uint32_t n_dims, value_t *input,
                          value_t *output, void *pars)
{
  // Cast the params
  lowpass_state_t *params = (lowpass_state_t *) pars;
  register int32_t a = bitsk(params->a);
  register int32_t b = bitsk(params->b);

  // Apply the filter to every dimension (realised as a Direct Form I digital
  // filter).
  for (uint32_t d = 0; d < n_dims; d++)
  {
    // The following is equivalent to:
    //
    //    output[d] *= params->a;
    //    output[d] += input[d] * params->b;

    // Compute the next value in a register
    register int64_t next_output;

    // Perform the first multiply
    int32_t current_output = bitsk(output[d]);
    next_output = __smull(current_output, a);

    // Perform the multiply accumulate
    int32_t current_input = bitsk(input[d]);
    next_output = __smlal(next_output, current_input, b);

    // Scale the result back down to store it
    output[d] = kbits(convert_s32_30_s16_15(next_output));
  }
}
Beispiel #2
0
void DoFakeCalibSequence(_Fract* yRateBias, volatile _Fract* yRateNoise, 
                         _Fract* xAxisBias, volatile _Fract* xAxisNoise, 
                         _Fract* zAxisBias, volatile _Fract* zAxisNoise,
                         _Fract* gravity,   _Accum* gyroGain)
{
   int16_t yRateBiasInt  = FakeYrateBias;
   int16_t yRateNoiseInt = FakeYrateNoise;
   // Fake condtions
   *yRateBias  = rbits(yRateBiasInt);
   *xAxisBias  = rbits(FakeXaxisBias);
   *zAxisBias  = rbits(FakeZaxisBias);
   *gravity    = rbits(FakeGravity);
   gSquared    = (*gravity)*(*gravity);

   *gyroGain   = kbits(FakeGyroGain);
   *yRateNoise = rbits(yRateNoiseInt);
   *xAxisNoise = rbits(FakeXaxisNoise);
   *zAxisNoise = rbits(FakeZaxisNoise);

#ifdef ForceGyroCalib
   waitUntilFacing(CircuitSideUp, 0, 0, 0);
   _Accum gyroIntegral = 0;
   waitUntilFacing(CircuitSideDown, &upYAverage, &upYNoise, &gyroIntegral);
   // gyro integral should correspond to a 180 degree flip.
   // 180 deg = 1 in binary angle
   *gyroGain = (1.0/gyroIntegral);
#endif
}
void _lti_filter_step(uint32_t n_dims, value_t *input,
                      value_t *output, void *s)
{
  // Cast the state
  lti_state_t *state = (lti_state_t *) s;

  // Apply the filter to every dimension (realised as a Direct Form I digital
  // filter).
  for (uint32_t d = n_dims, dd = n_dims - 1; d > 0; d--, dd--)
  {
    // Point to the correct previous x and y values.
    ab_t *xy = &state->xyz[dd * state->order];

    // Create the new output value for this dimension
    register int64_t output_val = 0;

    // Direct Form I filter
    // `m` acts as an index into the ring buffer of historic input and output.
    for (uint32_t k=0, m = state->n; k < state->order; k++)
    {
      // Update the index into the ring buffer, if this would go negative it
      // wraps to the top of the buffer.
      if (m == 0)
      {
        m += state->order;
      }
      m--;

      // Apply this part of the filter
      // Equivalent to:
      //     output[dd] += ab.a * xyz.a;
      //     output[dd] += ab.b * xyz.b;
      ab_t ab = state->abs[k];
      ab_t xyz = xy[m];
      output_val = __smlal(output_val, bitsk(ab.a), bitsk(xyz.a));
      output_val = __smlal(output_val, bitsk(ab.b), bitsk(xyz.b));
    }

    // Include the initial new input
    xy[state->n].b = input[dd];

    // Save the current output for later steps
    output[dd] = kbits(convert_s32_30_s16_15(output_val));
    xy[state->n].a = output[dd];
  }

  // Rotate the ring buffer by moving the starting pointer, if the starting
  // pointer would go beyond the end of the buffer it is returned to the start.
  if (++state->n == state->order)
  {
    state->n = 0;
  }
}