Hi
I am new to PIC Assembly coding, But have been using Arduino for a few years now.
Any help with the following would be very much appreciated, and help me to understand the code.
I have download a freely available .asm file for a signal generator and have the project working on a breadboard layout.
I am now wanting to adapt the code to my requirements.
I have got stuck on the following:
The code has 16 memory location for the frequency. Memory locations set from "MemButton" press steps through the 16 stored frequencies.
I only need 2 frequency memory locations, and the MemButton to toggle between the 2 memory locations.
This is the part of the code regarding the MemButton:-
I am new to PIC Assembly coding, But have been using Arduino for a few years now.
Any help with the following would be very much appreciated, and help me to understand the code.
I have download a freely available .asm file for a signal generator and have the project working on a breadboard layout.
I am now wanting to adapt the code to my requirements.
I have got stuck on the following:
The code has 16 memory location for the frequency. Memory locations set from "MemButton" press steps through the 16 stored frequencies.
I only need 2 frequency memory locations, and the MemButton to toggle between the 2 memory locations.
This is the part of the code regarding the MemButton:-
Code:
LIST P=16F627A
INCLUDE "p16F627A.inc"
errorlevel 2
__config 0x3F50 ; ..1101010000 LV Programming off , INTOSC I/O on A6/7, MCLRE tied to Vcc
#define DDSreset PORTA, 0
#define FData PORTA, 1 ;DDS Data on port A
#define FQud PORTA, 2
#define WClk PORTA, 3
#define NLED PORTA, 4
#define LCDE PORTA, 6
#define LCDRS PORTA, 7
#define LCDPORT PORTB ;B4-7
#define RotI PORTB, 0 ;Drives interrupt
#define RotQ PORTB, 1
#define Button PORTB, 2
#define MemButton PORTB, 3
#define Updated Flags, 0 ;Set after synth update
PLL = 0
LINE1 = 0x80 ;Address of start of each each line of text on
LINE2 = 0x80 + d'64' ; the LCD module, + command for setting it
LINE3 = 0x80 + d'16'
LINE4 = 0x80 + d'80'
LCDHINIBBLE = 1 ;0 for LCD on Port bits 0-3, 1 for bits 4-7
STEP1 = 1 ;0.01
STEP2 = d'10' ;0.1Hz
STEP3 = d'100' ;1Hz
STEP4 = d'1000'
STEP5 = d'10000'
STEP6 = d'100000' ;1kHz ;>6 bits allowed here
STEP7 = d'1000000' ;10kHz ; " " "
STEP8 = d'10000000' ;100kHz ; " " "
CHARMARK = "^"
org 0x2100
FREQCONST de 0x00,0x00,0x57,0xF5,0xFF,0x86 ;Tuning step / Fclock * 2^ 64, 0.01Hz, 125MHz
;FREQCONST de 0x00,0x04,0x4B,0x82,0xFA,0x10 ;Tuning step / Fclock * 2^ 64, 0.01Hz, 10MHz
StFreq de 0x00, 0xD1, 0xCE, 0xF0 ;137.5kHz Turn on value
de 0x02, 0xFD, 0x13, 0x60 ;501.4kHz
; de 0x0A, 0xFF, 0x3F, 0x20 ;1.845MHz
; de 0x16, 0x81, 0xB8, 0x00 ;3.776
; de 0x1F, 0x83, 0x52, 0x60 ;5.287
; de 0x2A, 0x9E, 0x08, 0xC0 ;7.15
; de 0x3C, 0x0E, 0xC1, 0x80 ;10.076
; de 0x55, 0x2B, 0x48, 0xA0 ;14.289
; de 0x6B, 0xE8, 0x83, 0x00 ;18.104
; de 0x7F, 0x07, 0x88, 0x00 ;21.312
; de 0x94, 0x70, 0x7D, 0x00 ;24.904
; de 0xAC, 0x86, 0x90, 0xA0 ;28.945
; de 0x00, 0x01, 0x86, 0xA0 ;1000Hz
; de 0x00, 0x02, 0x49, 0xF0 ;1500Hz
; de 0x00, 0x00, 0x9C, 0x40 ;400Hz
; de 0x00, 0x00, 0x00, 0x64 ;1Hz
org 0
nop
clrw
movwf INTCON ;disable interrupts
goto StartUp ;jump to main code
;.....................................................
org 4 ;Interrupt routine, every time RotI goes low to high
movwf Wreg ;Save W
swapf STATUS , W ; nb. movwf does not affect any STATUS bits
movwf StsReg ;Stave STATUS, without affecting it
btfss INTCON, INTF
goto OtherInt
clrf TMR0 ;Reset every pulse.
bcf INTCON, T0IF ; gives 4.1ms delay before T0IF is set
bcf Updated ;Force an update on next timeout
bcf INTCON , INTE ;Disable interrupt until routine is completed
bcf INTCON , INTF ;Clear interrupt flag
btfss RotQ ;Reverse these if tuning direction is wrong
call FreqUp
btfsc RotQ
call FreqDn
bsf INTCON , INTE ;Re enable the interrupt
goto CarryOnInt
;................
OtherInt
CarryOnInt
swapf StsReg , W ;Restore STATUS
movwf STATUS
swapf Wreg ;Restore W
swapf Wreg , W ; nb. movf affects Z bit
retfie
;=============================================================
StartUp
clrf PORTA ;Special setup to disable comparator on 'F628
movlw 7
movwf CMCON
bsf STATUS,RP0 ;ram page 1
movlw b'00000000' ;
movwf PORTA ;
movlw b'00001111' ;B0/1/2/3 - I/Q/Buttons
movwf PORTB ;
movlw b'01000010' ;Internal input, Prescalar /4, pull-ups
movwf OPTION_REG
bcf STATUS,RP0 ;ram page 0
;
clrf PORTA
bsf DDSreset
clrf D4
movlw PLL
addwf D4
call SetUpLCD
bcf DDSreset
call IntroMsg
call ShowConst
movlw d'40'
call LongerDel ;2s
ShowInitLoop
call Delay50
btfss Button ;If button held down at start, freezes intro window
goto ShowInitLoop
call ClrDisp
clrf Flags
movlw 2
movwf ButtonPress
clrf CurrentMem
movlw LINE2 + d'10
call LCDCmd
movlw CHARMARK
call LCDChar
call DispMem
call LoadFreq
call DispFreq
call SendSynth
call Delay50
call SendSynth ;Send twice just in case
bsf INTCON, INTF
bsf INTCON, GIE
goto JumpIn ;Enter main loop so display is set correctly
;.......................
MainLoop
btfss MemButton
goto DoMemory
btfsc Button
goto NoButton
call Delay50
btfsc Button
goto NoButton
clrf ButtCount ;Button pressed for 1s stores freq
SavLoop
call Delay50
incf ButtCount
movlw d'20'
subwf ButtCount, W
btfsc STATUS, C
goto SaveFreqs
btfss Button
goto SavLoop
decf ButtonPress
movlw 7
btfsc ButtonPress, 7 ;Test for underflow
movwf ButtonPress ;Cycles round 7 - 0
JumpIn
movlw LINE2 + 2 ;Show the digit being changed
call LCDCmd
movlw " " ;Clear existing marker
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movf ButtonPress, W ;0-6 depending on digit being changed. 0 = LSD
sublw d'10' ;move Back from position of LS digit
movwf Temp
movlw 5 ;Need to bypass the decimal point for ButtonPress = 5/ 6
subwf ButtonPress, W ;W = BP - 5, if +ve/0, C=1, move back one
btfsc STATUS, C
decf Temp
movf Temp, W
addlw LINE2
call LCDCmd ;Position under the digit to be changed
movlw CHARMARK
call LCDChar
movlw 0
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt0
movlw LOW(STEP1)
movwf StepLo
movlw HIGH(STEP1)
movwf StepMe
clrf StepHi
goto DoneButt
;...........
NotButt0
movlw 1
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt1
movlw LOW(STEP2)
movwf StepLo
movlw HIGH(STEP2)
movwf StepMe
clrf StepHi
goto DoneButt
;...........
NotButt1
movlw 2
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt2
movlw LOW(STEP3)
movwf StepLo
movlw HIGH(STEP3)
movwf StepMe
clrf StepHi
goto DoneButt
;...........
NotButt2
movlw 3
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt3
movlw LOW(STEP4)
movwf StepLo
movlw HIGH(STEP4)
movwf StepMe
clrf StepHi
goto DoneButt
;...........
NotButt3
movlw 4
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt4
movlw LOW(STEP5)
movwf StepLo
movlw HIGH(STEP5)
movwf StepMe
clrf StepHi
goto DoneButt
;...........
NotButt4
movlw 5
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt5
movlw LOW(STEP6)
movwf StepLo
movlw (STEP6 >> d'8') & 0xFF
movwf StepMe
movlw (STEP6 >> d'16') & 0xFF
movwf StepHi
goto DoneButt
;.......
NotButt5
movlw 6
subwf ButtonPress, W
btfss STATUS, Z
goto NotButt6
movlw LOW(STEP7)
movwf StepLo
movlw (STEP7 >> d'8') & 0xFF
movwf StepMe
movlw (STEP7 >> d'16') & 0xFF
movwf StepHi
goto DoneButt
;........
NotButt6
movlw LOW(STEP8)
movwf StepLo
movlw (STEP8 >> d'8') & 0xFF
movwf StepMe
movlw (STEP8 >> d'16') & 0xFF
movwf StepHi
DoneButt
call DispFreq
NoButton
btfsc INTCON, T0IF ;Look for 4ms timeout, ie. no rotary
goto DoUpdate ; encoder activity for this period
call Delay50
goto MainLoop
;...............
DoUpdate
btfss Updated ;See if it has already been done
goto DoOne
goto MainLoop
;...............
DoOne
bcf INTCON, INTE ;Inhibit interrupt while doing update
bsf Updated ;To prevent repeatedly sending the same data
call CalcDDS ;generate D0..3 from Frequency register
call DispFreq
call DispCode
call SendSynth
bsf INTCON, INTE
goto MainLoop
;..........
SaveFreqs
movlw LOW(StFreq)
addwf CurrentMem, W
movwf Whi
movf F3, W
call StoreEE
incf Whi
movf F2, W
call StoreEE
incf Whi
movf F1, W
call StoreEE
incf Whi
movf F0, W
call StoreEE
movlw LINE1
call LCDCmd
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw "-"
call LCDChar
movlw "-"
call LCDChar
movlw " "
call LCDChar
movlw "S"
call LCDChar
movlw "A"
call LCDChar
movlw "V"
call LCDChar
movlw "E"
call LCDChar
movlw "D"
call LCDChar
movlw " "
call LCDChar
movlw "-"
call LCDChar
movlw "-"
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
ButtWait
btfss Button
goto ButtWait
call DispFreq
goto MainLoop
;-----------------------------
DoMemory
call Delay50
btfsc MemButton
goto NoButton
MbuttUp
call Delay50
btfss MemButton
goto MbuttUp
movlw 4 ;Count in multiples of 4, 00 - 0x2C
addwf CurrentMem, W
andlw b'00111100'
movwf CurrentMem
call DispMem
call LoadFreq
call CalcDDS
call DispFreq
call DispCode
call SendSynth
goto NoButton
;========================== SUBROUTINES ==============================
FreqUp
movf StepLo, W
addwf F0
btfss STATUS, C
goto FrqUp1Done ;if FreqMe already = 0 and no overflow then
incf F1 ; an error occurs here without the jump out
btfsc STATUS, Z ; Test for overflow after above increment
incf F2 ;
btfsc STATUS, Z
incf F3 ;
FrqUp1Done
movf StepMe, W
addwf F1
btfss STATUS, C
goto FrqUp2Done
incf F2
btfsc STATUS, Z
incf F3
FrqUp2Done
movf StepHi, W
addwf F2
btfsc STATUS, C
incf F3
return
;-------------------------------
FreqDn
movf StepLo, W
subwf F0
btfsc STATUS, C ;If borrowed, C=0
goto FrqDwn1Done
decf F1 ;decf doesn't set carry flag, so we need to test
comf F1, W ; for FreqHi going from 0 > 0xFF by complementing
btfss STATUS, Z ; then test for zero
goto FrqDwn1Done
decf F2
comf F2, W
btfsc STATUS, Z
decf F3
comf F3, W
btfsc STATUS, Z
goto GoneNeg
FrqDwn1Done
movf StepMe, W
subwf F1
btfsc STATUS, C
goto FrqDwn2Done
decf F2
comf F2, W
btfsc STATUS, Z
decf F3
comf F3, W
btfsc STATUS, Z
goto GoneNeg
FrqDwn2Done
movf StepHi, W
subwf F2
btfss STATUS, C
decf F3
comf F3, W
btfsc STATUS, Z
goto GoneNeg
return
;...............
GoneNeg
clrf F0
clrf F1
clrf F2
clrf F3
return
;-------------------------------
CalcDDS ;Calculates D0..3 for DDS, = FREQCONST * F0..3 / 2^32
movf F0, W
movwf A0
movf F1, W
movwf A1
movf F2, W
movwf A2
movf F3, W
movwf A3
movlw LOW(FREQCONST + 5)
call GetEE
movwf B0
movlw LOW(FREQCONST + 4)
call GetEE
movwf B1
movlw LOW(FREQCONST + 3)
call GetEE
movwf B2
movlw LOW(FREQCONST + 2)
call GetEE
movwf B3
movlw LOW(FREQCONST + 1)
call GetEE
movwf B4
movlw LOW(FREQCONST)
call GetEE
movwf B5
call Multiply48x32 ;A * B / 2^16 .... Truncated to 64 bit result
movf Acc5, W ;Divide by another 2^16 to compensate for DDS constant
movwf D3 ; by offsetting accumulator by 16 bits to give the
movf Acc4, W ; 32 bit word for the DDS
movwf D2
movf Acc3, W
movwf D1
movf Acc2, W
movwf D0
return
;----------------------------------
DispMem
movlw LINE2 + d'12'
call LCDCmd
movlw "M"
call LCDChar
movlw "e"
call LCDChar
movlw "m"
call LCDChar
rrf CurrentMem, W
movwf Temp
rrf Temp, W
andlw 0x0F
addlw "A"
call LCDChar
return
;-------------------------
DispFreq
movf F0, W
movwf A0
movf F1, W
movwf A1
movf F2, W
movwf A2
movf F3, W
movwf A3
call BinToBCD
movlw LINE1
call LCDCmd ;Use leading zero blanking on first two digits
movlw " "
call LCDChar ;Preset first two to spaces
movlw " "
call LCDChar
movf BCDUi ;Test for Both MS digits = 00
btfsc STATUS, Z
goto NoMSDs
movlw LINE1 ;If not, reposition at start
call LCDCmd
swapf BCDUi, W
andlw 0x0F
btfsc STATUS, Z
movlw 0xF0 ;Modify to print a space in place of 0
addlw 0x30
call LCDChar
movf BCDUi, W ;Want this to print a zero if it gets here
andlw 0x0F
addlw 0x30
call LCDChar
NoMSDs
movlw LINE1 + 2
call LCDCmd
swapf BCDVi, W
andlw 0x0F
addlw 0x30
call LCDChar
movf BCDVi, W
andlw 0x0F
addlw 0x30
call LCDChar
swapf BCDHi, W
andlw 0x0F
addlw 0x30
call LCDChar
movlw "."
call LCDChar
movf BCDHi, W
andlw 0x0F
addlw 0x30
call LCDChar
swapf BCDMe, W
andlw 0x0F
addlw 0x30
call LCDChar
movf BCDMe, W
andlw 0x0F
addlw 0x30
call LCDChar
swapf BCDLo, W
andlw 0x0F
addlw 0x30
call LCDChar
movf BCDLo, W
andlw 0x0F
addlw 0x30
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw " "
call LCDChar
movlw LINE1 + d'12'
call LCDCmd
movlw "k"
call LCDChar
movlw "H"
call LCDChar
movlw "z"
call LCDChar
return
;-------------------------------
DispCode
movlw LINE4 + d'1'
call LCDCmd
movlw "0"
call LCDChar
movlw "x"
call LCDChar
movf D4, W
call ShowHex
movlw "."
call LCDChar
movf D3, W
call ShowHex
movf D2, W
call ShowHex
movf D1, W
call ShowHex
movf D0, W
call ShowHex
movlw " "
call LCDChar
return
;-------------------------------
BinToBCD ;Takes in A3/A2/A1/A0, calculates packed BCD equivalent
clrf BCDUi ;Result in BCDUi/3/2/1/0
clrf BCDVi ;Also uses BCDCounter, BCDTemp Destroys A
clrf BCDHi ; may be able to reuse Acc registers in some cases
clrf BCDMe
clrf BCDLo
movlw d'32'
movwf BCDCounter
BCDloop
rlf A0
rlf A1
rlf A2
rlf A3
rlf BCDLo
rlf BCDMe
rlf BCDHi
rlf BCDVi
rlf BCDUi
decfsz BCDCounter ;Need a final shift only, so loop count here
goto BCDgo
goto BCDone
;..........
BCDgo
movf BCDUi , W
addlw 3
movwf BCDTemp
btfsc BCDTemp , 3
movwf BCDUi ;If BCDUi >= 5, add 3 and store back
movf BCDUi , W
addlw 0x30
movwf BCDTemp
btfsc BCDTemp , 7
movwf BCDUi ;Adjust BCDUi if > 80
movf BCDVi , W
addlw 3
movwf BCDTemp
btfsc BCDTemp , 3
movwf BCDVi
movf BCDVi , W
addlw 0x30
movwf BCDTemp
btfsc BCDTemp , 7
movwf BCDVi
movf BCDHi , W ;Repeating for middle then low digits
addlw 3
movwf BCDTemp
btfsc BCDTemp , 3
movwf BCDHi
movf BCDHi , W
addlw 0x30
movwf BCDTemp
btfsc BCDTemp , 7
movwf BCDHi
movf BCDMe , W ;
addlw 3
movwf BCDTemp
btfsc BCDTemp , 3
movwf BCDMe
movf BCDMe , W
addlw 0x30
movwf BCDTemp
btfsc BCDTemp , 7
movwf BCDMe
movf BCDLo , W ;
addlw 3
movwf BCDTemp
btfsc BCDTemp , 3
movwf BCDLo
movf BCDLo , W
addlw 0x30
movwf BCDTemp
btfsc BCDTemp , 7
movwf BCDLo
goto BCDloop
;...........
BCDone
return
;---------------------------------------------------
ShowHex ;Convert byte to ASCII / Hex and print to LCD
movwf Temp2 ;Uses Temp2 , Temp
swapf Temp2 , W
andlw 0x0F ;High nibble
addlw 0x30 ;Convert to ASCII
movwf Temp ;Temp contains correct ASCII for "0" to "9"
sublw 0x39 ;W = "9" - W, if > "9" answer -ve so C=0
movlw 7 ;(Does not affect status bits)
btfss STATUS , C
addwf Temp ;Add 7 for "A" - "F"
movf Temp , W
call LCDChar ;Make sure Temp2 is preserved
movf Temp2 , W ;Recover original data
andlw 0x0F ;Low nibble
addlw 0x30
movwf Temp
sublw 0x39
movlw 7
btfss STATUS , C
addwf Temp
movf Temp , W
call LCDChar
movf Temp2 , W ;Restore original data to W
; as this is a test mode only
return
;------------------------------
LCDChar
bsf LCDRS
goto LcdNibble
LCDCmd ;Command byte to LCD module RS = 0
bcf LCDRS
LcdNibble
movwf Temp ;LCD is on high order nibble of LCDPORT
movf Temp, W
andlw 0xF0 ;mask to low order bits
movwf LCDPORT ;MS Nibble to PORT 4/7
nop
bsf LCDE
nop
bcf LCDE ;Strobe in high order nibble
nop
swapf Temp , W ;load low order nibble
andlw 0xF0 ;mask to low order bits
movwf LCDPORT
nop
bsf LCDE
nop
bcf LCDE ;Strobe in low order nibble
call Delay100us
return
;-------------------------------
SetUpLCD
call Delay50
bcf LCDE ;LCDPORT - B0-B3 to be used for nibble data
bcf LCDRS
movlw 0x30 ;LCDPORT is on Hig Nibble
movwf LCDPORT ;R/W - Write RS = 0 E = Low
nop
bsf LCDE
nop
bcf LCDE ;strobe in first $30
call Delay5
bsf LCDE
nop
bcf LCDE ;second $30
call Delay5
bsf LCDE
nop
bcf LCDE ;third $30
call Delay5
movlw 0x20 ;set nibble node $20
movwf LCDPORT
nop
bsf LCDE
nop
bcf LCDE
nop ;LCD Module now working in nibble mode
; so we can now use the routines
movlw 0x28 ;Sets 4bit, 2 lines 5x10 dots
call LCDCmd
movlw 0x1C ;Cursor move, shift right
call LCDCmd
movlw 0x0C ;Display on, Cursor on, Blink
call LCDCmd
movlw 0x04 ;Increment cursor
call LCDCmd
movlw 0x01 ;Clear and Home
call LCDCmd
call Delay5 ;could eventually use RS232 delay
call ClrDisp
return
;-------------------------------
ClrDisp
movlw 1
call LCDCmd
call Delay50
return
;-------------------------------
Delay100us
movlw d'19'
movwf DelCount
ShortDelLoop
nop
nop
decfsz DelCount
goto ShortDelLoop
return
;-------------------------------
Delay50 ;General purpose 50ms delay
movlw d'250'
movwf DelCount2
Del50Loop
call Delay100us
call Delay100us
decfsz DelCount2
goto Del50Loop
return
;----------------------------
Delay5 ;5ms delay for LCD setup
movlw d'50'
movwf DelCount2
Del5Loop
call Delay100us
decfsz DelCount2
goto Del5Loop
return
;-------------------------------
LongerDel ;Delays by W * 50ms
movwf Counter
LongDelLoop
call Delay50
decfsz Counter
goto LongDelLoop
return
;------------------------------
LoadFreq
movlw LOW(StFreq)
addwf CurrentMem, W
call GetEE
movwf F3
movlw LOW(StFreq + 1)
addwf CurrentMem, W
call GetEE
movwf F2
movlw LOW(StFreq + 2)
addwf CurrentMem, W
call GetEE
movwf F1
movlw LOW(StFreq + 3)
addwf CurrentMem, W
call GetEE
movwf F0
return
;-----------------------------=
GetEE ;different from ;F84 EE registers all in bank 1 now
bsf STATUS,RP0 ;ram page 1
movwf EEADR
bsf EECON1 , RD
movf EEDATA , W
bcf STATUS , RP0 ;ram page 0
return
;-------------------------
StoreEE ;Enter with W = EE data, Whi = EE address
bsf STATUS, RP0
movwf EEDATA
bcf STATUS, RP0
movf Whi, W
bsf STATUS, RP0
movwf EEADR
bsf STATUS , RP0 ;All EE registers in Bank 1
bsf EECON1 , WREN ;Enable EEprom writing
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1 , WR
bcf STATUS, RP0 ;PIR1 register is in bank 0
EEwaitW
btfss PIR1 , EEIF
goto EEwaitW
bcf PIR1 , EEIF ;has to be cleared manually
bsf STATUS, RP0
bcf EECON1 , WR
bcf STATUS , RP0
return
;-------------------------
ConstructR0
return
;-----------------------------
;--------------------
Multiply48x32 ;32x 48 bit multiplication, followed by /2^16
clrf Acc0 ;Input A0/1/2/3 and B0/1/2/3/4/5, output Acc0---7
clrf Acc1 ;A destroyed, B kept
clrf Acc2 ;64 bit answer, LSBs thrown away
clrf Acc3
clrf Acc4
clrf Acc5
clrf Acc6
clrf Acc7 ;Extend A range by changing counter and adding
; extra RRF Ax terms
movlw d'32'
movwf Counter
MultLoop
bcf STATUS, C
rrf A3
rrf A2
rrf A1
rrf A0 ;Effectivley adds shifted version of B
btfss STATUS, C ; into Acc depending on working bit of A
goto NoMult ; by shifting the accumulator instead of B itself
movf B0, W ;Get B0 value and add
addwf Acc2 ; into shifted accumulator if 1 in
btfss STATUS, C ; appropriate bit in Avalue
goto MulAdd1
incf Acc3
btfss STATUS, Z
goto MulAdd1
incf Acc4
btfss STATUS, Z
goto MulAdd1
incf Acc5
btfss STATUS, Z
goto MulAdd1
incf Acc6
btfss STATUS, Z
goto MulAdd1
movlw 1 ;Need more complex addition routine for last Acc as
addwf Acc7 ; final Carry has to be preserved for the shift
MulAdd1
movf B1, W
addwf Acc3
btfss STATUS, C
goto MulAdd2
incf Acc4
btfss STATUS, Z
goto MulAdd2
incf Acc5
btfss STATUS, Z
goto MulAdd2
incf Acc6
btfss STATUS, Z
goto MulAdd2
movlw 1
addwf Acc7
MulAdd2
movf B2, W
addwf Acc4
btfss STATUS, C
goto MulAdd3
incf Acc5
btfss STATUS, Z
goto MulAdd3
incf Acc6
btfss STATUS, Z
goto MulAdd3
movlw 1
addwf Acc7
MulAdd3
movf B3, W
addwf Acc5
btfss STATUS, C
goto MulAdd4
incf Acc6
btfss STATUS, Z
goto MulAdd4
movlw 1
addwf Acc7
MulAdd4
movf B4, W
addwf Acc6
btfss STATUS, C
goto MulAdd5
movlw 1
addwf Acc7
MulAdd5
movf B5, W
addwf Acc7
NoMult ;Need to rotate in carry from final addition. C is
rrf Acc7 ; already zero if we've jumped in here.
rrf Acc6
rrf Acc5
rrf Acc4
rrf Acc3
rrf Acc2
rrf Acc1
rrf Acc0
decfsz Counter
goto MultLoop
return ;Acc7/6/5/4/3/2/1/0 = A * B
;------------------------------------------------------------------
Div2N ;Divides Acc by 2^N. N in W
movwf Counter ;Does not work if entered with 0
movf Counter
btfsc STATUS , Z ;So trap it out
return
DivLoop
bcf STATUS , C
rrf Acc3
rrf Acc2
rrf Acc1
rrf Acc0
decfsz Counter
goto DivLoop
return
;------------------------------
ShowConst
movlw LINE3 + 2
call LCDCmd
movlw "F"
call LCDChar
movlw "r"
call LCDChar
movlw "e"
call LCDChar
movlw "q"
call LCDChar
movlw " "
call LCDChar
movlw "C"
call LCDChar
movlw "o"
call LCDChar
movlw "n"
call LCDChar
movlw "s"
call LCDChar
movlw "t"
call LCDChar
movlw "."
call LCDChar
movlw " "
call LCDChar
movlw "="
call LCDChar
movlw LINE4 + 1
call LCDCmd
movlw "0"
call LCDChar
movlw "x"
call LCDChar
movlw LOW(FREQCONST + 0)
call GetEE
call ShowHex
movlw LOW(FREQCONST + 1)
call GetEE
call ShowHex
movlw LOW(FREQCONST + 2)
call GetEE
call ShowHex
movlw LOW(FREQCONST + 3)
call GetEE
call ShowHex
movlw LOW(FREQCONST + 4)
call GetEE
call ShowHex
movlw LOW(FREQCONST + 5)
call GetEE
call ShowHex
return
;-------------------------------------
IntroMsg
movlw LINE1 + 5
call LCDCmd
movlw "G"
call LCDChar
movlw "4"
call LCDChar
movlw "J"
call LCDChar
movlw "N"
call LCDChar
movlw "T"
call LCDChar
movlw " "
call LCDChar
movlw LINE2 + 1
call LCDCmd
movlw "A"
call LCDChar
movlw "D"
call LCDChar
movlw "9"
call LCDChar
movlw "8"
call LCDChar
movlw "5"
call LCDChar
movlw "0"
call LCDChar
movlw " "
call LCDChar
movlw "C"
call LCDChar
movlw "o"
call LCDChar
movlw "n"
call LCDChar
movlw "t"
call LCDChar
movlw "r"
call LCDChar
movlw "o"
call LCDChar
movlw "l"
call LCDChar
return
;--------------------------------------
SendSynth ;Send Tx registers as a serial data to DDS
movf D0 , W
call Write9850
movf D1 , W
call Write9850
movf D2 , W
call Write9850
movf D3 , W
call Write9850
movf D4 , W ;Phase word
call Write9850
bcf WClk
goto $+1
bsf FQud ;+ve edge of FQud sets 9850 internal reg
goto $+1
bcf FQud
bcf FData
nop
return
;--------------------------
Write9850
movwf Temp
movlw 8
movwf BitCount
Loop9850
bcf WClk ;data changes with -ve edge of clock
rrf Temp
btfss STATUS , C
bcf FData
btfsc STATUS , C
bsf FData
goto $+1
bsf WClk
goto $+1
decfsz BitCount
goto Loop9850
return
;------------------------------
cblock 0x20
Temp, Temp2, BTemp, Whi
Counter
DelCount, DelCount2
BitCount
ButtCount, ButtonPress
AutoEEADR
Flags
Wreg, StsReg
CurrentMem
StepHi, StepMe, StepLo ;24 bit Tuning step
A0, A1, A2, A3,
B0, B1, B2, B3, B4, B5
Acc0, Acc1, Acc2, Acc3, Acc4, Acc5, Acc6, Acc7
SynthReg1, SynthReg2
F0,F1, F2, F3 ;Frequency Register
D0, D1, D2, D3, D4
BCDLo, BCDMe, BCDHi, BCDVi, BCDUi
BCDTemp, BCDCounter
Tx0, Tx1, Tx2, Tx3 ;Serial shift registers
endc
;------------------------------------------------
end
Last edited: