?? at.c
字號:
// this bit takes care of the AT modem dialing etc
/*
* Copyright (C) 2003-2004 by Clive Moss All rights reserved.
*
* Help & Contributions from D.J.Armstrong
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CLIVE MOSS 'AS IS' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.
* IN NO EVENT SHALL CLIVE MOSS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
//#ifdef CPU_eZ8
// #pragma stkck // enable stack checking
//#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "common.h"
#include "at.h"
#include "ppp.h"
//*************************************************************************************
#ifdef Debug
flash char ATStageStr1[] = "\n*** AT Stage: ";
flash char ATStageStr2[] = "Idle\n";
flash char ATStageStr3[] = "Dial Init 1\n";
flash char ATStageStr4[] = "Dial Init 2\n";
flash char ATStageStr5[] = "Dial Init 3\n";
flash char ATStageStr6[] = "Dialing\n";
flash char ATStageStr7[] = "PPP\n";
flash char ATStageStr8[] = "Disc 1\n";
flash char ATStageStr9[] = "Disc 2\n";
flash char ATStageStr10[] = "Unknown\n";
flash char ATStageStr20[] = "*** AT Retry Fail\n";
flash char ATDialTermStr[] = "AT\n";
#endif
T_AT AT;
//*************************************************************************************
#ifdef Debug
bool AT_DisplayStage(void)
{
if(!SendDebugRStr(ATStageStr1)) return false;
switch (AT.Stage)
{
case AT_Idle : return SendDebugRStr(ATStageStr2);
case AT_DialInit1 : return SendDebugRStr(ATStageStr3);
case AT_DialInit2 : return SendDebugRStr(ATStageStr4);
case AT_DialInit3 : return SendDebugRStr(ATStageStr5);
case AT_Dial : return SendDebugRStr(ATStageStr6);
case AT_PPP : return SendDebugRStr(ATStageStr7);
case AT_Disc1 : return SendDebugRStr(ATStageStr8);
case AT_Disc2 : return SendDebugRStr(ATStageStr9);
default : return SendDebugRStr(ATStageStr10);
}
}
#endif
//*************************************************************************************
void AT_Stage(T_AT_Stage Stage)
{ // set the AT modem stage
if (AT.Stage == Stage) return; // no change
//
AT.Stage = Stage; //
AT.Retries = 0; //
u16_Put(&AT.Retry_Timer, 0); // send next thing asap
#ifdef Debug
AT_DisplayStage();
#endif
}
bool AT_Start(void)
{ // start a connection attempt
// call this from the executive when you want to connect
if (AT.Stage != AT_Idle) return false; // already busy with the modem
#ifdef WindowsPPP
AT_Stage(AT_PPP); //
PPP_Start(PPP_Rom_Username, PPP_Rom_Password); // start a PPP session
return true; //
#else
AT_Stage(AT_DialInit1); //
//
MainBufferWr_Rx = 0; //
MainBufferWr_Tx = 0; //
UART1_RxBufferRd = 0; //
UART1_RxBufferWr = 0; //
//
return true; //
#endif
}
void AT_End(void)
{ // terminate a connection
if (PPP.Stage != PPPS_None)
{ // terminate the PPP first
PPP_End();
return;
}
#ifdef WindowsPPP
AT_Stage(AT_Idle);
#else
switch (AT.Stage)
{
case AT_Idle : break;
case AT_DialInit1 : AT_Stage(AT_Idle);
break;
case AT_DialInit2 : AT_Stage(AT_Idle);
break;
case AT_DialInit3 : AT_Stage(AT_Idle);
break;
case AT_Dial : AT_Stage(AT_Disc2);
break;
case AT_PPP : PPP_End();
break;
case AT_Disc1 : break; // already trying to disconnect
case AT_Disc2 : break; // already trying to disconnect
default : AT_Stage(AT_Idle);
break;
}
#endif
}
//*************************************************************************************
// call this when we have a new byte received from the modem - call from the executive
void AT_AddNewRxByte(u8 c)
{
#ifndef WindowsPPP
bool ok = false;
bool error = false;
bool ring = false;
bool failed = false;
bool connect = false;
if (c != 13)
{
if (c < 32) return; // ignore control charcters
if (MainBufferWr_Rx >= (sizeof(MainBuffer) - 1)) return; // buffer overflow - ignore character
if (MainBufferWr_Rx < 0) MainBufferWr_Rx = 0;
MainBuffer[MainBufferWr_Rx++] = tolower((char)c);
MainBuffer[MainBufferWr_Rx] = 0;
return;
}
// CR
strtrim(MainBuffer, ' ');
MainBufferWr_Rx = 0;
if (MainBuffer[0] == 0) return; // empty line
#ifdef Debug
SendDebugStr(MainBuffer);
SendDebugStr("\n");
#endif
if (strcmp((char*)MainBuffer, "ok") == 0) ok = true;
else
if (strcmp((char*)MainBuffer, "error") == 0) error = true;
else
if (strcmp((char*)MainBuffer, "ring") == 0) ring = true;
else
if (strcmp((char*)MainBuffer, "busy") == 0) failed = true;
else
if (strcmp((char*)MainBuffer, "no dialtone") == 0) failed = true;
else
if (strcmp((char*)MainBuffer, "no answer") == 0) failed = true;
else
if (strcmp((char*)MainBuffer, "no carrier") == 0) failed = true;
else
if ((strlen((char*)MainBuffer) >= 7) && (strncmp((char*)MainBuffer, "connect", 7) == 0)) connect = true;
memset(MainBuffer, 0, sizeof(MainBuffer));
if ((AT.Stage != AT_Dial) && failed)
{
AT_Stage(AT_Idle);
return;
}
switch (AT.Stage)
{
case AT_DialInit1 : if (ok) AT_Stage(AT_DialInit2);
break;
case AT_DialInit2 : if (ok) AT_Stage(AT_DialInit3);
break;
case AT_DialInit3 : if (ok) AT_Stage(AT_Dial);
break;
case AT_Dial : if (failed || error)
{
u16_Put(&AT.Retry_Timer, AT_Dial_Retry_Time); // try again in 6 seconds
break;
}
case AT_Idle : if (connect)
{
AT_Stage(AT_PPP);
PPP_Start(PPP_Rom_Username, PPP_Rom_Password); // start a PPP session
}
break;
case AT_PPP : break; // PPP is using the modem
case AT_Disc1 : if (ok || error) AT_Stage(AT_Disc2); // the modem has come out of data mode - we used the '+++' thingy
break;
case AT_Disc2 : if (ok) AT_Stage(AT_Idle); // the modem accepted the hangup command(s)
break;
default : AT_Stage(AT_Idle);
break;
}
#endif
}
//*************************************************************************************
// call this every 10ms - say from a timer interrupt
void AT_10ms_Timer(void)
{ // call this every 10ms
#ifndef WindowsPPP
if (AT.Stage == AT_Idle) return;
if (AT.Retry_Timer >= 10)
AT.Retry_Timer -= 10;
else
AT.Retry_Timer = 0;
#endif
}
//*************************************************************************************
// call this as often as possible from your executive loop - NOT from an interrupt
// it takes care of all the AT modem stuff for you
void AT_Process(void)
{
u8 c;
#ifdef WindowsPPP
//
if (PPP.Stage != PPPS_None) return; //
//
if (!MainBufferWr_Tx)
{
while (UART1_RxBufferRd != UART1_RxBufferWr)
{
c = (u8)UART1_RxBuffer[UART1_RxBufferRd++]; // get rx'ed byte
if (UART1_RxBufferRd >= sizeof(UART1_RxBuffer)) UART1_RxBufferRd -= sizeof(UART1_RxBuffer); // wap awound
AT_AddNewRxByte(c); // pass the byte onto the AT RX routine
}
}
#ifdef ModemHandShaking
HardwareFlowControl(ModemUart); // tell em to hold it - if need be
#endif
//
AT_Stage(AT_Idle); //
#else
if (PPP.Stage != PPPS_None) //
{ //
AT.Retries = 0; //
u16_Put(&AT.Retry_Timer, 0); //
return; // PPP is busy
} //
// **********************************
// get any new data from the PPP uart
if (!MainBufferWr_Tx)
{
while (UART1_RxBufferRd != UART1_RxBufferWr)
{
c = (u8)UART1_RxBuffer[UART1_RxBufferRd++]; // get rx'ed byte
if (UART1_RxBufferRd >= sizeof(UART1_RxBuffer)) UART1_RxBufferRd -= sizeof(UART1_RxBuffer); // wap awound
AT_AddNewRxByte(c); // pass the byte onto the AT RX routine
}
}
#ifdef ModemHandShaking
HardwareFlowControl(ModemUart); // tell em to stop sending data if our buffer is full
#endif
// **********************************
if (AT.Stage == AT_Idle) return; //
//
if (u16_Get(&AT.Retry_Timer)) return; // not time to retry
//
if (AT.Retries >= AT_Retries) //
{ //
#ifdef Debug
SendDebugRStr(ATStageStr20);
#endif
AT_Stage(AT_Idle); //
return; //
}
switch (AT.Stage)
{
case AT_Idle : break;
case AT_DialInit1 : SendModemRStr(DialInit1);
u16_Put(&AT.Retry_Timer, AT_Timeout);
AT.Retries++;
#ifdef Debug
SendDebugRStr(DialInit1);
#endif
break;
case AT_DialInit2 : SendModemRStr(DialInit2);
u16_Put(&AT.Retry_Timer, AT_Timeout);
AT.Retries++;
#ifdef Debug
SendDebugRStr(DialInit2);
#endif
break;
case AT_DialInit3 : SendModemRStr(DialInit3);
u16_Put(&AT.Retry_Timer, AT_Timeout);
AT.Retries++;
#ifdef Debug
SendDebugRStr(DialInit3);
#endif
break;
case AT_Dial : SendModemRStr(DialStr);
u16_Put(&AT.Retry_Timer, AT_Dial_Timeout);
AT.Retries++;
#ifdef Debug
SendDebugRStr(DialStr);
#endif
break;
case AT_PPP : AT_Stage(AT_Disc1); // start disconnect sequence
u16_Put(&AT.Retry_Timer, 2000); // 2 second wait
break;
case AT_Disc1 : SendModemStr("+++"); // get modem in command mode
u16_Put(&AT.Retry_Timer, AT_Timeout); //
AT.Retries++; //
#ifdef Debug
SendDebugStr("+++\n");
#endif
break;
case AT_Disc2 : SendModemStr("ATH\n"); // tell modem to hang up
u16_Put(&AT.Retry_Timer, AT_Timeout); //
AT.Retries++; //
#ifdef Debug
SendDebugStr("ATH\n");
#endif
break;
default : AT_Stage(AT_Idle);
break;
}
#endif
// **********************************
}
//*************************************************************************************
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -