No cost streams

Interesting! I looked at the Sanguino.zip, and not only is the Print class supported, but someone has already added my original suggestion for streaming support! :slight_smile:

    inline Print &operator <<(char arg) {print(arg); return *this;}
    inline Print &operator <<(const char *arg) {print(arg); return *this;}
    inline Print &operator <<(uint8_t arg) {print(arg); return *this;}
    inline Print &operator <<(int arg) {print(arg); return *this;}
    inline Print &operator <<(unsigned int arg) {print(arg); return *this;}
    inline Print &operator <<(long arg) {print(arg); return *this;}
    inline Print &operator <<(unsigned long arg) {print(arg); return *this;}

You may be able to use << style streaming without doing anything!

Mikal

Yep, this person is me! And it did not work…

But this piece of code is not present in the arduino core, and it works with this this core… I’m lost.

Print class supported: you mean that I don’t need to copy the line at the top of the sketch, and that I can use directly the operator << ?

It does not work:

In function ‘void loop()’:
error: no match for ‘operator<<’ in 'Serial << “Some data” ’

If your core contains Print.h and Print.cpp you should be able to use <<. Originally I thought you had to add the 7 lines to Print.h, but later I realize that inserting the (single) template line at the top of your sketch would work just as well without having to change Print.h.

I doubt if you can do both, so I’d remove the code you added to Print.h and just use the single template line.

With that you should be able to do

Serial << "My name is " << name;

Mikal

I did what you said, and it's still not working..

This core is special: there are 2 serial ports, Serial & Serial1, which can be used both in a sketch.. So there might be some modifications in the code that handle serial I/O...

Originally, the file Print.cpp was empty. On the code I gave you, I put the code of the Arduino core, nothing changed.

Yeah, looking more closely I see that your class HardwareSerial doesn’t inherit from Print so none of the above is going to work. But this might work for you (but only for Serial and Serial1, not for LCDs, etc.):

//alternative option for Franky's Sanguino
template<class T> inline HardwareSerial &operator <<(HardwareSerial &obj, T arg) { obj.print(arg); return obj; }

Mikal

Don't worry about LCD, as mine works with serial port, I'll be able to modify my library once this stream trick works.. And with only 16 characters, I prefer to keep the control on what and where I display..

Here is what I have:

That works fine for me. If you replace

Serial << "My name is";

with

Serial.print("My name is");

does that work? That error message leaves much to be desired.

Mikal

Yep, it works, very strange… It looks like Serial needs to be instanciated somewhere else… But it’s already been in HarwareSerial if I’m right…

What happens with the non-templated version?

//alternative option for Franky's Sanguino
inline HardwareSerial &operator <<(HardwareSerial &obj, const char *arg) { obj.print(arg); return obj; } 

void setup() {
  Serial.begin(38400);
  Serial << "My name is";
}

void loop() {
}

it compiles, but without the "const" before "char *"..

But fixing the arg type to char * makes it impossible to use with non-string variables, such as ints or bytes. Is there a generic type for this kind of case?

Yeah, the generic version is the one with “template”!

Ah, I think I see the problem. Your old HardwareSerial.h doesn’t define a print method for type “const char ”. Here’s what you need to do:

  1. In HardwareSerial.h, change the two instances of “char ” to “const char ”.
  2. In HardwareSerial.cpp, change the two instances of “char c” to “const char c”.
  3. Add the “HardwareSerial” version of the “template…” line either to the bottom of HardwareSerial.h or, if you prefer, at the top of your sketch.
//alternative option for Franky's Sanguino
template<class T> 
inline HardwareSerial &operator <<(HardwareSerial &obj, T arg) 
{ obj.print(arg); return obj; }

I’m guessing that this will work for you, but if not, I have one last trick up my sleeve.

Mikal

I think you will have to release your last trick.. same problem with the general template, instantiated from here..

Oh and the const replacement did not work, as the _uart() function needs a pointer, and the casting does not work..

Don’t give up yet on that idea yet! :slight_smile: Keep the const’s in there but change

    uart_write(_uart, &c[i], 1);

to

    uart_write(_uart, (char *)&c[i], 1);

If that all still doesn’t work – but it will eventually! – dump the template and manually insert the 7

inline HardwareSerial &operator <<(HardwareSerial &obj, char *arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj, char arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj,  uint8_t arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj,  int arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj,  unsigned arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj,  long arg) { obj.print(arg); return obj; }
inline HardwareSerial &operator <<(HardwareSerial &obj,  unsigned long arg) { obj.print(arg); return obj; }

Yeehaa! That works!! Thank you for all your work on this..

Another question: did you think of including the base markers, like hex, dec, bin in the stream? Is it even possible? For what I know about C++, these markers modify all the stream until another marker is found, kind of hard to implement, but maybe by only applying the marker once, on the immediate next value sent on the stream..

Implementing endl newline marker is easy: #define endl "\n"

Yes, it would be nice to have hex and bin manipulators, but that would require substantially more than the “single line” template. I may do it someday if crowds of people beat down my door.

And for other people reading this thread, keep in mind that the last 15 or so posts just deal with Franky’s special Sanguino build. For most people, this is perfectly sufficient:

template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }

I also wrote this up on my Arduino site.

Mikal

Yeah, and I think a dedicated library is worth it, I just wait to learn a bit more about C++ and I start studying this (I'm in the library-making mood these days..)

I will write to Zach Smith, the author of the Sanguino, to give him the modifications of the core code for its 1.4 release.. And that would be cool to have this feature as native in the cores of the arduino 13 IDE..

Nice! This saved many lines of code, and actually made the binary a wee bit smaller :)

Now if only I could get rid of sprintf and strcpy()... I wouldn't have to import stdio.h and I'd save 2k!

sprintf? What do you use this function for? strcpy is naturally available on the arduino, I use it without having to include stdlib or stdio.

I was using it for string concatenation until you made me realize that I get strcat for free in string.h :)

Oh man... if only there were an embedded version of python....

Anyways, I see no reason not to put streams in the default namespace. It takes up no additional flash, and it still allows people use the standard print statements, keeping it's "pseudo-sideways-compatibility" with Processing.

if only there were an embedded version of python....

Pymite answers that request but unfortunately the Arduino's ATmega168 is not up to the task of running it.

--Phil.