//***************************************************************
// GM862.H
// Definizioni e librerie per la gestione del modem GM862
// su modulo EE01
//
// TANZILLI.COM di Sergio Tanzilli
// http://www.tanzilli.com
//---------------------------------------------------------------
// Versione 1.14 del 25/3/2004
//***************************************************************

// Associazione tra le connessioni del modem ed il pin out del PIC18F452

#define GM_TXD    PIN_C6	// Out
#define GM_RXD    PIN_C7	// Inp
#define GM_RING   PIN_D0	// Inp
#define GM_CTS    PIN_D1	// Inp
#define GM_RES    PIN_D2	// Out
#define GM_ONOFF  PIN_D3	// Out
#define GM_RTS    PIN_D4	// Out
#define GM_DTR    PIN_D5	// Out
#define GM_DCD    PIN_D6	// Inp
#define GM_DSR    PIN_D7	// Inp
#define GM_PWRCTL PIN_B5	// Inp

#define GM_RX_BUFFER_SIZE 64

BYTE gm_rx_buffer[GM_RX_BUFFER_SIZE];
BYTE gm_next_in = 0;
BYTE gm_next_out = 0;

int32 timer1Tick;

// Funzioni di I/O seriale con il modem GM862

#use RS232(baud=9600,parity=N,bits=8,xmit=GM_TXD,rcv=GM_RXD)

//***************************************************************
// 	Controlla se ci sono caratteri in ricezione dal
// 	modem GM862
//
// 	Ritorna: 
//		0 se non ci sono caratteri
//    1 se ci sono caratteri
//***************************************************************

#define gm_KbHit (gm_next_in!=gm_next_out)

//***************************************************************
// 	Attende l'arrivo di un carattere dal modem GM862
//
// 	Ritorna: 
//		Il codice ascii del carattere ricevuto
//***************************************************************

BYTE gm_Getc() {
  BYTE c;

  while(!gm_KbHit) ;
  c=gm_rx_buffer[gm_next_out];
  gm_next_out=(gm_next_out+1) % GM_RX_BUFFER_SIZE;
  return(c);
}

//***************************************************************
// 	Invia un carattere al modem GM862
//***************************************************************

void gm_Putc(BYTE c) { putc(c); }

//***************************************************************
// Svuota il buffer di ricezione dal modem
//***************************************************************

void gm_FlushRxBuffer(void) {
  while(gm_KbHit) gm_getc();
}

//***************************************************************
// Handler di gestione degli interrupt
//***************************************************************

//***************************************************************
// Carattere ricevuto e pronto nel buffer della USART
//***************************************************************
#int_rda 
void serial_isr() {
	int t;
	
	gm_rx_buffer[gm_next_in]=getc();
	t=gm_next_in;
	gm_next_in=(gm_next_in+1) % GM_RX_BUFFER_SIZE;
	if(gm_next_in==gm_next_out)
	gm_next_in=t;           // Buffer pieno !!
}

//***************************************************************
// Overflow Timer 1
//***************************************************************

#int_timer1
void wave_timer() {
	set_timer1(63036);
	timer1Tick--;
}


//***************************************************************
// Start Timer
//***************************************************************

void StartTimer(int32 ms) {
	set_timer1(63036);
	timer1Tick=ms;
  setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  enable_interrupts(int_timer1);
}	

//***************************************************************
// Stop Timer
//***************************************************************

void StopTimer(void) {
  disable_interrupts(int_timer1);
}	

//***************************************************************
// Check Timer
//***************************************************************

int CheckTimer(void) {
  if (timer1Tick<=0) {
  	StopTimer();
  	return 1;
  } else {
  	return 0;
  }
}	

//***************************************************************
// Riceve la stringa di risposta dal modem
// 
// to timeout in mS
// buffer Buffer di memorizzazione della risposta (256 car)
//
// Ritorna 0 se uscito per timeout o dimensione massima (256 car)
// Ritorna 1 se ha ricevuto la sequenza OK<CR><LF>
//***************************************************************

int gm_WaitResponse(int32 to, char *buffer) {
  int8 c;
  int8 pToken;
  int8 pBuffer;
  char token[6];
  
  sprintf(token,"OK\r\n");

	pToken=0;
	pBuffer=0;
  StartTimer(to);
  for (;;) {
  	if (CheckTimer()) {
     	StopTimer();
     	buffer[pBuffer]=0;
  		return 0;
  	}	
    if (gm_kbhit) {
      c=gm_getc();
      buffer[pBuffer]=c;
      pBuffer++;
      if (pBuffer==0) {
       	StopTimer();
       	buffer[pBuffer]=0;
      	return 0;
      }	
		  StartTimer(to);
      if (c==token[pToken]) {
        pToken++;
        if (pToken==strlen(token)) {
        	StopTimer();
        	buffer[pBuffer]=0;
        	return 1;
        }	
      } else {
        pToken=0;
      }
    }	
  } 
} 

//***************************************************************
// Invia un impulso di accensione al modem GM862
//***************************************************************

void gm_SendONOFF(void) {
  output_high(GM_ONOFF);
  delay_ms(1200);
  output_low(GM_ONOFF);
 	delay_ms(5000);
}

//***************************************************************
// Accende il modem e controlla se risponde ai comandi AT
//***************************************************************

int gm_PowerOn(void) {
	char buffer[256];
	
  if (input(GM_PWRCTL)==0) {
  	gm_sendONOFF();
  }	
  
	for (;;) {
		gm_FlushRxBuffer();
  	printf(gm_putc,"AT\r");
  	delay_ms(100);
  	printf(gm_putc,"AT\r");
		delay_ms(100);
	    
  	if (gm_WaitResponse(200,buffer)) {
  		
  		// Disattiva l'echo
	  	printf(gm_putc,"ATE0\r");
			gm_WaitResponse(200,buffer);	  	

	  	// Blocca l'autobauding 
	  	// (Vedi pag.12 del Software User Guide)
	  	printf(gm_putc,"AT+IPR=9600\r");
			gm_WaitResponse(200,buffer);	  	
  		return 1;
  	}	else {
  		gm_SendONOFF();
  	}	
  }	
}

//***************************************************************
// Controlla se il modem si è registrato alla rete GSM
//
// Ritorna 0 se il modem non è ancora registrato
// Ritorna 1 se il modem è registrato
//***************************************************************

int gm_NetworkChecking() {
	char buffer[256];
	char token[20];

	printf(gm_putc,"AT+CREG\r");
		
	if (gm_WaitResponse(500,buffer)>0) {
		sprintf(token,"+CREG: 0,1");
		if (strstr(buffer,token)==0) return 1;
		sprintf(token,"+CREG: 1,1");
		if (strstr(buffer,token)==0) return 1;
	}	else {
		return 0;
	}
}

//***************************************************************
// Stato di riposo dei criteri del modem
//***************************************************************

void gm_LineInit(void) {
  output_high(GM_TXD);
  output_low(GM_DTR);
  output_high(GM_RTS);
  output_low(GM_ONOFF);
  output_low(GM_RES);
}


