/** ****************************************************************************** * @file bflb_kys.c * @version V1.0 * @date 2022-11-17 * @brief This file is the low hardware abstraction layer file ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2022 Bouffalo Lab

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of Bouffalo Lab nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #include "bflb_core.h" #include "bflb_kys.h" #include "bflb_clock.h" #include "bflb_l1c.h" #include "hardware/kys_reg.h" /** * @brief keyscan init * * @param dev * @param config */ void bflb_kys_init(struct bflb_device_s *dev, const struct bflb_kys_config_s *config) { uint32_t reg_base; uint32_t reg_val; reg_base = dev->reg_base; /* disable kys */ reg_val = getreg32(reg_base + KYS_KS_CTRL_OFFSET); reg_val &= ~(KYS_KS_EN_MASK); putreg32(reg_val, reg_base + KYS_KS_CTRL_OFFSET); /* mask all interrupt before init */ reg_val = getreg32(reg_base + KYS_KS_INT_EN_OFFSET); #if defined(BL702) reg_val &= ~(KYS_KS_INT_EN_MASK); #else reg_val &= ~(KYS_KS_DONE_INT_EN_MASK | KYS_KEYFIFO_FULL_INT_EN_MASK | KYS_KEYFIFO_HALF_INT_EN_MASK | KYS_KEYFIFO_QUARTER_INT_EN_MASK | KYS_KEYFIFO_NONEMPTY_INT_EN_MASK | KYS_GHOST_INT_EN_MASK); #endif /* kys init */ reg_val = getreg32(reg_base + KYS_KS_CTRL_OFFSET); reg_val &= ~(KYS_COL_NUM_MASK | KYS_ROW_NUM_MASK | #if defined(BL702L) KYS_FIFO_MODE_MASK | #endif KYS_RC_EXT_MASK | KYS_GHOST_EN_MASK | KYS_DEG_EN_MASK | KYS_DEG_CNT_MASK); reg_val |= ((config->col - 1) << KYS_COL_NUM_SHIFT); reg_val |= ((config->row - 1) << KYS_ROW_NUM_SHIFT); reg_val |= ((config->idle_duration) << KYS_RC_EXT_SHIFT); reg_val |= (config->ghost_en << KYS_GHOST_EN_SHIFT); reg_val |= (config->deglitch_en << KYS_DEG_EN_SHIFT); reg_val |= (config->deglitch_cnt << KYS_DEG_CNT_SHIFT); #if defined(BL702L) reg_val |= (0x1 << KYS_FIFO_MODE_SHIFT); #endif putreg32(reg_val, reg_base + KYS_KS_CTRL_OFFSET); } /** * @brief keyscan enable * */ void bflb_kys_enable(struct bflb_device_s *dev) { uint32_t reg_base; uint32_t reg_val; reg_base = dev->reg_base; reg_val = getreg32(reg_base + KYS_KS_CTRL_OFFSET); reg_val |= (0x1 << KYS_KS_EN_SHIFT); putreg32(reg_val, reg_base + KYS_KS_CTRL_OFFSET); } /** * @brief keyscan disable * */ void bflb_kys_disable(struct bflb_device_s *dev) { uint32_t reg_base; uint32_t reg_val; reg_base = dev->reg_base; reg_val = getreg32(reg_base + KYS_KS_CTRL_OFFSET); reg_val &= ~(KYS_KS_EN_MASK); putreg32(reg_val, reg_base + KYS_KS_CTRL_OFFSET); } /** * @brief keyscan interrupt enable * * @param dev * @param flag interrupt flag @KEYSCAN_INT_EN define * @param enable enable or disable interrupt */ void bflb_kys_int_enable(struct bflb_device_s *dev, uint32_t flag, bool enable) { uint32_t reg_base; uint32_t reg_val_en; reg_base = dev->reg_base; reg_val_en = getreg32(reg_base + KYS_KS_INT_EN_OFFSET); if (enable) { reg_val_en |= (flag); } else { reg_val_en &= ~(flag); } putreg32(reg_val_en, reg_base + KYS_KS_INT_EN_OFFSET); } /** * @brief keyscan interrupt clear flag * * @param dev * @param flag */ void bflb_kys_int_clear(struct bflb_device_s *dev, uint32_t flag) { putreg32(flag, dev->reg_base + KYS_KEYCODE_CLR_OFFSET); } /** * @brief keyscan get interrupt status * * @param dev * @return uint32_t */ uint32_t bflb_kys_get_int_status(struct bflb_device_s *dev) { uint32_t reg_base; uint32_t reg_sts_val, reg_mask_val; reg_base = dev->reg_base; reg_sts_val = getreg32(reg_base + KYS_KS_INT_STS_OFFSET); reg_mask_val = getreg32(reg_base + KYS_KS_INT_EN_OFFSET); return (reg_sts_val & (reg_mask_val)); } #if defined(BL702L) /** * @brief get keyscan keycode index in fifo * * @param dev * @param fifo_head * @param fifo_tail * @param fifo_valid_cnt * */ void bflb_kys_get_fifo_info(struct bflb_device_s *dev, uint8_t *fifo_head, uint8_t *fifo_tail, uint8_t *fifo_valid_cnt) { uint32_t reg_base; uint32_t reg_val; reg_base = dev->reg_base; reg_val = getreg32(reg_base + KYS_KEYFIFO_IDX_OFFSET); *fifo_head = (uint8_t)(reg_val & 0x7); *fifo_tail = (uint8_t)((reg_val & 0x700) >> 8); *fifo_valid_cnt = (uint8_t)((reg_val & 0xf0000) >> 16); } #endif /** * @brief get keyscan keycode value * * @param dev * @param index * @return uint8_t */ uint8_t bflb_kys_read_keyvalue(struct bflb_device_s *dev, uint8_t index) { #if defined(BL702L) return (uint8_t)(getreg32(dev->reg_base + KYS_KEYFIFO_VALUE_OFFSET) & 0xff); #endif #if defined(BL702) return (uint8_t)((getreg32(dev->reg_base + KYS_KEYFIFO_VALUE_OFFSET) >> (index * 8)) & 0xff); #endif }