yet more DAM1021 filters....

The main purpose of this blog is to document my experiments with custom filters for the Soekris DAM1021 R2R DAC.

I had been posting up filters at DIYAudio since Feb 2015, but the nature of the forum makes it extremely difficult to organise and impossible to manage the filters. The result has been that it's not exactly clear what is a "hey check this out" experiment and what's a serious attempt at a finished filter. In mid-June 2015 I requested the mods to disable my account on DIYAudio, and will no longer be active on that forum.

Please note that the comments are moderated, so won't appear until they have been approved.

Truncate vs Round

 

I've been looking at how the SKR files are encoded and came across something I thought was a little odd.

It appears that the MKROM.exe is simply truncating filter coefficients.
It only effects the LSB where the value to the right of the rounding point is greater than 0.5.

It's not a huge issue as the difference between truncated and rounded is 1 LSB and this has fairly minimal impact on the accuracy of the filter.
But it's just as easy to round as truncate, so for my own code I'm using rounding.

Below are a couple of comparisions between the output of the MKROM.exe and the coefficient processor I'm working on.

Differences between the two are highlighted in red.

FIR1

FIR2

Apart from the difference in rounding (an improvement imo) my conversion function looks like it's working ok.
Next task on the to-do list is a (robust) parser for the skr config file (now done).

Update

After getting the conversion working 98% I got stuck with the checksum - which isn't currently used fwiw - and ended up shooting an email to Søren, who very kindly sent me code snippet.

I think I probably would have got there in the end, as my code was pretty close - the main issue I had was that MATLAB was "helpfully" converting a 2 byte integer into a double rather than letting it overflow.
Once I solved this minor issue using bitand() to mask the lower 16 bits things fell into place fairly quickly, and my checksum function only needed fairly minor changes.

With both utilities truncating the generated .skr files are identical:

 

RoomEQ and Crossovers with the DAM1021

Update: Tested a new version of the firmware this morning and this appears to have rectified the issue withonly the first IIR loading.
I've just sent Søren email confirming that a filter with HPF, 5 peaking eq and a LPF works so I'd expect Søren will post the update release on DIYAudio in the not too distant future.

----------

Important Note: RoomEQ and Cross-over functionality requires uController firmware Rev 0.99  20151018 or later.

---------

Background

The clues on how to build crossovers have been in the filter template file, probably from the very first revisions of the firmware but the 0.99 filter config makes it a bit more obvious.

The filter template includes a note that there are 15 IIR filter slots available for use. One of these slots is taken by the CD de-emphasis filter which should be coded to load on demand, leaving 14 availabe for user filters.
0.99v filters include a DC Blocking filter by default which always loads and operates. This can be removed from the configuration file if needed.

The DC Blocking filter offers a big clue to how the IIR filters operate:  if an IIR filter is present it will always be included in the filter processing chain.

Toolkit

This is probably going to be the major challenge in the process.  I've been having a look around and the tools for creating IIR crossovers are fairly thin on the ground. 

Update: I've discovered that MiniDSP's "advanced biquad programming" uses the IIR biquads that are required for the DAM1021 IIR filters.

Charlie Laub's Active Crossover Designer spreadsheet and it's accompanying documentation look to be the best place to start for creating "real world" active crossovers:

I'll try to go through the ACD tutorial and add information on translating the output from ACD -> DAM filter files.

There is a more basic spreadsheet available on miniDSP website that will produce a range of filters suitable for cross-overs, so might be a good starting point.

 Download here: custom biquad programming spreadsheet

I'm sure there are other filter creation tools available - the main criteria is that filter created is an IIR, not FIR.

In addition you'll need a text editor and the MKROM.exe for the 0.99 filter format and the template file for the 0.99 filters:

The Process

The key thing here is creating the IIR filter to add to the DAM1021. Once you have your filter the rest is relatively straight forward.
For this example I'll use the miniDSP spreadsheet to create a low pass filter with a 120Hz corner frequency.

A key point here is that you'll need to make 2 versions of each filter - one for Fs = 352800, and a second for Fs = 384000.

The image below shows the basic setup for the 120Hz LPF.  The three fields that adjust configuration are Freq., Q and Fs, so fairly straight forward.

The filter template file includes a comment that

IIR Coefficients is b0, b1, b2, a1, a2. a0 is assumed to be 1.0000

The spreadsheet creates the required values, listed under the Digital Coefficents heading.

In this case these values are:
 

a0    1
a1    1.995730285140360
a2    -0.995734842756604
    
b0    0.000001139404061
b1    0.000002278808123
b2    0.000001139404061

To transform these coefficents into a suitable format for the DAM it is simple matter of rearranging so the b values are first and removing the a0 value, and removing the prefixes.
The result is a list of five coefficents:

0.000001139404061
0.000002278808123
0.000001139404061
1.995730285140360
-0.995734842756604

To complete the filter a identifying header is required. This follows the standard format for all filters:

-- Format:
-- signature, samplerate, interpolationrate, type, numbercoefficients, multiplier
-- type 1 = FIR1, 2 = FIR2, 16..30 = IIR, 30 = Deemphasis

Take the DC Blocking filter as an example:

--
-- DC Blocking -3db @ 2 hz, 1st order, 352.8K/384K Samplerate
--

dam1021,352800,8,29,5,1
29 DC Blocking IIR, 352.8 Ksps, 2 Hz HP 1st order

 1.00
-1.00
 0.00
 0.99996438167
-0.00

This shows:

signature = dam1021
samplerate = 352800
interpolation rate = 8 (upsampled x8 to final sample rate of 2.8224 MHz)
type = 29 (for the IIR filters use a value between 16-29)
number of coefficents = 5
multiplier = 1 (gain applied to the filter stage)

So to construct this header for the new IIR filter, only 2 values need to be set - sample rate and type.
In this case sample rate is 352800 and it seems logical to start at the lowest available number for type.

dam1021,352800,8,16,5,1

The description is a completely arbitary text string which identifies the filter when "filters" or "filters all" command is used in uManager, so for eg.

16 120Hz LPF 1st order

Putting it all together:

dam1021,352800,8,16,5,1
16 120Hz LPF 1st order

 

0.000001139404061
0.000002278808123
0.000001139404061
1.995730285140360
-0.995734842756604

Repeat the above process for 384000...

The end result will look something like the following:

dam1021,352800,8,16,5,1
16 Test 120Hz LPF 352.8KHz

0.000001139404061
0.000002278808123
0.000001139404061
1.995730285140360
-0.995734842756604

dam1021,384000,8,16,5,1
16 Test 120Hz LPF 384KHz
    
0.000000961939483
0.000001923878965
0.000000961939483
1.996076859456820
-0.996080707214753

All that remains is to cut and paste these two filters into the filter template. I'd suggest respecting the number ordering of the filters and inserting these user IIR filters just above the DC Blocking filter.

To finish off, save a copy of the template file as 1021filt.txt into the same directory as the MKROM.EXE, open up a dos prompt in the directory and type

MKROM.EXE 1021filt

The filter .txt must be named 1021filt.txt or the MKROM.exe will report an error.

If all is well you should see a list of filters, including the ones you've just added and a 1021filt.skr will be created in the same directory.

Soekris Engineering mkrom utility vers 0.93, 20150815 
Reading 1021filt.txt 0x5d6a9 Bytes
04 Linear Phase FIR1, 44.1 Ksps, 0-19.7 Khz - 1 db, 22.3 Khz -150db
04 Linear Phase FIR1, 48 Ksps, 0-21 Khz - 1 db, 24.3 Khz -150db
05 Mixed Phase FIR1, 44.1 Ksps, 0-19.6 Khz - 1 db, 22.6 Khz -150db
05 Mixed Phase FIR1, 48 Ksps, 0-20.5 Khz - 1 db, 24.6 Khz -150db
06 Minimum Phase FIR1, 44.1 Ksps, 0-19.2 Khz - 1 db, 24 Khz -100db
06 Minimum Phase FIR1, 48 Ksps, 0-20.2 Khz - 1 db, 26 Khz -100db
07 Soft Minimum FIR1, 44.1 Ksps, 0-20.2 Khz - 1 db, 25.2 Khz -50db
07 Soft Minimum FIR1, 48 Ksps, 0-22 Khz - 1 db, 29 Khz -50db
04 Linear Phase FIR1, 88.2 Ksps, 0-35 Khz - 1 db, 45 Khz -150db
04 Linear Phase FIR1, 96 Ksps, 0-38 Khz - 1 db, 49 Khz -150db
05 Mixed Phase FIR1, 88.2 Ksps, 0-34 Khz - 1 db, 45 Khz -150db
05 Mixed Phase FIR1, 96 Ksps, 0-37 Khz - 1 db, 49 Khz -150db
04 Linear Phase FIR1, 176.4 Ksps, 0-66 Khz -1 db, 90 Khz -150db
04 Linear Phase FIR1, 192 Ksps, 0-72 Khz -1 db, 98 Khz -150db
05 Mixed Phase FIR1, 176.4 Ksps, 0-63 Khz -1 db, 90 Khz -150db
05 Mixed Phase FIR1, 192 Ksps, 0-68 Khz -1 db, 98 Khz -150db
04 Bypass FIR1, 352.8 Ksps
04 Bypass FIR1, 384 Ksps
08 Linear Phase FIR2, 352.8 Ksps, 0-83 Khz -1 db, 209 Khz -100 db
08 Linear Phase FIR2, 384 Ksps, 0-76 Khz -1 db, 192 Khz -100 db
16 Test 120Hz LPF 352.8KHz
16 Test 120Hz LPF 384KHz

29 DC Blocking IIR, 352.8 Ksps, 2 Hz HP 1st order
29 DC Blocking IIR, 384 Ksps, 2 Hz HP 1st order
30 Deemphasis IIR, 352.8 Ksps, 50/15 uS
30 Deemphasis IIR, 384 Ksps, 50/15 uS
Rounded to 0xef00 Bytes
Writing 1021filt.skr 0xef00 Bytes 

That is basic process for adding in IIR crossover filters.
It should be possible to create far more complex filters by "stacking" additional IIR biquads in the filter positions 17-28 for eg.

1021filt.txt with the example IIR filter inserted near the end of the file: 1021filt.txt

Room EQ

At this point, it's entirely possible but slightly fiddly.

Add: Got a reply from the REW developer and while he has support custom equalisers on the "todo list" which would simplify the process, his current recommendation is to use the MiniDSP spreadsheet to cacluate the biquad coefficents as described below.

A rough procedure is:

  1. Use REW to generate correction EQ;
  2. Export filter settings to file;
  3. Use MiniDSP spreadsheet to create filters to specs at 352800//384000;
  4. Add coefficents to 1021filt.txt;
  5. Create .skr with MKROM.exe

I'm still without an audio interface so I'm not able to use Room EQ Wizard correctly, so ended up with a filter with the following specs...

Filter  1: ON  PK       Fc     90 Hz  Gain -99.0 dB  Q  2.00

The PK indicates it's a peaking eq, and this filter can be created using the MiniDSP spreadsheet PeakingEQ tab.

Type in the specs from REW into the approriate calculator:

Then copy the required coefficents in the order: b0, b1, b2, a1, a2

0.900976338179341
-1.801948500338870
0.900974116026889
1.801948500338870
-0.801950454206231

As noted above you need to do this with sampling rates at Fs = 352800 and Fs = 384000.

Add  header and description to each block of coefficents:

dam1021,352800,8,16,5,1
16, 90Hz -99dB Peaking EQ, 352.8KHz

0.893154824513051
-1.786304956718700
0.893152426840975
1.786304956718700
-0.786307251354026

dam1021,384000,8,16,5,1
16, 90Hz -99dB Peaking EQ, 384KHz

0.900976338179341
-1.801948500338870
0.900974116026889
1.801948500338870
-0.801950454206231

And at this point the filter can be pasted into the 1021filt template file and process with MKROM.exe as above.

With the filters + EQ loaded into the DAM, playing 44.1KHz white noise the output looks like this:

From the above it's clear that the calculated curve shown in the spreadsheet is being applied correctly by the DAM1021.

You can use up to 13 biquads, so it's possible to do fairly complex Room EQ in this way.
I'd recommend that you get a good impulse capture and an EQ in REW before you start building filters, but it's really pretty simple once you've followed the workflow a couple of times.

Back to the Future: inter-sample clipping and headroom

Zfe has posted a comment, pointing out that it is still possible to have clipped samples with interpolated filters.

There was some discussion in the DIYA filter thread regarding clipping on full scale square waves, as this was the worst case scenario. Sine waves were fine at full scale/0dB, but additional headroom was need for the square waves test signals with non-NOS filters.

The issue is called "inter-sample clipping", and it's probably fair to say it's actually a widespread producition issue rather than replay problem as such.

Apple recommend that tracks mastered for sale on iTunes have 1dB headroom above any inter-sample peaks.  There is some good analysis of these recommendations here (translated from a Russian article by Alexey Lukin of Izotope).  The conclusions reached are:

Apple’s recommendation on signal peak levels is valid: the headroom of 1 dB is necessary and sufficient for preventing clipping in musical material.

The process of adaptation of existing published CDs for iTunes distribution should include limiting of the signal to −1dBTP (true peak) levels and saving it to a 24-bit format.

"True peak" is the level of the inter-sample peaks, rather than peak sample values. Unfortunately standard mastering practice is to normalise so that peak sample values are just below 0dBFS.

How bad is the problem?

If you take a look at Apples mastering tools for iTunes (available on this page) there is a commandline tool called afclip that identiifes clipped samples and inter-sample clipping.  Running afclip on a rip of Chesky CD 1002.3Hz 0dB square wave identifies 1,262,490 inter-sample clipping events in both left and right channels, with a peak value of +1.707367dB. 

This is an excerpt from the afclip help:

afclip prints clipped samples in a sound file and the value, channel, sample number, and time of each.

If there is clipping, afclip also writes a sound file containing the left channel of the original file and a right channel which contains impulses corresponding to each clipped sample in the original.

If the left channel clipped, the impulse is +0.5, if the right channel clipped then the impulse is -0.5, if multiple channels clipped, the impulse is +1.0,

Even if no digital samples are clipped, the analog waveform may clip in between samples when reconstructed. Therefore afclip upsamples the input by 4 and checks those samples for clipping. This can be turned off with the -i option.

Doing a quick survey of some recent downloads from Bandcamp, there is clearly little attention paid to this issue on other platforms.

As an example: Tor.ma meets the Mexican Trancers in dub recent album Mara'akames Gathering is normalised to -0.1db but has intersample peaks of up to +1.88dB on at least one track, so will effectively be clipped when played back.

With these tracks 3dB headroom would give at least 1dB headroom above inter-sample peaks, as per the Apple iTunes store recommendation.

Benchmark have decided to go down the added headroom path with their DAC2 series of convertors as discussed in this post on their blog. Benchmark have settled on +3.5dBFS headroom in their DSP engine.

I've added an updated version of the EQHQ Variations filters with 3.5dB "headroom" here: http://www.moredamfilters.info/content/eqhq-variations-v1

Update

To illustrate the problem I've attached a couple of screen shots from Bitscope-DSO of the output from the DAM1021 - buffered (no feedback cap) and unbuffered.

First shows the standard EQHQ variations filter with the 7.8 gain coefficent playing a 1001Hz 0dBFS Sine wave with level set to 0dB

The sine wave shows no indication of clipping on either buffered or unbuffered ouputs.

The same cannot be said for a 1002.3Hz 0dBFS square wave:

Contrast the clipped waveform above with how the same square wave reproduces using the added 3.5dB headroom version of the filter...

CD's that aren't afflicted by  "normalize to -0.1dB" are far less likely to suffer the problem, but seems that it's so prevealent with modern recordings that running with added headroom is sensible.

Repairs update

The DAM is back from having FPGA swapped and while the results were initially promising it seems there might be a minor alignment issue which is preventing correct operation.

I was able to sucessfully replace and reprogram the STM32, and had the "unlock" flash happening but I was able to get a lock with a audio stream.  Checking with a logic analyser I could see the intial setup code sent to the Si514 but there was no further data transmitted which would suggest FPGA was at least partially operational. Testing with a TOSLINK signal on the SPDIF2 input I could see a signal as far as the input protection diodes which was the last//only component between the input header and the FPGA.

While the uManager reports a FPGA firmware version, the "filters" command returns a blank list, which indicates that there is either a communication problem with the FPGA, or that filters aren't loading because the DAC hasn't locked to a signal.

Anyway, it seems that without investing in something like StencilQuik ( a "solder in place" stencil that helps to locate BGA chips correctly) and a hot air rework station I unlikely to get the board up and running. Given the number of pads that lifted when I did the "hot plate" solder job on the first board I'm tempted to get the repairer to pull the current FPGA so I at least know if it's worth trying again.

I've resigned myself to the fact that it's unlikely to be repaired anytime soon, so I've ordered an "EOL" 0.02% board as a replacement.

Reprogramming the STM32 uController

 

After trying to follow my previously posted method of reprogramming the STM32 without any luck, I thought it might be an idea to document a more robust hook up.

Looking at the ST-Link/v2 docs I noticed that pins 1 & 2 on the programmer are used to detect "Target Voltage".
Swapping the DAM's 3.3V and GND from pins 19 & 20 to pins 2 & 4 (4 = GND) didn't have the desired effect.

What does work is a 6 wire connection.

DAM -> ST-Link

SMD-3.3V -> Pin 2   (Target Voltage detect)
SMD-GND -> Pin 4 (GND)

SMD-SWDIO -> Pin 7
SMD-SWCLK -> Pin 9

J2-3.3V -> Pin 19 (Target Power)
J2-GND -> Pin 20 (GND)

Illustration of hookup below (thanks to glt for the pilfered dam pcb photo!)

The advantage of this hookup is that the ST-Link powers the board, and correctly senses the target voltage levels.

Make sure that you disconnect everything from the DAM1021 before attempting hooking up the programmer.

With the DAM hooked up, fire up the programming software then go into settings.  The Programmer serial should be shown regardless of whether the STM32 is detected or not.  If the connection between the ST-Link and DAM is correct you should see a Target Voltage of 2.7-3.3V or there abouts, and the type of STM32 chip installed on the board displayed.  If not you have some trouble shooting to do!

Once you have the target displayed as "Detected", go to the Target menu and select "program and verify". If you haven't loaded the uManager .bin file, you will prompted to select it at this point.

With any luck the firmware should load program and verify in a matter of seconds....

DAM1021 Rev 2 Availability and pricing

Søren has updated the first post of the DIYAudio vendor thread with details of the Rev 2 boards.

The new boards will be available mid-September, so probably 1-2 weeks.  Oddly the .EU store is showing the REV2 boards as "in stock", and the 0.02% as EOL, and availble until stocks are exhausted.

Pricing is

dam1021-05: USD 195 / EUR 174 (0.05% resistor version)
dam1021-12: USD 295 / EUR 263 (0.01%/0.02% resistor version)

The 0.01/0.02% is same price as the old 0.01% board if you look at Euro pricing, or $40US cheaper if you look at the USD pricing.

I'll have to check the total costs again to see how price//shipping//exchange rates pans out.

Crunching the numbers

US:  295 (DAM)+123 (shipping) = $418US  or $592AUD

EU: 263 (DAM) + 92.57 (shipping) = 355.57Euro or $564AUD

It's a pity the turn around on orders and shipping time from .dk is so slow. It seems to take 1 to 1.5 weeks longer than an order from the US to reach AUS.

Time to give up?

AIt looks like I've killed a second DAM in a similar way to the first.

I've been trying to get to the bottom of my SSR04 weirdness which is increasingly looking like a faulty D44H11 or alternatively just rectifier noise on the ground plane.  I've now tried replacing the opamps with LT1028 (no improvement), swapping the zeners for red LED's (no improvement), add compensation caps to limit op-amp bandwidth (no improvement), swapping smothing caps (no improvement) and replacing BC556 transitiors on the positive reg (no  improvement), replacing bridge rectifiers (no improvement).

Anyway, when I was checking the output of the 3.3V reg and shift register VCC to see if there was any measurable improvement, I noticed that the zener/LED on the postive rail was very dim, and the +ve rail was measuring only 3V.  Unplugging from the DAM the voltage was back to +12.5V.  Sure enough the resistance between GND and +3.3V was 0 ohm. Removing the 3.3V reg gave the same result which indicates the digitial section has taken a hit - possibly a short to +12V when I was probing the regulator pins.

Next project is attempting to ID the fault but if it's anything like the other DAM I killed messing with 3.3V regulators it is a right off until I can get the Spartan-6 FPGA's replaced.

And a big thanks to those who have been kind enough to make donations to the site thus far... These contributions will help ease the pain of getting the boards back up and running.

Update

As the likelihood of successfully repairing the boards at a cost that is not prohibitive appears to be fairly slim, I've put the donations on hold for the moment.  The continuing slide of the $AUD vs USD and EURO is making the DAM look significantly less attractive than it did when I purchased the 0.02% board originally.  If Søren's indicative pricing for the new combo .01/.02% of midway between the current pricings is correct then I'll be looking at $540AUD landed at current rates, and that is likely to worsen by the time the revised DAM finally hits the stores.  Nice as it is, I still getting significant pops on input changes with current firmware and the prospect for solid remote control is still not great, and I know I'm going to have to write my own firmware to handle wired IR.

After burning two boards, I'm now seriously considered throwning the towel in on the DAM and buying something like the Audiolab m-dac that basically does out of the box what I'd (mistakenly) thought would be straight forward to implement with the DAM.  

Update 2

At this point I'm still waiting to see if the DAM is repairable.

After a fair bit of thought and taking into account the support from those who made donations to the site, I'll decided that if it turns out to be unrepairable I'll buy a Rev 2 board as a replacement.

As an interim measure for testing, I'm going to pick up a SPDIF -> TOSLINK converter. This will let me use my Sound Devices SD722 as an ADC by routing via the SPDIF outputs -> Macbook Pro optical input. It's definitely a short term solution as the SD722 isn't something I want to abuse in any way...

Excuse the mess

I have to apologise for the intermittent issues with access and disappearing images etc.

I'm still trying to "harden" the site, and have had a few issues with the recommended permissions blocking access to image directories and the like.
This should be fully sorted out in the next day or so.

Filter Loading from .skr

I and others have noticed issues immediately after loading a filter set from .skr file.

The problem manifiests as distorted play back or even silence on occassion, and is not fixed by simply changing inputs or sampling rates.

If you log into uManager and use the "filters" command to list loaded filters it should show (from memory) that the orignal FIR1 filter remains active even after an input or sample rate change.  I can't retest this to see exactly which sequences work and which don't until I have an operational DAM but this "brute force" method does work:

  1. Toggle inputs: I3 +return is simplest way to do this if you have only one active input, then;
  2. Toggle filters: typing F7 +return then F4 +return will do the job.

It shouldn't be too difficult to script the input toggle followed by filter toggle.
Without these two steps I found the filters end up as a hodgepodge of the previously loaded FIR1 and the new FIR2.

 

Pages

Subscribe to moreDAMfilters RSS
Membership