About Arduino’s DigitalWrite – Adafruit 16×32 LED matrix on Arduino Due (3)

In the previous article I already noticed how the display was starting to get less bright when I bumped up the refresh rate. Reading some parts of the Arduino Uno driver I noticed this one comment hinting to the slow Arduino DigitalWrite function. I never knew or red about this function not being very fast, I was expecting maybe a little impact but not as much as described in some online articles. And so I began to think of also looking for a way to faster manipulate pin outputs so that the driver works faster and better, and maybe allow us to do more than before. For Arduino Uno there is tons of information to find, however for Due you have to look a lot better. On the Arduino forums however I found this thread where faster port manipulation code has been presented:

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

void setup() {                
  pinMode(13, OUTPUT);     
  pinMode(12, INPUT);     
  Serial.begin(9600);
}

void loop() {
  digitalWriteDirect(13, HIGH);   
  delay(1000);           
  digitalWriteDirect(13, LOW);    
  delay(1000);          
  Serial.println(digitalReadDirect(12));
}

In my current driver I swapped all digitalWrite methods with the digitalWriteDirect methods from above and than compared how fast writing one (double) row of LEDs goes. Time was measured by calling the micros() method before and after writing on row of data, taking the difference of both and next report back by doing a single Serial.write(). Here is a comparison:
digitalWriteDirect: 91us
digitalWrite: 661us
So as you can see the direct implementation gives us nearly 7 times better performance, or the other way around I kind nearly draw the entire display this time where before I could draw only one row. I also now noticed that in my display only the last rows of each half screen were illuminating very bright while others where nearly not illuminating at all. The reason is because now we switch so fast from one row to the next that the HIGH time of the pixels in a row is very small compared to before when using the slow Arduino implementation. The reason why the last row was however bright is because it get’s drawn as last and from here on it takes nearly 5000us before the next interrupt is being called, so it is really obvious that it was appearing really bright. In my last update I changed to drawing only one row per timer interrupt. This way rows get painted on a steady time base, and with using the faster digitalWriteDirect method we can easily bump up the refresh rate of the display so now the interrupt routine gets called 8 times more than before.
Next problem I get is that I need to call the interrupt code each 1250us in order to get a steady image. That is a 800MHz refresh rate per pixel row, and so 100Hz for the entire display, which kinds of bothers me because now interrupt code will interrupt normal program flow a lot of times, and I’m still at only 3 bit colors and I don’t have any support for dimming. I guess there is more reading ahead of me…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s