Thanks, you were right about the name mangling! Using your modified SPI.h fixed the linking issues.
I've managed to get it working now after fixing up some errors in the example code.
The next question is how to properly use the library. I initially attempted to obtain SPI readings from render() (i.e in the audio thread). This seems to cause underruns and "mode switches". Is this because the render() function is running on the PRU, but the SPI.c library is accessing SPI via "/dev/spidev2.0" in the operating system?
Looking at the MPR121 I2C example, I see that an AuxiliaryTask is used instead, meaning that the sensor is read outside of the render() audio thread... using that as an example this is what I've come up with so far:
#include <Bela.h>
#include <stdio.h>
#include "SPI.h"
const int busSpeedHz = 32000000; // Fastest speed available
const int csDelay = 0; // how long to delay after the last bit transfer before deselecting the device
const int wordLength = 8;
AuxiliaryTask SPITask;
void readSPI(void*);
int readInterval = 50;// Change this to change how often SPI is read (in Hz)
int readCount = 0; // How long until we read again...
int readIntervalSamples; // How many samples between reads
unsigned char exampleOutput;
bool setup(BelaContext *context, void *userData)
{
// Initialise SPI
if (SPIDEV_init("/dev/spidev2.0", 0, busSpeedHz, SPI_SS_LOW,
csDelay, wordLength,
SPI_MODE3) == -1)
printf("SPI initialization failed\r\n");
else
printf("SPI initialized - READY\r\n");
// Set up auxiliary task to read SPI outside of the real-time audio thread:
SPITask = Bela_createAuxiliaryTask(readSPI, 50, "bela-SPI");
readIntervalSamples = context->audioSampleRate / readInterval;
return true;
}
void render(BelaContext *context, void *userData)
{
for(unsigned int n = 0; n < context->audioFrames; n++) {
// Schedule auxiliary task for SPI readings
if(++readCount >= readIntervalSamples) {
readCount = 0;
Bela_scheduleAuxiliaryTask(SPITask);
}
// use SPI output for whatever you need here
exampleOutput;
}
}
// Auxiliary task to read SPI
void readSPI(void*)
{
int transmissionLength = 4;
unsigned char Tx_spi[transmissionLength];
unsigned char Rx_spi[transmissionLength];
Tx_spi[0] = 0xff;
Tx_spi[1] = 0x22;
Tx_spi[2] = 0xff;
Tx_spi[3] = 0x0;
if (SPIDEV_transfer(Tx_spi, Rx_spi, transmissionLength) == 0)
{
// Print result
printf("SPI: Transaction Complete. Sent %d bytes, received: ", transmissionLength);
int n = 0;
for(n = 0; n < transmissionLength; ++n)
{
printf("%#02x ", Rx_spi[n]);
}
printf("\n");
// Send first byte of result to audio thread via global variable
exampleOutput = Rx_spi[0];
}
else
printf("SPI: Transaction Failed\r\n");
}
void cleanup(BelaContext *context, void *userData)
{
}
This code seems to work fairly well! However I still get a single: 1 mode switch detected on the audio thread.
Aside from that one error, my only concern is latency. The SPI is set to be read at 50 Hertz, but is this guaranteed? What is the smallest possible latency between an SPI sensor change to corresponding change in audio output?
P.S... it seems the forum will not upload my .zip Bela project - please advise