void AP_IOMCU_FW::heater_update() { uint32_t now = AP_HAL::millis(); if (!has_heater) { // use blue LED as heartbeat if (now - last_blue_led_ms > 500) { palToggleLine(HAL_GPIO_PIN_HEATER); last_blue_led_ms = now; } } else if (reg_setup.heater_duty_cycle == 0 || (now - last_heater_ms > 3000UL)) { palWriteLine(HAL_GPIO_PIN_HEATER, 0); } else { uint8_t cycle = ((now / 10UL) % 100U); palWriteLine(HAL_GPIO_PIN_HEATER, !(cycle >= reg_setup.heater_duty_cycle)); } }
/* update safety state */ void AP_IOMCU_FW::safety_update(void) { uint32_t now = AP_HAL::millis(); if (now - safety_update_ms < 100) { // update safety at 10Hz return; } safety_update_ms = now; bool safety_pressed = palReadLine(HAL_GPIO_PIN_SAFETY_INPUT); if (safety_pressed) { if (reg_status.flag_safety_off && (reg_setup.arming & P_SETUP_ARMING_SAFETY_DISABLE_ON)) { safety_pressed = false; } else if ((!reg_status.flag_safety_off) && (reg_setup.arming & P_SETUP_ARMING_SAFETY_DISABLE_OFF)) { safety_pressed = false; } } if (safety_pressed) { safety_button_counter++; } else { safety_button_counter = 0; } if (safety_button_counter == 10) { // safety has been pressed for 1 second, change state reg_status.flag_safety_off = !reg_status.flag_safety_off; } led_counter = (led_counter+1) % 16; const uint16_t led_pattern = reg_status.flag_safety_off?0xFFFF:0x5500; palWriteLine(HAL_GPIO_PIN_SAFETY_LED, (led_pattern & (1U << led_counter))?0:1); }
static THD_FUNCTION(spi_thread_2, p) { (void)p; chRegSetThreadName("SPI thread 2"); while (true) { spiAcquireBus(&PORTAB_SPI1); /* Acquire ownership of the bus. */ palWriteLine(PORTAB_LINE_LED1, PORTAB_LED_OFF); spiStart(&PORTAB_SPI1, &ls_spicfg); /* Setup transfer parameters. */ spiSelect(&PORTAB_SPI1); /* Slave Select assertion. */ spiExchange(&PORTAB_SPI1, 512, txbuf, rxbuf); /* Atomic transfer operations. */ spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */ spiReleaseBus(&PORTAB_SPI1); /* Ownership release. */ } }
/** * @brief Enables a PWM channel. * @pre The PWM unit must have been activated using @p pwmStart(). * @post The channel is active using the specified configuration. * @note The function has effect at the next cycle start. * @note Channel notification is not enabled. * * @param[in] pwmp pointer to a @p PWMDriver object * @param[in] channel PWM channel identifier (0...channels-1) * @param[in] width PWM pulse width as clock pulses number * * @notapi */ void pwm_lld_enable_channel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width) { #if NRF5_PWM_USE_GPIOTE_PPI const PWMChannelConfig *cfg_channel = &pwmp->config->channels[channel]; const uint8_t gpiote_channel = cfg_channel->gpiote_channel; const uint8_t *ppi_channel = cfg_channel->ppi_channel; uint32_t outinit; switch(cfg_channel->mode & PWM_OUTPUT_MASK) { case PWM_OUTPUT_ACTIVE_LOW : outinit = GPIOTE_CONFIG_OUTINIT_Low; break; case PWM_OUTPUT_ACTIVE_HIGH: outinit = GPIOTE_CONFIG_OUTINIT_High; break; case PWM_OUTPUT_DISABLED : /* fall-through */ default : goto no_output_config; } /* Deal with corner case: 0% and 100% */ if ((width <= 0) || (width >= pwmp->period)) { /* Disable GPIOTE/PPI task */ NRF_GPIOTE->CONFIG[gpiote_channel] = GPIOTE_CONFIG_MODE_Disabled; NRF_PPI->CHENCLR = ((1 << ppi_channel[0]) | (1 << ppi_channel[1])); /* Set Line */ palWriteLine(cfg_channel->ioline, ((width <= 0) ^ ((cfg_channel->mode & PWM_OUTPUT_MASK) == PWM_OUTPUT_ACTIVE_HIGH))); /* Really doing PWM */ } else { const uint32_t gpio_pin = PAL_PAD(cfg_channel->ioline); const uint32_t polarity = GPIOTE_CONFIG_POLARITY_Toggle; /* Program tasks (one for duty cycle, one for periode) */ NRF_PPI->CH[ppi_channel[0]].EEP = (uint32_t)&pwmp->timer->EVENTS_COMPARE[channel]; NRF_PPI->CH[ppi_channel[0]].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[gpiote_channel]; NRF_PPI->CH[ppi_channel[1]].EEP = (uint32_t)&pwmp->timer->EVENTS_COMPARE[pwmp->channels]; NRF_PPI->CH[ppi_channel[1]].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[gpiote_channel]; NRF_PPI->CHENSET = ((1 << ppi_channel[0]) | (1 << ppi_channel[1])); /* Something Old, something New */ const uint32_t old_width = pwmp->timer->CC[channel]; const uint32_t new_width = width; /* Check GPIOTE state */ const bool gpiote = (NRF_GPIOTE->CONFIG[gpiote_channel] & GPIOTE_CONFIG_MODE_Msk) != GPIOTE_CONFIG_MODE_Disabled; /* GPIOTE is currently running */ if (gpiote) { uint32_t current; while (true) { pwmp->timer->TASKS_CAPTURE[PWM_GPIOTE_PPI_CC] = 1; current = pwmp->timer->CC[PWM_GPIOTE_PPI_CC]; if (pwm_within_safe_margins(pwmp, current, old_width) && pwm_within_safe_margins(pwmp, current, new_width)) break; } if (((old_width <= current) && (current < new_width)) || ((new_width <= current) && (current < old_width))) { NRF_GPIOTE->TASKS_OUT[gpiote_channel] = 1; } /* GPIOTE need to be restarted */ } else { /* Create GPIO Task */ NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | ((gpio_pin << GPIOTE_CONFIG_PSEL_Pos ) & GPIOTE_CONFIG_PSEL_Msk )| ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk)| ((outinit << GPIOTE_CONFIG_OUTINIT_Pos ) & GPIOTE_CONFIG_OUTINIT_Msk ); pwmp->timer->TASKS_CAPTURE[PWM_GPIOTE_PPI_CC] = 1; if (pwmp->timer->CC[PWM_GPIOTE_PPI_CC] > width) NRF_GPIOTE->TASKS_OUT[gpiote_channel] = 1; } } no_output_config: #endif pwmp->timer->CC[channel] = width; }