Re-writing Adafruit's AF_XPort library for Arduino IDE 1.0

I’ve been attempting to re-write Adafruit’s library AF_XPort, but I’m running into a problem. When I compile my project, the compiler finds the library header itself, but not the library’s depencency on SoftwareSerial.h:

In file included from TwitterFetch.cpp:1:
C:\Users\Chris\Documents\Arduino\libraries\AF_XPort/AF_XPort.h:11:28: error: SoftwareSerial.h: No such file or directory
In file included from TwitterFetch.cpp:1:
C:\Users\Chris\Documents\Arduino\libraries\AF_XPort/AF_XPort.h:18: error: 'SoftwareSerial' does not name a type

This is the beginning of the new AF_XPort.h:

#ifndef _AFXPort_h_
#define _AFXPort_h_

#define ERROR_NONE 0
#define ERROR_TIMEDOUT 2
#define ERROR_BADRESP 3
#define ERROR_DISCONN 4

#include <SoftwareSerial.h>
#include <Arduino.h>

class AF_XPort
{
 private:
  uint8_t rxpin, txpin, resetpin, dtrpin, rtspin, ctspin;
  SoftwareSerial xportserial;
  
 public:
  AF_XPort(uint8_t rx, uint8_t tx, uint8_t reset=0, uint8_t dtr=0, uint8_t rts=0, uint8_t cts=0);
  void begin(uint16_t b);
  ...

I’ve attached the modified library files; the original is downloadable at Ethernet shield. I probably just made a syntax error or something trivial, but my C++ is rusty at best. If I manage to get this fixed, I plan to submit it back to Adafruit.

Edit: changed font styles to code blocks

AF_XPort.h (1.11 KB)

AF_XPort.cpp (3.76 KB)

Include this…

#include <SoftwareSerial.h>

…in the sketch.

That gets me further at least. Now the compiler is complaining about calling the SoftwareSerial constructor from within the AF_XPort constructor:

C:\Users\Chris\Documents\Arduino\libraries\AF_XPort\AF_XPort.cpp: In constructor 'AF_XPort::AF_XPort(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)':
C:\Users\Chris\Documents\Arduino\libraries\AF_XPort\AF_XPort.cpp:3: error: no matching function for call to 'SoftwareSerial::SoftwareSerial()'
C:\Program Files (x86)\arduino-1.0\libraries\SoftwareSerial/SoftwareSerial.h:83: note: candidates are: SoftwareSerial::SoftwareSerial(uint8_t, uint8_t, bool)
C:\Program Files (x86)\arduino-1.0\libraries\SoftwareSerial/SoftwareSerial.h:48: note:                 SoftwareSerial::SoftwareSerial(const SoftwareSerial&)

Here’s the constructor in AF_XPort.cpp:

AF_XPort::AF_XPort(uint8_t rx, uint8_t tx, uint8_t reset, uint8_t dtr, uint8_t rts, uint8_t cts) {
  rxpin = rx;
  txpin = tx;
  xportserial = SoftwareSerial(rxpin, txpin, false);
  resetpin = reset;
  ...
}

I’ve tried the SoftwareSerial() call both with and without the last, optional “false” argument. The uint8_t types match… It seems like it’s not identifying the right SoftwareSerial constructor, but I don’t know why.

AF_XPort::AF_XPort(uint8_t rx, uint8_t tx, uint8_t reset, uint8_t dtr, uint8_t rts, uint8_t cts)
: xportserial( rx, tx, false ) // <— add
{
rxpin = rx;
txpin = tx;
// remove —> xportserial = SoftwareSerial(rxpin, txpin, false);
resetpin = reset;

}

By golly, it compiles! I'll test it more extensively tomorrow, but at least it's that far. Thanks for the help, Coding Badly!

Freaking Java programmers, assuming things about C++...

You are welcome.

xylo04: Freaking Java programmers, assuming things about C++...

Which Java programmers?

Oh, I was trying to refer to myself. I'm a Java programmer by day, and didn't realize C++ used that other syntax. I'm guessing that's to initialize a member object from within a constructor? Anyway, I assumed the syntax would be the same as the SoftwareSerial example, which looked similar enough to Java. I had a hard enough time not writing "new"!

I'm guessing that's to initialize a member object from within a constructor?

A member [u]element[/u]. The syntax also works for data.

In your defense, the syntax is about as intuitive as putting in plain view a great big red mushroom-shaped button labeled "Emergency Stop" that, to shutdown the equipment, must be [u]pulled[/u].

Has anyone been able to get this working?
I am able to compile on IDE 1.0.2 using the above library and tweaks but I cant get any of the xport functions to work.
for example xport.reset() or xport.connect().

I am using the following (modified) example from ladyada:

#include <SoftwareSerial.h>
#include <AF_XPort.h>

//#define IPADDR "207.58.139.246"  //www.ladyada.net
#define IPADDR "10.0.0.99"  //local http server
#define PORT 8008 //non standard port

char linebuffer[256]; // large buffer for storing data

#define XPORT_RXPIN 2
#define XPORT_TXPIN 3
#define XPORT_RESETPIN 4
#define XPORT_DTRPIN 5
#define XPORT_CTSPIN 6
#define XPORT_RTSPIN 7

AF_XPort xport = AF_XPort(XPORT_RXPIN, XPORT_TXPIN, XPORT_RESETPIN, XPORT_DTRPIN, XPORT_RTSPIN, XPORT_CTSPIN);

void setup()  {
  
  Serial.begin(57600);
  xport.begin(57600);
  xport.reset();
  delay(1000);
  Serial.println("Finished Setup...");

}

void loop()
{
  byte ret;

  Serial.println("Connecting...");
  xport.connect(IPADDR, PORT);
  xport.flush(300);
  Serial.println("Getting...");
  xport.println("GET /door/index.html");  

  ret=xport.readline_timeout(linebuffer, 255, 3000); // get first line
  while(ret!=0){
    Serial.println("Output...");
    Serial.print(linebuffer);  
    ret=xport.readline_timeout(linebuffer,255,4000);
  }

  Serial.print("Readline returned: ");Serial.println(ret,HEX);

}

Sorry it's taken a while to respond. Honestly, at some point I got fed up with trying to debug this and bought the Arduino Ethernet Shield. At the time it was just easier. I'm sure it's still possible to use the XPort, so I'll try to revisit this in the future.

Hi

I did not find an updated version of the AF_XPort for the Arduino 1.0.x versions too. And I really want to use my xPort+ Ethernet Shield!
So I took all my science (not much in fact) and modified the code of AF_XPort.cpp file to use SoftwareSerial instead of the old librairies … surprised to me, it was not difficult and 5mn later (yes, I used vi to edit the file) it built successfully. It was too cool to be true …
Since then, I am fighting like hell to have another output than “Timeout on reset”.
I am using the same piece of code I used to have back on arduino-022 and which was working fine … using the regular adafruit code of AF_XPort.
So, here is the modified AF_XPort code:

#include <avr/io.h>
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "AF_XPort.h"

SoftwareSerial xportserial(2,3); // we dont know the pins yet

AF_XPort::AF_XPort(uint8_t rx, uint8_t tx, uint8_t reset, uint8_t dtr, uint8_t rts, uint8_t cts) {
  rxpin = rx;
  txpin = tx;
  resetpin = reset;
  if (resetpin) {
    pinMode(resetpin, OUTPUT);
    digitalWrite(resetpin, HIGH);
  }
  
  dtrpin = dtr;
  rtspin = rts;
  ctspin = cts;
  if (ctspin) {
    digitalWrite(ctspin, HIGH);
    pinMode(ctspin, OUTPUT);
  }
}

void AF_XPort::begin(uint16_t b) {
  //xportserial.setTX(rxpin);
  //xportserial.setRX(txpin);
  xportserial = SoftwareSerial(rxpin,txpin);
  xportserial.begin(b);
}

uint8_t AF_XPort::reset(void) {
  char d;

  if (resetpin) {
    digitalWrite(resetpin, LOW);
    delay(50);
    digitalWrite(resetpin, HIGH);
  }

// wait for 'D' for disconnected
  if (serialavail_timeout(5000)) { // 3 second timeout 
    d = xportserial.read();
    //Serial.print("Read: "); Serial.print(d, HEX);
    if (d != 'D'){
      return ERROR_BADRESP;
    } else {
      return 0;
    }
  }
  return ERROR_TIMEDOUT;
}

uint8_t AF_XPort::disconnected(void) {
  if (dtrpin != 0) {
     return digitalRead(dtrpin);
  } 
  return 0;
}


uint8_t AF_XPort::connect(char *ipaddr, long port) {
  char ret;
  
  xportserial.print('C');
  xportserial.print(ipaddr);
  xportserial.print('/');
  xportserial.println(port);
  // wait for 'C'
  if (serialavail_timeout(3000)) { // 3 second timeout 
    ret = xportserial.read();
    //Serial.print("Read: "); Serial.print(d, HEX);
    if (ret != 'C') {
      return ERROR_BADRESP;
    }
  } else { 
    return ERROR_TIMEDOUT; 
  }
  return 0;
}


// check to see what data is available from the xport
uint8_t AF_XPort::serialavail_timeout(int timeout) {  // in ms
  while (timeout) {
    if (xportserial.available()) {
      if (ctspin) { // we read some stuff, time to stop!
        digitalWrite(ctspin, HIGH);
      }
      return 1;
    }
    // nothing in the queue, tell it to send something
    if (ctspin) {
     digitalWrite(ctspin, LOW);
    }
    timeout -= 1;
    delay(1);
  }
  if (ctspin) { // we may need to process some stuff, so stop now
     digitalWrite(ctspin, HIGH);
  }
  return 0;
}



uint8_t AF_XPort::readline_timeout(char *buff, uint8_t maxlen, int timeout) {
  uint8_t idx;
  char c;

  for (idx=0; idx < maxlen; idx++) {
    buff[idx] = 0;
    if (serialavail_timeout(timeout)) {
      c = xportserial.read();
      //Serial.print(c);    // debugging
      if (c == '\n') {
   return idx;
      } else {
   buff[idx] = c;
      }
    } else {
      // timedout!
      break;
    }
  }
  return idx;
}


// clear out any extra data
void AF_XPort::flush(int timeout) {
  while (serialavail_timeout(timeout)) {
    xportserial.read();
  }
}

// on direct+ and xport's we can toggle a line to disconnect
void AF_XPort::disconnect() {  
  /* digitalWrite(XPORT_DISCONN, LOW);
  delay(20);
  digitalWrite(XPORT_DISCONN, HIGH);*/
}

// print a string from Flash, saves lots of RAM space!
void AF_XPort::ROM_print(const char *pSTR) {
  uint16_t i;  
  for (i = 0; pgm_read_byte(&pSTR[i]); i++) {       
    xportserial.print(pgm_read_byte(&pSTR[i]));  
  } 
}

// all the prints
void AF_XPort::print(uint8_t b) { xportserial.print(b); }
void AF_XPort::print(const char *b) { xportserial.print(b); }
void AF_XPort::print(char b) { xportserial.print(b); }
void AF_XPort::print(unsigned int b) { xportserial.print(b); }
void AF_XPort::print(long b) { xportserial.print(b); }
void AF_XPort::print(long b, int base) { xportserial.print(b, base); }
void AF_XPort::println(void) { xportserial.println(); }
void AF_XPort::println(const char c[]) { xportserial.println(c); }
void AF_XPort::println(uint8_t b) { xportserial.println(b); }
void AF_XPort::println(int b) { xportserial.println(b); }
void AF_XPort::println(long b) { xportserial.println(b); }
void AF_XPort::println(unsigned long b) { xportserial.println(b); }
void AF_XPort::println(long n, int base) { xportserial.println(n, base); }

And here is my code to test (I am using the adafruit Ethernet XPort+ module)

#include <SoftwareSerial.h>
#include <AF_XPort.h>
#include <VirtualWire.h>

#define HTTPPATH "/xPortPost.php?"
#define WEB_HOST "<wonttellyou>"
#define IPADDR "xx.xx.xx.xx"
#define PORT 80

#define XPORT_RXPIN 2
#define XPORT_TXPIN 3
#define XPORT_RESETPIN 4
#define XPORT_DTRPIN 0
#define XPORT_CTSPIN 6
#define XPORT_RTSPIN 0

#define RX_PIN      8
#define LED_PIN     13
#define PIN_BUZZER  10

//*** Channel 1
//Baudrate 57600, I/F Mode 4C, Flow 00
//Port 10001
//Connect Mode : D4
//Send '+++' in Modem Mode enabled
//Show IP addr after 'RING' enabled
//Auto increment source port disabled
//Remote IP Adr: --- none ---, Port 00000
//Disconn Mode : 00
//Flush   Mode : 77

AF_XPort xPortSerial = AF_XPort(XPORT_RXPIN, XPORT_TXPIN, XPORT_RESETPIN, XPORT_DTRPIN, XPORT_RTSPIN, XPORT_CTSPIN);
char linebuffer[256];

uint8_t errno;

void setup(void) {

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  Serial.begin(9600);
  Serial.print("Setup...");
  
  // set the data rate for the SoftwareSerial port
  xPortSerial.begin(57600);
  delay(1000);
  Serial.println("done.");
}

void loop()
{
      httpPost("TOTO");
      delay(5000);
}

int httpPost(char* json)
{
  uint8_t ret;
  char *found=0;

  ret = xPortSerial.reset();
  switch (ret) {
  case  ERROR_TIMEDOUT: 
    { 
      Serial.println("Timed out on reset!"); 
      return 0;
    }
  case ERROR_BADRESP:  
    { 
      Serial.println("Bad respons on reset!");
      return 0;
    }
  case ERROR_NONE: 
    { 
      Serial.println("Reset OK!");
      break;
    }
  default:
    Serial.println("Unknown error"); 
    return 0;
  }
  // time to connect...
  ret = xPortSerial.connect(IPADDR, PORT);
  switch (ret) {
  case  ERROR_TIMEDOUT: 
    { 
      Serial.println("Timed out on connect"); 
      return 0;
    }
  case ERROR_BADRESP:  
    { 
      Serial.println("Failed to connect");
      return 0;
    }
  case ERROR_NONE: 
    { 
      Serial.println("Connected..."); 
      break;
    }
  default:
    Serial.println("Unknown error"); 
    return 0;
  }

  xPortSerial.print("GET "); 
  xPortSerial.print(HTTPPATH); 
  xPortSerial.print(json); 
  xPortSerial.println(" HTTP/1.1");
  Serial.print("GET "); 
  Serial.print(HTTPPATH); 
  Serial.print(json); 
  Serial.println(" HTTP/1.1");
  xPortSerial.print("Host: "); 
  xPortSerial.println(WEB_HOST);
  Serial.print("Host: "); 
  Serial.println(WEB_HOST);
  xPortSerial.println("");
  Serial.println("");

  while (1) {
    // read one line from the xport at a time
    ret = xPortSerial.readline_timeout(linebuffer, 255, 3000); // 3s timeout
    // if we're using flow control, we can actually dump the line at the same time!
    Serial.print(linebuffer);
    if (strstr(linebuffer, "HTTP/1.1 200 OK") == linebuffer)
      ret = 1;

    if (((errno == ERROR_TIMEDOUT) && xPortSerial.disconnected()) ||
      ((XPORT_DTRPIN == 0) &&
      (linebuffer[0] == 'D') && (linebuffer[1] == 0)))  {
      Serial.println("\nDisconnected...");
      return ret;
    }
  }
}

void base64encode(char *s, char *r) {
  char padstr[4];
  char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  uint8_t i, c;
  uint32_t n;

  i = 0;
  c = strlen(s) % 3;
  if (c > 0) { 
    for (i=0; c < 3; c++) { 
      padstr[i++] = '='; 
    } 
  }
  padstr[i]=0;

  i = 0;
  for (c=0; c < strlen(s); c+=3) { 
    // these three 8-bit (ASCII) characters become one 24-bit number
    n = s[c]; 
    n <<= 8;
    n += s[c+1]; 
    if (c+2 > strlen(s)) {
      n &= 0xff00;
    }
    n <<= 8;
    n += s[c+2];
    if (c+1 > strlen(s)) {
      n &= 0xffff00;
    }

    // this 24-bit number gets separated into four 6-bit numbers
    // those four 6-bit numbers are used as indices into the base64 character list
    r[i++] = base64chars[(n >> 18) & 63];
    r[i++] = base64chars[(n >> 12) & 63];
    r[i++] = base64chars[(n >> 6) & 63];
    r[i++] = base64chars[n & 63];
  }
  i -= strlen(padstr);
  for (c=0; c<strlen(padstr); c++) {
    r[i++] = padstr[c];  
  }
  r[i] = 0;
  Serial.println(r);
}

Any help would be very appreciated!
Thanks!

SoftwareSerial xportserial(2,3); // we dont know the pins yet

Then don't declare an instance of SoftwareSerial here.

So, here is the modified AF_XPort code:

Well, half of it, anyway. Where is the header file?

Hi Everyone,

Could any of you get the AF_XPort library work with arduino 1.0?