void pwm_init(void){
	*AT91C_PMC_PCER |= (1<<AT91C_ID_PWMC);
	*AT91C_PIOA_PDR |= PWM_MASK;
	*AT91C_PIOA_BSR |= PWM_MASK;
	#if ORIGINAL_FREQ
	pwm_configure_clock(0x00000014);
	#elif DOUBLED_FREQ
	pwm_configure_clock(0x0000060F);
	#endif
	pwm_configure_channel(0, AT91C_PWMC_CPRE_MCKA, 0, 1);
	pwm_configure_channel(1, AT91C_PWMC_CPRE_MCKA, 0, 1);
	pwm_configure_channel(2, AT91C_PWMC_CPRE_MCKA, 0, 1);	
	pwm_configure_channel(3, AT91C_PWMC_CPRE_MCKA, 0, 1);
	pwm_set_period(0, 4800);
	pwm_set_period(1, 4800);
	pwm_set_period(2, 4800);
	pwm_set_period(3, 4800);
	pwm_set_duty_cycle(0, 0);
	pwm_set_duty_cycle(1, 0);
	pwm_set_duty_cycle(2, 0);
	pwm_set_duty_cycle(3, 0);	 //here must set 0 first, or the polarity will be wrong
	pwm_enable_channel(0);
	pwm_enable_channel(1);
	pwm_enable_channel(2);
	pwm_enable_channel(3);
	pwm_set_duty_cycle(0, 2400);
	pwm_set_duty_cycle(1, 2400);
	pwm_set_duty_cycle(2, 2400);
	pwm_set_duty_cycle(3, 2400);
}
Beispiel #2
0
static int
registers_set_one(uint8_t page, uint8_t offset, uint16_t value)
{
	switch (page) {

	case PX4IO_PAGE_STATUS:
		switch (offset) {
		case PX4IO_P_STATUS_ALARMS:
			/* clear bits being written */
			r_status_alarms &= ~value;
			break;

		case PX4IO_P_STATUS_FLAGS:

			/*
			 * Allow FMU override of arming state (to allow in-air restores),
			 * but only if the arming state is not in sync on the IO side.
			 */

			if (PX4IO_P_STATUS_FLAGS_MIXER_OK & value) {
				r_status_flags |= PX4IO_P_STATUS_FLAGS_MIXER_OK;

			} else if (!(r_status_flags & PX4IO_P_STATUS_FLAGS_ARM_SYNC)) {
				r_status_flags = value;

			}

			if (PX4IO_P_STATUS_FLAGS_MIXER_OK & r_status_flags) {

				/* update failsafe values, now that the mixer is set to ok */
				mixer_set_failsafe();
			}

			break;

		default:
			/* just ignore writes to other registers in this page */
			break;
		}

		break;

	case PX4IO_PAGE_SETUP:
		switch (offset) {
		case PX4IO_P_SETUP_FEATURES:

			value &= PX4IO_P_SETUP_FEATURES_VALID;

			/* some of the options conflict - give S.BUS out precedence, then ADC RSSI, then PWM RSSI */

			/* switch S.Bus output pin as needed */
#ifdef ENABLE_SBUS_OUT
			ENABLE_SBUS_OUT(value & (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | PX4IO_P_SETUP_FEATURES_SBUS2_OUT));

			/* disable the conflicting options with SBUS 1 */
			if (value & (PX4IO_P_SETUP_FEATURES_SBUS1_OUT)) {
				value &= ~(PX4IO_P_SETUP_FEATURES_PWM_RSSI |
					   PX4IO_P_SETUP_FEATURES_ADC_RSSI |
					   PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
			}

			/* disable the conflicting options with SBUS 2 */
			if (value & (PX4IO_P_SETUP_FEATURES_SBUS2_OUT)) {
				value &= ~(PX4IO_P_SETUP_FEATURES_PWM_RSSI |
					   PX4IO_P_SETUP_FEATURES_ADC_RSSI |
					   PX4IO_P_SETUP_FEATURES_SBUS1_OUT);
			}

#endif

			/* disable the conflicting options with ADC RSSI */
			if (value & (PX4IO_P_SETUP_FEATURES_ADC_RSSI)) {
				value &= ~(PX4IO_P_SETUP_FEATURES_PWM_RSSI |
					   PX4IO_P_SETUP_FEATURES_SBUS1_OUT |
					   PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
			}

			/* disable the conflicting options with PWM RSSI (without effect here, but for completeness) */
			if (value & (PX4IO_P_SETUP_FEATURES_PWM_RSSI)) {
				value &= ~(PX4IO_P_SETUP_FEATURES_ADC_RSSI |
					   PX4IO_P_SETUP_FEATURES_SBUS1_OUT |
					   PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
			}

			/* apply changes */
			r_setup_features = value;

			break;

		case PX4IO_P_SETUP_ARMING:

			value &= PX4IO_P_SETUP_ARMING_VALID;

			/*
			 * Update arming state - disarm if no longer OK.
			 * This builds on the requirement that the FMU driver
			 * asks about the FMU arming state on initialization,
			 * so that an in-air reset of FMU can not lead to a
			 * lockup of the IO arming state.
			 */

			if (value & PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED) {
				r_status_flags |= PX4IO_P_STATUS_FLAGS_INIT_OK;
			}

			/*
			 * If the failsafe termination flag is set, do not allow the autopilot to unset it
			 */
			value |= (r_setup_arming & PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE);

			/*
			 * If failsafe termination is enabled and force failsafe bit is set, do not allow
			 * the autopilot to clear it.
			 */
			if (r_setup_arming & PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE) {
				value |= (r_setup_arming & PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE);
			}

			r_setup_arming = value;

			break;

		case PX4IO_P_SETUP_PWM_RATES:
			value &= PX4IO_P_SETUP_RATES_VALID;
			pwm_configure_rates(value, r_setup_pwm_defaultrate, r_setup_pwm_altrate);
			break;

		case PX4IO_P_SETUP_PWM_DEFAULTRATE:
			if (value < 25) {
				value = 25;
			}

			if (value > 400 && r_page_setup[PX4IO_P_SETUP_PWM_ALTCLOCK] == 1) {
				value = 400;
			}

			pwm_configure_rates(r_setup_pwm_rates, value, r_setup_pwm_altrate);
			break;

		case PX4IO_P_SETUP_PWM_ALTRATE:
			if (value < 25) {
				value = 25;
			}

			if (value > 400 && r_page_setup[PX4IO_P_SETUP_PWM_ALTCLOCK] == 1) {
				value = 400;
			}

			pwm_configure_rates(r_setup_pwm_rates, r_setup_pwm_defaultrate, value);
			break;

		case PX4IO_P_SETUP_PWM_ALTCLOCK:
			if (value < 1) {
				value = 1;
			}

			if (value > 8) {
				value = 8;
			}
			pwm_configure_clock(r_setup_pwm_rates, value);
			r_page_setup[PX4IO_P_SETUP_PWM_ALTCLOCK] = value;
			break;
            
#ifdef CONFIG_ARCH_BOARD_PX4IO_V1

		case PX4IO_P_SETUP_RELAYS:
			value &= PX4IO_P_SETUP_RELAYS_VALID;
			r_setup_relays = value;
			POWER_RELAY1((value & PX4IO_P_SETUP_RELAYS_POWER1) ? 1 : 0);
			POWER_RELAY2((value & PX4IO_P_SETUP_RELAYS_POWER2) ? 1 : 0);
			POWER_ACC1((value & PX4IO_P_SETUP_RELAYS_ACC1) ? 1 : 0);
			POWER_ACC2((value & PX4IO_P_SETUP_RELAYS_ACC2) ? 1 : 0);
			break;
#endif

		case PX4IO_P_SETUP_VBATT_SCALE:
			r_page_setup[PX4IO_P_SETUP_VBATT_SCALE] = value;
			break;

		case PX4IO_P_SETUP_SET_DEBUG:
			r_page_setup[PX4IO_P_SETUP_SET_DEBUG] = value;
			isr_debug(0, "set debug %u\n", (unsigned)r_page_setup[PX4IO_P_SETUP_SET_DEBUG]);
			break;

		case PX4IO_P_SETUP_REBOOT_BL:
			if (r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) {
				// don't allow reboot while armed
				break;
			}

			// check the magic value
			if (value != PX4IO_REBOOT_BL_MAGIC) {
				break;
			}

			// we schedule a reboot rather than rebooting
			// immediately to allow the IO board to ACK
			// the reboot command
			schedule_reboot(100000);
			break;

		case PX4IO_P_SETUP_DSM:
			dsm_bind(value & 0x0f, (value >> 4) & 0xF);
			break;

		case PX4IO_P_SETUP_FORCE_SAFETY_ON:
			if (value == PX4IO_FORCE_SAFETY_MAGIC) {
				r_status_flags &= ~PX4IO_P_STATUS_FLAGS_SAFETY_OFF;

			} else {
				return -1;
			}

			break;

		case PX4IO_P_SETUP_FORCE_SAFETY_OFF:
			if (value == PX4IO_FORCE_SAFETY_MAGIC) {
				r_status_flags |= PX4IO_P_STATUS_FLAGS_SAFETY_OFF;

			} else {
				return -1;
			}

			break;

		case PX4IO_P_SETUP_RC_THR_FAILSAFE_US:
			if (value > 650 && value < 2350) {
				r_page_setup[PX4IO_P_SETUP_RC_THR_FAILSAFE_US] = value;
			}

			break;

		case PX4IO_P_SETUP_PWM_REVERSE:
			r_page_setup[PX4IO_P_SETUP_PWM_REVERSE] = value;
			break;

		case PX4IO_P_SETUP_TRIM_ROLL:
		case PX4IO_P_SETUP_TRIM_PITCH:
		case PX4IO_P_SETUP_TRIM_YAW:
		case PX4IO_P_SETUP_IGNORE_SAFETY:
			r_page_setup[offset] = value;
			break;

		case PX4IO_P_SETUP_SBUS_RATE:
			r_page_setup[offset] = value;
			sbus1_set_output_rate_hz(value);
			break;

		case PX4IO_P_SETUP_HEATER_DUTY_CYCLE:
			last_heater_us = hrt_absolute_time();
			r_page_setup[offset] = value;
			break;

		default:
			return -1;
		}

		break;

	case PX4IO_PAGE_RC_CONFIG: {

			/**
			 * do not allow a RC config change while safety is off
			 */
			if (r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) {
				break;
			}

			unsigned channel = offset / PX4IO_P_RC_CONFIG_STRIDE;
			unsigned index = offset - channel * PX4IO_P_RC_CONFIG_STRIDE;
			uint16_t *conf = &r_page_rc_input_config[channel * PX4IO_P_RC_CONFIG_STRIDE];

			if (channel >= PX4IO_RC_INPUT_CHANNELS) {
				return -1;
			}

			/* disable the channel until we have a chance to sanity-check it */
			conf[PX4IO_P_RC_CONFIG_OPTIONS] &= PX4IO_P_RC_CONFIG_OPTIONS_ENABLED;

			switch (index) {

			case PX4IO_P_RC_CONFIG_MIN:
			case PX4IO_P_RC_CONFIG_CENTER:
			case PX4IO_P_RC_CONFIG_MAX:
			case PX4IO_P_RC_CONFIG_DEADZONE:
			case PX4IO_P_RC_CONFIG_ASSIGNMENT:
				conf[index] = value;
				break;

			case PX4IO_P_RC_CONFIG_OPTIONS:
				value &= PX4IO_P_RC_CONFIG_OPTIONS_VALID;
				r_status_flags |= PX4IO_P_STATUS_FLAGS_INIT_OK;

				/* clear any existing RC disabled flag */
				r_setup_arming &= ~(PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED);

				/* set all options except the enabled option */
				conf[index] = value & ~PX4IO_P_RC_CONFIG_OPTIONS_ENABLED;

				/* should the channel be enabled? */
				/* this option is normally set last */
				if (value & PX4IO_P_RC_CONFIG_OPTIONS_ENABLED) {
					uint8_t count = 0;
					bool disabled = false;

					/* assert min..center..max ordering */
					if (conf[PX4IO_P_RC_CONFIG_MIN] < 500) {
						count++;
					}

					if (conf[PX4IO_P_RC_CONFIG_MAX] > 2500) {
						count++;
					}

					if (conf[PX4IO_P_RC_CONFIG_CENTER] < conf[PX4IO_P_RC_CONFIG_MIN]) {
						count++;
					}

					if (conf[PX4IO_P_RC_CONFIG_CENTER] > conf[PX4IO_P_RC_CONFIG_MAX]) {
						count++;
					}

					/* assert deadzone is sane */
					if (conf[PX4IO_P_RC_CONFIG_DEADZONE] > 500) {
						count++;
					}

					if (conf[PX4IO_P_RC_CONFIG_ASSIGNMENT] == UINT8_MAX) {
						disabled = true;

					} else if ((conf[PX4IO_P_RC_CONFIG_ASSIGNMENT] >= PX4IO_RC_MAPPED_CONTROL_CHANNELS) &&
						   (conf[PX4IO_P_RC_CONFIG_ASSIGNMENT] != PX4IO_P_RC_CONFIG_ASSIGNMENT_MODESWITCH)) {
						count++;
					}

					/* sanity checks pass, enable channel */
					if (count) {
						isr_debug(0, "ERROR: %d config error(s) for RC%d.\n", count, (channel + 1));
						r_status_flags &= ~PX4IO_P_STATUS_FLAGS_INIT_OK;

					} else if (!disabled) {
						conf[index] |= PX4IO_P_RC_CONFIG_OPTIONS_ENABLED;
					}
				}

				break;
				/* inner switch: case PX4IO_P_RC_CONFIG_OPTIONS */

			}

			break;
			/* case PX4IO_RC_PAGE_CONFIG */
		}

	case PX4IO_PAGE_TEST:
		switch (offset) {
		case PX4IO_P_TEST_LED:
			LED_AMBER(value & 1);
			break;
		}

		break;

	default:
		return -1;
	}

	return 0;
}