list n=0 ; Turn off page breaks in the List file
;
#DEFINE RIT
;
;********************************************************************************
; *
; COPYRIGHT NOTICE *
; *
; Copyright T Mowles VK5TM 2022 *
; AD9850_VFO-16F1827.asm *
; *
; *
; *******************************************************************************
;
;********************************************************************************
;
; Target Controller PIC16F1827
; __________
; RIT IN-----RA2 |1 18| RA1---SPARE
; PWR DETECT-RA3 |2 17| RA0---DDS_LOAD
; SPARE------RA4 |3 16| RA7---DDS_DATA
; SPARE------RA5 |4 15| RA6---DDS_CLK
; Ground-----Vss |5 14| VDD---+5 V
; ENCODER----RB0 |6 13| RB7---SPARE
; ENCODER----RB1 |7 12| RB6---LED STEP 10kHz
; STEP SW----RB2 |8 11| RB5---LED STEP 1kHz
; CAL--------RB3 |9 10| RB4---LED STEP 10Hz
; ----------
;
; *******************************************************************************
; * Device type and options *
; *******************************************************************************
;
processor 16F1827
radix dec
errorlevel -207 ; Skip found label after column 1
errorlevel -302 ; Skip out of bank nuisance messages
errorlevel -303 ; Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827: *
; *******************************************************************************
;
include <P16F1827.INC>
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
; *******************************************************************************
;
; *******************************************************************************
; * Allocate variables in general purpose register space *
; *******************************************************************************
;
CBLOCK 0x20 ; Start Data Block
AD9851_0 ; AD9850/AD9851 control word
AD9851_1 ; (5 bytes)
AD9851_2
AD9851_3
AD9851_4
fstep_0 ; Frequency inc/dec
fstep_1 ; (4 bytes)
fstep_2
fstep_3
mult_count ; Used in calc_dds_word
bit_count ; "
byte2send ;
osc_temp_0 ; Oscillator frequency
osc_temp_1 ; (4 bytes)
osc_temp_2
osc_temp_3
timer1 ; Used in delay routines
timer2 ; "
dir ; for encoder routine
encold ; for encoder routine
count
byte_count
flags ; RIT Flags
; flags,0 = 0 - RIT = 0
; flags,1 = 0 - RIT = same as last time
; flags,1 = 1 - RIT = changed
NumH_temp
NumL_temp
temp
rxf_0 ; VFO frequency if NO RIT
rxf_1 ; "
rxf_2 ; "
rxf_3 ; "
ritf_0 ; VFO frequency if RIT active
ritf_1 ; "
ritf_2 ; "
ritf_3 ; "
ENDC ; End of Data Block
CBLOCK 0x70 ; Use bank common locations - saves bank switching
freq_0 ; Frequency (hex)
freq_1 ; (4 bytes)
freq_2 ;
freq_3 ;
osc_0 ; Current oscillator
osc_1 ; (4 bytes)
osc_2
osc_3
step_size ; 0=10Hz 1=1kHz 2=10kHz step size
NumH ; Used in RIT routine
NumL ; "
ENDC ; End of Data Block
;
; *******************************************************************************
; * General equates. These may be changed to accommodate the reference clock *
; * frequency, the desired upper frequency limit, and the default startup *
; * frequency. *
; *******************************************************************************
;
; For 125 MHz Oscillator =======
ref_osc_3 equ 0x22 ; Most significant osc byte
ref_osc_2 equ 0x5C ; Next byte
ref_osc_1 equ 0x17 ; Next byte
ref_osc_0 equ 0xD0 ; Least significant byte
;
; Change limits to suit
;
; Limit_0...3 contains the upper limit frequency as a 32 bit integer.
;
limit_hi_3 equ 0x00 ; Most significant byte for 5.5 MHz
limit_hi_2 equ 0x53 ; Next byte
limit_hi_1 equ 0xEC ; Next byte
limit_hi_0 equ 0x60 ; Least significant byte
;
; Low_limit_3..0 contains the lower frequency limit as a 32 bit integer
;
limit_low_3 equ 0x00 ; Most significant byte for 5.0 MHz
limit_low_2 equ 0x4C ; Next byte
limit_low_1 equ 0x4B ; Next byte
limit_low_0 equ 0x40 ; Least significant byte
;
; Default contains the default startup frequency as a 32 bit integer.
; This will be overwritten by the frequency save routine in normal use.
;
default_3 equ 0x00 ; Most significant byte for 5.0 MHz
default_2 equ 0x4C ; Next byte
default_1 equ 0x4B ; Next byte
default_0 equ 0x40 ; Least significant byte
;
; Frequency at which Calibration will take place
;
cal_freq_3 equ 0x00 ; Most significant byte for 5.250 MHz
cal_freq_2 equ 0x50 ; Next byte
cal_freq_1 equ 0x1B ; Next byte
cal_freq_0 equ 0xD0 ; Least significant byte
;
EEstartup_adr equ 4 ; Location of startup frequency in EEPROM
;
#IFDEF RIT
#define center 486 ; RIT pot center value///////////////////////////
#ENDIF
;
; *******************************************************************************
; * Setup the initial constant, based on the frequency of the reference *
; * oscillator. This can be tweaked with the calibrate function. *
; *******************************************************************************
;
ORG 0xF000 ; For 16F1827
; ref_osc bytes must be first 4 bytes of EEPROM
DATA ref_osc_0
DATA ref_osc_1
DATA ref_osc_2
DATA ref_osc_3
; startup frequency bytes must be next 4 bytes of EEPROM
DATA default_0 ; startup -> freq_0
DATA default_1 ; startup -> freq_1
DATA default_2 ; startup -> freq_2
DATA default_3 ; startup -> freq_3
DATA 0
;
; *******************************************************************************
; * Assign names to IO pins. *
; *******************************************************************************
#DEFINE DDS_clk LATA,6 ; AD9850/AD9851 write clock
#DEFINE DDS_dat LATA,7 ; AD9850/AD9851 serial data input
#DEFINE DDS_load LATA,0 ; Update pin on AD9850/AD9851
#DEFINE CAL_sw PORTB,3 ; Cal switch input
#DEFINE STEP_sw PORTB,2 ; Step switch input
;
;
; 16F1827 Oscillator setup
; OSCCON - Oscillator control reg.
; ---------------------------------
; SPLLEN bit 7 enable PLL x4
; 1 = enabled 0 = disabled
; IRCF | bits 6-3 frequency selection
; 1111 = 16MHz HF
; 1110 = 8 or 32MHz HF
; 1101 = 4MHz HF
; 1100 = 2MHz HF
; 1011 = 1MHz HF
; 1010 = 500kHz HF
; 1001 = 250kHz HF
; 1000 = 125kHz HF
; 0111 = 500kHz MF (default)
; 0110 = 250kHz MF
; 0101 = 125kHz MF
; 0100 = 62.5kHz MF
; 0011 = 31.25kHz HF
; 0010 = 31.25kHz MF
; 000x = 31.25kHz LF
; Reserved bit 2 reserved, 0
; SCS bits 1-0: 1x = int. OSC.
; 01 = Timer1 oscillator
; 00 = determined by FOSC <2:0> in Configuration
; POR default 00111-00 500 kHz (POR = Power On Reset)
OSCCONVAL EQU b'01101000' ; 4MhZ CLOCK
;
; *******************************************************************************
; * Purpose: This is the start of the program. *
; *******************************************************************************
;
;
ORG 0x0000
BRA start ; Jump to main program
ORG 0x0004 ; interrupt routine data save
; BRA start
bcf INTCON,GIE ; Clear Global Interrupt Enable bit
;
BANKSEL PIR2
bcf PIR2,C2IF ; Clear comparator flag
movlb 0
;
clrf PORTA
clrf PORTB
;
retfie ; Enable general interrupts and return
;
start
clrf INTCON ; clear INTCON
clrf PORTA
clrf PORTB
clrf step_size
clrf NumH_temp
clrf NumL_temp
; Set PIC oscillator frequency
banksel OSCCON ; Select OSCCON
movlw OSCCONVAL ;
movwf OSCCON ; Loads the wanted oscillator value
; Configures I/O as analog/digital
Banksel ANSELA
; movlw b'00001000' ; RA3 analog all others digital
movlw b'00001100' ; RA2:3 analog all others digital
movwf ANSELA
clrf ANSELB ; PORTB all digital
; Disable all wakeup pull-ups
Banksel WPUA
clrf WPUA
clrf WPUB
banksel OPTION_REG
movlw b'10000000' ; Pull-ups disabled
movwf OPTION_REG ;
;
; movlw b'00111110' ; PORTA (RA0 & 6:7 outputs RA1:5 inputs)
movlw b'00111110' ; ##TEST TEMP## PORTA (RA0 & 6:7 outputs RA1:5 inputs)
movwf TRISA ;
movlw b'10001111' ; PORTB 0:3 & 7 inputs 4:6 outputs
movwf TRISB ; NOTE: Pull-up via 10k resistor all unused pins
;
BANKSEL FVRCON
; movlw b'10001100' ; FVR on, Comparator ref 4.096V
movlw b'10001000' ; FVR on, Comparator ref 2.048V
movwf FVRCON
;
movlb 0
movlw 40 ; Delay for FVR to stabilise
movwf temp
decfsz temp,f
BRA $-1
BANKSEL CM1CON0
clrf CM1CON0
clrf CM1CON1
movlw b'10100011'
movwf CM2CON1 ; Positive interrupt on
; Negative interrupt off
; C2VP connects to FVR
; C2VP connects to FVR
; Unimplemented
; Unimplemented
; C2VN connects to C12IN3- pin - RA3
; C2VN connects to C12IN3- pin - RA3
movlw b'10000110'
movwf CM2CON0 ; Comparator enabled
; Comparator Output bit polarity
; Comparator Output internal
; Comparator output is not inverted
; Unimplemented
; Comparator operates in normal power, higher speed mode
; Comparator hysteresis enabled
; Comparator output to Timer1 and I/O pin is asynchronous
movlb 0
;
; Initialize DDS Module with zero freq
;
clrf AD9851_0 ; AD9850/51 control words
clrf AD9851_1 ; (5 bytes)
clrf AD9851_2
clrf AD9851_3
clrf AD9851_4
call send_dds_word ; Send it to the DDS twice to be sure
call send_dds_word ;
;
; Enter Calibrate Mode if PORTB,3 is low when turning the power on
btfss CAL_sw ; Cal pushbutton pressed?
call calibrate ; Yes, call calibration routine
;
; Get the reference oscillator constant from the EEPROM
;
read_EEocs
;
BANKSEL EEADRL ;
clrf EEADRL ; Data Memory Address to read
call read_EEPROM ; Read EEPROM
movf EEDATL,W ; Get the first osc byte
movwf osc_0 ; Save osc frequency
call read_EEPROM ; Read EEPROM
movf EEDATL,W ;
movwf osc_1 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,W ;
movwf osc_2 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,W ;
movwf osc_3 ; Save it
;
; Set the power on frequency to the defined value
; (They always follow the osc bytes)
;
call read_EEPROM ; Read EEPROM
movf EEDATL,w ; Get the first default freq byte
movwf freq_0 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,w ; Get the next freq byte
movwf freq_1 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,w ; Get the next freq byte
movwf freq_2 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,w ; Get the last freq byte
movwf freq_3 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATL,w ; Get step size
movwf step_size ; Save it
movlb 0 ; Back to bank 0
call step_led
;
#IFDEF RIT
call freq_to_rxf ; Load rxf registers with start-up frequency
; call freq_to_ritf ; Load ritf registers with start-up frequency
BANKSEL ADCON1 ; Set up ADC
movlw b'11000000' ; right justify, FOSC/4 vdd and vss vref
movwf ADCON1 ;
BANKSEL ADCON0 ;
movlw b'00001001' ; select channel an2 & turn adc on
movwf ADCON0 ;
movlb 0
rit_test
movlw 50 ; Delay for ADC to stabilise
movwf count
decfsz count,f
BRA $-1
PAGESEL rit
call rit ; Get RIT value
PAGESEL $
btfss flags,0 ; RIT = 0 if flags,0 = 0
BRA exit_start ; No RIT shift, start with saved frequency
call stepdir ; Else add/subtract RIT to start frequency
#ENDIF
;
exit_start
call update_dds
;PIC Time Delay = 0.09999800 s with Osc = 4000000 Hz
movlw D'130' ;///Testing RIT function
movwf timer2 ;///Testing RIT function
movlw D'221' ;///Testing RIT function
movwf timer1 ;///Testing RIT function
loop
decfsz timer1,1 ;///Testing RIT function
goto loop ;///Testing RIT function
decfsz timer2,1 ;///Testing RIT function
goto loop
call rxf_to_freq ;///Testing RIT function
BRA rit_test ;///Testing RIT function
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; Currently doesn't progress past this point as testing RIT function
; operation during the start up phase but it does use routines past this point.
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
movf PORTB,w ; Get the power on encoder value
movwf encold ; Save it
movlw b'00000011' ; Get encoder mask (PORTB,0 and PORTB,1)
andwf encold,f ; Get encoder bits and zero all other bits
clrf dir ; Clear the knob direction indicator
clrf PIR2 ; Clear interrupt flags in PIR2
BANKSEL PIE2
bsf PIE2,C2IE ; Turn on Comparator 2 interrupt
bsf INTCON,PEIE ; Turn on Periperal interrupts
bsf INTCON,GIE ; Enable general interrupts
movlb 0
;
; *******************************************************************************
; * *
; * Purpose: This is the Main Program Loop. The program's main loop *
; * calls poll_encoder, which continuously polls the rotary shaft *
; * encoder. When the shaft encoder has changed, the direction *
; * it moved is determined and stored in 'dir'. The subroutine *
; * then returns to main. *
; * *
; * The variable fstep is added or subtracted from the current *
; * VFO frequency and stored in freq. *
; * Next, the subroutine calc_dds_word is used to calculate the DDS *
; * frequency control word from the values in freq and osc. *
; * The result is stored in AD9850/AD9851. This data is transferred *
; * to the AD9851 DDS chip by calling the subroutine send_dds_word. *
; * *
; *******************************************************************************
;
main
call poll_encoder ; Check for knob movement (wait there!)
; Return here when encoder or RIT change detected
#IFDEF RIT
btfsc flags,1 ; Has RIT changed?
BRA rit_adjust ; Yes
#ENDIF
call step ; No
call stepdir
call update_dds
BRA main
#IFDEF RIT
rit_adjust
call rxf_to_freq ; move base frequency minus old RIT to freq_0:3
btfsc flags,0 ; If RIT = 0 send base frequency to DDS
call stepdir
call update_dds
BRA main
#ENDIF
;
; *******************************************************************************
; Code for pushbutton selection of step size *
; Step size 10Hz/1kHz/10kHz *
; *******************************************************************************
step ;
clrf fstep_3 ;
clrf fstep_2 ;
clrf fstep_1 ;
clrf fstep_0 ;
step1
movfw step_size ; If step_size = 0
xorlw 0
btfsc STATUS,Z
BRA step_10hz ; Set step to 10Hz
movfw step_size ; If step_size = 1
xorlw 1
btfsc STATUS,Z
BRA step_1khz ; Set step to 1kHz
; Else step_size = 10kHz
movlw 0x10 ; 10kHz steps
movwf fstep_0 ;
movlw 0x27 ;
movwf fstep_1 ;
return
step_10hz ;
movlw 0x0A ; 10Hz steps
movwf fstep_0 ;
return
step_1khz
movlw 0xE8 ; 1kHz steps
movwf fstep_0 ;
movlw 0x03 ;
movwf fstep_1 ;
return
;
; Based on the knob direction, either add or subtract the increment,
; then update DDS.
;
stepdir
btfsc dir,0 ; Is the knob going up?
BRA up ; Yes, then add the increment
down
call sub_step ; Subtract fstep from freq
return
up
call add_step ; Add fstep to freq
call check_add ; Make sure we did not exceed the maximum
return
update_dds
call calc_dds_word ; Calculate the control word for the DDS chip
call send_dds_word ; Send the control word to the DDS chip
return
;
; *******************************************************************************
; * *
; * Purpose: Poll encoder *
; * *
; *******************************************************************************
;
poll_encoder
;
btfss CAL_sw ; Test if in calibrate mode
BRA read_encoder
;
; *******************************************************************************
; * Code for pushbutton selection of step size *
; *******************************************************************************
;
btfsc STEP_sw ; Is Step switch pushed?
#IFDEF RIT
BRA read_rit
#ELSE
BRA read_encoder ;
#ENDIF
incf step_size,f
movfw step_size ; Keep step_size in range of 0 - 2
xorlw 3
btfsc STATUS,Z
clrf step_size
step_exit
btfss STEP_sw
BRA step_exit ; Wait for Step switch to be released
call step_led
#IFDEF RIT
read_rit
PAGESEL rit ;
call rit
PAGESEL $
; TEST FLAG TO SEE IF RIT VALUE CHANGED - IF YES RETURN ELSE CARRY ON TO READ ENCODER
btfsc flags,0
return
#ENDIF
;
read_encoder
movf PORTB,w ; load switch data
andlw b'00000011' ; mask encoder B and A switches
xorwf encold,w ; same as last reading?
btfsc STATUS,Z
BRA poll_encoder ; yes, branch (no change), else
xorwf encold,w ; restore encoder bits in W
rrf encold,f ; prep for B-old ^ A-new
xorwf encold,f ; encold bit 0 = direction
rrf encold,f ; now Carry bit = direction
movwf encold ; update encold (new BA bits)
;
; encoder position has changed but we only act on a change
; that occurs when the encoder falls into one of the detent
; positions (we ignore the changes between detents)
;
xorlw b'00000011' ; detent position?
btfss STATUS,Z
BRA read_encoder ; No, go test again
bcf dir,0 ; Set direction bit based on value in STATUS,C
btfsc STATUS,C ; 1 = UP
bsf dir,0
return
;
; *******************************************************************************
; * *
; * Set step size and output pulses to indicate step size *
; * *
; *******************************************************************************
step_led
movfw step_size ; If step_size = 0
xorlw 0
btfsc STATUS,Z
BRA step_led10hz ; Set 10Hz LED
movfw step_size ; If step_size = 1
xorlw 1
btfsc STATUS,Z
BRA step_led1khz ; Set 1kHz LED
;
; ; Else set 10kHz LED
;
BANKSEL LATB
bsf LATB,6 ; 10kHz LED
nop
bcf LATB,5 ; 1kHz LED
nop
bcf LATB,4 ; 10Hz LED
movlb 0
return
;
step_led10hz
BANKSEL LATB ;
bsf LATB,4
nop
bcf LATB,5
nop
bcf LATB,6
movlb 0
return
;
step_led1khz
BANKSEL LATB
bsf LATB,5
nop
bcf LATB,6
nop
bcf LATB,4
movlb 0
return
;
; *******************************************************************************
; * *
; * Purpose: This routine adds the 32 bit value of fstep to the 32 bit *
; * value in freq. When incrementing, the fstep value is a *
; * positive integer. When decrementing, fstep is the complement *
; * of the value being subtracted. *
; * *
; * Input: The 32 bit values in fstep and freq *
; * *
; * Output: The sum of fstep and freq is stored in freq. When incrementing *
; * this value may exceed the maximum. When decrementing, it may *
; * go negative. *
; * *
; *******************************************************************************
;
org 0x100
add_step
movf fstep_0,w ; Get low byte of the increment
addwf freq_0,f ; Add it to the low byte of freq
btfss STATUS,C ; Any carry?
BRA add1 ; No, add next byte
incfsz freq_1,f ; Ripple carry up to the next byte
BRA add1 ; No new carry, add next byte
incfsz freq_2,f ; Ripple carry up to the next byte
BRA add1 ; No new carry, add next byte
incf freq_3,f ; Ripple carry up to the highest byte
add1
movf fstep_1,w ; Get the next increment byte
addwf freq_1,f ; Add it to the next higher byte
btfss STATUS,C ; Any carry?
BRA add2 ; No, add next byte
incfsz freq_2,f ; Ripple carry up to the next byte
BRA add2 ; No new carry, add next byte
incf freq_3,f ; Ripple carry up to the highest byte
add2
movf fstep_2,w ; Get the next to most significant increment
addwf freq_2,f ; Add it to the freq byte
btfss STATUS,C ; Any carry?
BRA add3 ; No, add last byte
incf freq_3,f ; Ripple carry up to the highest byte
add3
movf fstep_3,w ; Get the most significant increment byte
addwf freq_3,f ; Add it to the most significant freq
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: Check if freq exceeds the upper limit. *
; * If freq is below the limit, it is unchanged. Otherwise, it is *
; * set to equal the upper limit. *
; * *
; *******************************************************************************
;
check_add
;
; Check the most significant byte.
;
movlw 0xFF-limit_hi_3 ; Get (FF - limit of high byte)
addwf freq_3,w ; Add it to the current high byte
btfsc STATUS,C ; Was high byte too large?
BRA set_max ; Yes, apply limit
movlw limit_hi_3 ; Get high limit value
subwf freq_3,w ; Subtract the limit value
btfss STATUS,C ; Are we at the limit for the byte?
BRA exit1 ; No, below. Checks are done.
;
; Check the second most significant byte.
;
movlw 0xFF-limit_hi_2 ; Get (FF - limit of next byte)
addwf freq_2,w ; Add it to the current byte
btfsc STATUS,C ; Is the current value too high?
BRA set_max ; Yes, apply the limit
movlw limit_hi_2 ; Second limit byte
subwf freq_2,w ; Subtract limit value
btfss STATUS,C ; Are we at the limit for the byte?
BRA exit1 ; No, below. Checks are done.
;
; Check the third most significant byte.
;
movlw 0xFF-limit_hi_1 ; Get (FF - limit of next byte)
addwf freq_1,w ; Add it to the current byte
btfsc STATUS,C ; Is the current value too high?
BRA set_max ; Yes, apply the limit
movlw limit_hi_1 ; Third limit byte
subwf freq_1,w ; Subtract limit value
btfss STATUS,C ; Are we at the limit for the byte?
BRA exit1 ; No, below. Checks are done.
;
; Check the least significant byte.
;
movlw limit_hi_0 ; Fourth limit byte
subwf freq_0,w ; Subtract limit value
btfss STATUS,C ; Are we at the limit for the byte?
BRA exit1 ; No, below. Checks are done.
set_max
movlw limit_hi_0 ; Get least significant limit
movwf freq_0 ; Set it in freq
movlw limit_hi_1 ; Get the next byte limit
movwf freq_1 ; Set it in freq_1
movlw limit_hi_2 ; Get the next byte limit
movwf freq_2 ; Set it in freq_2
movlw limit_hi_3 ; Get the most significant limit
movwf freq_3 ; Set it in freq_3
exit1
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: Subtract the increment step from freq. *
; * *
; *******************************************************************************
;
sub_step
;
call invert_fstep ; Invert fstep_3..0 to perform the subtraction
call add_step ; Add the complement to do the subtraction
;
; *******************************************************************************
; * *
; * Purpose: Test the new frequency to see if it is above the lower limit. *
; * If not, the frequency is set to the lower limit. *
; * *
; *******************************************************************************
;
low_limit_chk
; Check the most significant byte.
;
btfsc freq_3,7
BRA set_low ; Yes, set to lower frequency limit
movf freq_3,w
sublw limit_low_3
btfss STATUS,C ; Are we at the limit for the byte?
return ; No, above.
btfss STATUS,Z ; Are the bytes equal?
BRA set_low ; No, so vfo_X_3 > limit_3.
;
; Check the second most significant byte when MSB equals limit_3
;
movf freq_2,w
sublw limit_low_2
btfss STATUS,C ; Are we at the limit for the byte?
return ; No, above.
btfss STATUS,Z ; Might they be equal?
BRA set_low ; Nope, so vfo_X_2 > limit_2
;
; Check the third most significant byte.
;
movf freq_1,w
sublw limit_low_1
btfss STATUS,C ; Are we at the limit for the byte?
return ; No, above.
btfss STATUS,Z ; Check if the bytes are equal
BRA set_low ; No, so vfo_X_1 > limit_1
;
; Check the least significant byte.
;
movf freq_0,w
sublw limit_low_0
btfss STATUS,C ; Are we at the limit for the byte?
return ; No, above.
;
; The frequency is below the band lower limit. Set frequency to the
; band starting frequency.
set_low
movlw limit_low_0
movwf freq_0
movlw limit_low_1
movwf freq_1
movlw limit_low_2
movwf freq_2
movlw limit_low_3
movwf freq_3
return ; Return to caller
;
; *******************************************************************************
; * *
; * Function: invert_fstep *
; * *
; * Purpose: Support function for sub_step and calibrate. This function *
; * negates the value of fstep_3..0 to assist in the frequency *
; * decrement. This operation is performed twice by sub_step, and *
; * is also used by calibrate. *
; * *
; * Input: fstep_3, fstep_2, fstep_1, fstep_0 *
; * *
; * Output: fstep_3..0 contain the 2's complement of their original value *
; * *
; *******************************************************************************
;
invert_fstep ; Invert the bits in
comf fstep_0,f ; fstep_0
comf fstep_1,f ; fstep_1
comf fstep_2,f ; fstep_2
comf fstep_3,f ; fstep_3
incfsz fstep_0,f ; Now incremnt fstep_0 to get 2's complement
BRA invert_done ; If fstep_0 > 0, then done
; Else, there was a carry out of fstep_0
incfsz fstep_1,f ; Add 1 to fstep_1
BRA invert_done ; If fstep_1 > 0, then done
; Else, there was a carry out of fstep_1
incfsz fstep_2,f ; Add 1 to fstep_2
BRA invert_done ; if fstep_2 > 0, then done
; Else, there was a carry out of fstep_2
incf fstep_3,f ; Increment the high byte
;
invert_done
return ; Back to caller
;
; *******************************************************************************
; * *
; * Purpose: This routine is entered at start up if the calibrate pads are *
; * shorted at power-on time. *
; * *
; * The DDS chip is programmed to produce a frequency, based on the *
; * osc value stored in the EEPROM and the calibration frequency as *
; * at the head of the code. As long as the pads are shorted, the *
; * osc value is slowly altered to allow the output to be trimmed. *
; * Once the encoder is turned after the short is removed from the *
; * Cal pads, the new osc value is stored in the EEPROM and normal *
; * operation begins. *
; * *
; * Input: The original osc constant in EEPROM *
; * *
; * Output: The corrected osc constant in EEPROM *
; * *
; *******************************************************************************
;
calibrate
bcf INTCON,GIE ; Turn off interupts to be sure
;
movlw cal_freq_0 ; Move Calibration frequency constants
movwf freq_0 ; to freq_0...3 for Calibration routine.
movlw cal_freq_1 ;
movwf freq_1 ;
movlw cal_freq_2 ;
movwf freq_2 ;
movlw cal_freq_3 ;
movwf freq_3 ;
;
; Read the starting reference oscillator value from EEPROM.
;
BANKSEL EEADRL
clrf EEADRL ; Reset the EEPROM read address
call read_EEPROM ; Read first byte from EEPROM (all in bank 1)
movf EEDATL,w ; Get the first osc byte
movwf osc_0 ; Save osc frequency
call read_EEPROM ; Read second byte from EEPROM
movf EEDATL,w ;
movwf osc_1 ; Save it
call read_EEPROM ; Read third byte from EEPROM
movf EEDATL,w ;
movwf osc_2 ; Save it
call read_EEPROM ; Read fourth byte from EEPROM
movf EEDATL,w ;
movwf osc_3 ; Save it
movlb 0 ; Back to bank 0
;
cal_loop
call calc_dds_word ; Calculate DDS value based on current osc
call send_dds_word ; Update the DDS chip
call poll_encoder ; Wait until the encoder has moved.
btfsc CAL_sw ; Calibrate switch/jumper still set?
BRA cal_out ; No, go to exit and save values to EEPROM
clrf fstep_3 ; Clear the three most significant
clrf fstep_2 ; bytes of fstep
clrf fstep_1 ;
movlw 0x10 ;
movwf fstep_0 ; Use small increment
nop ; Wait a cycle
btfsc dir,0 ; Are we moving down?
BRA faster ; No, increase the osc value
;
; slower
;
comf fstep_0,f ; Subtraction of fstep is done by
comf fstep_1,f ; adding the twos compliment of fsetp
comf fstep_2,f ; to osc
comf fstep_3,f ;
incfsz fstep_0,f ; Increment last byte
BRA faster ; Non-zero, continue
incfsz fstep_1,f ; Increment next byte
BRA faster ; Non-zero, continue
incfsz fstep_2,f ; Increment next byte
BRA faster ; Non-zero, continue
incf fstep_3,f ; Increment the high byte
faster
movf fstep_0,w ; Get the low byte increment
addwf osc_0,f ; Add it to the low osc byte
btfss STATUS,C ; Was there a carry?
BRA add4 ; No, add the next bytes
incfsz osc_1,f ; Ripple carry up to the next byte
BRA add4 ; No new carry, add the next bytes
incfsz osc_2,f ; Ripple carry up to the next byte
BRA add4 ; No new carry, add the next bytes
incf osc_3,f ; Ripple carry up to the highest byte
add4
movf fstep_1,w ; Get the second byte increment
addwf osc_1,f ; Add it to the second osc byte
btfss STATUS,C ; Was there a carry?
BRA add5 ; No, add the third bytes
incfsz osc_2,f ; Ripple carry up to the next byte
BRA add5 ; No new carry, add the third bytes
incf osc_3,f ; Ripple carry up to the highest byte
add5
movf fstep_2,w ; Get the third byte increment
addwf osc_2,f ; Add it to the third osc byte
btfss STATUS,C ; Was there a carry?
BRA add6 ; No, add the fourth bytes
incf osc_3,f ; Ripple carry up to the highest byte
add6
movf fstep_3,w ; Get the fourth byte increment
addwf osc_3,f ; Add it to the fourth byte
BRA cal_loop ; Yes, stay in calibrate mode
;
; Write final value to EPROM
;
cal_out
BANKSEL EEADRL
movf osc_0,w ; Get the first osc byte to record
clrf EEADRL ; osc bytes start at EEPROM address 0
movwf EEDATL ; Put byte in EEPROM write location
call write_EEPROM ;
movf osc_1,w ; Get the second byte to record
movwf EEDATL ; Put byte in EEPROM write location
call write_EEPROM ;
movf osc_2,w ; Get the third byte to record
movwf EEDATL ; Put byte in EEPROM write location
call write_EEPROM ;
movf osc_3,w ; Get the fourth byte to record
movwf EEDATL ; Put byte in EEPROM write location
call write_EEPROM ;
movlb 0 ; Back to bank 0
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: This routine will save the current frequency and step size in *
; * EEPROM on power down. *
; * *
; *******************************************************************************
;
update_EEPROM ;
bcf INTCON,GIE ; turn interrupts off
btfsc INTCON,GIE ; See AN576 - make sure interrupts are off
BRA $-2
BANKSEL EEADRL ;
movlw EEstartup_adr ; Get startup address location
movwf EEADRL ; and set up for start of EEPROM writes
movf freq_0,w ; Get the first freq byte to write
movwf EEDATL ; First freq byte to EEPROM Write register
call write_EEPROM ; Write it
movf freq_1,w ; Get the second freq byte to write
movwf EEDATL ; Second freq byte to EEPROM Write register
call write_EEPROM ; Write it
movf freq_2,w ; Get the third freq byte to write
movwf EEDATL ; Third freq byte to EEPROM Write register
call write_EEPROM ; Write it
movf freq_3,w ; Get the fourth freq byte to write
movwf EEDATL ; Fourth freq byte to EEPROM Write register
call write_EEPROM ; Write it
movf step_size,w ; Move step size value to w to save in to EEprom
movwf EEDATL ;
call write_EEPROM ; Write it
movlb 0 ; Back to bank 0
bsf INTCON,GIE ; turn interrupts on
return ;
;
; *******************************************************************************
; * *
; * Required sequence to write to EEPROM *
; * Used by update_EEPROM and calibrate routines *
; * *
; *******************************************************************************
;
write_EEPROM
bcf EECON1,CFGS ; Deselect Configuration space
bcf EECON1,EEPGD ; Point to DATA memory
bsf EECON1,WREN ; Set the EEPROM write enable bit
; Start of required sequence
movlw 0x55 ; Write 0x55 and 0xAA to EECON2
movwf EECON2 ; control register, as required
movlw 0xAA ;
movwf EECON2 ;
bsf EECON1,WR ; Set WR bit to begin write
; End of required sequence
bit_check
btfsc EECON1,WR ; Has the write completed?
BRA bit_check ; No, keep checking
bcf EECON1,WREN ; Clear the EEPROM write enable bit
incf EEADRL,f ; Increment the EE write address
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: Read a byte of EEPROM data at address EEADR into EEDATA. *
; * *
; * Input: The address EEADR. *
; * *
; * Output: The value in EEDATA. *
; * *
; * NOTE: All in BANK 1 *
; * *
; *******************************************************************************
;
read_EEPROM
bcf EECON1,CFGS ; Deselect Config space
bcf EECON1,EEPGD ; Point to DATA memory
bsf EECON1,RD ; EE Read
incf EEADRL,f ; Increment the read address
return
;
; *******************************************************************************
; * *
; * Purpose: Multiply the 32 bit number for oscillator frequency times the *
; * 32 bit number for the displayed frequency. *
; * *
; * Input: The reference oscillator value in osc_3 ... osc_0 and the *
; * current frequency stored in freq_3 ... freq_0. The reference *
; * oscillator value is treated as a fixed point real, with a 24 *
; * bit mantissa. *
; * *
; * Output: The result is stored in AD9851_3 ... AD9851_0. *
; * *
; *******************************************************************************
;
org 0x200
calc_dds_word
;
clrf AD9851_0 ; Clear the AD9850/AD9851 control word bytes
clrf AD9851_1 ;
clrf AD9851_2 ;
clrf AD9851_3 ;
clrf AD9851_4 ;
movlw 0x20 ; Set count to 32 (4 osc bytes of 8 bits)
movwf mult_count ; Keep running count
movf osc_0,w ; Move the four osc bytes
movwf osc_temp_0 ; to temporary storage for this multiply
movf osc_1,w ; (Don't disturb original osc bytes)
movwf osc_temp_1 ;
movf osc_2,w ;
movwf osc_temp_2 ;
movf osc_3,w ;
movwf osc_temp_3 ;
mult_loop
bcf STATUS,C ; Start with Carry clear
btfss osc_temp_0,0 ; Is bit 0 (Least Significant bit) set?
BRA noAdd ; No, don't need to add freq term to total
movf freq_0,w ; Get the "normal" freq_0 term
addwf AD9851_1,f ; Add it in to total
btfss STATUS,C ; Does this addition result in a carry?
BRA add7 ; No, continue with next freq term
incfsz AD9851_2,f ; Yes, add one and check for another carry
BRA add7 ; No, continue with next freq term
incfsz AD9851_3,f ; Yes, add one and check for another carry
BRA add7 ; No, continue with next freq term
incf AD9851_4,f ; Yes, add one and continue
add7
movf freq_1,w ; Get the "normal" freq_0 term
addwf AD9851_2,f ; Add freq term to total in correct position
btfss STATUS,C ; Does this addition result in a carry?
BRA add8 ; No, continue with next freq term
incfsz AD9851_3,f ; Yes, add one and check for another carry
BRA add8 ; No, continue with next freq term
incf AD9851_4,f ; Yes, add one and continue
add8
movf freq_2,w ; Get the "normal" freq_2 term
addwf AD9851_3,f ; Add freq term to total in correct position
btfss STATUS,C ; Does this addition result in a carry?
BRA add9 ; No, continue with next freq term
incf AD9851_4,f ; Yes, add one and continue
add9
movf freq_3,w ; Get the "normal" freq_3 term
addwf AD9851_4,f ; Add freq term to total in correct position
noAdd
rrf AD9851_4,f ; Shift next multiplier bit into position
rrf AD9851_3,f ; Rotate bits to right from byte to byte
rrf AD9851_2,f ;
rrf AD9851_1,f ;
rrf AD9851_0,f ;
rrf osc_temp_3,f ; Shift next multiplicand bit into position
rrf osc_temp_2,f ; Rotate bits to right from byte to byte
rrf osc_temp_1,f ;
rrf osc_temp_0,f ;
decfsz mult_count,f ; One more bit has been done. Are we done?
BRA mult_loop ; No, go back and do next
#ifdef AD9850
movlw 0x00 ; No clock multiplier (AD9850)
#endif
#ifdef AD9851
movlw 0x01 ; Turn on 6x clock multiplier (AD9851)
#endif
movwf AD9851_4 ; Last byte to be sent
; Mult answer is in bytes _3 .. _0
return ; Done.
;
; *******************************************************************************
; * *
; * Purpose: This routine sends the AD9850/AD9851 control word to the DDS *
; * using a serial data transfer. *
; * *
; * Input: AD9851_4 ... AD9851_0 *
; * *
; * Output: The DDS chip register is updated. *
; * *
; *******************************************************************************
;
send_dds_word
movlw 5 ; Set number of control bytes to send
movwf byte_count ;
movlw LOW AD9851_0
movwf FSR0L
movlw HIGH AD9851_0
movwf FSR0H
next_byte
movf INDF0,w ;
movwf byte2send ;
movlw 0x08 ; Set counter to 8
movwf bit_count ;
next_bit
rrf byte2send,f ; Test if next bit is 1 or 0
btfss STATUS,C ; Was it zero?
BRA send0 ; Yes, send zero
BANKSEL LATA
bsf DDS_dat ; No, send one
bsf DDS_clk ; Toggle write clock
bcf DDS_clk ;
movlb 0 ; Bank 0
BRA break ;
send0
BANKSEL LATA
bcf DDS_dat ; Send zero
bsf DDS_clk ; Toggle write clock
bcf DDS_clk ;
movlb 0 ; Bank 0
break
decfsz bit_count,f ; Has the whole byte been sent?
BRA next_bit ; No, keep going.
incf FSR0L,f
decfsz byte_count,f ;
BRA next_byte ;
BANKSEL LATA
bsf DDS_load ; Send load signal to the AD9850/AD9851
bcf DDS_load ;
movlb 0 ; Bank 0
return ;
;
#IFDEF RIT
freq_to_rxf
movfw freq_0
movwf rxf_0
movfw freq_1
movwf rxf_1
movfw freq_2
movwf rxf_2
movfw freq_3
movwf rxf_3
return
freq_to_ritf
movfw freq_0
movwf ritf_0
movfw freq_1
movwf ritf_1
movfw freq_2
movwf ritf_2
movfw freq_3
movwf ritf_3
return
rxf_to_freq
movfw rxf_0
movwf freq_0
movfw rxf_1
movwf freq_1
movfw rxf_2
movwf freq_2
movfw rxf_3
movwf freq_3
return
ritf_to_freq
movfw ritf_0
movwf freq_0
movfw ritf_1
movwf freq_1
movfw ritf_2
movwf freq_2
movfw ritf_3
movwf freq_3
return
rxf_to_ritf
movfw rxf_0
movwf ritf_0
movfw rxf_1
movwf ritf_1
movfw rxf_2
movwf ritf_2
movfw rxf_3
movwf ritf_3
return
#ENDIF
#IFDEF RIT
org 0x800
rit
; bcf flags,0 ; Clear RIT changed flag
clrf flags ; Clear RIT flag bits
BANKSEL ADCON0
bsf ADCON0,ADGO ; start conversion
btfsc ADCON0,ADGO ; is conversion done?
BRA $-1 ; no, test again
movf ADRESH,w ; read upper 2 bits
movwf NumH ; store in gpr space
movf ADRESL,w ; read lower 8 bits
movwf NumL ; store in gpr space
movlb 0
getValue
;first do ADC-center value to discover direction
bsf dir,0 ; set direction, 1 = up
movlw high(center)
subwf NumH,f
movlw low(center)
subwf NumL,f
btfss STATUS,C
decf NumH,f
btfss NumH,7 ; is it negative
BRA notNeg
;need to negate acc
bcf dir,0 ; set direction, 1 = up
movlw 0xff
xorwf NumL,f
xorwf NumH,f
incf NumL,f
btfsc STATUS,Z
incf NumH,f
notNeg
; have now got a valid lookup value
BANKSEL EEADRL ; Select Bank for EEPROM registers
movfw NumL ;
movwf EEADRL
movfw NumH
addlw 0x0e
movwf EEADRH
bcf EECON1,CFGS ; Do not select Configuration Space
bsf EECON1,EEPGD ; Select Program Memory
bsf EECON1,RD ; Initiate read
NOP ; required 2 x NOPs
NOP
; EEDAT will now contain 0 - 2500
; and direction bit will be set
movf EEDATH,w
movlb 0
movwf fstep_1 ; for DDS frequency change
BANKSEL EEDATL
movf EEDATL,w
movlb 0
movwf fstep_0 ; for DDS frequency change
movf fstep_1,f ; Test if fstep_1 = 0
btfss STATUS,Z
BRA RIT_exit ; RIT is greater than 0
movf fstep_0,f ; Test if fstep_0 = 0
btfss STATUS,Z
BRA RIT_exit
bcf flags,0 ; RIT = 0 & flags bit 0 = 0
return
RIT_exit
; Test if same as last time
; test for value change and return if no change
bsf flags,0
movfw NumH
subwf NumH_temp,w ; Test if both registers the same. If yes test
btfss STATUS,Z ; next set of registers. else get value from table
BRA RIT_exit2
movfw NumL
subwf NumL_temp,w ; Test if both registers the same. If yes then
btfsc STATUS,Z ; nothing changed so return from here else get
return ; value from table
RIT_exit2
movfw NumH
movwf NumH_temp
movfw NumL
movwf NumL_temp
bsf flags,1 ; 0 = same as last time 1 = different
return
;
org 0xe00
;note, dead band incorporated into table
DW 0,0,0,0,0,0,0,0,0,0,5,11,16,22,28,33,39,45,50,56 ; 20
DW 62,67,73,79,84,90,96,101,107,113,118,124,130,135,141,147,152,158,164,169 ; 40
DW 175,180,186,192,197,203,209,214,220,226,231,237,243,248,254,260,265,271,277,282 ; 60
DW 288,294,299,305,311,316,322,328,333,339,345,350,356,361,367,373,378,384,390,395 ; 80
DW 401,407,412,418,424,429,435,441,446,452,458,463,469,475,480,486,492,497,503,509 ; 100
DW 514,520,526,531,537,542,548,554,559,565,571,576,582,588,593,599,605,610,616,622 ; 120
DW 627,633,639,644,650,656,661,667,673,678,684,690,695,701,707,712,718,723,729,735 ; 140
DW 740,746,752,757,763,769,774,780,786,791,797,803,808,814,820,825,831,837,842,848 ; 160
DW 854,859,865,871,876,882,888,893,899,904,910,916,921,927,933,938,944,950,955,961 ; 180
DW 967,972,978,984,989,995,1001,1006,1012,1018,1023,1029,1035,1040,1046,1052,1057,1063,1069,1074 ; 200
DW 1080,1085,1091,1097,1102,1108,1114,1119,1125,1131,1136,1142,1148,1153,1159,1165,1170,1176,1182,1187 ; 220
DW 1193,1199,1204,1210,1216,1221,1227,1233,1238,1244,1250,1255,1261,1266,1272,1278,1283,1289,1295,1300 ; 240
DW 1306,1312,1317,1323,1329,1334,1340,1346,1351,1357,1363,1368,1374,1380,1385,1391,1397,1402,1408,1414 ; 260
DW 1419,1425,1430,1436,1442,1447,1453,1459,1464,1470,1476,1481,1487,1493,1498,1504,1510,1515,1521,1527 ; 280
DW 1532,1538,1544,1549,1555,1561,1566,1572,1578,1583,1589,1595,1600,1606,1611,1617,1623,1628,1634,1640 ; 300
DW 1645,1651,1657,1662,1668,1674,1679,1685,1691,1696,1702,1708,1713,1719,1725,1730,1736,1742,1747,1753 ; 320
DW 1759,1764,1770,1776,1781,1787,1792,1798,1804,1809,1815,1821,1826,1832,1838,1843,1849,1855,1860,1866 ; 340
DW 1872,1877,1883,1889,1894,1900,1906,1911,1917,1923,1928,1934,1940,1945,1951,1957,1962,1968,1973,1979 ; 360
DW 1985,1990,1996,2002,2007,2013,2019,2024,2030,2036,2041,2047,2053,2058,2064,2070,2075,2081,2087,2092 ; 380
DW 2098,2104,2109,2115,2121,2126,2132,2138,2143,2149,2154,2160,2166,2171,2177,2183,2188,2194,2200,2205 ; 400
DW 2211,2217,2222,2228,2234,2239,2245,2251,2256,2262,2268,2273,2279,2285,2290,2296,2302,2307,2313,2319 ; 420
DW 2324,2330,2335,2341,2347,2352,2358,2364,2369,2375,2381,2386,2392,2398,2403,2409,2415,2420,2426,2432 ; 440
DW 2440,2450,2460,2470,2480,2490,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500 ; 460
DW 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500 ; 480
DW 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500 ; 500
DW 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500 ; 512
#ENDIF
END
;--------------------------------------------------------------------------------
I didn't know that. Learned something new today!There's no context save in the ISR because it is automatic in the Enhanced 16F PIC's
I've been meaning to figure out how to search pin-compatible alternatives..Beginning to think I should be using 18F parts - any recommendation for a drop in replacement for the 16F1827 (through hole part)?
<!--Pin 5-->
<edc:VirtualPin edc:name="Vss"/>
<!--Pin 14-->
<edc:VirtualPin edc:name="Vdd"/>
;
; *******************************************************************************
; * *
; * Purpose: This routine adds the 32 bit value of fstep to the 32 bit *
; * value in freq. When incrementing, the fstep value is a *
; * positive integer. When decrementing, fstep is the complement *
; * of the value being subtracted. *
; * *
; * Input: The 32 bit values in fstep and freq *
; * *
; * Output: The sum of fstep and freq is stored in freq. When incrementing *
; * this value may exceed the maximum. When decrementing, it may *
; * go negative. *
; * *
; *******************************************************************************
;
org 0x100
add_step
if $>0x100
error "Memory overwritten"
endif
org 0x100
I don't know what the 256 byte (word) problem is. However, if it fixed other problems then I suspect something else.Moving the code so that the various routines started at the 256 block beginnings ie 0x100 and 0x200 solved part of the problem in that it now correctly adds up to 2500Hz in the + direction.
That's the reasoning behind thinking it is a 256 byte block problem.
Well, depending on which datasheet you read, supposedly call and goto can only jump a limited distance like +/- 256 bytes and yet in other places they are indicated as being able to reach any point within a 2k page.The only limit I know that involves 256 is the table read and relative jumps. Is there another one I'm not aware of?
In any datasheet I've read they can reach anywhere in a 2K page. Look at the instruction and they both have an 11 bit address field, giving them an address space of 2K.Well, depending on which datasheet you read, supposedly call and goto can only jump a limited distance like +/- 256 bytes and yet in other places they are indicated as being able to reach any point within a 2k page.
Are there long call macros for the 16F1827
Long Jumps And Calls The assembler recognizes several mnemonics that expand into regular PIC MCU assembly instructions. The mnemonics are fcall and ljmp. On baseline and mid-range parts, these instructions expand into regular call and goto instructions respectively, but also ensure the instructions necessary to set the bits in PCLATH (for mid-range devices) or STATUS (for baseline devices) will be generated, should the destination be in another page of program memory. Page selection instructions can appear immediately before the call or goto, or be generated as part of, and immediately after, a previous fcall/ljmp mnemonic.
This is well beyond the program space for this chip. One too many zeros?ORG 0xF000 ; For 16F1827
Thats EEPROM, not program space.This is well beyond the program space for this chip. One too many zeros?
There's callw where you preload w with the destination, but again, the 16FXXX to 16F1XXX migration document is not that clear on how far it can actually jump.Are there long call macros for the 16F1827?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?