Ладно, раз всем лениво, раскрою алгоритм, который весьма прост)
В данном случае используется алгоритм генерации синуса посредством рекурсивного цифрового генератора (о чем упоминалось даже в этой теме неоднократно). Многим он больше знаком по алгоритму Герцеля:
D0 = a1 * D1 - D2 + x,
D2 = D1,
D1 = D0,
который является модификацией данного генератора с добавленным возбуждением коэффициентом x. А сам генератор в чистом виде - это:
D0 = a1 * D1 - D2,
D2 = D1,
D1 = D0,
где a1 = 2 * cos (2 * pi * частота / частота_отсчетов),
или же a1 = 2 * cos (2 * pi * k);
Ввиду того, что алгоритм рекурсивный, требуется большая точность (разрядность) чисел. Приемлимой точности даже 16 битами (не говоря уже о 8) на отрезке в пару сот итераций не добиться. Поэтому выбрана разрядность 24 бита.
Далее о коэффициенте a1. Понятно, что ни о каком умножении речи быть не может. Единственный вариант - представить a1 в виде достаточно простого полинома вида 2 * (2^0 + 2^(...) + 2^(...) + ...) и т.д.
Самым простым полиномом, удовлетворяющим периоду близкому к 256, и при этом имеющим близкий к целому числу корень 1/k - это полином 2 * (2^0 - 2^(-11)), что легко представлятся в виде сдвига вправо на 8 + 3 бит, и одного вычетания. Что я и изобразил в своем алгоритме.
Посчитаем 1/k (число отсчетов) для данного полинома.
a1 = 2 * (1 - 2^(-11)) = 1,9990234375
1 / k = 1 / (arccos(a1 / 2) / (2 * pi) = 201.0536,
что является достаточно точным, близким к целочисленному периодом.
Если кого интересует полином для периода 256, то я тоже прикидывал его, у меня получился 2 * (2^0 - 2^(-12) - 2^(-14) + 2^(-18)), что потребует уже целых 3 сдвига и 3 сложения, усложняя код, ведь это все надо в 24-х битной арифметике сдвигать и складывать (ну, младшие части полинома можно и в 16, и даже в 12-битной).
Посчитаем 1/k (число отсчетов) для данного полинома:
a1 = 2 * (1 - 2^(-12) - 2^(-14) + 2^(-18)) = 1,99939727783203125
1 / k = 1 / (arccos(a1 / 2) / (2 * pi) = 255.92,
что уже менее точно, но все же достаточно приемлимо.
Вот вышеприведенный уже код, но с комментариями:
Код:org $8000
LD B,201 ; Длина таблицы синуса 201 байт
LD HL,$8100 ; Адрес таблицы синуса
EXX ;
XOR A ; D0/D1 = $00.00.00
LD H,A ;
LD L,A ;
PUSH HL ; D2 = -$02.00.00
LD IXL,-2 ;
JR LoopIn ; --> LoopIn
;------------------------------- Главный цикл
MLoop:
EXX ;
SBC HL,BC ; A.H.L = A.H.L - LX.B.C
SBC A,IXL ; (D0 = a1*D1 - D2)
LD IXL,D ; Сохранить LX для D2 будущей итерации
;-------------------------------
LoopIn:
; D0/D1 = A.H.L
LD D,A ; D = A (и заодно сохранить A)
ADD A,A ;
SBC A,A ;
LD IXH,A ; A = $00/$FF, в зависимости от знака
LD A,D ; Восстановить A
LD E,H ;
LD B,3 ; DE = (A.H.L >> 8) >> 3 = A.H.L >> 11
RLoop: SRA D ;
RR E ;
DJNZ RLoop ;
POP BC ; Восстановить D2 = LX.B.C
PUSH HL ; Сохранить D1 = (A).H.L
SBC HL,DE ; A.H.L = A.H.L - HX.D.E
LD D,A ;
SBC A,IXH ;
ADD HL,HL ; A.H.L = A.H.L << 1
ADC A,A ; (D0 = a1 * D1)
EXX ; Сохранить A в (HL)+
LD (HL),A ; и цикл
INC L ;
DJNZ MLoop ;
POP AF ; Восстановить стек
RET ; Выход
---------- Post added at 15:21 ---------- Previous post was at 15:19 ----------
Да, начальная амплитуда задается через коэффициент в D2 со знаком минус.

