Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ void setup() {
}
```

## Using cin an cout
When you include this header file you automatically get cin and cout based on Serial. There isn't yet a way to select you own device at runtime. Using cin and cout is
## Using ```cin``` an ```cout```
When you include this header file you automatically get cin and cout based on ```Serial```. See below for how to specify your own device. Here's an example sketch using ```cin``` and ```cout``` .

```c++
#include <ArduinoSTL.h>
Expand All @@ -47,10 +47,40 @@ void loop() {
}
}
```
## Changing the Serial Port
You can change what serial port that ```cin```, ```cout``` and ```printf()``` use. You can use built-in serial ports (e.g. ```Serial1``` on Leonardo) or you can use software serial ports that implement ```Stream```.

### Using a Built-in Port
In ```src/ArduinoSTL.cpp``` change the value of ```ARDUINOSTL_DEFAULT_SERIAL```. Leave the other defaults uncommented.

### Using a SoftwareSerial port.
Set ```ARDUINO_DEFAULT_SERAL``` to ```NULL```. Comment out the other defaults.

Here's an example sketch that uses SofwareSerial:

```c++
#include <ArduinoSTL.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(0, 1);

namespace std {
ohserialstream cout(mySerial);
ihserialstream cin(mySerial);
}

void setup() {
mySerial.begin(9600);
ArduinoSTL_Serial.connect(mySerial);
}
```

## Avoiding Instantiation of ```cin``` and ```cout```
Comment out ```ARDUINOSTL_DEFAULT_CIN_COUT``` and nothing will be instantiated. You must comment out this flag if you intend to select a non-default serial port. There's no appreciable overhead for using ```printf()``` so you cannot currently avoid initializaing it.

## Known Issues

Printing of floats and doubles using cout ignores format specifiers.
Printing of floats and doubles using ```cout``` ignores format specifiers.

uClibc seems to be fairly complete. Strings and vectors both work, even with the limited amount of heap available to Arduino. The uClibc++ status page can be found here:

Expand Down
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=ArduinoSTL
version=1.0.5
version=1.1.0
author=Mike Matera <matera@lifealgorithmic.com>
maintainer=Mike Matera <matera@lifealgorithmic.com>
sentence=A port of uClibc++ packaged as an Arduino library.
paragraph=This library includes important C++ functions, including cout and cin, printf and scanf. It also includes STL containers like vector and algorithms.
paragraph=This library includes important C++ functions, including cout and cin, printf and scanf. It also includes STL containers like vector and algorithm.
category=Other
url=https://github.com/mike-matera/ArduinoSTL
architectures=avr,samd
Expand Down
54 changes: 30 additions & 24 deletions src/ArduinoSTL.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
#include <ArduinoSTL.h>
#include <Arduino.h>

//
// Configuration Help
//
// If you're using a serial port that's statically declared somewhere in
// Arduino (e.g. Serial1 on Leonardo)
// 1. Set ARDUINOSTL_SERIAL_DEVICE to your device
// 2. Uncomment the ARDUINOSTL_DEFAULT_CIN_COUT flag.
//
// If you're using a sofware serial port:
// 1. Set ARDUINOSTL_DEFAULT_SERIAL to NULL
// 2. Comment out ARDUINOSTL_DEFAULT_CIN_COUT
// Your sketch must contain delarations of cin and cout, and a call to
// ArduinoSTL_serial.connect().
//

#define ARDUINOSTL_DEFAULT_SERIAL Serial
#define ARDUINOSTL_DEFAULT_CIN_COUT

using namespace std;

#ifdef ARDUINOSTL_DEFAULT_CIN_COUT
// Create cout and cin.. there doesn't seem to be a way
// to control what serial device at runtime. Grr.
namespace std
{
ohserialstream cout(Serial);
ihserialstream cin(Serial);
ohserialstream cout(ARDUINOSTL_DEFAULT_SERIAL);
ihserialstream cin(ARDUINOSTL_DEFAULT_SERIAL);
}
#endif // ARDUINOSTL_DEFAULT_CIN_COUT

/*
* Implementation of printf() is highly libc dependent.
Expand All @@ -21,22 +41,8 @@ namespace std
* ARDUINO_ARCH_* - ARMs are probably the same as above.
*/
#if defined(ARDUINO_ARCH_AVR)
//
// This is a hack to make C stdio work on "Serial" without
// having to be manually initialized. It works becuase I can
// call a constructor before setup().
//
class __Arduino_STDIO_hack {
public:
__Arduino_STDIO_hack(Stream *u);
Stream *getUart() {
return uart;
}
private:
Stream *uart;
};

static __Arduino_STDIO_hack __stdio_wrapper(&Serial);
ArduinoSTL_STDIO ArduinoSTL_Serial(ARDUINOSTL_DEFAULT_SERIAL);

// arduino_putchar(char, FILE*)
// Output a single character to the serial port.
Expand All @@ -46,7 +52,7 @@ static __Arduino_STDIO_hack __stdio_wrapper(&Serial);
// automatically addes a \r when it sees a \n
//
static int arduino_putchar(char c, FILE* f) {
Stream *uart = __stdio_wrapper.getUart();
Stream *uart = ArduinoSTL_Serial.getUart();
if (c == '\n') uart->write('\r');
return uart->write(c) == 1? 0 : 1;
}
Expand All @@ -57,18 +63,18 @@ static int arduino_putchar(char c, FILE* f) {
// returns: The character or -1 on a read error
//
static int arduino_getchar(FILE *f) {
Stream *uart = __stdio_wrapper.getUart();
Stream *uart = ArduinoSTL_Serial.getUart();
while (! uart->available()) { /* wait */ }
return uart->read();
}

// Initialize STDIO using a pointer to whatever Serial is.
// Serial.begin() must be called at some point.
//
__Arduino_STDIO_hack::__Arduino_STDIO_hack(Stream *u) {
void ArduinoSTL_STDIO::connect(Stream *u) {
if (file != NULL)
free (file);
uart = u;
fdevopen(arduino_putchar, arduino_getchar);
file = fdevopen(arduino_putchar, arduino_getchar);
}

#else
#warning "printf() will not be functional on this platform."
#endif
35 changes: 34 additions & 1 deletion src/ArduinoSTL.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,37 @@ namespace std
extern ihserialstream cin;
}

#endif
#if defined(ARDUINO_ARCH_AVR)

class ArduinoSTL_STDIO {
public:
// Initialize STDIO using a pointer to whatever Serial is.
// Serial.begin() must be called at some point.
ArduinoSTL_STDIO(Stream *u) : file(NULL) {
connect(u);
}

ArduinoSTL_STDIO(Stream &u) : file(NULL) {
connect(u);
}

Stream *getUart() {
return uart;
}

void connect(Stream *u);

inline void connect(Stream &u) {
connect(static_cast<Stream*>(&u));
}

private:
Stream *uart;
FILE *file;
};

extern ArduinoSTL_STDIO ArduinoSTL_Serial;

#endif // ARDUINO_ARCH_AVR

#endif // ARDUINOSTL_M_H