I'm trying to generate a simple sinusoid sound with a PIC32MX250F128B communicating by I2S with a DAC+Amplifier slave module (MAX98257). The end goal is to make a synthesizer with a keyboard for a school project.
I created a basic project with MPLABX (v.5.40) I'm not using Harmony or any other framework for now, I'm just trying to have a basic sound generating, working code.
Here is the code :
Microcontroller Configuration bits :
// DEVCFG3
#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = ON // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON // USB VBUS ON Selection (Controlled by USB Module)
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_18 // PLL Multiplier (18x Multiplier)
#pragma config UPLLIDIV = DIV_12 // USB PLL Input Divider (12x Divider)
#pragma config UPLLEN = OFF // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 1)
// DEVCFG1
#pragma config FNOSC = PRIPLL // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = ON // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = XT // Primary Oscillator Configuration (XT osc mode)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_2 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/2)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window Size is 25%)
// DEVCFG0
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
SPI/I2S configuration + code :
int sineTable[4096]= { ... };
int i = 0;
void main(void) {
RPB5R = 0b0011; //pin 14 : SDO1 (data out)
RPA0R = 0b0011; //pin 2 : SS1 (word select)
SPI1CON2bits.AUDEN = 1; //audio protocol enabled
SPI1CON2bits.AUDMONO = 1; //MONO mode
SPI1CON2bits.AUDMOD = 0b00; //I2S mode
SPI1CON2bits.IGNROV = 1; // Ignore Receive Overflow bit (for Audio Data Transmissions)
SPI1CON2bits.IGNTUR = 1; // Ignore Transmit Underrun bit (for Audio Data Transmissions) 1 = A TUR is not a critical error and zeros are transmitted until thSPIxTXB is not empty 0 = A TUR is a critical error which stop SPI operation
SPI1BRG = 140;
SPI1CONbits.MSTEN = 1;
SPI1CONbits.MCLKSEL = 0; //Clock = Fpb
SPI1CONbits.CKP = 1; //Idle state high, active state low
SPI1CONbits.MODE32 = 1;
SPI1CONbits.MODE16 = 0; //32 bit
//SPI1CONbits.STXISEL = 0b11; //quand générer l'interruption?
SPI1CONbits.DISSDI = 1; // disable serial data in
SPI1CONbits.ENHBUF = 1; // enable enhanced buffer
SPI1CONbits.ON = 0; //ON
SPI1CONbits.ON = 1; //ON
while(1)
{
SPI1BUF = sineTable[i];
while( SPI1STATbits.SPIBUSY); // wait for transfer complete
if(i >= 4095){
i = 0;
}
i++;
} // main loop
}
Simulation behaviour : In simulation, the code seems to work fine, however all the bits in the status register (SPI1STAT) are 0 and always stay at 0 (SPIBUSY included) which is odd.
Behaviour with Target : I'm programming the PIC32 with a Pickit3 on a breadboard (ICSP, no devboard). I followed the basic connections for the PIC32MX specified in the datasheet and I connected the DAC
What I notice :
- SPIBUSY gets set after I fill SPI1BUF with the first value from sinetable.
- I don't see the value of the buffer (SPI1BUF) change in the watches window, whereas in simulation i do (but that might be normal idk)
- The program gets stuck in the while loop because SPIBUSY never gets cleared
So in simulation, it seems to work fine, probably because the SPI1BUSY bit never changes anyway (just like the other STATUS bits).
And with the target, the status bits seem to work except for SPI1BUSY that never gets cleared.
Any idea why that might be? Thank you