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; } } }
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; }
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++; } } }
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; }