Объявление

#1 25-07-2010 09:30:23

Программирование Digital sound processor звуковой карты

Приветствую всех.
Возникла необходимость программирования DSP звуковой карты, в книге В. Несвижский "Программирование аппаратных средств в Windows" имеется некоторый материал, откуда понятно что DSP надо программировать через порты 2x6h; 2xAh; 2xCh; 2xEh.
Меня конкретно интересуют функции порта 2xCh.
В книге есть небольшой список функций, но их оказалось не достаточно.
Пожалуйста помогите достать как можно более полный список функций для этого порта(2xCh).

 

#2 25-07-2010 11:02:09

Re: Программирование Digital sound processor звуковой карты

SOA
Эм... Ну вообще то, этото порт используется для записи команд или данных.
Но он легко гуглится :)
Перечень команды можн найти тут: http://irlp.kc6hur.net/SoundBlaster.pdf
Некоторое пособие по кодингу нашлось тут: http://articles.org.ru/docum/soundbl.php

В принципе вам надо бы сказать что же вы хотите сделать, более конкретно, каких вам функций не хватило например. Тогда вам подскажут гораздо более точно.


Мой блог
マカフィー直流チーム
"Не жди, дурак, свободы, её лишь смерть даёт." (С)

 

#3 25-07-2010 11:45:50

Re: Программирование Digital sound processor звуковой карты

TermoSINteZ

У меня по google получилось найти только то что в прикрепленном файле отсюда http://www.dcee.net/Files/Programm/Sound/.

Спасибо за перечень команд!

Я пытаюсь написать простенький плеер с возможностью регулировки звука покачто только для wav файлов.
Поэтому у меня возникла необходимость написания процедур воспроизведения звука как минимум с 8 битным, 16 битным и в перспективе 24 битным сэймплом.
   С написанием функции для воспроизведения 8 битного сэймпла проблем не возникло, я использовал функцию 10h и воспроизвожу звук в цикле по биту из буфера, длина которого расчитывается так чтоб его хвататало на 1 секунду.
   Но вот для воспроизведения 16 битного сэймпла я функцию пока не нашел чтоб была подобной функции 10h для 8 битного. В наличии покачто только функции с использованием DMA где размер буфера не может превышать 64Кб и воспроизводится на автомате из этого же буфера, а не как в 10h по одному байту, вследствие чего проблематично поставить в цикл данную функцию. Можно конечно использовать функции паузы, или еще как то ухищряться, но это не то что мне нужно.

P.S. то что находится в прикрепленном файле можно посмотреть в более читабельном виде здесь
http://homepages.cae.wisc.edu/~brodskye … 16doc.html

Отредактировано SOA (04-08-2010 15:54:31)


Прикреплённые файлы:
Attachment Icon DSP.TXT, Размер: 20,972 b, Скачано: 73

 

#4 25-07-2010 13:30:08

Re: Программирование Digital sound processor звуковой карты

TermoSINteZ
Ещё раз спасибо за перечень команд, там на 55 странице кажется нашел то что меня интересовало.
Думаю вопрос можно считать закрытым.
8D

 

#5 25-07-2010 13:44:04

Re: Программирование Digital sound processor звуковой карты

SOA
Ну если точно удалось, вы напишите как поступили и как решили проблему, чтобы другие новички, столкнувшись - нашли ответ.


Мой блог
マカフィー直流チーム
"Не жди, дурак, свободы, её лишь смерть даёт." (С)

 

#6 25-07-2010 14:19:42

Re: Программирование Digital sound processor звуковой карты

TermoSINteZ
OK
Если получится то отпишу процедуру с коментами, если вы конечно это имели ввиду.
Ну а если вы имели ввиду функцию то тут все просто ставим длину буфера для функции 16 бит и все функция обрабатывается один раз и ее смело можно помещать в цикл обработки большого буфера.

Отредактировано SOA (25-07-2010 14:24:03)

 

#7 25-07-2010 14:21:14

Re: Программирование Digital sound processor звуковой карты

Да, именно это и имел ввиду. Ну или хотя бы на словах подробно, как решалась задача.


Мой блог
マカフィー直流チーム
"Не жди, дурак, свободы, её лишь смерть даёт." (С)

 

#8 25-07-2010 19:24:20

Re: Программирование Digital sound processor звуковой карты

TermoSINteZ
К сожелению при попытке использования данной функции возникли некоторые трудности. Распишу по шагам, как на странице 55 перечня команд:
1 Установить бит прерываний для DSP

Код:

Enable_16_bit_Interrupt proc    ; процедура устанавливающая прерывание DSP для 16 битного сэймпла
Push edx

and bl,11110000b
add bl,Fh    ; сохраняем в bx номер порта 2xFh

mov dl,82h    ; номер регистра хранящего бит прерываний для DSP
call Write_DSP    ; вызываем этот регистр(функцию)
in Restore_int_mode,bx    ; сохраняем предидущее значение бита прерываний для DSP

@cikl
mov dl,82h    ; номер регистра хранящего бит прерываний для DSP
call Write_DSP    ; вызываем этот регистр(функцию)
mov dl,2h    ; устанавливаем второй бит
call Write_DSP    ; записываем в порт 2xF значение 00000010b
in dl,bx    ; проверяем установился ли бит
cmp dl,2h
jne @cikl

Pop edx
ret
Enable_16_bit_Interrupt ENDP

2 разрешить прерывания (я их не запрещал)

3 запрограммировать DMA контроллер для 16 битного DMA mode transfer (к сожелению информации в мануале не оказалось, вернее она слишком скудная для программирования контроллера динамического доступа к памяти)

4 установить частоту дискретизации

Код:

Set_DSP_Sampling_Rate proc    ; процедура устанавливающая частоту дискретизации в моем случае не важна
push edx

and bl,11110000b
add bl,Ch    ; сохраняем в bx номер порта 2xCh
mov dl,41h    ; режим воспроизведения
call Write_DSP
mov dl,ACh    ; Старший байт значения частоты
call Write_DSP
mov dl,44h    ; младший байт значения частоты
call Write_DSP    ; частота дискретизации равна 44100Гц но в моём случае не важна

pop edx
ret
Set_DSP_Sampling_Rate ENDP

5 установить команду, затем тип передачи бит, число передаваемых бит

Код:

Set_Transfer_mode proc    ; процедура устанавливающая тип передачи бит и размер буфера
push edx

and bl,11110000b
add bl,Ch    ; сохраняем в bx номер порта 2xCh

mov dl,B0h    ; 16 битное воспроизведение
call Write_DSP
mov dl,30h    ; 16 битное стерео
call Write_DSP
mov dl,1h    ; младший байт числа сэймплов, которые будут обработаны
call Write_DSP
mov dl,0h    ; старший байт числа сэймплов, которые будут обработаны
call Write_DSP

pop edx
ret
Set_Transfer_mode ENDP

6 Восстановить бит прерываний для DSP

Код:

Restore_interrupt_mode proc    ; процедура востанавливающая значение бита прерывания для DSP
Push edx

and bl,11110000b
add bl,Fh    ; сохраняем в bx номер порта 2xFh


@cikl
mov dl,82h    ; номер регистра хранящего бит прерываний для DSP
call Write_DSP    ; вызываем этот регистр(функцию)
mov dl,Restore_int_mode    ; востанавливаем значение бита прерываний для DSP
call Write_DSP    ; записываем в порт 2xFh значение 00000010b
in dl,bx    ; проверяем установился ли бит
cmp dl,Restore_int_mode
jne @cikl

pop edx
ret
Restore_interrupt_mode ENDP

Код:

Write_DSP proc    ; процедура записи в порт DSP 2xCh

@cikl1:        ; проверяем готовность порта 2xch к приему данных
in dl,bx    ; считываем в dl значение в порте 2xch
bt dl,7
jc @cikl1

out bx,dl    ; записываем команду в порт 2xch
ret
Write_DSP ENDP

После этих инструкций на 56 странице идет следующий текст после таблички The transfer begins here. The DSP will generate an interrupt after transferring the programmed number of samples.
Я так понимаю что после 5 пункта DSP должен считать из памяти DMA заданное число бит, после чего будет сгенерировано прерывание. Но т.к. DMA остался незапрограммированным, то нет возможности передать через него функции информацию.
Получается все упирается в пункт 3.
Если я не прав поправьте меня пожалуйста. =(

Отредактировано SOA (25-07-2010 19:27:17)

 

#9 26-07-2010 07:14:52

Re: Программирование Digital sound processor звуковой карты

Вроде бы нашел информацию по программированию DMA.

http://wasm.ru/article.php?article=atazen02
www.inversereality.org/files/dmaprogramming.pdf

Не знаю поможет или нет :/.

P.S. если у когото есть маны по программированию DMA на asm для soundblaster'а plz скажите где скачать.

Отредактировано SOA (26-07-2010 07:15:26)

 

#10 26-07-2010 09:14:36

Re: Программирование Digital sound processor звуковой карты

SOA

если у когото есть маны по программированию DMA на asm для soundblaster'а plz скажите где скачать.

кажется в  "Ассемблер Зубков С.В." было

 

#11 26-07-2010 13:36:13

Re: Программирование Digital sound processor звуковой карты

wsd
Спасибо!

Отредактировано SOA (26-07-2010 13:37:11)

 

#12 28-07-2010 12:38:21

Re: Программирование Digital sound processor звуковой карты

Нашел еще немного информации по программированию DMA, которую свел в небольшой мануал(пока черновой вариант).
По прежнему остаются вопросы по программированию DMA

Как запрограммировать прерывания, которыми DMA сигнализирует устройству о завершении транзакции?

Как сообщить устройству из какого канала DMA считывать информацию, хотя сам собой напрашивается ответ сообщить ему адрес в виртуальной памяти, где хранится DMA буфер и при получении прерывания считывать буфер, вот только если бы это было реализуемо, то в DMA отпала необходимость и я сообщил бы адрес большого буфера, но информации на этот счет нет.

Но стало ясно что программа должна работать в нулевом кольце системы, т.к. при программировании DMA используется команда CLI, которая если я не ошибаюсь может использоваться только в нулевом кольце.

Отредактировано SOA (04-08-2010 15:26:29)

 

#13 29-07-2010 15:07:45

Re: Программирование Digital sound processor звуковой карты

Все мануал считаю окончательно сформированным.
Спасибо Jari Kaija программисту из братской финляндии, благодаря мануалу которого удалось разобраться с программированием DMA для DSP и добавить пример программирования.


Прикреплённые файлы:
Attachment Icon Программирование DMA.pdf, Размер: 92,678 b, Скачано: 69

 

#14 04-08-2010 15:47:41

Re: Программирование Digital sound processor звуковой карты

Пока что удалось накодить следующее и исправить множество ошибок допущенных в предидущем коде

Данные

Код:

title PlayBuf for 32 byte
.486P
.MODEL FLAT, Stdcall

PUBLIC PlayByte
PUBLIC PlayWord
PUBLIC ResetDSP
          
.DATA
EXTRN bufsize: DWORD        ; Перемнная хранящая количество элементов массива
EXTRN numchannels: WORD        ; Переменная хранящая количество каналов fmt.numchannels
EXTRN vol: BYTE            ; Переменная которая контроллирует громкость звука

adres DWORD ?            ; Переменная хранящая адрес нулевого элемента массива
delay WORD ?            ; Переменная содержащая задержку в мкс
Restore_int_mode byte ?        ; переменная хранящая тип прерывания DSP который был ранее

1Установить бит прерываний для DSP

Код:

Enable_16_bit_Interrupt proc    ; процедура устанавливающая бит прерывания для DSP
Push eax

and dl,11110000b
add dl,0Fh    ; сохраняем в bx номер порта 2xFh

mov al,82h    ; адрес регистра хранящего бит прерываний в карте регистров микшера
out dx,al    ; вызываем этот регистр(функцию)
in al,dx    ; сохраняем предидущее значение бита прерываний для DSP
mov Restore_int_mode,al

cikl8:
mov al,82h    ; номер регистра хранящего бит прерываний для DSP
out dx,al    ; вызываем этот регистр(функцию)
mov al,2h    ; устанавливаем второй бит (прерывание для 16 битного сэймпла)
out dx,al    ; записываем в порт 2xF значение 00000010b
in al,dx    ; проверяем установился ли бит
cmp al,2h
jne cikl8

Pop eax
ret
Enable_16_bit_Interrupt ENDP

2 пропускаем разрешение прерываний так как мы их не запрещали

3 Программируем DMA контроллер для 16 битного сэймпла без автоинициализации в моно режиме

Код:

Program_DMA_chanel_5 proc    ; Программируем 5 порт DMA
push eax edx

;Отключаем 5 канал, который будем использовать для передачи

mov dx,0D4h    ; адрес Single mask register для 16 битного DMA
mov al,5h    ; команда отключения 5 канала
out dx,al

;Перезагружаем регистр flip-flop для DMA2

mov dx,0D8h    ; адрес регистра flip-flop для 16 битного DMA
mov al,0h
out dx,al

;Устанавливаем значение Mode регистра

mov dx,0D6h        ; Адрес mode регистра для DMA2
mov al,01001001b    ; программируем mode регистр
out dx,al

;Передаем в Offset port значение указателя

mov dx,0C4h    ; Адрес offset port для 5 канала
push eax ebx ecx
bt ebx,16
jc next1    ; если 16 бит равен 1
jmp next2   ; если не равен 1
next1:
mov cl,1
shr ebx,cl     ; делим указатель на 2
next2:
mov ax,bx   ; помещаем младшую часть делимого в ax
mov edx,ebx
shr edx,16  ; помещаем старшую часть делимого в dx

mov bx,65535
div bx

out dx,al    ; Передаем в порт младший бит часного
mov al,ah
out dx,al    ; Передаем в порт старший бит часного

pop ecx ebx eax

;Передаем в Block size регистр значение 1= 2 байтам т.к. передаваемое значение всегда на меньше

mov dx,0C6h    ; Адрес Block size регистра
mov al,01h
out dx,al

;***************************************************************************
;Передаем в page port значение номера страницы
 
mov dx,8Bh    ; Адрес page port для 5 канала
push eax ebx

mov ax,bx   ; помещаем младшую часть делимого в ax
mov edx,ebx
shr edx,16  ; помещаем старшую часть делимого в dx

mov bx,65535; получаем номер страницы
div bx
    
out dx,al              ; передаем в page порт номер страницы


pop ebx eax
;***************************************************************************


;Включаем 5 канал

mov dx,0D4h    ; Адрес Single mask register для 16 битного DMA
mov al,1h    ; Команда включения 5 канала
out dx,al

pop edx eax
ret
Program_DMA_chanel_5 ENDP

4 устанавливаем частоту дискретизации

Код:

Set_DSP_Sampling_Rate proc    ; процедура устанавливающая частоту дискретизации в моем случае не важна
push eax

and dl,11110000b
add dl,Ch    ; сохраняем в bx номер порта 2xCh
mov al,41h    ; режим воспроизведения
call Write_DSP
mov al,0ACh    ; Старший байт значения частоты
call Write_DSP
mov al,44h    ; младший байт значения частоты
call Write_DSP    ; частота дискретизации равна 44100Гц но в моём случае не важна

pop eax
ret
Set_DSP_Sampling_Rate ENDP

5 Устанавливаем команду тип передачи и число бит

Код:

Set_Transfer_mode proc    ; процедура устанавливающая тип передачи бит и размер буфера
push eax

and dl,11110000b
add dl,Ch    ; сохраняем в bx номер порта 2xCh

mov al,0B0h    ; 16 битное воспроизведение
call Write_DSP
mov al,10h    ; 16 битное моно
call Write_DSP
mov al,1h    ; младший байт числа сэймплов, которые будут обработаны
call Write_DSP
mov al,0h    ; старший байт числа сэймплов, которые будут обработаны
call Write_DSP

pop eax
ret
Set_Transfer_mode ENDP

6 Востанавливаем бит прерываний для DSP

Код:

Restore_interrupt_mode proc    ; процедура востанавливающая значение бита прерывания для DSP
Push eax

and dl,11110000b
add dl,0Fh    ; сохраняем в bx номер порта 2xFh

cikl9:
mov al,82h    ; номер регистра хранящего бит прерываний для DSP
out dx,al    ; вызываем этот регистр(функцию)
mov al,Restore_int_mode    ; востанавливаем значение бита прерываний для DSP
out dx,al    ; записываем в порт 2xFh значение 00000010b
in al,dx    ; проверяем установился ли бит
cmp al,Restore_int_mode
jne cikl9

pop eax
ret
Restore_interrupt_mode ENDP

Процедура записи в порт DSP

Код:

Write_DSP proc        ; процедура записи в порт DSP 2xCh
push eax

cikl3:            ; проверяем готовность порта 2xch к приему данных
in al,dx        ; считываем в al значение в порте 2xch
bt ax,7
jc cikl3

pop eax
out dx,al        ; записываем команду в порт 2xch
ret
Write_DSP ENDP

Процедура воспроизведения 16 битного сэймпла из большого буфера

Код:

PlayWord Proc    ; Процедура проигрывания wav файла с длинной сэймпла word
    PUSH EAX EBX EDX ECX
    push ebp
    mov ebp,esp          ; Поместили в bp указатель на вершину стека
    mov dx,[ebp+18]          ; Поместили в dx номер порта который предварительно сохранили под delphi
                  ; 18 потому что eax+ebx+edx+ecx+bp=18 байт
        mov ebx,[ebp+20]
    mov adres,ebx         ; adres указывает на область памяти где хранится нулевой элемент массива    
                  ; используем ebx потому что переменная типа DWORD
    mov ax,[ebp+24]
        mov delay,ax
 

    POP ebp
    call ResetDSP
    call Enable_16_bit_Interrupt    ; Устанавливаем прерывания для DSP
    call Set_DSP_Sampling_Rate    ; Устанавливаем частоту дискретизации для DSP
    
    mov ecx,bufsize                ; проигрываем буфер обмена
    and dl,11110000b
    add dl,Ch                      ; установили в bx номер порта 2xCh
    cikl2:                    ; воспроизводим два бита
    call Program_DMA_chanel_5    ; Программируем DMA для DSP
    call Set_Transfer_mode        ; Программируем тип передачи и длинну буфера для DSP
    ;Теперь мы должны что то услышать    

    push eax ecx edx
    mov ah,86h    ; номер функции задержки
    xor ecx,ecx    ; старшее слово таймера задержки
    mov dx,delay    ; младшее слово таймера задержки
    int 15h        ; подождать некоторое время
    pop edx ecx eax

    lea ebx,[ebx+numchannels]
    lea ebx,[ebx+numchannels] ; увеличиваем указатель два раза потому что тип word
    loop cikl2

    call Restore_interrupt_mode    ; Востанавливаем бит прерывания для DSP

    POP ECX EDX EBX EAX
    add esp,8    ; т.к. мы поместили 8 байт в стек перед выполнением процедуры
            ; номер порта+adres+delay
ret
PlayWord ENDP

Пока что интересует вопрос можно ли считать 32 битный указатель типа pointer из delphi линейным адресом, потому что от этого зависит работа процедуры инициализации DMA контроллера.
Если выражаться более точно то правильность значений в порте Offset и порте Page port DMA контроллера.

Кто в курсе пишите, ну и конечно если ошибки увидите ругайте:)

Ниже прикрепляю asm файл для tasm.

Отредактировано SOA (04-08-2010 15:50:51)


Прикреплённые файлы:
Attachment Icon PlayBuf.asm, Размер: 9,604 b, Скачано: 38

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson