; /wista.jp/Xmitter.htm 
;Refer to the parent page of /wista.jp/FMXmit.htm .
;FM Transmitter NS73M driver code, on 12F509 
;  by T. Fujiwara 12/11/2013
; version 1.0

 LIST P=12F509, c=132, n=0
 include <p12f509.inc>       ; processor specific variable definitions
 __CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC
 radix   DEC 

;bit definitions
bit0        equ     0
bit1        equ     1
bit2        equ     2
bit3        equ     3
bit4        equ     4
bit5        equ     5
bit6        equ     6
bit7        equ     7
w           equ     0
f           equ     1
z           equ     2

;signal definitions, GPIO
bck         equ     5       ;clock to NS73M
bda         equ     1       ;data to NS73M
bla         equ     2       ;latch to NS73M
teb         equ     4       ;TEB from NS73M, 0=unlocked, 1=locked

;reg definitions
regadr      equ     0x07    ;gpr7 for 73M register address
regdata     equ     0x08    ;gpr8 for 73M reg data
work        equ     0x09    ;work reg
work1       equ     0x0a    ;work reg1
counter     equ     0x0b    ;wait loop counter low
counter1    equ     0x0c    ;wait loop counter high
status      equ     0x03
fsr         equ     0x04
OSCCAL      equ     0x05
gpio        equ     0x06

;========== code ============
start:
    org     0
    movwf   OSCCAL
    call    wait        ;wait for power stabilization
    movlw   0
    movwf   fsr         ;bank 0
    clrf    gpio
    movlw   b'00011001' ;port bit,  1=in 0=out, bit(0,3,4)=in, bit(1,2,5)=out
    tris    gpio
    clrf    gpio
    movlw   b'10001111' ;WPullUp
    option

;== NS73M control ==
    ;software reset: address E, data xxxx 0101
    movlw   .14       ;R14
    movwf   regadr
    movlw   b'00000101' ;software reset
    movwf   regdata
    call    send

    ;pilot on, force subcarrier
    movlw   .1        ;R1
    movwf   regadr
    movlw   b'10110100' ;d6(subcarrier) on(0), d3(pilot) on(0)
    movwf   regdata
    call    send

    ;unlock detect on, power 0.5, 1 or 2 mW
    movlw   .2
    movwf   regadr
    movlw    b'00000101' ;d2=1 unlock detect, d0,d1=01=0.5mW
;    movlw    b'00000101' ;d2=1 unlock detect, d0,d1=10=1mW
;    movlw    b'00000111' ;d2=1 unlock detect, d0,d1=11=2mW
    movwf   regdata
    call    send

    ;set frequency
    call    whatfreq    ;read jumper and find which freq
    movlw   .3
    movwf   regadr
    movf    work,w
    movwf   regdata
    call    send
    movlw   .4
    movwf   regadr
    movf    work1,w
    movwf   regdata
    call    send
    ;set local OSC band
    movlw   .8
    movwf   regadr
    movlw   b'00011011' ;last two bits define the band.
                        ; 3:<90M, 2:<96M, 1:<102M, 0:<108M
    movwf   regdata
    call    send

    ;clear 5, 7, 9, 10, 11
    movlw   .5
    call    send0
    movlw   .7
    call    send0
    movlw   .9
    call    send0
    movlw   .10
    call    send0
    movlw   .11
    call    send0

    ;set input level, pre-emphasis, pwr-on
    movlw   .0
    movwf   regadr
    movlw   b'00000001' ;00:100mV, 0:50uS, 0:preemf-on, 0,test-off, 
                        ;0:mute-off 0:xtal-off, 1:pwr-on
    movwf   regdata
    call    send

    ;set charge 1.25uA
    movlw   .6
    movwf   regadr
    movlw   b'00011010' ;000:test, 11:generator charge pump 320uA, 
                        ;01:PLL charge pump=1.25uA, 0:test
    movwf   regdata
    call    send
    call    wait        ;locks within about 400ms (340ms) 
    call    wait
    call    wait        ;600ms wait
    btfsc   gpio,teb    ;test TEB, 1=locked, 0=not-locked(Err)
    ;locked
    goto    keepsleep
    ;unlocked
    call    wait
    btfsc   gpio,teb
    goto    keepsleep
    bsf     gpio,bck    ;unlocked, seeLED

keepsleep:
    sleep
    goto    keepsleep

;====== subroutines ==========
wait: ;wait 200ms
    movlw    .0
    movwf    counter
    movlw    .195
    movwf    counter1
wt1: nop
    decfsz  counter,f
    goto    wt1        ;4us*256-1=1023us
    decfsz  counter1,f
    goto    wt1        ;(1023us+3)*195-1=200.069ms
    retlw   .0

send0:  ;clear target reg
    movwf   regadr
    movlw   b'00000000'
    movwf   regdata
send:   ;set target reg
    clrf    gpio
    btfsc   regadr,bit0
    bsf     gpio,bda    ;data
    bsf     gpio,bck    ;clock pulse, 1/4MHz * 4 = 1us,  s/b >250ns
    bcf     gpio,bck
    bcf     gpio,bda    ;1st bit comp
    btfsc   regadr,bit1
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;2nd bit comp
    btfsc   regadr,bit2
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;3rd bit comp
    btfsc   regadr,bit3
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;4th bit comp, address complete

    btfsc   regdata,bit0
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;1st bit comp
    btfsc   regdata,bit1
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;2nd bit comp
    btfsc   regdata,bit2
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;3rd bit comp
    btfsc   regdata,bit3
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;4th bit comp
    btfsc   regdata,bit4
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;5th bit comp
    btfsc   regdata,bit5
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;6th bit comp
    btfsc   regdata,bit6
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;7th bit comp
    btfsc   regdata,bit7
    bsf     gpio,bda
    bsf     gpio,bck
    bcf     gpio,bck
    bcf     gpio,bda    ;8th bit comp, data complete
    
    bsf     gpio,bla    ;latch pulse, 1us
    bcf     gpio,bla
    retlw   0

;constant definitions
table0l     equ     b'11110111' ;87.7MHz
table0h     equ     b'00101001'
table1l     equ     b'00001111' ;87.9MHz
table1h     equ     b'00101010'
table2l     equ     b'01110001' ;88.7MHz
table2h     equ     b'00101010'
table3l     equ     b'10001001' ;88.9MHz
table3h     equ     b'00101010'
table4l     equ     b'10100010' ;89.1MHz
table4h     equ     b'00101010'

whatfreq:
    ;read frequency jumper
    ;first, test if 5th state
    movlw   b'00011000' ;GP0 as out
    tris    gpio
    bsf     gpio,0
    btfss   gpio,3      ;on= possible 5th state
    goto    not5th
    bcf     gpio,0
    btfsc   gpio,3      ;off= 5th state
    goto    not5th
    movlw   b'00011001' ;set tris back to original
    tris    gpio 
jumper5th: 
    movlw   table4l
    movwf   work
    movlw   table4h
    movwf   work1
    goto    exwhat   
not5th:
    movlw   b'00011001' ;enable bit 0 input
    tris    gpio
    ;test F0 and F1 for GND
    btfss   gpio,0      ;read jumper pin, bit3(f1) and bit0(f0)
    goto    testx1      ;bit0 is off (jumper0 exists)
    ;come here if x0 case (jumper 0 not exists)
    btfss   gpio,3      ;test jumper3
    goto    jumper10    ;jumper on,off
    goto    jumper00    ;jumper off,off
testx1: ;come here if jumper0 exists
    btfss   gpio,3
    goto    jumper11    ;two jumpers
    goto    jumper01    ;no jumper3
jumper00:
    movlw   table0l
    movwf   work
    movlw   table0h
    movwf   work1
    goto    exwhat
jumper01:
    movlw   table1l
    movwf   work
    movlw   table1h
    movwf   work1
    goto    exwhat 
jumper10:
    movlw   table2l
    movwf   work
    movlw   table2h
    movwf   work1
    goto    exwhat
jumper11:
    movlw   table3l
    movwf   work
    movlw   table3h
    movwf   work1
exwhat: retlw 0

 end

;NS73M Frequency setting                        
;MHz  N        N:rounded Err(kHz) N:hex N:bin    
;87.5 10718.26   10718   -2.144   29DE  00101001 11011110          
;87.6 10730.47   10730   -3.840   29EA  00101001 11101010          
;87.7 10742.68   10743   +2.656   29F7  00101001 11110111   <==0   
;87.8 10754.88   10755   +0.960   2A03  00101010 00000011
;87.9 10767.09   10767   -0.736   2A0F  00101010 00001111   <==1   
;88.0 10779.30   10779   -2.432   2A1B  00101010 00011011          
;88.1 10791.50   10792   +4.064   2A28  00101010 00101000          
;88.2 10803.71   10804   +2.368   2A34  00101010 00110100          
;88.3 10815.92   10816   +0.672   2A40  00101010 01000000          
;88.4 10828.13   10828   -1.024   2A4C  00101010 01001100          
;88.5 10840.33   10840   -2.720   2A58  00101010 01011000          
;88.6 10852.54   10853   +3.776   2A65  00101010 01100101          
;88.7 10864.75   10865   +2.080   2A71  00101010 01110001   <==2
;88.8 10876.95   10877   +0.384   2A7D  00101010 01111101          
;88.9 10889.16   10889   -1.312   2A89  00101010 10001001   <==3
;89.0 10901.37   10901   -3.008   2A95  00101010 10010101          
;89.1 10913.57   10914   +3.488   2AA2  00101010 10100010   <==4
;89.2 10925.78   10926   +1.792   2AAE  00101010 10101110          
;89.3 10937.99   10938   +0.096   2ABA  00101010 10111010          
;89.4 10950.20   10950   -1.600   2AC6  00101010 11000110          
;89.5 10962.40   10962   -3.296   2AD2  00101010 11010010          
;89.6 10974.61   10975   +3.200   2ADF  00101010 11011111          
;89.7 10986.82   10987   +1.504   2AEB  00101010 11101011          
;89.8 10999.02   10999   -0.192   2AF7  00101010 11110111          
;89.9 11011.23   11011   -1.888   2B03  00101011 00000011          
;kyoto open, 89.1, 89.0, 88.9, 88.8, 88.7, 88.5, 87.9, 87.8, 87.7
;band=  3:<90M, 2:<96M, 1:<102M, 0:<108M