Skip to content

Commit

Permalink
Merge pull request #21 from mike-matera/change-serial-device
Browse files Browse the repository at this point in the history
Enable changing the serial device.
  • Loading branch information
mike-matera committed Apr 4, 2018
2 parents f4a8c47 + bb13fa8 commit 4885bb3
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 30 deletions.
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

0 comments on commit 4885bb3

Please sign in to comment.