1. 程式人生 > >藍芽BLE---DA14683的GPIO中斷按鍵原始碼

藍芽BLE---DA14683的GPIO中斷按鍵原始碼

ad_gpio_intr.h 

/**
 * \addtogroup BSP
 * \{
 * \addtogroup ADAPTERS
 * \{
 * \addtogroup GPIO_INTR
 * \{
 */

/**
 *****************************************************************************************
 *
 * @file ad_gpio_intr.h
 *
 * @brief WKUP adapter API
 *
 * Copyright (C) 2015. Dialog Semiconductor Ltd, unpublished work. This computer
 * program includes Confidential, Proprietary Information and is a Trade Secret of
 * Dialog Semiconductor Ltd. All use, disclosure, and/or reproduction is prohibited
 * unless authorized in writing. All Rights Reserved.
 *
 * <
[email protected]
> and contributors. * ***************************************************************************************** */ #ifndef AD_GPIO_INTR_H_ #define AD_GPIO_INTR_H_ #include <hw_gpio.h> #ifdef __cplusplus extern "C" { #endif /** * \brief Device gpio pointer, handle to use with ad_gpio_intr_register(), ad_gpio_intr_unregister() etc. * */ #ifndef AD_GPIO_INTR_INSTANCE /** * \brief Entry for gpio interrupt * * \param [in] _name name that will be later used to refer to instance * \param [in] _port port id of triggering pin * \param [in] _pin pin id of triggering pin * \param [in] _press_callback function to be called when interrupt occurs * \param [in] _release_callback function to be called when interrupt occurs * */ #define AD_GPIO_INTR_INSTANCE(_name, _port, _pin, _press_callback, _release_callback) \ INITIALISED_PRIVILEGED_DATA ad_gpio_intr_config dev_##_name = { \ .port = _port, \ .pin = _pin, \ .pressed = false, \ .press_cb = _press_callback, \ .release_cb = _release_callback, \ .next_element = NULL, \ }; \ INITIALISED_PRIVILEGED_DATA ad_gpio_intr_config *_name = &dev_##_name; #endif /** * \brief Definition of callback function */ typedef void (*ad_gpio_intr_cb)(void); /** * \brief Definition of the structure of gpio interrupt instance */ typedef struct ad_gpio_intr_config { HW_GPIO_PORT port; HW_GPIO_PIN pin; bool pressed; ad_gpio_intr_cb press_cb; ad_gpio_intr_cb release_cb; struct ad_gpio_intr_config *next_element; } ad_gpio_intr_config; /** * \brief Initialize adapter environment */ void ad_gpio_intr_init(void); /** * \brief Register instance and if necessary setup wkup driver * * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro) */ void ad_gpio_intr_register(ad_gpio_intr_config *cfg); /** * \brief Unregister instance * * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro) */ void ad_gpio_intr_unregister(ad_gpio_intr_config *cfg); /** * \brief Check if instance has been registered * * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro) * * \return true if instance has been registered, false otherwise */ bool ad_gpio_intr_check_registered(ad_gpio_intr_config *cfg); /** * \brief Check if interrupt has been handled by checking the level of the specific irq line * * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro) * * \return true if instance has been handled, false otherwise */ bool ad_gpio_irq_handled(ad_gpio_intr_config *cfg); #ifdef __cplusplus extern } #endif #endif /* AD_GPIO_INTR_H_ */ /** * \} * \} * \} */

 

ad_gpio_intr.c

/**
 * \addtogroup BSP
 * \{
 * \addtogroup ADAPTERS
 * \{
 * \addtogroup GPIO_INTR
 * \{
 */

/**
 *****************************************************************************************
 *
 * @file ad_gpio_intr.c
 *
 * @brief WKUP adapter implementation
 *
 * Copyright (C) 2015. Dialog Semiconductor Ltd, unpublished work. This computer
 * program includes Confidential, Proprietary Information and is a Trade Secret of
 * Dialog Semiconductor Ltd. All use, disclosure, and/or reproduction is prohibited
 * unless authorized in writing. All Rights Reserved.
 *
 * <
[email protected]
> and contributors. * ***************************************************************************************** */ #if dg_configUSE_HW_KEYBOARD_SCANNER #include <stdint.h> #include "sdk_defs.h" #include "interrupts.h" #include <sys_power_mgr.h> #include <ad_gpio_intr.h> #include <assert.h> #include <stdarg.h> #include <platform_devices.h> #include <hw_wkup.h> #include "hw_keyboard_scanner.h" #include "hw_cpm.h" /* * \brief Definitions */ #define BUFFER_SIZE 16 //size must be a base-2 number #define WKUP_INT_PRIO 1 /* * \brief Forward function declarations */ static int ad_kbscn_msg_cb(void); static int ad_kbscn_fifo_over_cb(void); static void ad_wkup_cb(void); static void ad_gpio_intr_wake_up_ind(bool value); static bool ad_gpio_intr_prepare_for_sleep(void); static void ad_gpio_intr_sleep_cancel(void); static void ad_gpio_intr_xtal16m_ready_ind(void); /* * \brief Global variables */ struct ad_gpio_intr_env_t { OS_MUTEX ad_gpio_intr_mutex; ad_gpio_intr_config *head_config; }; const adapter_call_backs_t ad_gpio_intr_pm_call_backs = { .ad_prepare_for_sleep = ad_gpio_intr_prepare_for_sleep, .ad_sleep_canceled = ad_gpio_intr_sleep_cancel, .ad_wake_up_ind = ad_gpio_intr_wake_up_ind, .ad_xtal16m_ready_ind = ad_gpio_intr_xtal16m_ready_ind, .ad_sleep_preparation_time = 0, }; INITIALISED_PRIVILEGED_DATA static wkup_config ad_gpio_intr_wkup_cfg = { .debounce = 0, #if (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) .threshold = 1, #endif }; INITIALISED_PRIVILEGED_DATA static uint8_t columns[] = { UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, UNUSED_INDEX, }; INITIALISED_PRIVILEGED_DATA static uint8_t rows[] = { UNUSED_INDEX, }; PRIVILEGED_DATA static struct kbscn_msg_tag msg_buf[BUFFER_SIZE]; INITIALISED_PRIVILEGED_DATA struct kbscn_init_tag ad_gpio_intr_kbscn_init_env = { .columns = columns, .rows = rows, .num_columns = sizeof(columns), .num_rows = sizeof(rows), .row_scan_active_time = 1, // 1 + 1w + 1z = 3 cycles x (div/16 usec) = 3 usec => scan cycle = 1 * 3 = 3 usec .debounce_press_time = 5, // 5 * scan cycle = 15 usec .debounce_release_time = 5, // 5 * scan cycle = 15 usec .inactive_time = 0, .clock_div = KBSCN_PCLK_DIV16, // 16MHz / div = 1MHz .inactivity_cb = NULL, .fifo_under_cb = NULL, .fifo_over_cb = ad_kbscn_fifo_over_cb, .msg_cb = ad_kbscn_msg_cb, .msg_buf = msg_buf, .msg_buf_sz = BUFFER_SIZE, .msg_evt = true, .inactive_evt = false, .fifo_evt = true, }; PRIVILEGED_DATA static uint32_t msg_wr_idx = 0, msg_rd_idx = 0; PRIVILEGED_DATA static struct ad_gpio_intr_env_t ad_gpio_intr_env; /* * \brief Functions */ void ad_gpio_intr_init(void) { if (ad_gpio_intr_env.ad_gpio_intr_mutex == NULL) { OS_MUTEX_CREATE(ad_gpio_intr_env.ad_gpio_intr_mutex); OS_ASSERT(ad_gpio_intr_env.ad_gpio_intr_mutex); pm_register_adapter(&ad_gpio_intr_pm_call_backs); hw_wkup_init(NULL); hw_wkup_set_debounce_time(ad_gpio_intr_wkup_cfg.debounce); #if 0//(dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) hw_wkup_set_counter_threshold(ad_gpio_intr_wkup_cfg.threshold); hw_wkup_reset_counter(); #endif } } void ad_gpio_intr_register(ad_gpio_intr_config *cfg) { int i; ad_gpio_intr_config *cfg_ptr; if (!cfg) { return; } OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER); cfg_ptr = ad_gpio_intr_env.head_config; if (!ad_gpio_intr_env.head_config){ ad_gpio_intr_env.head_config = cfg; hw_wkup_register_interrupt(ad_wkup_cb, WKUP_INT_PRIO); } else { while (cfg_ptr) { ///Check if already added if (cfg_ptr == cfg) break; ///Add it if not in the list if (cfg_ptr->next_element == NULL){ cfg_ptr->next_element = cfg; break; } cfg_ptr = cfg_ptr->next_element; } } for (i = 0; i < sizeof(columns); i++) { HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4)); HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]))); if((cfg->port == port) && (cfg->pin == pin)) break; } if (i == sizeof(columns)) { for (i = 0; i < sizeof(columns); i++) { if (columns[i] == UNUSED_INDEX) { columns[i] = CONV_PORT_PIN_TO_INDEX( ((0x0F & cfg->port) << 4) | (0x0F & cfg->pin)); break; } } } OS_ASSERT(i < sizeof(columns)); //No available slot in columns array OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex); hw_wkup_freeze(); if (hw_kbscn_get_status()) hw_kbscn_disable(); hw_kbscn_init(&ad_gpio_intr_kbscn_init_env, &msg_wr_idx, &msg_rd_idx); hw_wkup_configure_pin(cfg->port, cfg->pin, true, HW_WKUP_PIN_STATE_LOW); hw_kbscn_enable(); hw_wkup_unfreeze(); hw_kbscn_activate_msg_evt(); } void ad_gpio_intr_unregister(ad_gpio_intr_config *cfg) { int i; bool remove = true; ad_gpio_intr_config *cfg_ptr; if (!cfg) { return; } for (i = 0; i < sizeof(columns); i++) { HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4)); HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]))); if ((cfg->port == port) && (cfg->pin == pin)) break; } if (i == sizeof(columns)) return; OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER); cfg_ptr = ad_gpio_intr_env.head_config; if(ad_gpio_intr_env.head_config == cfg){ ad_gpio_intr_env.head_config = NULL; hw_wkup_unregister_interrupt(); } else { while (cfg_ptr) { if (cfg_ptr->next_element == cfg) { cfg_ptr->next_element = cfg->next_element; } else if((cfg_ptr->port == cfg->port) && (cfg_ptr->pin == cfg->pin)) { remove = false; break; } cfg_ptr = cfg_ptr->next_element; } } if (remove) columns[i] = UNUSED_INDEX; OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex); hw_wkup_configure_pin(cfg->port, cfg->pin, false, 0); } bool ad_gpio_intr_check_registered(ad_gpio_intr_config *cfg) { bool ret = false; ad_gpio_intr_config *cfg_ptr; if (!cfg) { return ret; } OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER); cfg_ptr = ad_gpio_intr_env.head_config; while (cfg_ptr) { if (cfg_ptr == cfg) { ret = true; break; } cfg_ptr = cfg_ptr->next_element; } OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex); return ret; } bool ad_gpio_irq_handled(ad_gpio_intr_config *cfg) { volatile ad_gpio_intr_config *cfg_gbl = cfg; bool status, ret = true; cfg_gbl->pressed = false; hw_cpm_delay_usec(200); status = hw_gpio_get_pin_status(cfg->port, cfg->pin); if(!cfg_gbl->pressed){ cfg_gbl->pressed = !status; ret = status; } return ret; } static void ad_wkup_cb(void) { hw_wkup_reset_interrupt(); hw_wkup_freeze(); } static void ad_kbscn_msg_consume(void) { struct kbscn_msg_tag *p_msg; ad_gpio_intr_config *cfg_ptr; while (msg_rd_idx != msg_wr_idx) { p_msg = &msg_buf[msg_rd_idx]; if (!(p_msg->flags & LAST_MSG)) { HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[p_msg->column]) >> 4)); HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[p_msg->column]))); OS_ASSERT(p_msg->row == 0); if (p_msg->flags & PRESSED) { cfg_ptr = ad_gpio_intr_env.head_config; while (cfg_ptr) { if ((cfg_ptr->port == port) && (cfg_ptr->pin == pin) && !cfg_ptr->pressed) { cfg_ptr->pressed = true; if (cfg_ptr->press_cb) { cfg_ptr->press_cb(); } } cfg_ptr = cfg_ptr->next_element; } } if (!p_msg->flags) { cfg_ptr = ad_gpio_intr_env.head_config; while (cfg_ptr) { if ((cfg_ptr->port == port) && (cfg_ptr->pin == pin) && cfg_ptr->pressed) { cfg_ptr->pressed = false; if (cfg_ptr->release_cb) { cfg_ptr->release_cb(); } } cfg_ptr = cfg_ptr->next_element; } } } msg_rd_idx++; msg_rd_idx &= (BUFFER_SIZE - 1); // fast modulo operation } } static int ad_kbscn_msg_cb(void) { ad_kbscn_msg_consume(); /* Re-enable fifo irq in case of buffer overflow */ hw_kbscn_activate_msg_evt(); return 0; } static int ad_kbscn_fifo_over_cb(void) { hw_kbscn_disable(); hw_kbscn_reset_fifo(); /* Consume any events in buffer */ ad_kbscn_msg_consume(); /* Reset buffer */ msg_wr_idx = 0; msg_rd_idx = 0; hw_kbscn_enable(); hw_kbscn_activate_msg_evt(); return 0; } static void ad_gpio_intr_wake_up_ind(bool value) { hw_kbscn_init(&ad_gpio_intr_kbscn_init_env, &msg_wr_idx, &msg_rd_idx); hw_kbscn_enable(); hw_kbscn_activate_msg_evt(); } static void ad_gpio_intr_sleep_cancel(void) { hw_wkup_freeze(); } static void ad_gpio_intr_xtal16m_ready_ind(void) { /* nothing to do */ } static bool ad_gpio_intr_prepare_for_sleep(void) { ad_gpio_intr_config *cfg_ptr; for (int i = 0; i < sizeof(columns); i++) { HW_GPIO_PORT port; HW_GPIO_PIN pin; if (columns[i] == UNUSED_INDEX) continue; port = 0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4); pin = 0xF & (CONV_INDEX_TO_PORT_PIN(columns[i])); if (!hw_gpio_get_pin_status(port, pin)){ return false; } } cfg_ptr = ad_gpio_intr_env.head_config; while (cfg_ptr) { if (cfg_ptr->pressed) { return false; } cfg_ptr = cfg_ptr->next_element; } hw_wkup_unfreeze(); return true; } #endif /** * \} * \} * \} */

gpio_key.h

/**
 ****************************************************************************************
 *
 * @file demo_hw.h
 *
 * @brief Code related to mesh reference design hardware
 *
 * Copyright (C) 2016-2018 Dialog Semiconductor.
 * This computer program includes Confidential, Proprietary Information  
 * of Dialog Semiconductor. All Rights Reserved.
 *
 ****************************************************************************************
 */

#ifndef DEMO_HW_H_
#define DEMO_HW_H_

#include <stdint.h>
#include "osal.h"

/**
 * Initialize peripherals needed for demo
 * These are initialized only once
 */
void hw_init(void);

/**
 * Configure peripherals needed for demo
 * These need to be reinitialized after sleep exit
 */
void hw_configure(void);

/**
 * Trigger hardware reset
 */
void hw_trigger_reboot(void);

#endif /* DEMO_HW_H_ */

 gpio_key.c

/**
 ****************************************************************************************
 *
 * @file demo_hw.c
 *
 * @brief Code related to mesh reference design hardware
 *
 * Copyright (C) 2016-2018 Dialog Semiconductor.
 * This computer program includes Confidential, Proprietary Information  
 * of Dialog Semiconductor. All Rights Reserved.
 *
 ****************************************************************************************
 */

#include <stdio.h>
#include <string.h>
#include "hw_led.h"
#include "hw_breath.h"
#include "hw_gpio.h"
#include "hw_wkup.h"
#include "hw_watchdog.h"
#include "hw_timer2.h"
#include "sys_power_mgr.h"
#include "hw_cpm.h"
#include "ad_gpio_intr.h"
#include "ad_spi.h"
#include "sys_rtc.h"
#include "platform_devices.h"
#include "gpio_key.h"
//#include "appl_support.h"

#       define CFG_GPIO_MB_BUTTON_SW1_PORT       (HW_GPIO_PORT_3)
#       define CFG_GPIO_MB_BUTTON_SW1_PIN        (HW_GPIO_PIN_1)

#       define CFG_GPIO_MB_BUTTON_SW2_PORT       (HW_GPIO_PORT_3)
#       define CFG_GPIO_MB_BUTTON_SW2_PIN        (HW_GPIO_PIN_2)


//uint64_t mytime = 0;
static void k1_button_pressed(void);
static void k1_button_released(void);
//Create GPIO interrupt instance for K1 button
static AD_GPIO_INTR_INSTANCE(K1_BUTTON, CFG_GPIO_MB_BUTTON_SW1_PORT, CFG_GPIO_MB_BUTTON_SW1_PIN,
                             k1_button_pressed, k1_button_released);

static void k2_button_pressed(void);
static void k2_button_released(void);
//Create GPIO interrupt instance for K1 button
static AD_GPIO_INTR_INSTANCE(K2_BUTTON, CFG_GPIO_MB_BUTTON_SW2_PORT, CFG_GPIO_MB_BUTTON_SW2_PIN,
                             k2_button_pressed, k2_button_released);


static void k2_button_pressed(void)
{
        printf("k2_button_pressed\r\n");
}

static void k2_button_released(void)
{
        printf("k2_button_released\r\n");
}

static void k1_button_pressed(void)
{
    printf("k1_button_pressed \r\n");
    //mytime = rtc_get_fromISR();
}

static void k1_button_released(void) {
  //  if ((rtc_get_fromISR() - mytime) > 100000)
    {
        printf("k1_button_released \r\n");
    }
}

void hw_configure(void)
{
        /* Configure Pushbutton K1 */
        hw_gpio_configure_pin(CFG_GPIO_MB_BUTTON_SW1_PORT, CFG_GPIO_MB_BUTTON_SW1_PIN,
               HW_GPIO_MODE_INPUT_PULLUP, HW_GPIO_FUNC_GPIO, true);

        hw_gpio_configure_pin(CFG_GPIO_MB_BUTTON_SW2_PORT, CFG_GPIO_MB_BUTTON_SW2_PIN,
               HW_GPIO_MODE_INPUT_PULLUP, HW_GPIO_FUNC_GPIO, true);
        //mytime = rtc_get_fromISR();
}

void hw_set_mb_led1_level(uint8_t level)
{

}

void hw_init(void)
{
        hw_configure();
        ad_gpio_intr_init();
        ad_gpio_intr_register(K1_BUTTON);
        ad_gpio_intr_register(K2_BUTTON);
}


void hw_trigger_reboot(void)
{
        hw_cpm_reboot_system();
}