/* **************************************************************************************************** * FM_MODULATION.ASM -FM modulation using common square wavetable * * * * Developed for the 21161 EZ-KIT Lite Evaluation Board * * * * * * Based on Sec.8.1.3 of Introduction to Signal Processing * * By S. J. Orfanidis - 1996, Prentice-Hall * * ISBN 0-13-209172-0 * * * * * * I/O equations: F(n) = c0 + Am * square(*fm*t) * * y(n) = square(F(n)*n) * * * * For each input sample, the sample processing algorithm does the following: * * generated AM carrier, A = square(fc*t) * * y = A * x or y = A * square(f*t) * * * * Why use frequency modulation? * * You can develop complex waveforms with rich sounds for synthesis applications by generating * * frequency modulated signals, then combine them with other amplitude and frequency modulated * * signals. * * * * * *******************************************************************************************************/ /* ADSP-21161 System Register bit definitions */ #include "def21161.h" .GLOBAL Frequency_Modulation; .GLOBAL Init_AM_Buffers; .GLOBAL select_modulator_freq; .GLOBAL select_signal_frequency; //.EXTERN Left_Channel_In1; //.EXTERN Right_Channel_In1; //.EXTERN Left_Channel_Out0; //.EXTERN Right_Channel_Out0; .section /dm fre_modu; /* AM Control Knobs */ #define WaveSize 4000 /* sinusoidal wavetable */ #define Am 30 /* Am = 0.30 * c0 */ #define A 0x2d410000 /* A = 0.50/sqrt(2) = signal amplitude */ .var square[WaveSize] = "squartbl.dat"; /* min frequency f1 = fs/WaveSize = 48k/4k = 12 Hz */ /* load one period of the wavetable */ .var cm = 1; /* fm = cm * fs/D = 2 Hz */ .var c0 = 100; /* signal freq f0 = c0 * f1 = 200 Hz */ .var AM_rate = 6; .var wavetbl_counter = 0x00000000; .var IRQ1_counter = 10; .var IRQ2_counter = 10; /* ------------------------------------PROGRAM MEMORY CODE---------------------------------------*/ .section /pm pm_code; Init_AM_Buffers: B0 = square; /* pointer for signal generator */ L0 = @square; /* get size of sine table lookup */ M0 = 1; B1 = square; /* pointer for signal generator */ L1 = @square; /* get size of sine table lookup */ M1 = 1; RTS; Init_AM_Buffers.end: /* //////////////////////////////////////////////////////////////////////////////////////////// */ /* */ /* AM Modulation Generator */ /* */ /* //////////////////////////////////////////////////////////////////////////////////////////// */ Frequency_Modulation: /* combine both left and right input samples together into 1 signal */ r0 = dm(Left_Channel_In1); /* left input sample */ r1 = dm(Right_Channel_In1); /* right input sample */ r0 = ashift r0 by -1; /* scale signal by 1/2 for equal mix */ r1 = ashift r1 by -1; /* scale signal by 1/2 for equal mix */ r0 = r0 + r1; /* 1/2xL(n) + 1/2 xR(n) */ test_wav_update: /* update sine value from lookup table? Update every 6 SPORT rx interrupts */ /* frequency = 6 * c * 4000 / fs = 96000 /48k = ? sec */ r11 = DM(AM_rate); /* count up to 80 interrupts */ r10 = DM(wavetbl_counter); /* get last count from memory */ r10 = r10 + 1; /* increment preset */ comp (r10, r11); /* compare current count to max count */ if ge r10 = r10 - r10; /* if count equals max, reset to zero and start over */ DM(wavetbl_counter) = r10; /* save updated count */ r12 = pass r10; /* test for wave count 0? */ if eq jump update_wavetbl_ptr; /* if you are here, reuse same wavetable values for now */ jump FM_done; /* if necessary, calculate updated pointer to wavetables */ update_wavetbl_ptr: /* Calculate Am * square(fm*t) */ m0 = DM(cm); /* desired increment cm - frequency f = cm x fs / WaveSize */ r1 = Am; /* Amplitude */ r2 = dm(i0, m0); /* get next value in wavetable */ r3 = r1 * r2 (SSFR); /* r3 = Am * square(fm*t) */ /* Calculate carrier frequency F(n) = c = c0 + Am * square(fm*t), or c = c0 + x(n) */ r4 = DM(c0); r5 = r3 + r4; /* Calculate FM-modulated sinusoid, where r6 = y(n) = A * square(fm*t) */ m1 = r5; /* desired increment c - frequency f = c x fs / WaveSize */ r1 = A; r2 = dm(i1, m1); /* get next value in wavetable */ r6 = r1 * r2 (SSFR); /* r6 = y(n) = A * square(fm*t)) */ FM_done: r6 = ASHIFT r6 by -5; /* saves your ears when using headphones */ /* write output sample to AD1836 Master Codec channels */ dm(Left_Channel_Out0) = r6; /* left output sample */ dm(Right_Channel_Out0) = r6; /* right output sample */ rts; Frequency_Modulation.end: ////////////////////////////////////////////////////////////////////////////////////////// /* ------------------------------------------------------------------------------------ */ /* */ /* IRQ2 Pushbutton Interrupt Service Routine */ /* */ /* This routine allows the user to modify flanger width and rate presets. */ /* */ /* Default before 1st IRQ push: */ /* 12th Pushbutton Press: Reverts back to 1st Pushbutton Press */ /* */ /* The pushbutton setting is shown by the active LED setting, all others are off */ /* ------------------------------------------------------------------------------------ */ select_modulator_freq: bit set mode1 SRRFH; /* enable background register file */ NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!! */ r13 = 12; /* number of presets */ r15 = DM(IRQ2_counter); /* get preset count */ r15 = r15 + 1; /* increment preset */ comp (r15, r13); if ge r15 = r15 - r15; /* reset to zero */ DM(IRQ2_counter) = r15; /* save preset count */ r10 = pass r15; /* get preset mode */ if eq jump modulator_settings_2; /* check for count == 0 */ r10 = r10 - 1; if eq jump modulator_settings_3; /* check for count == 1 */ r10 = r10 - 1; if eq jump modulator_settings_4; /* check for count == 2 */ r10 = r10 - 1; if eq jump modulator_settings_5; /* check for count == 3 */ r10 = r10 - 1; if eq jump modulator_settings_6; /* check for count == 5 */ r10 = r10 - 1; if eq jump modulator_settings_7; /* check for count == 5 */ r10 = r10 - 1; if eq jump modulator_settings_8; /* check for count == 6 */ r10 = r10 - 1; if eq jump modulator_settings_9; /* check for count == 7 */ r10 = r10 - 1; if eq jump modulator_settings_10; /* check for count == 8 */ r10 = r10 - 1; if eq jump modulator_settings_11; /* check for count == 9 */ r10 = r10 - 1; if eq jump modulator_settings_12; /* check for count == 10 */ modulator_settings_1: /* count therefore, is == 11 if you are here */ r14 = 1; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3E; /* turn on Flag4 LED */ bit set ustat1 0x01; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_2: r14 = 2; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3D; /* turn on Flag5 LED */ bit set ustat1 0x02; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_3: r14 = 4; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3B; /* turn on Flag6 LED */ bit set ustat1 0x04; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_4: r14 = 8; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x37; /* turn on Flag7 LED */ bit set ustat1 0x08; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_5: r14 = 16; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x2F; /* turn on Flag8 LED */ bit set ustat1 0x10; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_6: r14 = 32; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x1F; /* turn on Flag9 LED */ bit set ustat1 0x20; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_7: r14 = 64; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3E; /* turn on Flag5 LED */ bit set ustat1 0x01; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_8: r14 = 128; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3D; /* turn on Flag5 LED */ bit set ustat1 0x02; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_9: r14 = 256; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x3B; /* turn on Flag6 LED */ bit set ustat1 0x04; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_10: r14 = 512; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x37; /* turn on Flag7 LED */ bit set ustat1 0x08; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_11: r14 = 1024; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x2F; /* turn on Flag8 LED */ bit set ustat1 0x10; dm(IOFLAG)=ustat1; jump done_FM_freq_change; modulator_settings_12: r14 = 2048; DM(cm) = r14; ustat1=DM(IOFLAG); bit clr ustat1 0x1F; /* turn on Flag9 LED */ bit set ustat1 0x20; dm(IOFLAG)=ustat1; done_FM_freq_change: rti(db); bit clr mode1 SRRFH; /* switch back to primary register set */ nop; select_modulator_freq.end: /* ------------------------------------------------------------------------------------ */ /* */ /* IRQ1 Pushbutton Interrupt Service Routine */ /* */ /* */ /* Default before 1st IRQ push: Delay = 20.83 msec */ /* 7th Pushbutton Press: Reverts back to 1st Pushbutton Press */ /* */ /* The pushbutton setting is shown by the inactive LED setting, all others are on */ /* (reverse of IRQ1 LED settings, which show lit LED for setting #) */ /* ------------------------------------------------------------------------------------ */ select_signal_frequency: bit set mode1 SRRFH; /* enable background register file */ NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!! */ r13 = 12; /* number of presets */ r15 = DM(IRQ1_counter); /* get preset count */ r15 = r15 + 1; /* increment preset */ comp (r15, r13); if ge r15 = r15 - r15; /* reset to zero */ DM(IRQ1_counter) = r15; /* save preset count */ r10 = pass r15; /* get preset mode */ if eq jump frequency_settings_2; /* check for count == 0 */ r10 = r10 - 1; if eq jump frequency_settings_3; /* check for count == 1 */ r10 = r10 - 1; if eq jump frequency_settings_4; /* check for count == 2 */ r10 = r10 - 1; if eq jump frequency_settings_5; /* check for count == 3 */ r10 = r10 - 1; if eq jump frequency_settings_6; /* check for count == 4 */ r10 = r10 - 1; if eq jump frequency_settings_7; /* check for count == 5 */ r10 = r10 - 1; if eq jump frequency_settings_8; /* check for count == 6 */ r10 = r10 - 1; if eq jump frequency_settings_9; /* check for count == 7 */ r10 = r10 - 1; if eq jump frequency_settings_10; /* check for count == 8 */ r10 = r10 - 1; if eq jump frequency_settings_11; /* check for count == 9 */ r10 = r10 - 1; if eq jump frequency_settings_12; /* check for count == 10 */ frequency_settings_1: /* count therefore, is == 11 if you are here */ r14 = 50; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3E; /* turn off Flag4 LED */ bit clr ustat1 0x01; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_2: r14 = 100; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3D; /* turn off Flag5 LED */ bit clr ustat1 0x02; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_3: r14 = 150; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3B; /* turn off Flag6 LED */ bit clr ustat1 0x04; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_4: r14 = 200; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x37; /* turn off Flag7 LED */ bit clr ustat1 0x08; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_5: r14 = 300; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x2F; /* turn off Flag8 LED */ bit clr ustat1 0x10; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_6: r14 = 400; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x1F; /* turn off Flag9 LED */ bit clr ustat1 0x20; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_7: /* count therefore, is == 5 if you are here */ r14 = 500; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3E; /* turn off Flag4 LED */ bit clr ustat1 0x01; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_8: r14 = 600; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3D; /* turn off Flag5 LED */ bit clr ustat1 0x02; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_9: r14 = 800; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x3B; /* turn off Flag6 LED */ bit clr ustat1 0x04; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_10: r14 = 1000; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x37; /* turn off Flag7 LED */ bit clr ustat1 0x08; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_11: r14 = 1200; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x2F; /* turn off Flag8 LED */ bit clr ustat1 0x10; dm(IOFLAG)=ustat1; jump exit_frequency_tweak; frequency_settings_12: r14 = 1600; DM(c0) = r14; ustat1=DM(IOFLAG); bit set ustat1 0x1F; /* turn off Flag9 LED */ bit clr ustat1 0x20; dm(IOFLAG)=ustat1; exit_frequency_tweak: rti(db); bit clr mode1 SRRFH; /* switch back to primary register set */ nop; select_signal_frequency.end: