From 1e563e2b731d928942f43e1341c8c50b0faf1c01 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Fri, 31 May 2024 11:39:31 +0800
Subject: [PATCH] APPS:IGKBoard-IMX6ULL: Add test-apps source code:
---
drivers/test-apps/pwm_play.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 214 insertions(+), 0 deletions(-)
diff --git a/drivers/test-apps/pwm_play.c b/drivers/test-apps/pwm_play.c
new file mode 100644
index 0000000..63cc028
--- /dev/null
+++ b/drivers/test-apps/pwm_play.c
@@ -0,0 +1,214 @@
+/*********************************************************************************
+ * Copyright: (C) 2021 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
+ * All rights reserved.
+ *
+ * Filename: pwm_music.c
+ * Description: This file used to test PWM music
+ *
+ * Version: 1.0.0(10/21/2022~)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "10/21/2022 17:46:18 PM"
+ *
+ ********************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+
+#define PWM_CHIP 1 /* buzzer on pwmchip1 */
+
+typedef struct pwm_note_s
+{
+ unsigned int msec; //持续时间,毫秒
+ unsigned int freq;//频率
+ unsigned char duty;//相对占空比,百分比 * 100
+}pwm_note_t;
+
+/* 使用宏确定使用中音还是高、低音 */
+#define CX CM
+
+/* 低、中、高音频率*/
+static const unsigned short CL[8] = {0, 262, 294, 330, 349, 392, 440, 494};
+static const unsigned short CM[8] = {0, 523, 587, 659, 698, 784, 880, 988};
+static const unsigned short CH[8] = {0, 1046, 1175, 1318, 1397, 1568, 1760, 1976};
+
+/* 小星星曲子*/
+static unsigned short melody[] = {
+ CX[1], CX[1], CX[5], CX[5], CX[6], CX[6], CX[5], CX[0],
+ CX[4], CX[4], CX[3], CX[3], CX[2], CX[2], CX[1], CX[0],
+ CX[5], CX[5], CX[4], CX[4], CX[3], CX[3], CX[2], CX[0],
+ CX[5], CX[5], CX[4], CX[4], CX[3], CX[3], CX[2], CX[0],
+};
+
+static char pwm_path[64]; /* pwm file path buffer */
+
+static int pwm_export(int chip);
+static int pwm_config(const char *attr, const char *val);
+static int pwm_ring(pwm_note_t *note);
+static inline void msleep(unsigned long ms);
+
+int main(int argc, char *argv[])
+{
+ pwm_note_t note;
+ int i;
+
+ if( pwm_export(PWM_CHIP) < 0 )
+ return 1;
+
+ pwm_config("enable", "1");
+
+ for(i=0; i<sizeof(melody)/sizeof(melody[0]); i++)
+ {
+ if(melody[i] == 0)
+ {
+ note.duty = 0;
+ }
+ else
+ {
+ note.duty = 15; //越大音量越大
+ note.freq = melody[i];
+ }
+ note.msec = 300;
+
+ pwm_ring(¬e);
+ }
+
+ pwm_config("enable", "0");
+
+ return 0;
+}
+
+static int pwm_export(int chip)
+{
+ char file_path[100];
+ int fd, rv=0;
+
+ /* 导出pwm 首先确定最终导出的文件夹路径*/
+ memset(pwm_path, 0, sizeof(pwm_path));
+ snprintf(pwm_path, sizeof(pwm_path), "/sys/class/pwm/pwmchip%d/pwm0", PWM_CHIP);
+
+ //如果pwm0 目录已经存在了, 则直接返回
+ if ( !access(pwm_path, F_OK))
+ return 0;
+
+ //如果pwm0 目录不存在, 则开始导出
+
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path, sizeof(file_path) , "/sys/class/pwm/pwmchip%d/export", PWM_CHIP);
+
+ if ( (fd = open(file_path, O_WRONLY) < 0))
+ {
+ printf("ERROR: open pwmchip%d error\n", PWM_CHIP);
+ return 1;
+ }
+
+ if ( write(fd, "0", 1) < 0 )
+ {
+ printf("write '0' to pwmchip%d/export error\n", PWM_CHIP);
+ rv = 2;
+ }
+
+ close(fd);
+ return rv;
+}
+
+/*pwm 配置函数 attr:属性文件名字
+ * val:属性的值(字符串)
+*/
+static int pwm_config(const char *attr, const char *val)
+{
+ char file_path[100];
+ int fd;
+
+ if( !attr || !val )
+ {
+ printf("[%s] argument error\n", __FUNCTION__);
+ return -1;
+ }
+
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path, sizeof(file_path), "%s/%s", pwm_path, attr);
+ if( (fd=open(file_path, O_WRONLY)) < 0 )
+ {
+ printf("[%s] open %s error\n", __FUNCTION__, file_path);
+ return fd;
+ }
+
+ if ( write(fd, val, strlen(val)) < 0) {
+ printf("[%s] write %s to %s error\n", __FUNCTION__, val, file_path);
+ close(fd);
+ return -2;
+ }
+
+ close(fd); //关闭文件
+ return 0;
+}
+
+/* pwm蜂鸣器响一次声音 */
+static int pwm_ring(pwm_note_t *note)
+{
+ unsigned long period = 0;
+ unsigned long duty_cycle = 0;
+ char period_str[20] = {};
+ char duty_cycle_str[20] = {};
+
+ if( !note || note->duty > 100 )
+ {
+ printf("[INFO] %s argument error.\n", __FUNCTION__);
+ return -1;
+ }
+
+ period = (unsigned long)((1.f / (double)note->freq) * 1e9);//ns单位
+ duty_cycle = (unsigned long)(((double)note->duty / 100.f) * (double)period);//ns单位
+
+ snprintf(period_str, sizeof(period_str), "%lu", period);
+ snprintf(duty_cycle_str, sizeof(duty_cycle_str), "%lu", duty_cycle);
+
+ //设置pwm频率和周期
+ if (pwm_config("period", period_str))
+ {
+ printf("pwm_config period failure.\n");
+ return -1;
+ }
+ if (pwm_config("duty_cycle", duty_cycle_str))
+ {
+ printf("pwm_config duty_cycle failure.\n");
+ return -2;
+ }
+
+ msleep(note->msec);
+
+ /* 设置占空比为0 蜂鸣器无声 */
+ if (pwm_config("duty_cycle", "0"))
+ {
+ printf("pwm_config duty_cycle failure.\n");
+ return -3;
+ }
+ msleep(20);
+
+ return 0;
+}
+
+/* ms级休眠函数 */
+static inline void msleep(unsigned long ms)
+{
+ struct timespec cSleep;
+ unsigned long ulTmp;
+
+ cSleep.tv_sec = ms / 1000;
+ if (cSleep.tv_sec == 0)
+ {
+ ulTmp = ms * 10000;
+ cSleep.tv_nsec = ulTmp * 100;
+ }
+ else
+ {
+ cSleep.tv_nsec = 0;
+ }
+
+ nanosleep(&cSleep, 0);
+}
--
Gitblit v1.9.1