Перейти к содержанию
    

STM32 Audio device class

Приветствую. До этого работал только с плис и дсп, теперь осваиваю стм и юсб.

Необходимо по юсб принять аудиопоток на стм. Собрал в CubeMX проект, потом подправил дескрипторы под 48kHz, 24bit, увеличил стек и кучу чтоб все завелось.

Устройство в виндовсе определяется без ошибок, аудио выплёвывает.

Теперь вопрос, а где эти данные искать в микроконтроллере?!? В описании библиотеки:

How to use this driver

This driver uses an abstraction layer for hardware driver (i.e. HW Codec, I2S interface, I2C

control interface...). This abstraction is performed through a lower layer (i.e.

usbd_audio_if.c) which you can modify depending on the hardware available for your

application.

To use this driver:

Through the file usbd_conf.h, you can configure:

• The audio sampling rate (define USBD_AUDIO_FREQ)

Call the function USBD_AUDIO_Init() at startup to configure all necessary firmware and

hardware components (application-specific hardware configuration functions are also called

by this function). The hardware components are managed by a lower layer interface (i.e.

usbd_audio_if.c) and can be modified by user depending on the application needs.

The entire transfer is managed by the following functions (no need for user to call any

function for out transfers):

• usbd_audio_DataIn() and usbd_audio_DataOut() which update the audio buffers with

the received or transmitted data. For Out transfers, when data are received, they are

directly copied into the audiobuffer and the write buffer (wr_ptr) is incremented.

The Audio Control requests are managed by the functions USBD_AUDIO_Setup() and

USBD_AUDIO_EP0_RxReady(). These functions route the Audio Control requests to the

lower layer (i.e. usbd_audio_if.c). In the current version, only SET_CUR and GET_CUR

requests are managed and are used for mute control only.

 

Причём функция usbd_audio_DataIn пустая и программа в неё даже не заходит. Где искать этот самый audiobuffer?

Изменено пользователем maxis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Устройство в виндовсе определяется без ошибок, аудио выплёвывает.

Теперь вопрос, а где эти данные искать в микроконтроллере?!? В описании библиотеки:

Причём функция usbd_audio_DataIn пустая и программа в неё даже не заходит. Где искать этот самый audiobuffer?

Это не та ли путаница с USB, что есть In, и что Out? Обычно, название дается с точки зрения PC, поэтому следует обратить внимание на usbd_audio_DataOut.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это не та ли путаница с USB, что есть In, и что Out? Обычно, название дается с точки зрения PC, поэтому следует обратить внимание на usbd_audio_DataOut.

Да, действительно, приём данных происходит в usbd_audio_DataOut. Вижу что данные принимаются, кладётся в какой то буфер. Но при этом абсолютно не понимаю как из этого буфера правильно вычитывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, действительно, приём данных происходит в usbd_audio_DataOut. Вижу что данные принимаются, кладётся в какой то буфер. Но при этом абсолютно не понимаю как из этого буфера правильно вычитывать.

Прежде всего, надо знать, что именно приходит. Я предполагаю, что идут PCM выборки, по 16 бит на канал.

Технически надо дописать функцию так, чтобы при приходе данных взводился какой-то флаг (например, принятая длина буфера), который бы анализировался в некоем процессе, который, зная местоположение буфера, выбирал бы из него лежащие там данные и пользовал по своему усмотрению. Например, переписывал в рабочий (двойная буферизация), откуда посылал бы в I2S периферию или DAC. Это уже вопросы техники программирования, RTOS и т.п.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прежде всего, надо знать, что именно приходит. Я предполагаю, что идут PCM выборки, по 16 бит на канал.

Технически надо дописать функцию так, чтобы при приходе данных взводился какой-то флаг (например, принятая длина буфера), который бы анализировался в некоем процессе, который, зная местоположение буфера, выбирал бы из него лежащие там данные и пользовал по своему усмотрению. Например, переписывал в рабочий (двойная буферизация), откуда посылал бы в I2S периферию или DAC. Это уже вопросы техники программирования, RTOS и т.п.

С структурой буфера все более менее понятно. Не ясно как к ней обратится.

Указатель на буфер(pClassData) находится в структуре:

typedef struct _USBD_HandleTypeDef
{
  uint8_t                 id;
  uint32_t                dev_config;
  uint32_t                dev_default_config;
  uint32_t                dev_config_status; 
  USBD_SpeedTypeDef       dev_speed; 
  USBD_EndpointTypeDef    ep_in[15];
  USBD_EndpointTypeDef    ep_out[15];  
  uint32_t                ep0_state;  
  uint32_t                ep0_data_len;     
  uint8_t                 dev_state;
  uint8_t                 dev_old_state;
  uint8_t                 dev_address;
  uint8_t                 dev_connection_status;  
  uint8_t                 dev_test_mode;
  uint32_t                dev_remote_wakeup;

  USBD_SetupReqTypedef    request;
  USBD_DescriptorsTypeDef *pDesc;
  USBD_ClassTypeDef       *pClass;
  void                    *pClassData;  
  void                    *pUserData;    
  void                    *pData;    
} USBD_HandleTypeDef;

 

проблема в том что значение USBD_HandleTypeDef->pUserData в функции приёма данных принимает правильное значение, а если я вычитываю эту переменную в мэйне то значение не верное. Видимо из за динамической памяти.

 

 

 

Ну да с этим разберусь. Проблема в другом.

Пытаюсь сделать асинхонный аудио девайс клас.

Для этого добавил эндпоинт для обратной связи. Подшаманил с дискриптором, всё завелось.

В USBTrace всё время мелькает сообщение SYNC_RESET_PIPE_AND_CLEAR_STALL для эндпоинта обратной связи. В чём дело понять не могу.

Изменено пользователем maxis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По аналогии с примером виртуального ком порта сделал функцию

uint8_t  USBD_AUDIO_TransmitPacket(USBD_HandleTypeDef *pdev)
{
  if(pdev->pClassData != NULL)
  {    
    if(TxState == 0)
    {
      feedback_value = 48<<14;            
      /* Transmit next packet */
            //USBD_LL_FlushEP(pdev, AUDIO_IN_EP);
      USBD_LL_Transmit(pdev,
                       AUDIO_IN_EP,
                       (uint8_t *)(&feedback_value),
                       0x03);      
      /* Tx Transfer in progress */
      TxState = 1;
      return USBD_OK;
    }
    else
    {
      return USBD_BUSY;
    }
  }
  else
  {
    return USBD_FAIL;
  }
}

И внёс изменение в:

static uint8_t  USBD_AUDIO_DataIn (USBD_HandleTypeDef *pdev, 
                              uint8_t epnum)
{
    TxState = 0;
  /* Only OUT data are processed */
  return USBD_OK;
}

USBD_AUDIO_TransmitPacket вызывается всё время из мейна и должна сообщать хосту сколько семплов прислать. Но проблево в том что данное сообщение отправляется только один раз. TxState выставляется в 1 и не сбрасывается. Ну и в USBD_AUDIO_DataIn соответственно тоже не попадает. В чём может быть дело?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

USBD_AUDIO_TransmitPacket вызывается всё время из мейна и должна сообщать хосту сколько семплов прислать. Но проблево в

фидбек еп такая же изохронная еп как и остальные две, а значит должна обрабатываться соф ивентом. Например в обработчике прерывания. При чем тут функция мейн?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

фидбек еп такая же изохронная еп как и остальные две, а значит должна обрабатываться соф ивентом. Например в обработчике прерывания. При чем тут функция мейн?
Я думал что функция USBD_LL_Transmit лишь готовит данные к отправке, а непосредственно они будут переданы только после запроса хоста, после чего и будет вызвана функция USBD_AUDIO_DataIn , которая разрешит подготовить следующую посылку. Завтра проверю, срабатывает ли вообще USBD_AUDIO_Sof и попробую запустить передачу из неё.
Изменено пользователем maxis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрите проекты sdr_widget и audio_widget. Все исходники доступны. Кроме того, посмотрите мой проект, который выкладывал в теме про DMA для DDS. http://electronix.ru/forum/index.php?showtopic=128332

Также здесь http://electronix.ru/forum/lofiversion/ind...hp/t115850.html

Freescale USB stack тоже содержит пример юсб аудио устройства с эксплисит эндпойнтом

 

Фишка в том (секрет Полишинеля), что Виндовс некорректно реагирует на то число, которое ей возвращает аудио девайс в фидбэк эндпоинте. В Audio_widget эту проблему обрулили, насколько понял, по отношению к частоте дискретизации получается кольцо из ресэмплера и ПИ-регулятора (один в драйвере usbaudio.sys, второй в устройстве)

 

На форуме ST есть гуру по этому вопросу - Tsuneo Chinzei.

Изменено пользователем romanetz

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Фишка в том (секрет Полишинеля), что Виндовс некорректно реагирует на то число, которое ей возвращает аудио девайс в фидбэк эндпоинте. В На форуме ST есть гуру по этому вопросу - Tsuneo Chinzei.

[DELETED] Вин ХП и 7 работают как и ожидается. Тсунео известный фантазер, когда его попросили привести док-ва ресемплинга, слился из темы и больше не появлялся. Больше напоминае теоретига, ни разу не делавшего реальный аудио проект.

От себя добавлю, нет никакого ресемплинга и ПИ не нужен, достаточно прямого расчета. Хотя разумеется никто не запрещает вонзать эти сущности в свой проект, если сильно хочется.

Изменено пользователем IgorKossak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

TIM2 имеет специальный режим измерения периода SOFов. В данном случае - по отношению к частоте мастерклока выходного ЦАПа. Соответственно, значение в нем прямо пропорционально Fsample/Fsof, которое требуется отправлять в фидбэке. ри этом все же возникает рассинхронизация скоростей приема из USB и выдачи в ЦАП. По этой причине необходимо в ориентироваться в прерывании SOFа на указатель буфера чтения NDTR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...