📄 an_008.asm
字号:
BCF STATUS, RP1 ; Select Bank0
CLRF PORTC ; Clear output data latches
CLRF PORTB ; Clear output data latches
BSF STATUS, RP0 ; Select Bank1
MOVLW 0x08 ; PORTC: Pin 0, 1 og 2 as output
; (PDATA, CLOCK and STROBE)
MOVWF TRISC ; PORTC: Pin 3 as input (DIO)
MOVLW 0X32 ; PORTB: Pin 0 og 2 as output
; (CLK_OUT and DATA_OUT)
MOVWF TRISB ; PORTB: Pin 1, 4 og 5 as input
; (DATA_IN, RX/TX and PD)
BCF STATUS, RP0 ; Select Bank0
GOTO mode_decision ; Go to mode_decision
;*****************************************************************************
; Interrupt handler
;*****************************************************************************
ServiceInterrupt:
BTFSC INTCON, RBIF ; Check if external interrupt
; (PD or RX/TX)
GOTO mode_decision ; If external interrupt ->
; go to mode_decision
interrupt_internal:
BTFSC MODE, RXTX ; Check if system was in RX/TX-mode
; before interrupt
GOTO mode_RX_routine ; If RXTX=1 ->go to mode_RX_routine
GOTO mode_TX_routine ; If RXTX=0 ->go to mode_TX_routine
mode_decision:
MOVF PORTB, 0 ; Read PORTB
MOVWF TEMP ; Store PORTB in TEMP
BTFSC TEMP, 4 ; Check PD
GOTO mode_PD ; If PD=1 -> go to mode_PD
BTFSC TEMP, 5 ; Check RX_TX
GOTO mode_RX ; If RX_TX=1 ->go to mode_RX
GOTO mode_TX ; If RX_TX=0 ->go to mode_TX
;*****************************************************************************
;******************* RX-MODE *************************************************
;*****************************************************************************
; Initialisation of the RX-mode. The CC700/CC900 is configured and registers
; used in MCU are initialised. The TMR0-interrupt is scaled for the correct
; data-rate, and enabled. Waits for interrupt.
;*****************************************************************************
mode_RX:
BSF STATUS, RP0 ; Select Bank1
BSF TRISC, DIO ; PORTC: Set DIO-pin as input
BCF STATUS, RP0 ; Select Bank0
CCX00_config_RX: ; Download configuration to CCX00 with
; CLOCK, PDATA og STROBE (table
; look-up: TABLE_RX)
MOVLW TABLE_PT_val ; TABLE_PT initialy set to 0 ->
MOVWF TABLE_PT ; Shows where in the table to look up
; (From 0 to 15).
CLRF REG_COUNTER ; Counts the registers configured in
; CC700/CC900 (8 16bit registers).
; Initially 0.
BCF CONTROL, CONF_LOOP ; Two loops are used.
; CONF_LOOP=0 -> loop_inner_RX_1
; CONF_LOOP=1 -> loop_inner_RX_2
BCF PORTC, STROBE ; Set STROBE=0
BSF PORTC, CLOCK ; Set CLOCK=1
loop_outer_RX: ; This loop reads values from TABLE_RX
; and stores them in CONFIG_REG.
CLRF BIT_COUNTER ; Clear BIT_COUNTER. Counts the bits
; read from CONFIG_REG.
CALL Table_RX ; Look-up table
MOVWF CONFIG_REG ; Value read from TABLE_RX is
; stored in CONFIG_REG
INCF TABLE_PT, 1 ; Increment table pointer. Read next
; register next time.
BTFSC CONTROL, CONF_LOOP ; Checks which loop to execute
GOTO loop_inner_RX_2 ; CONF_LOOP=0 -> loop_inner_RX_1.
; CONF_LOOP=1 -> loop_inner_RX_2
loop_inner_RX_1: ; Used for _H regisers from table.
; MSB of CC700/CC900 registers
RLF CONFIG_REG, 1 ; Rotate CONFIG_REG.
; Most significant bit moves to CARRY
BTFSC STATUS, CARRY ; Check if PDATA should be high
BSF PORTC, PDATA ; If high -> Set PDATA=1
BTFSS STATUS, CARRY ; Check if PDATA should be low
BCF PORTC, PDATA ; If low -> Set PDATA=0
BCF PORTC, CLOCK ; Set CLOCK=0. For 50% duty cycle
; configuration clock -> Include 4 NOP
INCF BIT_COUNTER, 1 ; Increase BIT_COUNTER. Another bit is
; read.
BSF PORTC, CLOCK ; Set CLOCK=1
BTFSS BIT_COUNTER, 3 ; Check if all 8 bits in register
; CONFIG_RX have been read.
GOTO loop_inner_RX_1 ; If not all 8 bits have been read ->
; Go to loop_inner_RX_1
BSF CONTROL, CONF_LOOP ; This loop is done. Execute
; loop_inner_RX_2 next time.
GOTO loop_outer_RX ; If all 8 bits have been read ->
; Go to loop_outer_RX
loop_inner_RX_2: ; Used for _L regisers from table.
; LSB of CC700/CC900 registers
RLF CONFIG_REG, 1 ; Rotate CONFIG_REG.
; Most significant bit moves to CARRY
BTFSC STATUS, CARRY ; Check if PDATA should be high
BSF PORTC, PDATA ; If high -> Set PDATA=1
BTFSS STATUS, CARRY ; Check if PDATA should be low
BCF PORTC, PDATA ; If low -> Set PDATA=0
BCF PORTC, CLOCK ; Set CLOCK=0.
INCF BIT_COUNTER, 1 ; Increase BIT_COUNTER. Another bit is
; read.
BTFSC BIT_COUNTER, 3 ; Check if all 8 registers have
; been read.
GOTO set_strobe_RX ; If all 8 bits have been read ->
; Go to set_strobe_RX.
BSF PORTC, CLOCK ; Set CLOCK=1
GOTO loop_inner_RX_2 ; If not all 8 bits are read ->
; Go to loop_inner_RX_2
set_strobe_RX:
BSF PORTC, STROBE ; Set STROBE=1
BSF PORTC, CLOCK ; Set CLOCK=1
BCF PORTC, STROBE ; Set STROBE=0
INCF REG_COUNTER, 1 ; Increase REG_COUNTER. An entire 16
; bit register in the CC700/CC900 has
; been configured.
BCF CONTROL, CONF_LOOP ; Do loop_inner_RX_1 next time
BTFSS REG_COUNTER, 3 ; Check if all 8 registers in
; CC700/C900 have been configured
GOTO loop_outer_RX ; If not-> Go to loop_outer_RX
BCF PORTC, STROBE ; Set STROBE=0
BCF PORTC, CLOCK ; Set CLOCK=0
init_RX: ; Give registers initial values
CLRF X ; X=00000000
MOVLW 0x08
MOVWF A ; A=1000 (LSB)
MOVWF An1 ; An1=1000 (LSB)
MOVWF An2 ; An2=1000 (LSB)
CLRF R ; R=000 (LSB)
CLRF COUNT ; COUNT=000 (LSB)
CLRF CONTROL ; CONTROL=00 (LSB)
MOVLW A_LIMIT_val
MOVWF A_LIMIT ; A_LIMIT=A_LIMIT_val
MOVLW A_LIMIT_val2
MOVWF A_LIMIT2 ; A_LIMIT2=A_LIMIT_val2
; (>4, Must not sync on 000..)
MOVLW COUNT_LIMIT_val
MOVWF COUNT_LIMIT ; COUNT_LIMIT=COUNT_LIMIT_val
CLRF INPUT ; INPUT=0 (LSB)
BSF MODE, RXTX ; Set RXTX=1 -> shows RX-mode after
; TMR0-interrupt
enable_interrupt_RX: ; Enables interrupt in RX-mode
MOVLW 0xFD
MOVWF TMR0 ; Change TMR0 register value (first
; interrupt after just a short while)
BSF STATUS, RP0 ; Select Bank1
MOVLW Rate_RX
MOVWF OPTION_REG ; Set TIMER0 Rate
BCF STATUS, RP0 ; Select Bank0
MOVLW 0xA8
MOVWF INTCON ; Enables interrupts (external and
; internal) -> GIE=1, T0IE=1, RBIE=1,
; others=0 (incl RBIF OG T01F)
wait_for_interrupt:
; Update sync pin
BTFSS CONTROL,SYNC ; If SYNC bit is set,
BCF PORTC, 4 ; set SYNC pin
BTFSC CONTROL,SYNC ; If SYNC bit is cleared,
BSF PORTC, 4 ; clear SYNC pin
GOTO wait_for_interrupt ; Loop. Wait for interrupt.
; Return here after TMR0-interrupt
;*****************************************************************************
;*********** TMR0-INTERRUPT IN RX-MODE ***************************************
;*****************************************************************************
; Each time an interrupt occurs, the DIO-pin is sampled.
; 8 interrupts (samples) per bit. Resynchronisation is done after each bit.
;*****************************************************************************
mode_RX_routine: ; TMR0-interrupt routine in RX-mode
MOVLW TIMING_RX
MOVWF TMR0 ; TMR0=TIMING_TX
BCF INPUT, DI ; Clear DI bit in INPUT-register
BTFSC PORTC, DIO ; Check DIO-pin
BSF INPUT, DI ; If DIO=1 -> DI=1
store_two_last_A: ; Store two last values of A
MOVF An1, 0
MOVWF An2 ; An2=An1
MOVF A, 0
MOVWF An1 ; An1=A
calculate_A: ; Calculate new A
BCF STATUS, CARRY ; Clear CARRY
BTFSC INPUT, DI ; Check DI (DIO-pin)
BSF STATUS, CARRY ; If DIO was 1 -> CARRY=1
RRF X, 1 ; Shift DIO value into X (from right)
MOVLW 0X08
XORWF X, 1 ; Inverts bit nr 4 in X
BTFSS X, 7 ; If X7=0 -> Increment A
INCF A, 1
BTFSS STATUS, CARRY ; If CARRY=0 -> Decrement A
DECF A, 1
BTFSC X, 3 ; If X3=1 -> Decrement A
DECF A, 1
BTFSS X, 3 ; If X3=0 -> Increment A
INCF A, 1
sample_number:
BTFSC CONTROL, R_ENABLE ; Check if R_ENABLE=1
GOTO resync ; If R_ENABLE=1 -> Go to resync
MOVF R, 0
XORLW SAMPLE_ALL ; R xor 00000111
BTFSC STATUS, Z ; Check if R=111
GOTO sync ; If R=111 -> Go to sync
MOVF R, 0
XORLW SAMPLE_HALF ; R xor 00000011
BTFSC STATUS, Z ; Check if R=011
BSF PORTB, CLK_OUT ; If R=011 -> Set CLK_OUT =1
INCF R, 1 ; R=R+1
GOTO end_interrupt_RX
sync:
BTFSC CONTROL, SYNC ; Check SYNC-bit in CONTROL-register
GOTO sync_ok ; If SYNC=1 -> Go to sync_ok
MOVF A_LIMIT2, 0
SUBWF A, 0 ; A-A_LIMIT2
MOVWF TEMP ; Store difference in TEMP
BTFSS TEMP, 7 ; Check if TEMP is pos/neg
; (A>/<A_LIMIT)
GOTO sync_A_upper ; If A>=A_LIMIT2 (DIO=1) -> Go to
; sync_A_upper
CLRF COUNT ; If A<A_LIMIT -> clear COUNT
CLRF R ; Clear R
BSF CONTROL, R_ENABLE ; Set R_ENABLE=1
GOTO end_interrupt_RX
sync_ok: ; Detect loss of sync
MOVF A, 0
SUBLW A_SYNC_LIMIT_hi ; W=A_SYNC_LIMIT_hi-A
MOVWF TEMP ; Store difference in TEMP
BTFSC TEMP,7 ; Skip if result positive
GOTO signal_OK ; Result is negative, signal is OK
MOVF A,0
SUBLW A_SYNC_LIMIT_lo ; W=A_SYNC_LIMIT_lo-A
MOVWF TEMP ; Store difference in TEMP
BTFSS TEMP,7 ; Skip if result negative
GOTO signal_OK ; Result is positive, signal is OK
; Signal is not OK
INCF BIT_ERRORS,1 ; Increase number of detected errors
MOVF BIT_ERRORS,0
SUBLW BIT_ERROR_LIMIT_val ; W=BIT_ERROR_LIMIT_val-BIT_ERRORS
BTFSS STATUS,Z ; Skip if zero
GOTO sync_ok2 ; Continue
; Reached error limit
BCF CONTROL,SYNC ; Clear sync bit
signal_OK:
CLRF BIT_ERRORS ; Clear errors
sync_ok2:
SUBWF A, 0 ; A-A_LIMIT
MOVWF TEMP ; Store difference in TEMP
BTFSS TEMP, 7 ; Check if TEMP is pos/neg
; (A>/<A_LIMIT)
GOTO data_out_high ; If A>=A_LIMIT (DIO=1) ->
; Go to data_out_high
BCF PORTB, DATA_OUT ; If A<A_LIMIT (DIO=1) ->
; Set DATA_OUT=0
BCF PORTB, CLK_OUT ; Set CLK_OUT=0
CLRF R ; Clear R
BSF CONTROL, R_ENABLE ; Sett R_ENABLE=1
GOTO end_interrupt_RX
data_out_high:
BSF PORTB, DATA_OUT ; Set DATA_OUT=1
BCF PORTB, CLK_OUT ; Set CLK_OUT=0
CLRF R ; Clear R
BSF CONTROL, R_ENABLE ; Set R_ENABLE=1
; (resync next interrupt)
NOP
GOTO end_interrupt_RX
sync_A_upper: ; Synchronise; bit received is a 1
MOVF COUNT_LIMIT, 0
SUBWF COUNT, 0 ; COUNT-COUNT_LIMIT
BTFSC STATUS, Z ; Z=0 if COUNT=COUNT_LIMIT
BSF CONTROL, SYNC ; If COUNT=COUNT_LIMIT -> Set SYNC=1
INCF COUNT, 1 ; COUNT=COUNT+1
CLRF R ; Clear R
BSF CONTROL, R_ENABLE ; Set R_ENABLE=1
NOP
GOTO end_interrupt_RX
resync:
MOVF An1, 0
SUBWF An2, 0 ; An2-An1
MOVWF TEMP1 ; Store difference in TEMP1
BTFSS TEMP1, 7 ; Check if TEMP1 is pos/neg
; (An2>/<An1)
GOTO resync_1 ; If An2>=An1 -> Go to resync_1
MOVF A, 0
SUBWF An1, 0 ; An1-A
MOVWF TEMP2 ; Store difference in TEMP2
BTFSC TEMP2, 7 ; Check if TEMP2 is pos/neg (An1>/<A)
GOTO resync_2 ; If An1<A -> Go to resync_2
INCF R, 1 ; R=R+1 (no resync)
GOTO end_interrupt_RX2
resync_1:
MOVF A, 0
SUBWF An1, 0 ; An1-A
MOVWF TEMP2 ; Store difference in TEMP2
BTFSS TEMP2, 7 ; Check if TEMP2 is pos/neg (An1>/<A)
GOTO resync_3 ; If An1>=A -> Go to resync_3
BTFSC CONTROL, SYNC ; Check SYNC-bit in CONTROL-register
INCF R, 1 ; If SYNC=1 -> R=R+1 (no resync)
GOTO end_interrupt_RX2
resync_2:
NOP
BTFSS CONTROL, SYNC ; Check SYNC-bit in CONTROL-register
GOTO end_interrupt_RX2 ; If SYNC=0 -> Go to end_interrupt_RX
MOVF A_LIMIT, 0
SUBWF An1, 0 ; A-A_LIMIT
MOVWF TEMP ; Store difference in TEMP
BTFSC TEMP, 7 ; Check if TEMP is pos/neg
; (An1>/<A_LIMIT)
GOTO r_add_2 ; If not An1>=A_LIMIT -> Go to r_add_2
GOTO end_interrupt_RX2
resync_3:
MOVF TEMP1, 1 ; TEMP1 written to itself
; (Z is affected)
BTFSC STATUS, Z ; Check if An2=An1
GOTO no_resync ; If An2=An1 -> Go_to no_resync
MOVF TEMP2, 1 ; TEMP2 written to itself
; (Z is affected)
BTFSC STATUS, Z ; Check if An1=A
GOTO no_resync ; If An1=A -> Go_to no_resync
MOVF A_LIMIT, 0
SUBWF An1, 0 ; A-A_LIMIT
MOVWF TEMP ; Store difference in TEMP
BTFSS TEMP, 7 ; Check if TEMP is pos/neg
; (An1>/<A_LIMIT)
GOTO r_add_2 ; If An1>=A_LIMIT -> Go to r_add2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -