poniedziałek, 8 października 2018

[28] STM32F7 - Kodek audio WM8994ECS/R.

W tym poście chciałbym opisać sposób obsługi kodeka audio zamontowanego na płytce STM32F7 Discovery.

[Źródło: http://www.st.com/en/evaluation-tools/32f746gdiscovery.html]

Schemat podłączenia:



Na płycie zamontowano kodek audio firmy Cirrus WM8994ECS/R. Posiada on cztery kanały DAC oraz dwa kanały ADC podłączone do interfejsu SAI. Komunikacja z mikrokontrolerem odbywa się przez linię I2C współdzieloną z modułem kamery.

Przygotowaną bibliotekę oparłem o kod udostępniony przez firmę ST dla układu STM32F7.

Program:


Najpierw inicjalizacja kodeka, lista funkcji wygląda następująco:

  1. uint32_t wm8994_audio_Init(uint16_t DeviceAddr, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq);
  2. void     wm8994_audio_DeInit(void);
  3. uint32_t wm8994_audio_ReadID(uint16_t DeviceAddr);
  4. uint32_t wm8994_audio_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size);
  5. uint32_t wm8994_audio_Pause(uint16_t DeviceAddr);
  6. uint32_t wm8994_audio_Resume(uint16_t DeviceAddr);
  7. uint32_t wm8994_audio_Stop(uint16_t DeviceAddr, uint32_t Cmd);
  8. uint32_t wm8994_audio_SetVolume(uint16_t DeviceAddr, uint8_t Volume);
  9. uint32_t wm8994_audio_SetMute(uint16_t DeviceAddr, uint32_t Cmd);
  10. uint32_t wm8994_audio_SetOutputMode(uint16_t DeviceAddr, uint8_t Output);
  11. uint32_t wm8994_audio_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq);
  12. uint32_t wm8994_audio_Reset(uint16_t DeviceAddr);

Wszystkie wspomniane funkcje obsługują kodek audio. Przesyłają one dane przez I2C do układu.

Kolejna grupa funkcji odpowiada za inicjalizację, zapisywanie oraz odtwarzanie dźwięku to

  1. opStat_Typedef AudioOutputInit(uint16_t selectedDevice, uint8_t volValue, uint32_t audioFrequency);
  2. opStat_Typedef AudioOutputPlayArray(uint16_t* playBuffer, uint32_t bufSize);
  3. opStat_Typedef AudioOutputPlayWav(WAVStructure *wavFilePtr, uint16_t outputDeviceName, uint8_t volValue);
  4. opStat_Typedef AudioOutputStop(void);
  5. opStat_Typedef AudioOutputSetVolume(uint8_t volume);
  6. void AudioOutSetAudioFrameSlot(uint32_t AudioFrameSlot);

  7. opStat_Typedef AudioInputInit(uint16_t inputDevice, uint8_t volValue, uint32_t audioFreq);
  8. opStat_Typedef AudioInputRecordArray(uint16_t* pbuf, uint32_t size);
  9. opStat_Typedef AudioInputStop(void);
  10. opStat_Typedef AudioInputSetVolume(uint8_t volume);
  11. opStat_Typedef AudioInputOutputInit(uint16_t inputDevice, uint16_t outputDevice, uint8_t setVolume, uint32_t audioFrequency);

Tutaj podobnie jak poprzednio wykorzystuję strukturę z wskaźnikami do funkcji:

  1. typedef struct{
  2.     opStat_Typedef (*OutputInit)(uint16_t, uint8_t, uint32_t);
  3.     opStat_Typedef (*OutputPlayArray)(uint16_t*, uint32_t);
  4.     opStat_Typedef (*OutputPlayWav)(WAVStructure*, uint16_t, uint8_t);
  5.     opStat_Typedef (*OutputStop)(void);
  6.     opStat_Typedef (*OutputSetVolume)(uint8_t);
  7.     void(*OutSetAudioFrameSlot)(uint32_t);
  8.     opStat_Typedef (*InputInit)(uint16_t, uint8_t, uint32_t);
  9.     opStat_Typedef (*InputRecordArray)(uint16_t*, uint32_t);
  10.     opStat_Typedef (*InputStop)(void);
  11.     opStat_Typedef (*InputSetVolume)(uint8_t);
  12.     opStat_Typedef (*InputOutputInit)(uint16_t, uint16_t, uint8_t, uint32_t);
  13. }stmAudio_Structure;

  1. stmAudio_Structure audioStruct ={
  2.     AudioOutputInit,
  3.     AudioOutputPlayArray,
  4.     AudioOutputPlayWav,
  5.     AudioOutputStop,
  6.     AudioOutputSetVolume,
  7.     AudioOutSetAudioFrameSlot,
  8.     AudioInputInit,
  9.     AudioInputRecordArray,
  10.     AudioInputStop,
  11.     AudioInputSetVolume,
  12.     AudioInputOutputInit
  13. };

Biblioteki można pobrać z dysku Google pod tym linkiem.