Files
luban-lite-t3e-pro/packages/third-party/beep/beep.c

296 lines
9.1 KiB
C
Raw Normal View History

2023-08-30 16:21:18 +08:00
/*
* Copyright (c) 2006-2020, Sunwancn(bwsheng2000@163.com)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-02-14 Sunwancn the first version
*/
#include <rtdevice.h>
#include <rtthread.h>
#include <beep.h>
#ifdef LPKG_USING_BEEP
#if !defined(LPKG_BEEP_THREAD_STACK_USING_HEAP)
ALIGN(RT_ALIGN_SIZE)
static char beep_thread_stack[LPKG_BEEP_THREAD_STACK_SIZE];
static struct rt_thread beep_thread_struct = {0};
#endif /* !defined(LPKG_BEEP_THREAD_STACK_USING_HEAP) */
static struct beep_struct beep_data = {0};
static rt_thread_t beep_thread = RT_NULL;
#ifdef LPKG_BEEP_PASSIVE_BUZZER
static void beep_set(void);
#endif
static void beep_on(void);
static void beep_off(void);
static void beep_thread_entry(void *parameter);
#if defined(LPKG_BEEP_PASSIVE_BUZZER) && defined(LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE)
int pm_run_freq_change(const struct rt_device *device, rt_uint8_t mode)
{
if (&beep_data.pwm_dev->parent == device)
{
beep_set();
}
return RT_EOK;
}
static struct rt_device_pm_ops beep_pm_ops =
{
RT_NULL,
RT_NULL,
pm_run_freq_change
};
#endif /* defined(LPKG_BEEP_PASSIVE_BUZZER) && defined(LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE) */
/***************************************************************************************************
* @fn beep_init
*
* @brief
*
* @param pin - drv_gpio.c使GET_PIN()
* reset_level - PIN_LOW或PIN_HIGH
*
***************************************************************************************************/
void beep_init(rt_base_t pin, rt_base_t reset_level)
{
#ifdef LPKG_BEEP_PASSIVE_BUZZER
(void)pin;
(void)reset_level;
beep_data.pwm_dev = (struct rt_device_pwm *)rt_device_find(LPKG_BEEP_PWM_DEV_NAME);
RT_ASSERT(beep_data.pwm_dev);
beep_data.freq = LPKG_BEEP_DEFAULT_FREQ;
#ifdef LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE
rt_pm_device_register(&beep_data.pwm_dev->parent, &beep_pm_ops);
#endif /* LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE */
beep_set();
#else /* LPKG_BEEP_ACTIVE_BUZZER */
rt_pin_write(pin, reset_level);
rt_pin_mode(pin, PIN_MODE_OUTPUT);
beep_data.pin = pin;
beep_data.pin_reset_level = reset_level;
#endif /* LPKG_BEEP_PASSIVE_BUZZER */
beep_data.inited = RT_TRUE;
}
int passive_beep_init(void)
{
beep_init(0, 0);
return 0;
}
INIT_COMPONENT_EXPORT(passive_beep_init);
/***************************************************************************************************
* @fn beep_deinit
*
* @brief
*
***************************************************************************************************/
void beep_deinit(void)
{
#ifdef LPKG_BEEP_PASSIVE_BUZZER
#ifdef LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE
rt_pm_device_unregister(&beep_data.pwm_dev->parent);
#endif /* LPKG_BEEP_SUPPORT_PM_RUN_FREQ_CHANGE */
beep_data.pwm_dev = RT_NULL;
#endif /* LPKG_BEEP_PASSIVE_BUZZER */
beep_data.inited = RT_FALSE;
}
#ifdef LPKG_BEEP_PASSIVE_BUZZER
void beep_set(void)
{
RT_ASSERT(beep_data.pwm_dev);
// 频率(Hz)转换为相应的周期(ns)
rt_uint32_t period = 1000000000ULL / beep_data.freq;
// PWM设置恒为50%占空比方波
rt_pwm_set(beep_data.pwm_dev, LPKG_BEEP_PWM_DEV_CHANNEL, period, period >> 1);
}
#endif /* LPKG_BEEP_PASSIVE_BUZZER */
/***************************************************************************************************
* @fn beep
*
* @brief 使使
*
* @param nums -
* period - [10-100000]
* percent - [1-100]
* freq - 0[0, 500-10000]
*
* @return None
***************************************************************************************************/
void beep(rt_uint32_t nums, rt_uint32_t period, rt_uint32_t percent, rt_uint32_t freq)
{
#ifdef LPKG_BEEP_PASSIVE_BUZZER
RT_ASSERT(beep_data.pwm_dev);
RT_ASSERT(freq == 0 || (freq >= LPKG_BEEP_FREQ_MIN && freq <= LPKG_BEEP_FREQ_MAX));
#endif
RT_ASSERT(period >= LPKG_BEEP_PERIOD_MIN && period <= LPKG_BEEP_PERIOD_MAX);
RT_ASSERT(percent > 0 && percent <= 100);
if (nums)
{
beep_data.nums = nums;
beep_data.pulse = period * percent / 100;
beep_data.npulse = period - beep_data.pulse;
#ifdef LPKG_BEEP_PASSIVE_BUZZER
if (freq && beep_data.freq != freq)
{
beep_data.freq = freq;
beep_set();
}
#endif /* LPKG_BEEP_PASSIVE_BUZZER */
if (beep_thread == RT_NULL || beep_thread->stat == RT_THREAD_CLOSE)
{
#ifdef LPKG_BEEP_THREAD_STACK_USING_HEAP
beep_thread = rt_thread_create("beep", beep_thread_entry, RT_NULL,
LPKG_BEEP_THREAD_STACK_SIZE, LPKG_BEEP_THREAD_PRIORITY, LPKG_BEEP_THREAD_TIMESLICE);
if (beep_thread != RT_NULL)
rt_thread_startup(beep_thread);
#else
beep_thread = &beep_thread_struct;
rt_thread_init(beep_thread, "beep", beep_thread_entry, RT_NULL,
&beep_thread_stack, sizeof(beep_thread_stack), LPKG_BEEP_THREAD_PRIORITY, LPKG_BEEP_THREAD_TIMESLICE);
rt_thread_startup(beep_thread);
#endif /* LPKG_BEEP_THREAD_STACK_USING_HEAP */
}
}
}
/***************************************************************************************************
* @fn beep_stop
*
* @brief
*
***************************************************************************************************/
void beep_stop(void)
{
beep_off();
if (beep_thread != RT_NULL)
#ifdef LPKG_BEEP_THREAD_STACK_USING_HEAP
rt_thread_delete(beep_thread);
#else
rt_thread_detach(beep_thread);
#endif /* LPKG_BEEP_THREAD_STACK_USING_HEAP */
beep_thread = RT_NULL;
}
void beep_on(void)
{
#ifdef LPKG_BEEP_PASSIVE_BUZZER
RT_ASSERT(beep_data.pwm_dev);
rt_pwm_enable(beep_data.pwm_dev, LPKG_BEEP_PWM_DEV_CHANNEL);
#else
rt_pin_write(beep_data.pin, (beep_data.pin_reset_level == PIN_HIGH) ? PIN_LOW : PIN_HIGH);
#endif
}
void beep_off(void)
{
#ifdef LPKG_BEEP_PASSIVE_BUZZER
RT_ASSERT(beep_data.pwm_dev);
rt_pwm_disable(beep_data.pwm_dev, LPKG_BEEP_PWM_DEV_CHANNEL);
#else
rt_pin_write(beep_data.pin, beep_data.pin_reset_level);
#endif
}
void beep_thread_entry(void *parameter)
{
while ((beep_data.nums --) && beep_data.pulse)
{
#if defined(RT_USING_PM) && defined(LPKG_BEEP_PASSIVE_BUZZER) && defined(LPKG_BEEP_BLOCK_POWER_STOP)
rt_pm_request(LPKG_BEEP_REQUEST_PM_MODE);
#endif
beep_on();
rt_thread_mdelay(beep_data.pulse);
#if defined(RT_USING_PM) && defined(LPKG_BEEP_PASSIVE_BUZZER) && defined(LPKG_BEEP_BLOCK_POWER_STOP)
rt_pm_release(LPKG_BEEP_REQUEST_PM_MODE);
#endif
beep_off();
if (beep_data.npulse)
{
rt_thread_mdelay(beep_data.npulse);
}
}
beep_thread = RT_NULL;
}
#if defined(RT_USING_FINSH) && defined(LPKG_BEEP_USING_MSH_CMD)
#include <stdlib.h>
static void __beep(rt_uint8_t argc, char **argv)
{
int nums, period, prcent, freq;
if (!beep_data.inited)
{
rt_kprintf("Not initialized! Must be initialize first.\n");
}
else if (argc <= 2)
{
rt_kprintf("Please input: beep <nums> <period> [prcent] [freq]\n");
}
else if (argc == 3)
{
nums = atoi(argv[1]);
period = atoi(argv[2]);
if (nums > 0 && period >= LPKG_BEEP_PERIOD_MIN && period <= LPKG_BEEP_PERIOD_MAX)
beep(nums, period, 50, 0);
else
rt_kprintf("Out of range! Must be at: nums[1-any] period[%d-%d]\n", LPKG_BEEP_PERIOD_MIN, LPKG_BEEP_PERIOD_MAX);
}
else if (argc == 4)
{
nums = atoi(argv[1]);
period = atoi(argv[2]);
prcent = atoi(argv[3]);
if (nums > 0 && period >= LPKG_BEEP_PERIOD_MIN && period <= LPKG_BEEP_PERIOD_MAX
&& prcent > 0 && prcent <= 100)
beep(nums, period, prcent, 0);
else
rt_kprintf("Out of range! Must be at: nums[1-any] period[%d-%d] prcent[1-100]\n", LPKG_BEEP_PERIOD_MIN, LPKG_BEEP_PERIOD_MAX);
}
else
{
nums = atoi(argv[1]);
period = atoi(argv[2]);
prcent = atoi(argv[3]);
freq = atoi(argv[4]);
if (nums > 0 && period >= LPKG_BEEP_PERIOD_MIN && period <= LPKG_BEEP_PERIOD_MAX
&& prcent > 0 && prcent <= 100 && (freq == 0 || (freq >= LPKG_BEEP_FREQ_MIN && freq <= LPKG_BEEP_FREQ_MAX)))
beep(nums, period, prcent, freq);
else
rt_kprintf("Out of range! Must be at: nums[1-any] period[%d-%d] prcent[1-100] freq[0,%d-%d]\n", \
LPKG_BEEP_PERIOD_MIN, LPKG_BEEP_PERIOD_MAX, LPKG_BEEP_FREQ_MIN, LPKG_BEEP_FREQ_MAX);
}
}
MSH_CMD_EXPORT_ALIAS(__beep, beep, Buzzer beep any);
#endif /* defined(RT_USING_FINSH) && defined(LPKG_BEEP_USING_MSH_CMD) */
#endif /* LPKG_USING_BEEP */