📄 pdu.asm
字号:
;==========================================================
; This is a part of: Eversmith - AVRSMS
; Copyright (2003) Martin Thomas, Kaiserslautern, Germany.
; This Software is distributed under the Aladdin Free
; Public License (AFPL) Read the file license.txt included
; in the distibution-package. See main-file for more infor-
; mation and license.
;==========================================================
; - PDU generation and transmit to ME
; - PDU decoding of received SMS-PDUs
;
; Based on: Siemens Developers-Guide "SMS with PDU-Mode"
; Version 1.2, Jul 30, 1997 ("google" for it)
;
; Modem is connected to USART1
;
; Search the lines "*Siemens only" if you don't use a
; Siemens GSM ME (like Nokia or Ericsson) and read the
; comments. Test for user-configuration in V0.56...
;----------------------------------------------------------
; Maximum memory index that will be read from the GSM-
; device by AT+CMGR=x (x=1...CMGRMAXIDX)
; (see Subroutine SMSProcessUnread)
;;; for debuging: changed from 15 to 10
.equ CMGRMAXIDX=10
;----------------------------------------------------------
; Maximum length of decoded PDU (rest is ignored) in SMSPARSEMAXLEN
; this means the number of digits in the senders number +
; the number of chars in the message + 2 for separator \r($0D) and lineend \0
; eg:491711234567\nABCDEFG\0 = 21
; (see Subroutine SMSDecodePDUtoRAM)
.equ SMSPARSEMAXLEN = 60
;----------------------------------------------------------
; a work area to store Messages to send and received
; SMSes - PDUs are generated on the fly so the
; area can be shared but take care to avoid side-effects
;
;(a) either create a local area:
;;.equ SMSWorkAreaMAX = 160
;;.DSEG
;;SMSWorkArray: .byte SMSWorkAreaMax
;;.equ SMSWorkArea = SMSWorkArray
;(b) or use shared area reserved in avrsms.asm
; Work1 must be assigned to a ram-area (dseg) before
; using it here (see map-file if in doubt)
.equ SMSWorkArea = Work1
;----------------------------------------------------------
; Poll-Intervall
; the ME will be polled every SMSPOLLINT seconds
; for incoming SMS
.equ SMSPOLLINT = 30
.CSEG
;----------------------------------------------------------
; PDUUartSend - Sends a byte to UART (GSM Modem)
;----------------------------------------------------------
;
; Inputs:
; r16 - Byte to send
;
; Ouputs:
; none
PDUUartSendByte:
call UART1SendByte
ret
;----------------------------------------------------------
; PDUStrLenRam - calculated length of Null-term. string in
; SRAM
;----------------------------------------------------------
;
; Inputs:
; Y-Register = Pointer to String
;
; Output:
; r17 = length of string (without terminating Null)
;
PDUStrLenRam:
push r16
push YL
push YH
ldi r17,$00
PDUStrLenRam_L1:
ld r16, Y+
tst r16
breq PDUStrLenRam_End
inc r17
rjmp PDUStrLenRam_L1
PDUStrLenRam_End:
pop YH
pop YL
pop r16
ret
;----------------------------------------------------------
; PDUAddCharRam - Adds a character to a Null-terminated
; string in SRAM
;----------------------------------------------------------
;
; Inputs:
; Y-Register = Pointer to String in SRAM
; r17 = Character to add
;
; Output:
; none
;
PDUAddCharRam:
push r16
push YL
push YH
PDUACR_L1:
ld r16,Y+
tst r16 ; test for Null
breq PDUACR_End
rjmp PDUACR_L1
PDUACR_End:
st -Y,r17 ; add character at eof
adiw YH:YL,$01
ldi r16,$00
st Y,r16 ; store terminating 0
pop YH
pop YL
pop r16
ret
;----------------------------------------------------------
; PDUHexAsciiLow - converts low nibble of byte to
; ASCII HEX-char
;----------------------------------------------------------
; based on code form the AVR Assembler tutorial
; TODO: add URL here
;
; Input:
; r17 = input byte
;
; Output:
; r16 = charcater rep. for low nibble
PDUHexAsciiLow:
mov r16, r17
andi r16, $0F ; only low nibble
subi r16,-'0' ; r16=r16+'0'
cpi r16,'9'+1 ; larger than '9'
brcs PDUHexAsciiLow_L1 ; no -> jump
subi r16,-7 ; r16=r16+7 ('0'=$30, '9'=$39, 'A'=$41, 'F'=$46)
PDUHexAsciiLow_L1:
ret
;----------------------------------------------------------
; PDUHexAsciiHigh - converts high nibble of byte to
; ASCII HEX-char
;----------------------------------------------------------
;
; Input:
; r17 = input byte
;
; Output:
; r16 = charcater rep. for high nibble
PDUHexAsciiHigh:
push r17
swap r17
rcall PDUHexAsciiLow
pop r17
ret
;----------------------------------------------------------
; PDUUartSendHex - Send a byte to UART Hex-encoded
;----------------------------------------------------------
;
; Input:
; r17 = input byte
;
; Output:
; goes to UART
PDUUartSendHex:
push r16
rcall PDUHexAsciiHigh
rcall PDUUartSendByte
rcall PDUHexAsciiLow
rcall PDUUartSendByte
pop r16
ret
;----------------------------------------------------------
; PDUSendHeader - Sends the PDU header (destination-number
; etc.) to UART
;----------------------------------------------------------
; depends on EEReadPlus from eeprom.asm
;
; Inputs:
; r24 = Destination Number in EEPROM low (Data null terminated)
; r25 = Destination Number in EEPROM high
;
; Output:
; Data goes to UART
;
; Side-effects:
; implicit from EEReadPlus
PDUSendHeader:
push r16 ; used by UartSend/Convert
push r17 ; used by Convert
push r18 ; counter
push r19 ; work num
push r20 ; work num
push r24
push r25
; SCA Len = 0 = use SMSC number stored in ME
ldi r17,$00
rcall PDUUartSendHex
; PDU-Type:
; VPF=16 validity relativ
; MTI=1 SMS-Submit MS->SMSC
ldi r17,16+1
rcall PDUUartSendHex
; Message Reference MR=0
ldi r17,$00
rcall PDUUartSendHex
; Orginator Adress Length
call EESeqLen ; load length in r17
rcall PDUUartSendHex ; send length in r17 as octet
; Orginator Adress type of number
; ALWAYS "number international" = int. acc. code prefixes number
ldi r16,'9'
rcall PDUUartSendByte
ldi r16,'1'
rcall PDUUartSendByte
; Orginator Adress Number
ldi r18,$01
PSH_L1:
; read
call EEReadPlus ; read first half of octet (high) in r16
mov r19,r16 ; store first half octet in r19
tst r19 ; end of number?
breq PSH_End
call EEReadPlus ; read second half of octet (low) in r16
mov r20,r16 ; store second half in r20
tst r16 ; end of number?
brne PSH_L2 ; no->jump to write
ldi r20,$0F ; fill with $0F if odd(ungrade)
ldi r18,$00 ; mark end
PSH_L2:
; write second half off octet
mov r17,r20 ; write second half first
rcall PDUHexAsciiLow
rcall PDUUartSendByte
mov r17,r19 ; write first half
rcall PDUHexAsciiLow
rcall PDUUartSendByte
tst r18
brne PSH_L1
PSH_End:
; PID always 00h
ldi r17,$00
rcall PDUUartSendHex
; coding-scheme
; coding group (bits 7-4) = 1111
; data-coding 7 bit (bit 2 cleared)
; class 1 ME (bit 0 set, bit 1 cleared)
ldi r17,0b11110001
rcall PDUUartSendHex
; validity period
.equ MAXDAYSVALID = 4
ldi r17,166+MAXDAYSVALID
rcall PDUUartSendHex
pop r25
pop r24
pop r20
pop r19
pop r18
pop r17
pop r16
ret
;----------------------------------------------------------
; PDUHeaderLen - Calculates the length of the header
;----------------------------------------------------------
; depends on EEReadPlus from eeprom.asm
;
; Inputs:
; r24 = Destination Number in EEPROM low (Data null terminated)
; r25 = Destination Number in EEPROM high
;
; Output:
; r22 = length of the header (0 if emphty or Error)
;
PDUHeaderLen:
push r16
push r24
push r25
ldi r22,$00 ; init counter
; initial empty protection:
call EEReadByte
cpi r16,$FF ; default EEprom content ofter chip-erase
breq PHL_END
; number length
PHL_L1:
call EEReadPlus ; read byte
inc r22 ; increment counter
tst r16 ; test for end-of-string
brne PHL_L1 ; no - read more
dec r22 ; decrement because the $00 has been counted
; needed bytes (devide by 2):
clc ; clear carry
ror r22 ; rotate right (devide by 2)
brcc PHL_L2 ; if r22 mod 2 == 0 skip
inc r22 ; count modulo
PHL_L2:
; rest of the header
;; According to the Siemens TC35-Documentation the SCA (length
;; and number) does not count to the pdu-length for at+cgms,
;; so the SCA-byte does not count here
;; no! ; inc r22 ; SCA length byte
inc r22 ; PDU-type
inc r22 ; Msg.-reference
inc r22 ; Orginator Adress length
inc r22 ; Org. adr. type of number
nop ; Length of dest.-number already calculated above
inc r22 ; PID
inc r22 ; Coding-scheme
inc r22 ; validity period
rjmp PHL_END
PHL_END:
pop r25
pop r24
pop r16
ret
;----------------------------------------------------------
; PDUSendText - Sends UDL/UD (the Text) to UART
;----------------------------------------------------------
;
; Inputs:
; Y-Register = SMS Text in RAM (Null terminated)
;
; Output:
; r24 - bytes in PDU by UDL and UD in bytes
; Data goes to UART
;
; Output:
; goes to UART
; TODO: well - this code looks strange and it is strange,
; it needs some clean-up, but, it works
PDUSendText:
push r16
push r17
push r18
push r19
push r20
push r21
push r22
push r23
push YL
push YH
; Data length UDL
rcall PDUStrLenRam ; len of message into r17
rcall PDUUartSendHex ; send r17 as hex
ldi r24,$01 ; init PDU byte count
; Data UD 7bit encoded
.def PDU_lens = r18 ; work byte
.def PDU_t = r17 ; work byte
.def PDU_n = r19 ; next byte
.def PDU_avn = r20 ; bits avail in next byte
.def PDU_avt = r21 ; bits avail in work byte
.def PDU_i = r22 ; counter
.def PDU_j = r23 ; counter
mov PDU_lens,r17 ; save len
inc PDU_lens
ldi PDU_avn,$00
ldi PDU_avt,$01
clc
ld PDU_t, Y+
; andi PDU_t,$ff; 0b01111111 ; clear 7th bit
ldi PDU_i,$01
PDU_brmain:
ldi PDU_j,$00
cpi PDU_avt,8
brlo PDU_br2
ldi PDU_avt,1
ld PDU_t, Y+
inc PDU_i
PDU_br2:
cp PDU_j,PDU_avt
breq PDU_br3
clc
rol PDU_t
inc PDU_j
rjmp PDU_br2
PDU_br3:
ld PDU_n,Y+
inc PDU_i
ldi PDU_avn,1
ldi PDU_j,0
PDU_br4:
cp PDU_j,PDU_avt
breq PDU_br5
ror PDU_n
ror PDU_t
inc PDU_avn
inc PDU_j
rjmp PDU_br4
PDU_br5:
; send r17=PDU_t
rcall PDUUartSendHex
inc r24
mov PDU_t,PDU_n
mov PDU_avt,PDU_avn
cp PDU_i,PDU_lens
brlo PDU_brmain
pop YH
pop YL
pop r23
pop r22
pop r21
pop r20
pop r19
pop r18
pop r17
pop r16
ret
;----------------------------------------------------------------------
; PDUDataLen - Calculates the length of the User Data (with length UDL)
;----------------------------------------------------------------------
;
; Inputs:
; YL = Message in SRAM low (Data null terminated)
; YH = Message in SRAM high
;
; Output:
; r23 = length of the user UD in PDU including length UDL
;
PDUDataLen:
push r16
push r17
push ZL
push ZH
; get Number of characters in message:
rcall PDUStrLenRam ; len goes into r17
clr ZL
clr ZH
; Number of bits in message (7 per char)
; (MUL not supported on 8515)
PDL_MUL:
cpi r17,$00
breq PDL_MULEND
adiw ZH:ZL,$07
dec r17
rjmp PDL_MUL
PDL_MULEND:
; devide Word in Z-Register by 8
ldi r16,$00
PDL_DIV:
cpi ZH,$00
brne PDL_DIV1
cpi ZL,$08
brlo PDL_DIV2
PDL_DIV1:
sbiw ZH:ZL,$08
inc r16
rjmp PDL_DIV
; if modulo!=0 add one to length
PDL_DIV2:
cpi ZL,$00
breq PDL_DIVFIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -