;  		AMSAT/TAPR DSP BPSK demod for PIII satellites
;               Sample rate should be set to 8000 samples/sec. 
;                       code by Bob McGwier N4HY
;
     org 0
     b go
;
;      Okay Jose' set up equates for data memory etc.
;
        org 10H  ;  code should begin at memory address 16 cause David
           ;  does something strange with locations 0-15.  Does
           ;  he in fact document this?
	
sine:   equ 0    ;  will store sine values from tone
one:    equ 1      ;  guess what goes here duhhhhh!
freq:   equ 2    ;  PLL frequency stored here
phase:  equ 3    ;  PLL phase stored here
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
bitpc:  equ 20   ;  freqo is assigned one of the values above for remod

xn0:    equ 21   ;  place  for storing all the values for the "I" or data arm
xn1:    equ 22
xn2:    equ 23
xn3:    equ 24
xn4:    equ 25
xn5:    equ 26
xn6:    equ 27
xn7:    equ 28
xn8:    equ 29
xn9:    equ 30
xn10:   equ 31
xn11:   equ 32
xn12:   equ 33
xn13:   equ 34
xn14:   equ 35
xn15:   equ 36
xn16:   equ 37
xn17:   equ 38
xn18:   equ 39
xn19:   equ 40
xn20:   equ 41
xn21:   equ 42
xn22:   equ 43
yn0:    equ 44  ; storage for values in "Q" or phase error arm.
yn1:    equ 45
yn2:    equ 46
yn3:    equ 47
yn4:    equ 48
yn5:    equ 49
yn6:    equ 50
yn7:    equ 51
yn8:    equ 52
yn9:    equ 53
yn10:   equ 54
yn11:   equ 55
yn12:   equ 56
yn13:   equ 57
yn14:   equ 58
yn15:   equ 59
yn16:   equ 60
yn17:   equ 61
yn18:   equ 62
yn19:   equ 63
yn20:   equ 64
yn21:   equ 65
yn22:   equ 66
c0:     equ 67  ; Phase error
maskf:  equ 68  ; frequency mask so that frequency doesn't try and leave
                ; proper range
H9:	equ 69
H10:    equ 70  ;  arm filter value too large to use mpyk
H11:    equ 71  ;  arm filter value too large to use mpyk
sweep:  equ 74  ;  contains sweep value  +/- one frequency unit per sample
highfq: equ 75  ;  high end of sweep range
lowfq:  equ 76  ;  low end of sweep range
clkfr:	equ 78
clkph:	equ 79
ch4:	equ 80
ch5:	equ 81
ch6:	equ 82
bd0:	equ 83
bd1:	equ 84
bd2:	equ 85
bd3:	equ 86
bd4:	equ 87
bd5:	equ 88
bd6:	equ 89
bd7:	equ 90
bd8:	equ 91
bd9:	equ 92
bd10:	equ 93
bd11:	equ 94
bd12:	equ 95
cd0:	equ 96
cd1:	equ 97
cd2:	equ 98
cd3:	equ 99
cd4:	equ 100
cd5:	equ 101
cd6:	equ 102
cd7:	equ 103
cd8:	equ 104
cd9:	equ 105
cd10:	equ 106
cd11:	equ 107
cd12:	equ 108
clkav:	equ 109
bit:	equ 110
clock:	equ 111
clocke:	equ 112
bito:	equ 115
bit0:	equ 18
bit1:	equ 19
bita0:	equ 113
bita1:	equ 114
clkit:  equ 116
bitm0:  equ 117
bitm1:  equ 118
tbit:   equ 119
tclk:   equ 120
tfrq:   equ 121
tph:    equ 122
tcnt:   equ 123
carof:  equ 124
inty:   equ 125
eom:	equ 126
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
armfilt: dw  5054   ; H9 
         dw  7679   ; H10
	 dw  8706   ; H11
	 dw  4769   ; CH4 
	 dw  6557   ; CH5 
	 dw  7249   ; CH6 
go:  ldpk 0         ; make sure that we are pointing to 0 data page
     larp ar0
     lark ar0,1
     lark ar1,19
     lack one   ; make and store one
     sacl one
     
     lack armfilt ; store address of the too large coefficients
     tblr H9
     add one
     tblr H10
     add one
     tblr H11
     add one
     tblr CH4
     add one
     tblr ch5
     add one
     tblr ch6
     lac one,11  ; make and store DAC converter mask
     sacl masko
     lac one,13   ; make and store frequency mask
     sub one
     sacl maskf
     lt one
     mpyk 3072  ; 1500Hz
     pac
     sacl freq
     lt one
     mpyk 4095  ; make and store high end of sweep range
     pac
     sacl highfq
     lt one
     mpyk 2400 ; make and store low end of sweep range
     pac
     sacl lowfq
     zac
     sub one
     sacl mone  ; make and store minus one
     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;
     zac
     sacl inty
     sacl phase
     sacl clkph
     sacl tph
     sacl clkph
     lac one
     sacl sweep
     lt one
     mpyk 1638  ; make and store clock rate (1638 = 800 Hz)
     pac
     sacl clkfr
     lt one
     mpyk 3072
     pac
     sacl tfrq
     
;  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

;    modulator/status/misc output

     lac bito,12
     addh masko
     sach yn0
     out yn0,pa4   ; send bito to DAC
     out bitpc,pa7 ;  output control word to PC
	lac inty   ; load the PC interrupt control word
 	bz noi
	zac        ; yes
	sacl inty
	out 6,6   ; tell the PC that we are ready

;    end output

;    Determine transmit bit timing

noi: larp 1   ; transmit timing auxiliary register
     banz noty ;  is time to tick the clock for the PC?

     lark ar1,19  ; yes,reset output bit counter
     zac
     sacl tcnt    ; reset Manchester (split phase) counter
     lac one,2    ; get ready to tick the clock in the PC control word
     sacl c0
     lac bitpc    ; load the control word
     xor c0       ; tick the <TX> clock
     sacl bitpc   ; store the new PC control word
     lac inty
     or one
     sacl inty
     in  c0,7     ; input the PC side control word
     lac one,4
     and c0       ; pick off the eye or modulator control bit
     sacl eom
     lac one,3    ; pick off the transmit bit
     and c0
     bgz tpo      ; is it zero ?
     lac mone     ; yes set bit multiplier to minus one
     sacl tbit
     b noty
tpo: lac one      ; No it is a one so set the multiplier to one
     sacl tbit

noty: 
	

;    Manchester the bit

     lac tcnt    ; Find out if we are half way through the bit
     sub one,3
     sub one,2   ; if tcnt is ten, it is time to split the bit
     bnz dnch    ; if we are not half way, don't change it
     lt mone     ;  We are halfway so change the sign of the bit multiplier
     mpy tbit
     pac
     sacl tbit
dnch: lac tcnt   
     add one     ;  Increment ther Manchester (split phase) counter
     sacl tcnt

;    Begin modulator
     lac eom
     bnz eye
     lac mone
     sacl modem ; real tone
     lack one  ;
     sacl mps  ;   Restore sine and cosine quadrant multipliers
     sacl mpc  ;
     lac tph  
     add tfrq ; increment the modulator phase, tph, by the modulator frq, tfrq
     and mask
     sacl tph
     call tones  ; get the sinusoid
     lt sine
     mpy tbit   ; multiply by the bit
     pac
     sacl bito  ; store for the DAC  to output to the transmitter


;    Begin demodulator
eye: lack one
     sacl modem  ; store control that makes complex tone
     lack one  ;
     sacl mps  ;   Restore sine and cosine quadrant multipliers
     sacl mpc  ;
     lac phase
     call tones ; go make complex tone

     lt xn0  ; load the current sample
     mpy cosine; multiply by cosine
     pac
     sach yn0,1 ; store it Q channel current sample
     mpy sine ; multiply sample by sine
     pac
     sach xn0,1 ; now store it in current sample place for I channel
     
;     Low pass for each sample cutoff is at 800 Hz. Carrier is 20-25 dB down

;     First lowpass I arm product to get the lower frequency mixer products

     zac
;
     lt xn22
     mpyk -117
;
     ltd xn21
     mpyk 675
;
     ltd xn20
     mpyk 647
;
     ltd xn19
     mpyk 325
;
     ltd xn18
     mpyk -453
;
     ltd xn17
     mpyk -1303
;
     ltd xn16
     mpyk -1513
;
     ltd xn15
     mpyk -459
;
     ltd xn14
     mpyk 1949
;
     ltd xn13
     mpy H9
;
     ltd xn12
     mpy H10
;
     ltd xn11
     mpy H11
;
     ltd xn10
     mpy H10
;
     ltd xn9
     mpy H9
;
     ltd xn8
     mpyk 1949
;
     ltd xn7
     mpyk -459
;
     ltd xn6
     mpyk -1513
;
     ltd xn5
     mpyk -1303
;
     ltd xn4
     mpyk -453
;
     ltd xn3
     mpyk 325
;
     ltd xn2
     mpyk 647
;
     ltd xn1
     mpyk 675
;
     ltd xn0
     mpyk -117
;
     apac
;
     sach xn0,1
     
;  Now do the Q arm to get the lower frequency mixer products.

     zac
;
     lt yn22
     mpyk -117
;
     ltd yn21
     mpyk 675
;
     ltd yn20
     mpyk 647
;
     ltd yn19
     mpyk 325
;
     ltd yn18
     mpyk -453
;
     ltd yn17
     mpyk -1303
;
     ltd yn16
     mpyk -1513
;
     ltd yn15
     mpyk -459
;
     ltd yn14
     mpyk 1949
;
     ltd yn13
     mpy H9
;
     ltd yn12
     mpy H10
;
     ltd yn11
     mpy H11
;
     ltd yn10
     mpy H10
;
     ltd yn9
     mpy H9
;
     ltd yn8
     mpyk 1949
;
     ltd yn7
     mpyk -459
;
     ltd yn6
     mpyk -1513
;
     ltd yn5
     mpyk -1303
;
     ltd yn4
     mpyk -453
;
     ltd yn3
     mpyk 325
;
     ltd yn2
     mpyk 647
;
     ltd yn1
     mpyk 675
;
     ltd yn0
     mpyk -117
;
     apac
;
     sach yn0,1

;  Okay we now have filtered products with data bauding pseudo base banded
;  Let's close the loop and lock on

     lac xn0;  Hard limit data line for phase error detector
     sacl bd0;  Input data into delay line so that demanchester can occur at
             ;  Zero crossing.
     bgez pdps  ; is data baud a plus one ?
     lt yn0     ; get ready for a multiply
     mpyk -1    ; multiply phase error arm by -1
     pac
     sacl yn0
pdps: lt carof
     mpyk 7     ; leaky integrate the phase error
     pac 
     sacl cosy
     lac carof,15
     add cosy,12  ; take 7/8 of the old value and add it to the gain times
     add yn0,10   ; the current phase error observation. (LPF)
     sach carof
;;	lac carof,3  ;  uncomment these two lines to send the
;;	sacl bito  ;  VCO error voltage out the D/A
     lac yn0,10  ; add a small amount of the current phase error to
     addh carof  ; the integrator output.
     sach c0     ; this is the phase correction
     lac c0      ;  load correction
delph: add phase   ; add the old phase 
     add freq    ; add the phase increment (frequency)
     and mask    ; modulo 2*pi
     sacl phase  ; store it for next sample complex tone generation step
	lac eom
	bz mod
	lac xn0     ; uncomment these two lines to send eye patterns out
	sacl bito   ; the D/A port
;	lac sine,11 ; uncomment these two to hear recovered carrier.
;	sach bito


;    Assuming lock, let's recover clock using a PLL on a nonlinearity
;    generating a clock tone

mod: lt xn0
     mpy xn0    ; square the current data arm value
     pac
     apac
     apac       ; add it to the accumulator three times to raise the number
		; of significant bits in the high word
     sach cd0,1 ; shift left 4 and store the high word
     lt clkav
     mpyk 3    ; we will LPF with an exponential decay filter to estimate
     pac        ;  the average amplitude of the clock signal.  Multiply old
     sacl cosy
     lac cd0,13 ; load one sixteenth of the current clock signal value
     abs
     add clkav,15  ; value first by fifteen and then divide by 16.
     add cosy,13
     sach clkav
     lac cd0,2     ;load it shifting one up to increase significance
     sub clkav,2
     sacl cd0      ; subtract the average value, that is remove the DC.
;	sacl bito
     lac mone  
     sacl modem ; real tone
     lack one  ;
     sacl mps  ;   Restore sine and cosine quadrant multipliers
     sacl mpc  ;
     lac one,12    ;  we are going to use the tone generator and we need
     sub clkph     ; cosine so take pi/2 - phase and then find the sine of
     add one,14    ; that after doing mod 2*pi
     and mask
     call tones    ; get the cosine  (which will be the sine since we did
;	lac sine,11
;	sach bito  ; un comment these two lines to see the clock tone
     lt sine       ; complimentary angle
     mpy cd0       ; multiply by the current clock tone value
     pac          
     sach cd0,1

;    filter this product to get the clock signal phase error 
;    sine(clock phase)*cosine(clock phase estimate) yields the error signal
;    LP Filter to get the lower frequency mixer products
;    Filter with cutoff at 800 Hz, doesn't need to be a great filter, just
;    the best you can do in 13 taps.  25+ dB rejection of the stuff at
;    1600.

     lt cd12
     mpyk -930
     pac
     
     ltd cd11
     mpyk -293
     apac
     dmov bd11
     
     ltd cd10
     mpyk 732
     apac
     dmov bd10
     
     ltd cd9
     mpyk 2571
     apac
     dmov bd9
     
     ltd cd8
     mpy ch4
     apac
     dmov bd8
     
     
     ltd cd7
     mpy ch5
     apac
     dmov bd7
     
     ltd cd6
     mpy ch6
     apac
     dmov bd6
     
     ltd cd5
     mpy ch5
     apac
     dmov bd5
     
     ltd cd4
     mpy ch4
     apac
     dmov bd4
     
     ltd cd3
     mpyk 2571
     apac
     dmov bd3
      
     ltd cd2
     mpyk 732
     apac
     dmov bd2
     
     ltd cd1
     mpyk -293
     apac
     dmov bd1
     
     ltd cd0
     mpyk -930
     apac
     dmov bd0
     
     sach clocke

     lt clkit
     mpyk 15   ; SLOW leak integrator,  31/32 old phase error plus
     pac
     sacl cosy
;     lac clkit,15
     lac cosy,12
;     add cosy,11
;     lac clkit,11 
     add clocke,11  ;   1/32 of the new phase error estimate
     sach clkit
     lac clocke,10  ;   add 1/32 of the current phase error observation to
     add clkit,15     ;   the integrated estimate
     sach clocke
     lac clocke     ;   load phase correction
	
dlcph: add clkph   ; add the old phase 
     add clkfr    ; add the phase increment (frequency)
     sacl clkph
     sub 1,14     ; if the phase is greater than two pi, we have hit a
     blz wait     ; baud boundary, if not, go back to wait and start over

;    We have crossed a baud boundary since the phase is >= 2^14.

     sacl clkph  ; store it for next sample complex tone generation step
;
;	We have had to comprimise.  The most we could fit, due to constraints
;       of 128 data memory data locations in page 0, is just over half the total
;       bit into our delay line.  HOWEVER, this is "the important half"
;       It is the center and contains the "peaks" around the guaranteed
;       zero crossing in the center of the bit.  Convolve with the bit shape
;       and get 0 or 1.
;
     ; de Manchester the bits in the delay line
     lt bd12
     mpyk 1024
     pac
     lt bd11
     mpyk 4095
     apac
     lt bd10
     mpyk 4095
     apac
     lt bd8
     mpyk 1024
     apac
     lt bd7
     mpyk 128
     apac
     lt bd5
     mpyk -128
     apac
     lt bd4
     mpyk -1024
     apac
     lt bd2
     mpyk -4095
     apac
     lt bd1
     mpyk -4095
     apac
     lt bd0
     mpyk -1024
     apac
     sach bit,4   ; Store the de-Manchestered bit
;    There is an ambiguity in the clock since the clock tone recovery
;    above runs at 800 Hz.  We must decide which is the REAL bit center
;    and then output that bit determined above.  This is a statistical
;    process.  We are guaranteed a bit transition in center of each
;    bit.   If we are on the boundary, the occasional change from a zero
;    to a one and vice versa causes NO transition.  The process above
;    Will yield a small positive number for abs(bit) when there is no
;    transition
     lac bit
     larp 0      ; set auxiliary register pointer to the receive clock control.
		 ; <RX> clock control register
     banz b1     ; is it bit time 0 or bit time 1
     bgz psb0    ; it is bit time zero.  Is the bit positive?
     lac mone,10    ; No  load -1
     sacl bit0   ; and store it in bit 0
     b rar0
psb0: lac one,10
     sacl bit0 
rar0: lark ar0,1  ; reset the counter  for the next two 2pi crossings.
     lac bit      ; load bit for the bit time 0, take absolute value
     abs
     sacl bita0   ; store it for later
     b wait
;    The bit time was 1 and not zero.
b1:  bgz psb1   ; is bit positive?
     lac mone,10   ; no so load -1
     sacl bit1  ; store it in bit one
     b rar1
;    yes it is positive
psb1: lac one,10   ; load one
     sacl bit1  ; store it in bit one
rar1: lac bit   ; load bit for the bit time 1, take absolute value
     abs
     sacl bita1 ; store it for later
     lack 13    ;  load the accumulator with 1101  binary
     and bitpc  ;  use it mask the PC control word to destroy old bit.
     xor one    ; tick the output clock
     sacl bitpc ; store it
     lac inty
     or one     ; setup to interrupt PC with new control word
     sacl inty
     lac bita1  ;  load the bit1 size
     sub bita0  ;  sub the bit0 size
     add bitm0  ;  integrate
     sacl bitm0 ; store it
     sub 1,12  ; let 4096 be the rails
     bgz th   ; are we greater than 4096?
     lac bitm0 ; load it again
     add 1,12   ; add 4096
     blz tl    ; still less than zero?  < -4096?
     b dbt
;   Yes we are greater than 4096, so make us 4096
th:  lac 1,12
     sacl bitm0
     b dbt
;   Yes we are less than -4096, so make us -4096
tl:  zac
     sub one,12   ; load -4096
     sacl bitm0  ; store it
dbt: lt bitm1 
     mpyk 7   ; average with 31/32 times old + 1/32 * new
     pac
     sacl cosy
     lac bitm1,15
     lac cosy,12
     add bitm0,11
     sach bitm1
     lac bitm1
;	sacl bito  ; uncomment to see which clock phase was chosen for
		   ; the true center of bit
     blz bi0  ; is the averaged size of bit0 bigger?
; NO
     lac bit1 ; load bit 1
     b outb   ; jump to modify PC control word
bi0: lac bit0
outb: 
;	sacl bito     ; uncomment to send bits out the D/A port
     blz wait ; if the bit is negative, bitpc is already setup
     lac one,1 ; if not we need to add a 1 in the 2's spot, i.e. add 2.
     or bitpc
     sacl bitpc ; store it in the PC control word
outp: b wait         ; go output and then do it again

;     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

