NetBurner 3.1
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 
69 #define EDMA_CH_DAC0 62
70 #define EDMA_CH_DAC1 63
71 #define EDMA_CH_DAC0_INT 0x40000000
72 #define EDMA_CH_DAC1_INT 0x80000000
73 
74 #define TCD_POOL_SIZE 20
75 #define DAC_COUNT 2
76 #define MAX_SAMPLE_RATE 100000
77 
78 
79 namespace WAVFILE {
80  struct Chunk {
81  char id[4];
82  uint32_t size;
83  };
84  struct RIFFChunk {
85  char ChunkID[4]; // 'R', 'I', 'F', 'F'
86  uint32_t ChunkSize;
87  char Format[4]; // 'W', 'A', 'V', 'E'
88  };
89  struct formatChunk {
90  char ChunkID[4]; // 'f', 'm', 't', ' '
91  uint32_t SubChunkSize;
92  uint16_t AudioFormat; // 1 = PCM, others are handled
93  uint16_t ChannelCount; // How many channels are recorded in this file?
94  uint32_t SampleRate; // Samples per second
95  uint32_t ByteRate; // Bytes per second = Sample Rate * ChannelCount * BitsPerSample
96  uint16_t BlockAlign; // Bytes per sample set = BitsPerSample * ChannelCount
97  uint16_t BitsPerSample; // Bits of data per sample
98  // Note: this is rounded up to multiples of 8-bits
99  // for BlockAlign and ByteRate
100  };
101  struct dataChunk {
102  char ChunkID[4]; // 'd', 'a', 't', 'a'
103  uint32_t SubChunkSize;
104  uint8_t data[]; // Arbitrary length array definition
105  };
106 
107  // Structure definition for the 'canonical' WAV file
108  struct WavFile {
109  RIFFChunk riff; // Leading chunk defining the data block as a RIFF chunk
110  formatChunk fmt; // First subchunk, describing the format of the data section
111  dataChunk data; // The actual data section
112  };
113 }
114 
115 
116 class WavPlayer {
117 public:
118 // Public enum definitions
119  enum playState {
120  STATE_NO_DAC,
121  STATE_NO_TIMER,
122  STATE_NOT_LOADED,
123  STATE_NOT_PROCESSED,
124  STATE_BUFFER_RESET,
125  STATE_PROCESSED,
126  STATE_READY,
127  STATE_PLAYING,
128  STATE_PAUSED,
129  STATE_FINISHED,
130  };
131 
132  enum wavError {
133  ERROR_NONE,
134  ERROR_PLAYING,
135  ERROR_FILE,
136  ERROR_FILE_SIZE,
137  ERROR_TYPE,
138  ERROR_SHORT,
139  ERROR_LONG,
140  ERROR_FORMAT,
141  ERROR_RATE,
142  ERROR_BITSIZE,
143  ERROR_SIZE_MISMATCH,
144  ERROR_CHANNEL,
145  ERROR_DACNUM,
146  ERROR_TIMER,
147  ERROR_IN_USE,
148  ERROR_OTHER
149  };
150 
151 private:
152  enum readMode {
153  MODE_FILE,
154  MODE_BUFFER,
155  MODE_NONE
156  };
157 
158  struct channelControl {
159  int dacNum;
160  uint32_t dataRem;
161  uint16_t transfersRem;
162  uint16_t finalTransferSize;
163  bool finished;
164  volatile dacstruct *dac;
165  volatile edma_tcdstruct *tcd;
166  };
167 
168  struct wavData {
169  uint32_t SampleRate;
170  uint16_t BitsPerSample;
171  uint16_t ChannelCount;
172  uint32_t dataSize;
173  };
174 
175  struct initialPlaySettings {
176  uint16_t channel;
177  uint16_t transfersRem;
178  uint16_t transferSize;
179  };
180 
181  static WavPlayer *s_players[DAC_COUNT];
182 
183  readMode m_mode;
184  playState m_state;
185  wavData m_wavInfo;
186  channelControl m_channel[DAC_COUNT];
187  initialPlaySettings m_initSettings[DAC_COUNT];
188  uint32_t m_timer;
189  int m_playsRem[DAC_COUNT];
190  timerstruct timerSettings;
191  WAVFILE::WavFile *m_pWav;
192  WAVFILE::RIFFChunk *m_pWav_riff; // Leading chunk defining the data block as a RIFF chunk
193  WAVFILE::formatChunk *m_pWav_fmt; // First subchunk, describing the format of the data section
194  WAVFILE::dataChunk *m_pWav_data; // The actual data section
195  OS_SEM *m_finishedSem;
196 
197  // Prepare the data for sending to DAC
198  wavError PrepareData();
199 
200  const uint8_t *FindChunk(const char *chunkID, const uint8_t *data, uint32_t dataLen);
201  wavError ParseHeader();
202  // Helper functions for swapping endianess of header segments
203  void PrepChunk_RIFF();
204  void PrepChunk_fmt();
205  void PrepChunk_data();
206 
207  void SetLengths();
208  void ConfigDAC();
209  void ConfigDMA();
210  void ConfigTimer();
211  void ISR( int channelNum );
212 
213 public:
214  WavPlayer();
215  ~WavPlayer();
216 
217  static void RunISR( );
218 
219 #ifdef WAV_PLAYER_FILESYSTEM
220  /* OpenFile
221  * Opens and readies a WAV file from disk
222  *
223  * Args:
224  * - fileName: pointer to C string containing the name of the file to be opened
225  * - dataBuffer: pointer to a buffer to load the file into
226  * - bufferSize: the size of the buffer being used
227  *
228  * Returns:
229  * - ERROR_NONE: File loaded successfully
230  * - Other: Failure while loading file, value indicates type
231  */
232  wavError OpenFile( const char * fileName, uint8_t * dataBuffer, uint32_t bufferSize );
233 #endif /* #ifdef WAV_PLAYER_FILESYSTEM */
234  /* OpenBuffer
235  * Readies a WAV file stored in a buffer.
236  * WARNING: This function mutates the passed buffer if successful. Until
237  * either a new WAV file is loaded, ResetBuffer() is called, or the
238  * WavPlayer is destroyed, the buffer should not be read or modified.
239  *
240  * Args:
241  * - data: pointer to a buffer containing a WAV file
242  *
243  * Returns:
244  * - ERROR_NONE: File loaded successfully
245  * - Other: Failure while loading file, value indicates type
246  */
247  wavError OpenBuffer( uint8_t * data );
248 
249  /* SetChannelDAC
250  * Sets the association between an audio channel and the DAC that is used
251  * to play it. Note: Only 2 channel WAVs are supported.
252  *
253  * Args:
254  * - channel: WAV sample channel to read from
255  * - dacNum: DAC channel to output to
256  *
257  * Returns:
258  * - ERROR_NONE: Channel Associated
259  * - Other: Failure, value indicates type
260  */
261  wavError SetChannelDAC( int channel = 0, int dacNum = 0);
262  /* SetTimer
263  * Selects which DMA Timer is used as the trigger source for the DAC(s)
264  *
265  * Args:
266  * - timerNum: the dma timer to use
267  *
268  * Returns:
269  * - ERROR_NONE: Channel Associated
270  * - Other: Failure, value indicates type
271  */
272  wavError SetTimer( int timerNum = 3 );
273 
274  /* Play
275  * Plays the previously loaded WAV file
276  *
277  * Args:
278  * - wavFinishedSem: Optional semaphore posted to upon completion
279  *
280  * Returns:
281  * NONE
282  */
283  wavError Play( OS_SEM *wavFinishedSem = NULL);
284 
285  /* Loop
286  * Repeatedly plays the open file.
287  *
288  * Args:
289  * - playCount: the number of times to play the file, 0 = loop forever
290  *
291  * Returns:
292  *
293  */
294  wavError Loop( uint32_t playCount = 0, OS_SEM *wavFinishedSem = NULL );
295 
296  /* Stop
297  * Immediately stops playback
298  *
299  */
300  wavError Stop();
301 
302  /* StopGraceful
303  * Stops playback once current loop iteration is finished.
304  */
305  wavError StopGraceful();
306 
307  wavError Pause();
308 
309  wavError Resume();
310 
311  /* ResetBuffer
312  * Reset the data buffer back to its unmutated state. Only needed when the
313  * WAV file was loaded using OpenBuffer and the buffer is not reverted from
314  * other sources.
315  *
316  * Args:
317  * NONE
318  *
319  * Returns:
320  * NONE
321  */
322  wavError ResetBuffer();
323 
324  /* GetState
325  * Gets the current state of the WavPlayer.
326  *
327  * Args:
328  * NONE
329  *
330  * Returns:
331  * NONE
332  */
333  playState GetState();
334 };
335 
336 #endif /* ----- #ifndef ___WAV_PLAYER_H ----- */
337 
NetBurner Real-Time Operating System API.
Semaphores are used to control access to shared resource critical section, or to communicate between ...
Definition: nbrtos.h:318
Definition: wavPlayer.h:79
#define NULL
Definition: nm_bsp.h:76