Aww, I'm such an idiot. The answer is so simple. The passband isn't wide enough! When you click the IQ button on the Kiwi it sets IQ demod mode, but also sets a default passband. But that's just how the Kiwi user interface works.
With kiwirecorder when you change the mode with "-m iq" the low-level command it's sending on the web socket only changes the mode. It doesn't know anything about the passband. You'll get whatever the last passband was. The default for a new Kiwi connection is USB 300 - 2700 (2400 wide).
This is of course not what you want with IQ mode. So try something like:
I was trying to use the Kiwi pmux code because it makes it easier to move the CS1 pin. But it was harder to back-port this code into sdgps than I thought it would be.
If the GPS clock is different you must change a few things. I'll talk about the Beagle_GPS code below.
1) In gps/gps.h change the constants FC, FS and FS_I to match what your front-end chip produces.
2) Further down you'll see the constants FFT_LEN and NSAMPLES are a function of FS_I. So this will be the size of the acquisition FFT assuming no decimation (DECIM = 1). But there are several aspects of the Verilog that depend on these constants, and they are not automatically taken into account as FS and FS_I are changed. So you have to check the sizes and adjust the Verilog if necessary. For the SE4150L the clock is 16.368 MHz, so FFT_LEN and NSAMPLES is 65472. In verilog/gps/sampler.v the size of the sampler memory is 1-bit by 64k (65536). So NSAMPLES just fits. If your clock if faster you need to increase the size of the memory. Some chips like the MAX can give you a range of output clock frequencies which helps. If your clock is slower it doesn't matter -- the buffer will just be larger than it needs to be. The code in gps/search.cpp:Sample() and e_cpu/kiwi.gps.asm:CmdGetGPSSamples() always moves the correct amount of data.
3) The other piece of Verilog that changes depending on clock frequency is the maximum size of the integrators in the tracking loops. Look at Andrew's article: http://www.aholme.co.uk/GPS/Main.htm Go down to the tracking loop diagram in yellow and green. See how the yellow parts are in the FPGA hardware clocked at 10 MHz? The 10 MHz shown is the front end clock rate, so on the Kiwi this is really 16.368 MHz. The integrators shown (sigma symbols with n = 1 .. 10000) accumulate the input bit stream for one PRN repetition period (one millisecond). 10 MHz times one milliseconds is 10000. So the integrators must be at least 14-bits wide (2^14 = 16384, 2^13 = 8192 would be too small).
For the Kiwi clock the value is 16368. I can't remember why but I ended up using 16-bits (2^16 = 65536). I think there is some rounding in the integrators that would cause 2^14 to overflow in some cases, so at least 15-bit would be needed (see the business with the "lsb" register). This integrator width is in verilog/gps/demod.v Go to the comment that says "Down-convert to baseband". Then you'll see the integrator registers defined with [16:1] i.e. 16-bits. The integrator values are transferred all the way to the e_cpu code. So further down you'll see the serial transmission code that also takes the 16-bit register width into account.
If your clock rate fits into 16-bits (with some margin) then there is no need to change any of this. It should just work. I forgot another complication. The code in e_cpu/kiwi.gps.asm:GPS_Method() assumes the IQ samples will fit into an unsigned 16-bit value initially. If you need more than this then that code will have to be rewritten. Eventually 32 and 64-bit values are used for the loop filtering code. But you'd have to change the initial IQ processing 16-bit code to be 32-bit or something.
One problem I've noticed with HF DRM is that the way HF broadcasters have it configured (not enough redundancy) you really need a signal/noise ratio of > 18 dB to keep audio dropouts from happening. That means it's almost useless in any sort of significant fading condition (i.e. long distances, multi-hop etc.) Some interesting perspective here: https://www.drmradio.co.uk/drm_010.htm