;  	   AMSAT/TAPR DSP BEL-202 modem.  Filter splitter design
;            Sample rate should be set to 9600 samples/sec. 
;          		code by Bob McGwier N4HY
     org 0
     b go
     org 16
sine:   equ 0    ;  will store sine values from tone
one:    equ 1      ;  guess what goes here duhhhhh!
energy: equ 2
thresh: equ 3
maskl:  equ 4    ;  mask for fine or low order bits of phase
mask:   equ 5    ;  mask for doing modulo 16384 arithmetic with phase
sinx:   equ 6    ;  used to store coarse sine value (high order bits)
cosx:   equ 7    ;  as above for cosine
mone:   equ 8    ;   minus one stored here
wkph:   equ 9    ;  different phases (PLL, remodulator tone etc) are stored hr
                 ;  for frequency synthesis
masko:  equ 10   ;  mask for converting on board PCM to DAC format
mps:    equ 11   ;  multiplier for quadrant determination for sine
mpc:    equ 12   ;  multiplier for quadrant determination for cosine
siny:   equ 13   ;  fine correction value for use in SIN(X+Y) = sinx*cosy+
cosy:   equ 14   ;          cosx*siny
cosine: equ 15   ;  cosine is also needed for Q arm in Costas loop
coph:   equ 16   ;  working number holder
modem:  equ 17   ;  Used to choose between complex tone for arms and real tone
                 ;  in the modulator as explained below
xn0:	equ 18
xn1:	equ 19
xn2:	equ 20
xn3:	equ 21
xn4:	equ 22
xn5:	equ 23
xn6:	equ 24
xn7:	equ 25
xn8:	equ 26
xn9:	equ 27
xn10:	equ 28
xn11:	equ 29
xn12:	equ 30
xn13:	equ 31
xn14:	equ 32
xn15:	equ 33
xn16:	equ 34
xn17:	equ 35
xn18:	equ 36
xn19:	equ 37
xn20:	equ 38
xn21:	equ 39
xn22:	equ 40
xn23:	equ 41
xn24:	equ 42
xn25:	equ 43
xn26:	equ 44
xn27:	equ 45
xn28:	equ 46
xn29:	equ 47
xn30:	equ 48
xn31:	equ 49
xn32:	equ 50
b0:	equ 51
b1:	equ 52
b2:	equ 53
b3:	equ 54
b4:	equ 55
b5:	equ 56
b6:	equ 57
b7:	equ 58
b8:	equ 59
b9:	equ 60
b10:	equ 61
b11:	equ 62
b12:	equ 63
b13:	equ 64
b14:	equ 65
b15:	equ 66
b16:	equ 67
b17:	equ 68
b18:	equ 69
b19:	equ 70
b20:	equ 71
freql:  equ 72   ;  low tone for remodulator stored here
freqh:  equ 73   ;  high tone remod.
freqo:  equ 74   ;  freqo is assigned one of the values above for remod
phaseo: equ 75      ;  phaseo is the phase of the remodulator output. phase is
hl12: 	equ 76
hl13:	equ 77
hl15:	equ 78
hl16:	equ 79
hu13:	equ 80
hu14:	equ 81
hu16:	equ 82
hb8:	equ 83
hb9:	equ 84
hb10:	equ 85
tester: equ 86
suml:	equ 87
sumh:	equ 88
clockp: equ 89
clockf: equ 90
clocke: equ 91
clocka:	equ 92
sintbl: 
       dw      0  ; coarse sine table in steps of PI/64 radians to PI/2
       dw    804
       dw   1607
       dw   2410
       dw   3211
       dw   4011
       dw   4807
       dw   5601
       dw   6392
       dw   7179
       dw   7961
       dw   8739
       dw   9511
       dw  10278
       dw  11038
       dw  11792
       dw  12539
       dw  13278
       dw  14009
       dw  14732
       dw  15446
       dw  16150
       dw  16845
       dw  17530
       dw  18204
       dw  18867
       dw  19519
       dw  20159
       dw  20787
       dw  21402
       dw  22004
       dw  22594
       dw  23169
       dw  23731
       dw  24278
       dw  24811
       dw  25329
       dw  25831
       dw  26318
       dw  26789
       dw  27244
       dw  27683
       dw  28105
       dw  28510
       dw  28897
       dw  29268
       dw  29621
       dw  29955
       dw  30272
       dw  30571
       dw  30851
       dw  31113
       dw  31356
       dw  31580
       dw  31785
       dw  31970
       dw  32137
       dw  32284
       dw  32412
       dw  32520
       dw  32609
       dw  32678
       dw  32727
       dw  32757
       dw  32767  ; PI/2
fines: dw      0  ; fine sine table  in steps of PI/(64*64) radians to PI/64
       dw     12
       dw     25
       dw     37
       dw     50
       dw     62
       dw     75
       dw     87
       dw    100
       dw    113
       dw    125
       dw    138
       dw    150
       dw    163
       dw    175
       dw    188
       dw    201
       dw    213
       dw    226
       dw    238
       dw    251
       dw    263
       dw    276
       dw    289
       dw    301
       dw    314
       dw    326
       dw    339
       dw    351
       dw    364
       dw    376
       dw    389
       dw    402
       dw    414
       dw    427
       dw    439
       dw    452
       dw    464
       dw    477
       dw    490
       dw    502
       dw    515
       dw    527
       dw    540
       dw    552
       dw    565
       dw    578
       dw    590
       dw    603
       dw    615
       dw    628
       dw    640
       dw    653
       dw    665
       dw    678
       dw    691
       dw    703
       dw    716
       dw    728
       dw    741
       dw    753
       dw    766
       dw    779
       dw    791
finec: dw   32767  ;ditto to above for fine sine
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32766
       dw   32765
       dw   32765
       dw   32765
       dw   32765
       dw   32765
       dw   32765
       dw   32765
       dw   32765
       dw   32764
       dw   32764
       dw   32764
       dw   32764
       dw   32764
       dw   32764
       dw   32764
       dw   32763
       dw   32763
       dw   32763
       dw   32763
       dw   32763
       dw   32762
       dw   32762
       dw   32762
       dw   32762
       dw   32762
       dw   32761
       dw   32761
       dw   32761
       dw   32761
       dw   32760
       dw   32760
       dw   32760
       dw   32760
       dw   32759
       dw   32759
       dw   32759
       dw   32759
       dw   32758
       dw   32758
       dw   32758
       dw   32758
       dw   32757
       dw   32757
filtd:
	dw  -4178
	dw  -5415
	dw   4323
	dw   7299

	dw  -4545
	dw  -5167
	dw   6951

	dw   4513
	dw   8819
	dw   10635
go:  ldpk 0         ; make sure that we are pointing to 0 data page
     lack one   ; make and store one
     sacl one
     lac one,11
     sacl clockf
     lack filtd ; store address of the too large coefficients
     tblr hl12
     add one
     tblr hl13
     add one
     tblr hl15
     add one
     tblr hl16
     add one
     tblr hu13
     add one
     tblr hu14
     add one
     tblr hu16
     add one
     tblr hb8
     add one
     tblr hb9
     add one
     tblr hb10
     sacl masko
     lt one
     mpyk 3755
     pac
     sacl freqh
     lac one,4
     sacl thresh
     lt one
     mpyk 2048
     pac
     sacl freql
     zac
     sacl clockp
     sub one
     sacl mone  ; make and store minus one
     sacl modem
     lac one,14
     sub one
     sacl mask  ; make and store mask for modulo 16384 phase arithmetic
     lac one,6
     sub one
     sacl maskl ; make and store fine part of address mask;
     lac one,8     ; make and store frequency address in memory
     sub one
     
;  Okay the BS is over lets get to work !     
     
wait: bioz fire    ; is it time for a new sample     
      b wait       ; nope go wait in the corner
fire: in xn0,pa3   ; get a new sample here

     lac xn0,4
     sub one,15   ; Change ADC format to two's complement
     sacl xn0

;     remodulator output

     lac thresh
     sub energy
     bgz noout
     lac sine,6
     addh masko
     sach b0
     out b0,pa4   ; send it to the TNC here
                   ; as the following routines have a variable length
;     end output
noout: lack one  ;
     sacl mps  ;   Restore sine and cosine quadrant multipliers
     sacl mpc  ;
;	
;              FINITE IMPULSE RESPONSE (FIR)
;            LINEAR PHASE DIGITAL FILTER DESIGN
;                REMEZ EXCHANGE ALGORITHM

;                     BANDPASS FILTER

;                   FILTER LENGTH =  33
;
;                       BAND  1       BAND  2       BAND  3
; LOWER BAND EDGE      .0000000      .1150000      .2290000
; UPPER BAND EDGE      .0550000      .1770000      .5000000
; DESIRED VALUE        .0000000     1.0000000      .0000000
; WEIGHTING           1.0000000     1.0000000     1.0000000
; DEVIATION            .0158519      .0158519      .0158519
; DEVIATION IN DB   -35.9983500      .1366083   -35.9983500

; EXTREMAL FREQUENCIES--MAXIMA OF THE ERROR CURVE
;     .0000000    .0404412    .0550000    .1150000    .1241912
;     .1462500    .1664706    .1770000    .2290000    .2381912
;     .2620883    .2896618    .3190736    .3503236    .3834119
;     .4146619    .4514267    .5000000
;
;	FILTER for low side with the filter given above
;
	zac ;  Zero the accumulator as we will be summing as we multiply
	lt xn32
	mpyk 270
	
	lta xn31
	mpyk -212
	
	lta xn30
	mpyk -670
	
	lta xn29
	mpyk -680
	
	lta xn28
	mpyk -25
	
	lta xn27
	mpyk 610
	
	lta xn26
	mpyk 479
	
	lta xn25
	mpyk -19
	
	lta xn24
	mpyk 317
	
	lta xn23
	mpyk 1577
	
	lta xn22
	mpyk 1907
	
	lta xn21
	mpyk -447
	
	lta xn20
	mpy hl12
	
	lta xn19
	mpy hl13
	
	lta xn18
	mpyk -1748
	
	lta xn17
	mpy hl15
	
	lta xn16
	mpy hl16
	
	lta xn15
	mpy hl15
	
	lta xn14
	mpyk -1748
	
	lta xn13
	mpy hl13
	
	lta xn12
	mpy hl12
	
	lta xn11
	mpyk -447
	
	lta xn10
	mpyk 1907
	
	lta xn9
	mpyk 1507
	
	lta xn8
	mpyk 317
	
	lta xn7
	mpyk -19
	
	lta xn6
	mpyk 479
	
	lta xn5
	mpyk 610
	
	lta xn4
	mpyk -25
	
	lta xn3
	mpyk -680
	
	lta xn2
	mpyk -670
	
	lta xn1
	mpyk -212
	
	lta xn0
	mpyk 270
	apac
	sach suml  ;  suml is the low side filter output
	bgez posl
	zac
	sub suml
	sacl suml
posl:
;	
;
;              FINITE IMPULSE RESPONSE (FIR)
;            LINEAR PHASE DIGITAL FILTER DESIGN
;                REMEZ EXCHANGE ALGORITHM

;                     BANDPASS FILTER

;                   FILTER LENGTH =  33

;                      BAND  1       BAND  2       BAND  3
; LOWER BAND EDGE      .0000000      .1770000      .2900000
; UPPER BAND EDGE      .1200000      .2290000      .5000000
; DESIRED VALUE        .0000000     1.0000000      .0000000
; WEIGHTING           1.0000000     1.0000000     1.0000000
; DEVIATION            .0114788      .0114788      .0114788
; DEVIATION IN DB   -38.8020300      .0991361   -38.8020300
;
;	FILTER for high side with the filter given above
;

	zac ;  Zero the accumulator as we will be summing as we multiply
	lt xn32
	mpyk -43
	
	ltd xn31
	mpyk -642
	
	ltd xn30
	mpyk -196
	
	ltd xn29
	mpyk 612
	
	ltd xn28
	mpyk 600
	
	ltd xn27
	mpyk -201
	
	ltd xn26
	mpyk -275
	
	ltd xn25
	mpyk 115
	
	ltd xn24
	mpyk -726
	
	ltd xn23
	mpyk -1492
	
	ltd xn22
	mpyk 785
	
	ltd xn21
	mpyk 3790
	
	ltd xn20
	mpyk 1545
	
	ltd xn19
	mpy hu13
	
	ltd xn18
	mpy hu14
	
	ltd xn17
	mpyk 2078
	
	ltd xn16
	mpy hu16
	
	ltd xn15
	mpyk 2078
	
	ltd xn14
	mpy hu14
	
	ltd xn13
	mpy hu13
	
	ltd xn12
	mpyk 1545
	
	ltd xn11
	mpyk 3790
	
	ltd xn10
	mpyk 785
	
	ltd xn9
	mpyk -1492
	
	ltd xn8
	mpyk -726
	
	ltd xn7
	mpyk 115
	
	ltd xn6
	mpyk -275
	
	ltd xn5
	mpyk -201
	
	ltd xn4
	mpyk 600
	
	ltd xn3
	mpyk 612
	
	ltd xn2
	mpyk -196
	
	ltd xn1
	mpyk -642
	
	ltd xn0
	mpyk -43
	apac
	sach sumh  ;  sumh is the high side filter output
	bgez posh
	zac
	sub sumh
	sacl sumh
posh:
	;  load the high filter value subtract the low filter value
	;  send this through the LPF. 
	lac sumh
 	sub suml
	sacl b0
	; See if there is energy in the filters and use this as a data
	; squelch.  In other words, you must use the squelch on your radio
	; to turn the data squelch on and off
	lac sumh,15
	add suml,15
	add energy,15
	sach energy


;              FINITE IMPULSE RESPONSE (FIR)
;            LINEAR PHASE DIGITAL FILTER DESIGN
;                REMEZ EXCHANGE ALGORITHM

;                     BANDPASS FILTER

;                   FILTER LENGTH =  21

;                       BAND  1       BAND  2
; LOWER BAND EDGE      .0000000      .1750000
; UPPER BAND EDGE      .1250000      .5000000
; DESIRED VALUE       1.0000000      .0000000
; WEIGHTING           1.0000000     1.0000000
; DEVIATION            .0687429      .0687429
; DEVIATION IN DB      .5774649   -23.2554400
;
;	LPF the splitter output and this is the bits
;
;
;	If the bit is positive output 2200 else output 1200
;
	zac

	lt b20
	mpyk -431
	
	ltd b19
	mpyk 323
	
	ltd b18
	mpyk 821
	
	ltd b17
	mpyk 801
	
	ltd b16
	mpyk -185
	
	ltd b15
	mpyk -1568
	
	ltd b14
	mpyk -1844
	
	ltd b13
	mpyk 269
	
	ltd b12
	mpy hb8
	
	ltd b11
	mpy hb9
	
	ltd b10
	mpy hb10
	
	ltd b9
	mpy hb9
	
	ltd b8
	mpy hb8
	
	ltd b7
	mpyk 269
	
	ltd b6
	mpyk -1844
	
	ltd b5
	mpyk -1568
	
	ltd b4
	mpyk -185
	
	ltd b3
	mpyk 801
	
	ltd b2
	mpyk 821
	
	ltd b1
	mpyk 323 
	
	ltd b0
	mpyk -431
	apac
	sach b0
;	b0 contains the bandlimited noisy bit value.  Recover the clock
;	so that we may choose point of maximum eye opening for the bit
;       decision.
;
;	The clock recovery nonlinearity begins with absolute value
	lac b0
	bgez addc
	zac
	sub b0
addc:   sacl clocke
;	Keep a IIR LPF version of this so that the DC may be subtracted
;	and get a clock tone at the data rate.
;	Simplest IIR,  0.5*old value + 0.5 * new value
;
	lac clocka,15
	add clocke,15
	sach clocka
;	Subtract off DC
	lac clocke
	sub clocka
	sacl clocke
;	get sine from tones that runs at the clock rate
	lac clockp
	call tones
	zac
;	mix (multiply) with the clock signal from above
	lt sine
	mpy clocke
	spac
;	taking the negative of this (spac from a zero'd accumulator)
	sach clocke
;	using a gain of 1/8 add correction into the old clock phase plus
;	the phase increment (frequency)
	lac clocke,13
	sach clocke
	lac clockf
	add clockp
	add clocke
	sacl clockp
;	After storing the new clock phase test to see if we have passed
;	two pi at which time we will take the value of b0 for the bit value
;	Since this is the point of maximal eye opening.  If the phase has
;	been corrected negative put back between 0 and 2pi.
	bgez gpi
	add one,14
	sacl clockp
	b outt
gpi:	lac one,14
	sub clockp
	blz nfrq
	b outt
nfrq:	lac clockp
	and mask
	sacl clockp
	lac b0
;	bit positive?
	bgez posb
;	No load low frequency for this bit period
	lac freql
	b newf
;	Yes load high frequency for this bit period
posb:   lac freqh
newf:	sacl freqo
;	freqo is the output frequency for the remodulator
outt:	lack one
	sacl mpc
	sacl mps
	lac freqo
	add phaseo
	and mask
	sacl phaseo
	call tones
	b wait
;     complex tone generator if modem>0 if modem<0 sine wave generator

tones: sacl wkph  ;  store a working copy
     lac wkph,4
     subh one
     blz getem  ;  is it in a quadrant bigger than first?
     subh one
     bgez thfr; is it in a quadrant greater than two?
     lac 1,13  ;  nope so load pi
     sub wkph  ;  subtract phase so that it maps back into 1st quad
     sacl wkph ; store
     lac mone  ; load -1
     sacl mpc  ; store it in the cosine multiplier
     b getem   ; go read tables
thfr: lac mone  ; multiplier for bottom half
     sacl mps  ; store
     lac wkph  ; 
     sub one,13 ; map angle back to  upper half and go do it again
     b tones
getem: lac wkph,10 ; take 1st quadrant phase equiv for sine and pick 
                   ; off coarse part of phase address
     sach coph     ; store it
     lack sintbl   ;  load sine table offset into accumulator
     add coph      ; add coarse address off set
     tblr sinx     ; read the coarse sine value
     lac one,6     ;  load pi/2
     sub coph      ; subtract the coarse phase to get cosines offset
     sacl coph      
     lack sintbl
     add coph      ; do same as above for coarse cosine
     tblr cosx
     lac wkph      ; load working phase
     and maskl     ;  mask off fine addres
     sacl coph     ; store it
     lack fines    ; locate fine table offset
     add coph      ; add for offset into fine table
     tblr siny     ;  read table
     lack finec
     add coph
     tblr cosy
     zac
     lt sinx       ; load sinx
     mpy cosy      ;  multiply by cosy
     lta siny      ; load t reg with fine sin and accumulate previous prod.
     mpy cosx      ; multiply by coarse cosx to use sin(X+Y)
     apac          ; add the result to coarse sine
     sach sine     ; store it.
     lac modem 
     blz mult
     lac 1,12      ; load full address pi/2
     sub wkph      ; subtract the working phase to get cosine
     sacl wkph 
     lac wkph,10   ;  from here to the later MARK it is identical to above
     sach coph
     lack sintbl
     add coph
     tblr sinx
     lac one,6
     sub coph
     sacl coph
     lack sintbl
     add coph
     tblr cosx
     lac wkph
     and maskl
     sacl coph
     lack fines
     add coph
     tblr siny
     lack finec
     add coph
     tblr cosy
     zac
     lt cosy
     mpy sinx
     lta siny
     mpy cosx
     apac  ; MARK
     sach cosine ; store it in the cosine
mult: lt mps;  now we need to do a few multiplies by sign changes due to
     mpy sine ; to quadrant part of phase address
     pac;     multiply sine by sine sign (:-)  and
     sacl sine ;  store the result
     lac modem
     bgz cosm
     ret
cosm: mpy cosine;  now multiply cosine by the same
     pac
     sacl cosine ; store it
     lt mpc;  load cosine differentiator from sine sign (:-)
     mpy cosine;  multiply
     pac
     sacl cosine ; store
     ret
     end
;  Ebbly Ebbly Ebbly thats all folks
ÿ


