В принципе, возможно подобрать константы под ровно 9kHz,но не данной имплементацией-она не только для 3MHz CPU clk, а на диапазон от 2 до 20MHz. Там для частот до 12MHz примерное табличко, на слух,а выше-линейная интерполяция некоей замысловатой функцией. Кроме того, для z80 и 8085-своя отдельная таблица и функция.
Частота между отсчётами может едва-едва плавает из-за моей ленивости -не стал точно nop-ами добивать места где нет обработки склейки байтов. Кроме того, там вывод бордюра и опрос клавиатуры впихнут между байтами. Вообще, драйвер читает стеком по 2 байта, что даёт 8 отсчётов, а обработка их значений развёрнута по 12 "функциям" с абсолютно одинаковым количеством тактов. Стеком-от того, что драйвер, естественно, читает данные из банка квазидиска: все вызовы "фунций" используют pchl.
Если это принципиально, могу попробовать написать более православно. Но имхо, на 3МГц звучит не сильно хуже 2-х битного ковокса.
PS. Посмотрел на сырец, и могу подтвердить, что между отсчётами действительно есть плавание. В принципе, его легко можно прибить nop-ами до 48 тактов, даже момент с выводом бордюра.
Для любознательных:
Код:
PLBYTE MACRO _reg,_lbl1,_lbl2,_brdrw
mov a,_reg
rlc
rlc
ani 1100b
DB (ori)
_lbl1: DB 0 ; 11B
PL_VOL CPUWte ; 32 cycles
mov a,_reg
rlc
rlc
ani 11B
sta _lbl2
mov a,_reg
PL_VOL CPUWte ; 48 cycles
mov a,_reg
rrc
rrc
mov _reg,a
IFNB <_brdrw>
out D30PB
EndIF
PL_VOL CPUWte ; 24/36 cycles
IFNB <_brdrw>
mov a,_reg
ani 1
out D30PB
EndIF
mov a,_reg
rrc
rrc
mov _reg,a
PL_VOL CPUWts ; 24 cycles
EndM
Прикинул: PL_VOL занимает 192 + (32 * CPUWte) тактов. Для 3MHz CPUWte=3, что для наихудшего из случаев 24 vs 48 cycles даёт 12% качание (6% девиации) несущей. Наверное, стоит всё-таки пробить NOP-ами в следующей версии дров.