AWG or sound sampling device?

to me interesting why the PCB is so huge if no USB, no power, no variable gain?

Well there are some additions to it (I'm not affiliated in anyway and it's my money purchase): https://nihtila.com/2020/02/02/adc-ak5572-very-high-performance-audio-ad-converter/

Part of the reason for space is it has not only the ADC but a protective front end:
ADC is AKM AK5572. Opamps are LM4562 and OPA1632 for input circuit and NE5532 for bias buffer. All capacitors in signal path are film or C0G types and resistors are 0.5% thin film type.

It would still need a scaler/HV frontend. Perhaps Jan's autoscaler. I did find an article giving an example of using a TLV6001 opamp to give ±200V input protection why reinvent the wheel?
 
I think I may simply make a AC coupled scaling connectors. That way I know the BNC connection is configured for a maximum voltage peak. For example have different BNC scaling front ends for line level, for 108Vpk (ie 30x) for speaker output and 400Vpk to replicate the scope front end max for tube work.
Given the frontend is an opamp with high impedance input, the amount of current required is minimal something in the region of 0.1mA could be planned without impacting the end circuit for audio use.
If isolation is required then I would put that on the digital side i2S/i2C or USB then use isolated power supplies in the box.

Although the 5572 uses chopping to reduce low frequency noise, I don't see the need to test DC signal (say <5Hz) for my uses anyway.
 
Well the hardware clock GPCLK0 on the RPI for the MCLK:
SDS00038.png


Not the perfect clock, also the RPI noise filter has a max rate of 25MHz according to the Broadcom zero 2w 2711 datasheet. I'm wondering if a simply threshold Schmitt trigger would clean that up. There's a strong harmonic given the distorted

This is using the pigpio library and simply configuration the gpio pins to ALT0 configuration and setting the hardware clock on pin 4 for 24.795MHz.
 
So the RPI has to divide (uses fractional skipping so a higher source clock will result in a nearer frequency) to achieve approximately the correct frequency. The options for the RPI are the 500MHz PLLC and the 1.2GHz PLLD. The PLLD gives a cleaner wave on the scope (at 1GSPS) but the frequency counter bounces between 24.9 and 25.02MHz. The PLLC bounces between 25.01MHz and 25.03MHz with an occasional 25.3MHz. That's with trigger noise reduction on and holdout set so I'd expect the distribution of clock frequencies to be worse.
So this brings me squarely to acknowledge the RPI clock isn't the best thing in the world (understatement) and so an external clock would be best for this. It will, however, allow me to test the RPI USB-i2S and i2C control.
At the same time I will also need to make a regulator board for it. Although it's got power regulation on board, I want to drive this from a small linear PSU in a small box.

So a signal generator would help round about now 🤣

So next steps:
a) Get the signal for i2s across through USB into the Mac.
b) 24.756MHz high precision/accuracy clock to replace the RPI.
c) A +15V/-15V and two 5V low noise supply (one for the RPI).

I suspect the RPI Zero 2w may have an issue with having an external master clock.

I just found this thread: https://www.diyaudio.com/community/...ernal-i2s-master-clock-pcm_mclk.266295/page-2 supports my findings and highlights the required changes that match the information in the peripheral manual:
a) the RPI won't take a MCLK directly (Broadcom issue, some other SoC manufacturers support this).
b) the RPI can take an external i2S bit clock (BICK attached to PCMCLK). The RPI will then clock the PCM_FS (attached to LPCK) then the PCM_DIN/DATA pin from the 5572 board will then look after itself naturally.
 
So the linux audio system can be a bit bewildering but it seems relatively simple. Researching, the following concepts seem to explain what I'm trying todo - in theory the system has enough support already coded this should be a configuration task:

ALSA - the main sound management system within linux.
Alsa has the concept of drivers split into classes, the two that are of most interest are:
1. platform class driver - these are the DMA capable drivers for i2s and PCM. The 5572 board itself has PCM configured natively and with a few changes i2s can be used.
2. machine class driver - this is the 'sound card driver' (ie the hardware control driver to initialise, manage and recover as needed). This of this as more control.
There are others but I don't think we need to go into them.

Alsa also provides some commands such as alsa-info and alsaloop.
alsa-info wth the --with-devices parameter lets us see the devices present on the system. In this case the UAC2Gadget (g_audio - the USB Audio gadget) appears but our PCM/i2s driver does not:
Code:
!!Soundcards recognised by ALSA
!!-----------------------------
 0 [UAC2Gadget     ]: UAC2_Gadget - UAC2_Gadget
                      UAC2_Gadget 0
 1 [vc4hdmi        ]: vc4-hdmi - vc4-hdmi
                      vc4-hdmi

The basic concept here is if we have two drivers - one for PCM to the 5572 ADC and one to the g_audio gadget, it allows us to use the alsaloop command to link both digitally. The Mac will then see the ADC streamed samples as a PCM audio input like a microphone. (as it stands I could loop to the HDMI sound at the moment!).

So the next point is - how do we create a PCM device using configuration? The ADC is connected to the PCM ALT0 pin configuration of the RPI.. so next is how do we bridge the gap between GPIO/PCM pins and expose that as an ASLA device for the system to use?
 
Digging deeper, there doesn't seem to be a generic PCM-GPIO driver which is a bit odd. PCM-based codecs exist but no generic driver.

In short I'd need to write a driver based on the PCM interface: https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html

This would then create a driver card which can then be looped back.

So I've hacked a module together:
Code:
pi@raspberrypi:~/pcmgpio $ more /proc/modules | grep pcm
pcmgpio 16384 0 - Live 0x0000000000000000 (O)
snd_pcm_dmaengine 20480 1 snd_soc_core, Live 0x0000000000000000
snd_pcm 139264 7 snd_soc_hdmi_codec,snd_soc_bcm2835_i2s,snd_soc_core,snd_compress,snd_pcm_dmaengine,snd_bcm2835,u_audio, Live 0x0000000000000000
snd_timer 36864 1 snd_pcm, Live 0x0000000000000000
snd 106496 7 snd_soc_hdmi_codec,snd_soc_core,snd_compress,snd_bcm2835,u_audio,snd_pcm,snd_timer, Live 0x0000000000000000

Sure enough it's installed an live. Currently it's a shell with ALSA interface so it should appear as an ALSA device. I just need to work out how to install it in ALSA.
 
So I'm getting there - specifically I know the mechanism to fill a kernel ring buffer using DMA for the PCM pins:
IMG_0662.jpg


Optimally the main FIFO kernel ring buffer would be shared between the DMA for the PCM/i2s and the USB DMA.. but that's in an ideal world (read - bare metal).

The way this will work is that the PCM DMA will be configured with a list managed to read off the frames from the FIFO without CPU into the kernel ring buffer. The next step is then expose that information via the kernel ALSA interface, copying the capture stream from the ring buffer into the target ALSA caller's buffer. That caller could be the loopback which would then feed the USB g_audio driver to provide the data output.

I can set both a receive threshold so that the DMA will execute every N sets of samples, increasing latency (given it's stereo that'll be 32 samples max in the FIFO), but reducing the DMA overhead. I'll probably run 20 samples threshold and set the panic to 32. On panic I can make it issue an interrupt to signal the error condition (ie will also be set as a flag). Where as on under-run and the ALSA stream read attempts to read data then I will simply return an error code.
It should be stated that without a ADC time stamp for each sample, the reading process is pretty much "as it comes through" so no timing can be implied by the samples coming through at a particular rate. The DMA won't MCLK timestamp so don't even try!

That said, the use of DMA should result in the fastest result. Only issue is this is dependant on the RPI version so at a later date the code may need refactoring to support different Broadcom SOCs.

I could both identify the AK5572 and control it by using the i2c bus and add the interface to the driver. However I don't want to mess around so it will be hard coded to 192K 32bit. The end device (Mac) will have to accept the rate unless it's resampled or reformatted using alsaloop.

I've worked out alot for the ALSA side of things - this should be a case of register the module driver with ALSA and as ALSA requests data (ie the capture stream) I transfer that out of the larger kernel ring buffer in the driver. It's then pretty much done.

I did find some additional kernel MODULE_ commands that obviously will help. An i2c pin would auto-probe if I could be bothered writing that bit. I am struggling with getting ALSA to recognise however after reading.. I think the penny clicked as I will need to use the module_init() and module_exit() to register with ALSA but what is my driver? The kernel AD drivers are i2c based and use probe() to recognise the chip. I'm not a PCI so reality, as a GPIO based device, I may have simply make a driver sit under the platform driver class.
 
Again, phofman can help. He has written ALSA drivers. Cramming ALSA into a pi zero will probably run into some internal limitations (like the clocking problems you found).

What you are trying to do is take a stream from one input and send it out another. I think you can configure ALSA to do that with a simple command string. I have not fiddled with ALSA for years but there are others here who deal with it a lot. I think you need a "plug" to connect the two points. This may help: https://superuser.com/questions/357278/how-to-configure-alsa If nothing tells ALSA that a "driver" exists it can't talk to the device.
 
  • Like
Reactions: NickKUK
I’ve managed to loop streams previously - it’s a single line command to link two “cards”. The g_audio is one card and the driver-to-be-written is the other. If there’s a pcm driver already then using that may be better (alot use i2c and most i2s are DACs).

I’ll ping phoman but i wanted to understand the subject before contacting him.
 
Again, phofman can help. He has written ALSA drivers. Cramming ALSA into a pi zero will probably run into some internal limitations (like the clocking problems you found).

What you are trying to do is take a stream from one input and send it out another. I think you can configure ALSA to do that with a simple command string. I have not fiddled with ALSA for years but there are others here who deal with it a lot. I think you need a "plug" to connect the two points. This may help: https://superuser.com/questions/357278/how-to-configure-alsa If nothing tells ALSA that a "driver" exists it can't talk to the device.

I suspect that it's not bug free either, plus tolerances for timing aren't known at this stage. I think I'll be asking for a function generator at this point for xmas 🙂
 
So looking at the current issues in stock for ADC clocks I took the plunge with a SDG1032X for generating the MCLK clock for the time being. I will then worry about adding higher spec'd clocks at a later stage - it keeps me moving.
 
So this evening will be an extravaganza - the SDG arrived. Already played a little with it at lunch but I've been working.

So today's mission is to setup:
1. Setup the ADC MCLK to master using the SDG to provide the 14.756MHz clock.
2. Setup the RPI PCM_CLK as MCLK slave (CLKM=1) which should then create an input on the pin. This should set the bit clock to 14.756MHz.
3. Setup the RPI FS CLK as output (FSM=0) and the ADC will clock the FS based on the MCLK.
4. screw the boards down to a piece of wood for prototyping.

I need to order some BNC cabling, 50R termination etc but for now this will see if the system runs (using the scope to clock to the data).
 
Why 14.756 MHz? Its a non standard frequency which may open a can of worms both in software and with the audio ADC's. I'm sure there is something I'm missing here.
Sorry 24.576MHz.

I think the signal degrades too much looking at the experimental results, so I'm going to have to wait for the 50ohm bits and bobs before trying again.
 
Last edited:
Just 'hacked' the SDG1032X 30MHz to a SDG1064X 60MHz with the 1.01.01.33R3 firmware by simply using the key generation script for the scopes to generate an MBCD key for 60Mhz without needing to hack using linux access or special versions of firmware. The scope verifies the 60Mhz results in a 60Mhz square wave.

I'm now waiting delivery of 50ohm coax with BNC and SMB, terminators etc.
 
So UPS finally decided to deliver my RF cabling.

Does the ADC work - hell yes!

IMG_0697.jpg


Bottom trace MCLK, top trace PCM FS clock, middle is the data. MCLK at 24.576MHz,192K and 24 bit configured as master so the MCLK will cause the ADC to drive the PCM i2s clocks without having to rely on the clocking for the RPI.

IMG_0696.jpeg



Happy as Larry as I thought I'd blown the ADC with my very noob attempts to get it working with scope cables.