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);