uint32_t app_button_is_pushed(uint8_t button_id, bool * p_is_pushed) { uint32_t err_code; uint32_t active_pins; if (button_id > m_button_count) { return NRF_ERROR_INVALID_PARAM; } app_button_cfg_t * p_btn = &mp_buttons[button_id]; if (mp_buttons == NULL) { return NRF_ERROR_INVALID_STATE; } err_code = app_gpiote_pins_state_get(m_gpiote_user_id, &active_pins); if (err_code != NRF_SUCCESS) { return err_code; } if(p_btn->active_state == APP_BUTTON_ACTIVE_LOW) { // If the pin is active low, then the pin being high means it is not pushed. if(((active_pins >> p_btn->pin_no) & 0x01)) { *p_is_pushed = false; } else { *p_is_pushed = true; } }
uint32_t app_button_is_pushed(uint8_t pin_no, bool * p_is_pushed) { uint32_t err_code; uint32_t active_pins; uint32_t pin_mask = 0; if (mp_buttons == NULL) { return NRF_ERROR_INVALID_STATE; } err_code = app_gpiote_pins_state_get(m_gpiote_user_id, &active_pins); if (err_code != NRF_SUCCESS) { return err_code; } pin_mask = (1 << pin_no); if ((pin_mask & active_pins) == 0) { *p_is_pushed = ((m_active_low_states_mask & pin_mask) ? true : false); } else { *p_is_pushed = ((m_active_high_states_mask & pin_mask) ? true : false); } return NRF_SUCCESS; }
/**@brief GPIOTE event handler. * * @param[in] event_pins_low_to_high Mask telling which pin(s) generated an event from low->high. * @param[in] event_pins_high_to_low Mask telling which pin(s) generated an event from high->low. */ static void gpiote_uart_event_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low) { if ((event_pins_high_to_low & event_pins_low_to_high & m_pin_cts_mask) != 0) { // We have an indication from GPIOTE that the CTS pin has toggled high->low and low->high. // If this occurs, we must read the active pins in the GPIOTE module ourself. uint32_t active_pins; uint32_t err_code; err_code = app_gpiote_pins_state_get(m_gpiote_uid, &active_pins); if (err_code != NRF_SUCCESS) { // Pin reading was not possible, even though an event from GPIOTE was received that the // CTS pin toggled. If pin double toggled but status cannot be fetched we silently // return and keep the current UART status as-is. return; } event_pins_low_to_high &= active_pins; event_pins_high_to_low &= ~active_pins; } if ((event_pins_high_to_low & m_pin_cts_mask) != 0) { on_uart_event(ON_CTS_LOW); } else if ((event_pins_low_to_high & m_pin_cts_mask) != 0) { on_uart_event(ON_CTS_HIGH); } else { // Do nothing, as the CTS pin didn't toggle. } }
/**@brief Function for handling the timeout that delays reporting buttons as pushed. * * @details The detection_delay_timeout_handler(...) is a call-back issued from the app_timer * module. It is called with the p_context parameter. The p_context parameter is * provided to the app_timer module when a timer is started, using the call * @ref app_timer_start. On @ref app_timer_start the p_context will be holding the * currently pressed buttons. * * @param[in] p_context Pointer used for passing information app_start_timer() was called. * In the app_button module the p_context holds information on pressed * buttons. */ static void detection_delay_timeout_handler(void * p_context) { uint32_t err_code; uint32_t current_state_pins; // Get current state of pins. err_code = app_gpiote_pins_state_get(m_gpiote_user_id, ¤t_state_pins); if (err_code != NRF_SUCCESS) { return; } uint8_t i; // Pushed button(s) detected, execute button handler(s). for (i = 0; i < m_button_count; i++) { app_button_cfg_t * p_btn = &mp_buttons[i]; if (((m_pin_transition.high_to_low & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL)) { //If it's active high then going from high to low was a release of the button. if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH) { button_handler_execute(p_btn, APP_BUTTON_RELEASE); } //If it's active low then going from high to low was a push of the button. else { button_handler_execute(p_btn, APP_BUTTON_PUSH); } } else if (((m_pin_transition.low_to_high & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL)) { //If it's active high then going from low to high was a push of the button. if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH) { button_handler_execute(p_btn,APP_BUTTON_PUSH); } //If it's active low then going from low to high was a release of the button. else { button_handler_execute(p_btn,APP_BUTTON_RELEASE); } } } }
/**@brief Timeout handler for delaying reporting buttons as pushed. * * @details The detection_delay_timeout_handler(...) is a call-back issued from the app_timer * module. It is called with the p_context parameter. The p_context parameter is * provided to the app_timer module when a timer is started, using the call * @ref app_timer_start. On @ref app_timer_start the p_context will be holding the * currently pressed buttons. * * @param[in] p_context Pointer used for passing information app_start_timer() was called. * In the app_button module the p_context holds information on pressed * buttons. */ static void detection_delay_timeout_handler(void * p_context) { uint32_t err_code; uint32_t event_pins_mask; uint32_t current_state_pins; uint32_t active_pins = 0; // Get state of pins when timer was started. event_pins_mask = (uint32_t)p_context; // Get current state of pins. err_code = app_gpiote_pins_state_get(m_gpiote_user_id, ¤t_state_pins); if (err_code != NRF_SUCCESS) { return; } active_pins = current_state_pins & m_active_high_states_mask; active_pins |= (~current_state_pins & m_active_low_states_mask); event_pins_mask &= active_pins; // Check if any event generating pins are still active. if (event_pins_mask != 0) { uint8_t i; // Pushed button(s) detected, execute button handler(s). for (i = 0; i < m_button_count; i++) { app_button_cfg_t * p_btn = &mp_buttons[i]; if (((event_pins_mask & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL)) { button_handler_execute(p_btn); } } } }
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params, app_uart_buffers_t * p_buffers, app_uart_event_handler_t event_handler, app_irq_priority_t irq_priority) { uint32_t err_code; uint32_t gpiote_high_pins; uint32_t gpiote_pin_low_high_mask = 0; uint32_t gpiote_pin_high_low_mask = 0; m_current_state = UART_OFF; m_event_handler = event_handler; // Configure buffer RX buffer. err_code = app_fifo_init(&m_rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size); if (err_code != NRF_SUCCESS) { // Propagate error code. return err_code; } // Configure buffer TX buffer. err_code = app_fifo_init(&m_tx_fifo, p_buffers->tx_buf, p_buffers->tx_buf_size); if (err_code != NRF_SUCCESS) { // Propagate error code. return err_code; } // Configure RX and TX pins. nrf_gpio_cfg_output(p_comm_params->tx_pin_no); nrf_gpio_cfg_input(p_comm_params->rx_pin_no, NRF_GPIO_PIN_NOPULL); NRF_UART0->PSELTXD = p_comm_params->tx_pin_no; NRF_UART0->PSELRXD = p_comm_params->rx_pin_no; // Configure baud rate and parity. NRF_UART0->BAUDRATE = (p_comm_params->baud_rate << UART_BAUDRATE_BAUDRATE_Pos); if (p_comm_params->use_parity) { NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos); } else { NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos); } if (p_comm_params->use_hardware_flow_control) { // Configure hardware flow control. nrf_gpio_cfg_output(p_comm_params->rts_pin_no); NRF_GPIO->OUT = 1 << p_comm_params->rts_pin_no; NRF_UART0->PSELCTS = UART_PIN_DISCONNECTED; NRF_UART0->PSELRTS = p_comm_params->rts_pin_no; NRF_UART0->CONFIG |= (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos); // Setup the gpiote to handle pin events on cts-pin. // For the UART we want to detect both low->high and high->low transistions in order to // know when to activate/deactivate the TX/RX in the UART. // Configure pin. m_pin_cts_mask = (1 << p_comm_params->cts_pin_no); GPIO_PIN_CONFIG(p_comm_params->cts_pin_no, GPIO_PIN_CNF_DIR_Input, GPIO_PIN_CNF_INPUT_Connect, GPIO_PIN_CNF_PULL_Disabled, GPIO_PIN_CNF_DRIVE_S0S1, GPIO_PIN_CNF_SENSE_Low); gpiote_pin_low_high_mask = (1 << p_comm_params->cts_pin_no); gpiote_pin_high_low_mask = (1 << p_comm_params->cts_pin_no); err_code = app_gpiote_user_register(&m_gpiote_uid, gpiote_pin_low_high_mask, gpiote_pin_high_low_mask, gpiote_uart_event_handler); if (err_code != NRF_SUCCESS) { return err_code; } err_code = app_gpiote_pins_state_get(m_gpiote_uid, &gpiote_high_pins); if (err_code != NRF_SUCCESS) { return err_code; } err_code = app_gpiote_user_enable(m_gpiote_uid); if (err_code != NRF_SUCCESS) { return err_code; } // UART CTS pin is active when low. if ((gpiote_high_pins & (1 << p_comm_params->cts_pin_no)) == 0) { on_uart_event(ON_CTS_LOW); } else { on_uart_event(ON_CTS_HIGH); } } else { uart_no_flow_control_init(); m_current_state = UART_READY; } // Enable UART interrupt NRF_UART0->INTENCLR = 0xffffffffUL; NRF_UART0->INTENSET = (UART_INTENSET_RXDRDY_Set << UART_INTENSET_RXDRDY_Pos) | (UART_INTENSET_TXDRDY_Set << UART_INTENSET_TXDRDY_Pos) | (UART_INTENSET_ERROR_Set << UART_INTENSET_ERROR_Pos); NVIC_ClearPendingIRQ(UART0_IRQn); NVIC_SetPriority(UART0_IRQn, irq_priority); NVIC_EnableIRQ(UART0_IRQn); return NRF_SUCCESS; }