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

📄 avr pocsag rev 1_1.asm

📁 AVR pocsag解码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
		rcall	send_page			; send it
		rjmp	cmd_top				

;--- parse console string  and store in one of two eeprom storage areas
get_eemsg:	sbi	PORTD,cts_232			; disable comm
		rcall	count_param
		cpi	byte_cnt,6			; check for minimum num of args	
		brsh	pc + 2
		rjmp	error				; not enough args	

		rcall	set_eeaddr			; get second char of string, set EEaddr to msg1_pin or msg2_pin
		breq	pc + 2
		rjmp	error
	
		rcall	parse_msg			; get pin and flags	
		rcall	test_cap			; is pin in valid range?
		brcc	pc +2
		rjmp	error

		mov	EEdata,binh			; save cap code to eprom
		rcall	EEwrite
		mov	EEdata,binm
		rcall	EEwrite
		mov	EEdata,bin
		rcall	EEwrite
		mov	EEdata,poc_flags
		rcall	EEwrite				; save the flag bits

		ldi	ii,6				; now get message data		
		rcall	pos_zl				; point to data
parse_dl:	clr	EEdata	
  		mov	temp,EEaddr
 		andi	temp,0b00111111			; only 64 chars allowed per message
 		cpi	temp,0b00111111		
 		breq	pc + 2	
		ld	EEdata,z+			; get char
		rcall	EEwrite				; save char
		tst	EEdata				; tst for zero termination
		brne	parse_dl			; get next char	
		rjmp	cmd_top
		
;--- send a canned message from eeprom
send_eemsg:	sbi	PORTD,cts_232			; disable comm
		rcall	set_eeaddr
		breq	pc + 2
		rjmp	error
		rcall	send_msg_ee
		rjmp	cmd_top				


;--- get second char of string
;--- load EEaddr, z is cleared if no match (bad)
set_eeaddr:	lds	temp2,ram_begin + 1		; get second char of string	
		ldi	temp,msg1_pin
		cpi	temp2,'1'
		breq	set_ee_end			; if '1' send message 1	
		ldi	temp,msg2_pin
		cpi	temp2,'2'
		breq	set_ee_end			; and etc.	
		clz					; no match, back to top
set_ee_end:	mov	EEaddr,temp
		ret


;-------------------------------------------------------------
;--- wait for hw input to de-assert, then send canned message 1 or 2
send_inp_1:	sbi	PORTD,cts_232			; disable comm
		ldi	temp,msg1_pin			; load pointer	
		clr	temp2
		led_on					; status
s_inp_1_lp:	sbis	PINB,inp_1			; debounce
		clr	temp2				; reset
		dec	temp2
		breq	send_inp_x			; do_it
		rjmp	s_inp_1_lp			; loop
;---
send_inp_2:	sbi	PORTD,cts_232
		ldi	temp,msg2_pin
		clr	temp2
		led_on
s_inp_2_lp:	sbis	PINB,inp_2			; debounce
		clr	temp2				; reset
		dec	temp2
		breq	send_inp_x			; do_it
		rjmp	s_inp_2_lp			; loop

send_inp_x:	mov	EEaddr,temp
		rcall	send_msg_ee
		rjmp	cmd_top	


;--- send message from eprom
;--- call with EEaddr pointing to pin
send_msg_ee:	rcall	get_ee_msg			; copy eeprom data to regs and ram
		ldi	poc_char_pnt,ram_begin		; point to data

;------------------------------------------------------------------
;--- send a complete page from ram
;--- bin should have cap code
;--- poc_flags should be loaded
;--- poc_char_ptr points to first char of data
send_page:	mov	byte_cnt,bin
		andi	byte_cnt,0x07			; get low three bits of address and save 
		lsl	byte_cnt			; multiply by 2

		mov	temp,bin			
		andi	temp,0b11111000			; mask off low bits
		sbrc	poc_flags,m_fun_1
		sbr	temp, 1 << 2			; copy in function bits 
		sbrc	poc_flags,m_fun_0
		sbr	temp, 1 << 1			; copy in function bits 
		mov	bin,temp			; copy it back
		
		;clr	binhh				; clear any garbage
		lsr	binh
		ror	binm
		ror	bin				; move to final bit positions
		rcall	ecc_bin				; add ecc and parity 

		mov	temp,poc_flags			; copy baud and invert status from stored message to isr flags
		andi	temp,0b00000111			; mask off high bits
		andi	flags,0b11111000		; mask off low bits
		or	flags,temp			; now mask in low bits

		rcall	key_radio			; key radio
		ldi	temp,50
		rcall	del_hunds			; wait a half second

		ldi	ii,18
send_preamble:	_flash2buff	_0xaa			; send preamble, 576 bit reversals				
		dec	ii
		brne	send_preamble
		rcall	new_frame			; new frame, send sync, clear frame counter	

wait4frame:	cp	frame,byte_cnt			; match?
		breq	send_message
		_flash2buff	_idle			; no match, send idle, keep looping	
		rcall	next_frame
		rjmp	wait4frame			; loop it

send_message:	rcall	bin2buff			; send address
		rcall	next_frame			; bump frame counter

		mov	temp,poc_flags
		andi	temp,0b11000000			; tone only message?
		breq	send_p_end			; then all done

		clt					; init for first data char
		ldi	bit_cnt,20			; 20 bits to pack per frame 
		ldi	byte_cnt,0			; count bits within char (4 bits tone) (7 bits alpha) 	

send_data_lp:	rcall	pack_data
		brcs	send_p_end			; if carry is set, there is no data to send
		rcall	bin2buff			; send packed data
		rcall	next_frame			; bump frame counter add frame sync as necessary
		rjmp	send_data_lp			; loop for more data

send_p_end:	rcall	fill_batch			; fill batch in progress with idle frames
wait_p_done:	tst	poc_bit_cnt			; wait for tx buffer to empty out
		brne	wait_p_done
		rcall	unkey_radio			; all done
		ret

;------- pocsag xmit support subroutines
;--- fill current batch with idles	
fill_batch:	sbrc	frame,4				;  are we at 16?		
		ret					; yes, all done
		_flash2buff	_idle			; send a idle frame	
		inc	frame				
		rjmp	fill_batch			; keep looping
;--- inc frame counter. if necessary send a frame sync and reset frame counter
next_frame:	inc	frame				; bump frame counter
		sbrs	frame,4				; roll over at 16
		ret
new_frame:	_flash2buff	_frame_sync		; send a frame sync char	
		clr	frame				; clear frame counter
		ret

;--- get chars from ram, pack them into 20 bit frames, ecc the data and return
;--- if no more data, set carry
;--- enter with xl pointing to first byte of zero terminated data string
;--- uses temp,bit_cnt,byte_cnt,poc_char,poc_char_ptr
;--- t bit flag indicates padding in progress
pack_data:	tst	byte_cnt			; any bits from left from last char?
		breq	pc + 2				; nope
		rcall	stuff_char			; otherwise shift in those left over bits	
		brts	pad_data			; last frame was padded, finish up

get_poc_char:	ld	poc_char,x+			; get char
		tst	poc_char			; all done
		breq	pad_data

		ldi	byte_cnt,7
		sbrc	poc_flags,m_type_num
		rcall	xlate_numbers			; if message numeric traslate ascii, and set byte_cnt to 4

		rcall	stuff_char
		cpi	bit_cnt,20			; did we fill a frame?
		brne	get_poc_char			; nope get another char
		clc					; clear carry to indicate okay data
		ret					; yep, return with encoded data

;--- fill empty bit positions in incomplete data words with appropriate data
;--- numeric message are filled with space charsif necessaary, alphas get at least one eom char
pad_data:	sbrc	poc_flags,m_type_alpha		; letters / numbers
		rjmp	pad_alpha			; 

;---
pad_num:	cpi	bit_cnt,20			; are we at beginning of next frame?	
		brne	pad_num_l			; no, have to pad
		sec					; yes, no data to send
		ret					; and out

pad_num_l:	ldi	poc_char,0x0c
		ldi	byte_cnt,4			;
		rcall	stuff_char			
		cpi	bit_cnt,20			; done ?
		brne	pad_num_l			; keep looping
pad_in_dat:	set					; set t flag to indicate padding was done
		clc					; there is data to send		
		ret

;--- we stick at least one eom char at end of alpha message
pad_alpha:	brtc	pad_alpha_1			; was frame was padded

		cpi	bit_cnt,20			; are we at beginning of next frame?	
		brne	fill_alpha			; no, we have to pad
		sec					; yes, done, no data to send
		ret	

pad_alpha_1:	rcall	stuff_eom			;
		breq	pad_in_dat			; no, send what we have, finish next time through

fill_alpha:	rcall	stuff_eom
		brne	fill_alpha			; 
		clr	byte_cnt			; discard rest of bits
		rjmp	pad_in_dat			; set status and return

;--- stuff eom char, test for full buffer
stuff_eom:	ldi	poc_char,eom_char		; fill rest of bin with eoms			
		ldi	byte_cnt,7			; 7 bits per char
		rcall	stuff_char
		cpi	bit_cnt,20
		ret

;--- rotate lsb of char being processed into lsb of bin
;--- dec byte_cnt, if more bits keep stuffing, otherwise exit
;--- when 20 bits are done, set high bit to indicate a data frame
;--- ecc bin, clear bit_cnt, and return
stuff_char:	ror	poc_char			; rotate lsb into carry

		rol	bin				; rotor it out
		rol	binm				; lsb of raw data is msb of frame
		rol	binh

		dec	bit_cnt				; amy more room in frame?
		breq	stuff_full			; nope	

		dec	byte_cnt			; all bits in char processed?
		brne	stuff_char			
		ret			

stuff_full:	dec	byte_cnt			; we have to count that last bit	
		ldi	temp,0b00001111
		and	binh,temp			; clear out any garbage
		ldi	temp,0b00010000
		or	binh,temp			; set high bit to indicate data
		rcall	ecc_bin				; add ecc and parity	
		ldi	bit_cnt,20 			; set up for next data frame
stuff_end:	ret 



;---  translate ascii data into numeric data
;--- numbers convert to numbers (duh), spaces, hyphens, brackets are translated individually
;--- non valid characters will convert to spaces 
xlate_numbers:	ldi	byte_cnt,4		; four bits for char stuff routine
		cpi	poc_char,'9'+1
		brsh	xlate_non_num
		cpi	poc_char,'0'
		brlo	xlate_non_num
		subi	poc_char,'0'
		ret				; 0-9, just convret to bcd  and return

xlate_non_num:	mov	temp,poc_char		; save it
		rcall	to_upper
		ldi	poc_char,0x0c		; preload with space char

		cpi	temp,'U'		; urgent char	
		brne	pc + 2
		ldi	poc_char,0x0B	
		cpi	temp,'-'
		brne	pc + 2
		ldi	poc_char,0x0D	
		cpi	temp,']'
		brne	pc + 2
		ldi	poc_char,0x0E
		cpi	temp,'['
		brne	pc + 2
		ldi	poc_char,0x0F
		ret

;--- parse string,  get pin,function,baud rate,invert status,msg type, 
;--- pin goes to bin, message flags goto poc_flags, leaves data in ram 
parse_msg:	ldi	ii,1				; get pin
		rcall	pos_zl
		rcall	asc2bin				; convert to binary
	
		ldi	ii,2				; now get msg options and mask into temp2
		rcall	pos_zl			

		ld	poc_flags,z
		andi	poc_flags,0x03			; mask off high bits
		swap	poc_flags			; move bits into location
		
		ldi	ii,3				; get baud
		rcall	pos_zl				; 2400,1200,512
		ld	temp,z
		cpi	temp,'2'			; if no match, will default to 512
		brne	pc + 2
		sbr	poc_flags, 1 << m_baud_2400	
		cpi	temp,'1'
		brne	pc + 2
		sbr	poc_flags, 1 << m_baud_1200	

		ldi	ii,4				; get message polarity, invert if 'I' 
		rcall	pos_zl				; else normal
		ld	temp,z
		rcall	to_upper
		cpi	temp,'I'
		brne	pc + 2
		sbr	poc_flags, 1 << m_invert
		
		ldi	ii,5				; get mesage type, A,N,T
		rcall	pos_zl				; default to Tone only
		ld	temp,z
		rcall	to_upper
		
		cpi	temp,'A'
		brne	pc + 2
		sbr	poc_flags, 1 << m_type_alpha	
		cpi	temp,'N'
		brne	pc + 2
		sbr	poc_flags, 1 << m_type_num	
		ret		
;---
key_radio:	led_on					; status
		sbis	PINB,tx_inhibit			; wait for inhibit line to de-assert 
		rjmp	key_radio
		led_off
		sbi	PORTD,ptt
		ret

unkey_radio:	cbi	PORTD,ptt
		ret

; make sure cap code (pin) is within  valid range 8 - 2097151
test_cap:	tst	binhh
		brne	test_p_err			 
		mov	temp,binh
		andi	temp,0b11100000			; mask off bottom bits
		tst	temp
		brne	test_p_err			; too big

		tst	binh
		brne	test_p_ok		
		tst	binm
		brne	test_p_ok

		mov	temp,bin
		cpi	temp,8
		brlo	test_p_err			; too small	

test_p_ok:	clc
		rjmp	pc + 2
test_p_err:	sec
		ret

;--- add ecc and even parity to 21 bits of data in bin0 - bin3
;--- bin3 is lsb
; trashes ii,temp,temp2
ecc_bin:	push	bin
		push	binm
		push	binh

		ldi	ii,21		; 21 bits to test
		rjmp	ecc_b		; first bit,  skip initial rotate

ecc_a:		rcall	rol_mant	; next bit
ecc_b:		sbrs	binh,4		; test hi bit of data
		rjmp	ecc_c		; no high bit, skip xor 

		ldi	temp,0x1d	; if the ms bit = 1 the xor in poly	
		eor	binh,temp	
		ldi	temp,0xa4
		eor	binm,temp

ecc_c:		dec	ii		; any more bits?	
		brne	ecc_a		; nope, keep going

		mov	temp,binm	; save ecc data	
		mov	temp2,binh
		lsr	temp2		; shift right to line up data
		ror	temp		; into final bit positions	

		pop	binhh		; get orig data, shifted by one byte	
		pop	binh		; ditto
		pop	binm		; ditto
		
		ldi	ii,3
ecc_dl:		rcall	rol_mant	; left shift into final positions
		dec	ii
		brne	ecc_dl

		mov	bin,temp	; get low bits of ecc
		or	binm,temp2	; or in hi bits of ecc

		mov	temp,binhh	; calc even parity
		eor	temp,binh
		eor	temp,binm
		eor	temp,bin	; reduce 32 bits to 8	

		mov	temp2,temp	; save it, two copies

		swap	temp2		; xor top nibble with lower
		eor	temp,temp2	; 8 bits reduced to 4
		mov	temp2,temp	; save it, two copies

		lsr	temp2
		lsr	temp2		; rotate 2 bit pos
		eor	temp,temp2	; 4 bits reduced to two bits

		mov	temp2,temp	; save it 
		lsr	temp2
		eor	temp,temp2	; parity left in bottom four bits 0000=even 1111=odd
		andi	temp,0x01	; leave only bottom bit
		or	bin,temp	; and mask it in
		ret	

;--- send zero terminated string from ram as morse code
;--- xl points to first char
send_cw_string:	ld	poc_char,x+		; get char
		tst	poc_char		; are we done?
		brne	pc + 2
		ret
		rcall	morse_xlate		; xlate to dits and daahs
		rcall	send_cw_char		; send char		
		rjmp	send_cw_string		; get next char
	
;--- ship single pre xlated char
send_cw_char:	tst	poc_char		; is space char?
		brne	send_char_l		; nope, send it
		rcall	del_word		; 
		ret

send_char_l:	sbrs	poc_char,7		; test high bit, call appropriate routine
		rcall	dit
		sbrc	poc_char,7		; call appropriate routine
		rcall	dah

		lsl	poc_char
		cpi	poc_char,0b10000000
		breq	pc +2

⌨️ 快捷键说明

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