Как написать простой драйвер Soundblaster 16, используя режим прямой записи для хобби ОС? - PullRequest
0 голосов
/ 14 ноября 2018

Я занимаюсь разработкой 32-разрядной операционной системы для хобби в защищенном режиме.На данный момент я ищу, чтобы добавить простую поддержку звука.Для этого я собираюсь использовать звуковой бластер 16 и использовать прямой режим для записи в ЦАП (я хочу избежать DMA любой ценой).Однако, когда я вывожу простую прямоугольную волну в ЦАП (используя команду 0x10), из динамиков моего компьютера звук не выводится.Я ищу решение этой проблемы.

Я пытаюсь использовать следующий алгоритм для создания звука:

1. Reset DSP
2. Enable the speakers
3. Write 0x10 to 0x22C (direct mode DAC write command)
4. Write 0x00 to 0x22C (To set the speaker to low)
5. Write 0x10 to 0x22C
6. Write 0xFF to 0x22C (To set the speaker to high)
7. Jump back to step 4 and repeat.

Вот мой код:

#define DSP_RESET 0x226
#define DSP_READ 0x22A
#define DSP_WRITE 0x22C
#define DSP_READ_STATUS 0x22E
#define DSP_INT_ACK 0x22F

#define REG_ADDR 0x224
#define REG_DATA 0x225

#define DIRECT_DAC 0x10
#define ENABLE_SPEAKER 0xD1

void dsp_reset(){
      uint32_t buf[4];
      *buf = 128;
      rtc_write(0, buf, 4);

      outb(1, DSP_RESET);
      rtc_read(0, 0, NULL, 0);
      outb(0, DSP_RESET);

      if(inb(DSP_READ) != 0xAA){
            print_term((uint8_t *)"Could not init sb16\n", 20);
      }

      return;
}

void play_simple_sound(){

      dsp_reset();

      while(inb(DSP_WRITE));
      print_term((uint8_t *)"Enabling speaker\n", 18);
      outb(0xD1, DSP_WRITE);

      while(inb(DSP_WRITE));
      print_term((uint8_t *)"Playing sound\n", 14);
      outb(0xF0, DSP_WRITE);

      while(1){
            while(inb(DSP_WRITE));
            outb(0x10, DSP_WRITE);
            outb(0x00, DSP_WRITE);
            rtc_read(0, 0, NULL, 0);
            while(inb(DSP_WRITE));
            outb(0x10, DSP_WRITE);
            outb(0xFF, DSP_WRITE);
            rtc_read(0, 0, NULL, 0);
      }

      return;
}

rtc_write устанавливает частоту rtc на пару сотен герц, а rct_read заставляет программу ждать на rtc (обе эти программы работают правильно).Dsp_reset также работает правильно, потому что при чтении вывода из DSP возвращается 0xAA (что показывает, что существует звуковой бластер 16).

В настоящее время я использую 64-битную версию Windows 10 для запуска Qemu, которая эмулируетоперационная система.Я запускаю qemu с установленным параметром "-soundhw all".Я не уверен, что не могу слышать звук из-за написанного мной кода или что-то не так с Qemu.У меня вопрос: что может быть за проблема, и какие шаги я могу предпринять, чтобы это исправить?Также была бы признательна за документацию и учебные пособия, связанные с sb 16.

1 Ответ

0 голосов
/ 15 ноября 2018

При эмуляции Qemu прямой ЦАП невозможен при использовании SoundBlaster 16. Прямой АЦП также не разрешен. Проверьте найденный здесь исходный код, посмотрите поддерживаемые команды, начиная со строки 390:

https://github.com/qemu/qemu/blob/master/hw/audio/sb16.c

Похоже, что для вывода звука с использованием карты звукового бластера необходимо использовать DMA. Более того, похоже, что эмуляции SB16 на Qemu не хватает. Хороший список команд, которые поддерживает настоящий SB16, можно найти здесь: http://the.earth.li/~tfm/oldpage/sb_dsp.html. Сравнивая эти команды с тем, что поддерживает Qemu, эмулируется только небольшая часть.

Редактировать 2: Что касается других эмуляторов, Bochs не поддерживает sb16 (см. Строку 858: http://bochs.sourceforge.net/cgi-bin/lxr/source/iodev/sound/sb16.cc),, но DOSBox имеет очень впечатляющую поддержку SB16 и поддерживает прямой ЦАП, но все еще не поддерживает прямой АЦП для микрофона). (см. строку 1611: http://dosbox -x.com / doxygen / html / sblaster_8cpp_source.html )

...