Пример #1
0
static void
comms_handle_frame(void *arg, const void *buffer, size_t length)
{
	const uint16_t *type = (const uint16_t *)buffer;


	/* make sure it's what we are expecting */
	if (length > 2) {
		switch (*type) {
		case F2I_MAGIC:
			comms_handle_command(buffer, length);
			break;

		case F2I_CONFIG_MAGIC:
			comms_handle_config(buffer, length);
			break;

		case F2I_MIXER_MAGIC:
			mixer_handle_text(buffer, length);
			break;

		default:
			break;
		}
	}
}
Пример #2
0
int
registers_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values)
{

	switch (page) {

		/* handle bulk controls input */
	case PX4IO_PAGE_CONTROLS:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_GROUPS * PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			r_page_controls[offset] = *values;

			offset++;
			num_values--;
			values++;
		}

		system_state.fmu_data_received_time = hrt_absolute_time();
		r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK;
		r_status_flags &= ~PX4IO_P_STATUS_FLAGS_RAW_PWM;
		
		break;

		/* handle raw PWM input */
	case PX4IO_PAGE_DIRECT_PWM:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			if (*values != PWM_IGNORE_THIS_CHANNEL) {
				r_page_servos[offset] = *values;
			}

			offset++;
			num_values--;
			values++;
		}

		system_state.fmu_data_received_time = hrt_absolute_time();
		r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK | PX4IO_P_STATUS_FLAGS_RAW_PWM;

		break;

		/* handle setup for servo failsafe values */
	case PX4IO_PAGE_FAILSAFE_PWM:

		/* copy channel data */
		while ((offset < PX4IO_SERVO_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values < PWM_LOWEST_MIN) {
				r_page_servo_failsafe[offset] = PWM_LOWEST_MIN;
			} else if (*values > PWM_HIGHEST_MAX) {
				r_page_servo_failsafe[offset] = PWM_HIGHEST_MAX;
			} else {
				r_page_servo_failsafe[offset] = *values;
			}

			/* flag the failsafe values as custom */
			r_setup_arming |= PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM;

			offset++;
			num_values--;
			values++;
		}
		break;

	case PX4IO_PAGE_CONTROL_MIN_PWM:

		/* copy channel data */
		while ((offset < PX4IO_SERVO_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values > PWM_HIGHEST_MIN) {
				r_page_servo_control_min[offset] = PWM_HIGHEST_MIN;
			} else if (*values < PWM_LOWEST_MIN) {
				r_page_servo_control_min[offset] = PWM_LOWEST_MIN;
			} else {
				r_page_servo_control_min[offset] = *values;
			}

			offset++;
			num_values--;
			values++;
		}
		break;
	
	case PX4IO_PAGE_CONTROL_MAX_PWM:

		/* copy channel data */
		while ((offset < PX4IO_SERVO_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values > PWM_HIGHEST_MAX) {
				r_page_servo_control_max[offset] = PWM_HIGHEST_MAX;
			} else if (*values < PWM_LOWEST_MAX) {
				r_page_servo_control_max[offset] = PWM_LOWEST_MAX;
			} else {
				r_page_servo_control_max[offset] = *values;
			}

			offset++;
			num_values--;
			values++;
		}
		break;

	case PX4IO_PAGE_DISARMED_PWM:
		{
			/* flag for all outputs */
			bool all_disarmed_off = true;

			/* copy channel data */
			while ((offset < PX4IO_SERVO_COUNT) && (num_values > 0)) {

				if (*values == 0) {
					/* 0 means disabling always PWM */
					r_page_servo_disarmed[offset] = 0;
				} else if (*values < PWM_LOWEST_MIN) {
					r_page_servo_disarmed[offset] = PWM_LOWEST_MIN;
					all_disarmed_off = false;
				} else if (*values > PWM_HIGHEST_MAX) {
					r_page_servo_disarmed[offset] = PWM_HIGHEST_MAX;
					all_disarmed_off = false;
				} else {
					r_page_servo_disarmed[offset] = *values;
					all_disarmed_off = false;
				}

				offset++;
				num_values--;
				values++;
			}

			if (all_disarmed_off) {
				/* disable PWM output if disarmed */
				r_setup_arming &= ~(PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE);
			} else {
				/* enable PWM output always */
				r_setup_arming |= PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE;
			}
		}
		break;

		/* handle text going to the mixer parser */
	case PX4IO_PAGE_MIXERLOAD:
		/* do not change the mixer if FMU is armed and IO's safety is off
		 * this state defines an active system. This check is done in the
		 * text handling function.
		 */
		return mixer_handle_text(values, num_values * sizeof(*values));

	default:
		/* avoid offset wrap */
		if ((offset + num_values) > 255)
			num_values = 255 - offset;

		/* iterate individual registers, set each in turn */
		while (num_values--) {
			if (registers_set_one(page, offset, *values))
				return -1;
			offset++;
			values++;
		}
		break;
	}
	return 0;
}
Пример #3
0
void
registers_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values)
{

	switch (page) {

		/* handle bulk controls input */
	case PX4IO_PAGE_CONTROLS:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			r_page_controls[offset] = *values;

			offset++;
			num_values--;
			values++;
		}

		system_state.fmu_data_received_time = hrt_absolute_time();
		r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK;
		r_status_flags &= ~PX4IO_P_STATUS_FLAGS_RAW_PWM;
		
		// wake up daemon to trigger mixer
		daemon_wakeup();
		break;

		/* handle raw PWM input */
	case PX4IO_PAGE_DIRECT_PWM:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			r_page_servos[offset] = *values;

			offset++;
			num_values--;
			values++;
		}

		system_state.fmu_data_received_time = hrt_absolute_time();
		r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK | PX4IO_P_STATUS_FLAGS_RAW_PWM;

		// wake up the main thread to trigger mixer
		daemon_wakeup();
		break;

		/* handle setup for servo failsafe values */
	case PX4IO_PAGE_FAILSAFE_PWM:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			r_page_servo_failsafe[offset] = *values;

			offset++;
			num_values--;
			values++;
		}
		break;

		/* handle text going to the mixer parser */
	case PX4IO_PAGE_MIXERLOAD:
		mixer_handle_text(values, num_values * sizeof(*values));
		break;

	default:
		/* avoid offset wrap */
		if ((offset + num_values) > 255)
			num_values = 255 - offset;

		/* iterate individual registers, set each in turn */
		while (num_values--) {
			if (registers_set_one(page, offset, *values))
				break;
			offset++;
			values++;
		}
	}
}
Пример #4
0
int
registers_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values)
{

	switch (page) {

	/* handle bulk controls input */
	case PX4IO_PAGE_CONTROLS:

		/* copy channel data */
		while ((offset < PX4IO_CONTROL_GROUPS * PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {

			/* XXX range-check value? */
			r_page_controls[offset] = *values;

			offset++;
			num_values--;
			values++;
		}

		system_state.fmu_data_received_time = hrt_absolute_time();
		r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK;
		r_status_flags &= ~PX4IO_P_STATUS_FLAGS_RAW_PWM;

		break;

	/* handle raw PWM input */
	case PX4IO_PAGE_DIRECT_PWM: {

			/* copy channel data */
			uint16_t widest_pulse = 0;

			while ((offset < PX4IO_ACTUATOR_COUNT) && (num_values > 0)) {

				/* XXX range-check value? */
				if (*values != PWM_IGNORE_THIS_CHANNEL) {
					r_page_direct_pwm[offset] = *values;

					if (*values > widest_pulse) {
						widest_pulse = *values;
					}
				}

				offset++;
				num_values--;
				values++;
			}

            if (widest_pulse > 2300) {
                // don't allow extreme pulses to cause issues with oneshot delays
                widest_pulse = 2300;
            }

			system_state.fmu_data_received_time = hrt_absolute_time();
			r_status_flags |= PX4IO_P_STATUS_FLAGS_FMU_OK | PX4IO_P_STATUS_FLAGS_RAW_PWM;

			if (r_setup_features & PX4IO_P_SETUP_FEATURES_ONESHOT) {
				/*
				  in oneshot we run the mixer as soon as we
				  get new data from the FMU
				 */
				mixer_tick();

				/*
				  we now need to trigger the output pulses,
				  ensuring that the new pulses don't interrupt
				  the previous pulses. We add a 50 usec safety
				  margin to ensure the ESC has registered the
				  end of the previous pulses.
				 */
				static hrt_abstime oneshot_delay_till;
				hrt_abstime now = hrt_absolute_time();

				if (now < oneshot_delay_till) {
					up_udelay(oneshot_delay_till - now);
				}

				up_pwm_servo_trigger(r_setup_pwm_rates);
				oneshot_delay_till = hrt_absolute_time() + widest_pulse + 50;
			}

			break;
		}

	/* handle setup for servo failsafe values */
	case PX4IO_PAGE_FAILSAFE_PWM:

		/* copy channel data */
		while ((offset < PX4IO_ACTUATOR_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values < PWM_LOWEST_MIN) {
				r_page_servo_failsafe[offset] = PWM_LOWEST_MIN;

			} else if (*values > PWM_HIGHEST_MAX) {
				r_page_servo_failsafe[offset] = PWM_HIGHEST_MAX;

			} else {
				r_page_servo_failsafe[offset] = *values;
			}

			/* flag the failsafe values as custom */
			r_setup_arming |= PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM;

			offset++;
			num_values--;
			values++;
		}

		break;

	case PX4IO_PAGE_CONTROL_MIN_PWM:

		/* copy channel data */
		while ((offset < PX4IO_ACTUATOR_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values > PWM_HIGHEST_MIN) {
				r_page_servo_control_min[offset] = PWM_HIGHEST_MIN;

			} else if (*values < PWM_LOWEST_MIN) {
				r_page_servo_control_min[offset] = PWM_LOWEST_MIN;

			} else {
				r_page_servo_control_min[offset] = *values;
			}

			offset++;
			num_values--;
			values++;
		}

		break;

	case PX4IO_PAGE_CONTROL_MAX_PWM:

		/* copy channel data */
		while ((offset < PX4IO_ACTUATOR_COUNT) && (num_values > 0)) {

			if (*values == 0) {
				/* ignore 0 */
			} else if (*values > PWM_HIGHEST_MAX) {
				r_page_servo_control_max[offset] = PWM_HIGHEST_MAX;

			} else if (*values < PWM_LOWEST_MAX) {
				r_page_servo_control_max[offset] = PWM_LOWEST_MAX;

			} else {
				r_page_servo_control_max[offset] = *values;
			}

			offset++;
			num_values--;
			values++;
		}

		break;

	case PX4IO_PAGE_DISARMED_PWM: {
			/* flag for all outputs */
			bool all_disarmed_off = true;

			/* copy channel data */
			while ((offset < PX4IO_ACTUATOR_COUNT) && (num_values > 0)) {

				if (*values == 0) {
					/* 0 means disabling always PWM */
					r_page_servo_disarmed[offset] = 0;

				} else if (*values < PWM_LOWEST_MIN) {
					r_page_servo_disarmed[offset] = PWM_LOWEST_MIN;
					all_disarmed_off = false;

				} else if (*values > PWM_HIGHEST_MAX) {
					r_page_servo_disarmed[offset] = PWM_HIGHEST_MAX;
					all_disarmed_off = false;

				} else {
					r_page_servo_disarmed[offset] = *values;
					all_disarmed_off = false;
				}

				offset++;
				num_values--;
				values++;
			}

			if (all_disarmed_off) {
				/* disable PWM output if disarmed */
				r_setup_arming &= ~(PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE);

			} else {
				/* enable PWM output always */
				r_setup_arming |= PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE;
			}
		}
		break;

	/* handle text going to the mixer parser */
	case PX4IO_PAGE_MIXERLOAD:
		/* do not change the mixer if FMU is armed and IO's safety is off
		 * this state defines an active system. This check is done in the
		 * text handling function.
		 */
		return mixer_handle_text(values, num_values * sizeof(*values));

	default:

		/* avoid offset wrap */
		if ((offset + num_values) > 255) {
			num_values = 255 - offset;
		}

		/* iterate individual registers, set each in turn */
		while (num_values--) {
			if (registers_set_one(page, offset, *values)) {
				return -1;
			}

			offset++;
			values++;
		}

		break;
	}

	return 0;
}