NetBurner 3.5.6
PDF Version
wavPlayer.h
1/*NB_REVISION*/
2
3/*NB_COPYRIGHT*/
4
5#ifndef ___WAV_PLAYER_H
6#define ___WAV_PLAYER_H
7
8#include <nbrtos.h>
9#include <sim.h>
10
11// Comment out this macro to remove filesystem requirement
12#define WAV_PLAYER_FILESYSTEM (1)
13
14// Sim1 Miscellaneous Control Register
15#define MISCCR2_DAC1SEL 0x0040 // Enable DAC1 drive output
16#define MISCCR2_DAC0SEL 0x0020 // Enable DAC0 drive output
17#define MISCCR2_ADCEN 0x0010 // Enable ADC 6-4 and 2-0
18#define MISCCR2_ADC7EN 0x0008 // Enable ADC 7
19#define MISCCR2_ADC3EN 0x0004 // Enable ADC 3
20
21// ADC Calibration Register
22#define ADC_CAL_DAC1 0x0002 // Selects the source of the ADCA7 input as DAC1 output.
23#define ADC_CAL_DAC0 0x0001 // Selects the source of the ADCA3 input as DAC0 output.
24
25// DAC Control Register
26#define DAC_CR_RESET 0x1101
27#define DAC_CR_FILT 0x1000
28#define DAC_CR_WMLVL_M 0x0300
29#define DAC_CR_WMLVL_S 8
30#define DAC_CR_DMA 0x0080
31#define DAC_CR_HSLS 0x0040
32#define DAC_CR_UP 0x0020
33#define DAC_CR_DOWN 0x0010
34#define DAC_CR_AUTO 0x0008
35#define DAC_CR_SYNC 0x0004
36#define DAC_CR_FMT 0x0002
37#define DAC_CR_PDN 0x0001 // Power down. 0 = power on, 1 = power down
38
39// DAC Trigger Select Register DACTSR
40// Channels
41#define DAC1_CH0 0x0000 // Source channel 0
42#define DAC1_CH1 0x0800 // Source channel 1
43#define DAC1_CH2 0x1000 // Source channel 2
44#define DAC1_CH3 0x1800 // Source channel 3
45
46#define DAC0_CH0 0x0000 // Source channel 0
47#define DAC0_CH1 0x0008 // Source channel 1
48#define DAC0_CH2 0x0010 // Source channel 2
49#define DAC0_CH3 0x0018 // Source channel 3
50
51// DAC Trigger Sources
52#define DAC1_SRC_PWMA 0x0000 // PWMs
53#define DAC1_SRC_PWMB 0x0100
54#define DAC1_SRC_PWMX 0x0200
55#define DAC1_SRC_PWMTRIG1 0x0300
56#define DAC1_SRC_PWMTRIG0 0x0400
57#define DAC1_SRC_TnOUT 0x0500 // Timers
58#define DAC1_SRC_TnIN 0x0600
59
60#define DAC0_SRC_PWMA 0x0000 // PWMs
61#define DAC0_SRC_PWMB 0x0001
62#define DAC0_SRC_PWMX 0x0002
63#define DAC0_SRC_PWMTRIG1 0x0003
64#define DAC0_SRC_PWMTRIG0 0x0004
65#define DAC0_SRC_TnOUT 0x0005 // Timers
66#define DAC0_SRC_TnIN 0x0006
67
68#define EDMA_CH_DAC0 62
69#define EDMA_CH_DAC1 63
70#define EDMA_CH_DAC0_INT 0x40000000
71#define EDMA_CH_DAC1_INT 0x80000000
72
73#define TCD_POOL_SIZE 20
74#define DAC_COUNT 2
75#define MAX_SAMPLE_RATE 100000
76
77namespace WAVFILE
78{
79struct Chunk
80{
81 char id[4];
82 uint32_t size;
83};
84struct RIFFChunk
85{
86 char ChunkID[4]; // 'R', 'I', 'F', 'F'
87 uint32_t ChunkSize;
88 char Format[4]; // 'W', 'A', 'V', 'E'
89};
90struct formatChunk
91{
92 char ChunkID[4]; // 'f', 'm', 't', ' '
93 uint32_t SubChunkSize;
94 uint16_t AudioFormat; // 1 = PCM, others are handled
95 uint16_t ChannelCount; // How many channels are recorded in this file?
96 uint32_t SampleRate; // Samples per second
97 uint32_t ByteRate; // Bytes per second = Sample Rate * ChannelCount * BitsPerSample
98 uint16_t BlockAlign; // Bytes per sample set = BitsPerSample * ChannelCount
99 uint16_t BitsPerSample; // Bits of data per sample
100 // Note: this is rounded up to multiples of 8-bits
101 // for BlockAlign and ByteRate
102};
103struct dataChunk
104{
105 char ChunkID[4]; // 'd', 'a', 't', 'a'
106 uint32_t SubChunkSize;
107 uint8_t data[]; // Arbitrary length array definition
108};
109
110// Structure definition for the 'canonical' WAV file
111struct WavFile
112{
113 RIFFChunk riff; // Leading chunk defining the data block as a RIFF chunk
114 formatChunk fmt; // First subchunk, describing the format of the data section
115 dataChunk data; // The actual data section
116};
117} // namespace WAVFILE
118
119class WavPlayer
120{
121 public:
122 // Public enum definitions
123 enum playState
124 {
125 STATE_NO_DAC,
126 STATE_NO_TIMER,
127 STATE_NOT_LOADED,
128 STATE_NOT_PROCESSED,
129 STATE_BUFFER_RESET,
130 STATE_PROCESSED,
131 STATE_READY,
132 STATE_PLAYING,
133 STATE_UNMUTE,
134 STATE_MUTE,
135 STATE_PAUSED_UNMUTE,
136 STATE_PAUSED_MUTE,
137 STATE_PAUSED,
138 STATE_FINISHED
139 };
140
141 enum wavError
142 {
143 ERROR_NONE,
144 ERROR_PLAYING,
145 ERROR_FILE,
146 ERROR_FILE_SIZE,
147 ERROR_TYPE,
148 ERROR_SHORT,
149 ERROR_LONG,
150 ERROR_FORMAT,
151 ERROR_RATE,
152 ERROR_BITSIZE,
153 ERROR_SIZE_MISMATCH,
154 ERROR_CHANNEL,
155 ERROR_DACNUM,
156 ERROR_TIMER,
157 ERROR_IN_USE,
158 ERROR_OTHER
159 };
160
161 private:
162 enum readMode
163 {
164 MODE_FILE,
165 MODE_BUFFER,
166 MODE_NONE
167 };
168
169 struct channelControl
170 {
171 int dacNum;
172 uint32_t dataRem;
173 uint16_t transfersRem;
174 uint16_t finalTransferSize;
175 bool finished;
176 volatile dacstruct *dac;
177 volatile edma_tcdstruct *tcd;
178 };
179
180 struct wavData
181 {
182 uint32_t SampleRate;
183 uint16_t BitsPerSample;
184 uint16_t ChannelCount;
185 uint32_t dataSize;
186 };
187
188 struct initialPlaySettings
189 {
190 uint16_t channel;
191 uint16_t transfersRem;
192 uint16_t transferSize;
193 };
194
195 static WavPlayer *s_players[DAC_COUNT];
196
197 readMode m_mode;
198 playState m_state;
199 wavData m_wavInfo;
200 channelControl m_channel[DAC_COUNT];
201 initialPlaySettings m_initSettings[DAC_COUNT];
202 uint32_t m_timer;
203 int m_playsRem[DAC_COUNT];
204 timerstruct timerSettings;
205 WAVFILE::WavFile *m_pWav;
206 WAVFILE::RIFFChunk *m_pWav_riff; // Leading chunk defining the data block as a RIFF chunk
207 WAVFILE::formatChunk *m_pWav_fmt; // First subchunk, describing the format of the data section
208 WAVFILE::dataChunk *m_pWav_data; // The actual data section
209 OS_SEM *m_finishedSem;
210
211 // Prepare the data for sending to DAC
212 wavError PrepareData();
213
214 const uint8_t *FindChunk(const char *chunkID, const uint8_t *data, uint32_t dataLen);
215 wavError ParseHeader();
216 // Helper functions for swapping endianess of header segments
217 void PrepChunk_RIFF();
218 void PrepChunk_fmt();
219 void PrepChunk_data();
220
221 void SetLengths();
222 void ConfigDAC();
223 void ConfigDMA();
224 void ConfigTimer();
225 void ISR(int channelNum);
226 void SoftMuteISR();
227
228 public:
229 WavPlayer();
230 ~WavPlayer();
231
232 static void RunISR();
233 static void RunSoftMuteISR(uint32_t vector);
234
235#ifdef WAV_PLAYER_FILESYSTEM
236 /* OpenFile
237 * Opens and readies a WAV file from disk
238 *
239 * Args:
240 * - fileName: pointer to C string containing the name of the file to be opened
241 * - dataBuffer: pointer to a buffer to load the file into
242 * - bufferSize: the size of the buffer being used
243 *
244 * Returns:
245 * - ERROR_NONE: File loaded successfully
246 * - Other: Failure while loading file, value indicates type
247 */
248 wavError OpenFile(const char *fileName, uint8_t *dataBuffer, uint32_t bufferSize);
249#endif /* #ifdef WAV_PLAYER_FILESYSTEM */
250 /* OpenBuffer
251 * Readies a WAV file stored in a buffer.
252 * WARNING: This function mutates the passed buffer if successful. Until
253 * either a new WAV file is loaded, ResetBuffer() is called, or the
254 * WavPlayer is destroyed, the buffer should not be read or modified.
255 *
256 * Args:
257 * - data: pointer to a buffer containing a WAV file
258 *
259 * Returns:
260 * - ERROR_NONE: File loaded successfully
261 * - Other: Failure while loading file, value indicates type
262 */
263 wavError OpenBuffer(uint8_t *data);
264
265 /* SetChannelDAC
266 * Sets the association between an audio channel and the DAC that is used
267 * to play it. Note: Only 2 channel WAVs are supported.
268 *
269 * Args:
270 * - channel: WAV sample channel to read from
271 * - dacNum: DAC channel to output to
272 *
273 * Returns:
274 * - ERROR_NONE: Channel Associated
275 * - Other: Failure, value indicates type
276 */
277 wavError SetChannelDAC(int channel = 0, int dacNum = 0);
278 /* SetTimer
279 * Selects which DMA Timer is used as the trigger source for the DAC(s)
280 *
281 * Args:
282 * - timerNum: the dma timer to use
283 *
284 * Returns:
285 * - ERROR_NONE: Channel Associated
286 * - Other: Failure, value indicates type
287 */
288 wavError SetTimer(int timerNum = 3);
289
290 /* Play
291 * Plays the previously loaded WAV file
292 *
293 * Args:
294 * - wavFinishedSem: Optional semaphore posted to upon completion
295 *
296 * Returns:
297 * NONE
298 */
299 wavError Play(OS_SEM *wavFinishedSem = NULL);
300
301 /* Loop
302 * Repeatedly plays the open file.
303 *
304 * Args:
305 * - playCount: the number of times to play the file, 0 = loop forever
306 *
307 * Returns:
308 *
309 */
310 wavError Loop(uint32_t playCount = 0, OS_SEM *wavFinishedSem = NULL);
311
312 /* Stop
313 * Immediately stops playback
314 *
315 */
316 wavError Stop();
317
318 /* StopGraceful
319 * Stops playback once current loop iteration is finished.
320 */
321 wavError StopGraceful();
322
323 wavError Pause();
324
325 wavError Resume();
326
327 /* ResetBuffer
328 * Reset the data buffer back to its unmutated state. Only needed when the
329 * WAV file was loaded using OpenBuffer and the buffer is not reverted from
330 * other sources.
331 *
332 * Args:
333 * NONE
334 *
335 * Returns:
336 * NONE
337 */
338 wavError ResetBuffer();
339
340 /* GetState
341 * Gets the current state of the WavPlayer.
342 *
343 * Args:
344 * NONE
345 *
346 * Returns:
347 * NONE
348 */
349 playState GetState();
350};
351
352#endif /* ----- #ifndef ___WAV_PLAYER_H ----- */
NetBurner Real-Time Operating System (NBRTOS) API.
Semaphores are used to control access to shared resources or or to communicate between tasks in a mul...
Definition nbrtos.h:411