📄 counter.asm
字号:
;--------------------------------------------------------------------------
neg32 macro op ; op1 := 0 - op2
local neg_done
comf op, f ; invert all 8 bits in high byte
comf op+1, f ; invert all 8 bits in middle high byte
comf op+2, f ; invert all 8 bits in middle low byte
comf op+3, f ; invert all 8 bits in low byte
; Note at this point 0x000000 would have turned into 0xFFFFFFF .
; Must add ONE to complete the TWO's COMPLIMENT calculation ( -0 = 0 ).
; Note that "incf" affects only the Z flag but not the C flag .
incfsz op+3, f ; increment low byte (bits 7...0)
goto neg_done ; if incremented result NOT zero, we're through !
incfsz op+2, f ; increment middle low byte (bits 15...8)
goto neg_done ; if incremented result NOT zero, ...
incfsz op+1, f ; increment middle high byte (bits 23...16)
goto neg_done ; if ...
incfsz op+0, f ; increment high byte (bits 31...24)
goto neg_done ;
neg_done
endm
;**********************************************************************
ORG 0x000 ; processor reset vector
goto MainInit ; go to beginning of program
; (begin of ROM is too precious to waste for ordinary code, see below...)
;**************************************************************************
; *
; Lookup tables *
; Must be at the start of the code memory to avoid crossing pages !! *
; *
;**************************************************************************
;--------------------------------------------------------------------------
; 7-segment LED data table
;--------------------------------------------------------------------------
; Index 0..9 used for decimal numbers, all other indices defined below :
CHAR_A equ .10 ; Letters A..F = HEX digits, index 10..15
CHAR_b equ .11 ;
CHAR_c equ .12 ;
CHAR_d equ .13 ;
CHAR_E equ .14 ;
CHAR_F equ .15 ;
CHAR_G equ .16 ; Other letters used in "programming" mode
CHAR_H equ .17 ;
CHAR_i equ .18 ;
BLANK equ .19 ; blank display
TEST equ .20 ; power-on display test
CHAR_P equ .21 ; A few other letters for programming mode...
CHAR_r equ .22 ;
CHAR_o equ .23 ; "Prog"
CHAR_Q equ .24 ; "Quit"
CHAR_u equ .25 ;
CHAR_t equ .26 ;
CHAR_S equ .27 ; "Sub"
CHAR_Z equ .28 ; "ZEro"
CHAR_I equ .29 ; large "I" (left aligned!) for "IF"
CHAR_J equ .30 ;
CHAR_k equ .31 ;
CHAR_L equ .32 ;
CHAR_N equ .33 ;
CHAR_V equ .34 ;
CHAR_EQ equ .35 ; "="
#if (DISP_VARIANT==1)
DPPOINT_BIT equ 4 ; decimal point bit (same for all digits)
#define _A 0x01 ; bitmask for segment A , etc ..
#define _B 0x02
#define _C 0x20
#define _D 0x08
#define _E 0x04
#define _F 0x40
#define _G 0x80
#define _DP 0x10
#endif ; DISPLAY VARIANT #1
#if (DISP_VARIANT==2) || (DISP_VARIANT==3)
DPPOINT_BIT equ 1 ; decimal point bit (same for all digits)
#define _A 0x40 ; bitmask for segment A , etc ..
#define _B 0x80
#define _C 0x04
#define _D 0x01
#define _E 0x08
#define _F 0x10
#define _G 0x20
#define _DP 0x02
#endif ; DISPLAY VARIANT #2 + #3
BLANK_PATTERN equ b'00000000' ; blank display pattern (7-segment code)
;-----------------------------------------------------------------------------
; Table to convert a decimal digit or a special character into 7-segment-code
; Note: In DL4YHF's PIC counter, all digits have the same segment connections,
; so we do not need individual conversion tables for all segments.
;
; AAAA
; F B
; F B
; GGGG
; E C
; E C
; DDDD DP
;
;-----------------------------------------------------------------------------
Digit2SevenSeg:
addwf PCL,f ; caution: this is 'PCL' only, not 'PC'. Beware of page borders.
; A = 0, B = 1, C = 5, D = 3, E = 2, F = 6, G = 7, DP = 4
#if (COMMON_ANODE)
#define SSEG_XORMASK 0xFF ; since 2005-03-21 ... never tested by the author !
#else
#define SSEG_XORMASK 0x00 ; for COMMON CATHODE: No bitwise EXOR to the pattern
#endif
retlw (_A+_B+_C+_D+_E+_F )^SSEG_XORMASK ; ABCDEF. = '0' ( # 0 )
retlw ( _B+_C )^SSEG_XORMASK ; .BC.... = '1' ( # 1 )
retlw (_A+_B +_D+_E +_G)^SSEG_XORMASK ; AB.DE.G = '2' ( # 2 )
retlw (_A+_B+_C+_D +_G)^SSEG_XORMASK ; ABCD..G = '3' ( # 3 )
retlw ( _B+_C +_F+_G)^SSEG_XORMASK ; .BC..FG = '4' ( # 4 )
retlw (_A +_C+_D +_F+_G)^SSEG_XORMASK ; A.CD.FG = '5' ( # 5 )
retlw (_A +_C+_D+_E+_F+_G)^SSEG_XORMASK ; A.CDEFG = '6' ( # 6 )
retlw (_A+_B+_C )^SSEG_XORMASK ; ABC.... = '7' ( # 7 )
retlw (_A+_B+_C+_D+_E+_F+_G)^SSEG_XORMASK ; ABCDEFG = '8' ( # 8 )
retlw (_A+_B+_C+_D +_F+_G)^SSEG_XORMASK ; ABCD.FG = '9' ( # 9 )
retlw (_A+_B+_C +_E+_F+_G)^SSEG_XORMASK ; ABC.EFG = 'A' ( # 10 )
retlw ( _C+_D+_E+_F+_G)^SSEG_XORMASK ; ..CDEFG = 'b' ( # 11 )
retlw ( _D+_E +_G)^SSEG_XORMASK ; ...DE.G = 'c' ( # 12 )
retlw ( _B+_C+_D+_E +_G)^SSEG_XORMASK ; .BCDE.G = 'd' ( # 13 )
retlw (_A +_D+_E+_F+_G)^SSEG_XORMASK ; A..DEFG = 'E' ( # 14 )
retlw (_A +_E+_F+_G)^SSEG_XORMASK ; A...EFG = 'F' ( # 15 )
retlw (_A +_C+_D+_E+_F )^SSEG_XORMASK ; A.CDEF. = 'G' ( # 16 )
retlw ( _B+_C +_E+_F+_G)^SSEG_XORMASK ; .BC.EFG = 'H' ( # 17 )
retlw ( _E )^SSEG_XORMASK ; ....E.. = 'i' ( # 18 )
retlw (BLANK_PATTERN )^SSEG_XORMASK ; ....... = ' ' ( # 19 )
retlw (b'11111111' )^SSEG_XORMASK ; all segments on ( # 20 )
; A few more letters for programming mode :
retlw (_A+_B +_E+_F+_G)^SSEG_XORMASK ; AB..EFG = 'P' ( # 21 )
retlw ( _E +_G)^SSEG_XORMASK ; ....E.G = 'r' ( # 22 )
retlw ( _C+_D+_E +_G)^SSEG_XORMASK ; ..CDE.G = 'o' ( # 23 )
retlw (_A+_B+_C +_F+_G)^SSEG_XORMASK ; ABC..FG = 'Q' ( # 24 )
retlw ( _C+_D+_E )^SSEG_XORMASK ; ..CDE.. = 'u' ( # 25 )
retlw ( _D+_E+_F+_G)^SSEG_XORMASK ; ...DEFG = 't' ( # 26 )
retlw (_A +_C+_D +_F+_G)^SSEG_XORMASK ; A.CD.FG = 'S' ( # 27 )
retlw (_A+_B +_D+_E +_G)^SSEG_XORMASK ; AB.DE.G = 'Z' ( # 28 )
retlw ( _E+_F )^SSEG_XORMASK ; ....EF. = 'I' ( # 29 )
retlw ( _B+_C+_D )^SSEG_XORMASK ; .BCD.. = 'J' ( # 30 )
retlw ( _D+_E+_F+_G)^SSEG_XORMASK ; ...DEFG = 'k' ( # 31 )
retlw ( _D+_E+_F )^SSEG_XORMASK ; ...DEF. = 'L' ( # 32 )
retlw (_A+_B+_C +_E+_F )^SSEG_XORMASK ; ABC.EF. = 'N' ( # 33 )
retlw ( _C+_D+_E+_F )^SSEG_XORMASK ; ..CDEF. = 'V' ( # 34 )
retlw ( _D +_G)^SSEG_XORMASK ; ...D..G = '=' ( # 35 )
;--------------------------------------------------------------------------
; Table to control which 7-segment display is enabled. Displays are usually
; COMMON CATHODE (variants 1+2) so pulled low to enable.
; For DISP_VARIANT=3 (COMMON ANODE), the digit-driving pattern is inverted.
; Input: W = 0 means the MOST SIGNIFICANT DIGIT (the leftmost one), etc.
; Result: VALUE to be written to ENABLE_PORT to activate the digit
;--------------------------------------------------------------------------
Digit2MuxValue: ;
addwf PCL,f ; caution: this is 'PCL' only, not 'PC'
; Note: If the program counter is affected, a command requires to instruction cycles (=8 osc cycles)
#if (DISP_VARIANT==1) ; muliplexer values for DISPLAY VARIANT #1 :
retlw b'11110111' ; most significant digit is on PA3 (!)
retlw b'11111110' ; next less significant dig. on PA0 (!)
retlw b'11111011' ; next less significant dig. on PA2 (!)
retlw b'11111101' ; 4th (sometimes the last) digit PA1 (!)
retlw b'11111111' ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif ; DISPLAY VARIANT #1
#if (DISP_VARIANT==2) ; muliplexer values for DISPLAY VARIANT #2 (5 digits, COMMON CATHODE) :
retlw b'11110111' ; most significant digit is on PA3 (!)
retlw b'11111011' ; next less significant dig. on PA2 (!!)
retlw b'11111110' ; next less significant dig. on PA0 (!!)
retlw b'11111101' ; 4th (sometimes the last) digit PA1 (!)
retlw b'11111111' ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif ; DISPLAY VARIANT #2
#if (DISP_VARIANT==3) ; muliplexer values for DISPLAY VARIANT #3 (5 digits, COMMON ANODE) :
; Unused bits (b7..b4) are left HIGH as above .
retlw b'11111000' ; most significant digit is on PA3 (!)
retlw b'11110100' ; next less significant dig. on PA2 (!!)
retlw b'11110001' ; next less significant dig. on PA0 (!!)
retlw b'11110010' ; 4th (sometimes the last) digit PA1 (!)
retlw b'11110000' ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif ; DISPLAY VARIANT #2
;--------------------------------------------------------------------------
; Powers-of-ten table (32 bits, most significant byte first)
; Based on an idea by James Hutchby (MadLab, 1996) .
; Modified for 32-bit arithmetic by Wolfgang Buescher (2004).
;--------------------------------------------------------------------------
TensTable addwf PCL,f
cquad .10000000 ; 10 million is sufficient for the counter itself
cquad .1000000
cquad .100000
cquad .10000
cquad .1000
cquad .100
cquad .10
cquad .1
;--------------------------------------------------------------------------
; DISPLAY jump table for programming mode .
; Loads the display-strings like "quit" etc into the display latches.
; Input parameter: menu_index (0 .. MI_INDEX_MAX)
; Output placed in display0..display3
;
;--------------------------------------------------------------------------
PMDisplay:
movfw menu_index ; load menu index into W register
addwf PCL, f ; add W to lower part of program counter (computed jump)
goto PmDisp_Quit ; show "quit" (quit programming mode)
goto PmDisp_PSave; show "PSave"(power-saving mode on/off)
goto PmDisp_Add ; show "add " (add frequency offset)
goto PmDisp_Sub ; show "sub " (subtract frequency offset)
goto PmDisp_Zero ; show "Zero" (set frequency offset to zero)
goto PmDisp_StIF ; show "StdIF" (select standard IF from table)
goto PmDisp_IF_1 ; show 1st standard IF from table
goto PmDisp_IF_2 ; show 2nd standard IF from table
goto PmDisp_IF_3 ; show 3rd standard IF from table
goto PmDisp_IF_4 ; show 4th standard IF from table
goto PmDisp_IF_5 ; show 5th standard IF from table
goto PmDisp_Quit ; show "quit" (quit STANDARD IF menu)
; Add more display strings here if needed !
;--------------------------------------------------------------------------
; EXECUTION jump table for programming mode .
; Executes the commands "quit", "psave", "add", "sub", "zero", etc.
; Input parameter: menu_index (0 .. MI_INDEX_MAX)
;--------------------------------------------------------------------------
PMExecute: ; Execute the function belonging to menu_index
movfw menu_index ; load menu index into W register
addwf PCL, f ; add W to lower part of program counter (computed jump)
goto PmExec_Quit ; quit programming mode
goto PmExec_PSave; turn power-saving mode on/off
goto PmExec_Add ; add frequency offset from now on
goto PmExec_Sub ; subtract frequency offset from now on
goto PmExec_Zero ; set frequency offset to zero
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -