Go Down

Topic: What am doing wrong here with my class? (Read 1 time) previous topic - next topic

Nick Gammon

#25
Nov 04, 2012, 11:07 pm Last Edit: Nov 04, 2012, 11:11 pm by Nick Gammon Reason: 1
This compiles. It appears to work:

Code: [Select]

#include <SPI.h>

namespace myLeds
    {
 
   const int LEDBYTES = 36;
   const int SCALEBYTES = 24;
   
   int modules;   // Number of LED modules connected.  Defined in config.txt.
 
   byte * data;    // LED data is stored as a string of 12 bit LED values.  There are 3 bytes for every two LEDs.  We store it this way because the data does not need to be altered when we are shifting it out to the TLC5947s.  Modifying the data with bit shifts would be very expensive and there is a lot of data to move.
   byte * scale;   // Scaling factor for LED brightness.  Used when say, you want to be able to adjust the brightness of the powercell without changing all the code that assumes the max desired brightness is 1.0.  Value stored here is scaling_factor*255, where scaling factor is 0..1.

   void set(const int which, const float a, const float b)
     {
     // whatever
     }
     
   float get(const int which)
     {
     return 42.0;
     }
   
   
}  // end of namespace myLeds

void setup ()
 {
 myLeds::modules = 2;

 myLeds::data =  (byte *) malloc (myLeds::modules * myLeds::LEDBYTES * sizeof(byte));  
 myLeds::scale = (byte *) malloc (myLeds::modules * myLeds::SCALEBYTES * sizeof(byte));
 
 SPI.begin ();
 Serial.begin (115200);
 
 }  // end of setup
 
void loop ()
 {
 myLeds::set (1, 2, 3);

 unsigned long startTime = micros();
     
 byte *thisLED = &myLeds::data [myLeds::modules * myLeds::LEDBYTES];
 byte *lastLED = &myLeds::data [0];
   
  noInterrupts ();
 
 do
   {      
   SPI.transfer (*--thisLED);
   } while (thisLED != lastLED);

 interrupts ();

 unsigned long endTime = micros();
 Serial.println (endTime - startTime);
 delay (1000);
 }  // end of loop
 


The serial monitor displays:

Code: [Select]

216
216
216
220
220
220
220
220
220


That was the predicted time (216 uS) for the fastest SPI loop. So not only does it work, it works nice and fast without mucking around with the SPI registers. Throw in one NOP if necessary if the LEDs require it.


(edit) Changed loop to post-test.

scswift

I just discovered that it was the NOP's which were the problem.  Somehow switching to the use of a namespace has changed the timing so 10 NOP's is no longer sufficient.  I threw 20 in there just to see if that was the issue (WAIT; WAIT;) , and sure enough the LEDs light up once more.

As for your suggestion Nick, I'm afraid there's one problem with your benchmark.  The benchmarks I was doing before were for 6 LED modules, not 2.  So that SPI function you're calling there is in fact 3x as slow as the theoretical max speed.

I guess I'll have to add or remove some NOPs and see what happens.  I probably only need to add one.  I had noticed with my earlier testing that removing just one would result in no LEDs lighting, and I could not figure out why that would be, when removing 2 resulted in garbage.

scswift

Well thanks for all your help.  I guess I must have had the class stuff right in the first place.  Ugh. :-)

Oh well at least I learned about namespaces.

Nick Gammon

Perhaps if you post all your code? All that namespaces do is change the compiler symbol table management.

scswift

All the code wouldn't fit into one post and it uses a modified wavehc and sd card reader lib and 1284 pin definitions and serial output on uart1 with a special bootloader...  I don't think you'd want to go to all the trouble to compile it. :-)  Anyway I'm gonna post something in the optimization thread for this spi stuff, I just came across something interesting.

Go Up