Assembler - язык неограниченных возможностей


Контроллер DMA - часть 4


В качестве примера вернемся к программированию звуковых плат и изменим программу wavdir.asm так, чтобы она использовала DMA.

; wavdma.asm ; Пример программы, проигрывающей файл C:\WINDOWS\MEDIA\TADA.WAV ; на звуковой карте при помощи DMA FILESPEC equ "c:\windows\media\tada.wav" ; заменить на c:\windows\tada.wav ; для старых версий Windows SBPORT equ 220h ; SBDMA equ 1 ; процедура program_dma рассчитана только на канал 1 SBIRQ equ 5 ; только IRQ0 - IRQ7 .model tiny .code .186 org 100h ; СОМ-программа start: call dsp_reset ; инициализация DSP jc no_blaster mov bl,0D1h ; команда OD1h call dsp_write ; включить звук call open_file ; прочитать файл в буфер call hook_sbirq ; перехватить прерывание mov bl,40h ; команда 40h call dsp_write ; установка скорости передачи mov bl,0B2h ; константа для 11025Hz/Stereo call dsp_write call program_dma ; начать DMA-передачу данных

main_loop: ; основной цикл cmp byte ptr finished_flag,0 je main_loop ; выход, когда байт finished_flag = 1

call restore_sbirq ; восстановить прерывание no_blaster: ret

old_sbirq dd ? ; адрес старого обработчика finished_flag db 0 ; флаг окончания работы filename db FILESPEC,0 ; имя файла

; обработчик прерывания звуковой карты ; устанавливает флаг finished_flag в 1

sbirq_handler proc far push ax mov byte ptr cs:finished_flag,1 ; установить флаг mov al,20h ; послать команду EOI out 20h,al ; в контроллер прерываний pop ax iret sbirq_handler endp

; процедура dsp_reset ; сброс и инициализация DSP dsp_reset proc near mov dx,SBPORT+6 ; порт 226h - регистр сброса DSP mov al,1 ; запись в него единицы ; запускает инициализацию out dx,al mov cx,40 ; небольшая пауза dsploop: in al,dx loop dsploop mov al,0 ; запись нуля завершает инициализацию out dx,al ; теперь DSP готов к работе add dx,8 ; порт 22Eh - бит 7 при чтении ; указывает на занятость mov сх,100 ; буфера записи DSP check_port: in al,dx ; прочитать состояние буфера записи, and al,80h ; если бит 7 ноль, jz port_not_ready ; порт еще не готов, sub dx,4 ; иначе: порт 22Аh - чтение данных из DSP in al,dx add dx,4 ; порт снова 22Eh cmp al,0AAh ; проверить, что DSP возвращает 0AAh ; при чтении - это сигнал его готовности ; к работе je good_reset port_not_ready: loop check_port ; повторить проверку на 0AAh 100 раз, bad_reset: stc ; если Sound Blaster не откликается, ret ; вернуться с CF = 1, good_reset: clc ; если инициализация прошла успешно, ret ; вернуться с CF = 0 dsp_reset endp




Начало  Назад  Вперед