platforms/nuttx/src/px4/nxp/kinetis/hrt/hrt.c
static void hrt_ppm_decode(uint32_t status)
{
	uint16_t count = rCNV_PPM;
	uint16_t width;
	uint16_t interval;
	unsigned i;

	/* how long since the last edge? - this handles counter wrapping implicitly. */
	width = count - ppm.last_edge;

#if PPM_DEBUG
	ppm_edge_history[ppm_edge_next++] = width;

	if (ppm_edge_next >= EDGE_BUFFER_COUNT) {
		ppm_edge_next = 0;
	}

#endif

	/*
	 * if this looks like a start pulse, then push the last set of values
	 * and reset the state machine
	 */
	if (width >= PPM_MIN_START) {

		/*
		 * If the number of channels changes unexpectedly, we don't want
		 * to just immediately jump on the new count as it may be a result
		 * of noise or dropped edges.  Instead, take a few frames to settle.
		 */
		if (ppm.next_channel != ppm_decoded_channels) {
			static unsigned new_channel_count;
			static unsigned new_channel_holdoff;

			if (new_channel_count != ppm.next_channel) {
				/* start the lock counter for the new channel count */
				new_channel_count = ppm.next_channel;
				new_channel_holdoff = PPM_CHANNEL_LOCK;

			} else if (new_channel_holdoff > 0) {
				/* this frame matched the last one, decrement the lock counter */
				new_channel_holdoff--;

			} else {
				/* we have seen PPM_CHANNEL_LOCK frames with the new count, accept it */
				ppm_decoded_channels = new_channel_count;
				new_channel_count = 0;
			}

		} else {
			/* frame channel count matches expected, let's use it */
			if (ppm.next_channel >= PPM_MIN_CHANNELS) {
				for (i = 0; i < ppm.next_channel; i++) {
					ppm_buffer[i] = ppm_temp_buffer[i];
				}

				ppm_last_valid_decode = hrt_absolute_time();

			}
		}

		/* reset for the next frame */
		ppm.next_channel = 0;

		/* next edge is the reference for the first channel */
		ppm.phase = ARM;

		ppm.last_edge = count;
		return;
	}

	switch (ppm.phase) {
	case UNSYNCH:
		/* we are waiting for a start pulse - nothing useful to do here */
		break;

	case ARM:

		/* we expect a pulse giving us the first mark */
		if (width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH) {
			goto error;        /* pulse was too short or too long */
		}

		/* record the mark timing, expect an inactive edge */
		ppm.last_mark = ppm.last_edge;

		/* frame length is everything including the start gap */
		ppm_frame_length = (uint16_t)(ppm.last_edge - ppm.frame_start);
		ppm.frame_start = ppm.last_edge;
		ppm.phase = ACTIVE;
		break;

	case INACTIVE:

		/* we expect a short pulse */
		if (width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH) {
			goto error;        /* pulse was too short or too long */
		}

		/* this edge is not interesting, but now we are ready for the next mark */
		ppm.phase = ACTIVE;
		break;

	case ACTIVE:
		/* determine the interval from the last mark */
		interval = count - ppm.last_mark;
		ppm.last_mark = count;

#if PPM_DEBUG
		ppm_pulse_history[ppm_pulse_next++] = interval;

		if (ppm_pulse_next >= EDGE_BUFFER_COUNT) {
			ppm_pulse_next = 0;
		}

#endif

		/* if the mark-mark timing is out of bounds, abandon the frame */
		if ((interval < PPM_MIN_CHANNEL_VALUE) || (interval > PPM_MAX_CHANNEL_VALUE)) {
			goto error;
		}

		/* if we have room to store the value, do so */
		if (ppm.next_channel < PPM_MAX_CHANNELS) {
			ppm_temp_buffer[ppm.next_channel++] = interval;
		}

		ppm.phase = INACTIVE;
		break;

	}

	ppm.last_edge = count;
	return;

	/* the state machine is corrupted; reset it */

error:
	/* we don't like the state of the decoder, reset it and try again */
	ppm.phase = UNSYNCH;
	ppm_decoded_channels = 0;

}
/**
 * Handle the PPM decoder state machine.
 */
Handle the PPM decoder state machine.
Handle the PPM decoder state machine .
static void hrt_ppm_decode(uint32_t status)
{
	uint16_t count = rCNV_PPM;
	uint16_t width;
	uint16_t interval;
	unsigned i;
	width = count - ppm.last_edge;
#if PPM_DEBUG
	ppm_edge_history[ppm_edge_next++] = width;
	if (ppm_edge_next >= EDGE_BUFFER_COUNT) {
		ppm_edge_next = 0;
	}
#endif
	if (width >= PPM_MIN_START) {
		if (ppm.next_channel != ppm_decoded_channels) {
			static unsigned new_channel_count;
			static unsigned new_channel_holdoff;
			if (new_channel_count != ppm.next_channel) {
				new_channel_count = ppm.next_channel;
				new_channel_holdoff = PPM_CHANNEL_LOCK;
			} else if (new_channel_holdoff > 0) {
				new_channel_holdoff--;
			} else {
				ppm_decoded_channels = new_channel_count;
				new_channel_count = 0;
			}
		} else {
			if (ppm.next_channel >= PPM_MIN_CHANNELS) {
				for (i = 0; i < ppm.next_channel; i++) {
					ppm_buffer[i] = ppm_temp_buffer[i];
				}
				ppm_last_valid_decode = hrt_absolute_time();
			}
		}
		ppm.next_channel = 0;
		ppm.phase = ARM;
		ppm.last_edge = count;
		return;
	}
	switch (ppm.phase) {
	case UNSYNCH:
		break;
	case ARM:
		if (width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH) {
			goto error;        
		}
		ppm.last_mark = ppm.last_edge;
		ppm_frame_length = (uint16_t)(ppm.last_edge - ppm.frame_start);
		ppm.frame_start = ppm.last_edge;
		ppm.phase = ACTIVE;
		break;
	case INACTIVE:
		if (width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH) {
			goto error;        
		}
		ppm.phase = ACTIVE;
		break;
	case ACTIVE:
		interval = count - ppm.last_mark;
		ppm.last_mark = count;
#if PPM_DEBUG
		ppm_pulse_history[ppm_pulse_next++] = interval;
		if (ppm_pulse_next >= EDGE_BUFFER_COUNT) {
			ppm_pulse_next = 0;
		}
#endif
		if ((interval < PPM_MIN_CHANNEL_VALUE) || (interval > PPM_MAX_CHANNEL_VALUE)) {
			goto error;
		}
		if (ppm.next_channel < PPM_MAX_CHANNELS) {
			ppm_temp_buffer[ppm.next_channel++] = interval;
		}
		ppm.phase = INACTIVE;
		break;
	}
	ppm.last_edge = count;
	return;
error:
	ppm.phase = UNSYNCH;
	ppm_decoded_channels = 0;
}
static void hrt_ppm_decode ( uint32_t status ) { uint16_t count = rCNV_PPM ; uint16_t width ; uint16_t interval ; unsigned i ; width = count - ppm . last_edge ; #if PPM_DEBUG ppm_edge_history [ ppm_edge_next ++ ] = width ; if ( ppm_edge_next >= EDGE_BUFFER_COUNT ) { ppm_edge_next = 0 ; } #endif if ( width >= PPM_MIN_START ) { if ( ppm . next_channel != ppm_decoded_channels ) { static unsigned new_channel_count ; static unsigned new_channel_holdoff ; if ( new_channel_count != ppm . next_channel ) { new_channel_count = ppm . next_channel ; new_channel_holdoff = PPM_CHANNEL_LOCK ; } else if ( new_channel_holdoff > 0 ) { new_channel_holdoff -- ; } else { ppm_decoded_channels = new_channel_count ; new_channel_count = 0 ; } } else { if ( ppm . next_channel >= PPM_MIN_CHANNELS ) { for ( i = 0 ; i < ppm . next_channel ; i ++ ) { ppm_buffer [ i ] = ppm_temp_buffer [ i ] ; } ppm_last_valid_decode = hrt_absolute_time ( ) ; } } ppm . next_channel = 0 ; ppm . phase = ARM ; ppm . last_edge = count ; return ; } switch ( ppm . phase ) { case UNSYNCH : break ; case ARM : if ( width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH ) { goto error ; } ppm . last_mark = ppm . last_edge ; ppm_frame_length = ( uint16_t ) ( ppm . last_edge - ppm . frame_start ) ; ppm . frame_start = ppm . last_edge ; ppm . phase = ACTIVE ; break ; case INACTIVE : if ( width < PPM_MIN_PULSE_WIDTH || width > PPM_MAX_PULSE_WIDTH ) { goto error ; } ppm . phase = ACTIVE ; break ; case ACTIVE : interval = count - ppm . last_mark ; ppm . last_mark = count ; #if PPM_DEBUG ppm_pulse_history [ ppm_pulse_next ++ ] = interval ; if ( ppm_pulse_next >= EDGE_BUFFER_COUNT ) { ppm_pulse_next = 0 ; } #endif if ( ( interval < PPM_MIN_CHANNEL_VALUE ) || ( interval > PPM_MAX_CHANNEL_VALUE ) ) { goto error ; } if ( ppm . next_channel < PPM_MAX_CHANNELS ) { ppm_temp_buffer [ ppm . next_channel ++ ] = interval ; } ppm . phase = INACTIVE ; break ; } ppm . last_edge = count ; return ; error : ppm . phase = UNSYNCH ; ppm_decoded_channels = 0 ; }
Handle the PPM decoder state machine.
Handle the PPM decoder state machine .
/* how long since the last edge? - this handles counter wrapping implicitly. */ /*
	 * if this looks like a start pulse, then push the last set of values
	 * and reset the state machine
	 */ /*
		 * If the number of channels changes unexpectedly, we don't want
		 * to just immediately jump on the new count as it may be a result
		 * of noise or dropped edges.  Instead, take a few frames to settle.
		 */ /* start the lock counter for the new channel count */ /* this frame matched the last one, decrement the lock counter */ /* we have seen PPM_CHANNEL_LOCK frames with the new count, accept it */ /* frame channel count matches expected, let's use it */ /* reset for the next frame */ /* next edge is the reference for the first channel */ /* we are waiting for a start pulse - nothing useful to do here */ /* we expect a pulse giving us the first mark */ /* pulse was too short or too long */ /* record the mark timing, expect an inactive edge */ /* frame length is everything including the start gap */ /* we expect a short pulse */ /* pulse was too short or too long */ /* this edge is not interesting, but now we are ready for the next mark */ /* determine the interval from the last mark */ /* if the mark-mark timing is out of bounds, abandon the frame */ /* if we have room to store the value, do so */ /* the state machine is corrupted; reset it */ /* we don't like the state of the decoder, reset it and try again */