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.
Yeah it's quite difficult to even get the software tools without buying their evaluation kits.
Yeah. And it happens I'm not one to drop $200+ to evaluate an apparently not especially great DSP bound to a decent but not exceptional DAC for a hobby. ;) While 102 biquads certainly fit in banks A and B I wouldn't necessarily assume both banks can be used simultaneously or that the banks and instructions per sample aren't shared with the antialiasing filter. Given possession of the GDE it's probably easy to figure that out. And get confirmation the instruction set's capable of a single precision biquad in 10 clocks or less. But, since TI holds the instruction set proprietary and doesn't provide alternate documentation, I'm not sure there's much to do about the data path and MAC but guess. The part's modern enough but low end enough I'd figure probably 24 bit data and 48 bit MAC.

Without also knowing things like the number format it's hard to express a compete statement against the SigmaDSPs. Which is a bit weird as those are obviously the market TI's going after. It's tempting to interpret TI's unwillingness to disclose as an indication the SigmaDSPs are more capable for DSP maths. But perhaps they've other reasons. I mean, really? 'cmon TI.

I'd gotten a fair ways along designing with the ADAU1442 before the LPC4300s became available so appreciate the convenience of a turnkey design tool, simplified programming, and less board layout. Using an M4 to get more guard bits than the SigmaDSPs and high precision biquads is certainly more complex.
 
To throw another idea out there, how about building something based on a FPGA? Say, a Spartan-3A 200 - the chip's got 16 18x18 multipliers that can run at ~250MHz, and the chip's about 10 bucks.

You could time-multiplex them or use multiple multipliers to do 36x36 multiplies which is well beyond what you'll ever need for audio processing. Building IIR/FIR blocks around these wouldn't be too hard, same with adding I2S audio input/output.

You could run a microblaze/picoblaze in there, or use an external uC to provide a configuration/control surface.

ISE tools are free, and a $50 Diligent HS2 pod does everything you need.
 
To throw another idea out there, how about building something based on a FPGA? Say, a Spartan-3A 200 - the chip's got 16 18x18 multipliers that can run at ~250MHz, and the chip's about 10 bucks.

In fact I just ordered DE0-Nano kit to learn Fpga and possible do just that xover thing using it. Most fpga filters seem to use FIR, maybe because its easier to get right. IIR filters are possible but in limited range fixed point arithmetics there are more like to be some issues.

Regarding TI minidsp I found this document describing assembly code of TAS3108:

http://www.ti.com/lit/ug/sleu067a/sleu067a.pdf

Dont know how much it differs from miniDSP architecture.
 
Last edited:
To throw another idea out there, how about building something based on a FPGA? Say, a Spartan-3A 200 - the chip's got 16 18x18 multipliers that can run at ~250MHz, and the chip's about 10 bucks.

Fine notion, but OT as far as I can see. Unless there's an FPGA architecture that's licensed to various hardware vendors (as ARM does with its CPUs) and whose toolchain is at least somewhat open source.

@mhelin - TAS3108 going obsolete is a good example of why I'd like this thread to focus on hardware that's not tied down to one particular vendor. I've noted Bruno's got bitten by that - he decided to do a last-time buy of the devices for his forseeable needs. But now he's got a product containing a obsoleted device with no roadmap for any future enhancements without a major redesign. Precisely what I'd like to avoid in my own designs.
 
Last edited:
IIR filters work fine in fixed point. Floating point makes things seem easy in theory, but it's easy to lose sight of some things - eg you can't add a huge number to a small number without some loss of precision. Fixed point makes you think about things a bit more. And if you need floating point for your application, it's not too difficult to add floating point handling around a fixed point multiplier. I've implemented this in the past.

There's no "open source" FPGA vendor or synthesis tools that I'm aware of, but there's no reason you can't run the same code (with different vendor-specific blocks instantiated as needed) on an Actel or Altera part with similar multiplier/RAM blocks, or on a future FPGA from the same vendor if the existing one goes obsolete.

I think FPGAs are generally accepted by the open source community, despite proprietary synthesis tools - the work that's up on opencores is a pretty good indication of that.

Ultimately the FPGA/ARM choice comes down to this:

- FPGAs are harder to program, but they're a signal processing monster.
- ARMs don't have the same signal processing capability, but they're easier to develop on.
 
I
Ultimately the FPGA/ARM choice comes down to this:

- FPGAs are harder to program, but they're a signal processing monster.
- ARMs don't have the same signal processing capability, but they're easier to develop on.

I think there is ARM softcore for FPGA (yes, see http://opencores.org/project,storm_core , it could run at 80 MHz on my DE0-Nano with 40% device utilization, not bad). Anyway, both Altera (Arria V SoC and Cyclone V SoC) and Xilink (Zynq) have integrate ARM core(s) with FPGA on the same chip.

FPGA requires different thinking, though like if you know Python well you can use MyHDL for an example as an intermediate language. Some C-code can also be translated to Verilog for an example (see C to Verilog | Circuit design automation).

Regarding Cortex-M4 it is quite limited but very efficient with (dual) 16x16 multiplications with accumulation. This document tells what you can do and how you should do it:

http://www.arm.com/files/downloads/...ssing_Software_on_the_Cortex-M4_Processor.pdf

Wish the next Cortex M-version had dual (or rather quad) 32x32 MAC SIMD instructions (with saturation to be safe, don't want to break by tweeters).
 
Last edited:
Also, let's be fair. SGPIO and USIC are not ARM standard peripherals. So an ARM softcore with custom IO on an FPGA is, in practical terms, not as different from an LPC4300 or XPC4500 as one might perhaps think. There's also all the differences in tool chains, debuggers, and so on to consider.

Lots of ways to fry tweeters besides overflow. A scaling error or filter synthesis bug can do it, for example. Pretty much the only robust solution is to ensure the power amp channel driving the tweeter can't output more watts than the tweeter is rated for. Given reasonable gain budgeting and rail voltage selection this isn't that hard for the majority of tweeters and listening levels.
 
There appears be an Oldschool / Newschool dichotomy when it goes about speaker crossovers using Open Source DSP. Here is a perfect Newschool example.
At the moment I'm using my M-Audio Fast Track Pro as the output, it has 4 channels out. The player is JRiver. I just tell JRiver that I want 4 output channels and the convolver script text file does the routing, crossovers and such. I currently have a file for HP and a file for LP, each 24 bit mono wav. JRiver hits the 4 channels with Left Low, Right Low, Left High, Right High, then it's straight out of the Fast Track to the amps. So JRiver is doing the splitting into 4 channels, I tell the convolver which impulse to use and where to route it. Simple, but took some time to figure out.
Clearly, their "Open Source XO" is relying on FIR filters. The FIR filter gets executed by what they a call "a convolver".
What I'm suggesting is to refine the "script", for natively supporting IIR filters and FIR filters, enabling to cascade IIR BiQuads filters along with the FIR filter. Each FIR filter gets described just as usual, using a monophonic .wav file. Each IIR BiQuad filter would get described using a short stereo .wav containing 3 stereo samples. The non-recursive part of the IIR BiQuad would be described using the left channel. The recursive part of the IIR BiQuad would be described using the right channel. The script would be a text file just as usual, naming a succession .wav files.
 
Played little bit with the NGX LPC4330-Xplorer last weekend. Got it eventually working using LpcLink2 and LPCXpresso 6 software. Didn't find any SGPIO dualcore examples though, wondering where these have been buried as NXP made a big number of these features long ago. The lpc43xx git repository (for CMSIS project containing SGPIO I2S examples for Hitex boards & Keil MDK) seems to be gone, but I did found the remainders as a zip file.
The "Compliant Standard Peripheral Firmware Driver Library for LPC43xx" can be found here:
LPC43xx CMSIS-Compliant Standard Peripheral Firmware Driver Library (Keil, IAR) | www.LPCware.com
Page also tells "It is highly recommended to use LPCOpen for LPC43xx development work instead of this code package."

For LPCOpen there seems to be major refactoring going on, but v1.03 contains LPCXpresson compatible examples (without SGPIO) also for LPC4330-Xpresso. Anyway, the SGPIO doesn't seem to be a problem anyway- it's well documented with I2S examples on NXP user manuals for LPC43xx processors. Biggest problem is the intercommunication between M4 and M0 cores - the Hitex examples use some odd shared memory address in SRAM for which I haven't found any documentation (got to dig deeper I guess). Here the definitions:

Code:
#ifndef __BOARD_H 
#define __BOARD_H

///////////////////////////////////////////////////////////////////////////
//	shared memory between CPUs
//

#define HACK_BUFFER		0x10090020

#define sGPIO_buffer(x)		( * (volatile int *) (HACK_BUFFER + (x<<2)))

#define outta_sGPIO_buffer	( * (volatile unsigned char *) (HACK_BUFFER-4))
#define into_sGPIO_buffer	( * (volatile unsigned char *) (HACK_BUFFER-8))

However, there is the AN11177 application note with the IPC API which could be used instead of this "hack":

Code:
[url]http://www.lpcware.com/content/nxpfile/an11177-inter-processor-communication-lpc43xx[/url]

In case of some own experiments I guess any SRAM location not known to be used could be used as shared memory making things simpler. In the IPC API actually the message buffer is defined as global array in c-module like this:

#include <stdint.h>
#include "ipc_queue.h"
/* block holding registers (pointers) and data for the messages */
msgBlock hostMsgBufferControl __attribute__ ((section ("msgBuffer_section")));

/* buffer space holding messages */
msgToken _hostMsgBufferData[MSG_BUF_LEN] __attribute__ ((section ("msgBuffer_section")));

The command buffer is defined similarly.
 
Last edited:
BTW. If you think LPC43xx is too complicated environment as a dualcore one then why not just to use only the M4 core for everything? It's still faster than many other M4s around. You can get the I2S with DMA running easily using the examples available, and the SGPIO setup quite easily. Then later when you want to have like an USB interface to PC for loading a new filter kernel or a set of coefficients then implement the interface on the M0 core.
 
Anybody studied LpcLink2 schematics? It uses the SGPIO interface for implementing the JTAG functionality. Also it's configurable, it means programmable, so you can load your own code to it using the LPC-Link2 Configuration Tool (LPC-Link 2 configuration tool | www.LPCware.com) - or by using another LpcLink2 board as it seems the J2 socket is connected directly to JTAG pins of the LPC4370 on board. So you could also program it to run your crossover stuff and use the SGPIO to connect to your audio converters. So it IS a development board after all.

Got to order another LPC-Link2 to see how it works...
 
Last edited:
See LPC4370 microcontroller and LabTool for high performance data acquisition | www.LPCware.com

LPC-Link 2 is an extensible, stand-alone debug probe that can be configured to support various development tools and IDEs using a variety of different downloadable firmware images. It can also be used as an evaluation board in its own right for the NXP LPC4370 triple core MCU. And through the use of an add-on board from Embedded Artists, it can be used as an oscilloscope or logic analyzer!


Here's the 99EUR (including LPC-Link2) 11 channel logic analyzer (up to 100Msamples per second) + 2 channel oscilloscope (up to 80 Msamples per second, 6MHz BW) + 11 channel digital signal generator (up to 80 Msamples per second) +2 channel analog signal generator (40kHz BW) board:

LabTool | Embedded Artists AB

Instead of LabTool board I'd like to see an audio interface board with multichannel DACs, an ADC and an S/PDIF receiver with a sample rate converter.
 
Last edited:
Try page 49 of this thread.
TRACEDATA pins on J8 are only available as SGPIOs if you hack the debug connector to 10 pin Cortex from 20 pin JTAG.

I think there's no need to hack anything as the 10 pin Cortex connector is what can be used anyway if you use another LPC-Link2 to program the target one (connection is from J7 in debugger to J2 in target socket). If you already have a JTAG debugger with the 20-pin socket there are adapters available (from Ebay at leas Olimex is selling one for few euros).

J8 can be made to transfer four I2S data outputs (TRACEDATA0..3) and one input (JTAG_TMS_SWDIO, requires just moving the SGPIO15 (to be reserved for generating DMA trigger pulse) to pin C6 (BOOT2, guess it's used after boot) out of way of the GPIO pin going to J4 to control direction for SGPIO14), rest of pins can be used for clocks (haven't check though, those are connected to SGPIO10, SGPIO11 and SGPIO12) and the J3 (Serial Expansion) can be used to control converters over I2C, UART might be useful for programming coefficients and as general UI.

I think it looks pretty good and clean to me. Got to check yet if MCLK input would be possible - maybe if JTAG_TCK_SWCLK and JTAG_TDI (SGPIO11 and SGPIO12) are used as MCLK and BCLK. The proper slave mode with SPGIO might be impossible, you would need to configure the LRCK input pins for pattern matching and then in interrupt service routine copy the data from the shadow register to memory buffer assuming the counter has reached zero at this point and the REG and REG_SS have been swapped for that slice.

E: JTAG_TDI = SGPIO12 can be used as clock source (MCLK output/input) but the TAG_TCK_SWCLK cannot be used as BLCK output at the same time if MCLK is input (unless you remove U3 8-pin chip and jumper pins 2->7 and 3->6 which is easy though as the pins are opposite pins, but it's a hack anyway). Anyway, there should be no problems using master mode - maybe there are other ways to input MCLK to generate BCLK and LRCK from it.
 
Last edited:
You're right. I'd somehow failed to register J7. Dang. Facepalm.

J3 would presumably be in use for I2C and at least a reset line to the codec or DAC. It conveniently happens the LPC-Link 2 pins SSP1_SCK out on PF_4, which is also GP_CLKIN, and SSP1_SEL is pinned to P1_20, which is also SGPIO13. So, without overloading any JTAG pins shared with J7, J3 plus J8 offers a slave MCLK and six SGPIOs in addition to I2C and 8 GPIOs.

A limitation of using J8 is the T junction introduced on the JTAG lines. One issue its effect on signal integrity. If the ribbon's short, trimmed, or a 10 pin ribbon happens to fit on the high pins J8 (at 50 mils probably not likely unless one sands down the connector) that's easy enough to avoid. A bigger problem with picking up SGPIO12 via JTAG_TDI is the recipient of that line will see debug traffic as I2S. So it would be preferable to use it as a data output from the LPC4300 to avoid strange clocking and contention between the debugger and an audio device driving the line. It's difficult to guarantee a clean transition to an input when entering debug such that no contention would occur between the LPC4300 and debugger.

If a seventh SGPIO line is needed a more reliable and easier approach would be to take SGPIO9 from J4.

However, with the exception of accessing SGPIO13 from J3, all SGPIOs route through U4 and therefore go in the same direction. So using the LPC-Link 2 for XO and EQ with an I2S input requires lifting at least some of the pins on U4. I find this an odd design choice as it would seem to significantly increase the probability of users needing to hack the board. For asynchronous USB input it does look pretty turnkey as all SGPIOs can be outputs with MCLK brought in from J3---up to triamp from J8 with three I2S lines and quadamp with J3.

As an aside, U3's direction pin is brought out to J4 along with U4's direction pin. So use of TAG_TCK_SWCLK doesn't require removing U3. It just has all the same problems as trying to use JTAG_TDI for SGPIO. ;)
 
Last edited:
You're right. I'd somehow failed to register J7. Dang. Facepalm.

J3 would presumably be in use for I2C and at least a reset line to the codec or DAC. It conveniently happens the LPC-Link 2 pins SSP1_SCK out on PF_4, which is also GP_CLKIN, and SSP1_SEL is pinned to P1_20, which is also SGPIO13. So, without overloading any JTAG pins shared with J7, J3 plus J8 offers a slave MCLK and six SGPIOs in addition to I2C and 8 GPIOs.

A limitation of using J8 is the T junction introduced on the JTAG lines. One issue its effect on signal integrity. If the ribbon's short, trimmed, or a 10 pin ribbon happens to fit on the high pins J8 (at 50 mils probably not likely unless one sands down the connector) that's easy enough to avoid. A bigger problem with picking up SGPIO12 via JTAG_TDI is the recipient of that line will see debug traffic as I2S. So it would be preferable to use it as a data output from the LPC4300 to avoid strange clocking and contention between the debugger and an audio device driving the line. It's difficult to guarantee a clean transition to an input when entering debug such that no contention would occur between the LPC4300 and debugger.

If a seventh SGPIO line is needed a more reliable and easier approach would be to take SGPIO9 from J4.

However, with the exception of accessing SGPIO13 from J3, all SGPIOs route through U4 and therefore go in the same direction. So using the LPC-Link 2 for XO and EQ with an I2S input requires lifting at least some of the pins on U4. I find this an odd design choice as it would seem to significantly increase the probability of users needing to hack the board. For asynchronous USB input it does look pretty turnkey as all SGPIOs can be outputs with MCLK brought in from J3---up to triamp from J8 with three I2S lines and quadamp with J3.

As an aside, U3's direction pin is brought out to J4 along with U4's direction pin. So use of TAG_TCK_SWCLK doesn't require removing U3. It just has all the same problems as trying to use JTAG_TDI for SGPIO. ;)


The JTAG_TDI is just a name for that signal in debugger configuration, in target configuration it could be used for anything, in reality it is just SPGIO12 (with some other functions as ENET_TX etc. you can see in PinMux tool). The real JTAG pins are named LPC4370_<JTAG function>, so for an example LPC4370_TDI is the "real" JTAG_TDI. So no problems there.

I'd like to keep J3 connections in just control functions, it is also possible to build a converter board which is hardware configured not needing I2C or anything, and once youve got your crossover ready you really don't need any inteface for uploading coefficients either.

So what would work well for 1xI2S input (well, two inputs one for digital and another for analog might be useful) and 4xI2S ouput could look like this:

I2S_SDI JTAG_TCK_SWCLK (J7, J8) SPGIO11
I2S_MCLK JTAG_TDI (J7, J8) SGPIO12

I2S_SCK JTAG_TMS_SWDIO (J7, J8) SGPIO14

(alternative:
I2S_SCK TRACECLK_RTCK (J8) SGPIO8
I2S_SDI_1 JTAG_TMS_SWDIO (J7, J8) SGPIO14
)

I2S_WS JTAG_TDO_SWO (J7, J8) SGPIO10

I2S_SDO_0 TRACEDATA0 SGPIO0 (J8)
I2S_SDO_1 TRACEDATA1 SGPIO1 (J8)
I2S_SDO_2 TRACEDATA2 SGPIO2 (J8)
I2S_SDO_3 TRACEDATA3 SGPIO3 (J8)


TRACECLK_RTCK is also an output on J8, so the JTAG_TMS_SWDIO could be made another input and TRACECLK_RTCK would become SCK (I2S bit clock).
 
Ah, supporting only target and hence having J2 the only connector handling JTAG makes more sense. Thanks for clarifying intent and taking a closer look at the board than I did a few pages ago. I think you'd want something closer to

J8 inputs (direction controlled by DIR_U3 on J8 and P1_5 - SGPIO15_TMS_SWDIO_TXEN)
  • I2S_SCK - JTAG_TMS_SWDIO SGPIO14
  • I2S_SDI - JTAG_TCK_SWCLK SPGIO11
  • I2S_WS - JTAG_TDI SGPIO12
as not having an LRCK would make the receive a little tricky. :) All codecs I can think of allow SDI to be switched between their ADC and SPDIF receiver so 7400 muxing logic would only be required on "codec" boards implementing the two with separate chips.

I would probably do something like this for the outputs on J8.
  • I2S_SCK - JTAG_TDO_SWO SGPIO10 - needed if SCK not shared between I2Ses on codec board, requires MCLK via J3
  • I2S_WS - TRACECLK_RTCK SGPIO8
  • I2S_SDO_0 - TRACEDATA0 SGPIO0
  • I2S_SDO_1 - TRACEDATA1 SGPIO1
  • I2S_SDO_2 - TRACEDATA2 SGPIO2
  • I2S_SDO_3 - TRACEDATA3 SGPIO3
I'm not finding a manual for the LPC-Link 2 but looks like it ships set to boot from SPIFI flash. EXT_POW enables use of the board without USB plugged in and VIO_3V3Z provides an IO supply for the "codec". So I'm not seeing any reason why this wouldn't work. USD 40 for a pair of LPC-Link 2's from DigiKey or Mouser is tough pricing to beat too.

Also looks like the crystal's an HC-49 so swapping it to an audio clock for master mode execution would be an option. Might not be that clean of an MCLK but it's likely lower phase noise than using the fractional audio PLL.
 
Last edited:
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.