* * * phaser.asm * * * * Knobs - adjust these values within suggested range for * variations on the effect. * * Patch Name Dry Wet FB Top Bottom Speed * Basic phase 07fffh 07fffh 00000h 0f000h 07ff0h 0008h * Phase w/ FB 07fffh 07fffh 05000h 0f000h 07800h 0006h * Med. phase 07fffh 07fffh 00000h 0f000h 07800h 0020h * Fast phase 07fffh 07fffh 00000h 00000h 07000h 0050h * Invert w/ invert FB 07fffh 08000h 0a000h 0f000h 07400h 0002h * DRY_LEVEL .set 07fffh ; (0 - 07fffh dry signal level) WET_LEVEL .set 07fffh ; (08000h - 7fffh wet signal level) FB_LEVEL .set 01000h ; (08000h - 7fffh regeneration amount) SWEEP_TOP .set 0f000h ; top end of sweep range (0f000 - 0800h) SWEEP_BOT .set 07800h ; bottom end of sweep range (07ff0h - 0900h) SWEEP_SPEED .set 00012h ; rate of sweep (01h - 080h) * * Data storage * SPEED .set 00h ; storage for SWEEP_SPEED param WET .set 01h ; storage for WET_LEVEL DRY .set 02h ; storage for DRY_LEVEL FEEDBACK .set 03h ; storage for FB_LEVEL COEF_HI .set 04h ; coefficient of filter COEF_LO .set 05h ; fractional part of coefficient LX1 .set 06h ; filter states LY1 .set 07h ; . LX2 .set 08h ; . LY2 .set 09h ; . LX3 .set 0ah ; . LY3 .set 0bh ; . LX4 .set 0ch ; . LY4 .set 0dh ; . TMP .set 0eh ; temp register INPUT .set 0fh ; dry input OUTPUT .set 10h ; output of filter chain IOREG .set 11h ; filter in/out reg INC_LO .set 12h ; coefficient inc/dec value LSW INC_HI .set 13h ; ditto but MSW SWEEPDIR .set 14h ; track direction of sweep LOOKUP .set 15h ; lookup table index .include "setup.asm" * * main * main: ssxm ; set sign extension mode spm 1 ; set P shift for Q15 (1 bit left shift ; from P => accum) sovm ; set clipping overflow mode for ; "analog" processing ldpk 8 ; data at 0x400 lalk SWEEP_SPEED ; sweep rate sacl SPEED lalk FB_LEVEL sacl FEEDBACK ; delayed signal feedback mix lalk WET_LEVEL sacl WET ; delayed signal output mix lalk DRY_LEVEL sacl DRY ; straight signal output mix lalk 01000h ; midrange value sacl COEF_HI lack 0 sacl INC_LO sacl INC_HI sacl SWEEPDIR ; initially down in frequency lack 014h ; enable AIC recv interrupts ldpk 0 sacl IMR ldpk 8 ; loop here forever processing interrupts loop: idle b loop ; table of sweep adjustment factors SWEEPTAB: .word 11970 .word 11600 .word 10890 .word 9700 .word 8200 .word 6300 .word 3950 .word 1000 .word 1000 .word 1000 .word 1000 .word 1000 .word 1000 .word 1000 .word 1000 .word 12330 * * rint * * Recv interrupt handler performs all the work. Since there is * no main thread, there is no need to save or restore regs. * * Difference equation is: * * Y = COEF * (X + LY) - LX * * Where: * X = input value * Y = output * LX = last input * LY = last output * rint: ; note: no need to save/restore processor state since ; main thread does absolutely nothing sovm ; read in and store new input value ldpk 0 lac DRR ldpk 8 sfr ; dump lowest 2 junk bits sfr sacl IOREG sacl INPUT ; keep copy of dry input ; do feedback before entering filters lt OUTPUT ; get last output value mpy FEEDBACK pac addh INPUT ; filter input value is ready sach IOREG ; pass to filter both in IOREG and accum ; do first filter section addh LY1 ; add last Y sach TMP lt COEF_HI ; scale sum by COEF mpy TMP pac ; move to accum subh LX1 ; subtract last X sach LY1 ; output Y is ready, save in LY lar AR1,IOREG ; save X in LX sar AR1,LX1 sach IOREG ; pass to next filter ; do first second section addh LY2 ; add last Y sach TMP lt COEF_HI ; scale sum by COEF mpy TMP pac ; move to accum subh LX2 ; subtract last X sach LY2 ; output Y is ready, save in LY lar AR1,IOREG ; save X in LX sar AR1,LX2 sach IOREG ; pass to next filter ; do third filter section addh LY3 ; add last Y sach TMP lt COEF_HI ; scale sum by COEF mpy TMP pac ; move to accum subh LX3 ; subtract last X sach LY3 ; output Y is ready, save in LY lar AR1,IOREG ; save X in LX sar AR1,LX3 sach IOREG ; pass to next filter ; do fourth filter section addh LY4 ; add last Y sach TMP lt COEF_HI ; scale sum by COEF mpy TMP pac ; move to accum subh LX4 ; subtract last X sach LY4 ; output Y is ready, save in LY lar AR1,IOREG ; save X in LX sar AR1,LX4 sach IOREG ; pass to next filter sach OUTPUT ; save filter chain's output value ; do level scaling on direct and wet lt OUTPUT mpy WET ; scale wet signal pac lt INPUT ; get original input value mpy DRY ; scale dry signal apac ; generate composite final output sach TMP lac TMP ; prepare final output for AIC andk 0fffch ; clear lowest 2 bits ldpk 0 sacl DXR ; do output ldpk 8 ; adjust the coefficient rovm ; normal arithmetic lac COEF_LO ; 32 bit add add INC_LO sacl COEF_LO sovm lac COEF_HI addc INC_HI sacl COEF_HI rovm ; see if we hit the upper or lower bounds of the sweep lac SWEEPDIR bz down lalk SWEEP_TOP sub COEF_HI blez adj_inc lack 0 ; gonna start going down in freq sacl SWEEPDIR b reverse down: lalk SWEEP_BOT sub COEF_HI bgz adj_inc lack 1 ; gonna start going up in freq sacl SWEEPDIR reverse: lac SPEED ; reverse the sweep neg ; by swapping sign of speed value sacl SPEED adj_inc: ; adjust the increment value based on region of sweep rsxm lac COEF_HI,4 ; get high nibble into accum high 0-3 sach LOOKUP ssxm lalk SWEEPTAB add LOOKUP tblr TMP ; read the value from table into TMP lt TMP ; multiply adjustment factor mpy SPEED ; by sweep pac sacl INC_LO ; new 32 bit increment value sach INC_HI done: eint ret * * tint * * Timer interrupt - not used. * tint: eint ret * * xint * * AIC xmit interrupt - not used. * xint: eint ret