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; }
static void ppi_enable_channels(uint32_t ch_msk) { #if(USE_WITH_SOFTDEVICE == 1) sd_ppi_channel_enable_set(ch_msk); #else NRF_PPI->CHENSET = (ch_msk); #endif }
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); }
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); }
/* @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); }
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; } }
/** @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 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)); }
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; }
void enablePPIChannel(uint8_t channel_num) { 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->CHEN |= (1 << channel_num); } else { err_code = sd_ppi_channel_enable_set(1 << channel_num); APP_ERROR_CHECK(err_code); } }
uint32_t nrf_drv_ppi_channel_enable(nrf_ppi_channel_t channel) { uint32_t err_code; if (!is_app_channel(channel)) { err_code = NRF_ERROR_INVALID_PARAM; } else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel)) { err_code = NRF_ERROR_INVALID_STATE; } else { #if (NRF_PPI_RESTRICTED > 0) err_code = sd_ppi_channel_enable_set(channel_to_mask(channel)); #else nrf_ppi_channel_enable(channel); err_code = NRF_SUCCESS; #endif } return err_code; }
/**************************************************** * 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; }
/********************************************************************** 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; } */ }