Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Pages: [1]   Go Down
Author Topic: Improve of digitalWrite() possible - save 3.6 us  (Read 1571 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,
I'm developing a time critical application. Therefore I have tested a little bit the possibility of cbi and sbi macro. This saves me 3.6 usec per set or reset an digital output against digitalWrite() function. But I don't wan't loose the good readability of my code. Therefore I have created a macro named "digWrite()" for the Atmega168. If anyone have the same timing problems, simply use the macro below and substitute for example "digitalWrite(1,LOW)" with "digWrite(1,LOW). Eventually this can be inserted inside the core of arduino?

Good luck, Thomas

Code:
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define digWrite(bit,state) (state==LOW ? ((bit) < (8) ? cbi(PORTD, bit) : ((bit<14) ? cbi(PORTB, bit-8):cbi(PORTC, bit-14))):((bit) < (8) ? sbi(PORTD, bit) : ((bit<14) ? sbi(PORTB, bit-8):sbi(PORTC, bit-14))))
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 362
Posts: 17320
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Of course your macro won't be 'portable' with some of the different AVR chips that the IDE supports as the say 328 and 1280/2650 uses different ports/pins for the same abstracted 'arduino pin' numbers. Maybe add some conditional code that deals with processor types?

Lefty
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,
I have now made some good oscilloscope measurements. I have switched on and off a digital output 100 times and measured the resulting frequency.
Using the digitalWrite() function the period of switch on/off is 7,36us --> 135,8kHz (each switch takes exactly 3,68us).
Using the macro digWrite() the period of switch on/off is 250ns --> 4MHz (each switch takes exactly 125ns).

This is 29.45 times faster and saves you 3.555us per switch!

@Lefty: yes you are right, but with some compiler switches (#ifdef atmega168  ... #endif) this should be possible. I'm not familar enough with arduino core to make this portable for all.

Thomas
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 234
Posts: 14296
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

intereting timing, question that came in my mind are these figures true for every pin ? Looking at your macro I have some doubts. Nevertheless well done.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 362
Posts: 17320
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also I believe the Arduino development team has a fastdigitalread and fastdigitalwrite functions already developed and waiting for some future IDE release?

Lefty
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 216
Posts: 13140
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


I'm aware of three versions. 

The Teensy core includes a variation (speed optimized for all cases) that uses inline functions...
http://pjrc.com/teensy/teensyduino.html

jrraines built a library variation that uses macros...
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811;start=0;action=threadpagedrop

And, I believe, Arduino 1.0 includes a variation...
http://arduino.cc/forum/index.php?topic=61764.0
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Many thank's for the last two replys!

Anyone knows about the real timing benefit using this new solutions,  especially using code of arduino 1.0 Beta? If not I could test it with my Arduino NG rev. c board.

Thomas
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 216
Posts: 13140
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are certainly welcome to perform your own testing but all three have been tested to death.  I vaguely recall that I've written about the Teensy performance in the forum.  I believe @jrraines provided performance results in the forum topic listed above.  The Arduino implementation has been discussed on the Developers List...
http://www.google.com/search?q=fast+digital+site:arduino.cc%2Fpipermail%2Fdevelopers_arduino.cc%2F

If all the parameters are constants, the function call typically reduces to: a single machine instruction, three machine instructions (not ISR safe), or five machine instructions (ISR safe).

If any parameter is a variable, then the code produced varies considerably depending on the implementation.

If all the parameters are variable, then the code produced is close to the same as what is in the Arduino 0022 core.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did this a while ago.  This is my code.  It uses the C preprocessor to generate the PORTB, PORTD stuff.  It also uses C++ templates to map the pin numbers at compile time.

This pin mapping works with the Duemilanove board.  I think it has an ATMega328p processor.  I don't remember.  But anyways, you can always do...

Code:
#include <avr/io.h>
#ifdef __AVR_ATmega328P__
  // Add code here
#endif

to add support for other Arduino boards.

Code:
#ifndef PIN_TRAITS_H
#define PIN_TRAITS_H

#include <stdint.h>

#define __digital_high(L, N) PORT ## L |= _BV(N);
#define __digital_low(L, N) PORT ## L &= ~_BV(N);

inline void digital_write(boolean state);

template <uint8_t Pin> class pin_traits;

#define PIN_TRAITS_GENERATOR(L, N, P)       \
template <> class pin_traits<P>             \
{                                           \
  public:                                   \
  static void digital_write(boolean state)  \
  {                                         \
    if (state == HIGH)                      \
      __digital_high(L, N)                  \
    else                                    \
      __digital_low(L, N)                   \
  }                                         \
};

// Digital pins 0 - 7 are part of the D group
PIN_TRAITS_GENERATOR(D, 0, 0)
PIN_TRAITS_GENERATOR(D, 1, 1)
PIN_TRAITS_GENERATOR(D, 2, 2)
PIN_TRAITS_GENERATOR(D, 3, 3)
PIN_TRAITS_GENERATOR(D, 4, 4)
PIN_TRAITS_GENERATOR(D, 5, 5)
PIN_TRAITS_GENERATOR(D, 6, 6)
PIN_TRAITS_GENERATOR(D, 7, 7)

// Digital pins 8 - 13 are part of the B group
PIN_TRAITS_GENERATOR(B, 0, 8)
PIN_TRAITS_GENERATOR(B, 1, 9)
PIN_TRAITS_GENERATOR(B, 2, 10)
PIN_TRAITS_GENERATOR(B, 3, 11)
PIN_TRAITS_GENERATOR(B, 4, 12)
PIN_TRAITS_GENERATOR(B, 5, 13)

#undef PIN_TRAITS_GENERATOR

#endif /* PIN_TRAITS_H */

/** Same as digitalWrite(), except the pins need to be known at compile
    time.  This function is roughly 10 times faster than digitalWrite().
*/
template <uint8_t N>
inline void digital_write(boolean state)
{
  pin_traits<N>::digital_write(state);
}

So to set pin 5 to HIGH, you could do
Code:
digital_write<5>(HIGH);
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 216
Posts: 13140
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
And, I believe, Arduino 1.0 includes a variation...  http://arduino.cc/forum/index.php?topic=61764.0

I am wrong.  Arduino 1.0 does NOT include a variation of digital*Fast.
Logged

Washington
Offline Offline
God Member
*****
Karma: 39
Posts: 808
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I am wrong.  Arduino 1.0 does NOT include a variation of digital*Fast.
It should.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 362
Posts: 17320
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I am wrong.  Arduino 1.0 does NOT include a variation of digital*Fast.
It should.

It will. Arduino 1.0 is at beta so features still to come.

Lefty
Logged

Pages: [1]   Go Up
Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Jump to: