Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of AvnetATT_shape_hackathon by
Wnc.cpp
- Committer:
- elmkom
- Date:
- 2016-10-10
- Revision:
- 43:3979ea0a2df3
- Parent:
- 42:8500f0cb2ea5
- Child:
- 44:60008ebffdd4
File content as of revision 43:3979ea0a2df3:
#include "Wnc.h"
#include "mbed.h"
#include <cctype>
#include <string>
#include "config_me.h"
#include "SerialBuffered.h"
extern Serial pc;
DigitalOut mdm_uart2_rx_boot_mode_sel(PTC17); // on powerup, 0 = boot mode, 1 = normal boot
DigitalOut mdm_power_on(PTB9); // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem)
DigitalInOut mdm_wakeup_in(PTC2); // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield
DigitalOut mdm_reset(PTC12); // active high
DigitalOut shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active
DigitalOut mdm_uart1_cts(PTD0);
SerialBuffered mdm(PTD3, PTD2, 512);
bool powerSave = false;
bool firstWake = false;
Wnc::Wnc(void)
{
}
void Wnc::checkPassthrough()
{
if(pc.readable())
{
if(pc.getc() == '~')
passthrough();
}
}
void Wnc::passthrough()
{
pc.printf(">>\r\n");
while(1)
{
char c;
if(pc.readable())
{
c = pc.getc();
pc.putc(c);
if(c == '~')
{
pc.printf("exit\r\n");
break;
}
else if(c == '<')
{
mdm_wakeup_in = 0;
pc.printf("sleep\r\n");
}
else if(c == '>')
{
mdm_wakeup_in = 1;
pc.printf("wake\r\n");
}
else if(c == '}')
{
mdm_uart2_rx_boot_mode_sel = 1;
pc.printf("rx hi\r\n");
}
else if(c == '{')
{
mdm_uart2_rx_boot_mode_sel = 0;
pc.printf("rx low\r\n");
}
else if(c == '^')
{
pc.printf("reboot\r\n");
NVIC_SystemReset();
}
else
{
mdm.putc(c);
}
}
if(mdm.readable())
pc.putc(mdm.getc());
}
}
bool Wnc::isPowerSaveOn()
{
return powerSave;
}
void Wnc::resumePowerSave()
{
mdm_wakeup_in = 0;
}
char* Wnc::read(int timeout_ms)
{
static char response[3200];
int len = 0;
if(timeout_ms > 0) // read until timeout or OK
{
Timer timer;
timer.start();
while ((len < (3200-1)) && (timer.read_ms() < timeout_ms)) {
if (mdm.readable()) {
response[len++] = mdm.getc();
if(len>1 && response[len-2] == 'O' && response[len-1] == 'K')
break;
}
}
}
response[len] = (char)NULL;
pc.printf("{%s}\r\n",response);
return response;
}
char* Wnc::send(const char *cmd, int timeout_ms)
{
char* reply;
while (mdm.readable()) {
mdm.getc();
}
int tries = 4;
while(tries > 0)
{
tries--;
pc.printf("\r\n<%s>",cmd);
const char *pt = cmd;
size_t n = strlen(cmd);
while (n--) {
mdm.putc(*pt++);
};
mdm.putc('\r');
mdm.putc('\n');
reply = read(timeout_ms);
if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
break;
checkPassthrough();
}
return reply;
}
bool Wnc::isModemResponding()
{
char *reply = send("AT",WNC_WAIT_TIME_MS);
if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
return true;
return false;
}
void Wnc::setIn()
{
mdm_wakeup_in.input();
}
void Wnc::toggleWake()
{
mdm_wakeup_in = 0;
wait_ms(2000);
mdm_wakeup_in = 0;
}
int Wnc::init(void) {
mdm_wakeup_in.output();
// disable signal level translator (necessary
// for the modem to boot properly)
shield_3v3_1v8_sig_trans_ena = 0;
// Hard reset the modem (doesn't go through
// the signal level translator)
mdm_reset = 1;
// wait a moment for the modem to react
wait_ms(10);
// Let modem boot
mdm_reset = 0;
// wait a moment for the modem to react
wait(1.0);
// power modem on //off
mdm_power_on = 0; //1;
// insure modem boots into normal operating mode
// and does not go to sleep when powered on
mdm_uart2_rx_boot_mode_sel = 1;
mdm_wakeup_in = 1;
// initialze comm with the modem
mdm.baud(115200);
// clear out potential garbage
while (mdm.readable())
mdm.getc();
mdm_uart1_cts = 0;
// wait a moment for the modem to react to signal
// conditions while the level translator is disabled
// (sorry, don't have enough information to know
// what exactly the modem is doing with the current
// pin settings)
wait(1.0);
// enable the signal level translator to start
// modem reset process (modem will be powered down)
shield_3v3_1v8_sig_trans_ena = 1;
// Give the modem 60 secons to start responding by
// sending simple 'AT' commands to modem once per second.
Timer timer;
timer.start();
while (timer.read() < 60) {
SetLedColor(0x1); //red
if(isModemResponding())
{
SetLedColor(0);
return true;
}
SetLedColor(0); //off
wait_ms(1000 - (timer.read_ms() % 1000));
pc.printf("\r%d",timer.read_ms()/1000);
}
return false;
}
int Wnc::secToTau(int time)
{
/*
0 - value is incremented in multiples of 10 minutes
1 - value is incremented in multiples of 1 hour
2 - value is incremented in multiples of 10 hours
3 - value is incremented in multiples of 2 seconds
4 - value is incremented in multiples of 30 seconds
5 - value is incremented in multiples of 1 minute
*/
if(time/2 < 32)
{
return (0x3<<5)+time/2;
}
else if(time/30 < 32)
{
return (0x4<<5)+time/30;
}
else if(time/60 < 32)
{
return (0x5<<5)+time/60;
}
else if(time/3600 < 32)
{
return (0x1<<5)+time/3600;
}
else if(time/36000 < 32)
{
return (0x2<<5)+time/36000;
}
else
return (0x7<<5);
}
int Wnc::secToActivity(int time)
{
/*
0 - value is incremented in multiples of 2 seconds
1 - value is incremented in multiples of 1 minute
2 - value is incremented in multiples of decihours
7 - value indicates that the timer is deactivated.
*/
if(time/2 < 32)
{
return (0x0<<5)+time/2;
}
else if(time/60 < 32)
{
return (0x1<<5)+time/60;
}
else if(time/36000 < 32)
{
return (0x2<<5)+time/36000;
}
else
return (0x7<<5);
}
void Wnc::setPowerSave(bool on,int t3412,int t3324)
{
if(on)
{
int tau = secToTau(t3412);
int activity = secToActivity(t3324);
mdm_wakeup_in = 0; //allow power sleep mode
powerSave = true;
char cmd[32];
sprintf(cmd,"AT+CPSMS=1,,,%d,%d",tau,activity);
send(cmd, WNC_WAIT_TIME_MS);
}
else
{
mdm_wakeup_in = 1; //disallow power sleep mode
powerSave = false;
send("AT+CPSMS=0", WNC_WAIT_TIME_MS);
}
}
char* Wnc::getIccid()
{
static char iccidBuf[32];
iccidBuf[0] = NULL;
char* reply = send("AT%CCID",500);
int index = 0;
int begin = -1;
int i = 0;
while (reply[index]) { // While there are more characters to process...
if (begin == -1 && isdigit(reply[index])) { // Upon finding a digit, ...
begin = index;
}
if(begin != -1)
{
if(isdigit(reply[index]))
{
iccidBuf[i++] = reply[index];
}
else
{
iccidBuf[i++] = NULL;
return iccidBuf;
}
}
index++;
}
return iccidBuf;
}
void Wnc::wakeFromPowerSave()
{
char *reply;
mdm_wakeup_in = 1;
pc.printf("wake from power save\r\n");
firstWake = true;
// reply = send("AT+CFUN=1", WNC_WAIT_TIME_MS);
// reply = send("AT%CMATT=1", WNC_WAIT_TIME_MS);
// wait(5); // wait to attach
// reply = send("AT+CREG?", WNC_WAIT_TIME_MS);
// reply = send("AT@INTERNET=1", WNC_WAIT_TIME_MS); // Internet services enabled
// reply = send("AT@SOCKDIAL=1", WNC_WAIT_TIME_MS);
}
void Wnc::startInternet()
{
char *reply;
reply = send("ATE1",WNC_WAIT_TIME_MS); // Echo ON
char apn [32];
sprintf(apn,"AT%%PDNSET=1,%s,IP",MY_APN_STR);
reply = send(apn, 2*WNC_WAIT_TIME_MS); // Set APN, cmd seems to take a little longer sometimes
reply = send("AT+CREG?", WNC_WAIT_TIME_MS);
reply = send("AT@INTERNET=1", WNC_WAIT_TIME_MS); // Internet services enabled
reply = send("AT@SOCKDIAL=1", WNC_WAIT_TIME_MS);
}
char* Wnc::ping(char* ip)
{
char cmd[32];
sprintf(cmd,"AT@PINGREQ=\"%s\"",ip);
return send(cmd,WNC_WAIT_TIME_MS);
}
// AT@SOCKCONN=1,"108.244.165.22",5005
bool Wnc::connect(char* ip, int port)
{
char *reply;
if(isModemResponding())
{
reply = send("AT@SOCKCREAT=1", WNC_WAIT_TIME_MS);
if(strlen(reply) == 0 || strstr(reply,"OK") ==0)
return false;
}
char cmd[32];
if(isModemResponding())
{
sprintf(cmd,"AT@SOCKCONN=1,\"%s\",%d",ip,port);
reply = send(cmd,WNC_WAIT_TIME_MS);
if(firstWake)
{
for(int i = 0;i<10;i++)
{
pc.printf("%d",i);
send("AT", WNC_WAIT_TIME_MS);
reply = send("AT+CREG?",WNC_WAIT_TIME_MS);
if(strlen(reply) > 0 && strstr(reply,"2,1") != 0)
{
pc.printf("connected %s",reply);
break;
}
else
{
pc.printf("Unconnected %s",reply);
}
wait(1);
}
}
firstWake = false;
reply = send(cmd,WNC_WAIT_TIME_MS);
if(strlen(reply) == 0 || strstr(reply,"OK") ==0)
return false;
}
return true;
}
void Wnc::disconnect()
{
send("AT@SOCKCLOSE=1", WNC_WAIT_TIME_MS);
}
char* Wnc::encode(int value, char* result, int base)
{
// check that the base if valid
if ( base < 2 || base > 36 ) {
*result = '\0';
return result;
}
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if ( tmp_value < 0 )
*ptr++ = '-';
*ptr-- = '\0';
while ( ptr1 < ptr ) {
tmp_char = *ptr;
*ptr-- = *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
char* Wnc::writeSocket(const char * s)
{
char *reply;
char num2str[6];
size_t sLen = strlen(s);
if (sLen <= 99999)
{
string cmd_str("AT@SOCKWRITE=1,");
encode(sLen, num2str, 10);
cmd_str += num2str;
cmd_str += ",\"";
while(*s != '\0')
{
encode((int)*s++, num2str, 16);
// Always 2-digit ascii hex:
if (strlen(num2str) == 1)
{
num2str[2] = '\0';
num2str[1] = num2str[0];
num2str[0] = '0';
}
cmd_str += num2str;
}
cmd_str += "\"";
reply = send(cmd_str.c_str(), WNC_WAIT_TIME_MS);
}
else
pc.puts("sockwrite Err, string to long\r\n");
return NULL;
}
int Wnc::hex_to_int(char c){
if(c >=97)
c=c-32;
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int Wnc::hex_to_ascii(char h, char l){
int high = hex_to_int(h) * 16;
int low = hex_to_int(l);
return high+low;
}
int Wnc::indexOf(char* str, char c)
{
int index = 0;
while(str[index] != 0)
{
if(str[index] == c)
return index;
index++;
}
return -1;
}
char* Wnc::readSocket()
{
static char data[1000];
int i = 0;
char *reply;
reply = send("AT@SOCKREAD=1,1024",1000);
if(strlen(reply) > 0)
{
int pos_start = indexOf(reply,'"');
if(pos_start > 0)
{
pos_start+=1;
int length = indexOf(&reply[pos_start],'"');
if(length > 0)
{
char hi;
char low;
for(i = 0; i < length; i++){
if(i % 2 != 0){
low = reply[pos_start++];
data[i/2] = (char) hex_to_ascii(hi,low);
}else{
hi = reply[pos_start++];
}
}
}
}
}
data[i] = NULL;
return data;
}
