I have setup SPI2 on a dsPIC33CK64MP505 to receive Left adjusted audio as a slave. If I run the code by polling the SPI buffer, I get data in and all is dandy. However I need the synchronization of left and right channel so I'm trying to get the SPI2 RX interrupt to fire on received data. The Audio format is 24bit left adjusted so SPI2BUFH contains the 16bit MSB while the SPI2BUFL contains the last 8bit LSB.
I have configured it like this:
RPINR23bits.SS2R = 38; // RB6 LRCK
RPINR22bits.SCK2R = 39; // RB7 BCLK
RPINR22bits.SDI2R = 40; // RB8 ADCDAT (SDI)
IEC7bits.SPI2IE = 0;
SPI2CON1Lbits.SPIEN = 0;
SPI2CON1H = 0;
while(!SPI2STATLbits.SPIRBE) { (void) SPI2BUFL; (void) SPI2BUFH; }
SPI2STATLbits.SPIROV = 0; // Clear receive overflow
SPI2CON1Hbits.AUDMOD = 1; // Left justified
SPI2CON1Hbits.AUDEN = 1;
SPI2CON1Lbits.MSTEN = 0;
SPI2CON1Lbits.CKP = 0;
SPI2CON1Hbits.FRMPOL = 1;
SPI2CON1Lbits.MODE = 3; // 24bit over 32bit register
IPC7bits.SPI2RXIP = 4;
//SPI2IMSKHbits.RXMSK = 1; // Tried this as well
//SPI2IMSKHbits.RXWIEN = 1; // ...didn't work either
SPI2IMSKLbits.SPIRBFEN = 1;
IEC7bits.SPI2IE = 1;
//IFS7bits.SPI2IF = 0; // As a test, if I set this to 1,
// I enter the ISR instant.
SPI2CON1Lbits.ENHBUF = 1;
SPI2CON1Lbits.SPIEN = 1;
The interrupt routine is as follow:
void __attribute__((interrupt, no_auto_psv)) _SPI2Interrupt(void) {
IFS7bits.SPI2IF = 0;
while(!SPI2STATLbits.SPIRBE) { // Clear buffer for test.
(void)(uint16_t)(SPI2BUFH);
(void)(uint8_t)(SPI2BUFL);
}
SPI2STATLbits.SPIROV = 0; // Clear receive overflow
}
So, with an error free audio stream the interrupt never fire. If I set the SPI2IF flag at initialization it fires immediately, so the ISR is correct. I get in data when polling, so we know the pins are correctly configured. But for some reason it doesn't fire on the buffer-full event (I'm of course not polling when trying the interrupt solution).
I found out at the documentation was unclear and maybe even incomplete (no surprise Microchip). I had enabled SPI2IE instead of SPI2RXIE (also missing in the IO View together with the SPI2RXIF). The documentation only states, set up interrupts accordingly.
Also the enhanced SPI buffer mode MUST be used. If not, I got somewhat random values in the buffer until they stabilized and always return a fixed value.
The format in the buffer is not mentioned to be right aligned (it converts the audio format so LSB are in the buffer's LSB).
So my setup for Left adjusted 24bit audio became this:
And of course another interrupt vector needs to be setup.
This did the trick. Note that even if the audio format is left adjusted, it is right adjusted in the buffer. Take notice that the 24bit data isn't sign extended. You can easily do this by checking bit 23.
However, there is a bit in the SPI to sign extend, but I didn't get it to work. Hope this will help others trying to deal with Microchip documentation.