1 /*
2 * Copyright (c) 2006-2025 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2025-05-02 wumingzi First version
9 */
10
11 #include "tc_audio_common.h"
12
13 #define THREAD_PRIORITY 9
14 #define THREAD_TIMESLICE 5
15 #define thread_simulate_intr_create_stacksize 1024
16 static rt_thread_t thread_simulate_intr_handle;
17 static struct sound_device snd_dev;
18
thread_simulate_intr(void * parameter)19 static void thread_simulate_intr(void *parameter)
20 {
21 rt_flag_t exec_once = 0;
22 while(1)
23 {
24 if(audio_fsm_step == 1 && exec_once == 0)
25 {
26 /* Move the data(0xAA) from kernel to DMA buffer */
27 rt_audio_tx_complete(&snd_dev.audio);
28 audio_fsm_step = 2;
29 exec_once = 1;
30 rt_thread_mdelay(10);
31 }
32 else if(audio_fsm_step == 2 && exec_once == 1)
33 {
34 /* Move the data(0x55) from kernel to DMA buffer */
35 rt_audio_tx_complete(&snd_dev.audio);
36 audio_fsm_step = 3;
37 rt_thread_mdelay(10);
38 }
39 else if(audio_fsm_step == 4)
40 {
41 /* rt_device_close will call rt_completion_wait(FOREVER), so we need delay to
42 * let system run the point */
43 rt_thread_mdelay(10);
44 rt_audio_tx_complete(&snd_dev.audio);
45 break;
46 }
47 rt_thread_mdelay(10);
48 }
49 while (1)
50 {
51 rt_thread_mdelay(10);
52 }
53 }
54
thread_simulate_intr_create(void)55 static void thread_simulate_intr_create(void)
56 {
57 thread_simulate_intr_handle = rt_thread_create(
58 "thread_simulate_intr",
59 thread_simulate_intr,
60 RT_NULL,
61 thread_simulate_intr_create_stacksize,
62 THREAD_PRIORITY - 1, THREAD_TIMESLICE);
63
64 rt_thread_startup(thread_simulate_intr_handle);
65 }
66
player_device_init(struct rt_audio_device * audio)67 static rt_err_t player_device_init(struct rt_audio_device *audio)
68 {
69 return RT_EOK;
70 }
71
72 /* Simulate DMA interrupt */
player_device_start(struct rt_audio_device * audio,int stream)73 static rt_err_t player_device_start(struct rt_audio_device *audio, int stream)
74 {
75 thread_simulate_intr_create();
76 return RT_EOK;
77 }
78
player_device_stop(struct rt_audio_device * audio,int stream)79 static rt_err_t player_device_stop(struct rt_audio_device *audio, int stream)
80 {
81 rt_thread_delete(thread_simulate_intr_handle);
82 return RT_EOK;
83 }
84
player_device_getcaps(struct rt_audio_device * audio,struct rt_audio_caps * caps)85 static rt_err_t player_device_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
86 {
87 return RT_EOK;
88 }
89
player_device_configure(struct rt_audio_device * audio,struct rt_audio_caps * caps)90 static rt_err_t player_device_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
91 {
92 return RT_EOK;
93 }
94
player_device_transmit(struct rt_audio_device * audio,const void * writeBuf,void * readBuf,rt_size_t size)95 static rt_ssize_t player_device_transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)
96 {
97 return size;
98 }
99
player_device_buffer_info(struct rt_audio_device * audio,struct rt_audio_buf_info * info)100 static void player_device_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
101 {
102 RT_ASSERT(audio != RT_NULL);
103 /**
104 * TX_FIFO
105 * +----------------+----------------+
106 * | block1 | block2 |
107 * +----------------+----------------+
108 * \ block_size /
109 */
110 info->buffer = snd_dev.tx_fifo;
111 info->total_size = TX_DMA_FIFO_SIZE;
112 info->block_size = TX_DMA_BLOCK_SIZE;
113 info->block_count = RT_AUDIO_REPLAY_MP_BLOCK_COUNT;
114 }
115
116 static struct rt_audio_ops audio_ops =
117 {
118 .getcaps = player_device_getcaps,
119 .configure = player_device_configure,
120 .init = player_device_init,
121 .start = player_device_start,
122 .stop = player_device_stop,
123 .transmit = player_device_transmit,
124 .buffer_info = player_device_buffer_info,
125 };
126
rt_hw_sound_init(void)127 static int rt_hw_sound_init(void)
128 {
129 rt_uint8_t *tx_fifo = RT_NULL;
130
131 tx_fifo = rt_malloc(TX_DMA_FIFO_SIZE);
132 if (tx_fifo == NULL)
133 {
134 return -RT_ENOMEM;
135 }
136 snd_dev.tx_fifo = tx_fifo;
137
138 /* Init default configuration */
139 {
140 snd_dev.config.samplerate = PLAYER_SAMPLERATE;
141 snd_dev.config.channels = PLAYER_CHANNEL;
142 snd_dev.config.samplebits = PLAYER_SAMPLEBITS;
143 snd_dev.volume = PLAYER_VOLUME;
144 }
145
146 snd_dev.audio.ops = &audio_ops;
147 rt_audio_register(&snd_dev.audio, SOUND_PLAYER_DEVICE_NAME, RT_DEVICE_FLAG_WRONLY, &snd_dev);
148 return RT_EOK;
149 }
150 INIT_DEVICE_EXPORT(rt_hw_sound_init);