    // save the clk_sys frequency in clocks per us
    // cache the PIO cycles per us
    clocks_per_us = (clock_get_hz(clk_sys) + 500000) / 1000000;

    // internal fields to keep track of the previous state:
    uint prev_trans_pos, prev_trans_us;
    uint prev_step_us;
    uint prev_low, prev_high;
    uint idle_stop_sample_count;
    int speed_2_20;
    int stopped;

    // position reset value
    uint internal_position;

    // initialize the "previous state"
    read_pio_data(&step, &prev_step_us, &prev_trans_us, &forward);

    position = get_step_start_transition_pos(step) + 32;

    // set all fields to zero by default
    prev_trans_pos = 0;
    prev_low = 0;
    prev_high = 0;
    idle_stop_sample_count = 0;
    speed_2_20 = 0;
    speed = 0;

/**************************************************************
// read the encoder state and update "speed", "position" and "step". As a
    void update(void);

    uint new_step, step_us, transition_us, transition_pos, low, high;
    int forward, speed_high, speed_low;

    // read the current encoder state from the PIO
    *cycles = ...
    *new_step = ...
    *step_us = time_us_32(); // now
    *transition_us = *step_us - ((cycles * 13) / clocks_per_us);
    forward = ...

    low = get_step_start_transition_pos((new_step << 6) & 0xFFFFFF00) | calibration_data[step & 3];
    high = get_step_start_transition_pos((new_step + 1) << 6 & 0xFFFFFF00) | calibration_data[step & 3];

if (transition)
{
      speed_2_20 = ((int64_t) (transition_pos - prev_trans_pos) << 20)
           / transition_us - prev_trans_us;

    prev_trans_pos = transition_pos;
    prev_trans_us = transition_us;
}

      // otherwise use the slopes from the last transition to now
      speed_high = substep_calc_speed(high - prev_trans_pos, step_us - prev_trans_us);
      speed_low = substep_calc_speed(low - prev_trans_pos, step_us - prev_trans_us);

substep_calc_speed converts a speed in normal units to speed_2_20 units
    // make sure the current speed estimate is between the maximum and
    // minimum values obtained from the step slopes
    if (speed_2_20 > speed_high)
      speed_2_20 = speed_high;
    if (speed_2_20 < speed_low)
      speed_2_20 = speed_low;

    // convert the speed units from "sub-steps per 2^20 us" to "sub-steps
    // per second"
    speed = (speed_2_20 * 62500LL) >> 16;

    // estimate the current position by applying the speed estimate to the
    // most recent transition
    internal_position = prev_trans_pos + (((int64_t)speed_2_20 * (step_us - transition_us)) >> 20);

    // make sure the position estimate is between "low" and "high", as we
    // can be sure the actual current position must be in this range
    if ((int)(internal_position - high) > 0)
      {
        internal_position = high;
	double speed_limit = ((double) (high - prev_trans_pos))/((double) (step_us - prev_trans_us));
	if ( speed > speed_limit )
	  speed = speed_limit;
      }
    else if ((int)(internal_position - low) < 0)
      {
        internal_position = low;
	double speed_limit = ((double) (low - prev_trans_pos))/((double) (step_us - prev_trans_us));
	if ( speed < speed_limit )
	  speed = speed_limit;
      }
	
