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

📄 avr pocsag rev 1_1.asm

📁 AVR pocsag解码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;***************************************************************************
;* Title: AVR_POCSAG pocsag encoder test code Rev. 1.1
;* Made available for educational, and non-commercial use.
;* Commercial use forbidden without license from author.
;* Code may be modified as long as it is released publicly and credit
;* is given to the original author(s).  
;* (c) copyright 2000 Henry Carl Ott N2RVQ, All Rights Reserved.
;* Questions, comments or offers of cash? carlott@rcn.net  http://users.rcn.com/carlott/
;***************************************************************************
;* Description: A standalone pocsag encoder. Unit will accept strings from console and encode
;* as standard POCSAG. Alphanumeric, numeric only, and tone messages can be encoded at 
;* 512/1200/2400 baud and as inverted or non-inverted data. In addition support is provided for
;* transmission of Morse encoded strings at varying speed rates, radio control, and certain
;* debugging functions. Please see companion documentation for schematics, use, and command syntax.  
;****************************************************************************
;* Credits: The asc2bin routine is a modified/limited version of a routine by Jack Tidwell as made
;* available in his avrmath.asm code. Credit is also given to everyone who made example AVR
;* code available on the net for me to learn how to program these Atmel processors.
;***************************************************************************
;* Disclaimer: This code is provided "as is".  Don't use this code/design for any
;* application where human life is at risk  or property damage may occur.
;***************************************************************************  
;Versions:
; 1.1 fixed timing error in isr timer reload value
; 1.0 first release
 
.nolist
.include "2313def.inc"	
.list
.listmac

;***************************************************************************
;*
;* MACROS
;*
;***************************************************************************
;--- simple led macro
.macro	led_on
	sbi	PORTD,led
.endm	
.macro	led_off
	cbi	PORTD,led
.endm	

;--- send single char to console
.macro	_send
	ldi	temp,@0 
	rcall	putc
.endm	

;--- send string to console
.macro _send_232_str
	ldi	zh,high(@0 * 2)
       	ldi	zl,low(@0 * 2) 	;Init Z-pointer
	rcall	ser_ram_str
.endm

;--- copy flash data to pocsag output buffer
.macro	_flash2buff
	ldi	zh,high(@0 * 2)
       	ldi	zl,low(@0 * 2) 	;Init Z-pointer
	rcall	flash2buff
.endm

;--- skip next instruction
.macro	skip
	rjmp	(pc + 2)	; skip, next instruction	
.endm	

;------delay two cycles in one instruction
.macro	_nop_2
	rjmp	(pc + 1)
.endm	



;--- some program equates and constants
.equ	ram_begin	= 0x60		; start of ram on 2313	
.equ	max_str_len	= 80		; max len of string from console
.equ	getc_to_val	= 4		; time before getc will timeout (in approx 2.5 second incs)
.equ	eom_char	= eot		; char to append to alpha messages (may not be necessary)	
.equ	clock 		= 7372800 	; cpu clock
.equ	console_baud 	= 9600
.equ	isr_divider 	= (0xffff - (clock/9600)) + 15

;--- ascii char codes
.equ	ctrl_c 		= 0x03
.equ	etx		= 0x03
.equ	eot		= 0x04
.equ	bel 		= 0x07 		; bell
.equ	bs  		= 0x08		; back space
.equ	cr  		= 0x0d		; carriage return 
.equ	lf  		= 0x0a		; line feed


;.equ	frame_sync	= 0x7CD215D8	;  pocsag frame sync word (for reference)
;.equ	idle 		= 0x7A89C197	;  pocsag idle word 	  (for reference)

;-----------------------------------------------------------------
;--- port and pin defines
;--- portb 
.equ spare_0	= 0
.equ cfg_0	= 1	; unused at moment	
.equ cfg_1	= 2	; unused at moment 
.equ cw_out	= 3	; tone output for cw generation
.equ poc_out	= 4	; encoded pocsac data out
.equ inp_1	= 5	; send canned message 1
.equ inp_2	= 6	; send canned message 2	
.equ tx_inhibit	= 7	; x-mitter lockout

;--- portd
.equ ptt	= 6 	; key radio
.equ led	= 5	; status
.equ cts_232 	= 4	; clear to send output, asserts while transmitting to indicate busy 
.equ spare_1    = 3	;
.equ spare_2	= 2	;  
.equ txd_232	= 1	; O 232_txd 
.equ rxd_232	= 0	; I 232_rxd

;*****************************
;* Global Register Variables *
;*****************************
.def	r0		= r00	; used with lpm instruction
.def	tic		= r01	; incs @ 9600 hz resets at 96 0-95
.def	sec_01		= r02	; incs @ 100 hz	
.def	u_data  	= r03	; rs-232 data (rx)
.def	EEaddr		= r04	; internal eeprom address buffer
.def	EEdata		= r05	; internal eeprom data buffer for rd/wr 
.def	frame		= r06	; current pocsag frame 0-15

.def	mant1hh		= r07	
.def	mant1h		= r08	; used for ascii to bin conversion
.def	mant1m		= r09	; also mapped to bin
.def	mant1		= r10

.equ	at_bin		=  07	; pointer location of bin registers	
.def	binhh		= r07	; msb	
.def	binh		= r08	; working registers to build pocsag word
.def	binm		= r09
.def	bin		= r10	

.def	mant2hh		= r11
.def	mant2h		= r12	; used for asc2bin routines 
.def	mant2m		= r13	; also mapped to pocbuff
.def	mant2		= r14

.equ	at_poc_buff	=  11	; pointer location of buffer regs 
.def	poc_buff_hh	= r11	; 32 bits of data to be clocked out by isr
.def	poc_buff_h	= r12
.def	poc_buff_m	= r13
.def	poc_buff	= r14
.def	isr_save	= r15	; saves mcu status reg during isr 

.def	temp		= r16	; gp working reg 	
.def	temp2		= r17   ; yet another working register 
.def	ii		= r18	; gp loop counter
.def	flags		= r19	; various bit flags for isr
.def	poc_flags	= r20	; various bit flags of message being sent	
.def	byte_cnt	= r21	; general purpose byte counter
.def	bit_cnt		= r22	; gp bit counter
.def	morse_rate	= r23	; dit length in .01 incs 	 
.def	poc_bit_cnt	= r24	; bit counter for isr x-mit routine 1-32
.def	poc_baud_div	= r25	; divide isr 9600 tic to 2400,1200,512

.def	poc_char_pnt	= r26	; pointer to next message char to process 
.def	poc_char	= r27	; current char being processed
.def	yl		= r28	; used in flash2buff to point to destination
.def	yh		= r29	; 
.def	zl		= r30	; used for indirect indexing   
.def	zh		= r31	; used for indirect indexing 

;**************************
;- isr bit flags defined
;**************************
.equ	p_baud_1200	= 0x00		; pocsag baud rate for isr  
.equ	p_baud_2400	= 0x01		; ditto, if neither bit is set, then baud = 512
.equ	p_invert	= 0x02		; invert pocsag data before sending
.equ	cw_tone		= 0x03		; turns on tone generation in isr
.equ	uart_rx		= 0x04		; incoming char is ready
.equ	debug		= 0x05		; if set, echo pocsag data to console
.equ	poc_pre0	= 0x06		; divide by 4 prescaler for pocsag  512 baud
.equ	poc_pre1	= 0x07		; ditto

;**************************
;- pocsag stored message bit flags defined
;**************************
.equ	m_baud_1200	= 0x00	
.equ	m_baud_2400	= 0x01		; if neither bit, then 512
.equ	m_invert	= 0x02		; invert?
.equ	m_spare		= 0x03		; not used
.equ	m_fun_0		= 0x04		; msg function
.equ	m_fun_1		= 0x05		; msg function
.equ	m_type_num	= 0x06		; msg type numeric
.equ	m_type_alpha	= 0x07		; msg type alpha

;-------------------------

;*********************
;* Interrupt Vectors *
;*********************

.CSEG
.org		0x00				; reset 
		rjmp	reset			
.org		INT0addr			; external int 0 	
		reti
.org		INT1addr			; external int 1
		reti
.org		OVF1addr			; overflow of 16 bit timer 1 
		reti			
.org		OVF0addr			; overflow of 8  bit timer 0 ; 9600hz system tic 
		rjmp	t0int
.org 		URXCaddr			; reception of data by uart
		rjmp	uart_rx_isr		

;--- timer 1 overflow interupt, we should hit the isr @ 9600 hz		
;--- the isr shifts out the 32 bit pocsag word at the correct baud rate
;--- isr will also generats cw tone, and incs the sec_001 counter @ 100 hz
t0int:		in	isr_save,SREG		; save SREG
		push	temp	
		
		ldi	temp,256 - ((clock/8) / 9600) + 1 ;(1 = approx overhead)
		out	TCNT0,temp		; 

		inc	poc_baud_div		; 
		inc	tic			; bump counter everytime through
		ldi	temp,96			; divide by 96 to get our 10ms tic	
		eor	temp,tic		; 
		brne	no_roll_over		; no rollover		

		clr	tic
		inc	sec_01			; bump hunds of seconds (10ms)

no_roll_over:	sbrs	flags,cw_tone		; is tone enabled ?
		rjmp	sel_poc_baud		; no

		sbrc	tic,3			; 1200 hz out
		sbi	portb,cw_out		
		sbrs	tic,3
		cbi	portb,cw_out	
		rjmp	tmr0isr_end		; skip pocsag generation		

sel_poc_baud:	sbrc	flags,p_baud_1200	; test baud rate bits
		rjmp	set_1200		;
		sbrc 	flags,p_baud_2400	;
		rjmp	set_2400	
					
set_512:	mov	temp,flags		; (9600*4) / ((3*19)+18)) = 512
		andi	temp,0b11000000		; so, 1 in 4 times we count to 18 
		breq	div18			; other three times count to 19
div19:		ldi	temp,1
div18:		subi	temp, -18		; add 18 
		cp 	poc_baud_div,temp	; 
		brne 	tmr0isr_end		; no match

		ldi	temp,0x40		; matched	
		add	flags,temp		; top two bits of flag register is used to divide by 4
		rjmp	period			; process bit

set_1200:	cpi 	poc_baud_div,8		; 1200 = 9600 / 8
		breq 	period			; match	
		rjmp 	tmr0isr_end		; no match

set_2400:	cpi	poc_baud_div,4		; 2400 = 960 /4
		brne	tmr0isr_end		; no match
	
period:		clr	poc_baud_div		; reset baud rate divisor
		tst	poc_bit_cnt		; test for zero bits
		breq	tmr0isr_end		; nothing to send
	
		ldi	temp,0x80	 	; if invert flag is set, we invert the bit prior to sending
		sbrc	flags,p_invert		; 
		eor	poc_buff_hh,temp		

		sbrs	poc_buff_hh,7		; copy hi bit to output pin
		cbi	portb,poc_out		; 
		sbrc 	poc_buff_hh,7		; double test for no jitter
		sbi	portb,poc_out		; 	
		
		rol	poc_buff		; rotate next bit into position
		rol	poc_buff_m
		rol	poc_buff_h
		rol	poc_buff_hh		; msb

		dec	poc_bit_cnt		; dec number of bits left to send

tmr0isr_end:	pop	temp			; 
		out	SREG,isr_save		; restore
		reti

;--- rs-232 char reception isr, checks for errors and discards bad chars  
uart_rx_isr:	in	isr_save,SREG		; store SREG
		push	temp			
		sbic	USR, FE			; skip if framing error
		rjmp	uart_err		; 
		in	temp, UDR		; get rx byte
		sbic	USR, OR			; skip if overrun error
		rjmp	uart_err			; 
		mov	u_data,temp		; save actual data
		sbr	flags,(1<<uart_rx)	; set received data flag
		rjmp	uart_isr_end

uart_err:	in	temp, UDR		; read and discard byte to clear UDR
		cbr	flags,(1<<uart_rx)	; clear flag return

uart_isr_end:	pop	temp			; restore
		out	SREG,isr_save		; restore	
		reti

;------------------------------------------------------------------------
;--- start here on power up or external reset
;--- init ports, ints,  		
;--- zero all  registers, maybe not necessary but a good idea while debugging 		
reset:		ldi	r16,0
		ldi	zl,0				; beginning of registers		
clr_reg:	st	z+,r16
		cpi	zl,0x1e				; don't zero z reg
		brne	clr_reg

;--- init stack pointer (somewhat important)
		ldi    temp,low(RAMEND)			; init stack 
       		out    spl,temp 
;--- portb setup
		ldi	temp,(1 << cw_out)|(1 << poc_out)
		out	DDRB,temp
		sbi	PORTB,cfg_0			; pull up	
		sbi	PORTB,cfg_1			; pull up
;--- portd setup
		ldi	temp,(1 << led)|(1 << cts_232)|(1 << txd_232)|(1 << ptt)
		out	DDRD,temp
;--- setup uart, 9600 baud, int on rx, no tx ints
		ldi	temp,((clock / console_baud) / 16) -1
		out	UBRR,temp			; Set baud rate generator
		ldi	temp, (1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable rxc interrupts
		out	UCR,temp			; enable UART tx & rx  w/o interrupts
;--- set up tmr0

		ldi	temp,2				; timer 0 prescale/8
		out	TCCR0,temp			;

		ldi	temp,0b00000010			; enable Timer 0 interrupt
		out	TIMSK,temp

;--- global enable ints
		sei					; enable global ints
		ldi	morse_rate,0x05			; default morse wpm rate	
		
		_send_232_str	_hello			; display sign on message

		led_on					; flash the led
		ldi	temp,100
		rcall	del_hunds
		led_off
		
		rjmp	cmd_top				; wait for command

error:		_send_232_str	_error
;----------------------------------------------
cmd_top:	cbi	PORTD,cts_232			; enable comm
		rcall	crlf				; prompt
		_send	'.'


inp_loop:	sbis	PINB,inp_1			; inp 1 or 2 down?
		rjmp	send_inp_1		
		sbis	PINB,inp_2	
		rjmp	send_inp_2
		sbrs	flags,uart_rx			; any console data?
		rjmp	inp_loop

	   	rcall	get_string
		brcc	pc+2				; valid string?
		rjmp	cmd_top

		ldi	zl,ram_begin			; convert first char to upper case
		ld	temp,z
		rcall	to_upper

do_cmd:		cpi	temp,'D'			; set debug mode
		brne	pc+2
		rjmp	set_debug

		cpi	temp,'I'			; test inhibit line
		brne	pc+2				; return status
		rjmp	check_inhibit

		cpi	temp,'M'			; send morse string	
		brne	pc+2
		rjmp	send_morse

		cpi	temp,'R'			; get morse wpm
		brne	pc+2
		rjmp	set_m_rate

		cpi	temp,'G'			; get a message and store in eeprom
		brne	pc+2
		rjmp	get_eemsg

		cpi	temp,'S'			; send canned message from eeprom
		brne	pc+2
		rjmp	send_eemsg
	
		cpi	temp,'P'			; send pocsag message directly 
		breq	send_con_str
		rjmp	cmd_top

;---------------------------------------------------------------------------------
;--- set and display debug mode
set_debug:	lds	temp,ram_begin+1				; get arg
		cpi	temp,'0'
		brne	pc + 2
		cbr	flags, 1 << debug		; set appropriate flag
		cpi	temp,'1'
		brne	pc + 2
		sbr	flags, 1 << debug
		_send_232_str	_debug			; message
		ldi	temp,'0'
		sbrc	flags,debug
		ldi	temp,'1'
		rcall	putc				; send status
		rjmp	cmd_top

;--- test and return status of tx_inhibit line
check_inhibit:	rcall	crlf
		ldi	temp,'0'
		sbic	PINB,tx_inhibit
		ldi	temp,'1'
		rcall	putc
		rjmp	cmd_top	

;--- send console string via morse	
send_morse:	sbi	PORTD,cts_232
		ldi	ii,1
		rcall	pos_zl
		mov	xl,zl				; point to data

		rcall	key_radio
		rcall	send_cw_string
		rcall	unkey_radio
		rjmp	cmd_top	

;--- set morse wpm rate
set_m_rate:	ldi	ii,1
		rcall	pos_zl
		rcall	asc2bin
		mov	morse_rate,bin
		rjmp	cmd_top

;--- send console string as pocsag directly 
send_con_str:	sbi	PORTD,cts_232			; disable comm
		rcall	count_param
		cpi	byte_cnt,6			; check for minimum num of args	
		brsh	pc + 2	
		rjmp	error
		rcall	parse_msg			; parse out cap code and flags

		rcall	test_cap			; make sure cap code is within valid range
		brcc	pc +2
		rjmp	error

		ldi	ii,6
		rcall	pos_zl				; get pointer to message data	
		mov	poc_char_pnt,zl

⌨️ 快捷键说明

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