📄 avr pocsag rev 1_1.asm
字号:
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 + -