mborgerson
Well-known member
I am using the SPI EventResponder to good effect in receiving SPI data packets in the background from a Lepton 3.5 thermal imaging camera. The driver receives data frames as fast as the Lepton can send them (~9 frames per second due to ITAR limitations). It's all done in the background and uses about 5% of the CPU bandwidth on a T3.2 at 48MHz. The foreground polls a frame-complete flag and sends the frame data via USB Serial to a T4.1 host in the dead time between frames. The T4.1 receives the frame data using USBHost Serial, writes them to SD files, and sends the files to my PC using MTP.
In this working driver, I use an external proxy function to forward the End-of-packet event to my driver. An example of how that is done is in this code:
My next goal is to encapsulate the event responder declarations and code inside the SPIDev_cl class. That's not going so well. I've tried many ways to encapsulate the event response inside the class. None have succeeded.
Here is the test code, which varies in just a handful of lines:
If anyone knows the magic words to accomplish this goal, please let me know.
In this working driver, I use an external proxy function to forward the End-of-packet event to my driver. An example of how that is done is in this code:
C++:
// Demo SPI with event handler callled from external proxy function
// compiles and runs on T4.1 TD 1.59 Arduino IDE 2.3.1
#include <SPI.h>
#define PKTLEN 20
EventResponder SPIEvent;
// define a simple SPI test class
class SPIDev_cl {
private:
const int pin_cs = 10;
uint8_t pktbuffer[PKTLEN];
uint32_t pktsrcvd = 0;
public:
void begin(void){
SPI.begin();
}
void GetPacket(void){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
digitalWriteFast(pin_cs, LOW); // cs goes high in event responder
SPI.transfer(NULL, pktbuffer, PKTLEN, SPIEvent);
}
void Responder(void){ // ignore the results of read, increment pktsrcvd
digitalWriteFast(pin_cs, HIGH);
SPI.endTransaction();
pktsrcvd++;
}
uint32_t PktsRcvd(void){ return pktsrcvd;}
}; // end of class definition
SPIDev_cl spiDev1; // create one instance of class
// Event responder is outside class
void SPIEventResponder(EventResponderRef event_responder) {
spiDev1.Responder();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(1000);
spiDev1.begin();
SPIEvent.attachImmediate(&SPIEventResponder);
}
void loop() {
// put your main code here, to run repeatedly:
spiDev1.GetPacket();
delay(1); // 20 bytes at 10MHz SCLK shouldn't take long!
Serial.print("pktsrcvd: ");
Serial.println(spiDev1.PktsRcvd());
delay(999); // keep output slow enough to read
}
My next goal is to encapsulate the event responder declarations and code inside the SPIDev_cl class. That's not going so well. I've tried many ways to encapsulate the event response inside the class. None have succeeded.
Here is the test code, which varies in just a handful of lines:
C++:
// Demo SPI with event handler callled from internal function
// Doesn't compile.
#include <SPI.h>
#define PKTLEN 20
// define a simple SPI test class and try to encapsulate event responder setup
class SPIDev_cl {
private:
static const int pin_cs = 10;
uint8_t pktbuffer[PKTLEN];
EventResponder SPIEvent;
uint32_t pktsrcvd = 0;
void SPIEventResponder(EventResponderRef event_responder) {
Responder();
}
public:
void begin(void){
SPI.begin();
// Now try to attach the event responder
//SPIEvent.attachImmediate(&SPIEventResponder); // THis line causes error
SPIEvent.attachImmediate([this](){Responder();}); //attempted lambda function didn't work either
}
void GetPacket(void){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
digitalWriteFast(pin_cs, LOW); // cs goes high in event responder
SPI.transfer(NULL, pktbuffer, PKTLEN, SPIEvent);
}
void Responder(void){ // ignore the results of read, increment pktsrcvd
digitalWriteFast(pin_cs, HIGH);
SPI.endTransaction();
pktsrcvd++;
}
uint32_t PktsRcvd(void){ return pktsrcvd;}
}; // end of class definition
SPIDev_cl spiDev1;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(1000);
spiDev1.begin();
}
void loop() {
// put your main code here, to run repeatedly:
spiDev1.GetPacket();
delay(1); // 20 bytes at 10MHz SCLK shouldn't take long!
Serial.print("pktsrcvd: ");
Serial.println(spiDev1.PktsRcvd());
delay(999); // keep output slow enough to read
}
If anyone knows the magic words to accomplish this goal, please let me know.