/* /////////////////////////////////////////////////////////////////////////////////// / talkthru.asm / / / / Receives input from the AD1836 internal ADCs via the ADSP-21161 serial port / / (SPORT0), and transmits the data back to the AD1836 internal DACs (SPORT2). / / / / The samples from the AD1836 are 24 bit and are left-justified in the upper / / 24-bits of the the 32-bit word (timeslot). No shifting of the data is required / / in order to preserve the sign of the samples when they are converted to / / floating point numbers, as the audio data is already in the assumed 1.31 format./ / The values are also scaled to the range +/-1.0 with the integer to float / / conversion (f0 = float r0 by r1). / /////////////////////////////////////////////////////////////////////////////////// */ /* ADSP-21161 System Register bit definitions */ #include "def21161.h" /*----------------------------------------------------------------------------------*/ .section /pm pm_data; //define your user program memory variables here .section /dm dm_data; //define your user data memory variables here //w tablicy sin_coeff znajduja sie wspolczynniki wielomianu aproksymujacego sinusoide .VAR sin_coeff[5] = 0x32570A3D, /* 3.140625 */ 0x0052FFFF, /* 0.02026367 */ 0xAACBFF47, /* -5.325196 */ 0x08B70011, /* 0.5446778 */ 0x1CCE0008; /* 1.800293 */ //przechowanie rezultatow obliczania wartosci pojedynczych funkcji sinus .VAR SIN_Result1; .VAR SIN_Result2; //sum1 i sum2 przechowuja aktualne fazy sinusow .var sum1 = 0x00000000; .var sum2 = 0x00000000; //hertz1 i hertz2 przechowuja czestotliwosci sinusow skladajacych sie na ton dtmf //domyslnie ton odpowiadajacy cyfrze "1" .var hertz1 = 0x000004B9; .var hertz2 = 0x000002B9; //liczniki wcisniec przyciskow uruchamiajacych przerwania .var IRQ2_counter; .var IRQ1_counter; //zmienna sygnalizujaca uruchomienie zapetlonego odtwarzania tonow dtmf .var loop_init = 0; //zawiera wartosc licznika czasu w zapetlonym odtwarzaniu dtmf .var loop_counter = 0; //zaiera wartosc licznika wskazujacego ktory ton w petli ma zostac odtworzony .var tone_counter = 0; .section /pm pm_code; .EXTERN RX_left_flag; .EXTERN Left_Channel_In0; .EXTERN Right_Channel_In0; .EXTERN Left_Channel_In1; .EXTERN Right_Channel_In1; .EXTERN Left_Channel_Out0; .EXTERN Right_Channel_Out0; .EXTERN Left_Channel_Out1; .EXTERN Right_Channel_Out1; .EXTERN Left_Channel_Out2; .EXTERN Right_Channel_Out2; .EXTERN Left_Channel_AD1852; .EXTERN Right_Channel_AD1852; .GLOBAL process_audio; .GLOBAL user_code_init; //ponizsze funkcje sa globalne aby byl do nich dostep w pliku ISR_table.asm .GLOBAL dtmf_generator; .GLOBAL dtmf_loop; user_code_init: /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* insert your initialization code for circular (delay) buffers */ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ rts; user_code_init.end: /* //////////////////////////////////////////////////////////////////////////////// * * audio processing routine * * //////////////////////////////////////////////////////////////////////////////// */ //funkcja pracujaca w petli process_audio: /* loop back 'non-processed' ADC0/ADC1 data to DAC0, DAC2, and external AD1852 DAC */ r0 = dm(Left_Channel_In0); dm(Left_Channel_Out1) = r0; r0 = dm(Right_Channel_In0); dm(Right_Channel_Out1) = r0; r0 = dm(Left_Channel_In1); dm(Left_Channel_Out2) = r0; dm(Left_Channel_AD1852) = r0; r0 = dm(Right_Channel_In1); dm(Right_Channel_Out2) = r0; dm(Right_Channel_AD1852) = r0; /* now let's process ADC1 L/R channel data and send results to DAC1 L/R channels */ r1 = -31; /* scale the input samples to the range of +/-1.0 */ r0 = DM(Left_Channel_In1); /* get left AD1836 ADC0 input sample */ r2 = DM(Right_Channel_In1); /* get right AD1836 ADC0 input sample */ f0 = float r0 by r1; /* convert to floating point */ f2 = float r2 by r1; /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* insert floating point processing algorithm here */ /* f0 = left channel in/out, f2 = right channel in/out */ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ r1 = 31; /* scale the result back up to MSBs */ r0 = fix f0 by r1; /* convert back to fixed point */ r2 = fix f2 by r1; //generator DTMF zostal zrealizowany w arytmetyce staloprzecinkowej //blok kodu odpowiadajacy za wybieranie tonowe przyciskami FLAG0 - FLAG3 //takie wybieranie jest nadrzedne nad praca krokowa lub odtwarzaniem w petli r8 = dm(hertz1); //pobranie czestotliwosci r9 = dm(hertz2); r12 = FLAGS; //pobranie zawartosci rejestru flag r11 = 0x1; //wartosc do porownania comp(r12,r11); //porownanie - jezeli rowne (przycisk FLAG0 wcisniety) to skok if eq JUMP push_tone_0; //skok do bloku odtwarzajacego ton cyfry "1" r11 = 0x2; /*kolejne porowniania wykonywane sa analogicznie */ comp(r12,r11); /*az do wykorzystania wszystkich mozliwosci 10 cyfr*/ if eq JUMP push_tone_1; r11 = 0x3; comp(r12,r11); if eq JUMP push_tone_2; r11 = 0x4; comp(r12,r11); if eq JUMP push_tone_3; r11 = 0x5; comp(r12,r11); if eq JUMP push_tone_4; r11 = 0x6; comp(r12,r11); if eq JUMP push_tone_5; r11 = 0x7; comp(r12,r11); if eq JUMP push_tone_6; r11 = 0x8; comp(r12,r11); if eq JUMP push_tone_7; r11 = 0x9; comp(r12,r11); if eq JUMP push_tone_8; r11 = 0xA; comp(r12,r11); if eq JUMP push_tone_9; if ne JUMP sine_routine1; //jezeli zaden przycisk nie jest wcisniety skok do generacji sinusa //ponizej znajduja sie bloki odpowiadajace za ustawianie czestotliwosci //i zapalnaie odpowiednich LEDow na potrzeby wybierania tonu z przyciskow FLAG0 - FLAG2 push_tone_0: r14 = 0x2B9; DM(hertz1) = r14; //ustawienie i zapisanie czestotliwosci obu tonow skladowych r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); //pobranie zawartosci rejestru flag zwiazanych z LEDami bit clr ustat1 0x3E; //ustawienie LEDOW - w tym przypadku (000001) bit set ustat1 0x01; dm(IOFLAG)=ustat1; //ponowny zapis do rejestru jump sine_routine1;//skok do generacji sinusa push_tone_1: r14 = 0x2B9; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3D; bit set ustat1 0x02; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_2: r14 = 0x2B9; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3C; bit set ustat1 0x03; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_3: r14 = 0x302; DM(hertz1) = r14; r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3B; bit set ustat1 0x04; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_4: r14 = 0x302; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3A; bit set ustat1 0x05; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_5: r14 = 0x302; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x39; bit set ustat1 0x06; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_6: r14 = 0x354; DM(hertz1) = r14; r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x38; bit set ustat1 0x07; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_7: r14 = 0x354; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x37; bit set ustat1 0x08; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_8: r14 = 0x354; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x36; bit set ustat1 0x09; dm(IOFLAG)=ustat1; jump sine_routine1; push_tone_9: r14 = 0x3AD; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3F; bit set ustat1 0x00; dm(IOFLAG)=ustat1; jump sine_routine1; //funkcja obliczajaca wartosc funkcji sin sine_routine1: R9 = dm(sum1); //pobranie dotychczasowej wartosci sinusa R10 = dm(hertz1); //pobranie czestotliwosci R12 = 0x00015D86; //zapisanie wartosci potrzebnej do obliczenia przyrostu fazy na podstawie czestotliwosci MRF = R10*R12(UUF); //mnozenie dwoch liczb unsigned R11 = MR0F; //pobranie wyniku R9 = R11 + R9; //dodanie przyrostu fazy do poprzednio zapisanej fazy zakumulowanej dm(sum1) = R9; //wpisanie obecnaej wartosci fazy do pamieci I3 = sin_coeff; //wskaznik do tablicy ze wspolczynnikami M3 = 1; //ustawinie parametrow zwiazanych z obsluga indeksowanie tablicy L3 = 0; R10 = 0x40000000; R11 = R9; R8 = R9 AND R10; // sprawdzenie czy wynik znajduje sie w 2 lub 4 cwiartce IF NE R11 = -R9; // jezeli tak to negacja R12 = 0x7FFFFFFF; R11 = R11 AND R12; //usuniecie bitu znaku R13 = R11; MRB = R11*R13 (SSFR), R14 = DM(I3,M3);// MRB = x*x - podniesienie do kwadratu i pobranie pierwszego wspolczynnika MRF = R14*R13 (SSF), R14 = DM(I3,M3); // wymnazanie przez wspolczynniki LCNTR = 4, DO sine_approx1 UNTIL LCE; R15 = MR1B; MRF = MRF + R14*R15 (SSF); /* MRF = C1*x + C2*x^^2 + C3*x^^3 + C4*x^^4 + C5*x^^5 */ MRB = R11*R15 (SSFR); sine_approx1: R14 = DM(I3,M3); R7 = MR1F; R8 = MR0F; R7 = ASHIFT R7 BY 3; // konwersja do formatu 1.31 R7 = R7 OR LSHIFT R8 BY -29; // OR in the upper 3 bits in MR0B as LSBs for R7 */ R7 = PASS R7; IF LT R7 = PASS R12; R9 = PASS R9; IF LT R7 = -R7; //jesli konieczne to negacja DM(SIN_Result1) = R7; //zapisanie rezultatu do pamieci //kolejna funkcja wykonuje dokladnie to samo co poprzednia //lecz dla innej czestotliwoci - drugi ton skladowy dtmf sine_routine2: R9 = dm(sum2); R10 = dm(hertz2); R12 = 0x00015D86; MRF = R10*R12(UUF); R11 = MR0F; R9 = R11 + R9; dm(sum2) = R9; I3 = sin_coeff; M3 = 1; L3 = 0; R10 = 0x40000000; R11 = R9; R8 = R9 AND R10; IF NE R11 = -R9; R12 = 0x7FFFFFFF; R11 = R11 AND R12; R13 = R11; MRB = R11*R13 (SSFR), R14 = DM(I3,M3); MRF = R14*R13 (SSF), R14 = DM(I3,M3); LCNTR = 4, DO sine_approx2 UNTIL LCE; R15 = MR1B; MRF = MRF + R14*R15 (SSF); MRB = R11*R15 (SSFR); sine_approx2: R14 = DM(I3,M3); R7 = MR1F; R8 = MR0F; R7 = ASHIFT R7 BY 3; R7 = R7 OR LSHIFT R8 BY -29; R7 = PASS R7; IF LT R7 = PASS R12; R9 = PASS R9; IF LT R7 = -R7; DM(SIN_Result2) = R7; //zapisanie drugiego wyniku do pamieci /*********************************************************/ /* koniec generacji sinusow */ /*******************************************************/ //dodanie obu wartosci sinusow R8 = DM(SIN_Result1); R9 = DM(SIN_Result2); R11 = ASHIFT R8 BY -1; R12 = ASHIFT R9 BY -1; R10 = R11 + R12; //blok kodu zwiazanego z odtwarzaniem tonow w petli r15 = DM(loop_init); //pobranie wartosci zmiennej loop_init r13 = 1; comp (r15, r13); if ne JUMP loop_done; //jezeli loop_init rozne od 1 t oskok do loop_done r15 = dm(loop_counter); //jezeli loop_init=1 inkrementacja licznika r15 = r15 + 1; r13 = 0x17700; comp (r15, r13); if ne JUMP not_48k; //jezeli licznik nie rowny 48000 przejdz dalej r15 = r15 - r15; dm(loop_counter) = r15; r13 = 9; r15 = dm(tone_counter); //inkrementacja licznika tone_counter r15 = r15 + 1; comp (r15, r13); if gt r15 = r15 - r15; DM(tone_counter) = r15; JUMP loop_label; //skok do loop_label not_48k: dm(loop_counter) = r15; loop_done: rts (db); DM(Left_Channel_Out0) = R10; //wyslanie wyniku dla kanalu lewego do AD1836 Left DAC0 */ DM(Right_Channel_Out0) = R10; // wyslanie wyniku dla kanalu prawego do AD1836 Right DAC0 */ process_audio.end: //koniec funkcji //funkcja uruchamiana po kazdorazowym wcisnieciu przycisku IRQ2 //(wejscie do niej -loop_label- nastepuje rowniez po wcisnieciu przycisku IRQ1 //lecz nie jest to uruchomienie funkcji z przerwania) dtmf_generator: bit set mode1 SRRFH; /* enable background register file */ NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISTER!! */ r13 = 0; DM(loop_init) = r13; r13 = 9; /* liczba nastaw */ r15 = DM(IRQ2_counter); /* pobranie wartosci licznika */ r15 = r15 + 1; /* inkrementacja */ comp (r15, r13); if gt r15 = r15 - r15; /* reset licznika */ DM(IRQ2_counter) = r15; /* zapisanie licznika */ //etykieta do ktorej wykonywany jest skok podczas odtwarzania tonow w petli loop_label: r10 = pass r15; /* pobranie numeru nastawy */ if eq jump tone_0; /* skok do generacji "1" */ r10 = r10 - 1; if eq jump tone_1; /* skok do generacji "2" */ r10 = r10 - 1; if eq jump tone_2; /* skok do generacji "3" */ r10 = r10 - 1; if eq jump tone_3; /* skok do generacji "4" */ r10 = r10 - 1; if eq jump tone_4; /* skok do generacji "5" */ r10 = r10 - 1; if eq jump tone_5; /* skok do generacji "6" */ r10 = r10 - 1; if eq jump tone_6; /* skok do generacji "7" */ r10 = r10 - 1; if eq jump tone_7; /* skok do generacji "8" */ r10 = r10 - 1; if eq jump tone_8; /* skok do generacji "9" */ r10 = r10 - 1; if eq jump tone_9; /* skok do generacji "0" */ //ponizsze bloki sa analogiczne do uzywanych //w odtwarzaniu przyciskami FLAG0 - FLAG2 tone_0: r14 = 0x2B9; DM(hertz1) = r14; r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3E; bit set ustat1 0x01; dm(IOFLAG)=ustat1; jump done; tone_1: r14 = 0x2B9; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3D; bit set ustat1 0x02; dm(IOFLAG)=ustat1; jump done; tone_2: r14 = 0x2B9; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3C; bit set ustat1 0x03; dm(IOFLAG)=ustat1; jump done; tone_3: r14 = 0x302; DM(hertz1) = r14; r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3B; bit set ustat1 0x04; dm(IOFLAG)=ustat1; jump done; tone_4: r14 = 0x302; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3A; bit set ustat1 0x05; dm(IOFLAG)=ustat1; jump done; tone_5: r14 = 0x302; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x39; bit set ustat1 0x06; dm(IOFLAG)=ustat1; jump done; tone_6: r14 = 0x354; DM(hertz1) = r14; r14 = 0x4B9; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x38; bit set ustat1 0x07; dm(IOFLAG)=ustat1; jump done; tone_7: r14 = 0x354; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x37; bit set ustat1 0x08; dm(IOFLAG)=ustat1; jump done; tone_8: r14 = 0x354; DM(hertz1) = r14; r14 = 0x5C5; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x36; bit set ustat1 0x09; dm(IOFLAG)=ustat1; jump done; tone_9: r14 = 0x3AD; DM(hertz1) = r14; r14 = 0x538; DM(hertz2) = r14; ustat1=dm(IOFLAG); bit clr ustat1 0x3F; bit set ustat1 0x00; dm(IOFLAG)=ustat1; jump done; done: r13 = dm(loop_init); r15 = 1; comp(r13, r15); if eq jump loop_done; rti(db); bit clr mode1 SRRFH; /* switch back to primary register set */ nop; dtmf_generator.end: //funkcja uruchamiana przerwaniem z przycisku IRQ1 //powoduje ustawienie lub wyczyszczenie loop_init w zaleznosci od ilosci wcisniec IRQ1 dtmf_loop: bit set mode1 SRRFH; /* enable background register file */ NOP; r13 = 1; /* liczba nastaw */ r15 = DM(IRQ1_counter); /* pobranie wartosci licznika */ r15 = r15 + 1; /* inkrementacja licznika */ comp (r15, r13); if gt r15 = r15 - r15; /* reset */ DM(IRQ1_counter) = r15; /* zapiswartosci licznika do pamieci */ r10 = pass r15; /* pobranie nastawy */ if eq jump loop_stop; r10 = r10 - 1; if eq jump loop_start; loop_start: r14 = 1; DM(loop_init) = r14; jump done_loop; loop_stop: r14 = 0; DM(loop_init) = r14; jump done_loop; done_loop: rti(db); bit clr mode1 SRRFH;/* switch back to primary register set */ nop; dtmf_loop.end: