STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
AudioPlayer.c
Go to the documentation of this file.
1 /*
2  * AudioPlayer.c
3  *
4  * Created on: May 28, 2016
5  * Author: Torsten
6  */
7 
55 /* Includes ------------------------------------------------------------------*/
56 #include "AudioPlayer.h"
57 
59 
60 /* Private define ------------------------------------------------------------*/
61 
62 /* Private macro -------------------------------------------------------------*/
63 /* Private typedef -----------------------------------------------------------*/
64 /* Private variables ---------------------------------------------------------*/
65 static AUDIO_OUT_BufferTypeDef BufferCtl;
66 static unsigned long sAudioHeartbeat = 0;
67 
68 /* Private function prototypes -----------------------------------------------*/
69 
70 /* Private functions ---------------------------------------------------------*/
71 
73 {
74 #if 0
75  if (BufferCtl.clockState)
76  {
77  BufferCtl.clockState = 0;
78  return 1;
79  }
80  else
81  return 0;
82 #else
83  //we will block here for max. 200 msec if we do not have an audio clock, so the GUI remains a bit responsive
85  {
86  BufferCtl.clockState = 0;
87  return 1;
88  }
89  else
90  {
91  taskYIELD();
92  return 0;
93  }
94 #endif
95 }
96 
98 {
99  static BaseType_t xHigherPriorityTaskWoken;
100 
101  //called from ISR - INT should be disabled !
102  BufferCtl.clockState = trig;
103 
104  xHigherPriorityTaskWoken = pdFALSE;
105  xSemaphoreGiveFromISR(xSemaphoreAudio, &xHigherPriorityTaskWoken);
106  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
107 }
108 
110 {
111  if (BufferCtl.state == BUFFER_OFFSET_HALF)
112  return 0;
113  else
114  return 1;
115 }
116 
117 int AUDIO_PLAYER_GetBuffer(uint8_t **out_BufAddr)
118 {
119  *out_BufAddr = BufferCtl.buff;
120  return sizeof(BufferCtl.buff);
121 }
122 
128 AUDIO_ErrorTypeDef AUDIO_PLAYER_Init(int outSelection, int sampleFreq)
129 {
130  if (outSelection)
131  {
132  if(BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, 100, sampleFreq) == 0)
133  {
135  return AUDIO_ERROR_NONE;
136  }
137  else
138  {
139  return AUDIO_ERROR_IO;
140  }
141  }
142  else
143  {
144  if(BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_SPEAKER, 100, sampleFreq) == 0)
145  {
147  return AUDIO_ERROR_NONE;
148  }
149  else
150  {
151  return AUDIO_ERROR_IO;
152  }
153  }
154 }
155 
162 {
163  BSP_AUDIO_OUT_Play((uint16_t*)&BufferCtl.buff[0], AUDIO_OUT_BUFFER_SIZE);
164  BufferCtl.clockState = 0;
165  return AUDIO_ERROR_NONE;
166 }
167 
169 {
170  BSP_AUDIO_OUT_Restart((uint16_t*)&BufferCtl.buff[0], AUDIO_OUT_BUFFER_SIZE);
171  BufferCtl.clockState = 0;
172  BufferCtl.state = 0;
173 }
174 
181 {
182  return AUDIO_ERROR_NONE;
183 }
184 
191 {
193  return AUDIO_ERROR_NONE;
194 }
195 
196 #if 1
197 
203 {
204  BufferCtl.state = BUFFER_OFFSET_FULL;
205  //BufferCtl.clockState = 2;
207 }
208 
215 {
216  BufferCtl.state = BUFFER_OFFSET_HALF;
217  //BufferCtl.clockState = 1;
219 }
220 #endif
221 
227 void AUDIO_Player_CpyBuf(uint8_t *buf)
228 {
229  if (BufferCtl.state == BUFFER_OFFSET_FULL)
230  memcpy(&BufferCtl.buff[AUDIO_TOTAL_BUF_SIZE], buf, AUDIO_TOTAL_BUF_SIZE);
231  else
232  memcpy(&BufferCtl.buff[0], buf, AUDIO_TOTAL_BUF_SIZE);
233 
235 }
236 
237 static int initDone = 0;
238 static int oIdx = 0;
239 
246 #if 0
247 void AUDIO_Player_QueueBuf(uint8_t *buf, int len)
248 {
249  uint8_t *dbuf;
250  static int oIdx = 0;
251  static int oState = 0;
252 
253  if (oState < 3)
254  {
255  if (BufferCtl.state == BUFFER_OFFSET_FULL)
256  //second buffer
257  if ( ! oState)
258  oState = 2;
259  else
260  oState = 4;
261  else
262  //first buffer
263  if ( ! oState)
264  oState = 1;
265  else
266  oState = 3;
267  }
268 
269  //wait for a new edge on DMA trigger, to make sure to start properly
270  if (oState < 3)
271  return;
272 
273  if (oState == 4)
274  {
275  dbuf = &BufferCtl.buff[AUDIO_TOTAL_BUF_SIZE];
276  }
277  else
278  {
279  dbuf = &BufferCtl.buff[0];
280  }
281 
282  if (oIdx <= (AUDIO_TOTAL_BUF_SIZE - len))
283  {
284  memcpy(dbuf + oIdx, buf, len);
285  oIdx += len;
286  }
287  else
288  {
289  //ERROR: what to do now?
290  oIdx = AUDIO_TOTAL_BUF_SIZE;
291  }
292 
293  if (oIdx >= AUDIO_TOTAL_BUF_SIZE)
294  {
295  oIdx = 0;
296  //flip the state for which buffer
297  if (oState == 4)
298  oState = 3;
299  else
300  oState = 4;
301  }
302 }
303 #else
304 void AUDIO_Player_QueueBuf(uint8_t *buf, int len)
305 {
306  //just to make sure:
307  if ((oIdx + len) <= sizeof(BufferCtl.buff))
308  {
309  memcpy(&BufferCtl.buff[oIdx], buf, len);
310  oIdx += len;
311  }
312  else
313  {
314  //an error, what to do?
315  oIdx = 0;
316  return;
317  }
318 
319  if ( ! initDone)
320  {
321  //tricky: how to restart audio out so that it is in sync?
322  //this seems to work the best way, but not always, we need a new reset and restart
323  if (oIdx >= (sizeof(BufferCtl.buff) / 2 + 192))
324  {
326  initDone = 1;
327  }
328  }
329 
330  if (oIdx >= sizeof(BufferCtl.buff))
331  oIdx = 0;
332 
334 }
335 #endif
336 
343 {
344  initDone = 0;
345  oIdx = 0;
346 }
347 
353 unsigned long AUDIO_Player_GetHeartbeat(void)
354 {
355  unsigned long x;
356  x = sAudioHeartbeat;
357  sAudioHeartbeat = 0;
358 
359  //if no heartbeat - clear the buffer
360  if ( ! x)
361  memset(BufferCtl.buff, 0x00, sizeof(BufferCtl.buff));
362 
363  return x;
364 }
365 
372 {
373  sAudioHeartbeat++;
374 }
375 
376 /*******************************************************************************
377  Static Functions
378 *******************************************************************************/
379 
380 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#define pdTRUE
Definition: projdefs.h:83
void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
Manages the DMA Half Transfer complete interrupt.
Definition: AudioPlayer.c:214
#define AUDIO_OUT_BUFFER_SIZE
Definition: AudioPlayer.h:17
int AUDIO_PLAYER_GetBuffer(uint8_t **out_BufAddr)
Definition: AudioPlayer.c:117
void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
Calculates the remaining file size and new position of the pointer.
Definition: AudioPlayer.c:202
#define CODEC_PDWN_SW
Definition: wm8994.h:94
AUDIO_ErrorTypeDef AUDIO_PLAYER_Process(void)
Manages Audio process.
Definition: AudioPlayer.c:180
AUDIO_ErrorTypeDef AUDIO_PLAYER_Stop(void)
Stops Audio streaming.
Definition: AudioPlayer.c:190
uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
Stops audio playing and Power down the Audio Codec.
int AUDIO_PLAYER_GetClock(void)
Definition: AudioPlayer.c:72
AUDIO_ErrorTypeDef
Definition: AudioPlayer.h:34
SemaphoreHandle_t xSemaphoreAudio
Definition: main.c:132
void AUDIO_Player_CpyBuf(uint8_t *buf)
Copy USB input buffer to SAI output buffer.
Definition: AudioPlayer.c:227
void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
Updates the Audio frame slot configuration.
#define taskYIELD()
Definition: task.h:202
uint8_t buff[AUDIO_OUT_BUFFER_SIZE]
Definition: AudioPlayer.h:28
uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
Configures the audio peripherals.
void AUDIO_Player_IncHeartbeat(void)
Increment the audio reception counter (heartbeat)
Definition: AudioPlayer.c:371
#define OUTPUT_DEVICE_HEADPHONE
Definition: wm8994.h:75
void AUDIO_Player_UDANTERestart(void)
Restart and sync audio for Network Audio.
Definition: AudioPlayer.c:342
volatile int clockState
Definition: AudioPlayer.h:31
#define AUDIO_TOTAL_BUF_SIZE
Definition: usbd_audio.h:108
void AUDIO_PLAYER_Restart(void)
Definition: AudioPlayer.c:168
#define portYIELD_FROM_ISR(x)
Definition: portmacro.h:135
int AUDIO_PLAYER_GetState(void)
Definition: AudioPlayer.c:109
AUDIO_ErrorTypeDef AUDIO_PLAYER_Start(void)
Starts Audio streaming.
Definition: AudioPlayer.c:161
#define CODEC_AUDIOFRAME_SLOT_13
#define OUTPUT_DEVICE_SPEAKER
Definition: wm8994.h:74
long BaseType_t
Definition: portmacro.h:98
AUDIO_ErrorTypeDef AUDIO_PLAYER_Init(int outSelection, int sampleFreq)
Initializes Audio Interface.
Definition: AudioPlayer.c:128
uint8_t BSP_AUDIO_OUT_Play(uint16_t *pBuffer, uint32_t Size)
Starts playing audio stream from a data buffer for a determined size.
#define xSemaphoreTake(xSemaphore, xBlockTime)
Definition: semphr.h:252
#define pdFALSE
Definition: projdefs.h:82
#define CODEC_AUDIOFRAME_SLOT_02
unsigned long AUDIO_Player_GetHeartbeat(void)
Get the counter (heartbeat) if we have audio reception.
Definition: AudioPlayer.c:353
void AUDIO_Player_QueueBuf(uint8_t *buf, int len)
Put the Network Audio samples into SAI output buffer.
Definition: AudioPlayer.c:304
void AUDIO_PLAYER_ReleaseClock(int trig)
Definition: AudioPlayer.c:97
void BSP_AUDIO_OUT_Restart(uint16_t *pBuffer, uint32_t Size)
#define xSemaphoreGiveFromISR(xSemaphore, pxHigherPriorityTaskWoken)
Definition: semphr.h:612
QueueHandle_t SemaphoreHandle_t
Definition: semphr.h:79
volatile BUFFER_StateTypeDef state
Definition: AudioPlayer.h:29