home *** CD-ROM | disk | FTP | other *** search
- {
- The code below represents a full duplex Adaptive Differential
- Pulse Code Modulation (ADPCM) transcoder. Although
- developed in accordance with ANSI specification T1.301-1987 and
- CCITT G.721 (bis), it has been modified to improve its speed.
-
- The modifications include the removal of the synchronous coding
- adjustment and the tone and transition detectors. These deletions
- should not noticably affect speech-only coding.
-
- An Application Note is available which describes the operation
- of the algorithm in detail. A copy of this Note can be obtained
- from Analog Devices, DSP Division.
-
- Analog Devices American National Consultive Committee
- DSP Division Standards Institute on International
- P.O. Box 9106 1430 Broadway Telephone and Telegraph
- Norwood, Ma 02062-9106 New York, N.Y. 10018
- (617) 461 - 3672
-
- Gordon A. Sterling
- Analog Devices
- DSP Division
- 9/3/88
-
- Calling Parameters
- AR = Companded PCM value (encoder)
- ADPCM I value (decoder)
-
- M0=3; L0=18;
- M1=1; L1=6;
- M2=-1
- L3=0;
- M4=0 L4=6;
- M5=1 L5=2
- M6=-1 L6=5
-
- Return Values
- AR = ADPCM I value (encoder)
- Companded PCM value (decoder)
-
- Altered Registers
- AX0, AX1, AY0, AY1, AF, AR,
- MX0, MX1, MY0, MY1, MR,
- I0, I1, I3, I4, I5, I6
- SI, SR
- M3
-
- Cycle Count
- 437 cycles for encode
- 409 cycles for decode
-
- }
-
- .MODULE Adaptive_Differential_PCM;
-
- .ENTRY ns_adpcm_encode, ns_adpcm_decode;
-
- .VAR/PM/CIRC b_buf[6]; {b coefficients for encode}
- .VAR/PM/CIRC a_buf[2]; {a coefficients for encode}
- .VAR/PM/CIRC b_buf_r[6]; {b coefficients for decode}
- .VAR/PM/CIRC a_buf_r[2]; {a coefficients for decode}
-
- .VAR/DM/CIRC b_delay_r[18]; {dq delay for decode}
- .VAR/DM/CIRC a_delay_r[6]; {sr delay for decode}
- .VAR/DM/CIRC b_delay[18]; {dq delay for encode}
- .VAR/DM/CIRC a_delay[6]; {sr delay for encode}
-
- .VAR/DM/CIRC mult_data[5]; {Predictor immediate data}
-
- .VAR/DM qn_values[10],dq_values[8]; {quantizer and dequantizer data}
- .VAR/DM f_values[12], w_values[8]; {Update coefficient data}
- .VAR/DM a_data[10];
-
- .VAR/DM s_e,s_r,a_ik,dq,p;
- .VAR/DM sez,sl,yu,yl_h,yl_l,y,y_2,ap,p_o,p_o_o,dms,dml,tdp,tr;
- .VAR/DM a_ik_r,dq_r,p_r;
- .VAR/DM yu_r,yl_h_r,yl_l_r,ap_r,p_o_r;
- .VAR/DM p_o_o_r,dms_r,dml_r,tdp_r;
-
- .VAR/DM sp_r; {PCM code word for synchronous adj}
-
- .VAR/DM hld_a_t, hld_b_t, hld_a_r, hld_b_r;
-
- .INIT qn_values: 7, 14, H#3F80,
- 400, 349, 300, 246, 178, 80, H#FF84;
-
- .INIT dq_values : h#F800, 4, 135, 213, 273, 323, 373, 425;
-
- .INIT f_values : -5, 0, 5120, 544,
- 0, 0, 0, 512, 512, 512, 1536, 3584;
-
- .INIT w_values: 65344, 288, 656, 1024, 1792, 3168, 5680, 17952;
-
- .INIT mult_data : H#1FFF, H#4000, h#7E00, H#7FFF, H#FFFE;
-
- .INIT a_data : H#1FFF, 2, 16384, 0, -7, 192, H#3000, H#D000,
- H#D200, H#3C00;
-
- .INIT hld_a_t : ^a_delay;
- .INIT hld_b_t : ^b_delay;
- .INIT hld_a_r : ^a_delay_r;
- .INIT hld_b_r : ^b_delay_r;
-
- .INIT b_buf : 0,0,0,0,0,0; {2.14}
- .INIT a_buf : 0,0; {2.14}
- .INIT b_delay : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; {16.0, 16.0, 0.16}
- .INIT a_delay : 0,0,0,0,0,0; {16.0, 16.0, 0.16}
- .INIT p : 0; {16.0}
- .INIT yu :0; {7.9}
- .INIT yl_h : 0; {7.9}
- .INIT yl_l : 0; {0.16}
- .INIT ap : 0; {8.8}
- .INIT p_o : 0; {16.0}
- .INIT p_o_o : 0; {16.0}
- .INIT dms : 0; {7.9}
- .INIT dml : 0; {5.11}
- .INIT tdp : 0; {16.0}
-
- .INIT b_buf_r : 0,0,0,0,0,0; {2.14}
- .INIT a_buf_r : 0,0; {2.14}
- .INIT b_delay_r : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;{16.0, 16.0, 0.16}
- .INIT a_delay_r : 0,0,0,0,0,0; {16.0, 16.0, 0.16}
- .INIT p_r : 0; {16.0}
- .INIT yu_r :0; {7.9}
- .INIT yl_h_r : 0; {7.9}
- .INIT yl_l_r : 0; {0.16}
- .INIT ap_r : 0; {8.8}
- .INIT p_o_r : 0; {16.0}
- .INIT p_o_o_r : 0; {16.0}
- .INIT dms_r : 0; {7.9}
- .INIT dml_r : 0; {5.11}
- .INIT tdp_r : 0; {16.0}
-
- ns_adpcm_encode:I4=^b_buf; {Set pointer to b-coefficients}
- I5=^a_buf; {Set pointer to a-coefficients}
- I6=^mult_data; {Set pointer to predictor data}
- I1=DM(hld_a_t); {Restore pointer to s_r delay}
- I0=DM(hld_b_t); {Restore pointer to dq delay}
-
- CALL expand; {Expand 8-bit log-PCM to12 bits}
- DM(sl)=AR; {Store linear PCM value in sl}
- CALL predict; {Call s_e and sez predictors}
- AX1=DM(ap);
- AY0=DM(yl_h);
- AX0=DM(yu);
- CALL lima; {Limit ap and compute y}
- DM(y)=AR; {Save y for later updates}
- DM(y_2)=SR1; {Save y>>2 for log and reconst}
- AX0=DM(sl);
- AY0=DM(s_e);
- AY1=SR1, AR=AX0-AY0; {Compute difference signal, d}
- CALL log; {Determine I value from d}
- DM(a_ik)=AR;
- CALL reconst; {Compute dq based ONLY on }
- DM(dq)=AR;
- AY0=DM(s_e);
- AR=AR+AY0; {Compute reconstructed signal}
- DM(s_r)=AR;
-
- DM(I1,M1)=AR, AR=ABS AR; {Convert s_r to floating point}
- SR1=H#4000; {Set SR1 to minimum value}
- SE=EXP AR (HI); {Determine exponent adjust}
- AX0=SE, SR=SR OR NORM AR (HI); {Normalize into SR}
- SR=LSHIFT SR1 BY -9 (HI); {Delete lower bits}
- AY0=11; {Base exponent}
- SR=LSHIFT SR1 BY 2 (HI); {Adjust for ADSP-210x version}
- AR=AX0+AY0; {Compute exponent}
- DM(I1,M1)=AR; {Save exponent}
- DM(I1,M1)=SR1; {Save mantissa}
-
- CALL update_filter; {Update filter if trigger false}
-
- MR0=DM(ap); {Load variables for updating}
- MR1=DM(y);
- MR2=DM(tdp); {Always load MR2 after MR1!}
- MY0=DM(yl_h);
- MY1=DM(yl_l);
- AY0=DM(y);
- MX0=DM(dms);
- MX1=DM(dml);
- CALL functw; {Update variables}
- DM(ap)=AR; {Store updated variables}
- DM(yu)=AX1;
- DM(yl_l)=MY1;
- DM(yl_h)=MY0;
- DM(dms)=MX0;
- DM(dml)=MX1;
-
- AX0=DM(a_ik); {Get I value for return}
- AY0=H#F; {Only 4 LSBs are used}
- AR=AX0 AND AY0; {So mask redundant sign bits}
-
- DM(hld_a_t)=I1; {Save s_r delay pointer}
- DM(hld_b_t)=I0; {Save dq delay pointer}
-
- RTS; {Return to caller}
-
- ns_adpcm_decode:I1=DM(hld_a_r); {Restore s_r delay pointer}
- I0=DM(hld_b_r); {Restore dq delay pointer}
- I4=^b_buf_r; {Set pointer to b-coefficients}
- I5=^a_buf_r; {Set pointer to a-coefficients}
- I6=^mult_data; {Set pointer to predictor data}
-
- SR=LSHIFT AR BY 12 (HI); {Get sign of ADPCM I value here}
- SR=ASHIFT SR1 BY -12 (HI); {Sign extend ADPCM value to 16}
- DM(a_ik_r)=SR1; {Save I value}
- CALL predict; {Call s_e and sez predictor}
- AX1=DM(ap_r);
- AY0=DM(yl_h_r);
- AX0=DM(yu_r);
- CALL lima; {Limit ap and compute y}
- DM(y)=AR;
- DM(y_2)=SR1;
- AY1=DM(y_2);
- AR=DM(a_ik_r);
- CALL reconst; {Compute dq from received I}
- DM(dq_r)=AR;
- AY0=DM(s_e);
- AR=AR+AY0; {Compute reconstructed signal}
- DM(s_r)=AR;
-
- DM(I1,M1)=AR, AR=ABS AR; {Make s_r floating point}
- SR1=H#4000; {Set SR1 to minimum value}
- SE=EXP AR (HI); {Determine exponent adjust}
- AX0=SE, SR=SR OR NORM AR (HI); {Normalize value}
- SR=LSHIFT SR1 BY -9 (HI); {Remove LSBs per spec}
- AY0=11; {Base exponent}
- SR=LSHIFT SR1 BY 2 (HI); {Adjust for ADSP-210x version}
- AR=AX0+AY0; {Compute exponent}
- DM(I1,M1)=AR; {Store exponent}
- DM(I1,M1)=SR1; {Store mantissa}
-
- CALL update_filter_r; {Update filter if trigger false}
-
- AY0=DM(y); {Load uariables for updating}
- MY1=DM(yl_l_r);
- MY0=DM(yl_h_r);
- MR0=DM(ap_r);
- MR1=DM(y);
- MR2=DM(tdp_r); {Always load MR2 after MR1!}
- MX0=DM(dms_r);
- MX1=DM(dml_r);
- CALL functw; {Update variables}
- DM(yu_r)=AX1; {Stored updated variables}
- DM(yl_l_r)=MY1;
- DM(yl_h_r)=MY0;
- DM(ap_r)=AR;
- DM(dms_r)=MX0;
- DM(dml_r)=MX1;
-
- CALL compress; {Compress PCM value}
-
- DM(hld_a_r)=I1; {Save s_r delay pointer}
- DM(hld_b_r)=I0; {Save dq delay pointer}
-
- RTS;
-
- compress: AR=DM(s_r); {Get reconstructed signal}
- AR=ABS AR; {Take absolute value}
- AY0=33; {Add offset of boundries}
- AR=AR+AY0;
- AY0=8191; {Maximum PCM value}
- AF=AR-AY0; {Cap input}
- IF GT AR=PASS AY0; {If in excess}
- SE=EXP AR (HI); {Find exponent adjustmet}
- AX0=SE, SR=NORM AR (LO); {Normalize input}
- AY0=H#4000;
- AR=SR0 XOR AY0; {Remove first significant bit}
- SR=LSHIFT AR BY -10 (LO); {Shift position bits}
- AR=PASS AY0;
- IF POS AR=PASS 0; {Create sign bit}
- SR=SR OR LSHIFT AR BY -7 (LO); {Position sign bit}
- AY0=9;
- AR=AX0+AY0; {Compute segment}
- IF LT AR=PASS 0;
- SR=SR OR LSHIFT AR BY 4 (LO); {Position segment bits}
- AY0=H#FF;
- AR=SR0 XOR AY0; {Invert bits}
- RTS;
-
- expand: AY0=H#FF; {Mask unwanted bits}
- AF=AR AND AY0, AX0=AY0;
- AF=AX0 XOR AF; {Invert bits}
- AX0=H#70;
- AR=AX0 AND AF; {Isolate segment bits}
- SR=LSHIFT AR BY -4 (LO); {Shift to LSBs}
- SE=SR0, AR=AR XOR AF; {Remove segment bits}
- AY0=H#FF80;
- AF=AR+AY0;
- IF LT JUMP posval; {Detemine sign}
- AR=PASS AF;
- AR=AR+AF; {Shift left by 1 bit}
- AY0=33;
- AR=AR+AY0; {Add segment offset}
- SR=ASHIFT AR (LO); {Position bits}
- AR=AY0-SR0; {Remove segment offset}
- RTS;
-
- posval: AF=PASS AR;
- AR=AR+AF; {Shift left by 1}
- AY0=33;
- AR=AR+AY0; {Add segment offset}
- SR=ASHIFT AR (LO);
- AR=SR0-AY0; {Remove segment offset}
- RTS;
-
- predict: AX1=DM(I0,M2), AY1=PM(I4,M6); {Point to dq6 and b6}
- AF=PASS 0, SI=PM(I4,M4); {AF hold partial sum}
- AY0=DM(I6,M5);
- MX1=3; {This multiply will give the}
- MY1=32768; {+48>>4 term}
- SR=ASHIFT SI BY -2 (HI); {Downshift b6 per spec}
- CNTR=6; {Loop once for each b}
- DO sez_cmp UNTIL CE;
- AR=ABS SR1, SR1=DM(I6,M5); {Get absolute value of b}
- AR=AR AND AY0, AY0=DM(I6,M5);{Mask bits per spec}
- SE=EXP AR (HI), MY0=DM(I0,M2);{Find exponent adjust}
- AX0=SE, SR=SR OR NORM AR (HI);{Compute bnMANT}
- AR=SR1 AND AY0, AY0=DM(I0,M2);{Mask bits per spec}
- MR=AR*MY0 (SS), AX1=DM(I0,M2), AY1=PM(I4,M6);
- AR=AX0+AY0, AY0=DM(I6,M5); {Compute WbEXP}
- SE=AR, MR=MR+MX1*MY1 (SU); {Compute WbnMANT}
- SR=LSHIFT MR1 (HI), SE=DM(I6,M5);{Compute Wbn}
- AR=SR1 AND AY0, SI=PM(I4,M4);{Mask Wbn per spec}
- AX0=AR, AR=AX1 XOR AY1; {Determine sign of Wbn}
- AR=AX0, SR=ASHIFT SI (HI); {Downshift b(n-1) per spec}
- IF LT AR=-AX0; {Negate Wbn if necessary}
- sez_cmp: AF=AR+AF, AY0=DM(I6,M5); {Add Wbn to partial sum}
- AR=PASS AF, AX1=DM(I0,M1), AY1=PM(I5,M6);{Get sezi}
- SR=ASHIFT AR BY -1 (HI); {Downshift to produce sez}
- DM(sez)=SR1;
- SI=PM(I5,M4); {Get a2}
- SR=ASHIFT SI (HI); {Downshift a2 per spec}
- AX1=DM(I1,M2), AY1=PM(I4,M5); {Restore bn and dqn pointers}
- CNTR=2; {Loop once for each a}
- DO s_e_cmp UNTIL CE;
- AR=ABS SR1, SR1=DM(I6,M5); {Get absolute value of a}
- AR=AR AND AY0, AY0=DM(I6,M5);{Mask bits per spec}
- SE=EXP AR (HI), MY0=DM(I1,M2);{Get exponent adjust for a}
- AX0=SE, SR=SR OR NORM AR (HI);{Compute anMANT}
- AR=SR1 AND AY0, AY0=DM(I1,M2);{Mask bits per spec}
- MR=AR*MY0(SS), AX1=DM(I1,M2), AY1=PM(I5,M6);
- AR=AX0+AY0, AY0=DM(I6,M5); {Compute WanEXP}
- SE=AR, MR=MR+MX1*MY1 (SU); {Complete WanMANT computation}
- SR=LSHIFT MR1 (HI), SE=DM(I6,M5);{Compute Wan}
- AR=SR1 AND AY0, SI=PM(I5,M4);{Mask Wan per spec}
- AX0=AR, AR=AX1 XOR AY1; {Determine sign of Wan}
- AR=AX0, SR=ASHIFT SI (HI); {Downshift a1 per spec}
- IF LT AR=-AX0; {Negate Wan if necessary}
- s_e_cmp: AF=AR+AF, AY0=DM(I6,M5); {Add Wan to partial sum}
- AR=PASS AF, AX1=DM(I1,M1), AY1=PM(I5,M5);{Get sei}
- SR=ASHIFT AR BY -1 (HI); {Compute se}
- DM(s_e)=SR1;
- RTS;
-
- lima: AY1=256; {Maximum value for ap}
- AR=AX1, AF=AX1-AY1; {Cap if it exceeds}
- IF GE AR=PASS AY1;
- SR=ASHIFT AR BY -2 (HI); {>>2 to produce al}
- SR=LSHIFT SR1 BY 9 (HI); {Adjust for ADSP-210x version}
-
- mix: MY0=SR1, AR=AX0-AY0; {MY0=al, AR=diff}
- AR=ABS AR; {Take absolute value of diff}
- MR=AR*MY0 (SU); {Generate prod}
- AR=MR1+AY0; {Add to yu}
- IF NEG AR=AY0-MR1; {Subtract if diff < 0}
- SR=ASHIFT AR BY -2 (HI); {Generate y>>2}
- RTS;
-
- log: I3=^qn_values; {Point to data array}
- AR=ABS AR, AX1=DM(I3,M1); {Take absolute of d}
- SE=EXP AR (HI), AX0=DM(I3,M1); {Determine exponent adjust}
- AY0=SE, SR=NORM AR (HI); {Normalize}
- AR=AX0+AY0, AY0=DM(I3,M1); {Compute exponent}
- IF LT AR=PASS 0; {Check for exponent -1}
- SI=AR, AR=SR1 AND AY0; {Mask mantissa bits}
- SR=LSHIFT AR BY -7 (HI); {Position mantissa}
- SR=SR OR LSHIFT SI BY 7 (HI); {Position exponent}
-
- subtb: AR=SR1-AY1, AY0=DM(I3,M1); {Subtract y>>2 for log}
- AX0=AR, AF=PASS AX1; {Setup for quantizing}
-
- quan: AR=AX0-AY0, AY0=DM(I3,M1); {Is dl less then upper limit?}
- IF LT AF=AF-1;
- AR=AX0-AY0, AY0=DM(I3,M1); {Continue to check for }
- IF LT AF=AF-1;
- AR=AX0-AY0, AY0=DM(I3,M1); {where dl fits in quantizer}
- IF LT AF=AF-1;
- AR=AX0-AY0, AY0=DM(I3,M1);
- IF LT AF=AF-1;
- AR=AX0-AY0, AY0=DM(I3,M1);
- IF LT AF=AF-1;
- AR=AX0-AY0, AY0=DM(I3,M1);
- IF LT AF=AF-1;
- AR=AX0-AY0;
- IF LT AF=AF-1;
- AR=PASS AF;
- IF NEG AR=NOT AF; {Negate value if ds negative}
- IF EQ AR=NOT AR; {Send 15 for 0}
- RTS;
-
- reconst: AF=ABS AR;
- IF NEG AR=NOT AR; {Find absolute value}
- M3=AR; {Use this for table lookup}
- I3=^dq_values; {Point to dq table}
- MODIFY(I3,M3); {Set pointer to proper spot}
- AX1=DM(I3,M1); {Read dq from table}
-
- adda: AR=AX1+AY1; {Add y>>2 to dq}
-
- antilog: SR=ASHIFT AR BY 9 (LO); {Get antilog of dq}
- AY1=127; {Mask mantisa}
- AX0=SR1, AR=AR AND AY1; {Save sign of DQ+Y in AX0}
- AY1=128; {Add 1 to mantissa}
- AR=AR+AY1;
- AY0=-7; {Compute magnitude of shift}
- SI=AR, AR=SR1+AY0;
- SE=AR;
- SR=ASHIFT SI (HI); {Shift mantissa }
- AR=SR1, AF=PASS AX0;
- IF LT AR=PASS 0; {If DQ+Y <0, set to zero}
- IF NEG AR=-SR1; {Negate DQ if I value negative}
- RTS;
-
- functw: I3=^w_values; {Get scale factor multiplier}
- MODIFY(I3,M3); {Based on I value}
- AF=PASS 0, SI=DM(I3,M1);
- I3=^f_values;
-
- filtd: SR=ASHIFT SI BY 1 (LO); {Update fast quantizer factor}
- AR=SR0-AY0, SE=DM(I3,M1); {Compute difference}
- SI=AR, AR=SR1-AF+C-1; {in double precision}
- SR=ASHIFT AR (HI), AX0=DM(I3,M1);{Time constant is 1/32}
- SR=SR OR LSHIFT SI (LO), AY1=DM(I3,M1);
- AR=SR0+AY0, AY0=DM(I3,M1); {Add gain}
-
- limb: AF=AR-AY1, SI=DM(I3,M3); {Limit fast scale factor}
- IF GT AR=PASS AY1; {Upper limit 10}
- AF=AR-AY0, AY1=MY1;
- IF LT AR=PASS AY0; {Lower limit 1.06}
-
- filte: AF=AX0-AY1, AY0=MY0; {Update quantizer slow factor}
- AF=AX0-AY0+C-1, AX0=DM(I3,M1); {Compute difference}
- AX1=AR, AR=AR+AF;
- SR=ASHIFT AR BY -6 (HI); {Time constant is 1/64}
- AR=SR0+AY1, AY1=MX0; {Add gain}
- MY1=AR, AR=SR1+AY0+C; {in double precision}
-
- filta: MY0=AR, AR=AX0-AY1; {Update short term I average}
- SR=ASHIFT AR (HI), SI=AX0; {Time constant is 1/32}
- AR=SR1+AY1, AY0=MX1; {Add gain}
-
- filtb: SR=LSHIFT SI BY 2 (HI); {Update long term I average}
- MX0=AR, AR=SR1-AY0;
- SR=ASHIFT AR BY -7 (HI); {Time constant is 1/128}
- AR=SR1+AY0, SI=MX0; {Add gain}
-
- subtc: SR=ASHIFT AR BY -3 (HI); {Compute difference of long}
- AF=PASS AR, AX0=SR1; {and short term I averages}
- SR=ASHIFT SI BY 2 (HI);
- MX1=AR, AR=SR1-AF;
- AF=ABS AR;
- AR=MR2, AF=AX0-AF; {tdp must be true for ax 0}
- IF LE AR=PASS 1;
- AY0=1536;
- AF=MR1-AY0, AY0=MR0;
- IF LT AR=PASS 1; {Y>3 for ax to be 0}
-
- filtc: SR=ASHIFT AR BY 9 (HI); {Update speed control}
- AR=SR1-AY0; {Compute difference}
- SR=ASHIFT AR BY -4 (HI); {Time constant is 1/16}
- AR=SR1+AY0; {Add gain}
- RTS;
-
- update_filter: AX0=DM(dq); {Get value of current dq}
- AR=128;
- AF=PASS AX0, AY1=DM(I0,M0); {Read sign of dq(6)}
- IF EQ AR=PASS 0; {If dq 0 then gain 0}
- SE=-8; {Time constand is 1/256}
- AX1=AR;
- CNTR=6;
- DO update_b UNTIL CE; {Update all b-coefficients}
- AF=AX0 XOR AY1, AY0=PM(I4,M4);{Get sign of update}
- IF LT AR=-AX1;
- AF=AR+AY0, SI=AY0; {Add update to original b}
- SR=ASHIFT SI (HI), AY1=DM(I0,M0);{Get next dq(k)}
- AR=AF-SR1; {Subtract leak factor}
- update_b: PM(I4,M5)=AR, AR=PASS AX1; {Write out new b-coefficient}
-
- place_dq: AR=ABS AX0, AY0=DM(I0,M2); {Take absolute value of dq}
- SE=EXP AR (HI); {Determine exponent adjust}
- SR1=H#4000; {Set minimum value into SR1}
- AX1=SE, SR=SR OR NORM AR (HI); {Normalize dq}
- AY0=11; {Used for exponent adjustment}
- SR=LSHIFT SR1 BY -9 (HI); {Remove lower bits}
- SR=LSHIFT SR1 BY 2 (HI); {Adjust for ADSP-210x version}
- DM(I0,M2)=SR1, AR=AX1+AY0; {Save mantisa, compute exp.}
- DM(I0,M2)=AR; {Save exponent}
- AX1=DM(a_ik); {Use sign of I, not dq}
- DM(I0,M0)=AX1; {Save sign}
-
- update_p: AY0=DM(sez); {Get result of predictor}
- AR=AX0+AY0; {Use dq from above}
- AY1=DM(p); {Delay all old p's by 1}
- AY0=DM(p_o);
- DM(p)=AR;
- DM(p_o)=AY1;
- DM(p_o_o)=AY0;
- AX1=AR, AR=AR XOR AY0; {Compute p xor poo}
- MR1=AR, AR=AX1 XOR AY1; {Compute p xor po}
- MR0=AR;
-
- upa2: I3=^a_data;
- SI=PM(I5,M5); {Hold a2 for later}
- AR=PM(I5,M5); {Get a1 for computation of f}
- AR=ABS AR, AY0=DM(I3,M1); {Cap magnitude of a1 at 1/2}
- AF=AR-AY0, SE=DM(I3,M1);
- IF GT AR=PASS AY0;
- IF NEG AR=-AR; {Restore sign}
- SR=ASHIFT AR (LO), AY0=DM(I3,M1);
- AF=ABS MR0, AY1=DM(I3,M1); {If p xor po = 0 negate f}
- AR=SR0, AF=PASS SR1;
- IF POS AR=AY1-SR0; {Double precision}
- IF POS AF=AY1-SR1+C-1;
- SR0=AR, AR=PASS AF;
- SR1=AR, AF=ABS MR1; {If p xor poo = 1 subtract}
- AR=SR0+AY0, SE=DM(I3,M1);
- AF=SR1+AY1+C, AX0=DM(I3,M1);
- IF NEG AR=SR0-AY0;
- IF NEG AF=SR1-AY1+C-1;
- SR=LSHIFT AR (LO);
- AR=PASS AF;
- SR=SR OR ASHIFT AR (HI), AY0=SI;
- AY1=SR0, SR=ASHIFT SI (HI); {Downshift a2 for adjustment}
- AR=AY0-SR1, AY0=DM(I3,M1);
- AF=PASS AX1;
- IF NE AR=AR+AY1; {If sigpk = 1, no gain}
-
- limc: AF=AR-AY0, AY1=DM(I3,M1); {Limit a2 to .75 max}
- IF GT AR=PASS AY0;
- AF=AR-AY1, AY0=DM(I3,M1); {Limit a2 to -.75 min}
- IF LT AR=PASS AY1;
- PM(I5,M5)=AR; {Store new a2}
-
- upa1: AR=AX0, AF=PASS MR0;
- IF LT AR=-AX0;
- AF=PASS AX1, SI=PM(I5,M4);
- IF EQ AR=PASS 0;
- SR=ASHIFT SI BY -8 (HI); {Leak Factor = 1/256}
- AF=PASS AR, AR=SI;
- AF=AF-SR1;
- AR=AR+AF, AX1=DM(I3,M1);
-
- limd: AX0=AR, AR=AX1-AY1; {Limit a1 based on a2}
- AY0=AR, AR=AY1-AX1;
- AY1=AR, AR=PASS AX0;
- AF=AR-AY0;
- IF GT AR=PASS AY0; {Upper limit 1 - 2^-4 - a2}
- AF=AR-AY1;
- IF LT AR=PASS AY1; {Lower limit a2 - 1 + 2^-4}
- PM(I5,M5)=AR; {Store new a1}
-
- RTS;
-
- update_filter_r:AX0=DM(dq_r); {Get dq_r}
- AR=128; {Set possible gain}
- AF=PASS AX0, AY1=DM(I0,M0); {Get sign of dq(6)}
- IF EQ AR=PASS 0; {If dq_r 0, gain 0}
- SE=-8; {Leak factor 1/256}
- AX1=AR;
- CNTR=6;
- DO update_b_r UNTIL CE; {Update all b-coefficients}
- AF=AX0 XOR AY1, AY0=PM(I4,M4);{Get sign of gain}
- IF LT AR=-AX1;
- AF=AR+AY0, SI=AY0; {Add gain to original b}
- SR=ASHIFT SI (HI); {Time constant is 1/256}
- AR=AF-SR1, AY1=DM(I0,M0); {Compute new b-value}
- update_b_r: PM(I4,M5)=AR, AR=PASS AX1; {Store new b-value}
-
- place_dq_r: AR=ABS AX0, AY0=DM(I0,M2); {Get absolute value fo dq_r}
- SE=EXP AR (HI); {Determine exponent adjustment}
- SR1=H#4000; {Set SR to minimum value}
- AX1=SE, SR=SR OR NORM AR (HI); {Normalize dq_r}
- AY0=11; {Used for exponent adjust}
- SR=LSHIFT SR1 BY -9 (HI); {Remove lower bits}
- SR=LSHIFT SR1 BY 2 (HI); {Adjust for ADSP-210x version}
- DM(I0,M2)=SR1, AR=AX1+AY0; {Store mantissa, compute exp}
- AX1=DM(a_ik_r); {Use sign of I, not dq}
- DM(I0,M2)=AR; {Store exponent}
- DM(I0,M0)=AX1; {Store sign}
-
- update_p_r: AY0=DM(sez); {Compute new p}
- AR=AX0+AY0; {Use dq_r from above}
- AY1=DM(p_r); {Delay old p's by 1}
- AY0=DM(p_o_r);
- DM(p_r)=AR;
- DM(p_o_r)=AY1;
- DM(p_o_o_r)=AY0;
- AX1=AR, AR=AR XOR AY0; {Compute p and poo}
- MR1=AR, AR=AX1 XOR AY1; {Compute p and po}
- MR0=AR;
-
- upa2_r: I3=^a_data;
- SI=PM(I5,M5); {Hold a2 for later}
- AR=PM(I5,M5); {Get a1 for computation of f}
- AR=ABS AR, AY0=DM(I3,M1); {Cap magnitude of a1 to 1/2}
- AF=AR-AY0, SE=DM(I3,M1);
- IF GT AR=PASS AY0;
- IF NEG AR=-AR; {Restore sign of f}
- SR=ASHIFT AR (LO), AY0=DM(I3,M1);
- AF=ABS MR0, AY1=DM(I3,M1); {If p_r xor poo_r =1 subtract}
- AR=SR0, AF=PASS SR1;
- IF POS AR=AY1-SR0;
- IF POS AF=AY1-SR1+C-1;
- SR0=AR, AR=PASS AF;
- SR1=AR, AF=ABS MR1;
- AR=SR0+AY0, SE=DM(I3,M1);
- AF=SR1+AY1+C, AX0=DM(I3,M1);
- IF NEG AR=SR0-AY0;
- IF NEG AF=SR1-AY1+C-1;
- SR=LSHIFT AR (LO);
- AR=PASS AF;
- SR=SR OR ASHIFT AR (HI), AY0=SI;
- AY1=SR0, SR=ASHIFT SI (HI); {Leak factor of 1/128}
- AR=AY0-SR1, AY0=DM(I3,M1);
- AF=PASS AX1;
- IF NE AR=AR+AY1; {If sigpk = 1 , no gain}
-
- limc_r: AF=AR-AY0, AY1=DM(I3,M1); {Limit a2 to .75 max}
- IF GT AR=PASS AY0;
- AF=AR-AY1, AY0=DM(I3,M1); {Limit a2 to -.75 min}
- IF LT AR=PASS AY1;
- PM(I5,M5)=AR; {Store new a2}
-
- upa1_r: AR=AX0, AF=PASS MR0;
- IF LT AR=-AX0;
- AF=PASS AX1, SI=PM(I5,M4);
- IF EQ AR=PASS 0;
- SR=ASHIFT SI BY -8 (HI); {Leak Factor = 1/256}
- AF=PASS AR, AR=SI;
- AF=AF-SR1;
- AR=AR+AF, AX1=DM(I3,M1);
-
- limd_r: AX0=AR, AR=AX1-AY1; {Limit a1 based on a2}
- AY0=AR, AR=AY1-AX1;
- AY1=AR, AR=PASS AX0;
- AF=AR-AY0;
- IF GT AR=PASS AY0; {Upper limit 1 - 2^-4 -a2}
- AF=AR-AY1;
- IF LT AR=PASS AY1; {Lower limit a2 - 1 + 2^-4}
- PM(I5,M5)=AR; {Store new a1 }
-
- RTS;
-
- .ENDMOD;
-
-