Go Down

Topic: Software Optimisation (Read 344 times) previous topic - next topic

ratchetclank

Hi

I'm working on a project where I would like to drive many 6" e-ink screen. I have finally overcome the crazy power requirement of such a screen and i'm turning to the driving part.


As I need 19 pins to drive a screen and as I wanted eventually to drive multiple screens with the same control unit, I looked at the arduino due which should allow me to drive 3 screen with it's great number of pins.

my problem come in 2 parts :

1) The screen is 800*600 with 2 bit per pixel, which is 960 000 bits in total or 120 000 bytes, which is too big for the onboard memory of the arduino Due. I'm currently trying to overcome this with either a spi ram chip or a spi sd card reader

2) Event without the memory problem, I think my code isn't fast enought. I've already rewriten a digitalWriteFast which work on the due (available here : https://github.com/remygrandin/DueDigitalWriteFast/blob/master/DueDigitalWriteFast.h) and exploited the ODSR register of the due to reduce greatly the amount of operation.
However, with a hard-coded byte to write to the 8 data lines (so without any external memory access), i'm still at between 150ms and 200ms to write the whole screen and i would need to write it about 8 or 16 time in a realy short period (less than 2 secs probably).

Here is my code :

Code: [Select]

#include "dueDigitalWriteFast.h"

const char S1P_WAKUP = 31;

const char S1P_CKV = 9;
const char S1P_SPV = 8;

const char S1P_SCL = 41;
const char S1P_SDA = 39;

const char S1P_CE = 2;
const char S1P_GMODE = 3;

const char S1P_D0 = 44;
const char S1P_D1 = 45;
const char S1P_D2 = 46;
const char S1P_D3 = 47;
const char S1P_D4 = 48;
const char S1P_D5 = 49;
const char S1P_D6 = 50;
const char S1P_D7 = 51;

const char S1P_SPH = 36;
const char S1P_SHR = 17;

const char S1P_OE = 14;
const char S1P_CL = 15;
const char S1P_LE = 16;


void setup()
{
pinMode(S1P_WAKUP, OUTPUT);

pinMode(S1P_CKV, OUTPUT);
pinMode(S1P_SPV, OUTPUT);

pinMode(S1P_CE, OUTPUT);
pinMode(S1P_GMODE, OUTPUT);

pinMode(S1P_D0, OUTPUT);
pinMode(S1P_D1, OUTPUT);
pinMode(S1P_D2, OUTPUT);
pinMode(S1P_D3, OUTPUT);
pinMode(S1P_D4, OUTPUT);
pinMode(S1P_D5, OUTPUT);
pinMode(S1P_D6, OUTPUT);
pinMode(S1P_D7, OUTPUT);

pinMode(S1P_SPH, OUTPUT);
pinMode(S1P_SHR, OUTPUT);

pinMode(S1P_OE, OUTPUT);
pinMode(S1P_CL, OUTPUT);
pinMode(S1P_LE, OUTPUT);


DirectRegisterEnable(S1P_D0);
DirectRegisterEnable(S1P_D1);
DirectRegisterEnable(S1P_D2);
DirectRegisterEnable(S1P_D3);

DirectRegisterEnable(S1P_D4);
DirectRegisterEnable(S1P_D5);
DirectRegisterEnable(S1P_D6);
DirectRegisterEnable(S1P_D7);

digitalWrite(S1P_WAKUP, HIGH);
}

void loop()
{
uint32_t microStart = micros();
StartFrame();

for (int i = 0; i < 200; ++i)
{

StartRow();
for (int j = 0; j < 150; ++j) {
WriteByte((byte)0);
CLPulse();
}

EndRow();
WriteRow();

}

EndFrame();

uint32_t microEnd = micros();

SerialUSB.print(String(microEnd - microStart));
}

void CKVPulse() {
digitalWriteFast(S1P_CKV, HIGH);
delayMicroseconds(1);
digitalWriteFast(S1P_CKV, LOW);
delayMicroseconds(4);
}

void CLPulse()
{
digitalWriteFast(S1P_CKV, HIGH);
digitalWriteFast(S1P_CKV, LOW);
}

void WriteByte(uint8_t data)
{
*__digitalPinToPortRegODSR(S1P_D0) = BITS_OFFSET((int)data, 11);
}

void StartFrame()
{
digitalWriteFast(S1P_GMODE, HIGH);
digitalWriteFast(S1P_SPV, HIGH);

CKVPulse();

digitalWriteFast(S1P_SPV, LOW);

CKVPulse();

digitalWriteFast(S1P_SPV, HIGH);

CKVPulse();
}

void EndFrame()
{
digitalWriteFast(S1P_GMODE, LOW);

CKVPulse();
CKVPulse();
CKVPulse();
CKVPulse();
CKVPulse();
}



void StartRow()
{
digitalWriteFast(S1P_LE, LOW);
digitalWriteFast(S1P_OE, LOW);

digitalWriteFast(S1P_SPH, LOW);
}

void EndRow()
{
digitalWriteFast(S1P_SPH, HIGH);
CLPulse();

digitalWriteFast(S1P_LE, HIGH);
digitalWriteFast(S1P_LE, LOW);
}

void WriteRow()
{
digitalWriteFast(S1P_CKV, HIGH);
digitalWriteFast(S1P_OE, HIGH);

delayMicroseconds(5);

digitalWriteFast(S1P_OE, LOW);
digitalWriteFast(S1P_CKV, LOW);

delayMicroseconds(50);
}

void SkipRow()
{
digitalWriteFast(S1P_CKV, HIGH);
delayMicroseconds(1);
digitalWriteFast(S1P_CKV, LOW);
delayMicroseconds(100);
}

void ClearRow()
{
digitalWriteFast(S1P_CKV, HIGH);
delayMicroseconds(20);
digitalWriteFast(S1P_CKV, LOW);
delayMicroseconds(200);
}





Do any of you see a way to speed it ? Any optimisation idea is welcome.

ard_newbie


You could use an I/O port expander http://tronixstuff.com/2011/08/26/tutorial-maximising-your-arduinos-io-ports/

Lag in code is mostly due to delaymicroseconds(), are they mandatory ?

And inline your functions to avoid registers pushs/pops on stack at each function call with something like:

inline __attribute__((always_inline)) void foo(void);


Go Up