From 75fe79b1843c17911071ed1c208dcf9fed912394 Mon Sep 17 00:00:00 2001 From: jzlv Date: Mon, 26 Jul 2021 10:50:57 +0800 Subject: [PATCH] [feat][qdec] add qdec hal driver and demo --- drivers/bl702_driver/hal_drv/inc/hal_qdec.h | 76 +++++ drivers/bl702_driver/hal_drv/src/hal_qdec.c | 291 ++++++++++++++++++++ examples/qdec/qdec_dc_motor/CMakeLists.txt | 2 + examples/qdec/qdec_dc_motor/main.c | 111 ++++++++ examples/qdec/qdec_dc_motor/readme.md | 22 ++ examples/qdec/qdec_it/CMakeLists.txt | 5 + examples/qdec/qdec_it/main.c | 72 +++++ 7 files changed, 579 insertions(+) create mode 100644 drivers/bl702_driver/hal_drv/inc/hal_qdec.h create mode 100644 drivers/bl702_driver/hal_drv/src/hal_qdec.c create mode 100644 examples/qdec/qdec_dc_motor/CMakeLists.txt create mode 100644 examples/qdec/qdec_dc_motor/main.c create mode 100644 examples/qdec/qdec_dc_motor/readme.md create mode 100644 examples/qdec/qdec_it/CMakeLists.txt create mode 100644 examples/qdec/qdec_it/main.c diff --git a/drivers/bl702_driver/hal_drv/inc/hal_qdec.h b/drivers/bl702_driver/hal_drv/inc/hal_qdec.h new file mode 100644 index 00000000..a101d52f --- /dev/null +++ b/drivers/bl702_driver/hal_drv/inc/hal_qdec.h @@ -0,0 +1,76 @@ +/** + * @file hal_qdec.h + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + */ + +#ifndef __HAL_QDEC__H__ +#define __HAL_QDEC__H__ + +#include "drv_device.h" +#include "bl702_config.h" + +#define DEVICE_CTRL_GET_SAMPLE_VAL (0x10) +#define DEVICE_CTRL_GET_SAMPLE_DIR (0x11) +#define DEVICE_CTRL_GET_ERROR_CNT (0x12) + +enum qdec_index_type { +#ifdef BSP_USING_QDEC0 + QDEC0_INDEX, +#endif +#ifdef BSP_USING_QDEC1 + QDEC1_INDEX, +#endif +#ifdef BSP_USING_QDEC2 + QDEC2_INDEX, +#endif + QDEC_MAX_INDEX, +}; + +enum { + QDEC_REPORT_EVENT, /*!< report interrupt */ + QDEC_SAMPLE_EVENT, /*!< sample interrupt */ + QDEC_ERROR_EVENT, /*!< error interrupt */ + QDEC_OVERFLOW_EVENT, /*!< ACC1 and ACC2 overflow interrupt */ + QDEC_ALL_EVENT, /*!< interrupt max num */ +}; + +typedef struct qdec_device { + struct device parent; + uint8_t id; + + uint8_t acc_mode; + uint8_t sample_mode; + uint8_t sample_period; + uint8_t report_mode; + uint32_t report_period; + uint8_t led_en; + uint8_t led_swap; + uint16_t led_period; + uint8_t deglitch_en; + uint8_t deglitch_strength; + +} qdec_device_t; + +#define QDEC_DEV(dev) ((qdec_device_t *)dev) + +int qdec_register(enum qdec_index_type index, const char *name); + +#endif // __HAL_QDEC_H__ diff --git a/drivers/bl702_driver/hal_drv/src/hal_qdec.c b/drivers/bl702_driver/hal_drv/src/hal_qdec.c new file mode 100644 index 00000000..d959e735 --- /dev/null +++ b/drivers/bl702_driver/hal_drv/src/hal_qdec.c @@ -0,0 +1,291 @@ +/** + * @file hal_qdec.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + */ + +#include "hal_qdec.h" +#include "qdec_reg.h" +#include "bl702_qdec.h" +#include "bl702_gpio.h" +#include "bl702_glb.h" + +static qdec_device_t qdecx_device[QDEC_MAX_INDEX] = { +#ifdef BSP_USING_QDEC0 + QDEC0_CONFIG, +#endif +#ifdef BSP_USING_QDEC1 + QDEC1_CONFIG, +#endif +#ifdef BSP_USING_QDEC2 + QDEC2_CONFIG, +#endif +}; +#ifdef BSP_USING_QDEC0 +static void QDEC0_IRQ(void); +#endif +#ifdef BSP_USING_QDEC1 +static void QDEC1_IRQ(void); +#endif +#ifdef BSP_USING_QDEC2 +static void QDEC2_IRQ(void); +#endif + +int qdec_open(struct device *dev, uint16_t oflag) +{ + qdec_device_t *qdec_device = (qdec_device_t *)dev; + QDEC_CFG_Type qdec_cfg = { 0 }; + + QDEC_DeInit(qdec_device->id); + + qdec_cfg.sampleCfg.sampleMod = qdec_device->sample_mode; + qdec_cfg.sampleCfg.samplePeriod = qdec_device->sample_period; + qdec_cfg.reportCfg.reportMod = qdec_device->report_mode; + qdec_cfg.reportCfg.reportPeriod = qdec_device->report_period; + qdec_cfg.ledCfg.ledEn = qdec_device->led_en; + qdec_cfg.ledCfg.ledSwap = qdec_device->led_swap; + qdec_cfg.ledCfg.ledPeriod = qdec_device->led_period; + qdec_cfg.deglitchCfg.deglitchEn = qdec_device->deglitch_en; + qdec_cfg.deglitchCfg.deglitchStrength = qdec_device->deglitch_strength; + qdec_cfg.accMod = qdec_device->acc_mode; + + QDEC_Init(qdec_device->id, &qdec_cfg); + + if (oflag & DEVICE_OFLAG_INT_RX) { +#ifdef BSP_USING_QDEC0 + if (qdec_device->id == QDEC0_ID) { + Interrupt_Handler_Register(QDEC0_IRQn, QDEC0_IRQ); + } +#endif +#ifdef BSP_USING_QDEC1 + if (qdec_device->id == QDEC1_ID) { + Interrupt_Handler_Register(QDEC1_IRQn, QDEC1_IRQ); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_REPORT, UNMASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_SAMPLE, MASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_ERROR, MASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_OVERFLOW, MASK); + // NVIC_EnableIRQ(QDEC1_IRQn); + } +#endif +#ifdef BSP_USING_QDEC2 + if (qdec_device->id == QDEC2_ID) { + Interrupt_Handler_Register(QDEC2_IRQn, QDEC2_IRQ); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_REPORT, UNMASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_SAMPLE, MASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_ERROR, MASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_OVERFLOW, MASK); + // NVIC_EnableIRQ(QDEC2_IRQn); + } +#endif + } + + return 0; +} + +int qdec_close(struct device *dev) +{ + qdec_device_t *qdec_device = (qdec_device_t *)dev; + + QDEC_Disable(qdec_device->id); + return 0; +} + +int qdec_control(struct device *dev, int cmd, void *args) +{ + qdec_device_t *qdec_device = (qdec_device_t *)dev; + + switch (cmd) { + case DEVICE_CTRL_SET_INT: { + if ((uint32_t)args == QDEC_REPORT_EVENT) { + QDEC_SetIntMask(qdec_device->id, QDEC_INT_REPORT, UNMASK); + } else if ((uint32_t)args == QDEC_SAMPLE_EVENT) { + QDEC_SetIntMask(qdec_device->id, QDEC_INT_SAMPLE, UNMASK); + } else if ((uint32_t)args == QDEC_ERROR_EVENT) { + QDEC_SetIntMask(qdec_device->id, QDEC_INT_ERROR, UNMASK); + } else if ((uint32_t)args == QDEC_OVERFLOW_EVENT) { + QDEC_SetIntMask(qdec_device->id, QDEC_INT_OVERFLOW, UNMASK); + } else { + QDEC_SetIntMask(qdec_device->id, QDEC_INT_REPORT, UNMASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_SAMPLE, UNMASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_ERROR, UNMASK); + QDEC_SetIntMask(qdec_device->id, QDEC_INT_OVERFLOW, UNMASK); + } + if (qdec_device->id == QDEC0_ID) { + NVIC_EnableIRQ(QDEC0_IRQn); + } else if (qdec_device->id == QDEC1_ID) { + NVIC_EnableIRQ(QDEC1_IRQn); + } else if (qdec_device->id == QDEC2_ID) { + NVIC_EnableIRQ(QDEC2_IRQn); + } + break; + } + + case DEVICE_CTRL_CLR_INT: { + if (qdec_device->id == QDEC0_ID) { + NVIC_DisableIRQ(QDEC0_IRQn); + } else if (qdec_device->id == QDEC1_ID) { + NVIC_DisableIRQ(QDEC1_IRQn); + } else if (qdec_device->id == QDEC2_ID) { + NVIC_DisableIRQ(QDEC2_IRQn); + } + break; + } + + case DEVICE_CTRL_GET_INT /* constant-expression */: + /* code */ + break; + + case DEVICE_CTRL_CONFIG /* constant-expression */: + /* code */ + break; + + case DEVICE_CTRL_RESUME /* constant-expression */: { + /* Enable timer */ + QDEC_Enable(qdec_device->id); + break; + } + + case DEVICE_CTRL_SUSPEND /* constant-expression */: { + QDEC_Disable(qdec_device->id); + break; + } + + case DEVICE_CTRL_GET_SAMPLE_VAL: { + return QDEC_Get_Sample_Val(qdec_device->id); + } + + case DEVICE_CTRL_GET_SAMPLE_DIR: { + return QDEC_Get_Sample_Direction(qdec_device->id); + } + + case DEVICE_CTRL_GET_ERROR_CNT: { + return QDEC_Get_Err_Cnt(qdec_device->id); + } + default: + break; + } + + return 0; +} + +int qdec_register(enum qdec_index_type index, const char *name) +{ + struct device *dev; + + if (QDEC_MAX_INDEX == 0) { + return -DEVICE_EINVAL; + } + + dev = &(qdecx_device[index].parent); + + dev->open = qdec_open; + dev->close = qdec_close; + dev->control = qdec_control; + dev->write = NULL; + dev->read = NULL; //qdec_read; + + dev->status = DEVICE_UNREGISTER; + dev->type = DEVICE_CLASS_QDEC; + dev->handle = NULL; + + return device_register(dev, name); +} + +void qdec_isr(qdec_device_t *handle) +{ + uint32_t tmp_sts = 0; + uint32_t tmp_val = 0; + uint32_t tmp_clr = 0; + uint32_t tmp_clr_val = 0; + + if (handle->id == QDEC0_ID) { + tmp_sts = BL_RD_WORD(QDEC0_BASE + QDEC0_INT_STS_OFFSET); + tmp_clr = QDEC0_BASE + QDEC0_INT_CLR_OFFSET; + tmp_clr_val = BL_RD_WORD(tmp_clr); + tmp_val = BL_RD_REG(QDEC0_BASE, QDEC0_INT_EN); + } else if (handle->id == QDEC1_ID) { + tmp_sts = BL_RD_WORD(QDEC0_BASE + QDEC1_INT_STS_OFFSET); + tmp_clr = QDEC0_BASE + QDEC1_INT_CLR_OFFSET; + tmp_clr_val = BL_RD_WORD(tmp_clr); + tmp_val = BL_RD_REG(QDEC1_BASE, QDEC0_INT_EN); + } else if (handle->id == QDEC2_ID) { + tmp_sts = BL_RD_WORD(QDEC0_BASE + QDEC2_INT_STS_OFFSET); + tmp_clr = QDEC0_BASE + QDEC2_INT_CLR_OFFSET; + tmp_clr_val = BL_RD_WORD(tmp_clr); + tmp_val = BL_RD_REG(QDEC2_BASE, QDEC0_INT_EN); + } + + if (!handle->parent.callback) { + return; + } + + /* qdec report intterupt */ + if (!(BL_GET_REG_BITS_VAL(tmp_val, QDEC_RPT_RDY_EN) ? UNMASK : MASK)) { + if (BL_IS_REG_BIT_SET(tmp_sts, QDEC_RPT_RDY_STS)) { + BL_WR_WORD(tmp_clr, BL_SET_REG_BIT(tmp_clr_val, QDEC_RPT_RDY_CLR)); + handle->parent.callback(&handle->parent, NULL, 0, QDEC_REPORT_EVENT); + } + } + + /* qdec sample intterupt */ + if (!(BL_GET_REG_BITS_VAL(tmp_val, QDEC_SPL_RDY_EN) ? UNMASK : MASK)) { + if (BL_IS_REG_BIT_SET(tmp_sts, QDEC_SPL_RDY_STS)) { + BL_WR_WORD(tmp_clr, BL_SET_REG_BIT(tmp_clr_val, QDEC_SPL_RDY_CLR)); + handle->parent.callback(&handle->parent, NULL, 0, QDEC_SAMPLE_EVENT); + } + } + + /* qdec error intterupt */ + if (!(BL_GET_REG_BITS_VAL(tmp_val, QDEC_DBL_RDY_EN) ? UNMASK : MASK)) { + if (BL_IS_REG_BIT_SET(tmp_sts, QDEC_DBL_RDY_STS)) { + BL_WR_WORD(tmp_clr, BL_SET_REG_BIT(tmp_clr_val, QDEC_DBL_RDY_CLR)); + handle->parent.callback(&handle->parent, NULL, 0, QDEC_ERROR_EVENT); + } + } + + /* qdec overflow intterupt */ + if (!(BL_GET_REG_BITS_VAL(tmp_val, QDEC_OVERFLOW_EN) ? UNMASK : MASK)) { + if (BL_IS_REG_BIT_SET(tmp_sts, QDEC_OVERFLOW_STS)) { + BL_WR_WORD(tmp_clr, BL_SET_REG_BIT(tmp_clr_val, QDEC_OVERFLOW_CLR)); + handle->parent.callback(&handle->parent, NULL, 0, QDEC_OVERFLOW_EVENT); + } + } +} + +#ifdef BSP_USING_QDEC0 +static void QDEC0_IRQ(void) +{ + qdec_isr(&qdecx_device[QDEC0_INDEX]); +} +#endif + +#ifdef BSP_USING_QDEC1 +static void QDEC1_IRQ(void) +{ + qdec_isr(&qdecx_device[QDEC1_INDEX]); +} +#endif + +#ifdef BSP_USING_QDEC2 +static void QDEC2_IRQ(void) +{ + qdec_isr(&qdecx_device[QDEC2_INDEX]); +} +#endif diff --git a/examples/qdec/qdec_dc_motor/CMakeLists.txt b/examples/qdec/qdec_dc_motor/CMakeLists.txt new file mode 100644 index 00000000..702c7182 --- /dev/null +++ b/examples/qdec/qdec_dc_motor/CMakeLists.txt @@ -0,0 +1,2 @@ +set(mains main.c) +generate_bin() diff --git a/examples/qdec/qdec_dc_motor/main.c b/examples/qdec/qdec_dc_motor/main.c new file mode 100644 index 00000000..6a369fa1 --- /dev/null +++ b/examples/qdec/qdec_dc_motor/main.c @@ -0,0 +1,111 @@ +/** + * @file main.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + */ + +#include "hal_pwm.h" +#include "hal_qdec.h" +#include "hal_gpio.h" + +uint16_t num = 0; +int qdec_val = 0; + +static void qdec_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state) +{ + if (state == QDEC_REPORT_EVENT) { + num = device_control(dev, DEVICE_CTRL_GET_SAMPLE_VAL, 0); + if (num & (1 << 15)) { + qdec_val = -(32768 - (num & 0x7FFF)); + // MSG("QDEC1 :d=%d,v=-%5d\r\n", device_control(dev, DEVICE_CTRL_GET_SAMPLE_DIR, 0), qdec_val); + } else { + // MSG("QDEC1 :d=%d,v= %5d\r\n", device_control(dev, DEVICE_CTRL_GET_SAMPLE_DIR, 0), num); + qdec_val = num; + } + } +} + +int main(void) +{ + pwm_dutycycle_config_t pwm_cfg[2]; + + pwm_cfg[0].threshold_low = 0; + pwm_cfg[0].threshold_high = 0; + + pwm_cfg[1].threshold_low = 0; + pwm_cfg[1].threshold_high = 0; + + bflb_platform_init(0); + + pwm_register(PWM_CH0_INDEX, "dc_motor_ch0"); + pwm_register(PWM_CH1_INDEX, "dc_motor_ch1"); + + struct device *dc_motor_ch0 = device_find("dc_motor_ch0"); + struct device *dc_motor_ch1 = device_find("dc_motor_ch1"); + + if (dc_motor_ch0) { + PWM_DEV(dc_motor_ch0)->period = 32; //frequence = 32K/1/32 = 1Khz + PWM_DEV(dc_motor_ch0)->threshold_low = 16; + PWM_DEV(dc_motor_ch0)->threshold_high = 32; + device_open(dc_motor_ch0, DEVICE_OFLAG_STREAM_TX); + pwm_channel_start(dc_motor_ch0); + } + if (dc_motor_ch1) { + PWM_DEV(dc_motor_ch1)->period = 32; //frequence = 32K/1/32 = 1Khz + PWM_DEV(dc_motor_ch1)->threshold_low = 16; + PWM_DEV(dc_motor_ch1)->threshold_high = 32; + device_open(dc_motor_ch1, DEVICE_OFLAG_STREAM_TX); + pwm_channel_start(dc_motor_ch1); + } + + qdec_register(QDEC1_INDEX, "qdec_it"); + + struct device *qdec_it = device_find("qdec_it"); + + if (qdec_it) { + device_open(qdec_it, DEVICE_OFLAG_INT_RX); + device_set_callback(qdec_it, qdec_irq_callback); + } else { + MSG("device find fail \r\n"); + } + + device_control(qdec_it, DEVICE_CTRL_SET_INT, (void *)QDEC_REPORT_EVENT); + device_control(qdec_it, DEVICE_CTRL_RESUME, 0); + + while (1) { + if (qdec_val > 0 && qdec_val <= 300) { + pwm_cfg[1].threshold_low = 0; + pwm_cfg[1].threshold_high = 0; + device_control(dc_motor_ch1, DEVICE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[1]); + + pwm_cfg[0].threshold_high = (qdec_val * 0.1); + device_control(dc_motor_ch0, DEVICE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[0]); + } else if (qdec_val < 0 && qdec_val >= -300) { + pwm_cfg[0].threshold_low = 0; + pwm_cfg[0].threshold_high = 0; + device_control(dc_motor_ch0, DEVICE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[0]); + + pwm_cfg[1].threshold_high = -(qdec_val * 0.1); + device_control(dc_motor_ch1, DEVICE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[1]); + } + // MSG("qdec_val:%d\r\n", qdec_val); + bflb_platform_delay_ms(100); + } +} diff --git a/examples/qdec/qdec_dc_motor/readme.md b/examples/qdec/qdec_dc_motor/readme.md new file mode 100644 index 00000000..9333f4f9 --- /dev/null +++ b/examples/qdec/qdec_dc_motor/readme.md @@ -0,0 +1,22 @@ +**board/bl706_iot/pinmux_config.h** 中 **CONFIG_GPIO20_FUNC**、**CONFIG_GPIO21_FUNC** 选择 **GPIO_FUN_PWM** + +**board/bl706_iot/pinmux_config.h** 中 **CONFIG_GPIO3_FUNC**、**CONFIG_GPIO4_FUNC** 选择 **GPIO_FUN_QDEC** + + +**board/bl706_iot/clock_config.h** 中 + +- **BSP_PWM_CLOCK_SOURCE** 选择 **ROOT_CLOCK_SOURCE_32K_CLK**,也可选择其他时钟源,用其他时钟源时应注意 case 中的设置要匹配 +- **BSP_PWM_CLOCK_DIV** 设置成 **1** + +- **BSP_QDEC_KEYSCAN_CLOCK_SOURCE** 选择 **ROOT_CLOCK_SOURCE_XCLK**,也可选择其他时钟源,用其他时钟源时应注意 case 中的设置要匹配 +- **BSP_QDEC_KEYSCAN_CLOCK_DIV** 设置成 **31** + +将两个通道分别接到 H 桥或半桥的两个通道 + +```bash + +$ make APP=qdec_dc_motor BOARD=bl706_iot + +``` + +**正常运行后,可以 QDEC 外设通过读旋转编码器的旋转位置控制 GPIO20 和 GPIO21 引脚分别先后输出 PWM 波,从而电机转速及正反转** diff --git a/examples/qdec/qdec_it/CMakeLists.txt b/examples/qdec/qdec_it/CMakeLists.txt new file mode 100644 index 00000000..bfd0e557 --- /dev/null +++ b/examples/qdec/qdec_it/CMakeLists.txt @@ -0,0 +1,5 @@ +set(mains main.c) +generate_bin() + + + diff --git a/examples/qdec/qdec_it/main.c b/examples/qdec/qdec_it/main.c new file mode 100644 index 00000000..ee8278da --- /dev/null +++ b/examples/qdec/qdec_it/main.c @@ -0,0 +1,72 @@ +/** + * @file main.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + */ + +#include "hal_qdec.h" +#include "hal_gpio.h" + +static volatile uint32_t flag = 0; + +static void qdec_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state) +{ + if (state == QDEC_REPORT_EVENT) { + uint16_t num = 0; + + flag++; + num = device_control(dev, DEVICE_CTRL_GET_SAMPLE_VAL, 0); + if (num & (1 << 15)) { + MSG("QDEC1 :%d,d=%d,v=-%5d\r\n", flag, device_control(dev, DEVICE_CTRL_GET_SAMPLE_DIR, 0), 32768 - (num & 0x7FFF)); + } else { + MSG("QDEC1 :%d,d=%d,v= %5d\r\n", flag, device_control(dev, DEVICE_CTRL_GET_SAMPLE_DIR, 0), num); + } + } +} + +int main(void) +{ + bflb_platform_init(0); + + qdec_register(QDEC1_INDEX, "qdec_it"); + + struct device *qdec_it = device_find("qdec_it"); + + if (qdec_it) { + device_open(qdec_it, DEVICE_OFLAG_INT_RX); + device_set_callback(qdec_it, qdec_irq_callback); + } else { + MSG("device find fail \r\n"); + } + + device_control(qdec_it, DEVICE_CTRL_SET_INT, (void *)QDEC_REPORT_EVENT); + device_control(qdec_it, DEVICE_CTRL_RESUME, 0); + + while (flag < 100) { + bflb_platform_delay_ms(100); + } + device_control(qdec_it, DEVICE_CTRL_CLR_INT, 0); + device_control(qdec_it, DEVICE_CTRL_SUSPEND, 0); + + BL_CASE_SUCCESS; + while (1) { + bflb_platform_delay_ms(100); + } +}