void Servo::writeMicroseconds(int value)
{
	uint8_t channel, instance;
	uint8_t pin = servos[this->servoIndex].Pin.nbr;
	//instance of pwm module is MSB - look at VWariant.h
	instance=(g_APinDescription[pin].ulPWMChannel & 0xF0)/16;
	//index of pwm channel is LSB - look at VWariant.h
	channel=g_APinDescription[pin].ulPWMChannel & 0x0F;
	group_pins[instance][channel]=g_APinDescription[pin].ulPin;
	NRF_PWM_Type * PWMInstance = instance == 0 ? NRF_PWM0 : (instance == 1 ? NRF_PWM1 : NRF_PWM2);
	//configure pwm instance and enable it
	seq_values[instance][channel]= value | 0x8000;
	nrf_pwm_sequence_t const seq={
								seq_values[instance],
								NRF_PWM_VALUES_LENGTH(seq_values),
								0,
								0
    };
	nrf_pwm_pins_set(PWMInstance, group_pins[instance]);
	nrf_pwm_enable(PWMInstance);
	nrf_pwm_configure(PWMInstance, NRF_PWM_CLK_125kHz, NRF_PWM_MODE_UP, 2500);	// 20ms - 50Hz
	nrf_pwm_decoder_set(PWMInstance, NRF_PWM_LOAD_INDIVIDUAL, NRF_PWM_STEP_AUTO);
	nrf_pwm_sequence_set(PWMInstance, 0, &seq);
	nrf_pwm_loop_set(PWMInstance, 0UL);
	nrf_pwm_task_trigger(PWMInstance, NRF_PWM_TASK_SEQSTART0);
}
bool nrfx_pwm_stop(nrfx_pwm_t const * const p_instance,
                   bool wait_until_stopped)
{
    NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);

    bool ret_val = false;

    if (nrfx_pwm_is_stopped(p_instance))
    {
        ret_val = true;
    }
    else
    {
        nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP);

        do {
            if (nrfx_pwm_is_stopped(p_instance))
            {
                ret_val = true;
                break;
            }
        } while (wait_until_stopped);
    }

    NRFX_LOG_INFO("%s returned %d.", __func__, ret_val);
    return ret_val;
}
示例#3
0
static void start_playback(nrf_drv_pwm_t const * const p_instance,
                           pwm_control_block_t * p_cb,
                           uint8_t               flags,
                           nrf_pwm_task_t        starting_task)
{
    p_cb->state = NRF_DRV_STATE_POWERED_ON;

    if (p_cb->handler)
    {
        // The notification about finished playback is by default enabled, but
        // this can be suppressed. The notification that the peripheral has been
        // stopped is always enable.
        uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK |
                            NRF_PWM_INT_STOPPED_MASK;

        if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0)
        {
            int_mask |= NRF_PWM_INT_SEQEND0_MASK;
        }
        if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1)
        {
            int_mask |= NRF_PWM_INT_SEQEND1_MASK;
        }
        if (flags & NRF_DRV_PWM_FLAG_NO_EVT_FINISHED)
        {
            int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK;
        }

        nrf_pwm_int_set(p_instance->p_registers, int_mask);
    }

    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);

    nrf_pwm_task_trigger(p_instance->p_registers, starting_task);
}
示例#4
0
bool nrf_drv_pwm_stop(nrf_drv_pwm_t const * const p_instance,
                      bool wait_until_stopped)
{
    ASSERT(m_cb[p_instance->drv_inst_idx].state != NRF_DRV_STATE_UNINITIALIZED);

    if (nrf_drv_pwm_is_stopped(p_instance))
    {
        return true;
    }

    nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP);

    do {
        if (nrf_drv_pwm_is_stopped(p_instance))
        {
            return true;
        }
    } while (wait_until_stopped);

    return false;
}
static uint32_t start_playback(nrfx_pwm_t const * const p_instance,
                               pwm_control_block_t * p_cb,
                               uint8_t               flags,
                               nrf_pwm_task_t        starting_task)
{
    p_cb->state = NRFX_DRV_STATE_POWERED_ON;
    p_cb->flags = flags;

    if (p_cb->handler)
    {
        // The notification about finished playback is by default enabled,
        // but this can be suppressed.
        // The notification that the peripheral has stopped is always enabled.
        uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK |
                            NRF_PWM_INT_STOPPED_MASK;

        // The workaround for nRF52 Anomaly 109 "protects" DMA transfers by
        // handling interrupts generated on SEQEND0 and SEQEND1 events (see
        // 'nrfx_pwm_init'), hence these events must be always enabled
        // to generate interrupts.
        // However, the user handler is called for them only when requested
        // (see 'irq_handler').
#if defined(USE_DMA_ISSUE_WORKAROUND)
        int_mask |= NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK;
#else
        if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ0)
        {
            int_mask |= NRF_PWM_INT_SEQEND0_MASK;
        }
        if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ1)
        {
            int_mask |= NRF_PWM_INT_SEQEND1_MASK;
        }
#endif
        if (flags & NRFX_PWM_FLAG_NO_EVT_FINISHED)
        {
            int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK;
        }

        nrf_pwm_int_set(p_instance->p_registers, int_mask);
    }
#if defined(USE_DMA_ISSUE_WORKAROUND)
    else
    {
        nrf_pwm_int_set(p_instance->p_registers,
            NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK);
    }
#endif

    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);

    if (flags & NRFX_PWM_FLAG_START_VIA_TASK)
    {
        uint32_t starting_task_address =
            nrf_pwm_task_address_get(p_instance->p_registers, starting_task);

#if defined(USE_DMA_ISSUE_WORKAROUND)
        // To "protect" the initial DMA transfer it is required to start
        // the PWM by triggering the proper task from EGU interrupt handler,
        // it is not safe to do it directly via PPI.
        p_cb->starting_task_address = starting_task_address;
        nrf_egu_int_enable(DMA_ISSUE_EGU,
            nrf_egu_int_get(DMA_ISSUE_EGU, p_instance->drv_inst_idx));
        return (uint32_t)nrf_egu_task_trigger_address_get(DMA_ISSUE_EGU,
            p_instance->drv_inst_idx);
#else
        return starting_task_address;
#endif
    }

    nrf_pwm_task_trigger(p_instance->p_registers, starting_task);
    return 0;
}