Pages: [1]   Go Down
Author Topic: New option for HardwareSerial library.  (Read 2554 times)
0 Members and 1 Guest are viewing this topic.
San Pedro, CA.
Offline Offline
Full Member
***
Karma: 3
Posts: 155
My head HURTS!!!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I made a small tweak to the HardwareSerial library (IDE 1.0.1) to have the ability to use only RX, only TX, or both RX and TX (normal operation). The modifications are very simple and easy to use. I've shown the modifications below. Make a copy of Arduino.h, HardwareSerial.h and HardwareSerial.cpp located in folder \arduino-1.0.1\hardware\arduino\cores\arduino\ and save them to a folder somewhere so if you screw up you can copy the old files back to the original folder.

Make the changes where indicated to the files below.

Arduino.h
Code:

// Place the three statements below somewhere around line 20
// with the other #define's that are listed there.

#define RX_TX 0
#define RX_ONLY 1
#define TX_ONLY 2


HardwareSerial.h
Code:

// Change the declaration below (at line 52)
  void begin(unsigned long);

// To this
  void begin(unsigned long, uint8_t mode = RX_TX);


HardwareSerial.cpp
Code:

// Change the definition below (at line 294)
void HardwareSerial::begin(unsigned long baud)

// To this
void HardwareSerial::begin(unsigned long baud, uint8_t mode)

// Located at the end of the same function (above)
// Replace the statements below (at lines 328, 329, 330)
  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);

// With these
  switch (mode)
  {
  case 1:
    sbi(*_ucsrb, _rxen);
    cbi(*_ucsrb, _txen);
    sbi(*_ucsrb, _rxcie);
    break;
  case 2:
    cbi(*_ucsrb, _rxen);
    sbi(*_ucsrb, _txen);
    cbi(*_ucsrb, _rxcie);
    break;
  default:
    sbi(*_ucsrb, _rxen);
    sbi(*_ucsrb, _txen);
    sbi(*_ucsrb, _rxcie);
    break;
  }


If you want keyword highlighting for the new constants, you can add a few lines to \arduino-1.0.1\lib\keywords.txt file, though it is not neccesary.

keywords.txt
Code:

// Right after the line below (at line 1)
# LITERAL1 specifies constants

// Place these three lines (Use tabs here, NOT spaces)
RX_TX
RX_ONLY LITERAL1 Serial_begin
TX_ONLY LITERAL1 Serial_begin


To use the new changes, it's a simple addition to Serial.begin().

Example:
Code:

// Functions the same as it always has
// The receive pin (RXDn) and transmit pin (TXDn) are both controlled by HardwareSerial
Serial.begin(115200);

// Functions the same as above
Serial.begin(115200, RX_TX);

// Only the receive pin (RXDn) is controlled by HardwareSerial
// The transmit pin (TXDn) is free to use as digital I/O
Serial.begin(115200, RX_ONLY);

// Only the transmit pin (TXDn) is controlled by HardwareSerial
// The receive pin (RXDn) is free to use as digital I/O
Serial.begin(115200, TX_ONLY);


I've tested this succesfully using IDE 1.0.1 and the Mega1280/2560 on Serial ports 1, 2 and 3. I think I need to connect two arduinos to check port 0. If someone could test this out and let me know, maybe we could get this in the next build. smiley-wink

Thanks for your time,
DigitalJohnson
« Last Edit: October 02, 2012, 05:45:29 pm by DigitalJohnson » Logged

DigitalJohnson

Offline Offline
Sr. Member
****
Karma: 4
Posts: 327
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

this gets the vote from me,

wish I had thought of it a few months back,
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1832
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I would suggest adding a define for both RX and TX being enabled, rather than rely on '0' enabling both.
Logged

San Pedro, CA.
Offline Offline
Full Member
***
Karma: 3
Posts: 155
My head HURTS!!!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@drjiohnsmith

Thanks, believe it or not, I was running low on available pins on my mega (big project). Need is the mother of...

@MichaelMeissner

I could do that. However, the way it is now, calling Serial.begin(baudrate) without the extra parameter behaves as it normally would. What would be the point of having a #define you don't need to use? I'm not saying it's a bad idea. Being a GOD member I'm sure you've been doing this far longer than I. I always like to learn. So, if it's not to much to ask, what is the benifit of the extra #define?
Logged

DigitalJohnson

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1832
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@MichaelMeissner

I could do that. However, the way it is now, calling Serial.begin(baudrate) without the extra parameter behaves as it normally would. What would be the point of having a #define you don't need to use? I'm not saying it's a bad idea. Being a GOD member I'm sure you've been doing this far longer than I. I always like to learn. So, if it's not to much to ask, what is the benifit of the extra #define?
All a GOD member means is I have made 500 posts since joining the forum.  That and $5 will get me a Carmel Macchiato at Starbucks.

I've been in the compiler business for 30+ years now, mostly on GCC for various ports (powerpc right now), but I have also worked on other compilers.  I tend to prefer when you have a flags argument, that all of the possibilities are enumerated via defines, as that can tell the reader of the code that you really want both RX and TX values.  In your own code, it doesn't matter (except when you come back to the code after being away from it for 6 months or so as I have done at various times over the years).  However I would suggest if you are trying to get the code installed as part of the standard software, that you have such an enumeration.  After all, somebody may see the need to have a 3rd argument, or more flag bits being set.
« Last Edit: October 01, 2012, 04:40:18 pm by MichaelMeissner » Logged

San Pedro, CA.
Offline Offline
Full Member
***
Karma: 3
Posts: 155
My head HURTS!!!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Fair enough answer. Will do. smiley

By the way, any suggestions on name of the third choice? Trying to keep it short and simple, like the other two. I don't know why, but I'm having a massive brain fart right now, can't come up with a simple, short name. smiley-confuse

As a side note, to those that can, this seems like an easy change to the library that gives a very useful option. Maybe on the next build...?

Thanks,
 DJ
« Last Edit: October 01, 2012, 04:42:21 pm by DigitalJohnson » Logged

DigitalJohnson

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1832
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

By the way, any suggestions on name of the third choice? Trying to keep it short and simple, like the other two. I don't know why, but I'm having a massive brain fart right now, can't come up with a simple, short name. smiley-confuse
If it were me, I would probably use RX_TX or TX_RX.  Maybe BOTH_RX_TX or BIDIRECTIONAL.
Logged

San Pedro, CA.
Offline Offline
Full Member
***
Karma: 3
Posts: 155
My head HURTS!!!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Changes... Done. I was going to use RX_AND_TX, but then someone might mistake the AND to mean the logical (RX & TX). So, I used RX_TX as suggested.

Thanks for the tips Mike.
DJ
Logged

DigitalJohnson

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 64
Posts: 2102
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I like this idea, although when applied I found that it increased the program size by 160 bytes ( must be more on the Mega ). But I took it a bit further  and good news, the same thing can be achieved with little to no increase ( 4 bytes max on Uno ) in size.

In HardwareSerial.h
Code:
//void begin(unsigned long);
//changes to
template< uint8_t mode > void begin(unsigned long);

In HardwareSerial.cpp
Code:
//void HardwareSerial::begin(unsigned long baud )
//changes to
template< uint8_t mode > void HardwareSerial::begin(unsigned long baud )

Then at the bottom of the HardwareSerial::begin ( after the closing '}' ) you need to place:

Code:
template void HardwareSerial::begin< RX_TX >(unsigned long baud );
template void HardwareSerial::begin< RX_ONLY >(unsigned long baud );
template void HardwareSerial::begin< TX_ONLY >(unsigned long baud );

And use like:
Code:
void setup()
  {
    Serial.begin< TX_ONLY >( 9600 );
  }
Logged


Pages: [1]   Go Up
Jump to: