dmays / google-code-arduino

Automatically exported from code.google.com/p/arduino
Other
0 stars 0 forks source link

Base Class for Serial Objects #60

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I'd like to propose making an abstract base class for all of the serial
objects/libraries.

This will make other library developers a little happier when it comes to
designing interfaces to serial devices.  End users will be happier too
since they will now have some input functions as well.

Library developers will have the ability to use polymorphism to talk to the
inherited Serial class - enabling easy use of ANY of the Serial classes
(and any new ones that come about).

This means that the only changes that any existing Serial objects need to
make are to inherit this class (Print comes along for the ride) and add a
new function called peek().

peek() returns the top character/byte from the serial input buffer.  This
enables a "try before you buy" method of seeing what's in the queue. 
Essential for input methods.

For only 84 bytes more of code space, you will now have getnumber() and
getstring() added to each and every serial object.

I've attached the patches for HardwareSerial.cpp/.h as well as the full
SerialComm.cpp/.h files.  (I also have modified versions of
NewSoftSerial.cpp/.h available).

Files can also be downloaded at: http://mediafire.com/arduino

More information here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1245549766

Original issue reported on code.google.com by rogue.bh...@gmail.com on 22 Jul 2009 at 6:59

Attachments:

GoogleCodeExporter commented 9 years ago
While on the topic of polymorphism, I would actually love to see more base 
classes.

Arduino is all about simplicity, right?

What could be simpler for the user that knowing that all temperature sensors 
has a 
readTemperature() function, or that all motors has setSpeed(), run() and stop() 
functions (and more).

Many libraries needs to be updated to function. A simple interface for 
Updateable 
could be beneficial.
This is a pitfall I myself has fallen into. I have some libraries with a 
function 
named check() and some with a update().

Some of you may know I fight for Hardware Abstraction Libraries: 
http://www.arduino.cc/playground/Code/HardwareAbstraction

The more well designed interfaces we have, the better the overall API and user 
experience.

Original comment by alexanderbrevig on 22 Jul 2009 at 11:56

GoogleCodeExporter commented 9 years ago
You seem to be mixing three things here: a new base class, a peek() function, 
and the getstring() / 
getnumber() functions.  The base class seems reasonable enough, especially as 
it doesn't change the interface 
seen by most users.  Can you submit a patch with just that?

The peek() function could be an interesting addition, but I'd like to 
understand the use cases better.  Can you 
post another issue or a message on the developers list explaining why it's 
necessary?

The other functions could make sense, but I'd like to see an API more along the 
lines of what Processing uses 
for its serial library: 
http://processing.org/reference/libraries/serial/index.html.  Do you want to 
see how 
closely we can follow that?

Original comment by dmel...@gmail.com on 29 Jul 2009 at 8:16

GoogleCodeExporter commented 9 years ago
It may seem that things are getting mashed into a single change, but you will
eventually see that they are all very closely related.

#1 The ABC (Abstract Base Class) is the main proposition - I will show below 
that it
only adds 6 bytes to the compiled output.

The ABC will allow for polymorphism - adding to hardware abstraction and code 
clarity.

#2 The peek() method is extremely vital to the serial classes, to keep the data 
queue
in control of the serial class itself, instead of the host program.

Please read the Arduino Developers mailing list for more information on the 
reasoning
for the peek() function.

#3 The input methods can be dropped, if it is bothersome to have them 
incorporated
with the base class.

A library can be written for these methods, but the library would need serial 
base
class in place to be useful (otherwise you're either passing function pointers
around, or you're writing individual libraries for each and every serial/stream 
class).

Code size results
-----------------

Original HardwareSerial from 0016, no modifications:
  '168: 1508 bytes
  Mega: 2402 bytes

SerialBase derived HardwareSerial (no peek() method):
  '168: 1514 bytes
  Mega: 2408 bytes

SerialBase derived HardwareSerial (including peek() method):
  '168: 1568 bytes
  Mega: 2462 bytes

Attached are the patches for HardwareSerial, and the full SerialBase.h (.cpp not
needed anymore because there are no method definitions).  The peek() function is
still included.

Original comment by rogue.bh...@gmail.com on 2 Aug 2009 at 7:42

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by dmel...@gmail.com on 2 Jan 2010 at 4:37

GoogleCodeExporter commented 9 years ago
Will this work with the Ethernet library, or other block/packet oriented 
protocols
likely to be developed in the future?

I noticed there is only a single byte write.  What about the block write?  See 
issue
#164 for some simple changes to the Print class that write in blocks instead of 
one
byte at a time, which greatly improves performance for packet oriented devices.

Any idea how Ethernet will implement peek?

Original comment by paul.sto...@gmail.com on 26 Jan 2010 at 6:09

GoogleCodeExporter commented 9 years ago
I'd like to see the SerialBase ABC implemented as a base for pretty much any 
sort of
serial based communications (i.e. asynchronous serial, synchronous serial, SPI, 
etc.)

A block write would be great to add.  This of course would probably be best 
served by
changing SerialBase from an ABC to a base class, since a block write is not
absolutely necessary (but as we know would likely improve performance on some 
devices).

The peek() method would also benefit from being able to produce a block of data 
from
the device (if possible).  Again, this can't be guaranteed at the lowest level, 
so it
could be virtual and overridden.

The Ethernet library, unless I'm mistaken, REALLY needs some finesse to 
accommodate
more ethernet controllers than the Wiznet W5100.  The peek() method, as the 
Ethernet
library stands, needs to get the first byte from the receive queue off of the 
shared
16KB buffer of the W5100 for whatever socket is being used.

- specifically:
 * get rx read pointer register (Sn_RX_RD0)
 * read data (for peek())
 * *DO NOT* update the rx write pointer (Sn_RS_RD0 through Sn_CR(Sn_CR_RECV))

The SerialBase class should work great with the Ethernet library, although 
there are
logistics to think about (e.g. which socket are we dealing with? maybe
client.selectSocket(x) or such) but there are many ways to skin a cat.  The 
time is
ripe, IMO, because the Ethernet library needs an overhaul anyway.

Original comment by rogue.bh...@gmail.com on 26 Jan 2010 at 11:41

GoogleCodeExporter commented 9 years ago
I've been thinking about this again recently as I've been working on a wireless 
networking library which also uses 
a SPI UART to communicate.

In terms of terminology I'd like to think of this a "Stream" interface.

In regard to the Ethernet library I would imagine the stream would be 
associated with a specific client object 
which already represents a single socket.

Original comment by follower@gmail.com on 22 Apr 2010 at 6:39

GoogleCodeExporter commented 9 years ago
As a concrete example of a class that would benefit from an stream base class, 
TextFinder from the playground 
is a good example:

  http://www.arduino.cc/playground/Code/TextFinder

At the moment each class of stream-based it supports needs to be handled 
separately.

Original comment by follower@gmail.com on 29 Apr 2010 at 4:06

GoogleCodeExporter commented 9 years ago
There are lots of libraries that would benefit from SerialBase.

Firmata
Messenger
X10
XBee
Any one of the serial LCD libraries
Camera328R
TinyGPS (or any GPS library for that matter)
etc...

SerialBase would ensure that they don't get tied down to a particular physical
hardware interface.  As long as the underlying hardware interface class 
implements
SerialBase, that hardware interface becomes instantly accessible to any of the 
child
classes.

----

In my original proposal, I had included some input functions.  I think creating
another base class for input functions would be beneficial for some libraries,
including TextFinder.  Maybe we'll call it SerialInputBase?  Or SerialIOBase?

e.g.
class superGPRSGizmo : public SerialInputBase ...

where SerialInputBase is:
class SerialInputBase : public SerialBase ...

and include a range of functions such as:

getNumber/getValue/getFloat/getInt etc...
getString/getChar/getLine
getArray etc...

Original comment by rogue.bh...@gmail.com on 29 Apr 2010 at 6:34

GoogleCodeExporter commented 9 years ago
I'd suggest adding the begin() and end() methods to the ABC as well. This is the
serial interface I'm currently using (which I have inherited in both 
HardwareSerial
and NewSoftSerial). It does not require any changes to the implementation of
HardwareSerial and NewSoftSerial other than adding an empty end() method to
NewSoftSerial and moving write() in NSS from private to public scope so that 
it's
basic interface is equivalent to HardwareSerial.h.

#ifndef ISerial_h
#define ISerial_h

#include <inttypes.h>
#include "Print.h"

class ISerial : public Print {
public:
    virtual void begin(long baud) = 0;
    virtual void end() = 0;
        virtual uint8_t available(void) = 0;
        virtual int read() = 0;
    virtual void flush() = 0;

    virtual void write(uint8_t byte) = 0;
    using Print::write;

protected:
    ISerial() {}
};

#endif

Original comment by jeff.ho...@gmail.com on 30 Apr 2010 at 2:06

GoogleCodeExporter commented 9 years ago
Being an abstract base class, I wouldn't want to push anything on to the 
subclass
that wasn't absolutely necessary.  IMO, the begin() and end() methods are not
absolutely necessary for the subclasses.

I think the essence of the serial base class should just have methods/properties
which pertain to getting data from/sending data to the serial interface.  How 
the
class is instantiated, or managed, should be up to the subclass.

Here's some more information (a little more in "layman's terms") that I've been
maintaining.  If you guys want to make changes to that page, go ahead (it's an 
open
wiki).

http://www.roguerobotics.com/wikidocs/code/arduino_serial_base_class

Original comment by rogue.bh...@gmail.com on 30 Apr 2010 at 4:32

GoogleCodeExporter commented 9 years ago

Original comment by dmel...@gmail.com on 28 May 2010 at 10:49