Direct port manipulation - SPI CS Pin

Hi Folks,

The title must be clear enough, but anyway:

I am not sure how the SD library sets/clears the CS pins, however, assuming it does so using a digital write, this operation on its own might take as much or more than the time needed for the data to be sent.

Is there any way to define the CS pin witting directly to the port?

Regards

Have you looked at the code. Why have you jumped to the conclusion that digitWrite() is used?

Mark

You can manipulate portpins directly:
To set a pin

PORTx |= 1<<bitnumber

To clear a pin

PORTx &= 0xFE<<bitnumber

To toggle a pin

PINx |= 1<<bitnumber

Where x is the port containing pin (B..D on a Meg328) and bitnumber is the bit(0..7) in that port

holmes4:
Why have you jumped to the conclusion that digitWrite() is used?

Pin control is left to the application.
Take for example, on the SD library, the file sd2Card.cpp

void Sd2Card::chipSelectHigh(void) {
  digitalWrite(chipSelectPin_, HIGH);
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow(void) {
  digitalWrite(chipSelectPin_, LOW);

nilton61:
You can manipulate portpins directly:

Thanks Nilton. Thats exactly what I do. But in libraries, say for a TFT or an SD card, I cannot define the chipselect as a port number. This means changing the library rather than the code, for every different project

Perhaps I should re-phrase my question:

Is there any macro I can use that allows me to write a function say "PORTx |= 1<<bitnumber" instead of having to do this manually each time I want to set up a library on a specific platform?

Why do you think you need to do this? Both the SD and TFT libraries allow you to set the CS pin in the begin function or constructor using the digital pin number.

casemod:
Perhaps I should re-phrase my question:

Is there any macro I can use that allows me to write a function say "PORTx |= 1<<bitnumber" instead of having to do this manually each time I want to set up a library on a specific platform?

Maybe: Google Code Archive - Long-term storage for Google Code Project Hosting.

I am not sure how the SD library sets/clears the CS pins, however, assuming it does so using a digital write, this operation on its own might take as much or more than the time needed for the data to be sent.

I strongly doubt that. Have you got any figures to back that up? The SD library has to read/write hundreds if not thousands of bytes to the SD card, a few microseconds setting chip select at the start won't make any difference.

Timing test:

#include <digitalWriteFast.h>

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  }  // end of setup

void loop ()
  {
  unsigned long start;
  unsigned long finish;
  const unsigned long iterations = 10000;
 
  unsigned long counter;
 
  start = micros ();
  for (counter = 0; counter < iterations; counter++)
     digitalWrite (10, HIGH);
  finish = micros ();
  
  Serial.print ("Using digitalWrite = ");
  Serial.print (finish - start);
  Serial.println (" uS");

  start = micros ();
  for (counter = 0; counter < iterations; counter++)
     digitalWriteFast (10, HIGH);
  finish = micros ();
  
  Serial.print ("Using digitalWriteFast = ");
  Serial.print (finish - start);
  Serial.println (" uS");
  
  while (true) {}
  }  // end of loop

Results:

Using digitalWrite = 54708 uS     <-- i.e. 5.471 µS each
Using digitalWriteFast = 5784 uS  <-- i.e. 0.579 µS each

So yep, you will save 5 µS by direct port manipulation. But compare that to how long it takes to access the SD card, open a file, write to it, and close it, and that will be virtually nothing.

Considering the speed boost I've seen in TFT's I have my doubts the speed increase is insignificant.
Take for example where a JPEG is read from the SD and forwarded to a SPI TFT. How many thousands of operations are required to select both devices, each one reading 1 byte at a time.

Good example timing digitalWritefast.
I timed direct port manipulation using the Atmel registers and that took 0.2uS per toggle, for a maximum output of 500Khz, so close enough

Well, I will have a look at this soon and post back the results.

The digitalWriteFast turns into port manipulation if it can (ie. if the port is a constant and not a variable).

As for the timings, surely you won't read a byte at a time from the SD card? If you are, there is your bottleneck. Read something like 512 bytes. And even the TFT device should be able to be selected once and then a whole lot of SPI sent to it.