Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic if gain control v2 #82

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

sbeckman
Copy link
Contributor

Support Automatic IF Gain Control (Version 2)

The code finds the lowest amplitude in each block of 1024 samples (in the frequency domain) and adjusts the IF gain to keep the lowest amplitude at a target value. The loop has two modes - a fast mode and a slow mode.

Fast mode can change the IF Gain 5 counts for every block of samples (new blocks are received approximately every 10 milliseconds.) Slow mode can change the IF Gain 1 count every second. The overall effect is that when going to a new band the IF Gain quickly finds the approximate right value. When the lowest amplitude is near the target value for 1 second then the loop switches to slow mode and stays there until a band change (even selecting a new stacking register in the same band qualifies) occurs, or a frequency is sent by telnet, which enables the Fast loop again.

The fast mode is engaged whenever the band is changed (which causes the mode to be updated, which this code uses as the trigger) or when a new frequency is set by telnet. Changing frequency by telnet does not trigger a mode change, so the code watches for that type of event as well. If the frequency commanded by telnet is in the same band, the IF Gain loop would not necessary need to be put into the fast mode, but if the loop has normalized then there will be little impact.

This is algorithm is able to find an appropriate IF Gain setting quickly (even when hopping from 10m to 80m) yet after the loop settles it can ignore noise bursts that would otherwise be disruptive.

A further improvement would be to have some way to disable the Auto IF Gain mode, either through a settings menu, when the user makes an adjustment to the IF Gain in the GUI, or when an IF Gain command is received over telnet.

Fix for high CPU usage and audio dropouts. Includes a define to enable debugging messages.
Changed the level of rigor from FFTW_ESTIMATE to FFTW_MEASURE in order to resolve an issue where the FFTW library would sometime make a bad choice about the FFT algorithm to use.

Added support for Wisdom files so that the FFTW library does not have to spend time picking the algorithm.
Changed the level of rigor from FFTW_ESTIMATE to FFTW_MEASURE in order to resolve an issue where the FFTW library would sometimes make a bad choice about the FFT algorithm to use.

Added support for Wisdom files so that the FFTW library does not have to spend time picking the algorithm.
@rafael2k
Copy link
Contributor

Hi @sbeckman ! Thanks for your wonderful work!
The logic seems right, but I don't understand how rx_gain changes just the radio rx ALSA control instead of both radio rx + mic input. I could not find any change which applies ALSA changes separate for left and right channels in the code.

@afarhan
Copy link
Owner

afarhan commented Jan 24, 2024 via email

@rafael2k
Copy link
Contributor

I really love the wm8731 tbh. Alsa provides individual left/right controls which are easily usable for automatic gain adjustment. I'm implementing this code right now. Soon I can share an example adapting @sbeckman code to use alsa for gain adjustment.

@sbeckman
Copy link
Contributor Author

Hi Rafael - Thanks for your comments. It's worth looking at the snd_mixer code to see if there's separate control for the RX channel and the TX channel. In case there is not -- then this code I've proposed should be modified so that the proper rx_gain value is restored as soon as the sbitx transitions from transmit to receive. The proposed code could impose up to a 1 second delay is setting the correct rx_gain. I will investigate in the next couple days and advise.

@sbeckman
Copy link
Contributor Author

Farhan - not sure how we should code to accommodate hardware that currently does not exist. The several hundred sbitx units currently fielded with a WM8731, and using a kernel driver and ALSA currently, are what we have on our benches today. I think we could possibly make better use of the ALSA sound system, or another sound system, to support other sound devices for both input and output.

Migrating to a DDC does sound interesting. The Hermes Light 2 has found a low cost device for handling analog in/out. However my sbitx currently has an SI5351 installed. Is there a path for upgrade being developed?

@rafael2k
Copy link
Contributor

Hi @sbeckman! Thanks for the anwser.
There is API, as I mentioned. Instead of using, for example,

snd_mixer_selem_set_playback_volume_all()

use

snd_mixer_selem_set_playback_volume()

with the channel set as parameter type snd_mixer_selem_channel_id_t.
Anyway, both ways will work fine. I'll test this alsa method soon and let you know how it goes. Btw, I totally support that this code be merged ASAP, if Farhan thinks it works fine. My comments are just suggestions for future improvement, if it gives any benefit.

@afarhan
Copy link
Owner

afarhan commented Jan 25, 2024 via email

@rafael2k
Copy link
Contributor

rafael2k commented Jan 25, 2024

Hi Farhan. The only thing that could be better, is that the pins chosen for the second i2c are not pins that can act as a hardware i2c controller (Both Pi4 and Pi5 have many i2c controllers), so the use of bit-banging is needed, which is not optimal (even if using hardware i2c supported pins, we could always change to software bitbang anyway... it was just a missed chance).

@rafael2k
Copy link
Contributor

Steve, At the moment, we don't have a candidate replacement for the WM8731. It took me almost 6 months to get it to work. The main trouble with this IC is that its I2C registers are all write-only, and the timing is very finicky. I had to use the delayed capture of my oscilloscope to understand the sequence needed to get it going. It can't handle another I2C slave on the same lines, this is why we had to place Si5351 and the RTC on different pins. The software should be capable of being rapidly adapted to new hardware and architectures. More on that in the next hour on the google meet. - f

On Thu, Jan 25, 2024 at 6:15 AM Rafael Diniz @.> wrote: Hi @sbeckman https://github.com/sbeckman! Thanks for the anwser. There is API, as I mentioned. Instead of using, for example, snd_mixer_selem_set_playback_volume_all() use snd_mixer_selem_set_playback_volume() with the channel set as parameter type snd_mixer_selem_channel_id_t. Anyway, both ways will work fine. I'll test this alsa method soon and let you know how it goes. Btw, I totally support that this code be merged ASAP, if Farhan thinks it works fine. My comments are just suggestions for future improvement, if it gives any benefit. — Reply to this email directly, view it on GitHub <#82 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFYXOEOU44BJSBNAF4Y7BDYQGTJBAVCNFSM6AAAAABCELFSXOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMBZGE3DCMJYGM . You are receiving this because you commented.Message ID: @.>

Just commenting on this - the same i2c line could be used, but it would require a specific device tree setup.

@rafael2k
Copy link
Contributor

rafael2k commented Jan 30, 2024

I implemented per channel alsa mixer calls. For the reference (eg. this is the call to set speaker volume):
https://github.com/Rhizomatica/hermes-net/blob/3f87abf81e594034471ee9834eb8eabc8504f960/trx_v3-userland/sbitx_alsa.c#L247

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants