aaaa

Dependencies:   SeeedStudioTFTv2 TFT_fonts mbed

Fork of Seeed_TFT_Touch_Shield by Bhavik Bhuta

Modem.cpp

Committer:
bhavk11
Date:
2014-11-03
Revision:
13:331f8235ea72
Parent:
11:575dfd388778

File content as of revision 13:331f8235ea72:

#include "Modem.h"

void cleanBuffer(char *buffer, int count)
{
    for(int i=0; i < count; i++) {
        buffer[i] = '\0';
    }
}

Modem::Modem(PinName tx, PinName rx, int baudRate,char *default_number):serial_modem(tx,rx)
{
    this->default_number = default_number;
//    serial_modem.baud(baudRate);
    buffer_p = 0;
    read_trail = false;
    read_buffer[BUF_SIZE]='\0';
    mIndex = 0 ;
    //available types mTypeState = 1 RING  mTypeState = 2 SMS
    mTypeState = 0 ;
    cleanBuffer(messageBuffer, SMS_MAX_LENGTH);
}


/***********************************************
Utility/debug Functions
***********************************************/
void Modem::copy_msg(){
    strcpy(messageCopyBuffer, messageBuffer);
    cleanBuffer(messageBuffer, SMS_MAX_LENGTH);
    mTypeState = 0;
    mIndex = 0;
}

int Modem::updateBuffer(char c){

    int messageType = MESSAGE_NONE;
    if(mTypeState == 0){
        if(c == 'R'){
            mTypeState = 01 ;    
        }else if (c == '+'){
            mTypeState = 11 ;
        }  
    }
    /*  Handling the SMS MESSAGE */
    else if (mTypeState == 11){
        if(c != 'C'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 12 ;  
        }
    }
    else if (mTypeState == 12){
        if(c != 'M'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 13 ;  
        }
    }
    else if (mTypeState == 13){
        if(c != 'T'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 14 ;  
        }
    }
    else if (mTypeState == 14){
        if(c != ':'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 15 ; 
            messageBuffer[mIndex++] = '+';
            messageBuffer[mIndex++] = 'C';
            messageBuffer[mIndex++] = 'M';
            messageBuffer[mIndex++] = 'T';
            messageBuffer[mIndex++] = ':';
//            serial_modem.puts("AT\r\n");
//            check_AT(); 
        }
    }
    else if (mTypeState == 15){
        messageBuffer[mIndex] = c ;
        //next index
        mIndex = (mIndex + 1) % SMS_MAX_LENGTH ;
        if(c != '\n'){
            mTypeState = 15 ;     
        }else {
            mTypeState = 16 ;  
        }
    }
    else if (mTypeState == 16){
        messageBuffer[mIndex] = c ;
        //next index
        mIndex = (mIndex + 1) % SMS_MAX_LENGTH ;
        if(c != '\n'){
            mTypeState = 16 ;     
        }else {
            mTypeState = 0 ;
            messageBuffer[mIndex] = '\0' ;
            messageType = MESSAGE_SMS ; 
//            strcpy(messageCopyBuffer,messageBuffer);
//            cleanBuffer(messageBuffer, SMS_MAX_LENGTH);
            mIndex = 0 ;   
        }
    }
    
    /*Handling the RING*/
    else if (mTypeState == 01){
        if(c != 'I'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 02 ;  
        }
    }else if (mTypeState == 02){
        if(c != 'N'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 03 ;  
        }
    }else if (mTypeState == 03){
        if(c != 'G'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 0 ;
            messageType = MESSAGE_RING ;  
        }
    }
    return messageType;
}


/*
int Modem::updateBuffer(char c){
//    messageBuffer[mIndex] = c ;
//    mIndex = (mIndex + 1) % SMS_MAX_LENGTH ;
    int messageType = MESSAGE_NONE;
//    if(mIndex == 0 ){
//        cleanBuffer(messageBuffer, SMS_MAX_LENGTH);    
//    }
    if(mTypeState == 0){
        if(c == 'R'){
            mTypeState = 01 ;    
        }else if (c == '+'){
            mTypeState = 11 ;
        }  
    }
//     Handling the SMS MESSAGE 
    else if (mTypeState == 11){
        if(c != 'C'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 12 ;  
        }
    }
    else if (mTypeState == 12){
        if(c != 'M'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 13 ;  
        }
    }
    else if (mTypeState == 13){
        if(c != 'T'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 14 ;  
        }
    }
    else if (mTypeState == 14){
        if(c != ':'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 15 ; 
            messageBuffer[mIndex++] = '+';
            messageBuffer[mIndex++] = 'C';
            messageBuffer[mIndex++] = 'M';
            messageBuffer[mIndex++] = 'T';
            messageBuffer[mIndex++] = ':'; 
            messageType = MESSAGE_SMS ; 
        }
    }
    else if (mTypeState == 15){
        messageBuffer[mIndex] = c ;
        //next index
        mIndex = (mIndex + 1) % SMS_MAX_LENGTH ;
        if(c != '\n'){
            mTypeState = 15 ;     
        }else {
            mTypeState = 16 ;  
        }
    }
    else if (mTypeState == 16){
        messageBuffer[mIndex] = c ;
        //next index
        mIndex = (mIndex + 1) % SMS_MAX_LENGTH ;
        if(c != '\r'){
            mTypeState = 16 ;     
        }else {
            mTypeState = 0 ;
//            messageType = MESSAGE_SMS ;    
        }
    }
    
//    /Handling the RING
    else if (mTypeState == 01){
        if(c != 'I'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 02 ;  
        }
    }else if (mTypeState == 02){
        if(c != 'N'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 03 ;  
        }
    }else if (mTypeState == 03){
        if(c != 'G'){
            mTypeState = 0 ;     
        }else {
            mTypeState = 0 ;
            messageType = MESSAGE_RING ;  
        }
    }
    
    
    return messageType;*/
//}

int Modem::loopHandle(void)
{
    char gprsBuffer[100];
    int i;
    char *s = NULL;
    while(serial_modem.readable()) {
        char c = serial_modem.getc();
    }
    wait(0.5);
START:
    cleanBuffer(gprsBuffer,100);
    i = 0;
    while(1) {
        if(serial_modem.readable()) {
            timeCnt.start();  // start timer
            while(1) {
                while (serial_modem.readable()) {
                    char c = serial_modem.getc();
                    if (c == '\r' || c == '\n') c = '$';
                    gprsBuffer[i] = c;
                    i++;
                    if(i > 100) {
                        i = 0;
                        break;
                    }
                }
                if(timeCnt.read() > 2) {          // time out
                    timeCnt.stop();
                    timeCnt.reset();
                    break;
                }
            }
            break;
        }
    }
    if(NULL != strstr(gprsBuffer,"RING")) {
        return MESSAGE_RING;
    } else if(NULL != (s = strstr(gprsBuffer,"+CMT"))) { //SMS: $$+CMTI: "SM",24$$
        if(NULL != (s = strstr(gprsBuffer,"+32"))) {
            s += 6;
            int i = 0;
            cleanBuffer(messageBuffer,SMS_MAX_LENGTH);
            while((*s != '$')&&(i < SMS_MAX_LENGTH-1)) {
                messageBuffer[i++] = *(s++);
            }
            messageBuffer[i] = '\0';
            return MESSAGE_SMS;
        } else {
            goto START;
        }
    } else {
        goto START;
    }
}


void Modem::clean_buffer()
{
    int i = 0;
    for(i = 0 ; i < BUF_SIZE ; i ++) {
        read_buffer[i] = '\0';
    }
}

void Modem::reset_buffer()
{
    buffer_p = 0;
    clean_buffer();
}

void Modem::debug_cmd_buffer()
{
//    TFT.printf("[DEBUG] ");
    int i = 0 ;
    for(i = 0 ; i < BUF_SIZE ; i ++) {
//        TFT.putc(read_buffer[i]);
    }
//    TFT.printf("\r\n");
}

int Modem::find_pattern_end(char *pattern, char *buffer, int size)
{
    int i = 0;
    int final_state = strlen(pattern);
    int state = 0;
    for (i = 0; i < size; i++) {
        char current = buffer[i];
        if (pattern[state] == current) {
            state += 1;
            continue;
        }
        if (state == final_state) {
            return i;
        }
        state = 0;
    }

    return -1;
}

/*******************************************************
Control/Init/Setup Functions for SeedsStudto GPRS modem
********************************************************/

int Modem::init()
{
    int i = 0;
    int ret = 0 ;
    for(i = 0 ; i < 10 ; i++) {
        ret = check_AT();
        wait(1);
    }

    if(ret) {
        ret = check_PIN();
    }
    if(ret) {
        ret = setup_SMS();
    }
    return ret;
};

int Modem::check_AT()
{
    int ret = sendCmdWaitResp("AT\r\n","OK", 5);
    if(ret == 0) {
        return -1 ;
    }

    return 1;
}

int Modem::check_PIN()
{
    int ret = sendCmdWaitResp("AT+CPIN?\r\n","+CPIN: READY", 5);

    //debug code
//    debug_cmd_buffer();

    if(ret == 0) {
        return -1 ;
    }

    return 1;
}

int Modem::setup_SMS()
{
//    sendCmdWaitResp("AT+CPMS=\"SM\",\"BM\"\r\n", "OK", 5);
//    int ret = sendCmdWaitResp("AT+CNMI=2,2\r\n", "OK", 5);
    int ret = 1 ;
    if(ret) {
        ret = sendCmdWaitResp("AT+CMGF=1\r\n","OK", 5);
    }
    //debug code
//    debug_cmd_buffer();
    if(ret == 0) {
        return -1 ;
    }

    return 1;
}

/***********************************************
Start of Primary Interface Functions
***********************************************/

int Modem::call_phone(char* number)
{
    //enable optional caller presentation
    sendCmdWaitResp("AT+COLP=1\r\n","OK", 5);
    //send actual call
    wait(1);
//    debug_cmd_buffer();
    int ret = 0 ;
    char temp[30];

    if(number == NULL) {
        snprintf(temp, 30, "\r\nATD%s;\r\n",default_number);
    } else {
        snprintf(temp, 30, "\r\nATD%s;\r\n",number);
    }
    ret = sendCmdWaitResp(temp,"OK", 5);
//    ret = sendCmdWaitResp("\r\nATD+13174806512;\r\n","OK", 5);
    //debug code
//    debug_cmd_buffer();

    if(ret == 0) {
        return -1 ;
    }
    return ret ;
};

void Modem::hangup_phone()
{
    int ret = sendCmdWaitResp("ATH\r\n","OK", 5);
    wait(1);
}

void Modem::recv_phone()
{
    int ret = sendCmdWaitResp("ATA\r\n","OK", 5);
}

void Modem::get_clck(char* msg, int size)
{
    int ret = sendCmdWaitResp("AT+CCLK?\r\n","OK", 5);
    //if returned OK
//    debug_cmd_buffer();
    if(ret == 1) {
        char *pattern = "+CCLK:";
        int index = find_pattern_end(pattern, read_buffer, BUF_SIZE);
        int state = 0;
        int curr = index + 2;
        int end = curr + 17 ;
        while(curr < end) {
            msg[state]=read_buffer[curr];
            state++;
            curr++;
        }
        msg[state] = '\0';
    }
}

int Modem::send_sms(char* number, char* msg)
{
    char temp[60];
//    while(read_device_ready()) {
//        char c = read_device();
//    }

    if(number == NULL) {
        snprintf(temp, 60, "AT+CMGS=\"%s\"\r\n",default_number);
    } else {
        snprintf(temp, 60, "AT+CMGS=\"%s\"\r\n",number);
    }

    sendCmdWaitResp(temp, ">", 5);
//    debug_cmd_buffer();
    wait(3);
    //now write the actual message
    serial_modem.puts(msg);
//    write_device_str(msg);
    //final ctrl+z character in ascii
//    write_device((char)0x1a);
    serial_modem.putc((char)0x1a);

    return 1 ;
}

void Modem::recv_sms(char* msg, int msg_size ,int index)
{
    char temp[30];
    snprintf(temp, 30, "AT+CMGR=%d\r\n",index);
    read_trail = true;
    int ret = sendCmdWaitResp("AT+CMGL=\"ALL\"\r\n","OK", 30);
    read_trail = false;
    wait(3);

//    debug_cmd_buffer();
    //if returned OK
//    if(ret == 1) {
    char *pattern = "+CMT:";
    int in = find_pattern_end(pattern, read_buffer, BUF_SIZE);
    int state = 0;
    int curr = in ;
    int end = BUF_SIZE ;
    while(curr < end) {
        msg[state]=read_buffer[curr];
        state++;
        curr++;
    }
    msg[state] = '\0';

//    }
    wait(1);
//    ret = sendCmdWaitResp("AT+CMGD=1,4\r\n","OK", 5);
}

/***********************************************
Start of Low Level Functions
***********************************************/

bool Modem::read_device_ready()
{
    return serial_modem.readable();
}

void Modem::cls()
{
//    TFT.locate(0,0);
//    TFT.cls();

}

char Modem::read_device()
{
    return serial_modem.getc();
}

int Modem::write_device(char c)
{
    int ret = 0;
    while(!serial_modem.writeable()) {
        //wait until writeable
    }
    ret = serial_modem.putc(c);
    if(ret != -1)
        return 0;
    return ret;
};


int Modem::write_device_str(char* str)
{
    int ret = 0;
    while(!serial_modem.writeable()) {
        //wait until writeable
    }

    ret = serial_modem.puts(str);
    if(ret != -1)
        return 0;

    return ret;
}

int Modem::sendCmdWaitResp(char* cmd, char* response, int timeout)
{
    //reset buffer pointer
    reset_buffer();
    //send command and wait until respose
    write_device_str(cmd);

    //wait
    Timer my_timer;
    my_timer.start();
    float start = my_timer.read();
    float elapsed = 0 ;

    int expected_resp_len = strlen(response);
    int curr_len = 0 ;
    while(1) {
        //ok start waiting game ;)
        if(read_device_ready()) {
            char rec_char = read_device();
//            pc.putc(rec_char);
            curr_len++;
            if(rec_char != response[curr_len - 1]) {
                //we haven't recieved expected response
                //reset
                curr_len = 0 ;
            }
            //update characters read so far in to the buffer (circular)
            read_buffer[buffer_p] = rec_char;
            buffer_p = (buffer_p + 1) % BUF_SIZE;

            if(!read_trail && curr_len == expected_resp_len) {
                //at this point response is matched and we have waited for the length of response
                return 1 ;
            }
        }

        elapsed = my_timer.read() - start;
        if(elapsed > timeout) {
            //we have waited long enough to succeed, but failed
            break;
        }
    }


    while(serial_modem.readable()) {      // display the other thing..
        char c = serial_modem.getc();
        //if we enabled reading trailing characters -> read them onto buffer
        if(read_trail) {
            read_buffer[buffer_p] = c;
            buffer_p = (buffer_p + 1) % BUF_SIZE;
        }
    }
    return 0 ;
}