Прикинул код для воспроизведения семплов - то, от чего придётся отталкиваться. Всё выглядит не так страшно, как казалось поначалу.
Код:
DAC EQU #####
CMD EQU #####
play_sample:
lxi h, 0 ; регистр стека будет использоваться
dad sp ; не по-назначению, поэтому сохраняем его
shsl spsav
lhld sample_start ; получаем адрес начала семпла
mvi e, 0 ; DE - младшие 16 бит 24-битной "фазы"
mov d, l
mov c, h ; C - старшие 8 бит 24-битной "фазы"
lhld sample_end ; получаем адрес конца семпла
mov b, h ; адрес конца семпла должен быть
; выровнен по концу 256-байтного блока!
; т.е. адрес последнего байта семпла
; должен всегда быть XXFFh
; это даёт возможность проверки границы
; одним 8-разрядным сравнением
lhld pitch ; значение, определяющее высоту тона
; воспроизведения семпла. к примеру,
; если оно равно 100h, семпл воспроизводится
; побайтно, если равно 200h - семпл
; воспроизводится через один байт
; если равно 80h - семпл воспроизводится
; в два раза медленнее (каждый отсчёт
; выводится дважды)
sphl ; SP будет использован для хранения
; этой величины, чтобы всё было
; на регистрах
loop:
in CMD ; 10 ; это "заглушка" проверки того,
ora a ; 4 ; что надо прекращать воспроизводить ноту
jm over ; 10
xchg ; 4 ; складываем младшие 16 разрядов "фазы"
dad sp ; 10 ; со значением pitch
xchg ; 4 ; возвращаем результат в DE
mov a, c ; 4 ; прибавляем перенос к старшим 8 разрядам
aci 0 ; 7 ; которые хранятся в регистре C
mov c, a ; 4
mov l, d ; 4 ; старшие 16 разрядов "фазы" - это адрес
mov h, c ; 4 ; очередного отсчёта семпла для вывода в ЦАП
cmp b ; 4 ; проверяем, что семпл ещё не закончился
jnc over ; 10 ; (про выравнивание семпла написано выше)
; это то самое место, где хорошо экономятся
; такты
mov a, m ; 7 ; получаем значение текущего отсчёта
out DAC ; 10 ; выводим его в ЦАП
jmp loop ; 10 ; повторяем цикл
over:
lhld spsav
sphl
ret
spsav: dw 0
sample_start: dw 0
sample_end: dw 0
pitch: dw 0
end
За счёт некоторого количества фокусов цикл воспроизведения семпла занимает 106 тактов (если с тактами не напутал и если в коде нет ошибок), что при тактовой 2 Мгц даёт частоту дискретизации 18867 Гц, а при тактовой 2,5 Мгц - 23584 Гц.
Кстати не помню XRA A - чистит бит переноса или нет. Если не чистит,
то можно выиграть три такта на сложении переноса:
Код:
xra a ; 4 ; прибавляем перенос к старшим 8 разрядам
adc c ; 4 ; которые хранятся в регистре C
mov c, a ; 4
Учитывая, что у перкуссиям питч не нужен - всякие хэты можно выдавать и на более высокой частоте.