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 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); }
/* @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; }
/*---------------------------------------------------------------------------*/ 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; } }
/** @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(); }
//#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; }
/**************************************************** * 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; } */ }