SMS BOX Comunicacion con Telefonia y PIC

Sección dedicada a imágenes de circuitos, diagramas que no requieren explicación previa, Proyectos sencillos.
Area para desarrollo de proyectos, colaboración de toda la comunidad en proyectos. Solución de dudas y aportes.

No publicar manuales, no publicar temas ajenos a los proyectos. de ser necesario, hacer indicación con enlace entre etiquetas CODE
Avatar de Usuario
Enigma
Administrador del Sitio
Administrador del Sitio
Mensajes: 1268
Registrado: 20 Oct 2013, 16:26
Genero: Mujer
Profesion: Webmaster CEO SEO
Ubicacion: Matrix
Navegador: Chrome
Contactar:

SMS BOX Comunicacion con Telefonia y PIC

Mensaje sin leer por Enigma » 16 Mar 2018, 09:07

Proyecto SMS BOX Comunicacion con Telefonia y PIC

Imagen

Imagen

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.

Imagen

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

Imagen

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.

Imagen

Imagen

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
Imagen

Imagen

Imagen

Imagen

Imagen

Configuración de Impresion:
Imagen

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

Actualizacion del proyecto:
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)

Imagen

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).

Imagen

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... 

What you need to do from this point is write a «reverse» functions that communicate with these two above.
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.



Volver a “Proyectos y Circuitos Didacticos”