Pages: 1 2 [3] 4   Go Down
Author Topic: No cost streams  (Read 4604 times)
0 Members and 1 Guest are viewing this topic.
Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Code:
//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
« Last Edit: February 11, 2009, 03:46:40 pm by mikalhart » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 51
Developer of the MIDI library
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged


Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Don't give up yet on that idea yet!  smiley Keep the const's in there but change

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

to

Code:
   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

Code:
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; }
« Last Edit: February 11, 2009, 04:53:24 pm by mikalhart » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 51
Developer of the MIDI library
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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"
« Last Edit: February 11, 2009, 05:33:39 pm by Franky » Logged


Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
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
« Last Edit: February 11, 2009, 05:44:45 pm by mikalhart » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 51
Developer of the MIDI library
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged


Raleigh, NC
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 51
Developer of the MIDI library
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Raleigh, NC
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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.
« Last Edit: February 14, 2009, 03:47:12 pm by JustinHoMi » Logged

New Zealand
Offline Offline
God Member
*****
Karma: 0
Posts: 999
Arduino pebbles
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

San Francisco
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So I found myself wanting to have line feeds after printing my variables for easier use over the serial monitor.  I added one more piece (show here in bold) to Mikal's code as to make it a bit more like the C++ std library in this regard:

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

enum EndLineCode {  endl  };

inline Print &operator <<(Print &obj, EndLineCode arg) { obj.print(13, BYTE); obj.print(10, BYTE); return obj; }

With this you can do something like:

Quote
  Serial << "Value printing on line one: " << value << endl << "Value2 printing on line two: " << value2 << endl;

Which prints out

Quote
Value printing on line one: 100
Value2 printing on line two: 200

This also takes the same amount of space as just writing a println (or writing out the CR & LF combo separately), so there's no overhead with doing it this way.  

I could add to the playground page if it's useful.

Cheers,
Paul
« Last Edit: April 17, 2009, 04:23:51 am by pvercello » Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very good stuff.  I'll add it to my web page and the playground.  Although wouldn't this be better:

Code:
inline Print &operator <<(Print &obj, EndLineCode arg) { obj.println();  return obj; }

?

Mikal
« Last Edit: April 17, 2009, 09:13:17 pm by mikalhart » Logged

San Francisco
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Ah, yeah.  I didn't realize you couldn't call println with no arguments.  Yes, that's better.

-Paul
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks to Paul V. and Ben Combee for their useful suggestions on how to support line endings (C++ "endl") and internal format manipulators, respectively, we now have a bona fide Streaming library.

With it, you can now write code like this:

Code:
 Serial << "A is " << lettera << "." << endl;
  lcd << "The current date is " << day << "-" << month << "-" << year << "." << endl;
  
  eth << "You can use modifiers too, for example:" << endl;
  Serial << _BYTE(lettera) << " is " << _HEX(lettera) << " in hex. " << endl;

And thanks very much for all the Arduinians who have used and commented on Streaming.  Cool stuff.

The new library is available at http://arduiniana.org/libraries/streaming.

Mikal
« Last Edit: April 17, 2009, 09:23:56 pm by mikalhart » Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6250
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduino version 0018 has added the capability to print floats specifying the number of digits after the decimal point.
Here is a modification to Mikal's library to support this.
Code:
/*
Streaming.h - Arduino library for supporting the << streaming operator
Copyright (c) 2009 Mikal Hart.  All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef ARDUINO_STREAMING
#define ARDUINO_STREAMING

#include <WProgram.h>

#define STREAMING_LIBRARY_VERSION 3  // modifed to support floating point digit argument - mem 20 Feb 2010

// Generic template
template<class T>
inline Print &operator <<(Print &stream, const T arg)
{ stream.print(arg); return stream; }

struct _BASED
{
  long val;
  int base;
  _BASED(long v, int b): val(v), base(b)
  {}
};

struct _FLOAT
{
  float val;
  int digits;
  _FLOAT(double v, int d): val(v), digits(d)
  {}
};

#define _HEX(a)     _BASED(a, HEX)
#define _DEC(a)     _BASED(a, DEC)
#define _OCT(a)     _BASED(a, OCT)
#define _BIN(a)     _BASED(a, BIN)
#define _BYTE(a)    _BASED(a, BYTE)

// Specialization for class _BASED
// Thanks to Arduino forum user Ben Combee who suggested this
// clever technique to allow for expressions like
//   Serial << _HEX(a);

inline Print &operator <<(Print &obj, const _BASED &arg)
{ obj.print(arg.val, arg.base); return obj; }

// Specialization for class _FLOAT
inline Print &operator <<(Print &obj, const _FLOAT &arg)
{ obj.print(arg.val, arg.digits); return obj; }


// Specialization for enum _EndLineCode
// Thanks to Arduino forum user Paul V. who suggested this
// clever technique to allow for expressions like
//   Serial << "Hello!" << endl;

enum _EndLineCode { endl };

inline Print &operator <<(Print &obj, _EndLineCode arg)
{ obj.println(); return obj; }

#endif
Logged

Pages: 1 2 [3] 4   Go Up
Jump to: