Pages: 1 2 [3] 4   Go Down
Author Topic: Higher Performance IO  (Read 7613 times)
0 Members and 1 Guest are viewing this topic.
London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Of course, you may use the code, especially since they are mods of arduino core stuff which is under the GPL.  No attribution required, but thanks for asking. smiley
ditto
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks smiley-grin
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I must have done something wrong, but I can't figure out what.

I put all the macros into a file called "fastSB.h", and include that in the header for the library. I then swapped out all calls to digitalWrite to fastWrite, and all shiftOut calls to shitOutByte. Now, when I try to build my example sketch, I get tons of strange errors:
Code:


/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::initPins()':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:49: multiple definition of `ShiftBrite::initPins()'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:49: first defined here

/Applications/arduino-0011/hardware/tools/avr/bin/../lib/gcc/avr/4.0.2/../../../../avr/bin/ld: Warning: size of symbol `_ZN10ShiftBrite8initPinsEv' changed from 164 in /Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o to 72 in /Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::ShiftBrite(int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:20: multiple definition of `ShiftBrite::ShiftBrite(int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:20: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::ShiftBrite(int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:20: multiple definition of `ShiftBrite::ShiftBrite(int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:20: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::ShiftBrite(int, int, int, int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:10: multiple definition of `ShiftBrite::ShiftBrite(int, int, int, int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:10: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::ShiftBrite(int, int, int, int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:10: multiple definition of `ShiftBrite::ShiftBrite(int, int, int, int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:10: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::sendPacket(int, int, int, int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:59: multiple definition of `ShiftBrite::sendPacket(int, int, int, int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:59: first defined here

/Applications/arduino-0011/hardware/tools/avr/bin/../lib/gcc/avr/4.0.2/../../../../avr/bin/ld: Warning: size of symbol `_ZN10ShiftBrite10sendPacketEiiii' changed from 9382 in /Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o to 306 in /Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::setColor(int, int, int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:40: multiple definition of `ShiftBrite::setColor(int, int, int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:40: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::setPower(int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:35: multiple definition of `ShiftBrite::setPower(int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:35: first defined here

/Applications/arduino-0011/hardware/libraries/ShiftBritev1/ShiftBrite.o: In function `ShiftBrite::setPower(int, int, int)':

/Applications/arduino-0011/hardware/libraries/ShiftBright/ShiftBrite.cpp:30: multiple definition of `ShiftBrite::setPower(int, int, int)'

/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.o:/Applications/arduino-0011/hardware/libraries/ShiftBrite/ShiftBrite.cpp:30: first defined here

Couldn't determine program size: hardware/tools/avr/bin/avr-size: '/tmp/build56400.tmp/shiftbright5.hex': No such file

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, that's just bizarre.  The exact same code works as long as it's in the original library folder, and not the duplicate folder I made to version up with.  I tried just duplicating the library with no code changes at all, and it fails to compile (with the above errors).  But the original library (exact same code, same files even) works.   :o

So the macros are working now that I'm working out of the original library folder.  Strange.
Logged

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

You can't have multiple cpp files with duplicate shiftBrite function names in the directories containing the libraries. If you want to keep multiple versions for testing you need to give the methods and public variables different names for each version.
Logged

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

Quote
If you want to keep multiple versions for testing you need to give the methods and public variables different names for each version.
Another approach is to move one of the conflicting versions into a folder named disabled, for example, while you're testing the other.

--Phil.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

*slaps head* of course!  Heh, I feel somewhat silly now. :-[

I think I'll keep the old version in a separate unused folder.  Make more sense that way now that I think about it too.

On a side note, I think I may have to switch to using functions instead of macros, as when the compiler flattens out all the macros, it takes up a lot of room smiley-sad  (A simple example sketch I made took up about 11k!).  The macros work really well, but seems to take up a lot of room.
Logged

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

Quote
On a side note, I think I may have to switch to using functions instead of macros, as when the compiler flattens out all the macros, it takes up a lot of room smiley-sad  (A simple example sketch I made took up about 11k!).  The macros work really well, but seems to take up a lot of room.

The fastWrite macro produces two bytes of code for every place its used in the source file so I would be surprised if that alone is causing the code size increase. Function calling has significant overhead compared to the time writing directly to a port so if speed is important it's worth seeing if you can find out why the code is as big as it is, it may not be the macros themselves, but the way they are used.

Perhaps if you post the source code for both versions, you can get some advice on how to get the size of the macro version down.


Logged

Boulder, CO
Offline Offline
Newbie
*
Karma: 0
Posts: 43
I want to be a really useful engine!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you find that they are taking too much space, use the macros only where you really need the speed, of course.  The big one is shiftOut().  The fastWrite() is probably not worth it unless you are doing a bunch in a row that need to be fast.  Nevertheless, I am having a hard time imagining 11K worth. smiley  If you happen to be calling shiftOutByte() many places in your code it makes sense to use something like shiftOutRaw() instead which is a function call, as long as you are always using the same pins it should work.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sure!  Here's the ShiftBrite.cpp file:
Code:
//Matt G.
//onion@doorcreekorchard.com
//July 2008

#include "ShiftBrite.h"


//====Public
//==Constructors
ShiftBrite::ShiftBrite(int dp, int lp, int ep, int cp)
{
      datapin=dp;
      latchpin=lp;
      enablepin=ep;
      clockpin=cp;
      initPins();
}


ShiftBrite::ShiftBrite(int cp)
{
      clockpin=cp;
      enablepin=cp+1;
      latchpin=cp+2;
      datapin=cp+3;
      initPins();
}

//==
void ShiftBrite::setPower(int r, int g, int b)
{
      sendPacket(B01,r,g,b); //B01 sets the mode to write to the current registers
}

void ShiftBrite::setPower(int p)
{
      sendPacket(B01,p,p,p);
}

void ShiftBrite::setColor(int r, int g, int b)
{
      sendPacket(B00,r,g,b); //B00 sets the mode to write to the PWM registers
}
#if _5BIT_SB
void ShiftBrite::setColor5b( byte r, byte g, byte b)
{
      setColor(SB_5bLUT_basic[0][r],SB_5bLUT_basic[1][g],SB_5bLUT_basic[2][b]);
}

void ShiftBrite::setColor5b(int val)
{
      /*byte r,g,b;
      
      //extract the channels
      b = val & 0x1F;
      g = (val >> 5) & 0x1F;
      r = (val >> 10) & 0x1F;
      */
      setColor5b((val >>10) & 0x1F,(val >> 5) & 0x1F,val & 0x1F);
}
#endif
//============


//====Private
void ShiftBrite::initPins()
{
      pinMode(datapin, OUTPUT);
      pinMode(latchpin, OUTPUT);
      pinMode(enablepin, OUTPUT);
      pinMode(clockpin, OUTPUT);
      fastWrite(latchpin, LOW);
      fastWrite(enablepin, LOW);
}

void ShiftBrite::sendPacket(int mode, int r, int g, int b)
{
      unsigned long SB_CommandPacket;
      
      SB_CommandPacket = mode & B11;
      SB_CommandPacket = (SB_CommandPacket << 10)  | (b & 1023);
      SB_CommandPacket = (SB_CommandPacket << 10)  | (r & 1023);
      SB_CommandPacket = (SB_CommandPacket << 10)  | (g & 1023);
      
      shiftOutByte(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 24);
      shiftOutByte(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 16);
      shiftOutByte(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 8);
      shiftOutByte(datapin, clockpin, MSBFIRST, SB_CommandPacket);
      
      delay(1); // adjustment may be necessary depending on chain length
      fastWrite(latchpin,HIGH); // latch data into registers
      delay(5); // adjustment may be necessary depending on chain length
      fastWrite(latchpin,LOW);
}

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ShiftBrite.h:
Code:
#ifndef ShiftBrite_h
#define ShiftBrite_h

#define SB_Ver 1.1

#ifndef _5BIT_SB
#define _5BIT_SB 1 //default include the 5bit part of the library.
#endif

#include "wiring.h"
#include "fastSB.h"
#include "LUTs_SB.h"

class ShiftBrite
{
  private:
      int datapin; //pins the ShiftBrite is connected to
      int latchpin;
      int enablepin;
      int clockpin;
      
      void initPins(); //sets up pins modes, etc.
      void sendPacket(int mode, int r, int g, int b);
  
 public:
    ShiftBrite(int dp, int lp, int ep, int cp);
      ShiftBrite(int cp);
      
      void setPower(int r, int g, int b);
      void setPower(int p);
      
      void setColor(int r, int g, int b);
#if _5BIT_SB
      void setColor5b(byte r, byte g, byte b); //sets a 5 bit color via a LUT
      void setColor5b(int val); //same as above, but from a packed 16 bit word
#endif
};

#endif
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

and fastSB.h:
Code:
//credit of the following code goes to mem on the arduino board (for fastWrite)
//and to MartinFick (all the shiftOut stuff)



//fastWrite()
// the following macro sets a digital pin high or low, pin must be between 0 and 13 inclusive
// usage: fastWrite(2,HIGH); fastWrite(13,LOW);
#define fastWrite(_pin_, _state_) ( _pin_ < 8 ? (_state_ ?  PORTD |= 1 << _pin_ : PORTD &= ~(1 << _pin_ )) : (_state_ ?  PORTB |= 1 << (_pin_ -8) : PORTB &= ~(1 << (_pin_ -8)  )))
// the macro sets or clears the appropriate bit in port D if the pin is less than 8 or port B if between 8 and 13



#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#define sbipin(pin) sbi((pin)<8 ? PORTD:PORTB, (pin) - ((pin)<8 ? 0:8))
#define cbipin(pin) cbi((pin)<8 ? PORTD:PORTB, (pin) - ((pin)<8 ? 0:8))

#define bitWrite(pin, val) { \
if ((val) == LOW) cbipin(pin); \
else              sbipin(pin); \
}

#define shiftOutBit(dataPin, clockPin, val, bit) { \
bitWrite(dataPin, ((val) & (1 << (bit))) ? HIGH:LOW); \
bitWrite(clockPin, HIGH); \
bitWrite(clockPin, LOW); \
}

#define shiftOutByte(dataPin, clockPin, bitOrder, val) { \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?0:7); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?1:6); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?2:5); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?3:4); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?4:3); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?5:2); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?6:1); \
shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?7:0); \
}


Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you need here's the LUT I made.  I tried excluding it because at first I thought it was the culprit for the large size, but it only reduced the size by about ~200 bytes or so when I did:

LUTs_SB.h:
Code:
/*
 *  LUTs.h
 *  
 *
 *  Created by Chippey on 8/9/08.
 *  
 *
 */
#if _5BIT_SB //only include lookup tables if they're going to be used

//basic lut is just that. it puts most of the range in 0-400, but the whole
//thing is linear, from 0-400, then 400-1023
const uint16_t SB_5bLUT_basic[][32] =
{{
      0, //0  //RED
      16, //1
      32, //2
      48, //3
      64, //4
      80, //5
      96, //6
      112, //7
      128, //8
      144, //9
      160, //10
      176, //11
      192, //12
      208, //13
      224, //14
      240, //15
      256, //16
      272, //17
      288, //18
      304, //19
      320, //20
      336, //21
      352, //22
      368, //23
      384, //24
      400, //25
      503, //26
      607, //27
      711, //28
      815, //29
      919, //30
      1023 //31
},
{
      0, //0  //GREEN
      16, //1
      32, //2
      48, //3
      64, //4
      80, //5
      96, //6
      112, //7
      128, //8
      144, //9
      160, //10
      176, //11
      192, //12
      208, //13
      224, //14
      240, //15
      256, //16
      272, //17
      288, //18
      304, //19
      320, //20
      336, //21
      352, //22
      368, //23
      384, //24
      400, //25
      503, //26
      607, //27
      711, //28
      815, //29
      919, //30
      1023 //31
},
{
      0, //0  //BLUE
      16, //1
      32, //2
      48, //3
      64, //4
      80, //5
      96, //6
      112, //7
      128, //8
      144, //9
      160, //10
      176, //11
      192, //12
      208, //13
      224, //14
      240, //15
      256, //16
      272, //17
      288, //18
      304, //19
      320, //20
      336, //21
      352, //22
      368, //23
      384, //24
      400, //25
      503, //26
      607, //27
      711, //28
      815, //29
      919, //30
      1023 //31
}};


#endif

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Last bit.  When the above is used with this sketch, the result is ~ 11k.

example sketch:
Code:
#include "ShiftBrite.h"

ShiftBrite SB(10); //A ShiftBrite starting on pin 10, assumes the next pins are sequentially going up

void setup() {
  pinMode(9,OUTPUT);
  digitalWrite(9,HIGH); //this is un UGLY HACK to supply +5 on pin 9
                    //so the SB can be directly hooked on the the arduino.  
                    //This will probably burn out your arduino and cause the end of days.  
                    //Find a better way of supply power to the SBs
  SB.setPower(127); //Full power captin!
}


//This examples has three ShiftBrites chained together in series, and cycles some colours through them
void loop() {
  SB.setColor(1023,0,0); // SB #3 (since the data gets pushed through the SBs, the last one is set first
  SB.setColor(0,1023,0); // SB #2
  SB.setColor(0,0,1023); // SB #1
  delay(500);
  SB.setColor(0,1023,0);
  SB.setColor(0,0,1023);
  SB.setColor(1023,0,0);
  delay(500);
  SB.setColor(0,0,1023);
  SB.setColor(1023,0,0);
  SB.setColor(0,1023,0);
  delay(500);
}
Logged

Boulder, CO
Offline Offline
Newbie
*
Karma: 0
Posts: 43
I want to be a really useful engine!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think that you are better off using the shiftOutHPPM() function for your library since you are allowing things (the latchpins) to not be hardcoded.  Since you are not hardcoding them it is probably easier and safer to use the function.  There is no real speed gain if you do not hardcode the pins.
Logged

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