/************************************************************** File Name: Viterbi.asm Date Modified: 6/23/01 BJM Description: ADSP-2192 single core subroutine that implements the 1/2 rate GSM soft decision Viterbi decoder. Assumptions: The class 1 bits are encoded with the 1/2 rate convolutional code defined by the polynomials: G0 = 1 + D3+ D4 G1 = 1 + D + D3+ D4 Encoded outputs are transmitted as signed antipodal analog signals. They are recieved at the decoder and quantized. The quantized number is represented in a 2's compliment giving the range of -8 to 7. The process of quantizing a binary analog signal with a multi-bit qunatizer is called soft decision. This soft decision is represented by the array 'SOFT_DEC_INPUT' Registers Affected: I0,I1,I2,I3,I4 M0,M1,M2,M3,M4,M5,M6,M7 L0,L1,L2,L3,L4 B1,B3,B4 AX0,AX1,AY0,AY1 AR,AF,SR,SI,SE MX0 Cycle Count: 30751 Cycles Memory Usage: Instructions Words (24-bits): 107 instruction words Data Words (16 or 24-bits): 2*N_out = Number of soft decisions (16-bit) N_out = Number of state transitions (16-bit) 16 = Number of New and Old metrics (16-bit) N_Words = Decoded output of GSM frame (16-bit) 8 = Metric Table (16-bit) Notes: **************************************************************/ #define N_out 189 #define N_words 12 #define N_mod_16 13 /* DM data */ .section/data data1; .VAR soft_dec_input[2*N_out] = "gsm_rec.dat"; .VAR state_trans[N_out]; .VAR old_acc_metric[16]; .VAR new_acc_metric[16]; .VAR decoded_output[N_words+4]; .VAR met_table[8]; /* PM interrupt vector code */ .section/pm IVreset; JUMP start; NOP; NOP; NOP; /* Interupt vector table */ /* Program memory code */ .section/pm program; start: I0 = soft_dec_input; /* Initialize soft_dec_input pointer */ L0 = 0; /* Initialize for modulo addressing */ I1 = old_acc_metric; /* Initialize old_acc_metric pointer */ L1 = length(old_acc_metric); /* Initialize old_acc_metric circular buffer */ AX0 = I1; reg(B1) = AX0; /* Initialize pointer to old_acc_metric */ I2 = state_trans; /* Initialize state_trans pointer */ L2 = 0; /* Initialize for modulo addressing */ I3 = met_table; /* Initialize met_table pointer */ L3 = length(met_table); /* Initialize met_table circular buffer */ AX0 = I3; reg(B3) = AX0; /* Initialize pointer to met_table */ I4 = new_acc_metric; /* Initialize new_acc_metric pointer */ L4 = length(new_acc_metric); /* Initialize new_acc_metric circular buffer */ AX0 = I4; reg(B4) = AX0; /* Initialize pointer to new_acc_metric */ M0 = -8; M1 = 1; M2 = -16; M3 = 0; M4 = 8; M5 = -7; M6 = -8; M7 = -1; SE = 1; /* Setup bit shift */ SI = 0X8000; SR0 = 0; SR1 = 0; CNTR = 16; DO zero_metric UNTIL CE; zero_metric: dm(I1,M1) = M3; /* Initialize accumulated metric array */ CNTR = N_out; /* FOR (k=0; k> Bit_Pos */ MR2 = AR, AR = MR0 AND AY1; SR = LSHIFT MR1 by - 3(LO); SE = AR; AR = TSTBIT 0 OF SR0; SI = AR; SR = LSHIFT SI (LO); AR = AX0 OR SR0; AX0 = AR; AR = MR0 -1; /* Decoded_output |= ((State & 8) >> 3) << (k & 15) */ MR0 = AR; state_bits: MR1 = MR2; /* State = new_acc_metric */ MX0 = 16; dm(I3,M1) = AX0; trace_back: AX0 = 0; looping: JUMP looping; /* Loop upon itself */