欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蓝牙BLE---DA14683的GPIO中断按键源码

程序员文章站 2022-05-25 17:06:56
...

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();
}

 

相关标签: DA14683