SMS Box: un dispositivo para decodificar mensajes PDU y leerlos, simplemente enviando mensajes, imprimiendo fácilmente números CLIP. Se cree que este mosaico se conecta a los controladores GSM y proporciona una comunicación fácil con el teléfono celular.
Puede habilitar SMS fácilmente cualquier proyecto sin necesidad de aprender comandos AT y analizar datos complicados al hablar con un módem AT dentro del teléfono.
Concepto
Si alguna vez quisiste conectar un teléfono GSM a tu proyecto de microcontrolador necesitarías saber que es un conjunto de comandos AT, usar comunicación serie, analizar todo tipo de datos para extraer lo que realmente necesitas, manejar errores de comunicación y todo tipo de cosas. La mayoría de los comandos AT son estándar para cada teléfono, pero no todos los teléfonos admiten mensajes de texto SMS en modo ASCII («TEXT-MODE»), sino que utilizan PDU-MODE.
Si cada teléfono fuera como, por ejemplo. Nokia 6210 la vida sería muy agradable. Simplemente construya un cable para habilitar su F-BUS (www.atrox.at) y listo, puede comenzar a usar mensajes SMS en modo texto. Otros teléfonos más baratos como Siemens C / M35, S25 y muchos teléfonos Ericsson no son compatibles con el modo de texto para mensajes SMS. En cambio, solo se pueden usar en pdu-mode (http://www.dreamfabric.com/sms). Lo bueno de ellos es que son muy baratos y no requieren cables externos para la inicialización. Tienen su puerto RS232 (TX, RX y GND) y listo, estás listo para hablar con el módem dentro de él.
Funcionamiento Técnico
¡La caja de SMS! maneja mensajes SMS en modo pdu para que no tenga que preocuparse por * muchas * cosas. Puede hablar con él a través de su «bus de 4 hilos» y se puede utilizar para:
- Recibir mensajes de sms (PDU -> ¡Conversión de texto!)
- Envío de mensajes SMS (modo TEXTO)
- Marcando un número de teléfono
- Cuelgue una llamada
- Consultar estado de llamada
- Recibir cadena CLIP
- Informe un proyecto RING al microcontrolador (interrumpa su programa uC)
- Responder una llamada
- Establecer la fecha y hora del teléfono - aún no implementado
- Obtener la fecha y hora del teléfono - aún no implementado
- Verifique el saldo de crédito prepago
Está basado en el microcontrolador PIC16F877A funcionando a 16MHz a 5V. Tiene un convertidor de nivel interno para comunicación serial con el teléfono gsm porque el pin de entrada UART RX de PIC tiene un gatillo Schmitt que dispara a 4,5 - 5V mientras el teléfono está enviando solo aprox. 3V desde su pin TX. También tiene un diodo Zener en el pin TX, por lo que no interrumpe la conexión de red del teléfono cuando habla con él. El firmware está escrito al 100 \% en el ensamblador MPASM.
Dos jumpers en los esquemas son para: cambio de velocidad de baudios (9600bps o 19200bps) - Los teléfonos Siemens usan principalmente 19200 mientras que los Ericsson usan 9600bps, el otro jumper es para habilitar el RING con informes CLIP para inicar alguna llamada en el proyecto de microcontrolador que se esté usando (si necesita que se lo notifiquen cuando el teléfono gsm está sonando, entonces se debe habilitar este jumper para que pueda ver quién está llamando por ejemplo).
El dispositivo ha sido desarrollado y probado en el teléfono Siemens M35. Otros teléfonos Siemens requieren pruebas y deben / deben funcionar. Lo mismo es para los teléfonos Ericsson. Los teléfonos que se pueden usar son los que tienen un «módem AT» dentro, un puerto UART y funcionan en 19200 o 9600 bps (casi todos los teléfonos).
Comandos de datos: comunicarse con la caja
Consulte los archivos del proyecto para obtener detalles sobre los comandos y el protocolo de comunicación.
Jumpers a bordo
¡En SMS Box! encontrarás dos jumpers:
- Habilitación de informe de anillo (puente en posición = apagado, puente eliminado = encendido)
- Habilitación de velocidad en baudios (puente en posición = 9600 bps, puente eliminado = 19200 bps)
Components list
Código: Seleccionar todo
C1 = 22pF
C2 = 22pF
C3 = 100µ
C4 = 10µ
C5 = 10n
D1 = 3,6V
LED1 = Yellow - Busy LED
LED2 = Green - GSM communication LED
LED3 = Green - 4-Wire communication LED
LED4 = Red - reserved / not used
LED5 = Red - 4-Wire communication Error LED
LED6 = Red - Send SMS Error LED (check pre-paid credit)
LED7 = Red - GSM communication Error LED
R1 = 220
R2 = 220
R3 = 220
R4 = 220
R5 = 220
R9 = 220
R10 = 220
R11 = 10k
R12 = 220
R13 = 1k
R14 = 4k7
R15 = 1k
R16 = 10k
R17 = 10k
R18 = 10
S1 = Jumper - prekidaè
S2 = Jumper - prekidaè
SMSBOX = PIC16F877A
T1 = 2N2222
T2 = 2N2222
VR1 = 7805
X1 = 16 MHz
Configuración de Impresion:
Códigos Fuente
controller_eng.asm
This is the controller that you will develop.
Código: Seleccionar todo
;*******************************
;
; SMS Controller example
; ==============
;
;*******************************
;
; Organizacija FLASH memorije:
; PAGE0 -
; PAGE1 -
; PAGE2 -
; PAGE3 -
;
;***** Config *****
PROCESSOR 16f877a
#include "p16f877a.inc"
__CONFIG _DEBUG_OFF & _CP_OFF & _PWRTE_ON & _BODEN_ON & _XT_OSC & _WDT_OFF & _LVP_OFF
;debug off, code protect, power up timer on, brown out detect on, ? osc, watch dog timer off
ERRORLEVEL 0, -302 ; suppress bank selection messages
ERRORLEVEL 0, -306 ; suppress page crossing messages
;***** Variables and constants *****
; bank 0 RAM
BOOLEAN equ 0x20 ; 8 boolean variables
tmp1 equ 0x21 ; temp var
tmp2 equ 0x22 ; temp var
tmp3 equ 0x23 ; temp var
tmp4 equ 0x24 ; temp var
tmp5 equ 0x25 ; temp var
tmp6 equ 0x26 ; temp var
;* for 4-wire communication
rut_DAT equ 0x27 ; trx data for 4-wire comm
rut_TMP1 equ 0x28 ; temp -||-
PAUS_TMP1 equ 0x29 ;
PAUS_TMP2 equ 0x2A ;
;--bank 0 RAM last: 0x7F
;***** Deklaracija hardvera *****
;4-wire protokol
#define portDAT TRISB, 4 ; tris for data pin
#define DAT PORTB, 4 ; pin for data
#define CLK PORTB, 5 ; pin for clock
#define IRQ PORTB, 6 ; pin for irq! they are calling me - input
#define HEY PORTB, 7 ; pin for hey! we are calling sms box! - output
;***** BANK macros *****
BANK0 MACRO
bcf STATUS, RP1 ; BANK 0
bcf STATUS, RP0
ENDM
BANK1 MACRO
bcf STATUS, RP1 ; BANK 1
bsf STATUS, RP0
ENDM
BANK2 MACRO
bsf STATUS, RP1 ; BANK 2
bcf STATUS, RP0
ENDM
BANK3 MACRO
bsf STATUS, RP1 ; BANK 3
bsf STATUS, RP0
ENDM
;***** PAGE makroi, u PAGE0 u FLASH-u *****
PAGE0 MACRO
BCF PCLATH, 3
BCF PCLATH, 4
ENDM
PAGE1 MACRO
BSF PCLATH, 3
BCF PCLATH, 4
ENDM
PAGE2 MACRO
BCF PCLATH, 3
BSF PCLATH, 4
ENDM
PAGE3 MACRO
BSF PCLATH, 3
BSF PCLATH, 4
ENDM
;***** Start uC-a *****
ORG 0x0000 ; reset vektor
bcf PCLATH, 3 ; 0x0000 --__ ( selektujmo )
bcf PCLATH, 4 ; 0x0001 -- ( PAGE0 Flash-a )
nop ; 0x0002 'nako...
GOTO Init ; 0x0003 inicijalizacija uC-a
;***** Init processor *****
Init BANK1 ; BANK 1 for TRIS registre
movlw b'00000111' ; (bilo:00000110) = all ports digital
movwf ADCON1 ;
clrf OPTION_REG ; =0, (Prescaler is assigned to the Timer0 module;
; bit3 registra i TMR0 Clock Source slect bit - internal instruction cycle - takodje .pdf dokumentacija)
movlw b'11111000' ; not used
movwf TRISA ; TRISA
movlw b'01011111' ;
movwf TRISB ; TRISB
movlw b'10111111' ;
movwf TRISC ; TRISC
movlw b'11111111' ;
movwf TRISD ; TRISD
movlw b'11111111' ;
movwf TRISE ; TRISE
BANK0 ; BANK 0
bsf HEY ; put this to high
clrf tmp1 ; =0
decf tmp1, 1 ;
nop ;
btfss STATUS, Z ; do if not zero
GOTO $-3 ; wait 255*nop*~ to settle...
clrf BOOLEAN ; =0
clrf PORTA ; debug leds off
GOTO Main ; ... goto main prog
;***** MAIN PROGRAM *****
Main bsf PORTA, 0
btfss PORTC, 0 ; button for sending a message?
goto sendsms ; send some test message
; if sms box! has something for us?
btfss IRQ ; yes he does
goto javi_se ; go see what he wants
; bsf PORTA, 1
; movlw a'H' ; hangup
; CALL rut_TX ; yo mama! ->
;
; btfsc IRQ ; wait for result!
; GOTO $-1 ;
; CALL rut_RX ; <- get result
; bcf PORTA, 1
;
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
; CALL Pauza1
GOTO Main ; ...
;see what sms box wants!
javi_se
call rut_RX ; read his command to us
; now we have that command data in rut_DAT, let's see what he sent
; he can send: A0-hello, A1-gsm comm err, A2-4wire comm err!
; he can send RING_REPORTING data also, but we didn't select that jumper so he cant send that :)
bcf PORTA, 1
bcf PORTA, 2
btfsc rut_DAT, 0 ; is it gsm comm err?
bsf PORTA, 1
btfsc rut_DAT, 1 ; is it 4wire comm err?
bsf PORTA, 2
goto Main
;send sms
sendsms
; command for sending a message
movlw a'S' ; send sms
call rut_TX
; type of message
movlw a'1' ; 1-flash sms
call rut_TX
; now number
movlw a'3' ; number format MUST be 'international' [country][operator][phone_number], example.: [387][61][123456]
call rut_TX
movlw a'8'
call rut_TX
movlw a'7'
call rut_TX
movlw a'6'
call rut_TX
movlw a'1'
call rut_TX
movlw a'1'
call rut_TX
movlw a'2'
call rut_TX
movlw a'3'
call rut_TX
movlw a'4'
call rut_TX
movlw a'5'
call rut_TX
movlw a'6'
call rut_TX
clrw ; null-byte
call rut_TX
; and now sms text
movlw a'H'
call rut_TX
movlw a'e'
call rut_TX
movlw a'j'
call rut_TX
movlw a' '
call rut_TX
movlw a':'
call rut_TX
movlw a')'
call rut_TX
clrw ; null-byte
call rut_TX ; send it now!
; now we are waiting for the reply
btfsc IRQ ; wait result!
GOTO $-1 ;
CALL rut_RX ; <- get it result
; we are not going the check the result value, this is just a test :)
GOTO Main ; ...
;***** Pauze... *****
Pauza1 movlw h'FF' ; w=XXh
movwf PAUS_TMP1 ; RS_TEMP1=w
Pauza_Y decfsz PAUS_TMP1, 1;
GOTO Pauza_X ;
RETURN ; vrati se...
Pauza_X movlw h'FF' ;
movwf PAUS_TMP2 ;
Pauza_Z decfsz PAUS_TMP2, 1;
GOTO Pauza_Z ;
GOTO Pauza_Y ;
;***** rut_TX sending a byte from W register *****
;* first (high) bit is being sent !
rut_TX movwf rut_DAT ; rut_DAT = W (we are sending rut_DAT register)
BANK1 ; bank 1
bcf portDAT ; output
BANK0 ; bank 0
bcf HEY ; tell him we want to send something
; wait for smsbox to be ready
btfsc IRQ ; wait for low
GOTO $-1 ; wait...
bsf HEY ; put this back to 1...
; send him now 8 bits
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter
rut_TX1 ; this is our loop !
btfss rut_DAT, 7 ; skip if set, do if clear [(0)0000000]
GOTO rut_TX2 ;
bsf DAT ; data = 1
GOTO rut_TX3 ;
rut_TX2 bcf DAT ; data = 0
rut_TX3
bcf CLK ; clock = 0 (tell smsbox to take this bit)
; a little pause for smsbox to fetch this data
movlw d'127' ; w=127
movwf tmp6 ; tmp6=0
decfsz tmp6, 1 ; --, skip if zero!
GOTO $-1 ; again...
bsf CLK ; clock = 1
rlf rut_DAT, 1 ; << rotate left 1x
decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_TX1 ; send next bit !
BANK1 ; bank 1
bsf portDAT ; input
BANK0 ; bank 0
RETURN ; vrati se...
;***** rut_RX receiving byte into W and rut_DAT register *****
;* first (high) bit is received !
rut_RX BANK1 ; bank 1
bsf portDAT ; input
BANK0 ; bank 0
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter
rut_RX1 ; this is our loop !
rlf rut_DAT, 1 ; << rotate left 1x
bcf CLK ; tell him to put data onto the bus (data line)
; lets wait a little for him to put the data
movlw d'30' ; w=30
movwf tmp6 ; tmp6=0
decfsz tmp6, 1 ; --, skip if zero!
GOTO $-1 ; opet...
;---
btfss DAT ; skip if set, do if clear
GOTO rut_RX2 ;
bsf rut_DAT, 0 ; [0000000(1)]
GOTO rut_RX3 ;
rut_RX2 bcf rut_DAT, 0 ; [0000000(0)]
rut_RX3
bsf CLK ; return this to HIGH so that sms box is ready for next transmission
; little pause for smsbox to shift data and get ready for next bit extraction
movlw d'30' ; w=30
movwf tmp6 ; tmp6=0
decfsz tmp6, 1 ; --, skip if zero!
GOTO $-1 ; again...
;---
decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_RX1 ; get next bit !
movfw rut_DAT ; w=result
RETURN ; go back...
;***** BYE BYE *****
END
PIC sms box chip
smsbox.asm
This is the brain of SMS Box!
Código: Seleccionar todo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; SMS Box: Interfacing cheap GSM phone to a microcontroller for SMS and CALL
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;********************************************
;
; SMS Box
; =======
; ==============================
; 1. Komande koje moze primiti:
; a) Read sms < a'R'
; b) Re-read sms < a'r'
; c) Send sms < a'S'
; d) Reply sms < a's'
; e) Dial (voice) < a'D'
; f) Hangup < a'H'
; g) Call status < a'C'
; h) Last CLIP get < a'c'
; i) Answer call < a'A'
; j) Set timestamp < a't' * NIJE IMPLEMENTIRANO!
; k) Get timestamp < a'T' * NIJE IMPLEMENTIRANO!
; l) Check credit < a'p'
; 2. Komande koje moze poslati:
; a) Ring with CLIP > a'R[TEL_NR][0]'
;
;********************************************
; Datum: 11.11.2006
; Update: 06.05.2007 (dodao: 'A', 'p' komande)
; Update: 24.06.2007 (prepravio da salje 8-bit uncompressed sms, nije vise UCS-16)
; Update: 08.04.2009 (doradio da salje 7-bit PDU sms, konacno :)
; Update: 14.04.2009 (imao sam gresku nakon prethodne prepravke, ne moze se vise kraj sms poruke oznacavati sa NULL jer u PDU modu NULL je dozvoljen karakter u poruci. Sad brojim bajte :))
; ------------------------------
;
; Organizacija FLASH memorije:
; PAGE0 - glavna "main" funkcija aplikacije
; PAGE1 - ..nastavak
; PAGE2 - funkcije razne
; PAGE3 - ..nastavak
;
;********************************************
;***** Deklaracija i konfigurisanje mikrokontrolera *****
PROCESSOR 16f877a
#include "p16f877a.inc"
__CONFIG _DEBUG_OFF & _CP_ALL & _PWRTE_ON & _BODEN_ON & _HS_OSC & _WDT_OFF & _LVP_OFF
;debug off, code protect, power up timer on, brown out detect on, ? osc, watch dog timer off
ERRORLEVEL 0, -302 ; suppress bank selection messages
ERRORLEVEL 0, -306 ; suppress page crossing messages
;***** Varijable i konstante *****
; bank 0 RAM
PAU_TEMP1 equ 0x20 ; za pauzu
PAU_TEMP2 equ 0x21 ; za pauzu
tmp1 equ 0x22 ; temp var
tmp2 equ 0x23 ; temp var
tmp3 equ 0x24 ; temp var
tmp4 equ 0x25 ; temp var
tmp5 equ 0x26 ; temp var
tmp6 equ 0x27 ; temp var
;* pdu->text
pdu_bytecnt equ 0x28 ;
pdu_left equ 0x29 ;
pdu_right equ 0x2A ;
pdu_indata equ 0x2B ;
pdu_tmp1 equ 0x2C ;
pdu_lastleft equ 0x2D ;
pdu_extra equ 0x2E ;
pdu_decoded equ 0x2F ;
;* moja sinhrona 1-wire komunikacija
rut_DAT equ 0x30 ; trx podatak za moju serisku komunikaciju
rut_TMP1 equ 0x31 ; temp -||-
;* misc
TEXT_FSR equ 0x32 ; kada se procita SMS ovdje se upise FSR lokacija odakle krece dekodirani text u RAMu
TP_DCS equ 0x33 ; za sklapanje data coding sheme za slanje sms-a
;*system auto-restart
;RESTART equ 0x34 ; za automatski restart prilikom startupa - prvobitni restart
PAU_TEMP3 equ 0x35 ; za pauzu
;* text->pdu
pdu_proizvdm equ 0x36 ;
pdu_prvi equ 0x37 ;
pdu_drugi equ 0x38 ;
pdu_coded equ 0x39 ;
pdu_dodajem equ 0x3A ;
;pdu_tmp1 ; koristim od pdu->text 0x2C
PDU_LEN equ 0x3B ; duzina PDU kodirane poruke, treba mi za slanje jer od sad brojim bajte, ne terminiram PDU sa NULL-om
;* ISR temp vars
temp_status equ 0x75 ; za interrupt rutinu
temp_w equ 0x76 ; za interrupt rutinu
temp_pclath equ 0x77 ; za interrupt rutinu
;* ConvertNr @ common ram space
dec1 equ 0x78 ; za ConvertNr
dec10 equ 0x79 ; za ConvertNr
dec100 equ 0x7A ; za ConvertNr
;common ram space:
BOOLEAN equ 0x7B ; neke boolean vrijednosti - 8 varijabli
comerr_count equ 0x7C ; koristi se i u interruptu pa treba biti u common ram space-u
ckerr1 equ 0x7D ; interrupt
ckerr2 equ 0x7E ; interrupt
ckerr3 equ 0x7F ; interrupt
;--bank 0 RAM zadnji: 0x7F
; bank 1 RAM
; start: 0xA0
; kraj: (0xEF) 0xFF
CLIP_DATA equ 0xA0 ; pocetak stringa sa CLIP brojem
;--bank 1 RAM zadnji:
; bank 2 RAM
; start: 0x110
; kraj: (0x16F) 0x17F
BEG_RAM1 equ 0x110
MSGID1 equ 0x110 ; msgid1
MSGID2 equ 0x111 ; msgid2
MSGIDEND equ 0x112 ; 0 byte
TELNRDATA equ 0x113 ; [Address-Length][Type-of-address of the sender number WARNING:moze biti 0-byte u extremnom slucaju][Sender number]
TELNRONLY equ 0x117 ; samo od telnr ([Sender number])
CREDIT_MESSAGE equ 0x117 ; ovdje se takodje cuva povratna poruka na ATD*100# i time brise trenutna sms poruka u internoj memoriji (destruktivna funkcija)
END_RAM1 equ 0x16F
;--bank 2 RAM zadnji:
; bank 3 RAM
; start: 0x190
; kraj: (0x1EF) 0x1FF
BEG_RAM2 equ 0x190
END_RAM2 equ 0x1EF
;--bank 3 RAM zadnji:
#define _SMD_ 1 ; da li je u SMD izvedbi? - 44pin-TQFP
;***** Deklaracija hardvera *****
;4-wire protokol
#ifdef _SMD_
#define portDAT TRISB, 0 ; tris za data pin
#define DAT PORTB, 0 ; pin za datu (TQFP 8)
#define CLK PORTB, 1 ; pin za clock (9)
#define HEY PORTB, 2 ; pin za hey! mi prozivamo - uvjek output (10)
#define IRQ PORTB, 3 ; pin za irq! mene proziva - uvjek input (11)
#else
#define portDAT TRISB, 0 ; tris za data pin
#define DAT PORTB, 0 ; pin za datu
#define CLK PORTB, 1 ; pin za clock
#define IRQ PORTB, 2 ; pin za irq! mene proziva - uvjek input
#define HEY PORTB, 3 ; pin za hey! mi prozivamo - uvjek output
#endif
;dip switch
#define RINGSEL PORTB, 6 ; ring reporting selection (1=on,0=off)
#define BAUDSEL PORTB, 7 ; baud rate select (0=9600,1=19200 bps)
;leds
#ifdef _SMD_
#define LEDBSY PORTC, 0 ; master busy led (32)
#define LEDGSM PORTC, 1 ; talking to phone LED or waiting data (35)
#define LED4WR PORTC, 2 ; talking over 4-wire to master or waiting data (36)
#define LED4RR PORTC, 3 ; 4-wire comm err (37)
#define LEDSER PORTD, 0 ; send sms error (provjeriti kredit na mobitelu :)) (38)
#define LEDERR PORTD, 2 ; gsm communication failure led! (treci neuspjeli init mobitela) (39)
#else
#define LEDBSY PORTC, 1 ; master busy led
#define LEDGSM PORTC, 2 ; talking to phone LED or waiting data
#define LED4WR PORTC, 3 ; talking over 4-wire to master or waiting data
#define LED___ PORTD, 0 ; rezervisano za neku novu led
#define LED4RR PORTD, 1 ; 4-wire comm err
#define LEDSER PORTD, 2 ; send sms error (provjeriti kredit na mobitelu :))
#define LEDERR PORTD, 3 ; gsm communication failure led! (treci neuspjeli init mobitela)
#endif
;***** Izvedene varijable i konstante *****
#define bINTER BOOLEAN, 0 ; interrupt bit
#define bNEWSMS BOOLEAN, 1 ; nova poruka dekodirana!
#define bCLIPNR BOOLEAN, 2 ; ima clip u ramu?
#define bINT_1 BOOLEAN, 3 ; kad se desi interrupt, idemo na reinit mobitela!
#define bINT_2 BOOLEAN, 4 ; --||--, idemo na mainloop samo al javi i 4-wire error
#define bGSMIN BOOLEAN, 5 ; gsm telefon inicijalizovan? treba nam ukoliko se desi 4-wire err da znamo ocemol na Main ili na MainLoop
#define bA1DO BOOLEAN, 6 ; da li treba dojaviti A1 gresku na 4-wire bus?
;***** Makroi - samo oni koji ne uzimaju previse memorije dzabe *****
;***** BANK makroi *****
BANK0 MACRO
bcf STATUS, RP1 ; BANK 0
bcf STATUS, RP0
ENDM
BANK1 MACRO
bcf STATUS, RP1 ; BANK 1
bsf STATUS, RP0
ENDM
BANK2 MACRO
bsf STATUS, RP1 ; BANK 2
bcf STATUS, RP0
ENDM
BANK3 MACRO
bsf STATUS, RP1 ; BANK 3
bsf STATUS, RP0
ENDM
;***** Za pristupanje RAM-u u banci 2i3 preko INDF(FSR)
BIGFSR MACRO
bsf STATUS, IRP ; za bank2,3
ENDM
LITFSR MACRO
bcf STATUS, IRP ; za bank0,1
ENDM
;***** PAGE makroi, u PAGE0 u FLASH-u *****
PAGE0 MACRO
BCF PCLATH, 3
BCF PCLATH, 4
ENDM
PAGE1 MACRO
BSF PCLATH, 3
BCF PCLATH, 4
ENDM
PAGE2 MACRO
BCF PCLATH, 3
BSF PCLATH, 4
ENDM
PAGE3 MACRO
BSF PCLATH, 3
BSF PCLATH, 4
ENDM
;***** Interrupt off macro ******
INTOFF MACRO
bcf INTCON, GIE ; main switch off :)
ENDM
;***** Start uC-a *****
ORG 0x0000 ; reset vektor
bcf PCLATH, 3 ; 0x0000 --__ ( selektujmo )
bcf PCLATH, 4 ; 0x0001 -- ( PAGE0 Flash-a )
nop ; 0x0002 'nako...
GOTO Init ; 0x0003 inicijalizacija uC-a
;***** Interapt rutina *****
ISR ORG 0x0004 ; int vektor
bcf INTCON, GIE ; onemoguci sve interupte za sad
bcf INTCON, TMR0IF; skini flag od ovog interrupta
; sacuvaj registre
movwf temp_w ; sacuvaj W reg
movfw STATUS ; W=STATUS reg
movwf temp_status ; sacuvaj ga
movfw PCLATH ; w=PCLATH
movwf temp_pclath ; sacuvaj i ovo govno
PAGE0 ; prebaci nas vodjek!
BANK0 ; prebacimo se i u defaultnu banku0, vratice se prethodno stanje banki (STATUS) dole na kraju
; INTERRUPT WORK:
incf ckerr1, 1 ; ++
btfsc STATUS, Z ; ako jeste zero
incf ckerr2, 1 ; ++
btfsc STATUS, Z ; ako jeste zero
incf ckerr3, 1 ; ++
btfsc STATUS, Z ; ako jeste zero
bsf bINTER ; interrupt!!!
btfss bINTER
GOTO ISR_Exit ; vrati se sa omogucenim interrupts u odgovarajucu page i vrati sve registre
; prekid!
btfsc bINT_1 ; jel ovo treba da se desi?
GOTO GoISR_GSM ; idi u main gdje imamo init gsm-a i odatle nastavi iz pocetka
; prekid!
btfsc bINT_2 ; jel ovo treba da se desi?
GOTO GoISR_4WIRE ; javi 4-wire error i idi u mainloop fino jer se to treba da desi
ISR_Exit
;clrf TMR0 ; :) ????????????????????????????????????????????????????
; vrati varijable i vrati se sa retfie
movfw temp_pclath ; W=pclath backup
movwf PCLATH ; PCLATH=W
movfw temp_status ; w=temp status
movwf STATUS ; STATUS=W
movfw temp_w ; i konacno W
RETFIE ; vrati se fino
;***** Init procesora *****
Init clrf INTCON ; gasi interrupte na pocetku za svaki slucaj
movlw b'00000000' ; ADCON0 (bank 0)
movwf ADCON0 ; (A/D converter module is shut-off and consumes no operating current)
BANK1 ; BANK 1 za TRIS registre
clrf OPTION_REG ; =0, (iz dokumentacije: Prescaler is assigned to the Timer0 module;
; bit3 registra i TMR0 Clock Source slect bit - internal instruction cycle - takodje .pdf dokumentacija)
movlw b'00000111' ; (bilo:00000110) = all ports digital
movwf ADCON1 ; All digital
movlw b'11111111' ; not used
movwf TRISA ; TRISA
#ifdef _SMD_
movlw b'11111011' ; sync 4-wire comm port & misc buttons
movwf TRISB ; TRISB
movlw b'10110000' ; uart port & leds
movwf TRISC ; TRISC
movlw b'11111010' ; leds only
movwf TRISD ; TRISD
#else
movlw b'11110111' ; sync 4-wire comm port & misc buttons
movwf TRISB ; TRISB
movlw b'10110001' ; uart port & leds
movwf TRISC ; TRISC
movlw b'11110000' ; leds only
movwf TRISD ; TRISD
#endif
movlw b'00000111' ; not used
movwf TRISE ; TRISE
BANK0 ; vrati
; Startup delay
CALL Delay_01s ; cekaj 0.1s
; baud rate select @ 10MHz, 9600(64) | 19200(31)
; baud rate select @ 16MHz, 9600(103) | 19200(51)
movlw d'103' ; 9600bps, 129@20mhz
btfsc BAUDSEL ; do if set
movlw d'51' ; 19200bps, 64@20mhz
BANK1
movwf SPBRG ; w=SPBRG
; txsta je takodje u bank1
movlw b'00100100' ; BRGH=1
movwf TXSTA ; set it man
BANK0
; rcsta je u bank0
movlw b'10010000' ; continuos receive enabled!
movwf RCSTA ;
clrf PORTD ; all leds off here :)
clrf PORTC ; all leds off and here :)
bsf HEY ; digni ovo na vcc (mada nije potrebno jer imamo pullups na PORTB, ali eto)
clrf BOOLEAN ; =0
clrf comerr_count; =0
; ; restart system once after powerup, if RESTART!=AAh
; movlw h'AA' ; w=aah
; subwf RESTART, 0 ; oduzmi
; btfss STATUS, Z ; do if not the same
; GOTO RestartChip ; idi resetuj se softverski
GOTO Main ; ... goto main prog
;***** GLAVNI PROGRAM *****
Main PAGE2
; da se osiguramo da rs232 port radi ok
bcf RCSTA, SPEN ; gasi port
bcf RCSTA, CREN ; gasi cont. receive
nop
bsf RCSTA, CREN ; pali nazad cont. receive
bsf RCSTA, SPEN ; pali port nazad
CALL RS_FLUSH ; flushaj buffer
incf comerr_count, 1; ++
CALL GSM_Init ; init telefona odma
clrf comerr_count; =0 sve ok! :)
bcf LEDERR ; gasi err led takodje
; da javimo klijentu da smo zivi (mobitel communikacija je ok)
; ako recimo klijent salje poruku i ovaj dio se zaglavi, klijent ce cekati sto godina na answer od nas
; ovo ce mu reci da je bila greska pri slanju ili bilo cemu (odnosno da smo krenuli iz pocetka)! zato ovo i treba
movlw h'A0' ; w=A0h (startup hello)
CALL rut_TX ; salji w
PAGE0
MainLoop; dohvati komandu od klijenta
MainLoop_1
btfsc PIR1, RCIF ; do if got the byte from da phone
GOTO JaviRing ; javi ring&clip korisniku na 4-wire bus
btfss IRQ ; do if clear, ako je oborena za neki podatak
GOTO MainLoop_2 ; idi odradi dobili smo neki data
GOTO MainLoop_1 ; cekaj i dalje...
MainLoop_2
PAGE2
CALL rut_RX ; primi datu u W a ujedno u rut_DAT
; sve se odvija u PAGE2:
; Read sms
movlw a'R' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO CkSMS ; idi sa GOTO!
; Re-read sms
movlw a'r' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO DumpSMS ; idi sa GOTO!
; Send sms
movlw a'S' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO SendSMS ; idi sa GOTO!
; Reply sms
movlw a's' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO ReplySMS ; idi sa GOTO!
; ostalo u PAGE0:
PAGE0
; Re-read CLIP if any
movlw a'c' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO DumpRing ; idi sa GOTO!
; Dial
movlw a'D' ; w=D
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO DialVoice ; idi sa GOTO!
; Query call status
movlw a'C' ; w=
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO QueryCall ; idi sa GOTO!
; Hangup
movlw a'H' ; w=H
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO SpustiSlus ; idi sa GOTO!
; Answer call
movlw a'A' ; w=A
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO DigniSlus ; idi sa GOTO!
; Check credit (passthru result from ATD[PARAM])
movlw a'p' ; w=p
subwf rut_DAT, 0 ; jel doslo
btfsc STATUS, Z ; do if the same!
GOTO CheckCredit ; idi sa GOTO!
GOTO MainLoop ;
;* subrutina, javi 4-wire err i ode u mainloop *
GoISR_4WIRE
BANK1
bsf portDAT ; vrati ovo na input
BANK0
bsf HEY ; vrati ovo na high
bsf LED4RR ; upali ovaj err, ugasice se pri zavrsetku rut_TX-a
bcf LEDBSY ; busy led off (ako nas je interrupt turio vamo) - cekamo
bcf LEDGSM ; gasi ovo smeta ako smo dosli odozdo iz GoISR_GSM-a zbog neuspjelog slanja A1h
; ako je 4-wire pukao na GoISR_GSM rutini, da to zavrsimo prvo...
btfsc bA1DO ; do if set
CALL GoISR_GSM_r ; idi to i vrati se sa return ovdje!!!
PAGE2
movlw h'A2' ; w=A2h
CALL rut_TX ; javi err (ili barem pokusaj).. ovdje cemo zaglaviti vjecno ako je otspojen MASTER! :)
PAGE0
btfss bGSMIN ; do if phone not initialized, ako nije inicijalizovan telefon, pa to je pokusano dojaviti masteru a nije ni to uspjelo, idi kreni pokusaj opet
GOTO Main ; idi i inicijalizuj ga..u ovoj liniji smo ako ne radi 4-wire comm pri pokusaju dojave A1h iz GoISR_GSM dole
GOTO MainLoop ; haj u mainloop cekaj novu naredbu, tel. je inicijalizovan fino
;* subrutina, dolazimo iz isr-a jer se mobitel ne javlja *
GoISR_GSM
bsf LEDERR; ozdol doso gor
; treba provjeriti if(comerr_count==4) pali comm error led i javi na 4-wire bus da master resetuje mobitel
movlw d'4'
subwf comerr_count, 0; w=comerr_count-w(4)
btfss STATUS, Z ; do if not the same
GOTO Main ; preskoci dojavu errora jer jos nije vrijeme za to
;decf comerr_count, 1; smanji jednom, jer naredni poziv na gsm_init ce ga prebaciti na 4, a to nam ne godi :) ako ga prebaci na 0-ok, ako de desi opet err bilo bi 5. eto zato
clrf comerr_count; =0 counter iz pocetka
; bsf LEDERR ; pali err led vala! ugasice se gore eto, kada se tel. fino inicijalizuje
bsf bA1DO ; ovo je pending za uraditi, ako pukne 4-wire da znamo da ovo prvo moramo poslati
PAGE2
movlw h'A1' ; w=A1h
CALL rut_TX ; javi err ..
PAGE0
bcf bA1DO ; dojavili smo je
GOTO Main ; haj gor nazad...
;* subrutina, pozvani smo sa call iz GoISR_4WIRE
GoISR_GSM_r
PAGE2
movlw h'A1' ; w=A1h
CALL rut_TX ; javi err ..
PAGE0
bcf bA1DO ; dojavili smo je
RETURN ; haj gor nazad...
;****** Resetovanje chipa softverski ******
;RestartChip
; movlw h'AA' ; w=AAh
; movwf RESTART ; sacuvaj
; ; napravi neku pauzu od 1s mozda
; PAGE2
; CALL Delay_1s
; CALL Delay_1s
; PAGE0
; GOTO Init ; idi se ponovo inicijalizuj!
;***** Check credit - passthru od ATD[param] ******
CheckCredit
bsf LEDBSY ; busy led on
PAGE2
CALL SND_AT ; AT
movlw a'D' ; W=D
CALL TX_UART ; salji
PAGE0
CheckCred_1
PAGE2
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
PAGE0
clrw ; w=0
subwf rut_DAT, 0 ; w=rut_DAT-w
btfsc STATUS, Z ; do if the same
GOTO CheckCred_2 ; nemoj vise, klijent je poslao nullbyte
PAGE2
movfw rut_DAT ; w=cifra za dial
CALL TX_UART ; salji broj na mobitel
PAGE0
GOTO CheckCred_1 ; jos...
CheckCred_2
PAGE2
CALL SND_CRL ; CR+LF .. i on pocinje da zove tamo centralu za kredit!
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
; sad cekamo reply
CALL PustiCRLFiUzmiNext ; sve je receno :)
PAGE0
xorlw a'4' ; uporedjujemo W koji smo dobili od mobitela sa a'4'
btfsc STATUS, Z ; uradi ako su isti, tojest ako jeste doslo a'4' a to znaci gresku
GOTO CheckCred_5 ; bjezi odavdje, ne diraj nista
; prvo slovo validnog responsa imamo u W trebamo ga sacuvati mamu mu
xorlw a'4' ; vrati originalnu vrijednost bajtu
movwf tmp6 ; sacuvaj to cemo ugurati u INDF(FSR) kad ga dole podesimo
; ovdje smo i znaci da je sve OK i trebamo uhvatiti sad text u FSR(CREDIT_MESSAGE)
bcf bNEWSMS ; reci da nema prosle poruke jer cemo je sad prepisati
bcf bCLIPNR ; reci da nemamo vise ni CLIP-a jer smo i njega prepisali
BIGFSR ; koristimo big bank :)
movlw LOW(CREDIT_MESSAGE)
movwf FSR ; FSR=W
; gore smo vec uzeli prvi od mobitela pa ga sacuvajmo na prvo mjesto :)
movfw tmp6 ; w=tmp6
movwf INDF ; INDF=w
PAGE2
CALL FSR_Next ; FSR++ :)
PAGE0
CheckCred_3
bsf LEDGSM ; pali gsm comm led, ugasice ga RX_UART
btfss PIR1, RCIF ; cekaj bajt...
GOTO $-1 ; cekaj vala...
PAGE2
CALL RX_UART ; ufati ga der ga
PAGE0
; jel CR - kraj?
xorlw d'13' ; CR?
btfsc STATUS, Z ; do if set, ako jesu odradi
GOTO CheckCred_4 ; kraj hvatanja!
PAGE2
xorlw d'13' ; vrati originalnu vrijednost u W
movwf INDF ; INDF(FSR)=W
CALL FSR_Next ; FSR++
PAGE0
GOTO CheckCred_3 ; jos
CheckCred_4
clrf INDF ; nullbyte - oznaci kraj stringa
PAGE2
CALL PustiDATA ; dolazi jos definitivno <LF><CR>0<LF>
INTOFF ; gasi interrupte
; ostacemo u page2, ne smeta par instrukcija, a i mora zbog rut_TX 00h dole
; sad treba uraditi dump na 4-wire sa FSR-a @ CREDIT_MESSAGE adrese
movlw h'FF' ; da mu posaljemo FFh da zna da podatak krece!
CALL rut_TX ; salji
movlw LOW(CREDIT_MESSAGE); w=adr
movwf FSR ; FSR=w
CheckCred_4a
movfw INDF ; w=INDF
PAGE2
CALL rut_TX ; salju klijentu bajt
PAGE0
clrw ; kraj? poslali smo mu nullbyte?
subwf INDF, 0 ;
btfsc STATUS, Z ;
GOTO CheckCred_4b; jesmo, bugija
PAGE2
CALL FSR_Next ; FSR++
PAGE0
GOTO CheckCred_4a ; jos...
CheckCred_4b
LITFSR
bcf LEDBSY ; gasi busy led
GOTO MainLoop ; vrati se sike...
CheckCred_5
PAGE2
CALL PustiDATA ; dolazi jos definitivno na kraju barem jedan CR
INTOFF ; gasi interupte
movlw h'00' ; da mu posaljemo 00h
CALL rut_TX ; salji mu nullbyte da zna da je neki err se desio
PAGE0
bcf LEDBSY ; gasi busy led
GOTO MainLoop ; vrati se...
;***** Query call status AT+CPAS ******
;Mogucnosti: AT+CPAS ili AT+CLCC
;Aktivna funkcija: AT+CLCC, dole zakomentirana je AT+CPAS
QueryCall
bsf LEDBSY ; busy led on
PAGE2
CALL SND_AT ; AT
CALL SND_PLS ; +
movlw a'C' ; W=C
CALL TX_UART ; salji
movlw a'L' ; W=L
CALL TX_UART ; salji
movlw a'C' ; W=C
CALL TX_UART ; salji
movlw a'C' ; W=C
CALL TX_UART ; salji
CALL SND_CRL ; CR LF
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
CALL PustiCRLFiUzmiNext; pustaj do neceg korisnog sto moze biti a'0' ili a'+'
movwf tmp1 ; sacuvaj u tmp1
PAGE0
movlw a'+' ; ako smo dobili + sve je OK
subwf tmp1, 0 ; w=tmp1-a'+'
btfsc STATUS, Z ; do if set, do if the same
GOTO QueryCall_0 ; idi nastavi hvatati, ima poziv!
; nema poziva, vrati FULL byte korisniku
PAGE2
CALL PustiDATA ; dolazi jos definitivno na kraju barem jedan CR
INTOFF ; gasi interupte
movlw h'ff' ; w=ffh
CALL rut_TX ; send it man
PAGE0
GOTO QueryCall_End; izadji fino
QueryCall_0
PAGE2
movlw a',' ; propustamo do zarez-, znaka
CALL PropustajDo ; propustaj do njega...
movlw a',' ; propustamo do zarez-, znaka
CALL PropustajDo ; propustaj do njega...
PAGE0
btfss PIR1, RCIF ; do if clear
GOTO $-1 ; cekaj ono sto nam treba!
PAGE2
CALL RX_UART ; ufati ga u W
movwf tmp2 ; sacuvaj da ga dole vratimo korisniku
CALL PustiDATA ; dolazi jos na kraju puno toga...
INTOFF ; gasi interupte
; posalji result na 4-wire bus.
movfw tmp2 ; w=tmp2
CALL rut_TX ; salji ga tamo!
PAGE0
QueryCall_End
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrati se...
;***** Ostvarivanje VOICE poziva ******
DialVoice
bsf LEDBSY ; busy led on
PAGE2
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
CALL Hangup ; spusti ako slucajno zvoni... PustiDATA je unutra
CALL PustiDATA ; cekaj da prodju podaci
INTOFF
CALL SND_AT ; AT
movlw a'D' ; D
CALL TX_UART ; salji D
PAGE0
DialVoice_1
PAGE2
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
PAGE0
clrw ; w=0
subwf rut_DAT, 0 ; w=rut_DAT-w
btfsc STATUS, Z ; do if the same
GOTO DialVoice_2 ; nemoj vise, klijent je poslao nullbyte
PAGE2
movfw rut_DAT ; w=cifra za dial
CALL TX_UART ; salji broj na mobitel
PAGE0
GOTO DialVoice_1 ; jos...
DialVoice_2
PAGE2
movlw a';' ; w=a';'
CALL TX_UART ; salji i ;
CALL SND_CRL ; CR+LF .. i on pocinje da zove!
; ipak cemo sacekati acknowlegment neki, ako nije 0 poslacemo FULL a ako je 0 saljemo NULL byte :)
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
CALL PustiCRLFiUzmiNext ; sve je receno :)
movwf tmp2 ; sacuvajmo result u ovaj var
CALL PustiDATA ; dolazi jos CR definitivno poslije podatka
INTOFF ; gasi interrupts jer smo zavrsili razgovor sa mobitelom
PAGE0
movlw a'0' ; w=0 ascii
subwf tmp2, 0 ;
btfsc STATUS, Z ; do if set, uradi ako su isti!
GOTO DialVoice_3 ; sve OK salji nullbyte
PAGE2
movlw h'ff' ; w=full byte
CALL rut_TX ; posalji error korisniku jer poziv nije kreiran
PAGE0
GOTO DialVoice_5 ; preskoci slanje nullbyte-a
DialVoice_3
PAGE2
clrw
CALl rut_TX ; salji korisniku NULL-byte
PAGE0
DialVoice_5
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrati se...
;***** Spustanje slusalice na zahtjev 4-wire bus-a ******
SpustiSlus
bsf LEDBSY ; busy led on
PAGE2
bsf bINT_1 ; gsm interrupts
bcf bINT_2 ; =0
CALL IntON ; ints on
CALL Hangup ; spusti ako slucajno zvoni... PustiDATA je unutra
CALL PustiDATA ; cekaj da prodju podaci
INTOFF ; ints off
clrw
CALL rut_TX ; javi da si odradio...
PAGE0
bcf LEDBSY ; busy led on
GOTO MainLoop ; vrati se gore...
;***** Dizanje slusalice na zahtjev 4-wire bus-a ******
DigniSlus
bsf LEDBSY ; busy led on
PAGE2
CALL SND_AT ; AT
movlw a'A' ; salji A
CALL TX_UART ; salji 'A'
CALL SND_CRL ; CR LF
bsf bINT_1 ; gsm interrupts
bcf bINT_2 ; =0
CALL IntON ; ints on
CALL PustiCRLFiUzmiNext ; sve je receno :)
movwf tmp6 ; rezultat imamo
CALL PustiDATA ; pusti preostali CR
INTOFF ; ints off
movfw tmp6 ; w=tmp6
CALL rut_TX ; javi da si odradio...
PAGE0
bcf LEDBSY ; busy led on
GOTO MainLoop ; vrati se gore...
;***** Dojava RING & CLIP korisniku preko 4-wire bus-a ******
JaviRing
bsf LEDBSY ; busy led on
; kupimo podatke, cekamo RING string koji je ustvari a'2' zbog init-a ATV0 :)
;bcf bCLIPNR ; javi da ga nemamo :)
;nema potrebe a nije ni dobro! nakon dial-a kada se uspostavi ili prekine veza, ovdje se uleti i ovo se obrise a ne treba! pri startupu ovo je =0 tako da je sve ok
PAGE2
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
CALL PustiCRLFiUzmiNext; sacekaj taj bajt koji mora biti a'2'
PAGE0
; ako je cojek preklopio RINGSEL dugme na 0 onda necemo ni javljati ring
btfss RINGSEL ; do if clear
GOTO JaviRing_0a ; samo propusti podatke i vrati se u main...
xorlw a'2' ; uporedjujemo W koji smo dobili od mobitela sa a'2'
btfsc STATUS, Z ; uradi ako JE doslo a'2' ;komentar je bio NIJE
GOTO JaviRing_0 ; ok je, nastavi, cekaj space a' ' dole
; error neki je bio ovdje! samo se vratimo bez ikakve dojave na 4-wire bus
JaviRing_0a
PAGE2
CALL PustiDATA ; mora zbog 13 sto dodje poslije :) i/ili zbog propustanja cijelog ring podatka zato sto je korisnik izabrao RINGSEL=0 na dugmetu
PAGE0
INTOFF ; gasi interupte
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrni se...
JaviRing_0
LITFSR ; koristimo fsr iz banke1
movlw LOW(CLIP_DATA); pocetak clip-a
movwf FSR ; ubaci ga u pokazivac
PAGE2
movlw a' ' ; propustamo do ' ' znaka
CALL PropustajDo ; propustaj do njega, naredni iz RCREG-a je onaj koji se primi poslije njega!
PAGE0
; sad kupi podatke do a',' a ignorisi a'"' navodnike.
JaviRing_1
bsf LEDGSM ; pali gsm comm led, ugasice ga RX_UART
btfss PIR1, RCIF ; cekaj bajt...
GOTO $-1 ; cekaj vala...
PAGE2
CALL RX_UART ; ufati ga der ga
PAGE0
; jesul navodnici?
xorlw a'"' ; cool
btfsc STATUS, Z ; do if set, uradi ako jesu
GOTO JaviRing_1 ; cekaj naredni, ovo su bili navodnici...
xorlw a'"' ; vrati originalnu vrijednost u W
; jel zarez - kraj?
xorlw a',' ; zarez?
btfsc STATUS, Z ; do if set, ako jesu odradi
GOTO JaviRing_2 ; kraj hvatanja!
xorlw a',' ; vrati originalnu vrijednost u W
; snimi podatak u INDF(FSR)
movwf INDF ; INDF(FSR)=W
incf FSR, 1 ; fsr++
GOTO JaviRing_1 ; jos...
JaviRing_2 ; kraj hvatanja, pozovi dump ram-a do nullbyte-a kojeg cemo evo sad zapisati
clrf INDF ; nullbyte
PAGE2
CALL PustiDATA ; garant dolazi jos toga...
PAGE0
INTOFF ; ne zaboraviti ovo!
bcf LEDBSY ; busy led off
bsf bCLIPNR ; javi da imamo clip u ramu od sad pa nadalje...
GOTO DumpRing ; dumpaj mu ring clip kako smo obecali
;***** DUMP RING CLIP-a iz RAM-a ******
; Return format: [CLIP_DATA][0]
DumpRing
bsf LEDBSY ; busy led on
btfsc bCLIPNR ; ako uopste imamo CLIP u RAM-u
GOTO DumpRing_0 ; OK nastavi
PAGE2
movlw h'00' ; javi err korisniku kao da nema nista
CALL rut_TX ; salju nullbyte klientu
PAGE0
bcf LEDBSY ; busy led off
GOTO MainLoop ; nema nista, haj bugija!
DumpRing_0
PAGE2
movlw a'R' ; R
CALL rut_TX ; salju R klijentu kao prefix
PAGE0
LITFSR ; IRP=0
movlw LOW(CLIP_DATA); w=adr
movwf FSR ; FSR=w
DumpRing_1
movfw INDF ; w=INDF
PAGE2
CALL rut_TX ; salju klijentu bajt
PAGE0
clrw ; kraj? poslali smo mu nullbyte?
subwf INDF, 0 ;
btfsc STATUS, Z ;
GOTO DumpRing_2 ; jesmo, bugija
incf FSR, 1 ; FSR++
GOTO DumpRing_1 ; jos...
DumpRing_2
bcf LEDBSY ; busy led off
GOTO MainLoop ; loopiraj...
; Delay = 0.1 seconds
; Clock frequency = 16 MHz
; Actual delay = 0.1 seconds = 400000 cycles
; Error = 0 %
Delay_01s ;399992 cycles
movlw h'35'
movwf PAU_TEMP1
movlw h'E0'
movwf PAU_TEMP2
movlw h'01'
movwf PAU_TEMP3
Delay_01s_0
decfsz PAU_TEMP1, 1
goto $+2
decfsz PAU_TEMP2, 1
goto $+2
decfsz PAU_TEMP3, 1
goto Delay_01s_0 ;4 cycles
goto $+1
goto $+1
RETURN ;4 cycles (including call)
;#################################################
;***** Flash PAGE1
;#################################################
ORG 0x0800 ; page 1 program memory
nop
;#################################################
;***** Flash PAGE2
;#################################################
ORG 0x1000 ; page 2 program memory
;***** PDU->TEXT SUBRUTINE *****
pdu_text; vec u pdu_indata imamo podatak za dekodiranje!
movfw pdu_left ;
movwf pdu_lastleft; sacuvaj prethodni ako ga je bilo i ako nije, bitan je ako je bilo
; lijeva sekcija
call pdu_table1 ; daj je u W
andwf pdu_indata,0; imamo lijevi dio u W
movwf pdu_left ; ovdje je lijevi dio sad
; desna sekcija
call pdu_table1 ; daj je u W opet
movwf pdu_tmp1 ; ovdje je maska treba je invertovat
comf pdu_tmp1, 0 ; w=invertovana maska
andwf pdu_indata,0; imamo desni dio u W
movwf pdu_right ; ovdje imamo desni dio sad
; ako se radi o prvom bajtu u nizu, onda ga komotno samo vrati (desnu sekciju)
clrw
subwf pdu_bytecnt,0 ; w=pdu_bytecnt-0
btfsc STATUS, Z ; do if is zero
goto pdu_text_1st; vrati mu prvi
; posto se ne radi o prvom bajtu u nizu idemo jebavat
; treba poslati DESNI LAST_LIJEVI ali sklopiti u 8 bita
; znaci treba uraditi desni ILI last_lijevi u jedan bajtic i to je to
; treba shiftat pdu_right ulijevo pdu_bytecnt-1 [Censurado]
movfw pdu_bytecnt
movwf pdu_tmp1
pdu_text1
bcf STATUS, C ; da nam dodje nula desno
rlf pdu_right, 1; ulijevo 1nom
decfsz pdu_tmp1,1 ; --, skip if zero
goto pdu_text1 ; opet ga shiftaj
; treba sad shiftat pdu_lastleft u desno 7-pdu_bytecnt [Censurado]
movlw d'9' ; w=7
subwf pdu_bytecnt,0; w=pdu_bytecnt-w
movwf pdu_tmp1
comf pdu_tmp1,1 ; ovoliko [Censurado] rotiramo udesno
pdu_text2
rrf pdu_lastleft, 1 ; desno 1nom
decfsz pdu_tmp1,1 ; --, skip if zero
goto pdu_text2
incf pdu_bytecnt, 1; byte counter
movfw pdu_right ; w=pdu desni
iorwf pdu_lastleft,0 ; w=pdu_desni ILI pdu_lastleft
; u W je dekodirani bajt!
movwf INDF ; INDF(FSR)=dekodirani bajt
CALL FSR_Next ; fsr++, & provjera
incf pdu_decoded, 1; moramo ovaj counter da vodimo
; ako imamo i extra bajt da i njega posaljemo!
movlw d'7' ;7
subwf pdu_bytecnt,0; w=bytecnt-w
btfsc STATUS, Z ; do if is zero
goto pdu_text_extra; vrati mu extra bajt na kraju
return ; vrati se...
pdu_text_1st
incf pdu_bytecnt, 1; byte counter++
movfw pdu_right ; w=rezultat
;SNIMI GA U RAM!
movwf INDF ; INDF(FSR)=dekodirani bajt
CALL FSR_Next ; fsr++, & provjera
incf pdu_decoded, 1; moramo ovaj counter da vodimo
return ; vrati se sa rez u W...
pdu_text_extra
; sad imamo EXTRA otpakovani byte!!! ovo je ujedno zadnji byte i treba resetovati counter
clrf pdu_bytecnt ;= 0
bcf STATUS, C ; =0 mi mora biti high-bit zbog rotacije
rrf pdu_left, 0 ; ;pdu_extra,0 treba sad i ovo poslati konacno!
; u W je dekodirani EXTRA BYTE
movwf INDF ; INDF(FSR)=dekodirani bajt
CALL FSR_Next ; fsr++, & provjera
incf pdu_decoded, 1; moramo ovaj counter da vodimo
return ; vrati se gore sa return ustvari
pdu_table1 ; ova tabela !!!MORA!!! biti unutar istih 255 bajta memoriskog prostora kao i onaj dio koji je zove sa CALL !!!!!!!!! tojest ove dole funkcije
movfw pdu_bytecnt ; da uzmemo masku za trentni byte 0..7
addwf PCL, 1 ; skoci na W-lokaciju+trenutni PC
retlw b'10000000' ;
retlw b'11000000' ;
retlw b'11100000' ;
retlw b'11110000' ;
retlw b'11111000' ;
retlw b'11111100' ;
retlw b'11111110' ;
retlw b'11111111' ; ;ako bude problema, high-bit postaviti na 0
;***** Rutina koja prima text SMS-a 8-bitni ASCII od klijenta u nas RAM i kodira je u PDU format ******
; pisemo u RAM krecuci sa lokacijom TEXT_FSR+2 i na kraju NE upisemo null-byte, nego brojimo duzinu PDU-a-2 (ne brojim UDL)
; prvo cemo rezervisati 2bytes na pocetku pa pisati poslije toga. tu ide length user date koji cemo dole upisati
pdu_table2 ; ova tabela !!!MORA!!! biti unutar istih 255 bajta memoriskog prostora kao i onaj dio koji je zove sa CALL !!!!!!!!! tojest ove dole funkcije
movfw pdu_proizvdm; da uzmemo masku za trentni byte 0..7
addwf PCL, 1 ; skoci na W-lokaciju+trenutni PC
retlw b'00000001' ;
retlw b'00000011' ;
retlw b'00000111' ;
retlw b'00001111' ;
retlw b'00011111' ;
retlw b'00111111' ;
retlw b'01111111' ;
retlw b'11111111' ;
PrimiText
BIGFSR ; IRP=1
movfw TEXT_FSR ; w=addr
movwf FSR ; podesi fsr
; rezervisi 2bytes za length koji cemo dole upisati
CALL FSR_Next ; rezervisi jedan
CALL FSR_Next ; rezervisi jos jedan
clrf PDU_LEN ; da izbrojim koliko sam proizveo bajta
clrf pdu_prvi ; =0
clrf pdu_drugi ; =0
clrf pdu_proizvdm; =0
clrf tmp3 ; length je za sad =0 :)
PrimiText_1
tstf pdu_proizvdm
btfss STATUS, Z ; if not zero, skip
GOTO PrimiText_1a; preskoci kupljenje "prvog"
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
movwf pdu_prvi ; prvi uzet
tstf pdu_prvi ; PROVJERI DA LI JE ==NULL da prekinemo
btfsc STATUS, Z ; uradi ako je NULL
GOTO PrimiText_2 ; ovo zavrsava posao, nema vise
; else, doslo neko slovo za sms:
incf tmp3, 1 ; tmp3++ = userdata length++ (the length here is the number of septets - ascii chars length)
PrimiText_1a
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
movwf pdu_drugi ; drugi uzet
movfw pdu_prvi ; w=prvi
movwf pdu_coded ; ubaci zadnji ovdje, sad treba zavrsiti posao sa ovim bajtom, ako je pdu_drugi==NULL
tstf pdu_drugi ; PROVJERI DA LI JE ==NULL da prekinemo
btfsc STATUS, Z ; uradi ako je NULL
GOTO PrimiText_1f; ovo ce tog zadnjeg snimiti, on se nema sa cime kodirati :)
incf tmp3, 1 ; tmp3++ = userdata length++ (the length here is the number of septets - ascii chars length)
PrimiText_1b
; sad imamo prvi i drugi uspjesno primljene
CALL pdu_table2 ; w = maska za zadrzavanje bita iz pdu_drugi
andwf pdu_drugi, 0; w = ono sto treba prebaciti u pdu_prvi na pocetak
movwf pdu_dodajem ; pdu_dodajem = w
movlw d'7'
movwf pdu_tmp1
movfw pdu_proizvdm; 0..6
subwf pdu_tmp1, 1 ; pdu_tmp1=7-w(pdu_proizvodim)
PrimiText_1b_rl ; rotiranje (7-pdu_proizvdm) [Censurado]
bcf STATUS, C ; he he :)
rlf pdu_dodajem, 1
decfsz pdu_tmp1, 1 ; --, skip if zero
GOTO PrimiText_1b_rl; jos!
; rotiranje zavrseno, merdzaj ih
movfw pdu_dodajem ; w=ono sto dodajem lijevo
iorwf pdu_prvi, 0 ; w = konacan rezultat pakovanja
movwf pdu_coded ; konacan rezultat je ovdje, treba ga ugurati u RAM
movfw pdu_drugi
movwf pdu_prvi ; prvi=drugi
; treba mu izbiti one desne koje smo prebacili u "prvi" i rotirati desno pdu_proizvdm [Censurado]!
movfw pdu_proizvdm
movwf pdu_tmp1 ; petlja, ovoliko [Censurado] rotiramo udesno
incf pdu_tmp1, 1 ; +1, mora jer mi petlja pocinje od 0 :)
PrimiText_1b_rr ; rotiranje (pdu_proizvdm) [Censurado]
bcf STATUS, C ; he he :)
rrf pdu_prvi, 1 ; pici desno sine moj
decfsz pdu_tmp1, 1 ; --, skip if zero
GOTO PrimiText_1b_rr; jos!
PrimiText_1z
movfw pdu_coded ; w=coded 8-bit char
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++, & provjera
incf PDU_LEN ; ++
incf pdu_proizvdm, 1 ; ++
; if ==7 then reset counter, ne smije biti >=7!
movlw d'7' ;
subwf pdu_proizvdm, 0
btfsc STATUS, Z ; do if set!
clrf pdu_proizvdm; reset :)
GOTO PrimiText_1 ; jos sike
PrimiText_1f
; treba snimiti i zadnjeg u vecini slucajeva
movfw pdu_coded ; w=coded 8-bit char
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++, & provjera
incf PDU_LEN ; ++
PrimiText_2
; snimi nullbyte
;clrf INDF ; nullbyte oznaci kraj texta - VISE SE NE OZNACAVA KRAJ PDU-a NULL-om, sad se broji duzina u PDU_LEN
;CALL FSR_Next ; fsr++, & provjera
; sacemo snimiti jos duzinu user length-a na lokaciju tmp4 od fsr-a
movfw TEXT_FSR ; w=TEXT_FSR
movwf FSR ; FSR=lokacija nasa
; snimi kao 2 bajta duzinu
; prvo gornji nibble prebaci u donji nibble i snimi ga u INDF, ali takodje u ASCII formatu!
movlw b'11110000' ;
andwf tmp3, 0 ; w=samo gornji nibble ali u gornjem nibblu
movwf tmp1 ; tmp1=w
swapf tmp1, 0 ; w= eto ga sad u donjem nibblu
CALL BIN2HEX ; W pretvori u ASCII HEX u W
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++, & provjera
movlw b'00001111' ;
andwf tmp3, 0 ; w=samo donji nibble i to u donjem :)
CALL BIN2HEX ; W pretvori u ASCII HEX u W
movwf INDF ; INDF(FSR)=w
;CALL FSR_Next ; fsr++, & provjera
LITFSR ; vrati IRP=0
RETURN ; vrati se...
;***** Konvertuje broj u stotke (param: W, rezult: dec100, dec10, dec1) *****
ConvertNr
movwf tmp4 ; sacuvaj temp iz W
movlw LOW(dec100) ; address of dec100 tj. vrijednost 100-tina
movwf FSR ; file select register
movlw h'03' ; number of variables units tens hundreds (3)
movwf tmp3 ; temporary counting variable
ConvertNr_0
clrf INDF ; clear current value
ConvertNr_1
call GetBaseScalar; uzmi vrijednost koju oduzimas
subwf tmp4, 0 ; prividno oduzmi
btfss STATUS,C ; provjeri da li se ista nalazi unutar tmp4
goto ConvertNr_2 ; ne
movwf tmp4 ; rezultat u tmp4 stvarna vrijednost nakon oduzimanja
incf INDF, 1 ; incremetiraj variablu odredenu sa FSR
goto ConvertNr_1 ; ponovi opet
ConvertNr_2
decf FSR, 1
decfsz tmp3, 1
goto ConvertNr_0
return ; vrati se...
GetBaseScalar
movf tmp3, 0
addwf PCL, 1
nop
retlw h'01' ;1
retlw h'0A' ;10
retlw h'64' ;100
; gornje sve iznad, mora biti u prvih 255 bajta ovog page-a
;***** Provjera SMS poruke i parsiranje ******
CkSMS bsf LEDBSY ; busy led on
; ocisti RAM od prosle komande...
CALL CistiRAM ; ocisti ga! ovo ce ujedno da postavi sve lokacije na 00h pa ne moramo na kraju dekodiranje poruke postavljati nullbyte jer ga je ovo vec evo postavilo
bcf bNEWSMS ; obrisi nas odma
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupt
CALL RS_FLUSH ; flushaj buffer
CALL Hangup ; spusti ako slucajno zvoni... PustiDATA je unutra
CALL PustiDATA ; cekaj da prodju podaci
CALL SND_AT ; salji AT
CALL SND_PLS ; salji +
CALL SND_CMG ; salji CMG
movlw a'L' ; L
CALL TX_UART ; salji W...
movlw a'=' ; =
CALL TX_UART ; salji W...
movlw a'4' ; a'4'
CALL TX_UART ; salji W...
CALL SND_CRL ; <CR><LF> AT+CMGL=4<cr><lf>
; sad dobijamo dump od mobitela, npr:
; siemens m35:
; ako nema novih poruka:
; 1. d'13'
; 2. d'48'
; 3. d'13'
; ili ako bude poruka:
; 1. 13
; 2. 10
; 3. +
; 4. C
; ...
CALL PustiCRLFiUzmiNext; pustaj CR LF sve dok ne uzmes nesto sto nije cr i nije lf!
movwf tmp1 ; tmp1=w .. ovo je ili + ako ima poruka, ili a'0' ako nema poruka
movlw a'+' ; ako smo dobili + sve je OK
subwf tmp1, 0 ; w=tmp1-a'+'
btfsc STATUS, Z ; do if set, do if the same
GOTO CkSMS_0 ; idi nastavi hvatati, ima sms poruka!
;CALL RS_FLUSH ; flushaj ako ima sta slucajno! - ne smije PustiDATA ovdje da bude!!!
CALL PustiDATA ; ko kaze da ne smije ovdje da bude PustiDATA ?! :) .. garant dolazi barem jos jedan <CR> da zavrsi!
GOTO CkSMS_End ; vrati se kako treba
CkSMS_0
BIGFSR ; od sada FSR pokazuje na BANK2 i BANK3 !
movlw LOW(BEG_RAM1); w=pocetak rama za sms storage
movwf FSR ; FSR=w
;7. 76 >> L
;8. 58 >> :
;9. 32 >> <- ovaj cemo sacekati...
;10. 55 >> 7
;11. 44 >> ,
;12. 48 >> 0
;13. 44 >> ,
;14. 44 >> ,
;15. 54 >> 6
;16. 49 >> 1
;17. 13 >>
;18. 10 >>
;19. 48 >> 0
;20. 55 >> 7
;21. 57 >> 9
;22. 49 >> 1
movlw a' ' ; propustamo do " " znaka
CALL PropustajDo ; propustaj do njega, naredni iz RCREG-a je onaj koji se primi poslije njega!
; MSGID1
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
CALL FSR_Next ; fsr++ & provjera
; MSGID2, obicno bude ","
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
CALL FSR_Next ; fsr++ & provjera
clrf INDF ; oznaci kraj MSGID1 i 2 u nizu
CALL FSR_Next ; fsr++ & provjera
;1. 13 >>
;2. 10 >>
;3. 43 >> +
;4. 67 >> C
;5. 77 >> M
;6. 71 >> G
;7. 76 >> L
;8. 58 >> :
;9. 32 >>
;10. 55 >> 7
;11. 44 >> ,
;12. 48 >> 0
;13. 44 >> ,
;14. 44 >> ,
;15. 54 >> 6
;16. 49 >> 1
;17. 13 >> <- sad cemo ovaj sacekati...
;18. 10 >> i prvi podatak uzeti sa PustiCRLFiUzmiNext
;19. 48 >> 0
;20. 55 >> 7
;21. 57 >> 9
;22. 49 >> 1
movlw d'13' ; propustamo do <CR> znaka
CALL PropustajDo ; propustaj do njega...
CALL PustiCRLFiUzmiNext ; pusti i LF ako je dosao :)
; Length of the SMSC information HIGH NIBBLE-BYTE
;btfss PIR1, RCIF ; do if clear - ako nema podatka!
;GOTO $-1 ; cekaj bajt od mobitela
;CALL RX_UART ; daj data u W
; gore smo ga vec uzeli sa PustiCRLFiUzmiNext ! :)
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; gornji nibble u donjem nibblu ovog bajta
swapf tmp1, 1 ; gornji nibble stavi u gornji nibble ovog bajta
; Length of the SMSC information LOW NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
; donji nibble u donjem nibblu W registra
iorwf tmp1, 1 ; sklopi sve u tmp1
bcf STATUS, C ; clear carry :)
rlf tmp1, 0 ; W= tmp1*2 (shift <<)
; preskocimo W (tmp1*2) (Type-of-address of the sender number)
CALL Propustaj ; propusti W bytes
; First octet of this SMS-DELIVER message HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; gornji nibble u donjem nibblu ovog bajta
swapf tmp1, 1 ; gornji nibble stavi u gornji nibble ovog bajta
; First octet of this SMS-DELIVER message HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
; donji nibble u donjem nibblu W registra
iorwf tmp1, 1 ; sklopi sve u tmp1
btfsc tmp1, 6 ; do if set! do if ima UDH info!
GOTO SmsDel ; idi discard the message jer ima UDH a to nam ne godi!
; Address-Length. Length of the sender number HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
incf FSR, 1 ; fsr++ bez provjere jer ne smijemo dzarati W reg
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; gornji nibble u donjem nibblu ovog bajta
swapf tmp1, 1 ; gornji nibble stavi u gornji nibble ovog bajta
; Address-Length. Length of the sender number LOW NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
incf FSR, 1 ; fsr++ bez provjere takodje
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
; donji nibble u donjem nibblu W registra
iorwf tmp1, 1 ; sklopi sve u tmp1 trebace nam dole u petlji i malo prije za stimanje da bude parni broj
; ako je gore iznad bio neparan, povecaj ga za 1 zbog petlje dole!
btfsc tmp1, 0 ; bit0 = 0 ili 1?
incf tmp1, 1 ; napravi da je paran!
; Type-of-address of the sender number HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
CALL FSR_Next ; fsr++ & provjera
; Type-of-address of the sender number LOW NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=W
CALL FSR_Next ; fsr++ & provjera
CkSMS_1 ; hvatajmo TELNR posiljaoca poruke !
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++ & provjera
decfsz tmp1, 1 ; --, skip if zero!
GOTO CkSMS_1 ; jos...
clrf INDF ; oznaci kraj broja telefona u nizu
CALL FSR_Next ; fsr++ & provjera
; 2x TP-PID. Protocol identifier
movlw d'2'
CALL Propustaj ; propusti te podatke
; TP-DCS Data coding scheme HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; gornji nibble u donjem nibblu ovog bajta
; u tmp1 sad moram dobiti bit0=0
btfsc tmp1, 0 ; do if set, do if error sms!
GOTO SmsDel ; obrisi SMS iz MSGID1 i MSGID2
; TP-DCS Data coding scheme LOW NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; donji nibble u donjem nibblu ovog bajta
; trebam dobiti bitove 3 i 2 =0! inace je error sms
movlw b'00001100' ; w=00001100
andwf tmp1, 0 ; w=tmp1 & 00001100
btfss STATUS, Z ; moram dobiti zero, ako nije zero onda je to error sms
GOTO SmsDel ; obrisi SMS iz MSGID1 i MSGID2
; 14x TP-SCTS. Time stamp (semi-octets)
movlw d'14'
CALL Propustaj ; propusti te podatke
; TP-UDL. User data length, length of message HIGH NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf tmp1 ; gornji nibble u donjem nibblu ovog bajta
swapf tmp1, 1 ; gornji nibble stavi u gornji nibble ovog bajta
; TP-UDL. User data length, length of message LOW NIBBLE-BYTE
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
; donji nibble u donjem nibblu W registra
iorwf tmp1, 1 ; sklopi sve u tmp1
movfw FSR ; backup
movwf TEXT_FSR ; odakle krece tekst, treba nam za funkcije slanja sms-a, da ne trazimo pocetak, vec, evo ga :)
clrf pdu_decoded ; koliko je otpakovano karaktera/slova iz poruke
clrf pdu_bytecnt ; decoding byte coutner
CkSMS_2 ; hvatajmo SMS PDU data i pretvarajmo ga pdu->text "on-the-fly" u RAM !
; high nibble-byte
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
; ovo ako je <CR> ili <LF> onda je kraj definitivno! full-proof algoritam :)
movwf tmp5 ; sacuvaj ga iz W...
movlw d'13' ; w=cr
subwf tmp5, 0 ; w=tmp1-13
btfsc STATUS, Z ; do if set! do if the same!
GOTO CkSMS_3 ; exit this shijaTZ
movlw d'10' ; w=lf
subwf tmp5, 0 ; w=tmp1-10
btfsc STATUS, Z ; do if set! do if the same!
GOTO CkSMS_3 ; exit this shijaTZ
movfw tmp5 ; vrati ga u W...
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
movwf pdu_indata ; gornji nibble u donjem nibblu ovog bajta
swapf pdu_indata, 1; gornji nibble stavi u gornji nibble ovog bajta
; low nibble-byte
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
CALL HEX2BIN ; pretvori ga iz ascii hex-a u binary
; donji nibble u donjem nibblu W registra
iorwf pdu_indata, 1; sklopi sve u pdu_indata
; konacni podatak koji treba dekodirati je u pdu_indata registru
CALL pdu_text ; !!! <- ona snima u INDF(FSR) RAM! i sredjuje FSR
movfw pdu_decoded ; if(tmp1==pdu_decoded)
subwf tmp1, 0 ;
btfss STATUS, Z ; do if not the same!
GOTO CkSMS_2
CkSMS_3 ; konverzija PDU->TEXT je ocigledno zavrsila
;prebaceno u SmsDel: ;CALL PustiDATA ; flushaj crlf ili/i crlfOKcrlf i/ili narednu cijelu poruku...
bsf bNEWSMS ; nasli smo NEW sms :)
GOTO SmsDel ; bye bye sms, vrati cemo se odma dole ispod iz SmsDel rutine!
CkSMS_End ; ova labela TREBA, jer tu dodje SMSDEL funkcija kad izbrise poruku i ako se ne procita SMS iz kartice tu se dodje!
LITFSR ; nadalje FSR pokazuje na BANK0 i BANK1
INTOFF ; gasi interupte
CALL RS_FLUSH ; flushaj ako ima jos stagod u bufferu...
bcf LEDBSY ; busy led off
;RETURN ; vrati se...
;GOTO MainLoop ; vrati se sa GOTO !!!
GOTO DumpSMS ; idi dumpaj je korisniku
;***** FSR Prekoracenje iz banke u banku? - nastima nam fino ******
FSR_Next
incf FSR, 1 ; FSR++
; ako je FSR=LOW(END_RAM1)+1 onda FSR presaltaj BEG_RAM2
movlw LOW(END_RAM1)+1 ; w=erroreous ram value
subwf FSR, 0 ; w=fsr-w
btfss STATUS, Z ; do if not the same
RETURN ; vrati se
movlw LOW(BEG_RAM2) ;w=pocetak bank 3
movwf FSR ; fsr=nova mem lok
RETURN ; nastimali smo vrati se
FSR_Prev
decf FSR, 1 ; FSR--
; ako je FSR=LOW(BEG_RAM2)-1 onda FSR presaltaj END_RAM1
movlw LOW(BEG_RAM2)-1 ; w=erroreous ram value
subwf FSR, 0 ; w=fsr-w
btfss STATUS, Z ; do if not the same
RETURN ; vrati se
movlw LOW(END_RAM1) ;w=kraj banke 2
movwf FSR ; fsr=nova mem lok
RETURN ; nastimali smo vrati se
;***** PrimiBroj prima broj telefona od klijenta i kodira i stavlja u RAM ******
PrimiBroj
BIGFSR
movlw LOW(TELNRONLY);w=telnronly
movwf FSR ; FSR=pocetak telnr only-a
; poslije cemo izracunati length i upisati zajedno
; sa formatom broja koji je fiksan na a'91' (international)
clrf tmp3 ; length =0 za sad
PrimiBroj_1
; primanje neparnog broja u parnu lokaciju
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
; primili smo neparni
clrw ; w=0
subwf rut_DAT, 0 ; w=rut_DAT-w
btfsc STATUS, Z ; do if the same
GOTO PrimiBroj_2 ; nemoj vise, klijent je poslao nullbyte
CALL FSR_Next ; stavi ga na parnu lokaciju
movfw rut_DAT ; w=neparni broj
movwf INDF ; snimi ga na parnu lokaciju
CALL FSR_Prev ; vrati se na neparnu lokaciju
incf tmp3, 1 ; counter++
; primanje parnog broja u neparnu lokaciju
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
; primili smo parni
clrw ; w=0
subwf rut_DAT, 0 ; w=rut_DAT-w
btfsc STATUS, Z ; do if the same
GOTO PrimiBroj_3 ; nemoj vise, klijent je poslao nullbyte, dodaj F unutra.
movfw rut_DAT ; w=parni broj
movwf INDF ; snimi ga na neparnu lokaciju
CALL FSR_Next ; parna lokacija koju smo gore vec popunili
CALL FSR_Next ; neparna lok. za naredni parni broj
incf tmp3, 1 ; counter++
GOTO PrimiBroj_1 ; jos sine...
PrimiBroj_2
; obiljezi kraj sa nullbyte-om
clrf INDF ; =0, adresa je vec bila podesena
CALL FSR_Next ; FSR++
movfw FSR ; w=fsr addr
movwf TEXT_FSR ; sacuvaj mjesto za pocetak texta obavezno
; snimi i length
movlw LOW(TELNRDATA); w=telnrdata
movwf FSR ; fsr=w
; sad ga treba razbiti na dva HEX bajta jer tako mobitel zeli da mu ga uklokamo :) gornji pa donji nibble po bajtovima, ali u ASCII formatu! znaci +48
movlw b'11110000' ;
andwf tmp3, 0 ; w=samo gornji nibble ali u gornjem nibblu
movwf tmp1 ; tmp1=w
swapf tmp1, 0 ; w= eto ga sad u donjem nibblu
CALL BIN2HEX ; W pretvori u ASCII HEX u W
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++, & provjera
movlw b'00001111' ;
andwf tmp3, 0 ; w=samo donji nibble i to u donjem :)
CALL BIN2HEX ; W pretvori u ASCII HEX u W
movwf INDF ; INDF(FSR)=w
CALL FSR_Next ; fsr++, & provjera
; snimimo i format tel.nr kao '91' international!
movlw a'9' ;
movwf INDF ; 9
CALL FSR_Next ; fsr++, & provjera
movlw a'1' ;
movwf INDF ; 1
;CALL FSR_Next ; fsr++, & provjera
LITFSR
RETURN ; vrati se...
PrimiBroj_3
; treba upisati F
movlw a'F' ; w=F
movwf INDF ; snimi ga na neparnu lokaciju
CALL FSR_Next ; parna lokacija koju smo gore vec popunili
CALL FSR_Next ; neparna lok. za naredni parni broj
GOTO PrimiBroj_2 ; izadji kako treba...
;***** Reply SMS poruka, ne trazi tel.nr jer ga imamo u RAM-u ******
ReplySMS
bsf LEDBSY ; busy led on
btfsc bNEWSMS ; ako ima SMS u RAM-u onda mozemo nastaviti!
GOTO ReplySMS_1 ; idi nastavi...
; javi korisniku error
movlw h'ff' ; w=fullbyte (error)
CALL rut_TX ; salju fullbyte klientu
PAGE0 ;
bcf LEDBSY ; busy led off
GOTO MainLoop ; haj bugija!
ReplySMS_1
; primi prvi bajt koji nam govori da li ce SMS biti flash sms, alert sms, ili normalni sms
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
movwf TP_DCS ; snimi tip poruke
; sad uklokujemo text!
CALL PrimiText ; ima funkcija za to :)
; sad u RAM-u imamo:
; INDF(FSR=TELNRDATA): [Address-Length][Type-of-address of the sender number WARNING:moze biti 0-byte u extremnom slucaju][Sender number]
; INDF(TEXT_FSR); [User Data Length][7-bit ENCODED PDU DATA]
CALL SendItNow
PAGE0
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrati se...
;***** SendSMS komanda za slanje poruke, trazi i broj tel i text poruke *****
SendSMS
bsf LEDBSY ; busy led on
; primi prvi bajt koji nam govori da li ce SMS biti flash sms, alert sms, ili normalni sms
CALL rut_RX ; CEKAJ& primi ASCII slovo od klijenta u W i rut_DAT
movwf TP_DCS ; snimi tip poruke
; ocisti RAM od prosle komande...
CALL CistiRAM ; ocisti ga! ovo ce ujedno da postavi sve lokacije na 00h pa ne moramo na kraju dekodiranje poruke postavljati nullbyte jer ga je ovo vec evo postavilo
bcf bNEWSMS ; reci da nema vise poruke, jer smo je upravo obrisali
; sad uklokujemo broj primaoca i kodiramo!
CALL PrimiBroj ; ima funkcija za to :)
; sad uklokujemo text 8-bit ASCII chars, OD SAD je kodiran!
CALL PrimiText ; ima funkcija za to :)
; sad u RAM-u imamo:
; INDF(FSR=TELNRDATA): [Address-Length][Type-of-address of the sender number WARNING:moze biti 0-byte u extremnom slucaju][Sender number]
; INDF(TEXT_FSR); [User Data Length][7-bit ENCODED PDU DATA]
CALL SendItNow
PAGE0
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrati se...
;***** SendItNow salje iz RAM-a, komunicira sa mobitelom *****
SendItNow
; treba prebrojati PDU LENGTH
; pdu_length=2+2+2+2+2+(RAM)
; AT+CMGS=pdu_lentgh
movlw d'5' ; w=10/2 jer 10 bajtova odnosno "5" saljem fiksno...
movwf tmp5 ; pdulength, decimalni broj ce da bude, 1-3 bytes
; preracunati duzinu PDU date
BIGFSR ; IRP=1
movlw LOW(TELNRDATA)-1; W=telnrdata
movwf FSR ; FSR=W
SendItNow_0
CALL FSR_Next ; ++, & provjera
; da vidimo jel to sad nullbyte, on mora biti na neparnoj lokaciji
clrw ;
subwf INDF, 0 ;
btfsc STATUS, Z ; do if zero!
GOTO SendItNow_0a; izadji, pa da brojimo message text length
CALL FSR_Next ; ++, & provjera (jos jednom pa da ne dijelimo sa 2 na kraju)
incf tmp5, 1 ; tmp5++ brojac
GOTO SendItNow_0 ; jos...
SendItNow_0a ; Vise ne brojim PDU bajte, jer se moze naci NULL kao validan karakter. Sad ovu duzinu imam u PDU_LEN, ali kao -1 zbog UDL kojeg nisam gore izbrojao u PrimiText
movfw PDU_LEN ; w=pdu_len
addwf tmp5, 1 ; tmp5=w+tmp5
incf tmp5, 1 ; ++, zbog preskocenih 2 bajt-polubajta (userdata length, 2bytes)
;14.04.2009, bilo:
; sad brojimo message text, po jedan FSR++, jer je tako snimljena poruka u RAM
; movfw TEXT_FSR ; w=text fsr
; addlw d'2' ; w+=2
; movwf FSR ; podesi FSR za ascii text
; incf tmp5, 1 ; zbog preskocenih 2 bajt-polubajta (userdata length, 2bytes)
;SendItNow_0b
; ; da vidimo jel to sad nullbyte
; clrw ;
; subwf INDF, 0 ;
; btfsc STATUS, Z ; do if zero!
; GOTO SendItNow_0c; izadji
;
; CALL FSR_Next ; ++, & provjera
; incf tmp5, 1 ; tmp5++ brojac
;
; GOTO SendItNow_0b; jos...
SendItNow_0c
; sad imamo tmp5=5+izracunati "dvobajti"
LITFSR ; ConvertNr trazi IRP=0
movfw tmp5 ; w=tmp5
CALL ConvertNr ; pretvori W u dec1, dec10 i dec100
BIGFSR ; vrati...
; ubaci u mobitel
CALL SND_AT ; AT
CALL SND_PLS ; +
CALL SND_CMG ; CMG
movlw a'S' ; w=S
CALL TX_UART ; salji w
CALL SND_JDK ; =
; provjerimo da li je duzina pdu-a >=100 tojest da li ima stotke da ne saljemo dzabe a'0' na mobitel npr 048
clrw ; w=0
subwf dec100, 0 ; w=dec100-w
btfsc STATUS, Z ; do if is zero!
GOTO SendItNow_1 ; preskoci slanje stotke jer je nula
movlw d'48' ; w=osnova za ascii
addwf dec100, 0 ; w=dec100 u ascii formatu
CALL TX_UART ; salji stotku
SendItNow_1
movlw d'48' ; w=osnova za ascii
addwf dec10, 0 ; w=dec100 u ascii formatu
CALL TX_UART ; salji deseticu
movlw d'48' ; w=osnova za ascii
addwf dec1, 0 ; w=dec100 u ascii formatu
CALL TX_UART ; salji jedinicu
CALL SND_CRL ; <cr><lf> poslali smo mu AT+CMGS=xxx<CR><LF>
CALL PustiCRLFiUzmiNext; pustaj sve dok ne dobijes > ili E(RROR)
movwf tmp5 ; podatak je u tmp5 sad zbog uporedjivanja tu dole
CALL PustiDATA ; pusti datu dok ne prestane. sad on salje zadnjih CR i LF ili samo CR zavisi od telefona
CALL RS_FLUSH ; flushaj...
; da vidimo sta smo dobili kao reply gore iznad, treba nam a'>'
movlw a'>' ; w=>
subwf tmp5, 0 ; oduzmi
btfss STATUS, Z ; do if not the same
GOTO SendItNow_6a; javi error kod slanja!
; sad mu saljemo PDU DUMP!
;Length of SMSC information. (00)
CALL SND_ZER ; salji 0
CALL SND_ZER ; salji 0
;First octet of the SMS-SUBMIT message. (11)
movlw a'1' ; w=a'1'
CALL TX_UART ; salji
CALL TX_UART ; salji jos jednom
;TP-Message-Reference.
CALL SND_ZER ; salji 0
CALL SND_ZER ; salji 0
;RAM: Address-Length. Length of phone number (11)
;RAM: Type-of-Address.
;RAM: The phone number in semi octets.
; saljemo do nullbyte-a
movlw LOW(TELNRDATA); W=telnrdata
movwf FSR ; FSR=W
SendItNow_2
; da vidimo jel null
clrw ;
subwf INDF, 0 ;
btfsc STATUS, Z ; do if zero!
GOTO SendItNow_3 ; kraj slanja broja
movfw INDF ; w=INDF(FSR)
CALL TX_UART ; salji
CALL FSR_Next ; FSR++, & provjera
GOTO SendItNow_2
SendItNow_3
;TP-PID. Protocol identifier
CALL SND_ZER ; salji 0
CALL SND_ZER ; salji 0
;TP-DCS. Data coding scheme.
; eh sad, jel alert sms ili je normalni sms?
; znaci 10h (alert) ili 11h (normal), 7-bit message default alphabet
; TP_DCS je ili a'0' ili a'1'. znaci ili h'30' ili h'31'.
; poigracu se sa ovom 1 u donjem nibblu
movlw a'1' ; 0001 = Bits 1 and 0 WILL have a message class meaning
CALL TX_UART ; salji..
movlw a'1' ; po defaultu 1
btfsc TP_DCS, 0 ; ako ima jedinica u ovom bajtu znaci da je to alert
movlw a'0' ; ovo je alert sms bezbeli
CALL TX_UART ; salji 0(flash) ili 1(normal sms) :)
;TP-Validity-Period. (F0) = 336 dana
movlw a'F' ; F0
CALL TX_UART ; salji F
CALL SND_ZER ; salji ascii nulu
; saljemo do nullbyte-a, ali ga polovimo jer je u RAM-u kao ASCII a ne kao HEXA reprezentacija ASCII-a. To smo prije radili u PrimiText, sad se radi ovdje.
movfw TEXT_FSR ; W=text poruke pocinje odavdje
movwf FSR ; FSR=W
movfw INDF ; w=INDF(FSR) Prvi bajt userdata length-a
CALL TX_UART ; salji
CALL FSR_Next ; FSR++, & provjera
movfw INDF ; w=INDF(FSR) Drugi bajt userdata length-a
CALL TX_UART ; salji
CALL FSR_Next ; FSR++, & provjera
SendItNow_4
; da vidimo jel ima jos koji bajt za poslati na mobitel
tstf PDU_LEN ; testiraj ga na zero
btfsc STATUS, Z ; do if set, uradi ako je ==0
GOTO SendItNow_5 ; kraj slanja texta
; sad ga treba razbiti na dva HEX bajta jer tako mobitel zeli da mu ga uklokamo :) gornji pa donji nibble po bajtovima, ali u ASCII formatu!
movlw b'11110000' ;
andwf INDF, 0 ; w=samo gornji nibble ali u gornjem nibblu
movwf tmp1 ; tmp1=w
swapf tmp1, 0 ; w= eto ga sad u donjem nibblu
CALL BIN2HEX ; W pretvori u ASCII HEX u W
CALL TX_UART ; salji
movlw b'00001111' ;
andwf INDF, 0 ; w=samo donji nibble i to u donjem :)
CALL BIN2HEX ; W pretvori u ASCII HEX u W
CALL TX_UART ; salji
CALL FSR_Next ; fsr++, & provjera
decf PDU_LEN, 1 ; length--, gore je provjera
GOTO SendItNow_4 ; jos!
SendItNow_5
LITFSR ; IRP=0
bsf bINT_1 ; aktiviraj gsm interrupt prije nego sto posaljemo CTRLZ radi brzine :)
bcf bINT_2 ; =0
CALL IntON ; pali interrupte
CALL SND_CTZ ; CTRL+Z
; sacemo pricekati odgovor od mobitela!!! cr i/ili lf + (ok) ...ili... cr i/ili lf E (error)
CALL PustiCRLFiUzmiNext; fina funkcija fakat :)
movwf tmp5 ; sacuvaj ga u tmp5 zbog poredjenja dole
CALL PustiDATA ; propusti i ostatak sto dolazi garant
INTOFF
movlw a'+' ;
subwf tmp5, 0 ;
btfsc STATUS, Z ; dosao je +
GOTO SendItNow_6 ; OK
SendItNow_6a
; javi korisniku da nije otislo bio je neki error od mobitela
bsf LEDSER ; pali send error led, neka provjeri kredit na mobitelu
movlw h'ff' ; fullbyte=error
CALL rut_TX ; salju fullbyte klientu
RETURN ; vrati se
SendItNow_6
; javi korisniku da je otislo (mozda) :)
bcf LEDSER ; gasi send error led
clrw
CALL rut_TX ; salju nullbyte klientu
RETURN ; vrati se...
;***** DUMP SMS poruke iz RAM-a ******
; Return format: [TEL_NR][0][SMS_PORUKA][0]
DumpSMS bsf LEDBSY ; busy led on
btfsc bNEWSMS ; ako uopste imamo poruku u RAM-u
GOTO DumpSMS_1 ; OK nastavi
movlw h'00' ; javi err korisniku kao da nema nista
CALL rut_TX ; salju nullbyte klientu
PAGE0 ;
bcf LEDBSY ; busy led off
GOTO MainLoop ; nema nista, haj bugija!
DumpSMS_1
movlw h'FF' ; javi korisniku da poruka slijedi
CALL rut_TX ; salju fullbyte klientu
BIGFSR ; IRP=1
movlw LOW(TELNRONLY); w=adr
movwf FSR ; FSR=w
DumpSMS_2
CALL FSR_Next ; haj na naredni drugi odma
movfw INDF ; w=INDF
CALL rut_TX ; salju klijentu parni bajt kao prvi
CALL FSR_Prev ; vrati se za jedan
; necemo mu slati a'F' ako je to ovaj bajt
movlw a'F' ; w=a'F'
subwf INDF, 0 ; oduzmi
btfsc STATUS, Z ; do if set, uradi ako jeste F
GOTO DumpSMS_2a ; preskoci slanje ovog bajta na 4-wire
movfw INDF ; w=INDF
CALL rut_TX ; salju klijentu neparni bajt kao drugi
DumpSMS_2a
CALL FSR_Next ; jedan vise
CALL FSR_Next ; i jos jedan vise i mozemo krenuti iz pocetka
; ako smo dosli do kraja broja (null)?
clrw
subwf INDF, 0
btfsc STATUS, Z
GOTO DumpSMS_3 ; nemoj vise slati broj, dole posalji null i nastavi dumpat do null-a
GOTO DumpSMS_2 ; jos...
DumpSMS_3
clrw
CALL rut_TX ; salju klijentu null za kraj broja, sacemo dumpat ostatak do null-a i njega
CALL FSR_Next ; preskocimo null, da dole odma ne izadjemo :)
DumpSMS_4
movfw INDF ; w=INDF
CALL rut_TX ; salju klijentu bajt
; jesmol poslali konacno null?
clrw
subwf INDF, 0
btfsc STATUS, Z
GOTO DumpSMS_End ; zavrsi dumpanje
CALL FSR_Next ; ovo sam bio zaboravio :)
GOTO DumpSMS_4 ; jos...
DumpSMS_End
LITFSR ; IRP=0
PAGE0 ;
bcf LEDBSY ; busy led off
GOTO MainLoop ; vrati se...
;***** Brise SMS poruku na lokaciji MSGID1 i MSGID2 ******
; fsr MORA biti podesen za bank 2 i 3
SmsDel ;zakomentirano jer sam prebacio iz CkSMS_3 ;CALL RS_FLUSH ; mora biti zbog discardanja poruke ako joj encoding pogresan ili ako ima UDH!
CALL PustiDATA ; flushaj crlf ili/i crlfOKcrlf i/ili narednu cijelu poruku...
; trebamo mu reci da prestane slati dump!
CALL SND_AT ; salji 'A','T'
CALL SND_CRL ; cr lf
CALL PustiDATA ; propusti answer...
; ; sad jedno cudno flushanje podataka. pozivanje funkcije X [Censurado] ukoliko bude potrebe za time
; clrf tmp6
;SmsDel_0a
; call pstpz ; unutra provjeravamo i ako ima vratimo se odma sa return i ovdje dole opet provjerimo i uzmemo podatak
; btfsc PIR1, RCIF ; uradi ako smo naisli na podatak!
; CALL PustiDATA ; uleti i propustaj unutra...
; decfsz tmp6, 1
; GOTO SmsDel_0a
; ;..
;
movlw LOW(MSGID1) ; prvi broj
movwf FSR ; fsr=lowaddr(msgid1)
; AT+CMGD=XY<CR><LF> - brisanje poruke 01..20
CALL SND_AT ; salji 'A','T'
CALL SND_PLS ; salji '+'
CALL SND_CMG ; salji 'C','M','G'
movlw a'D' ; W='D'
CALL TX_UART ; salji W
CALL SND_JDK ; salji '='
movfw INDF ; W=MSGID1
CALL TX_UART ; salji W
incf FSR, 1 ; FSR++
; Ovaj drugi msgid cemo slati samo ako nije jednak ',' zarezu
movlw a',' ; W=a','
subwf INDF, 0 ; W=MSGID2-W
btfsc STATUS, Z ; preskoci ako nije rezultat nula, odradi ako jest nula (do if MSGID2==',')
GOTO SmsDel_1 ; Znaci da je ',', pa skoci odma na slanje d'13'
movfw INDF ; W=MSGID2
CALL TX_UART ; salji W
SmsDel_1
CALL SND_CRL ; salji <CR><LF>
CALL PustiDATA ; propusti datu, jer garant dolazi OK od mobitela
GOTO CkSMS_End ; vrati se na kraj parsiranja...
;***** Ceka i propusta dok nesto ne bude jednako <cr> i jednako <lf> *******
; konacno uzme ne CR i ne LF u W i vrati ga
PustiCRLFiUzmiNext
bsf LEDGSM ; gsm comm led on
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
movwf tmp2 ; tmp2=podatak
; jel CR
movlw d'13' ; w=13
subwf tmp2, 0 ; oduzmi
btfsc STATUS, Z ; jeste 13
GOTO PustiCRLFiUzmiNext; propustili smo ga... provjeri naredni koji dolazi
; jel LF
movlw d'10' ; w=10
subwf tmp2, 0 ; oduzmi
btfsc STATUS, Z ; jeste 10
GOTO PustiCRLFiUzmiNext; propustili smo ga... provjeri naredni koji dolazi
; ovaj sto je dosao nije ni CR ni LF, bugija
bcf LEDGSM ; gsm comm led off
movfw tmp2 ; vrati podatak u W
RETURN ; vrati se....
;***** Ceka i propusta W bajtova ******
Propustaj
movwf tmp2 ; tmp2=counter propustanja
Propustaj_1
bsf LEDGSM ; gsm comm led on
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
decfsz tmp2, 1 ; --, skip if zero
GOTO Propustaj_1 ; jos...
bcf LEDGSM ; gsm comm led off
RETURN ; vrati se...
;***** Ceka i propusta bajtove sve dok ne naidje na bajt W ******
PropustajDo
movwf tmp2 ; tmp2=bajt koji cekamo
PropustajDo_1
bsf LEDGSM ; gsm comm led on
btfss PIR1, RCIF ; do if clear - ako nema podatka!
GOTO $-1 ; cekaj bajt od mobitela
CALL RX_UART ; daj data u W
subwf tmp2, 0 ; w=tmp2-w
btfss STATUS, Z ; skip if same, do if not the same
GOTO PropustajDo_1 ; jos...
bcf LEDGSM ; gsm comm led off
RETURN ; vrati se...
;***** (ASCII HEX) 2 (BIN) konverzija iz W u W ******
HEX2BIN movwf tmp2
movlw d'48' ; skini osnovu za broj 0
subwf tmp2, 1 ; u tmp2 je sad ili broj, ili >16. ako je >16 onda skini mu jos 7. to je to.
movlw d'16' ; w=16
subwf tmp2, 0 ; w=tmp2-16
btfss STATUS, C ; do if clear
GOTO HEX2BI1 ; vrati samo tmp2 u W
; veci je od 16, umanji ga jos za 7
movlw d'7'
subwf tmp2, 0 ; W = smanji W za 7 i to je to
RETURN ; vrati rez u W
HEX2BI1 movfw tmp2 ; w=tmp2
RETURN ; vrati rez u W
;***** (BIN) 2 (ASCII HEX) konverzija iz W u W ******
BIN2HEX movwf tmp2
; ako je broj >9 dodati mu 7
movlw d'10' ; w=10
subwf tmp2, 0 ; w=tmp2-9
btfss STATUS, C ; do if clear
GOTO BIN2HE1 ; nije veci od 9
; veci je od 9
movlw d'7' ; dodati mu 7 da predjemo na slova
addwf tmp2, 1 ; tmp2+=7
BIN2HE1 movlw d'48' ; dodaj mu ascii value
addwf tmp2, 0 ; add
RETURN ; vrati se sa rez u W
;***** Cisti RAM, proslu sms ***** !nastima STATUS,IRP za banke0 i 1 !!!
CistiRAM
BIGFSR ; IRP=1
movlw LOW(BEG_RAM1); w=adr
movwf FSR ; FSR=w
CistiRAM1
clrf INDF ; INDF(FSR)=00h
; jesmol dosli do totalnog kraja?
movlw LOW(END_RAM2); w=adr
subwf FSR, 0 ; w=fsr-w
btfsc STATUS, Z ; do if set
GOTO CistiRAM2 ; dosta ciscenja!
CALL FSR_Next ; fsr++, & provjera
GOTO CistiRAM1 ; cisti jos...
CistiRAM2
LITFSR ; IRP=0
RETURN ; vrati se sve smo zavrsili...!
;***** Init interrupta *****
IntON movlw h'FE' ; w=F?h
movwf ckerr3 ; ckerr3=F?h
;clrf ckerr2 ; ckerr2=0
movlw d'200' ; w=?
movwf ckerr2 ; smanji, umjesto=0
clrf ckerr1 ; ckerr1=0
bcf bINTER ; =0, mora!
clrf TMR0 ; iz pocetka molim :)
bsf INTCON, TMR0IE; omoguci prekid na tmr0 kad predje sa hFF na h00
bsf INTCON, GIE ; omoguci sve prekide ! main switch on :)
RETURN ; vrati se...
;***** Init telefona *****
;* NOTE: U ovoj rutini ce se desavati OERR tx buffer overrun error definitivno
;* ali nista strasno, nije problem.
GSM_Init
;ATZ
;ATE0
;ATV0
;AT+CLIP=1
bcf bGSMIN ; gsm initialized=0
bsf LEDBSY ; busy led on
bsf bINT_1 ; aktiviraj gsm interrupt
bcf bINT_2 ; =0
CALL IntON ; pali interrupt
; ATZ<CR><LF> - reset modem
CALL SND_AT ; salji 'A','T'
movlw a'Z' ; W='Z'
CALL TX_UART ; salji W
CALL SND_CRL ; salji <CR><LF>
CALL PustiDATA ; cekaj da GSM prestane slati datu
; sad echo dolazi 100%
; ATE0<CR><LF> - echo off
CALL SND_AT ; salji 'A','T'
movlw a'E' ; W='E'
CALL TX_UART ; salji W
movlw a'0' ; W='0'
CALL TX_UART ; salji W
CALL SND_CRL ; salji <CR><LF>
CALL PustiDATA ; cekaj da GSM prestane slati datu
; ATV0<CR><LF> - vracaj mi samo brojeve kao odgovor na moje komande
CALL SND_AT ; salji 'A','T'
movlw a'V' ; W='V'
CALL TX_UART ; salji W
movlw a'0' ; W='0'
CALL TX_UART ; salji W
CALL SND_CRL ; salji <CR><LF>
CALL PustiDATA ; cekaj da GSM prestane slati datu
; AT+CLIP=1<CR><LF> - daj broj pozivoca kad bude zvonio RING
CALL SND_AT ; salji 'A','T'
CALL SND_PLS ; salji plus
movlw a'C' ; W=C
CALL TX_UART ; salji W
movlw a'L' ; W=L
CALL TX_UART ; salji W
movlw a'I' ; W=I
CALL TX_UART ; salji W
movlw a'P' ; W=P
CALL TX_UART ; salji W
CALL SND_JDK ; salji =
movlw a'1' ; W=1
CALL TX_UART ; salji W
CALL SND_CRL ; salji <CR><LF>
CALL PustiDATA ; cekaj da GSM prestane slati datu
CALL RS_FLUSH ; na kraju jos flush
INTOFF ; gasi interrupt
bcf LEDBSY ; busy led off
bsf bGSMIN ; gsm initialized=1
RETURN ; vrati se...
;***** PustiDATA algoritam ******
; pricekaj jedan bajt, a ostale propustaj do kraja!
PustiDATA
bsf LEDGSM ; pali ovo da kazemo da cekamo podatak od mobitela. led ce ugasiti RX_UART rutina
btfss PIR1, RCIF ; do if clear
GOTO $-1 ; cekaj prvi bajt
PustiDATA_1
CALL RX_UART ; dummy read
; sad pauza sa provjerom 2x
clrf PAU_TEMP1 ;
PustiDATA_2
bsf LEDGSM ; pali ovo da kazemo da cekamo podatak od mobitela. led ce ugasiti RX_UART rutina
call pstpz ; unutra provjeravamo i ako ima vratimo se odma sa return i ovdje dole opet provjerimo i uzmemo podatak
btfsc PIR1, RCIF ; ako je u medjuvremenu dosao podatak, moramo ga odma procitati da se ne desi OERR
GOTO PustiDATA_1 ; procitaj ga odma i resetuj pauzu
decfsz PAU_TEMP1, 1;
GOTO PustiDATA_2 ; cekaj...
; kraj pauze sa obavezno provjerom u sebi
btfsc PIR1, RCIF ; do if set
GOTO PustiDATA_1 ; opet!
bcf LEDGSM ; gasi ovaj led ako nije dosao podatak, tojest ako smo docekali kraj podataka od mobitela
RETURN ; vrati se..
;pauza za ovu gore rutinu a koristi se i u SmsDel !!!
pstpz clrf PAU_TEMP2
pstpz_1 btfsc PIR1, RCIF ; ako je u medjuvremenu dosao podatak, moramo ga odma procitati da se ne desi OERR
RETURN ; vrati se posto je dosao ev u medjuvremenu
decfsz PAU_TEMP2,1 ; --, skip if zero!
GOTO pstpz_1 ; jos...
RETURN ; vrati se totalno, pauza istekla nije nista doslo u medjuvremenu
;***** Hangup ******
Hangup ; salji sad ATH<CR><LF> da spusti slusalicu
CALL SND_AT ; salji AT
movlw a'H' ; W=a'H'
CALL TX_UART ; salji W...
CALL SND_CRL ; salji CR LF
RETURN ; vrati se...
;***** Program koji salje AT na gsm *****
SND_AT movlw a'A' ; W='A'
CALL TX_UART ; salji W
movlw a'T' ; W='T'
CALL TX_UART ; salji W
RETURN ; vrati se...
;***** TX_UART, slanje W-a na UART *****
TX_UART bsf LEDGSM ; pali gsm comm led
BANK1
btfss TXSTA, TRMT ; (1) transmission is complete if hi
GOTO $-1 ; cekaj da bude hi
BANK0
movwf TXREG ; pukni ga u tx buffer
bcf LEDGSM ; gasi gsm comm led
RETURN ; vrati se...
;***** RX_UART, primanje u W sa UARTA *****
RX_UART bsf LEDGSM ; pali gsm comm led
btfsc RCSTA, OERR ; buffer overrun?
GOTO RX_UART_RESTART; resertuj prijem
bcf LEDGSM ; gasi gsm comm led
movf RCREG, W ; procitaj serial data u W
RETURN ; vrati se...
RX_UART_RESTART
bcf RCSTA, CREN ; gasi ga
nop
bsf RCSTA, CREN ; pali nazad
bcf LEDGSM ; gasi gsm comm led
RETURN ; vrati se totalno...
;***** Flushanje RCREG-a ******
RS_FLUSH
btfsc PIR1, RCIF ; do if set
CALL PustiDATA ; flushaj sto je ostalo...
movfw RCREG ; flush
movfw RCREG ; flush
movfw RCREG ; flush
RETURN ; vrati se...
;***** Program koji salje <CR><LF> na gsm ******
SND_CRL movlw d'13' ; W=d'13'
CALL TX_UART ; salji W
;movlw d'10' ; W=d'10' ; trax iskljucio 6.5.2007-me
;CALL TX_UART ; salji W
RETURN ; vrati se...
;***** Program koji salje '+' na gsm *****
SND_PLS movlw a'+' ; W='+'
CALL TX_UART ; salji W
RETURN ; vrati se...
;***** Program koji salje '0' na gsm *****
SND_ZER movlw a'0' ; W='0'
CALL TX_UART ; salji W
RETURN ; vrati se...
;****** Program koji salje '=' na gsm ******
SND_JDK movlw a'=' ; W='='
CALL TX_UART ; salji W
RETURN ; vrati se...
;****** Program koji salje CTRL Z ******
SND_CTZ movlw d'26' ; W='^Z'
CALL TX_UART ; salji W
RETURN ; vrati se...
;****** Program koji salje CMG ******
SND_CMG movlw a'C' ; W='C'
CALL TX_UART ; salji W
movlw a'M' ; W='M'
CALL TX_UART ; salji W
movlw a'G' ; W='G'
CALL TX_UART ; salji W
RETURN ; vrati se...
;***** rut_TX slanje bajta na modul iz W registra *****
;* prvo zadnji (high) bit se salje !
rut_TX movwf rut_DAT ; rut_DAT = W (mi ustvari saljemo rut_DAT registar)
bsf LED4WR ; 4-wire bus led
bsf HEY ; ovo je neophodno ako neuspije komunikacija pa se ovo ne vrati na 1, e ovdje cemo vratit ba :)
; treba provjeriti da li je bus slobodan, ako onaj tamo drzi HEY spustenu znaci da nije! javi odma ozbiljnu gresku!
btfsc IRQ ; do if set
GOTO rut_TX0 ; nastavi normalno
PAGE0
GOTO GoISR_4WIRE ; javi ozbiljnu gresku
rut_TX0 ; nastavi normalno
;pali interrupte da ne zaglavimo do kraja zivota ako master spava
bcf bINT_1 ; =0
bsf bINT_2 ; pali 4wire interr
CALL IntON ; pali interrupts
BANK1 ; bank 1
bcf portDAT ; ouput
BANK0 ; bank 0
bcf HEY ; trazimo prenos podataka, ovo je high sve dok smo u predaji
; posalji mu sad 8 bita na njegov zahtjev. sacekamo clock pa postavimo bit odma!
; onda cekamo da on vrati clock i vratimo se na pocetak i cekamo da ga opet spusti... tako 8 bita
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter
rut_TX1 ; ovdje se vrtimo !
; sacekajmo da on spusti clock, da mu postavimo bit na DATA liniju
btfsc CLK ; cekaj da ga spusti
GOTO $-1 ; cekaj...
bsf HEY ; vratimo nazad na 1 jer nas je eto cuo cim je poceo da clocka
btfss rut_DAT, 7 ; skip if set, do if clear [(0)0000000]
GOTO rut_TX2 ;
bsf DAT ; data = 1
GOTO rut_TX3 ; preskoci setovanje data=0
rut_TX2 bcf DAT ; data = 0
rut_TX3
btfss CLK ; cekaj da ga vrati nazad na 1 jer smo mi garant brzi od njega
GOTO $-1 ; cekaj da digne clock nazad
rlf rut_DAT, 1 ; << rotate left 1x
decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_TX1 ; salji slijedeci bit !
BANK1 ; bank 1
bsf portDAT ; nazad na input
BANK0 ; bank 0
INTOFF ; interrupts off
bcf LED4WR ; gasi 4-wire led ;ovdje bi mogo i gasiti 4RR led
bcf LED4RR ; gasi i 4-wire comm error led ako je slucajno nekad bilo upaljeno
RETURN ; vrati se...
;***** rut_RX primanje bajta sa modula u W i rut_DAT registar *****
;* prvo zadnji (high) bit se prima !
rut_RX bsf LED4WR ; 4-wire bus led
bsf HEY ; predostroznosti radi
;pali interrupte da ne zaglavimo do kraja zivota ako master spava
bcf bINT_1 ; =0
bsf bINT_2 ; pali 4wire interr
CALL IntON ; pali interrupts
btfsc IRQ ; cekaj podatak! ovo smo prebacili ovdje a bilo je prije svakog poziva ove rutine u cijelom programu
GOTO $-1 ; cekaj da se spusti
BANK1 ; bank 1
bsf portDAT ; input
BANK0 ; bank 0
bcf HEY ; kazi mu da smo spremni za prijem! sacemo sacekati da on spusti IRQ i krece komunikacija
btfss IRQ ; cekaj da je digne nazad
GOTO $-1 ; cekaj...
bsf HEY ; vrati ovo na 1 ne treba nam do daljnjeg prozivanja
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter
rut_RX1 ; ovdje se vrtimo !
rlf rut_DAT, 1 ; << rotate left 1x
btfsc CLK ; do if set, ako jos nije oborena za naredni/prvi bit?
GOTO $-1 ; cekaj da se obori linija
btfss DAT ; skip if set, do if clear (uradi ako je dosla 0)
GOTO rut_RX2 ;
bsf rut_DAT, 0 ; [0000000(1)]
GOTO rut_RX3 ; preskoci setovanje 0bita=0
rut_RX2 bcf rut_DAT, 0 ; [0000000(0)]
rut_RX3
btfss CLK ; ako je jos uvjek na nuli
GOTO $-1 ; cekaj da se digne linija opet!
decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_RX1 ; primi slijedeci bit !
INTOFF ; interrupts off
bcf LED4WR ; gasi 4-wire led
bcf LED4RR ; gasi i 4-wire comm error led ako je slucajno nekad bilo upaljeno
movfw rut_DAT ; w=rezultat
RETURN ; vrati se...
;***** Pauze *****
; Delay = 1 seconds
; Actual delay = 1 seconds = 4000000 cycles
; Error = 0 %
Delay_1s ;3999994 cycles
movlw h'23'
movwf PAU_TEMP1
movlw h'B9'
movwf PAU_TEMP2
movlw h'09'
movwf PAU_TEMP3
Delay_1s_0
decfsz PAU_TEMP1, 1
goto $+2
decfsz PAU_TEMP2, 1
goto $+2
decfsz PAU_TEMP3, 1
goto Delay_1s_0
goto $+1 ;2 cycles
return ;4 cycles (including call)
;#################################################
;***** Flash PAGE3
;#################################################
ORG 0x1800 ; page 3 program memory
nop
;***** KRAJ *****
END
Last update of this package: 21.5.2007 (sms box.pdf; return values of "R" and "r" commands were wrong)
Primitive commands (communicating with the box)
Commands you can send to the SMS Box! ([0] is representing a null-byte, [1] is representing a full-byte (FFh), all commands are case-sensitive ASCII characters)
Detailed commands and all possible return values:
«R» - read sms messages:
Note: Requires no additional parameter. Messages being read are read one at a time in a first-in-first-out order. Command returns only one (oldest) message and deletes it from the phone (removes from the queue). To know if you have reached the end of the queue (all messages read/processed and deleted) you must issue «R» command until you get [1] response (no more messages).
Return value:
a) queue not empty (message(s) available): [SENDER_NR][0][SMS][0]
b) no messages available: [1]
Example for a): 38761123456[0]Hello world![0]
«r» - re-read last sms message:
Note: Requires no additional parameter. If command «R» resulted in no messages than the result is [1]. If there was a message, than it's being dumped again.
Return value:
a) there is a message in internal SMS Box!'s memory than its being dumped again in the same form: [SENDER_NR][0][SMS][0]
b) if there was no message than result would be: [1]
«S» - sending the sms message:
Note: Requires 3 additional parameters: Type of message [flash message, normal message]. Messages being sent are Unicode encoded UCS2 (16bit) so some phones might not be able to receive them (my Panasonic PSTN fixed-phone line telephone with SMS support doesn't read them but all GSM phones should). Therefore, length of SMS message that's being sent is 160/2 = 80 characters maximum. The SMS Box! will not alert you when you exceed message length when clocking sms in, instead it will just inform you that it couldn't send the message.
Input command form and parameters:
Código: Seleccionar todo
S[TYPE][RECEIVER_NR][0][SMS][0]
S – keyword
[TYPE] – ASCII byte value 1 (flash message) or 0 (normal message) [RECEIVER_NR] – Receiver's gsm phone-number in international format
[SMS] – SMS text
Example for flash message (to number: 38761123456):
Código: Seleccionar todo
S138761123456[0]Temperature is 53,5 degrees.[0]
Please note: All parameters above are single-byte ASCII characters.
Return value:
a) [0] – message sent
b) [1] – message not sent for some reason (probably pre-paid credit expired). Now an appropriate LED is lit up. It will be turned off automatically after another successful sending of sms message.
Please note: [1] represents full-byte (hFF).
«s» - replying to a sms message:
Note: The same scenario as «S» command. Only [RECEIVER_NR][0] is omitted.
Example for non-flash message:
Código: Seleccionar todo
s0Temperature is 53,5 degrees.[0]
Return value: The same scenario as «S» command with an addition:
a) --||--
b) --||--
c) [1] – message not sent for some reason (if no appropriate LED is being lit up, than there was no phone number in internal memory so it couldn't do a reply to nowhere).
«D» - dial a number (place a voice call):
Note: No additional parameter required.
Example for placing a call:
Código: Seleccionar todo
D38761123456[0]
Return value:
a) [0] – Call request was forwarded to the phone, now you can check what's going on with «C» command.
«H» - hang-up
Note: No additional parameter required. This will hang up current active voice call or refuse a call.
Return value:
a) [0] – Call terminated (if any).
«C» - call status
Note: No additional parameter required.
Return values:
a) 0 – Ready
b) 3 – Incoming call (phone is ringing)
4) 4 – Call is active
Note: Return values are ASCII numbers.
«c» - last CLIP get
Note: No additional parameter required.
Return values:
a) [CLIP_DATA][0] – Phone had a ring since power up, this is the last caller's ID
b) [0] – There was nobody calling us, ever
Example for a): 38761123456[0]
Please note: If you need to be alerted with a phone-ring and caller ID data, see jumper selection in this document (ring-reporting jumper).
«A» - answer a call
Note: No additional parameter required
Return values:
a) 0 – connected, no error
b) /other response/ - meaning some error occurred
«p» - check prepaid credit balance / issue a CUSD command
Note: Requires additional parameter: service number, for example: *101#.
Example for issuing a prepaid credit check for some operators: p*101#[0]
Possible return value on the 4-wire bus would be:
a) Your credit balance is 5,3 EUR.[0]
b) 4 – meaning an error
Please note: This “p” command can also be used for any other CUSD command.
Please note: All above functions COULD return one or more results from the table below, in case of an error.
Commands that SMS Box! can send to your microcontroller project when in idle state or as a result of normal commands from the previous table: (all commands are represented as single byte HEX values except for the ring-reporting option data which is ASCII string).
You must answer to these commands because SMS Box! is waiting for you to accept this data. If you don't answer to these requests than 4-wire bus interrupt will raise and a proper LED will be lit-up in SMS Box!. Some kind of error-handling function as an interrupt should be implemented in your microcontroller project. In that function you just need to accept a byte-value and see what you need to do next.
Communication protocol, the 4-wire bus
Not so much thought has been given to this 4-wire synchronous bus.
Looking from the SMS Box!'s side, we have:
1. Data line – bidirectional (input - output)
2. Clock line – unidirectional (input - your microcontroller project is clocking-out/in the data from/to the SMS Box!)
3. IRQ line – unidirectional (input – this is interrupt for SMS Box!)
4. HEY line – unidirectional (output – this is where IRQ is generated to your microcontroller project)
All communication lines are pulled-up to Vcc with PIC16F877A's internal pull-up resistors, so, active line = low (GND).
SMS Box!'s 4-wire communication assembler routines (send and receive):
Código: Seleccionar todo
;***** rut_TX send a byte from W register *****
;* first (MSB) high bit is being sent !
rut_TX movwf rut_DAT ; rut_DAT = W (we are using rut_DAT
; temporary register in this function)
bsf LED4WR ; 4-wire bus led
bsf HEY ; in case we had a 4-wire bus error
; previously
; turn on proper interrupt in case your microcontroller project is
; lazy so we don't hang here forever bcf bINT_1 ; we don't need this interrupt... bsf bINT_2 ; we need this one, 4wire interr
CALL IntON ; turn them on
BANK1 ; bank 1 bcf portDAT ; ouput
BANK0 ; bank 0
bcf HEY ; we are requesting a data-transfer
; now send him 8 bits on his request. We wait for the clock and then
; set the bit rightaway
; then we wait for him to put the clock high and repeat this 8 times
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter
rut_TX1 ; this is our loop
; let's wait for him to put the clock LOW, so we can give him a data
; bit to the DATA line
btfsc CLK ; wait for low GOTO $-1 ; wait...
bsf HEY ; put this back to HIGH because he heard us
btfss rut_DAT, 7 ; skip if set, do if clear [(0)0000000]
GOTO rut_TX2 ;
bsf DAT ; data = 1
GOTO rut_TX3 ; skip setting to =0 rut_TX2 bcf DAT ; data = 0 rut_TX3
btfss CLK ; wait for him to return it to HIGH because
; we *should* be faster than microcontroller
; project
GOTO $-1 ; wait for clock to be HIGH
rlf rut_DAT, 1 ; << rotate left 1x decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_TX1 ; send next bit !
BANK1 ; bank 1
bsf portDAT ; back to input
BANK0 ; bank 0
INTOFF ; interrupts off
bcf LED4WR ; turn off 4-wire led
bcf LED4RR ; turn off 4-wire comm error led in case it
; was on because of 4-wire bus error
RETURN ; go back...
;***** rut_RX receiving a byte in W and rut_DAT register *****
;* first MSB (high) bit is being received!
rut_RX bsf LED4WR ; 4-wire bus led
; turn on proper interrupt in case your microcontroller project is
; lazy so we don't hang here forever
bcf bINT_1 ; =0
bsf bINT_2 ; turn on 4wire interr
CALL IntON ; swich'em on btfsc IRQ ; wait for data!
GOTO $-1 ; wit for low
BANK1 ; bank 1 bsf portDAT ; input BANK0 ; bank 0
bcf HEY ; let him know that we are ready to receive!
; now we are going to wait for him to lower
; the IRQ line and communication starts
btfss IRQ ; wait for him to bring it back to HIGH
GOTO $-1 ; wait...
bsf HEY ; put this back to HIGH, we don't need it
; until next call
movlw h'08' ; w=8
movwf rut_TMP1 ; =8, bit counter rut_RX1 ; this is our loop
rlf rut_DAT, 1 ; << rotate left 1x
btfsc CLK ; do if set, if not low yet for a data bit
GOTO $-1 ; wait for LOW
btfss DAT ; skip if set, do if clear (do if 0
; received)
GOTO rut_RX2 ;
bsf rut_DAT, 0 ; [0000000(1)] GOTO rut_RX3 ; preskoci setovanje 0bita=0 rut_RX2 bcf rut_DAT, 0 ; [0000000(0)] rut_RX3
btfss CLK ; if still zero GOTO $-1 ; wait for HIGH again!
decfsz rut_TMP1, 1 ; rut_TMP1--, skip if zero ! do if not!
GOTO rut_RX1 ; primi slijedeci bit !
INTOFF ; interrupts off
bcf LED4WR ; turn off 4-wire led
bcf LED4RR ; turn off 4-wire comm error led in case it
; was on because of 4-wire bus error
movfw rut_DAT ; w=result
RETURN ; return...
So you need something like in example «controller_eng.asm» (also assembler). In that example you can see how easy it is to send a flash message.