代码拉取完成,页面将自动刷新
同步操作将从 murphyzhao/FlexibleButton 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/**
* @File: flexible_button.c
* @Author: MurphyZhao
* @Date: 2018-09-29
*
* Copyright (c) 2018-2019 MurphyZhao <d2014zjt@163.com>
* https://github.com/murphyzhao
* All rights reserved.
* License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Change logs:
* Date Author Notes
* 2018-09-29 MurphyZhao First add
* 2019-08-02 MurphyZhao 迁移代码到 murphyzhao 仓库
*
*/
#include "flexible_button.h"
#include <string.h>
#include <stdio.h>
static flex_button_t *btn_head = NULL;
#define EVENT_CB_EXECUTOR(button) if(button->cb) button->cb((flex_button_t*)button)
#define MAX_BUTTON_CNT 16
static uint16_t trg = 0;
static uint16_t cont = 0;
static uint16_t keydata = 0xFFFF;
static uint16_t key_rst_data = 0xFFFF;
static uint8_t button_cnt = 0;
/**
* @brief Register a user button
*
* @param button: button structure instance
* @return Number of keys that have been registered
*/
int8_t flex_button_register(flex_button_t *button)
{
flex_button_t *curr = btn_head;
if (!button || (button_cnt > MAX_BUTTON_CNT))
{
return -1;
}
while (curr)
{
if(curr == button)
{
return -1; //already exist.
}
curr = curr->next;
}
button->next = btn_head;
button->status = 0;
button->event = FLEX_BTN_PRESS_NONE;
button->scan_cnt = 0;
button->click_cnt = 0;
btn_head = button;
key_rst_data = key_rst_data << 1;
button_cnt ++;
return button_cnt;
}
/**
* @brief Read all key values in one scan cycle
*
* @param void
* @return none
*/
static void flex_button_read(void)
{
flex_button_t* target;
uint16_t read_data = 0;
keydata = key_rst_data;
int8_t i = 0;
for(target = btn_head, i = 0;
(target != NULL) && (target->usr_button_read != NULL);
target = target->next, i ++)
{
keydata = keydata |
(target->pressed_logic_level == 1 ?
((!(target->usr_button_read)()) << i) :
((target->usr_button_read)() << i));
}
read_data = keydata^0xFFFF;
trg = read_data & (read_data ^ cont);
cont = read_data;
}
/**
* @brief Handle all key events in one scan cycle.
* Must be used after 'flex_button_read' API
*
* @param void
* @return none
*/
static void flex_button_process(void)
{
int8_t i = 0;
flex_button_t* target;
for (target = btn_head, i = 0; target != NULL; target = target->next, i ++)
{
if (target->status > 0)
{
target->scan_cnt ++;
}
switch (target->status)
{
case 0: /* is default */
if (trg & (1 << i)) /* is pressed */
{
target->scan_cnt = 0;
target->click_cnt = 0;
target->status = 1;
target->event = FLEX_BTN_PRESS_DOWN;
EVENT_CB_EXECUTOR(target);
}
else
{
target->event = FLEX_BTN_PRESS_NONE;
}
break;
case 1: /* is pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if ((target->scan_cnt >= target->short_press_start_tick) &&
(target->scan_cnt < target->long_press_start_tick))
{
target->status = 4;
target->event = FLEX_BTN_PRESS_SHORT_START;
EVENT_CB_EXECUTOR(target);
}
break;
case 2: /* is up */
if ((target->scan_cnt < target->click_start_tick))
{
target->click_cnt++; // 1
if (target->click_cnt == 1)
{
target->status = 3; /* double click check */
}
else
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_DOUBLE_CLICK;
EVENT_CB_EXECUTOR(target);
}
}
else if ((target->scan_cnt >= target->click_start_tick) &&
(target->scan_cnt < target->short_press_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_CLICK;
EVENT_CB_EXECUTOR(target);
}
else if ((target->scan_cnt >= target->short_press_start_tick) &&
(target->scan_cnt < target->long_press_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_SHORT_UP;
EVENT_CB_EXECUTOR(target);
}
else if ((target->scan_cnt >= target->long_press_start_tick) &&
(target->scan_cnt < target->long_hold_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_LONG_UP;
EVENT_CB_EXECUTOR(target);
}
else if (target->scan_cnt >= target->long_hold_start_tick)
{
/* long press hold up, not deal */
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_LONG_HOLD_UP;
EVENT_CB_EXECUTOR(target);
}
break;
case 3: /* double click check */
if (trg & (1 << i))
{
target->click_cnt++;
target->status = 2;
target->scan_cnt --;
}
else if (target->scan_cnt >= target->click_start_tick)
{
target->status = 2;
}
break;
case 4: /* is short pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if ((target->scan_cnt >= target->long_press_start_tick) &&
(target->scan_cnt < target->long_hold_start_tick))
{
target->status = 5;
target->event = FLEX_BTN_PRESS_LONG_START;
EVENT_CB_EXECUTOR(target);
}
break;
case 5: /* is long pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if (target->scan_cnt >= target->long_hold_start_tick)
{
target->status = 6;
target->event = FLEX_BTN_PRESS_LONG_HOLD;
EVENT_CB_EXECUTOR(target);
}
break;
case 6: /* is long pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
break;
}
}
}
/**
* flex_button_event_read
*
* @brief Get the button event of the specified button.
*
* @param button: button structure instance
* @return button event
*/
flex_button_event_t flex_button_event_read(flex_button_t* button)
{
return (flex_button_event_t)(button->event);
}
/**
* flex_button_scan
*
* @brief Start key scan.
* Need to be called cyclically within the specified period.
* Sample cycle: 5 - 20ms
*
* @param void
* @return none
*/
void flex_button_scan(void)
{
flex_button_read();
flex_button_process();
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。