I2S emulation and DDS implementation with interrupt latency align and interpolation to 16-bit resolution - this is the most interesting in this project.

` ;4 address store`

DDS: lds ZL,TCNT1L ;2 TCNT1L = 5..8

ldi ZH,high(JmpTab) ;1

ijmp ;2

.org (PC + 0x100) & 0xFF00 ;align to page

JmpTab: nop ; dummy

nop ; dummy

nop ; dummy

nop ; dummy

nop ; dummy

nop ;0/1 TCNT1L = 5

nop ;0/1 TCNT1L = 6

nop ;0/1 TCNT1L = 7

; TCNT1L = 8

in tsreg,SREG ;10/13 save status register

out SPDR,SinH ;1 ---> load DAC L high byte

add APhaseK,AFreqK ;1 Phase(0..33) = Phase(0..33) + Freq(0..31)

adc APhaseL,AFreqL ;1

adc APhaseM,AFreqM ;1

adc APhaseN,AFreqN ;1

adc APhaseP,zero ;1

mov ZL,APhaseN ;1 ZL = wa (word address)

mov r0,APhaseM ;1 r0 = dx

sbrc APhaseP,0 ;2/1 if(Phase.24 == 0)

com ZL ;0/1 wa = !wa

sbrc APhaseP,0 ;2/1 if(Phase.24 == 0)

com r0 ;0/1 dx = !dx

ldi ZH,high(LUT) ;1 ZH = table base (low(LUT) = 0)

add ZL,ZL ;1 offset * 2 (word offset)

adc ZH,zero ;1

ldi SinH,44 ;1

sts OCR1BL,SinH ;2

out SPDR,SinL ;19 ---> load DAC L low byte

ld SinL,Z+ ;2 SinL = lo sin[x]

ld SinH,Z+ ;2 SinH = hi sin[x]

ld r1,Z ;2 r1 = lo sin[x + 1]

sub r1,SinL ;1 r1 = dA

mul r1,r0 ;2 r1,r0 = dA * dx

rol r0 ;1 C = 1 if r0.7 == 1

adc SinL,r1 ;1 SinH:SinL = sin[x] + round(r1:r0 / 256)

adc SinH,zero ;1 SinH:SinL = A

sbrs APhaseP,1 ;2/1

rjmp ph_cd1 ;0/2 jump if Phase.25 == 0

ph_ab1: com SinL ;1/0 SIN > 0, data line has NOT gate,

com SinH ;1/0 SinH:SinL = !SinH:SinL

rjmp ph_ad1 ;2/0

ph_cd1: sec ;0/1

sbc SinL,zero ;0/1 SIN < 0, data line has NOT gate,

sbc SinH,zero ;0/1 SinH:SinL = SinH:SinL - 1

ph_ad1: out SPDR,SinH ;38 ---> load DAC R high byte

add BPhaseK,BFreqK ;1 Phase(0..33) = Phase(0..33) + Freq(0..31)

adc BPhaseL,BFreqL ;1

adc BPhaseM,BFreqM ;1

adc BPhaseN,BFreqN ;1

adc BPhaseP,zero ;1

mov ZL,BPhaseN ;1 ZL = wa (word address)

mov r0,BPhaseM ;1 r0 = dx

sbrc BPhaseP,0 ;2/1 if(Phase.24 == 0)

com ZL ;0/1 wa = !wa

sbrc BPhaseP,0 ;2/1 if(Phase.24 == 0)

com r0 ;0/1 dx = !dx

ldi ZH,high(LUT) ;1 ZH = table base (low(LUT) = 0)

add ZL,ZL ;1 offset * 2 (word offset)

adc ZH,zero ;1

ldi SinH,81 ;1

sts OCR1BL,SinH ;2

out SPDR,SinL ;56 ---> load DAC R low byte

ld SinL,Z+ ;2 SinL = lo sin[x]

ld SinH,Z+ ;2 SinH = hi sin[x]

ld r1,Z ;2 r1 = lo sin[x + 1]

sub r1,SinL ;1 r1 = dA

mul r1,r0 ;2 r1,r0 = dA * dx

rol r0 ;1 C = 1 if r0.7 == 1

adc SinL,r1 ;1 SinH:SinL = sin[x] + round(r1:r0 / 256)

adc SinH,zero ;1 SinH:SinL = A

sbrs BPhaseP,1 ;2/1

rjmp ph_cd2 ;0/2 jump if Phase.25 == 0

ph_ab2: com SinL ;1/0 SIN > 0, data line has NOT gate,

com SinH ;1/0 SinH:SinL = !SinH:SinL

rjmp ph_ad2 ;2/0

ph_cd2: sec ;0/1

sbc SinL,zero ;0/1 SIN < 0, data line has NOT gate,

sbc SinH,zero ;0/1 SinH:SinL = SinH:SinL - 1

ph_ad2: out SREG,tsreg ;1 restore status register

reti ;4

;89/92 total