Open Source DSP XOs

Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
In general, embedded firmware is not portable. I actually think that it's a mistake to code embedded firmware using techniques that are aimed at portability rather than optimization.

You might feel that way until you have to port the code for a safety critical system from an obsolete microcontroller family to something still in production.

Obviously, for DIY there are no such concerns about software quality or maintainability.
 
You might feel that way until you have to port the code for a safety critical system from an obsolete microcontroller family to something still in production.

Obviously, for DIY there are no such concerns about software quality or maintainability.
It depends entirely upon the details of the hardware changes, and also whether the safety-critical aspects are high-level or low-level. If you think that you can just compile Standard C code for completely different hardware without looking at hundreds of painstaking details and still remain safe, then I would be very concerned about using such a product. We might be on diyAudio, but none of my comments have anything to do with DIY shortcuts. In my experience, high-level code does not achieve the same level of quality as mixed assembly and C.

There is no shortcut for developing high quality firmware, whether it's a first-time development or a port. Using a portable language does not make the hardware aspects portable, nor does it save you from needing to know the minute details of what will happen when you change the hardware and leave the software the same. Invoking "safety critical" does not mean that the easier solution will work. Sometimes there is no avoiding the difficulties involved in a port, regardless of the language used.

Granted, if your safety-critical code is all high-level, and totally abstracted from the hardware, then, by all means, write in Standard C and leave it alone. But all along I have been advocating assembly for low-level hardware details, and those simply cannot be solved with high-level hand-waving.
 
Even in a new design, assembly carries the highest defect density of any language.
Is that because designs that require assembly are more difficult than others, regardless of the language used? ... or is it because the C language somehow makes it possible for people who don't know what they're doing to succeed?

Knowledge of assembly has been the path to defect correction in many cases. My experience tells me that defect density is way more complicated than language choice - you may merely be citing a statistic of correlation, rather than causation.
 
If anything, embedded systems where you can use asm are less complicated.

Humans make mistakes and create bugs. They make more of them writing in assembly. Heavy use of assembly is not recommended in safety critical systems. MISRA would like you to avoid pointer arithmetic in C for crying out loud.

Like I said, this is audio, not a pacemaker. Just keep in mind that you don't get a gold star for having your code execute faster than necessary.
 
If the code turns out to run faster than necessary then the CPU clock rate can be reduced, saving power and generating less noise to spread into surrounding audio circuits. There are equally well no gold stars for over-specifying hardware, taking up more power or real estate than absolutely necessary.
 
If the code turns out to run faster than necessary then the CPU clock rate can be reduced, saving power and generating less noise to spread into surrounding audio circuits.
Yep, that's another good technique to try from the bag of tricks. Shaving cycles by writing time-critical sections in assembly can help make it possible to lower the clock rate, especially if something that is frequently called like an interrupt is converted from C to assembly. We've actually covered quite a few embedded secrets in this thread lately.
 

Attachments

  • the PIC32MX2  USB-audio experiment.jpg
    the PIC32MX2 USB-audio experiment.jpg
    119.9 KB · Views: 215
Last edited:
Currently within the PIC32 range, there are three chip families.

PIC32 MX 1-2 (introduced at the end of 2011)
PIC32 MX 3-4
PIC32 MX 5-6-7

Their SPI modules are all different.
Some chips combine two different kind of SPI modules.
Some are not buffered.
Some are buffered.
Some are buffered and feature the I2S compatibility (aka audio mode).
The control registers are not the same.
See for yourself in the attached .jpg

At the moment, only the PIC32 MX 1-2 SPI feature the I2S compatibility (aka audio mode). How long shall we wait for getting the I2S compatibility (aka audio mode) on PIC 32 MX 5-6-7 featuring up to four SPI ?

Worth reading is the Microchip document entitled DS61106G.
To be found here : http://ww1.microchip.com/downloads/en/DeviceDoc/61106G.pdf
 

Attachments

  • PIC32 MX 1-2 - SPI registers.jpg
    PIC32 MX 1-2 - SPI registers.jpg
    247.9 KB · Views: 391
  • PIC32 MX 3-4 - SPI registers.jpg
    PIC32 MX 3-4 - SPI registers.jpg
    207 KB · Views: 396
  • PIC32 MX 5-6-7 - SPI registers.jpg
    PIC32 MX 5-6-7 - SPI registers.jpg
    310.1 KB · Views: 392
Last edited:
A more structured way to cover the PIC32 SPI modules :

PIC32 MX 1-2 datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/61168D.pdf
PIC32 MX 3-4 datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/61143G.pdf
PIC32 MX 5-6-7 datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/61156F.pdf

PIC32 MX 3-4 feature unbuffered, no I2S-compatible (aka audio mode) SPI. There can be one or two SPI modules. Those are the oldest chips.
The SPI registers are SPIxCON, SPIxSTAT, SPIxBUF, SPIxBRG.

PIC32 MX 5-6-7 feature buffered, no I2S-compatible (aka audio mode) SPI. There can be three or four SPI modules.
The SPI registers are SPIxCON, SPIxSTAT, SPIxBUF, SPIxBRG.
SPIxCON and SPIxSTAT remain compatible with the unbuffered SPI variants, but of course for activating the buffer feature you need to manage a few bits that remained unused in the PIC32 MX 3-4 family.

PIC MX 1-2 feature buffered, I2S-compatible (aka audio mode) SPI. There are two SPI modules. Those are the newest chips.
The SPI registers are SPIxCON, SPIxSTAT, SPIxBUF, SPIxBRG, SPIxCON2.
SPIxCON and SPIxSTAT remain compatible with the buffered SPI variants, apart from bit FRZ that's not showing anymore.
SPIxCON2 disables or enables the audio mode, and defines the audio mode modalities.

More info is available from Microchip about the I2S-compatbile mode (aka audio mode) here : http://ww1.microchip.com/downloads/en/DeviceDoc/61106G.pdf
There are a few lines dealing with 24 bit data.
There are a few lines dealing with an enhanced buffer mode.

The PIC32MX1/MX2 starter kit (DM320013) has a PIC32MX2 and a WM8731 Codec onboard. Microchip delivers it with a small audio application written in C. The PIC32 sends digital audio to the WM8731, delivered to the heaphones mini-jack. For some reason Microchip has not connected the I2S input of the WM8731. As a consequence, The PIC32 cannot read audio data from the WM8731.

Here is the corresponding SPI initialization code.

void I2SInit(void)
{
UINT32 ReadData;

LRCLK_PPS_SETUP;
LRCLK_TRIS_SETUP;
DAC_DATA_PPS_SETUP;
DAC_DATA_TRIS_SETUP;

WM8731Codec_MusicOn(FALSE); // Disable playing of music until it's turned on.

// Setup I2S on SPI1
I2SCON = I2SCON2 = 0; // Reset settings
I2SSTATBITS.SPIROV = 1; // Clear overflow, if set
I2SSTAT = 0;
ReadData = I2SBUF; // Read any data

WM8731DRV_TX_XFER_DONE_INT_FLAG = 0; // clear prior interrupts
WM8731DRV_TX_XFER_DONE_INT_PRIORITY = 4;
WM8731DRV_TX_XFER_DONE_INT_SUB_PRIORITY = 0;
WM8731DRV_TX_XFER_DONE_INT_ENABLE = 1; // Enable interrupts

IFS0bits.CS0IF = 0; // Clear interrupt flag for software
IPC0bits.CS0IP = 3; // FileReadISR priority < I2S priority
IPC0bits.CS0IS = 0; // Secondary priority = 0;

I2SBRG = 0x0D; // Set baud rate, not needed for slave
I2SCON = SPI_CONFIG_CKP_HIGH | // Invert input SCK polarity
SPI_CONFIG_ENHBUF ; // Enhanced buffer enabled
I2SCONBITS.STXISEL = 0x2; // Interrupt when half empty
I2SCON2 = SPI_CONFIG2_AUDMOD_I2S | // I2S mode
SPI_CONFIG2_IGNROV | // Ignore receive overflow
SPI_CONFIG2_IGNTUR | // Ignore transmit underrun
SPI_CONFIG2_AUDEN ; // Enable Audio Codec Support

// Fill xmit buffer
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;
SPI1BUF = 0;

I2SCONBITS.ON = 1; // Turn SPI1 on.

assert( SPI1STATbits.SPITUR == 0 );
assert( (SPI1STAT & 0x100) != 0x100 );


Now, don't we have something to start with ?
 

Attachments

  • PIC32 MX 3-4 - SPI registers.jpg
    PIC32 MX 3-4 - SPI registers.jpg
    213.6 KB · Views: 330
  • PIC32 MX 5-6-7 - SPI registers.jpg
    PIC32 MX 5-6-7 - SPI registers.jpg
    496.5 KB · Views: 332
  • PIC32 MX 1-2 - SPI registers.jpg
    PIC32 MX 1-2 - SPI registers.jpg
    305.4 KB · Views: 47
  • PIC32 MX 1-2 - SPI registers (enhanced buffer mode).jpg
    PIC32 MX 1-2 - SPI registers (enhanced buffer mode).jpg
    322.4 KB · Views: 48
  • PIC32 MX 1-2 - SPI registers (24 bit data).jpg
    PIC32 MX 1-2 - SPI registers (24 bit data).jpg
    89.2 KB · Views: 46
Last edited:
I guess for three and four way crossovers one can bit bang or try to munge the I2S peripherals into I4S or I8S. NXP SGPIO slices still seem like the way to go for more than two way, though the clocking isn't necessarily trival when the LPC is consuming a clock rather than operating as the master. In master its straightforward to feed a clock from the crystal oscillator, GP_CLKIN, or one of the PLLs to CLK_PERIPH_SGPIO via BASE_PERIPH_CLOCK. In slave situations assigning SGPIO pins 12 to 15 to the input I2S in CLK_SOURCE_SLICE_MODE allows pins 0 to 11 to use the incoming BCLK for I2S output. However, there's no way to double the BLCK coming into the SGPIO peripheral to regenerate it---a multiply by two's needed to enable a SGPIO slice to clock out 10101010... to create the regenerated clock. In most cases the basic solution of routing BCLK as a bussed net is probably fine and there's any number of clock doublers or clock generators one could use if one feels a need.

An alternative option for slave mode is to assign GP_CLKIN to an 256 or 512 (or whatever) Fs clock input and drive the SGPIO outputs with that, which offers more flexibility. This does mean if you're doing a board which supports both master and slave you can't put a 44.1 series (11.2896MHz, etc.) crystal down next to a 48 series XO (12.228MHz, etc.) to support all the common audio clocks with maximally clean sources just by switching the LPC's clock source in master. One workaround is running PLL0_AUDIO in integer mode with P = 8, M = 147, N = 20 to convert a 12.228MHz clock to 11.2896MHz. The PFD frequency isn't the greatest so it may or may not be better than operating in fractional mode, particularly if a crystal is used as the clock source rather than the internal RC oscillator. (Personally I don't have any scenarios where I need to switch between 44.1 and 48 series clocks on the fly so I figure my worst case would be soldering up two boards with different frequency crystals on them.)

As an aside, there's been a wave of LPC4300 collateral released in the past couple weeks---v3.2 of the datasheet, v1.2 of the manual, LCPXpresso 4.2.3, and more formal dual core support from Code Red. The example LPC4300 project is still pretty raw but at least it now exists. The datasheet also now has jitter figures for the crystal oscillator---about 6ps period jitter for 256 Fs crystals for single speed. Baseband jitter is attenuated by around 50dB in such measurements so the period jitter doesn't say much about audible jitter. But neither does it signal obvious problems should one want to use an LPC4300 as the source for an MCLK.
 
NXP LPC4330 SGPIO slices still seem like the way to go for more than two way, though the clocking isn't necessarily trival when the LPC is consuming a clock rather than operating as the master.
Let's begin with the fundamentals. Before considering using the NXP LPC4330 SGPIO in slave mode, let's see how NXP used it in master mode in Robert Cassaro YouTube presentation, for the DSP Concepts USB Speaker Demo.

Configurable and Virtual Peripherals SGPIO and SCT - YouTube

From What I understand, because of the 010101... pattern loaded in the recirculating register of the slice generating MCLK, you need clocking such slice at twice MCLK. Right?

There is a SGPIO_CLK in the schematic, distinct and asynchronous from the CPU clock. Say the board has two audio oscillators : the 44.1 series (11.2896MHz) and the 48 series (12.228MHz). Say the Codec needs a 256x MCLK when operating at the base frequency. This means 11.2896 MHz at 44.1 kHz and 12.288 MHz at 48 kHz. You cannot use those quartz oscillators as SGPIO_CLK. You need doubling the frequency. Right?

Is there a x2 PLL in the LPC4330, taking the quartz frequencies, multiplying them by two? What is the jitter?

At this stage, the NXP LPC4330 approach, as master, looks complicated, compared to using a multichannel Codec like WM8580 or WM8581 in Master mode.

Let's go back to the LPC4330 slice schematic. There is another device we need to deal with. We need to preset a counter, such counter acting as local SGPIO_CLK divider. It gives each slice the possibility to be individually clocked at slower rates like 1/2, 1/3, 1/4, 1/n, ... of SGPIO_CLK. This is particulary useful for generating the SCLK (48 x Fs if the frame consists of two 24-bit audio words). This is particulary useful for generating the WS (1 x Fs).

Actually for the SCLK and the WS generation, there is a degree of freedom as you can choose between dividing SGPIO_CLK by a certain number (by presetting the slice counter to a certain value), or loading slower patterns in the recirculating slice register like 110011001100... (inherent division by 2) or 111000111000111... (inherent division by 3) or 1111000011110000... (inherent division par 4), etc.

There is also a possibility to physically output the slice clock, just after the local division. This way, as single SGPIO slice can output both WS and BCLK.

There is also a possibility to define a SGPIO slice for generating a hardware DMA request.

I may have not understood a few subtelities, but at this stage, I have the nasty impression that NXP managed to complicate the whole stuff.

I don't like the idea of using the CPU as master, involving the CPU into the audio clocks generation, especially the MCLK generation.

The recirculating register trick for generating MCLK forces you to double the quartz frequency. You need a special quartz. Or you need a frequency doubler, introducing jitter. I say doubling the quartz frequency, only if the local slice divider can be persuaded to divide by 1. This is perhaps done by presetting the slice counter with a value equal to 1. Right?

After watching the NXP presentation, I had the diffuse feeling that NXP wanted to impress people, showing how the SGPIO could cope with difficult situations, like when you get forced to have the CPU acting as master, and the Codec acting as slave. I was thus thinking that for a less difficult case like using the NXP LPC4330 SGPIO as I2S slave, relieving it from the MCLK generation and other audio clocks generation, that the SGPIO would appear as simple and ideal.

And now, according to twest820, that's no the case? Using the LPC4330 SGPIO as I2S slave isn't so simple and ideal? You can't use the incoming SCLK as SGPIO_CLK, and use the WS for synchronizing the whole stuff like for triggering the data buffer swap?

Is there a NXP SGPIO library now, giving examples for building I2S slaves?
 

Attachments

  • LPC4330 SGPIO YouTube.jpg
    LPC4330 SGPIO YouTube.jpg
    39 KB · Views: 46
  • LPC4330 SGPIO YouTube Robert Cassaro.jpg
    LPC4330 SGPIO YouTube Robert Cassaro.jpg
    18.1 KB · Views: 46
  • LPC4330 SGPIO YouTube 04.30.jpg
    LPC4330 SGPIO YouTube 04.30.jpg
    55.4 KB · Views: 48
  • LPC4330 SGPIO YouTube 05.45.jpg
    LPC4330 SGPIO YouTube 05.45.jpg
    51.3 KB · Views: 60
  • LPC4330 SGPIO YouTube 07.05.jpg
    LPC4330 SGPIO YouTube 07.05.jpg
    54.7 KB · Views: 55
  • LPC4330 SGPIO YouTube 07.10.jpg
    LPC4330 SGPIO YouTube 07.10.jpg
    53.1 KB · Views: 54
  • LPC4330 SGPIO YouTube 07.35.jpg
    LPC4330 SGPIO YouTube 07.35.jpg
    42.3 KB · Views: 58
Last edited:
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.