Example #1
0
/*---------------------------------------------------------------------------*/
static void buzzer_gpiote_unconfig(void)
{
    nrf_gpiote_unconfig(GPIOTE_CHANNEL_NUMBER_0);
    nrf_gpiote_unconfig(GPIOTE_CHANNEL_NUMBER_1);

    nrf_gpio_cfg_output(BUZZ1);
    nrf_gpio_cfg_output(BUZZ2);

    nrf_gpio_pin_clear(BUZZ1);
    nrf_gpio_pin_clear(BUZZ2);
}
void ser_phy_close(void)
{
    //Disable UART interrupt.
    NRF_UART0->INTENCLR = 0xFFFFFFFF;

    //Unregister callback.
    m_ser_phy_event_handler = NULL;

    //Will not check err_code here as we will still continue with closure of UART despite errors.
    //Note that any error will still be reported back in the system.
    nrf_gpiote_unconfig(0);

    uart_peripheral_disable();

    //Clear internal UART states
    m_rx_state = UART_IDLE;
    m_tx_state = UART_IDLE;

    mp_tx_stream       = NULL;
    m_tx_stream_length = 0;
    m_tx_stream_index  = 0;

    mp_rx_stream       = NULL;
    m_rx_stream_length = 0;
    m_rx_stream_index  = 0;
}
Example #3
0
// called from wiring_digital.c
void turn_Off_GPIOTE_PPI_from_GPIO(uint32_t ulPin)
{
  uint32_t i;

  if (PPI_Channels_Occupied[ulPin][0] < 255)
  {
    rfduino_ppi_channel_unassign(PPI_Channels_Occupied[ulPin][0]);
    PPI_Channels_Occupied[ulPin][0] = 255;
  }

  if (PPI_Channels_Occupied[ulPin][1] < 255)
  {
    rfduino_ppi_channel_unassign(PPI_Channels_Occupied[ulPin][1]);
    PPI_Channels_Occupied[ulPin][1] = 255;
  }

  if (GPIOTE_Channels_Occupied[ulPin] < 255)
  {
    nrf_gpiote_unconfig(GPIOTE_Channels_Occupied[ulPin]);
    GPIOTE_Channels_Occupied[ulPin] = 255;
  }

  for (i = 0; i < 3; i++)
  {
    if (Timer1_Compare_Unit_Occupied_by_Pin[i] == ulPin)
      Timer1_Compare_Unit_Occupied_by_Pin[i] = 255;
    if (Timer2_Compare_Unit_Occupied_by_Pin[i] == ulPin)
      Timer2_Compare_Unit_Occupied_by_Pin[i] = 255;
  }
}
Example #4
0
void noTone(uint8_t ulPin)
{
	if (ulPin >= PINS_COUNT) return;
	if (ulPin == tone_pin) {
		// Stop Timer 2
		NRF_TIMER2->TASKS_STOP = 1;
		// Unconfig GPIOTE channel 3
		nrf_gpiote_unconfig(3);
		GPIOTE_Channels_Occupied[tone_pin] = 255;
		// Unconfig PPI channel 6
		wavelette_ppi_remove(6);
		digitalWrite(tone_pin, LOW);
		tone_pin = 255;
	}
}
static void uart_tx_start(void)
{
    if (mp_tx_stream != NULL)
    {
        //If RX is already ongoing then no wakeup signal is required.
        if (m_rx_state == UART_IDLE)
        {
            nrf_gpiote_unconfig(0);
            NRF_GPIO->OUTSET = 1 << SER_PHY_UART_RTS;
            nrf_gpio_cfg_output(SER_PHY_UART_RTS);
            uart_peripheral_connect_flow();
            uart_peripheral_enable();
        }
    }
}
static void uart_tx_last_byte(void)
{
    uart_peripheral_disconnect_flow();
    m_tx_state = UART_TX_LAST_BYTE_WAIT;

    //Configure event in case CTS is going low during this function execution
    nrf_gpiote_event_config(0, SER_PHY_UART_CTS, NRF_GPIOTE_POLARITY_TOGGLE);

    if (!nrf_gpio_pin_read(SER_PHY_UART_CTS)) //All pins are low --> last byte can be transmitted.
    {
        //Re-check state as it might have changed due to preemption of current interrupt.
        nrf_gpiote_unconfig(0);

        if (m_tx_state == UART_TX_LAST_BYTE_WAIT)
        {
            m_tx_state = UART_TX_COMPLETE;
            uart_tx_send();
        }
    }
}
Example #7
0
static void TIMER2_Interrupt(void)
{
	NRF_TIMER2->EVENTS_COMPARE[0] = 0;

	if (tone_toggle_count)
	{
		tone_toggle_count--;
	}
	else
	{
		// Stop Timer 2
		NRF_TIMER2->TASKS_STOP = 1;
		// Unconfig GPIOTE channel 3
		nrf_gpiote_unconfig(3);
		GPIOTE_Channels_Occupied[tone_pin] = 255;
		// Unconfig PPI channel 6
		wavelette_ppi_remove(6);
		digitalWrite(tone_pin, LOW);
		tone_pin = 255;
	}
}
static __INLINE void on_cts_low(void)
{
    m_cts_high_disconnect = false;
    nrf_gpiote_unconfig(0);

    if (m_tx_state == UART_STALL)
    {
        m_tx_pending = true;
    }
    else if (m_tx_state == UART_TX_LAST_BYTE_WAIT)
    {
        m_tx_state = UART_TX_COMPLETE;
        uart_tx_send();
    }
    else if (m_rx_state == UART_IDLE && m_tx_state == UART_IDLE)
    {
        NRF_GPIO->OUTSET = 1 << SER_PHY_UART_RTS;
        nrf_gpio_cfg_output(SER_PHY_UART_RTS);
        uart_peripheral_enable();
    }
}
void gpioteChannelClean(uint8_t channel)
{
	nrf_gpiote_unconfig(channel);
	GPIOTE_Channels_Occupied[channel] = UNAVAILABLE_GPIOTE_CHANNEL;
}
Example #10
0
/**********************************************************************
name :
function : 
**********************************************************************/
void GPIOTE_Channel_Clean(uint8_t channel)
{	
	nrf_gpiote_unconfig(channel);
	GPIOTE_Channels_Occupied[channel] = 255;
}
static void uart_rxdrdy_handle(void)
{
    if (m_rx_state == UART_IDLE)
    {
        m_rx_state = UART_RX;
    }

    //Set proper size and buff at the beginning of receiving header
    if ((m_rx_stream_header == true) && !m_rx_stream_index)
    {
        m_rx_stream_length = SER_PHY_HEADER_SIZE;
        mp_rx_stream       = m_rx_length_buf;
    }

    if (mp_rx_stream != NULL)
    {
        bool tx_dual_end = false;

        NRF_UART0->EVENTS_RXDRDY = 0;

        //Second last byte received.
        //Disconnect CTS before pulling the byte and receiving the final byte.
        if ((m_rx_stream_header == false) && ((m_rx_stream_index) == (m_rx_stream_length - 2)))
        {
            nrf_gpio_cfg_output(SER_PHY_UART_RTS);

            //Last byte is waiting for tansmission. Thus dual end TX case.
            //
            if (m_tx_state == UART_TX_LAST_BYTE_WAIT)
            {
                m_tx_state = UART_STALL;
                nrf_gpiote_unconfig(0);

                //Checking pending state.
                //- If pending is true then CTS have become low after we stalled the UART and final byte should be transmitted here.
                //- If pending is false we should check if final byte was tranmitted and if not, the do the transmission her.
                if ((m_tx_pending == true) || (m_tx_stream_index == (m_tx_stream_length - 1)))
                {
                    //tx_dual_end = true;
                    NRF_GPIO->OUTSET = 1 << SER_PHY_UART_RTS;
                    uart_tx_send();
                }
            }

            if (!tx_dual_end)
            {
                NRF_GPIO->OUTCLR = 1 << SER_PHY_UART_RTS;
            }
            m_tx_state = UART_STALL;

            NRF_UART0->PSELCTS = UART_PIN_DISCONNECTED;
            NRF_UART0->PSELRTS = UART_PIN_DISCONNECTED;
            NRF_UART0->CONFIG &= ~(UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);
        }

        if (m_rx_stream_index < (m_rx_stream_length - 1))
        {
            if (mp_rx_stream != m_rx_drop_buf)
            {
                mp_rx_stream[m_rx_stream_index++] = NRF_UART0->RXD;
            }
            else
            {
                mp_rx_stream[0] = NRF_UART0->RXD;
                m_rx_stream_index++;
            }

            if (m_tx_stream_index == (m_tx_stream_length - 1))
            {
                //Toggle CTS line to indicate ack.
                //If CTS is connected to UART this code will have no effect.
                //But on edge case on bi-directional last byte transfer this avoids lock-up.
                NRF_GPIO->OUTSET = 1 << SER_PHY_UART_RTS;
                nrf_delay_us(8);
                NRF_GPIO->OUTCLR = 1 << SER_PHY_UART_RTS;
            }
        }
        else
        {
            if (m_rx_stream_header == false)
            {
                NRF_GPIO->OUTSET = 1 << SER_PHY_UART_RTS;

                if (mp_rx_stream != m_rx_drop_buf)
                {
                    mp_rx_stream[m_rx_stream_index++] = NRF_UART0->RXD;
                }
                else
                {
                    mp_rx_stream[0] = NRF_UART0->RXD;
                    m_rx_stream_index++;
                }
                m_rx_state = UART_IDLE;

                //Last byte of payload received - notify that next transmission will be header
                m_rx_stream_header = true;

                //Prepare event
                if (mp_rx_stream != m_rx_drop_buf)
                {
                    m_ser_phy_event_rx.evt_type = SER_PHY_EVT_RX_PKT_RECEIVED;
                    m_ser_phy_event_rx.evt_params.rx_pkt_received.num_of_bytes = m_rx_stream_index;
                    m_ser_phy_event_rx.evt_params.rx_pkt_received.p_buffer     = mp_rx_stream;
                }
                else
                {
                    m_ser_phy_event_rx.evt_type = SER_PHY_EVT_RX_PKT_DROPPED;
                }

                m_rx_stream_length = 0;
                m_rx_stream_index  = 0;
            }
            else
            {
                mp_rx_stream[m_rx_stream_index++] = NRF_UART0->RXD;

                //Last byte of header received - notify that next transmission will be payload
                m_rx_stream_header = false;

                mp_rx_stream = NULL;

                //Clear index before receiving payload
                m_rx_stream_index = 0;

                //Prepare event
                m_rx_stream_length = uint16_decode(m_rx_length_buf);
                m_ser_phy_event_rx.evt_type = SER_PHY_EVT_RX_BUF_REQUEST;
                m_ser_phy_event_rx.evt_params.rx_buf_request.num_of_bytes = m_rx_stream_length;
            }

            //Notify upwards
            m_ser_phy_event_handler(m_ser_phy_event_rx);

            //UART TX was stalled while receiving final byte. Restart tx.
            if (m_tx_state == UART_STALL)
            {
                if (m_tx_stream_length == m_tx_stream_index)
                {
                    m_tx_state = UART_IDLE;
                }
                else if (m_tx_stream_index == (m_tx_stream_length - 1))
                {
                    m_tx_state = UART_TX_LAST_BYTE_WAIT;
                }
                else
                {
                    m_tx_state = UART_TX_SEND;
                }

                //Critical region for avoiding timing issues in 'simultaneous RX end and TX start'
                CRITICAL_REGION_ENTER();
                if (m_tx_pending == true)
                {
                    m_tx_pending = false;
                    uart_tx_start();

                    if (m_tx_state == UART_TX_SEND)
                    {
                        uart_tx_send();
                    }
                    else if (m_tx_state == UART_TX_LAST_BYTE_WAIT)
                    {
                        uart_tx_last_byte();
                    }
                }
                CRITICAL_REGION_EXIT();

                if (m_tx_state == UART_IDLE)
                {
                    uart_peripheral_disable();
                }
            }
        }
    }
    else
    {
        m_rx_state = UART_RX_PENDING;
    }
}
void nrf_pwm_set_value(uint32_t pwm_channel, uint32_t pwm_value)
{
    if (pwm_value == PWM_TIMER->CC[pwm_channel])
    {
        // No change necessary
        return;
    }
    
    if (PWM_TIMER->CC[pwm_channel] == 0)
    {
        // This PWM is not running
        if (pwm_value == 0)
        {
            // Corner case: This PWM is not running and new value is 0% duty cycle
            NRF_GPIO->OUTCLR = (1 << pwm_io_ch[pwm_channel]);
            PWM_TIMER->CC[pwm_channel] = pwm_value;
            return;
        }
        else if (pwm_value >= pwm_max_value)
        {
            // Corner case: This PWM is not running and new value is 100% duty cycle
            NRF_GPIO->OUTSET = (1 << pwm_io_ch[pwm_channel]);
            PWM_TIMER->CC[pwm_channel] = pwm_value;
            return;
        }
        
        ppi_disable_channels((1 << (pwm_channel * 2)) | (1 << (pwm_channel * 2 + 1)));
        PWM_TIMER->CC[pwm_channel] = pwm_value * 2;
        
        if (NRF_GPIO->OUT & (1 << pwm_io_ch[pwm_channel]))
        {
            // PWM is currently in 100% duty cycle
            nrf_gpiote_task_config(pwm_gpiote_channel[pwm_channel], pwm_io_ch[pwm_channel], NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
            
            ppi_configure_channel_group(pwm_ppi_chg, 0);
            ppi_disable_channel_group(pwm_ppi_chg);
            ppi_configure_channel_group(pwm_ppi_chg, (1 << (pwm_channel * 2)) | (1 << (pwm_channel * 2 + 1)));
            
            ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
            ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[3], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].EN);
            ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
        }
        else
        {
            // PWM is currently in 0% duty cycle
            nrf_gpiote_task_config(pwm_gpiote_channel[pwm_channel], pwm_io_ch[pwm_channel], NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
            
            ppi_configure_channel_group(pwm_ppi_chg, 0);
            ppi_disable_channel_group(pwm_ppi_chg);
            ppi_configure_channel_group(pwm_ppi_chg, (1 << (pwm_channel * 2)) | (1 << (pwm_channel * 2 + 1)));
            
            ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
            ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[pwm_channel], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].EN);
            ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
        }
        
        // Disable PPI channels next cycle
        pwm_freq_int_set();
        
        return;
    }
    
    if (pwm_value == 0)
    {
        // Corner case: 0% duty cycle
        NRF_GPIO->OUTCLR = (1 << pwm_io_ch[pwm_channel]);

        ppi_configure_channel_group(pwm_ppi_chg, 0);
        ppi_enable_channel_group(pwm_ppi_chg);
        ppi_configure_channel_group(pwm_ppi_chg, (1 << (pwm_channel * 2)) | (1 << (pwm_channel * 2 + 1)));
        ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[pwm_channel], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].DIS);
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
        
        // Wait for one PWM clock cycle
        nrf_delay_us(pwm_period_us);
        
        PWM_TIMER->CC[pwm_channel] = 0;
        
        ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
        ppi_configure_channel_group(pwm_ppi_chg, 0);
        
        nrf_gpiote_unconfig(pwm_gpiote_channel[pwm_channel]);
    }
    else if (pwm_value >= pwm_max_value)
    {
        // Corner case: 100% duty cycle
        NRF_GPIO->OUTSET = (1 << pwm_io_ch[pwm_channel]);

        ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
        ppi_configure_channel_group(pwm_ppi_chg, 0);
        ppi_enable_channel_group(pwm_ppi_chg);
        ppi_configure_channel_group(pwm_ppi_chg, (1 << (pwm_channel * 2)) | (1 << (pwm_channel * 2 + 1)));
        ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[3], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].DIS);
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
        
        // Wait for one PWM clock cycle
        nrf_delay_us(pwm_period_us);
        
        ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
        ppi_configure_channel_group(pwm_ppi_chg, 0);
        
        PWM_TIMER->CC[pwm_channel] = 0;
        
        // 100% duty cycle
        nrf_gpiote_unconfig(pwm_gpiote_channel[pwm_channel]);
        return;
    }
    else if ((pwm_value * 2) > PWM_TIMER->CC[pwm_channel])
    {
        // New duty cycle is larger than the current one
        ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
        PWM_TIMER->CC[2] = pwm_value * 2;
        
        ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[2], &PWM_TIMER->TASKS_CAPTURE[pwm_channel]);
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
     
        // Disable PPI channels next cycle
        pwm_freq_int_set();
    }
    else
    {
        // New duty cycle is smaller than the current one
        ppi_disable_channels((1 << (PWM_MAX_CHANNELS * 2)) | (1 << (PWM_MAX_CHANNELS * 2 + 1)) | (1 << (PWM_MAX_CHANNELS * 2 + 2)));
        ppi_configure_channel_group(pwm_ppi_chg, 0);
        ppi_disable_channel_group(pwm_ppi_chg);
        ppi_configure_channel_group(pwm_ppi_chg, (1 << (PWM_MAX_CHANNELS * 2)) | (1 << (PWM_MAX_CHANNELS * 2 + 1)));
        
        ppi_configure_channel(PWM_MAX_CHANNELS * 2,     &PWM_TIMER->EVENTS_COMPARE[2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[pwm_channel]]);
        ppi_configure_channel(PWM_MAX_CHANNELS * 2 + 1, &PWM_TIMER->EVENTS_COMPARE[2], &PWM_TIMER->TASKS_CAPTURE[pwm_channel]);
        ppi_configure_channel(PWM_MAX_CHANNELS * 2 + 2, &PWM_TIMER->EVENTS_COMPARE[3], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].EN);
        
        PWM_TIMER->CC[2] = pwm_value * 2;
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2 + 2));
        
        // Disable PPI channels next cycle
        pwm_freq_int_set();
    }
}