⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyer-3.0.18.asm

📁 PIC16F628A制作的自动键程序,供无线电爱好者参考.
💻 ASM
📖 第 1 页 / 共 5 页
字号:
; Keyer 3.0.18
; Goody K3NG
; Contributions and updates from W0ANM
; 2004.04.01

; This is a PIC based keyer.  Currently supported devices are the 16F628, 16F628A, and 16F648A.  This will compile for the
; 16F84 and 16F84A, however I don't test these anymore.  The 16F628 doesn't cost much more, switch over to it!  :-)
;
; http://www.qrpis.org
; goody @ qrpis . org


;	TODO - code practice, random callsigns
;	TODO - configurable memory repeat delay and store in eeprom
;	TODO - RX mute line (use TX wake line)
;	TODO - LCD Support
;	TODO - DDS Support
;	TODO - Configurable beacon sleep time
;	TODO - include_beacon_fox_message




; ************************************** user configurable stuff **********************************************

; processor definition - uncomment one and be sure to set your compiler for the right proc
;#define processor_16f84
;#define processor_16f84a
;#define processor_16f628
;#define processor_16f628a
#define processor_16f648a

; ***************************
; *     code inclusion      *
; ***************************

; comment out these to reduce the code size or change features
; note that some modules of code depend on others; read the notes
; bytes last updated 2004-09-18

; The Main Stuff

#define include_wavesidetone_code			; cost: ? bytes - additional support of wavesidetone
;#define include_function_button_code		; cost: 160 bytes (includes some dependent code); support for buttons other than mode
;#define include_toggle_sidetone_on_off_code	; cost: 18 bytes - code to turn off sidetone during TX
;#define include_mode_button_hold_code		; cost: 43 bytes - code for mode button hold shortcuts (programming memories, quick speed adj)
#define include_funky_beeps_code			; cost: 17 bytes - code for high and low beeps using wave sidetone; not applicable if using externally keyed sidetone oscillator (requires wavesidetone_code)
;#define include_m_and_h_cmd_code			; cost: 86 bytes - command modes M and H: program and playback memories in command mode
;#define include_eis_mh_cmd_code				; instead of 0,1,2 for memory select, it's e,i,s

; Frequency Counter Code
;#define include_freq_counter_code			; cost: 502 bytes - base frequency counter code
;#define include_freq_counter_button_code	; cost: 24 bytes - support for frequency counter button (requires freq_counter_code, function_button_code)
;#define	include_freq_counter_calib_code	; cost: 56 bytes - code for frequency calibration mode, command L (reqs freq_counter_code, function_button_code)

; Optional Features
;#define include_iambic_mode_code			; cost: 16 bytes - support for iambic a mode
;#define include_bug_code					; cost: 33 bytes - bug paddle mode
;#define include_call_cq_code				; cost: 55 bytes - call cq mode
;#define include_beacon_code				; cost: 60 bytes - beacon mode support
;#define include_nnnnn_code					; cost: 23 bytes - this code allows you to go into command mode after five consecutive Ns are sent
;#define include_txwake_line_code			; cost: ? bytes - code for TX_WAKE line
;#define include_tune_mode_code				; cost: 70 bytes - code for tune mode
;#define include_weighting_code				; cost: 77 bytes - command mode W: dah weighting
;#define include_paddle_reverse_code		; cost: 39 bytes - command mode R: reverse paddles
;#define include_needless_feature_code		; cost: 31 bytes - unimportant stuff
;#define include_say_hi_code					; cost: ? bytes - say hi at startup
;#define include_calibration_code			; cost: 34 bytes - this adds another command mode for calibrating the speed counters
;#define include_cw_rx_practice_code			; cost: 113 bytes - command mode P: random five letter group code practice
;#define include_cw_tx_practice_code			; cost: 25 bytes - command mode Q: send code without transmitting

; Experimental / Under Construction
;#define include_9850_dds_code				; experimental / under construction
;#define include_serial_cw_keyboard			; experimental
;#define include_beacon_serial_ctrl_code	; cost: ? bytes - control the beacon using a serial port
;#define include_fox_code					; under construction

; Debug code - turn all of these off for production chips
;#define include_debug_code					; misc debug code - comment out for production chips
;#define include_serial_rx_debug_code
;#define exclude_delays_debug


; *********************************************
; * dependencies - do not change this section *
; *********************************************

	; include_serial_port_rx_code required by include_beacon_serial_ctrl_code, include_serial_cw_keyboard
	ifdef include_beacon_serial_ctrl_code
#define include_serial_port_rx_code
	endif
	ifdef include_serial_cw_keyboard
	ifndef include_serial_port_rx_code
#define include_serial_port_rx_code
	endif
	endif

	; include_cw_table_long required by include_serial_port_rx_code, include_cw_rx_practice_code
	ifdef include_serial_port_rx_code
#define include_cw_table_long
	endif
	ifdef include_cw_rx_practice_code
	ifndef include_cw_table_long
#define include_cw_table_long
	endif
	endif

	; include_rotateBCD012_left required by include_serial_port_rx_code, include_freq_counter_code
	ifdef include_serial_port_rx_code
#define include_rotateBCD012_left
	endif
	ifdef include_freq_counter_code
	ifndef include_rotateBCD012_left
#define include_rotateBCD012_left
	endif
	endif

; ***************************
; *        options          *
; ***************************


#define _4_mhz_clock

; aliases for pins
#define mode_switch	PORTB,0x00			; momentary switch
;					PORTB,0x01			; Serial Port RX
#define dit			PORTB,0x02			; dit of paddle
#define dah			PORTB,0x03			; dah of paddle
	ifndef include_wavesidetone_code
#define sidetone	PORTB,0x04			; keys external sidetone oscillator
	else
#define wavesidetone PORTB,0x04			; square wave sidetone output
	endif
#define key			PORTB,0x05			; transmitter cw key
	ifdef include_txwake_line_code
#define txwake		PORTB,0x06			; goes high to turn on TX if used as FM CW unit, or T/R relay
	endif

	ifdef include_function_button_code
#define switch0		PORTA,0x00
#define switch1		PORTA,0x01
#define switch2		PORTA,0x02
	endif



#define initial_speed_wpm d'20'				; this is the default wpm speed when the cw_unit it first powered up
#define maxcwspeed  d'40'					; this is the max speed
#define initial_memory_repeat_delay d'35'	; this time in between repeating a memory in units of 100mS


; *************** don't adjust anything below this line unless you know what the hell you are doing *************

; eeprom addresses - this defines eeprom memory locations
#define eeprom_addr_speed_wpm 0x00			; CW speed in binary format
#define eeprom_wavesidetone_setting 0x01	; sidetone frequency setting
#define eeprom_settings1_location 0x02		; various user settings, register eeprom_settings1
#define eeprom_freq_calib_high 0x03			; frequency counter calibration, high byte
#define eeprom_freq_calib_low 0x04			; frequency counter calibration, low byte
#define eeprom_freq_offset_high 0x05		; frequency counter offset, lower nibble is BCD2
#define eeprom_freq_offset_low 0x06			; frequency counter offset, upper nibble is BCD1, lower nibble is BCD0
#define eeprom_memory_location_0 0x07		; cw memory 0 ( callsign )
#define eeprom_memory_loc_0_cw_units d'28'

	; first byte in memory location is a count of cw units stored in that memory
	; the remaining bytes are the stored cw units
	; a cw unit is two bits and is read MSB to LSB

	ifdef processor_16f84
#define eeprom_memory_location_1 0x0F 	; cw memory 1
#define eeprom_memory_location_2 0x28	; cw memory 2
#define eeprom_memory_loc_1_cw_units d'96'				; four cw units can be stored per byte
#define eeprom_memory_loc_2_cw_units d'92'
#define processor_low_end
	endif ;processor_16f84

	ifdef processor_16f84a
#define eeprom_memory_location_1 0x0F 	; cw memory 1
#define eeprom_memory_location_2 0x28	; cw memory 2
#define eeprom_memory_loc_1_cw_units d'96'				; four cw units can be stored per byte
#define eeprom_memory_loc_2_cw_units d'92'
#define processor_low_end
	endif ;processor_16f84a
	

	ifdef processor_16f628
#define eeprom_memory_location_1 0x0F	; cw memory 1
#define eeprom_memory_location_2 0x48	; cw memory 2
#define eeprom_memory_loc_1_cw_units d'224'
#define eeprom_memory_loc_2_cw_units d'220'
	endif ;processor_16f628

	ifdef processor_16f628a
#define eeprom_memory_location_1 0x0F	; cw memory 1
#define eeprom_memory_location_2 0x48	; cw memory 2  ( = eeprom_memory_location_1 + (eeprom_memory_loc_1_cw_units / 4) + 1 )
#define eeprom_memory_loc_1_cw_units d'224'		
#define eeprom_memory_loc_2_cw_units d'220'
	endif ;processor_16f628a

	ifdef processor_16f648a
#define eeprom_memory_location_1 0x0F	; cw memory 1
#define eeprom_memory_location_2 0x48	; cw memory 2
#define eeprom_memory_loc_1_cw_units d'224'
#define eeprom_memory_loc_2_cw_units d'220'
	endif ;processor_16f648a

; timing calibrations - these must be adjusted for clock speed
	
	ifdef _4_mhz_clock
#define _100ms_counter1_calibration 0xff
#define _100ms_counter2_calibration 0x78
#define _100ms_counter3_calibration 0x01
#define _cw_unit_wpm_factor d'20000' 			; this adjustment control the time length of one CW unit ( a dit )
#define _beep_length d'20'
#define	_high_beep_tone d'20'
#define	_low_beep_tone d'55'
#define _initial_wavesidetone_setting d'34'  	; this is the default wavesidetone frequency (600Hz)
#define _frequency_counter_calib	d'48900'	; higher = shorter sampling duration (1/4 second)
												; delay = 15 * 1uS * (65535 - _frequency_counter_calib) 
#define _txwake_delay_time d'30000'
#define _txwake_delay_time_straight_key d'400'
											
	endif ;_4_mhz_clock

	; processor declarations

	ifdef processor_16f84
	processor 16f84
	include <p16f84.inc>
	__config _HS_OSC & _WDT_OFF
	#define cblock_start 0x0c
	errorlevel -312			; turn off nagging about device not needing page selection
	endif ;processor_16f84
	
	ifdef processor_16f84a
	processor 16f84a
	include <p16f84a.inc>
	__config _HS_OSC & _WDT_OFF
	#define cblock_start 0x0c
	errorlevel -312			; turn off nagging about device not needing page selection
	endif ;processor_16f84a

	ifdef processor_16f628
	processor 16f628
	include <p16f628.inc>
	__config _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_OFF
	#define cblock_start 0x20
	errorlevel -312			; turn off nagging about device not needing page selection
	endif ;processor_16f628
	
	ifdef processor_16f628a
	processor 16f628a
	include <p16f628a.inc>
	__config _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_OFF
	#define cblock_start 0x20
	errorlevel -312			; turn off nagging about device not needing page selection
	endif ;processor_16f628a

	ifdef processor_16f648a
	processor 16f648a
	include <p16f648a.inc>
	__config _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_OFF
	#define cblock_start 0x20
	#define multi_memory_page_support
	endif ;processor_16f648a
	
	; define registers

	cblock cblock_start
		speed_wpm:1					;global
		bit_stuff1:1				;global
		bit_stuff2:1				;global
		bit_stuff3:1				;global
		cw_unit_counter:2			;loop_cw_unit
		counter1:1					;pause_100_ms, loop_cw_unit
		counter2:1					;pause_100_ms, loop_cw_unit
		counter3:1					;pause_100_ms, send_cw 
		cw_char_to_send:2			;send_cw(parm)
		temp:1						;send_cw
		dividend:2					;divideby16bit
		divisor:2					;divideby16bit
		quotient:2					;divideby16bit
		remainder:2					;divideby16bit
		count:1						;divideby16bit
		binary2bcd_binary_in:2		;binary2bcd
		BCD0:1						;binary2bcd
		BCD1:1						;binary2bcd
		BCD2:1						;binary2bcd
		bcd_low_nibble:1			;speed_mode
		bcd_high_nibble:1			;speed_mode
		write_verify_data:1			;write_eeprom
		write_verify_addr:1			;write_eeprom
		command_mode_loop_count1:1	; check_mode_button (enhanced)
		command_mode_loop_count2:1	; check_mode_button (enhanced)
		command_mode_loop_count3:1	; check_mode_button (enhanced)
		command_mode_buffer1:1		; check_mode_button (enhanced)
		command_mode_buffer2:1		; check_mode_button (enhanced)
		recording_loop_counter1:1	; program_memory
		recording_loop_counter2:1	; program_memory
		cw_unit_count:1				; program_memory
		temp_memory:1				; program_memory
		temp_memory_eeprom_pointer:1 ;program_memory
		temp_memory_mask:1			; program_memory
		temp_w:1					; program_memory.store_temp_memory_to_eeprom
		send_cw_temp:1				; send_cw
		memory_number:1				; program_memory, play_memory
		eeprom_memory_locations:3	; program_memory, play_memory
		eeprom_memory_loc_limits:3	; program_memory
		start_of_memory_location:1	; program_memory, play_memory
		porta_temp:1				; check_function_buttons
		eeprom_settings1:1
		wavesidetone_counter
		wavesidetone_counter_setting
	endc


	ifdef include_txwake_line_code	
		cblock
			txwakecounter:2
		endc
	endif ;include_txwake_line_code	

	
	ifdef include_nnnnn_code
		cblock
			ditdah_history1:1			; global - include_nnnnn_code		
			ditdah_history2:1			; global - include_nnnnn_code		
			ditdah_history_timer1:1		; global - include_nnnnn_code		
		endc
	endif
	

	ifdef include_weighting_code
		cblock
			cw_unit_counter_dah:2
			cw_unit_counter_dit:2
			speed_wpm_dah
		endc
	endif
	
	ifdef include_cw_rx_practice_code
		cblock
			randomnum:2
		endc
	endif
	
	ifdef include_freq_counter_code
		cblock
			freqcount:3
			BCD3:1
			frequency_counter_calib:2
			freq_offset_binary:2
			L_temp:1
			H_temp:1
		endc

bcd2binary_binary_out equ binary2bcd_binary_in

	ifdef include_debug_code
bcd2binary_binary_out_2 equ binary2bcd_binary_in+1	; for debugger work
freq_offset_binary_2 equ freq_offset_binary+1		; for debugger work
	endif ;include_debug_code

	endif ;include_freq_counter_code
	
#define dit_buffer					bit_stuff1,0x00			; used to store a dit in iambic operation
#define	dah_buffer					bit_stuff1,0x01			; used to store a dah
#define key_tx_active				bit_stuff1,0x02			; 0 = do not turn on key_tx line when sending cw
#define sending_dit					bit_stuff1,0x03			; 1 = send dit in send_dit_or_dah
	ifdef include_tune_mode_code
#define tune_latch_mode				bit_stuff1,0x04			; 1 = tx is latched on
	endif
#define temp_memory_dirty 			bit_stuff1,0x05			; used by memory record functions
#define paddle_was_hit				bit_stuff1,0x06
	ifdef include_function_button_code
#define memory_playback_manual_exit bit_stuff1,0x07
	endif

#define send_cw_preemptible			bit_stuff2,0x00			; send_cw routine can be interrupted by user when this flag is set
	ifndef include_wavesidetone_code
#define wavesidetone				bit_stuff2,0x01
	else
#define sidetone					bit_stuff2,0x01
	endif
#define expert_commands_on			bit_stuff2,0x02			; 1 = expert commands have been activated in command mode
#define bit_temp					bit_stuff2,0x03
	ifdef include_freq_counter_code
#define command_mode_v_cmd			bit_stuff2,0x04
#define command_mode_k_cmd			bit_stuff2,0x05
	endif
	ifdef include_call_cq_code
#define dit_hit						bit_stuff2,0x06
	endif ;include_call_cq_code
	ifdef include_m_and_h_cmd_code
#define command_mode_m_cmd			bit_stuff2,0x07

#define command_mode_h_cmd			bit_stuff3,0x00
	endif ;include_m_and_h_cmd_code

#define squeeze_detected			bit_stuff3,0x01


;eeprom_settings1 is used for settings that need to be stored in nonvolatile memory
;they are written to eeprom using call write_eeprom_settings1
#define sidetone_off_during_tx		eeprom_settings1,0x00		; 1 = no sidetone during TX (for internal use in rigs that alread have sidetone)
	ifdef include_iambic_mode_code
#define iambic_b_mode				eeprom_settings1,0x01		; 1 = iambic b mode activated
	endif
	ifdef include_paddle_reverse_code
#define paddle_reverse				eeprom_settings1,0x02		; 1 = paddle reverse mode activated
	endif
	ifdef include_freq_counter_code
#define eight_digit_mode			eeprom_settings1,0x03		; 1 = 8 digit frequency counter mode
#define offset0						eeprom_settings1,0x04		; offset0 and 1 stores frequency counter offset mode (table below)	
#define offset1						eeprom_settings1,0x05
	endif
	ifdef include_bug_code
#define bug_mode_on					eeprom_settings1,0x06		; 1 = bug mode activated
	endif



	; frequency counter offset table
	; offset0		offset1
	;	0				0		no offset
	;	0				1		reading = offset - measurement
	;	1				0		reading = measurement - offset
	;	1				1		reading = measurement + offset



	org 0x00
	pagesel main_program_start
	errorlevel -306
	goto main_program_start
	errorlevel +306
		
; Tables -------------------------------------------------------------


cw_table
	
	; this is a lookup table for sending numbers in CW using send_cw routine
	
	; 00 = termination
	; 01 = dit
	; 11 = dah
	
	; stream goes MSB -> LSB  (MSB first)
	; two bytes long
	

	addwf PCL, F
	retlw b'11111111'	;0		0
	retlw b'11000000'
	retlw b'01111111'	;1		1
	retlw b'11000000'
	retlw b'01011111'	;2		2
	retlw b'11000000'
	retlw b'01010111'	;3		3
	retlw b'11000000'
	retlw b'01010101'	;4		4
	retlw b'11000000'
	retlw b'01010101'	;5		5
	retlw b'01000000'
	retlw b'11010101'	;6		6
	retlw b'01000000'
	retlw b'11110101'	;7		7
	retlw b'01000000'
	retlw b'11111101'	;8		8
	retlw b'01000000'
	retlw b'11111111'	;9		9
	retlw b'01000000'
	ifdef include_cw_table_long
	retlw b'01110000'	;A		10
	retlw b'00000000'
	retlw b'11010101'	;B		11
	retlw b'00000000'
	retlw b'11011101'	;C		12
	retlw b'00000000'
	retlw b'11010100'	;D		13
	retlw b'00000000'
	retlw b'01000000'	;E		14
	retlw b'00000000'
	retlw b'01011101'	;F		15
	retlw b'00000000'
	retlw b'11110100'	;G		16
	retlw b'00000000'
	retlw b'01010101'	;H		17
	retlw b'00000000'
	retlw b'01010000'	;I		18
	retlw b'00000000'
	retlw b'01111111'	;J		19
	retlw b'00000000'
	retlw b'11011100'	;K		20
	retlw b'00000000'
	retlw b'01110101'	;L		21
	retlw b'00000000'
	retlw b'11110000'	;M		22
	retlw b'00000000'
	retlw b'11010000'	;N		23
	retlw b'00000000'
	retlw b'01111101'	;P		24
	retlw b'00000000'
	retlw b'11110111'	;Q		25
	retlw b'00000000'
	retlw b'01110100'	;R		26
	retlw b'00000000'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -