bool twi_master_read(uint8_t address, uint8_t *rx_data, uint8_t rx_data_length,twi_config_t *cfg)
{
    if(rx_data_length == 0)
    {
        return false;
    }
		active_config =cfg;

    cfg->twi->ADDRESS = address;
    rx_data_ptr = rx_data;
    rx_bytes_to_receive = rx_data_length;
    
    if (rx_bytes_to_receive == 1)
    {
        sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_STOP);
    }
    else
    {
        sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_SUSPEND);
    }
    sd_ppi_channel_enable_set(1 << cfg->twi_ppi_ch);
    
    cfg->twi->TASKS_STARTRX = 1;
    cfg->twi_operation_complete = false;

    while(cfg->twi_operation_complete == false);
		active_config =0;
    return cfg->twi_ack_received;
}
Beispiel #2
0
static bool twi_master_read(uint8_t *data, uint8_t data_length,
bool issue_stop_condition) {
	uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for RXDREADY event*/

	if (data_length == 0) {
		/* gently return false for requesting data of size 0 */
		return false;
	}

	if (data_length == 1) {
		//NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;

		sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
				&(NRF_TWI1->TASKS_STOP));
	} else {
		//NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
		sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
				&(NRF_TWI1->TASKS_SUSPEND));

	}
	//NRF_PPI->CHENSET = PPI_CHENSET_CH0_Msk;
	sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);
	NRF_TWI1->TASKS_STARTRX = 1;
	while (true) {

		while ((NRF_TWI1->EVENTS_RXDREADY == 0) && (--timeout)) { //nrf_app_event_wait();
		}

		if (timeout == 0) {
			/* timeout before receiving event*/
			return false;
		}

		NRF_TWI1->EVENTS_RXDREADY = 0;
		*data++ = NRF_TWI1->RXD;

		/* configure PPI to stop TWI master before we get last BB event */
		if (--data_length == 1) {
			//  NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
			sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
					&(NRF_TWI1->TASKS_STOP));
		}

		if (data_length == 0)
			break;

		NRF_TWI1->TASKS_RESUME = 1;
	}

	/* wait until stop sequence is sent and clear the EVENTS_STOPPED */
	while (NRF_TWI1->EVENTS_STOPPED == 0) {  //nrf_app_event_wait();
	}
	NRF_TWI1->EVENTS_STOPPED = 0;

	//  NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
	sd_ppi_channel_enable_clr(PPI_CHEN_CH0_Msk);
	return true;
}
void
protocol_init(struct ir_protocol *protocol, uint8_t led_pin, struct rtc_ctx *c)
{
	ctx = c;
	context.protocol = protocol;
	context.led_pin = led_pin;

	// low freq clock
	NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
	NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
	NRF_CLOCK->TASKS_LFCLKSTART = 1;
	while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
		/* NOTHING */;
	NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;

	// rtc1 interrupt
	sd_nvic_ClearPendingIRQ(RTC1_IRQn);
	sd_nvic_SetPriority(RTC1_IRQn, NRF_APP_PRIORITY_LOW);
	sd_nvic_EnableIRQ(RTC1_IRQn);
	NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
	NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;

	// high freq clock
	sd_clock_hfclk_request();

	// timer1
	NRF_TIMER1->TASKS_STOP = 1;
	NRF_TIMER1->TASKS_CLEAR = 1;
	NRF_TIMER1->PRESCALER = 4;
	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
	NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Msk;
	NRF_TIMER1->CC[0] = 1;
	NRF_TIMER1->CC[1] = ROUNDED_DIV(context.protocol->pulse_width, 3);
	NRF_TIMER1->CC[2] = context.protocol->pulse_width;

	// timer2 (counter)
	NRF_TIMER2->TASKS_STOP = 1;
	NRF_TIMER2->TASKS_CLEAR = 1;
	NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter;
	NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
	NRF_TIMER2->TASKS_START = 1;
	NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;

	// gpio (led)
	nrf_gpio_cfg_output(led_pin);

	// ppi's
	sd_ppi_channel_assign(0, &NRF_TIMER1->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[0]); // toggle led
	sd_ppi_channel_assign(1, &NRF_TIMER1->EVENTS_COMPARE[1], &NRF_GPIOTE->TASKS_OUT[0]); // toggle led
	sd_ppi_channel_assign(2, &NRF_TIMER1->EVENTS_COMPARE[2], &NRF_TIMER2->TASKS_COUNT); // inc timer2
	sd_ppi_channel_assign(3, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_TIMER1->TASKS_STOP); // stops timer1 after timer2 reaches N
	sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk |
		PPI_CHEN_CH1_Msk |
		PPI_CHEN_CH2_Msk |
		PPI_CHEN_CH3_Msk);
}
Beispiel #4
0
/* @brief PPI initialisation function.
 *
 * @details This function will initialise Programmable Peripheral Interconnect peripheral. It will
 *          configure the PPI channels as follows -
 *              PPI Channel 0 - Connecting CC0 Compare event to GPIOTE Task to toggle the LED state
 *          This configuration will feed a PWM input to the LED thereby making it flash in an
 *          interval that is dependent on the TIMER configuration.
 */
static void ppi_init(void)
{
    /* Configure PPI channel 0 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[0] match */
    sd_ppi_channel_assign(0, &(NRF_TIMER1->EVENTS_COMPARE[0]), &(NRF_GPIOTE->TASKS_OUT[0]));

    /* Configure PPI channel 1 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[1] match */
    sd_ppi_channel_assign(1,&(NRF_TIMER1->EVENTS_COMPARE[1]),&(NRF_GPIOTE->TASKS_OUT[0]));

    /* Enable only PPI channels 0 and 1 */
    sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk | PPI_CHEN_CH1_Msk);
}
uint32_t nrf_drv_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep)
{
    uint32_t err_code;

    if (((uint32_t *)eep == NULL) || ((uint32_t *)tep == NULL))
    {
        err_code = NRF_ERROR_NULL;
    }
    else if (!is_programmable_app_channel(channel))
    {
        err_code = NRF_ERROR_INVALID_PARAM;
    }
    else if (!is_allocated_channel(channel))
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }
    else
    {
#if (NRF_PPI_RESTRICTED > 0)
        err_code = sd_ppi_channel_assign((uint8_t) channel, (const volatile void *) eep, (const volatile void *) tep);
        if (err_code != NRF_SUCCESS)
        {
            err_code = NRF_ERROR_INVALID_PARAM;
        }
#else
        nrf_ppi_channel_endpoint_setup(channel, eep, tep);
        err_code = NRF_SUCCESS;
#endif
    }

    return err_code;
}
Beispiel #6
0
/*---------------------------------------------------------------------------*/ 
static void buzzer_ppi_config(void)
{
    /*  
     *  Configure PPI channel 0 to toggle GPIO_OUTPUT_PIN on 
     *  every TIMER0 COMPARE[0] match (300µs)
     */
    sd_ppi_channel_assign(GPIOTE_CHANNEL_NUMBER_0,
                          &BUZZ_TIMER->EVENTS_COMPARE[0],
                          &NRF_GPIOTE->TASKS_OUT[GPIOTE_CHANNEL_NUMBER_0]);

    sd_ppi_channel_assign(GPIOTE_CHANNEL_NUMBER_1, 
                          &BUZZ_TIMER->EVENTS_COMPARE[0], 
                          &NRF_GPIOTE->TASKS_OUT[GPIOTE_CHANNEL_NUMBER_1]);

    /* Enable PPI channels */
    sd_ppi_channel_enable_set((PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) |
                              (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos));
}
void gpiote_toggle_led_init()
{
    sd_ppi_channel_assign(TOGGLE_LED_GPIOTE_CHANNEL, &(NRF_TIMER2->EVENTS_COMPARE[0]) ,&(NRF_GPIOTE->TASKS_OUT[0]));

    nrf_gpio_cfg_output(SECONDARY_LED_PIN);
    nrf_gpio_pin_clear(SECONDARY_LED_PIN);
    nrf_gpiote_task_config(TOGGLE_LED_GPIOTE_CHANNEL, SECONDARY_LED_PIN, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
    sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);
}
uint32_t ir_lib_init(uint32_t ir_pin)
{
    uint32_t err_code = 0;

    NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task         << GPIOTE_CONFIG_MODE_Pos |
                            GPIOTE_CONFIG_OUTINIT_Low       << GPIOTE_CONFIG_OUTINIT_Pos |
                            GPIOTE_CONFIG_POLARITY_Toggle   << GPIOTE_CONFIG_POLARITY_Pos |
                            ir_pin                          << GPIOTE_CONFIG_PSEL_Pos;
    
    // Carrier timer init
    IR_TIMER_CARRIER->MODE          = TIMER_MODE_MODE_Timer;
    IR_TIMER_CARRIER->BITMODE       = TIMER_BITMODE_BITMODE_16Bit;
    IR_TIMER_CARRIER->PRESCALER     = 4;
    IR_TIMER_CARRIER->CC[0]         = IR_CARRIER_LOW_US;    
    IR_TIMER_CARRIER->CC[1]         = IR_CARRIER_LOW_US + IR_CARRIER_HIGH_US; 
    IR_TIMER_CARRIER->SHORTS        = TIMER_SHORTS_COMPARE1_CLEAR_Msk;

    // Modulation timer init
    IR_CARRIER_COUNTER->MODE        = TIMER_MODE_MODE_Counter;  
    IR_CARRIER_COUNTER->BITMODE     = TIMER_BITMODE_BITMODE_16Bit;
    IR_CARRIER_COUNTER->INTENSET    = TIMER_INTENSET_COMPARE0_Msk | TIMER_INTENSET_COMPARE1_Msk;
    IR_CARRIER_COUNTER->EVENTS_COMPARE[0] = 0;
    IR_CARRIER_COUNTER->EVENTS_COMPARE[1] = 0;

    err_code |= sd_nvic_SetPriority(IR_CARRIER_COUNTER_IRQn, IR_CARRIER_COUNTER_IRQ_Priority);
    err_code |= sd_nvic_EnableIRQ(IR_CARRIER_COUNTER_IRQn);

    err_code |= sd_ppi_channel_assign(IR_PPI_CH_A, &IR_TIMER_CARRIER->EVENTS_COMPARE[1], &IR_CARRIER_COUNTER->TASKS_COUNT);
    
    err_code |= sd_ppi_channel_assign(IR_PPI_CH_B, &IR_TIMER_CARRIER->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[0]);
    err_code |= sd_ppi_channel_assign(IR_PPI_CH_C, &IR_TIMER_CARRIER->EVENTS_COMPARE[1], &NRF_GPIOTE->TASKS_OUT[0]);

    err_code |= sd_ppi_group_assign(IR_PPI_GROUP, 1 << IR_PPI_CH_B | 1 << IR_PPI_CH_C);
    err_code |= sd_ppi_group_task_disable(IR_PPI_GROUP);
    
    err_code |= sd_ppi_channel_assign(IR_PPI_CH_D, &IR_CARRIER_COUNTER->EVENTS_COMPARE[0], &NRF_PPI->TASKS_CHG[IR_PPI_GROUP].DIS);
    err_code |= sd_ppi_channel_assign(IR_PPI_CH_E, &IR_CARRIER_COUNTER->EVENTS_COMPARE[1], &NRF_PPI->TASKS_CHG[IR_PPI_GROUP].EN);

    err_code |= sd_ppi_channel_enable_set(1 << IR_PPI_CH_A | 1 << IR_PPI_CH_B | 1 << IR_PPI_CH_C | 1 << IR_PPI_CH_D | 1 << IR_PPI_CH_E);
    
    m_busy = false;
    return err_code;
}
static void twi_interrupt_internal(NRF_TWI_Type * twi_master)
{
    if(twi_master->EVENTS_TXDSENT)
    {
        twi_master->EVENTS_TXDSENT = 0;
        if(tx_bytes_to_send)
        {
            twi_master->TXD = *tx_data_ptr++;  
            tx_bytes_to_send--;
        }
        else 
        {
            if(rx_bytes_to_receive == 0)
            {
                twi_master->TASKS_STOP = 1; 
            }
            else
            {
                sd_ppi_channel_enable_set(1 << active_config->twi_ppi_ch);

                twi_master->TASKS_STARTRX = 1;
            }
        }
    }
    if(twi_master->EVENTS_STOPPED)
    {
        twi_master->EVENTS_STOPPED = 0;
        active_config->twi_operation_complete = true;
        active_config->twi_ack_received = true;
    }
    if(twi_master->EVENTS_RXDREADY)
    {
        twi_master->EVENTS_RXDREADY = 0;
        *rx_data_ptr++ = twi_master->RXD;
        if (--rx_bytes_to_receive == 1)
        {
            sd_ppi_channel_assign(active_config->twi_ppi_ch, &twi_master->EVENTS_BB, &twi_master->TASKS_STOP);  
        }

        if(rx_bytes_to_receive > 0)
        {
            twi_master->TASKS_RESUME = 1;
        }
    }
    if(twi_master->EVENTS_ERROR)
    {
        twi_master->EVENTS_ERROR = 0;
        active_config->twi_operation_complete = true;
        active_config->twi_ack_received = false;
    }
}
Beispiel #10
0
/** @brief Function for the PPI initialization.
 *
 * @details This function will initialise Programmable Peripheral Interconnect peripheral. It will
 *          configure the PPI channels as follows -
 *              PPI Channel 0 - Connecting CC0 Compare event to GPIOTE Task to toggle the LED state
 *          This configuration will feed a PWM input to the LED thereby making it flash in an
 *          interval that is dependent on the TIMER configuration.
 */
static void ppi_init(void)
{
    uint32_t err_code;

    // Configure PPI channel 0 to toggle ADVERTISING_LED_PIN_NO on every TIMER1 COMPARE[0] match
    err_code = sd_ppi_channel_assign(PPI_CHAN0_TO_TOGGLE_LED,
                                     &(NRF_TIMER1->EVENTS_COMPARE[0]),
                                     &(NRF_GPIOTE->TASKS_OUT[GPIOTE_CHAN_FOR_LED_TASK]));
    APP_ERROR_CHECK(err_code);

    // Enable PPI channel 0
    err_code = sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);
    APP_ERROR_CHECK(err_code);
}
static void ppi_configure_channel(uint32_t ch_num, volatile uint32_t *event_ptr, volatile uint32_t *task_ptr)
{
    if(ch_num >= 16)
    {
        return;
    }
    else
    {
#if(USE_WITH_SOFTDEVICE == 1)
        sd_ppi_channel_assign(ch_num, event_ptr, task_ptr);
#else
        NRF_PPI->CH[ch_num].EEP = (uint32_t)event_ptr;
        NRF_PPI->CH[ch_num].TEP = (uint32_t)task_ptr;    
#endif
    }
}
bool twi_master_init(twi_init_config_t *init_cfg,twi_config_t *cfg)
{
    cfg->twi_operation_complete = true;
    cfg->twi_ack_received = true;

          
    /* To secure correct signal levels on the pins used by the TWI
       master when the system is in OFF mode, and when the TWI master is 
       disabled, these pins must be configured in the GPIO peripheral.
    */ 
    NRF_GPIO->PIN_CNF[init_cfg->twi_pinselect_scl] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);    

    NRF_GPIO->PIN_CNF[init_cfg->twi_pinselect_sda] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos); 
    
    cfg->twi->EVENTS_RXDREADY = 0;
    cfg->twi->EVENTS_TXDSENT = 0;
    cfg->twi->PSELSCL = init_cfg->twi_pinselect_scl;
    cfg->twi->PSELSDA = init_cfg->twi_pinselect_sda;
    
    switch(init_cfg->frequency)
    {
        case TWI_FREQ_100KHZ:
            cfg->twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos;
            break;
        case TWI_FREQ_400KHZ:
            cfg->twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos;
            break;
    }
    sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_SUSPEND);
    sd_ppi_channel_enable_clr(1 << cfg->twi_ppi_ch);
    sd_nvic_SetPriority(init_cfg->twi_interrupt_no, TWI_IRQ_PRIORITY_SD);
    sd_nvic_EnableIRQ(init_cfg->twi_interrupt_no);
    cfg->twi->INTENSET = TWI_INTENSET_TXDSENT_Msk | TWI_INTENSET_STOPPED_Msk | TWI_INTENSET_ERROR_Msk | TWI_INTENSET_RXDREADY_Msk;
    cfg->twi->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
    return twi_master_clear_bus(init_cfg);
}
/** @brief Function for initializing the twi_master.
 */
bool twi_master_init(void)
{
    /* To secure correct signal levels on the pins used by the TWI
       master when the system is in OFF mode, and when the TWI master is 
       disabled, these pins must be configured in the GPIO peripheral.
    */
    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] =     \
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) \
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  \
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) \
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);   

    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] =      \
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) \
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  \
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) \
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);    

    NRF_TWI1->EVENTS_RXDREADY = 0;
    NRF_TWI1->EVENTS_TXDSENT  = 0;
    NRF_TWI1->PSELSCL         = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
    NRF_TWI1->PSELSDA         = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
    NRF_TWI1->FREQUENCY       = TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos;
    
    sd_softdevice_is_enabled(&sd_enabled);
    if(sd_enabled)
    {
        sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_SUSPEND);
        sd_ppi_channel_enable_clr(1 << 0);
    }
    else
    {
        NRF_PPI->CH[0].EEP        = (uint32_t)&NRF_TWI1->EVENTS_BB;
        NRF_PPI->CH[0].TEP        = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
        NRF_PPI->CHENCLR          = PPI_CHENCLR_CH0_Msk;
    }    

    NRF_TWI1->ENABLE          = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

    return twi_master_clear_bus();
}
Beispiel #14
0
//#pragma GCC
bool twi_master_init(void) {
	/* To secure correct signal levels on the pins used by the TWI
	 master when the system is in OFF mode, and when the TWI master is
	 disabled, these pins must be configured in the GPIO peripheral.
	 */
	uint32_t err_code =0;(void)err_code;

	NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] =
			(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
					| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
					| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
					| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
					| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);

	NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] =
			(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
					| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
					| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
					| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
					| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);

	NRF_TWI1->EVENTS_RXDREADY = 0;
	NRF_TWI1->EVENTS_TXDSENT = 0;
	NRF_TWI1->PSELSCL = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
	NRF_TWI1->PSELSDA = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
	NRF_TWI1->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400
			<< TWI_FREQUENCY_FREQUENCY_Pos;

	/*
	 NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TWI1->EVENTS_BB;
	 NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
	 NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;*/
	err_code = sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
			&(NRF_TWI1->TASKS_SUSPEND));
	ASSERT(err_code == NRF_SUCCESS);

	err_code = sd_ppi_channel_enable_clr(PPI_CHEN_CH0_Msk);
	ASSERT(err_code == NRF_SUCCESS);

	NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

	return twi_master_clear_bus();
}
uint32_t wirePPIChannel(uint8_t channel_num, const volatile void * evt_endpoint, const volatile void * task_endpoint)
{
	uint32_t err_code = NRF_SUCCESS;
	uint8_t  softdevice_enabled;

	APP_ERROR_CHECK_BOOL(channel_num != UNAVAILABLE_PPI_CHANNEL
			&& channel_num < NB_PPI_APP_CHANNELS_SD_DISABLED);

	err_code = sd_softdevice_is_enabled(&softdevice_enabled);
	APP_ERROR_CHECK(err_code);
	if (softdevice_enabled == 0 )
	{
		NRF_PPI->CH[channel_num].EEP	=	(uint32_t)evt_endpoint;
		NRF_PPI->CH[channel_num].TEP  =	(uint32_t)task_endpoint;
		enablePPIChannel(channel_num);
	}
	else
	{
		err_code = sd_ppi_channel_assign(channel_num, evt_endpoint, task_endpoint);
		APP_ERROR_CHECK(err_code);
		enablePPIChannel(channel_num);
	}
	return 0;
}
Beispiel #16
0
/****************************************************
*                 Function Definitions
****************************************************/
void tone(uint8_t pin, uint16_t freq, uint32_t duration)
{
    uint8_t nrf_pin;
    uint32_t compare, prescaler;

    nrf_pin = Pin_nRF51822_to_Arduino(pin);
    if(nrf_pin >= 31)
        return;

    log_info("TONE : Start a tone \r\n");
    // Find appropriate values for PRESCALER and COMPARE registers
    uint8_t index;
    for (index=0; index<= 9; index++)
    {
        prescaler = index;
        compare = 16000000UL / freq;
        compare = compare >> (prescaler+1);
        compare = compare - 1;
        if ((compare >= 2) && (compare <= 65535))
            break;
    }
    log_info("TONE : The prescaler is %d \r\n", prescaler);
    log_info("TONE : The compare is %d \r\n", compare);
    // Check duration
    if(duration > 0) {
        finish_flag = 1;
        inter_count = ((freq * duration) / 1000) * 2;
    }
    else {
        finish_flag = 0;
        inter_count = 0xFFFFFFFF;
    }
    // Config GPIOTE task out.
    NRF_GPIOTE->CONFIG[TONE_USED_GPIOTE_NUM] &= ~( GPIOTE_CONFIG_MODE_Msk | GPIOTE_CONFIG_POLARITY_Msk);
    NRF_GPIOTE->CONFIG[TONE_USED_GPIOTE_NUM] = ( (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
                                                 (nrf_pin << GPIOTE_CONFIG_PSEL_Pos) |
                                                 (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |  //Task toggle
                                                 (GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos) //Inital value LOW
                                               );
#if defined(SOFTDEVICE_PRESENT)
    // Check whether softdevice is enbale.
    uint8_t  softdevice_enabled;
    uint32_t error_code;
    sd_softdevice_is_enabled(&softdevice_enabled);
    if(softdevice_enabled == 0) {
        log_info("TONE : Softdevice is disable, config PPI \r\n");
        NRF_PPI->CH[TONE_USED_PPI_CHANNAL].EEP = (uint32_t)(&TONE_USED_TIMER->EVENTS_COMPARE[0]);
        NRF_PPI->CH[TONE_USED_PPI_CHANNAL].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[TONE_USED_GPIOTE_NUM]);
        NRF_PPI->CHEN |= (1 << TONE_USED_PPI_CHANNAL);
    }
    else {
        log_info("TONE : Softdevice is enable, config PPI \r\n");
        error_code = sd_ppi_channel_assign(TONE_USED_PPI_CHANNAL, &TONE_USED_TIMER->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[TONE_USED_GPIOTE_NUM]);
        APP_ERROR_CHECK(error_code);
        error_code = sd_ppi_channel_enable_set(1 << TONE_USED_PPI_CHANNAL);
        APP_ERROR_CHECK(error_code);
    }
#else
    log_info("TONE : Softdevice is not used, config PPI \r\n");
    NRF_PPI->CH[TONE_USED_PPI_CHANNAL].EEP = (uint32_t)(&TONE_USED_TIMER->EVENTS_COMPARE[0]);
    NRF_PPI->CH[TONE_USED_PPI_CHANNAL].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[TONE_USED_GPIOTE_NUM]);
    NRF_PPI->CHEN |= (1 << TONE_USED_PPI_CHANNAL);
#endif

    log_info("TONE : Init TIMIERx \r\n");
    // Configure TIMERx
    TONE_USED_TIMER->TASKS_STOP = 1;
    TONE_USED_TIMER->TASKS_CLEAR = 1;

    TONE_USED_TIMER->MODE = TIMER_MODE_MODE_Timer;
    TONE_USED_TIMER->PRESCALER = prescaler;
    TONE_USED_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
    TONE_USED_TIMER->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);

    TONE_USED_TIMER->CC[0] = (uint16_t)(compare);
    TONE_USED_TIMER->EVENTS_COMPARE[0] = 0;

    TONE_USED_TIMER->INTENCLR = 0xFFFFFFFF;
    TONE_USED_TIMER->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
    // Enable IRQn
    NVIC_SetPriority(TONE_USED_TIMER_IRQn, APP_IRQ_PRIORITY_LOW);
    NVIC_ClearPendingIRQ(TONE_USED_TIMER_IRQn);
    NVIC_EnableIRQ(TONE_USED_TIMER_IRQn);
    // Start TIMER
    log_info("TONE : Start TIMIERx \r\n");
    TONE_USED_TIMER->TASKS_START = 1;
}
/** @brief Function for read by twi_master. 
 */
static bool twi_master_read(uint8_t *data, uint8_t data_length, bool issue_stop_condition)
{
    uint32_t timeout = MAX_TIMEOUT_LOOPS;   /* max loops to wait for RXDREADY event*/

    sd_softdevice_is_enabled(&sd_enabled);
    
    if (data_length == 0)
    {
        /* Return false for requesting data of size 0 */
        return false;
    }
    else if (data_length == 1)
    {
        if(sd_enabled)
        {
            sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_STOP);
        }
        else
        {
            NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
        }
    }
    else
    {
        if(sd_enabled)
        {
            sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_SUSPEND);
        }
        else
        {
            NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
        }
    }
    
    if(sd_enabled)
    {
        sd_ppi_channel_enable_set(1 << 0);
    }
    else
    {
        NRF_PPI->CHENSET          = PPI_CHENSET_CH0_Msk;
    }
    NRF_TWI1->EVENTS_RXDREADY = 0;
    NRF_TWI1->TASKS_STARTRX   = 1;
    
    /** @snippet [TWI HW master read] */                
    while (true)
    {
        while(NRF_TWI1->EVENTS_RXDREADY == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
        {    
            // Do nothing.
        }
        NRF_TWI1->EVENTS_RXDREADY = 0;

        if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
        {
          // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at 
          // Product Anomaly Notification document found at 
          // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
          NRF_TWI1->EVENTS_ERROR = 0;
          NRF_TWI1->ENABLE       = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; 
          NRF_TWI1->POWER        = 0; 
          nrf_delay_us(5); 
          NRF_TWI1->POWER        = 1; 
          NRF_TWI1->ENABLE       = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

          (void)twi_master_init();          
          
          return false;
        }

        *data++ = NRF_TWI1->RXD;

        /* Configure PPI to stop TWI master before we get last BB event */
        if (--data_length == 1)
        {
            sd_softdevice_is_enabled(&sd_enabled);
            if(sd_enabled)
            {
                sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_STOP);
            }
            else
            {
                NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
            }
        }

        if (data_length == 0)
        {
            break;
        }

        // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at 
        // Product Anomaly Notification document found at 
        // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
        nrf_delay_us(20);      
        NRF_TWI1->TASKS_RESUME = 1;
    }
    /** @snippet [TWI HW master read] */                    

    /* Wait until stop sequence is sent */
    while(NRF_TWI1->EVENTS_STOPPED == 0)
    {
        // Do nothing.
    }
    NRF_TWI1->EVENTS_STOPPED = 0;
    
    sd_softdevice_is_enabled(&sd_enabled);
    if(sd_enabled)
    {
        sd_ppi_channel_enable_clr(1 << 0);
    }
    else
    {
        NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
    }
    return true;
}
Beispiel #18
0
/**********************************************************************
name :
function : 
**********************************************************************/
void tone(uint32_t pin, uint16_t freq, uint32_t duration)
{
	uint32_t i,prescaler, compare, nrf_pin, err_code = NRF_SUCCESS;
	uint8_t channel, softdevice_enabled;
	
	channel = gpioteChannelFind();
	if(channel == UNAVAILABLE_GPIOTE_CHANNEL)
	{
		return;
	}
	nrf_pin = arduinoToVariantPin(pin);
	if(nrf_pin < 31)
	{
		//save the pin number
		tone_pin = nrf_pin;
		
		// Find appropriate values for PRESCALER and COMPARE registers
		for (i = 0; i <= 9; i++)
		{
			prescaler = i;
			compare = VARIANT_MCK / freq;
			compare = compare >> (prescaler+1);
			compare = compare - 1;
			if ((compare >= 2) && (compare <= 65535))
				break;
		}
		//calculate the interrupts count
		if(duration > 0)
		{	
			finish_flag = 1;
			inter_count = ((freq * duration) / 1000) * 2;
		}
		else
		{
			finish_flag = 0;
			inter_count = 0xFFFFFFFF;
		}
		//
		//pinMode(pin, OUTPUT);
		//digitalWrite(pin, LOW);
		NRF_GPIO->PIN_CNF[nrf_pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
								| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
								| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
								| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
								| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);	
		NRF_GPIO->OUTCLR = (1 << nrf_pin);						
		//pin_state = 0;
		//use ppi and gpiote_task 
		tone_channel = channel;
		gpioteChannelSet(channel);
		nrf_gpiote_task_config(channel, nrf_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
		//configure PPI
		err_code = sd_softdevice_is_enabled(&softdevice_enabled);
		APP_ERROR_CHECK(err_code);
		if (softdevice_enabled == 0)
		{	
			NRF_PPI->CH[6].EEP = (uint32_t)( &NRF_TIMER2->EVENTS_COMPARE[0] );
			NRF_PPI->CH[6].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[channel]);
			NRF_PPI->CHEN |= ( 1 << 6);
		}
		else
		{
			err_code = sd_ppi_channel_assign(6, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[channel]);
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_set(1 << 6);
			APP_ERROR_CHECK(err_code);
		}
		//Configure TIMER2
		NRF_TIMER2->TASKS_STOP = 1;
		NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
		NRF_TIMER2->PRESCALER = prescaler;
		NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
		
		NRF_TIMER2->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);

		NRF_TIMER2->TASKS_CLEAR = 1;
		NRF_TIMER2->CC[0] = (uint16_t)(compare);
		NRF_TIMER2->EVENTS_COMPARE[0] = 0;
		
		NRF_TIMER2->INTENCLR = 0xFFFFFFFF;
		NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
		//open IRQ
		IntController_linkInterrupt(TIMER2_IRQn, TIMER2_handler);
		NVIC_EnableIRQ(TIMER2_IRQn);
		NRF_TIMER2->TASKS_START = 1;
	}
/**********************************************************************
name :  
function : called by wiring_digital.c
**********************************************************************/
void PPI_ON_TIMER_GPIO(uint32_t gpiote_channel, NRF_TIMER_Type* Timer, uint32_t CC_channel)
{	
	uint32_t err_code = NRF_SUCCESS, chen;

	// Initialize Programmable Peripheral Interconnect
	int chan_0 = find_free_PPI_channel(255);
	int chan_1 = find_free_PPI_channel(chan_0);
	
	if ((chan_0 != 255) && (chan_1 != 255))
	{	
		err_code = sd_softdevice_is_enabled(&softdevice_enabled);
		APP_ERROR_CHECK(err_code);
		if (softdevice_enabled == 0)
		{	
			// Enable PPI using registers
			NRF_PPI->CH[chan_0].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[CC_channel]) );
			NRF_PPI->CH[chan_0].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
			NRF_PPI->CHEN |= ( 1 << chan_0);
			// Save PPI channel number
			PPI_Channels_Occupied[gpiote_channel][0] = chan_0;
			
			// Configure PPI channel "chan_1" to toggle "ulPin" pin on every Timer COMPARE[3] match
			NRF_PPI->CH[chan_1].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[3]) );
			NRF_PPI->CH[chan_1].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
			NRF_PPI->CHEN |= ( 1 << chan_1);
			// Save PPI channel number
			PPI_Channels_Occupied[gpiote_channel][1] = chan_1;
			//simple_uart_printHEX(NRF_PPI->CHEN);
						
		}
		else
		{	
			//Enable PPI using sd_ppi_x
			err_code = sd_ppi_channel_assign(chan_0, &((*Timer).EVENTS_COMPARE[CC_channel]), &NRF_GPIOTE->TASKS_OUT[gpiote_channel]);
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_set(1 << chan_0);
			APP_ERROR_CHECK(err_code);
			//Save PPI channel number
			PPI_Channels_Occupied[gpiote_channel][0] = chan_0;
			
			err_code = sd_ppi_channel_assign(chan_1, &((*Timer).EVENTS_COMPARE[3]), &NRF_GPIOTE->TASKS_OUT[gpiote_channel]);
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_set(1 << chan_1 );	
			APP_ERROR_CHECK(err_code);
			//Save PPI channel number
			PPI_Channels_Occupied[gpiote_channel][1] = chan_1;	
			
			err_code = sd_ppi_channel_enable_get(&chen);
			APP_ERROR_CHECK(err_code);
		}

	}

	/*
	if(0 == gpiote_channel)
	{
		NRF_PPI->CH[9].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[CC_channel]) );
		NRF_PPI->CH[9].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		
		NRF_PPI->CHEN |= ( 1 << 9);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][0] = 9;

		NRF_PPI->CH[10].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[3]) );
		NRF_PPI->CH[10].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		NRF_PPI->CHEN |= ( 1 << 10);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][1] = 10;		
	}
	else if(1 == gpiote_channel)
	{
		NRF_PPI->CH[11].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[CC_channel]) );
		NRF_PPI->CH[11].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		NRF_PPI->CHEN |= ( 1 << 11);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][0] = 11;

		NRF_PPI->CH[12].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[3]) );
		NRF_PPI->CH[12].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		NRF_PPI->CHEN |= ( 1 << 12);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][1] = 12;		
	}
	else if(2 == gpiote_channel)
	{
		NRF_PPI->CH[13].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[CC_channel]) );
		NRF_PPI->CH[13].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		NRF_PPI->CHEN |= ( 1 << 13);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][0] = 13;

		NRF_PPI->CH[14].EEP = (uint32_t)( &((*Timer).EVENTS_COMPARE[3]) );
		NRF_PPI->CH[14].TEP = (uint32_t)( &NRF_GPIOTE->TASKS_OUT[gpiote_channel] );
		NRF_PPI->CHEN |= ( 1 << 14);
		// Save PPI channel number
		PPI_Channels_Occupied[gpiote_channel][1] = 14;		
	}
	*/
}