AGC for uBITx controlled by I2C via Software

Nick VK4PLN admits he has tried just two AGC approaches on BITx rigs: the VK3YE AGC (which is shall we say very illuminating) and the ADAFRUIT TPA2016 I2C module.

Nick found the VK3YE solution messed with the audio quality, made it all scratchy, and still didnt handle local 100w stations well …

Now after playing with the TPA for a few days he is very happy with the results.  Audio has good depth and AGC is responsive, and the unit also gives a nice increase in gain.

One trick for others who want to implement this,  is that you will need to add some code to the Adafruit library to implement the enableNoiseGate(false); function.    We need to turn the NoiseGate off or else the AGC will not ramp up with only background noise and you will not hear anything until a loud signal comes on.  [EDITOR notes that this could be used as a kind of SQUELCH function].

Also the speaker output is NOT grounded, you need to isolate your SPEAKER jack so that the – ve line from the TPA2016 is direct to the speaker with no chassis grounding…   Output from the amplifier can’t be fed into another amplifier.

The Best part in Nick’s opinion is that all of the AGC related settings are customisable if you want.  If not, just use the voice settings from the datasheet.   Nick says the defaults work great!

Stereo 2.8W Class D Audio Amplifier – I2C Control AGC – TPA2016

Nick says he will post the code to the list along with a few pics… This extra info should appear here shortly.

REFERENCE

And the board installed in Nick’s uBITx can be seen below.  It looks a real tidy build!

Software

Nik has now shared his software:

/*************************************************************************
VK4PLN’s AGC Code. Adafruit TPA2016
Add call to setupTPA2016(); to main code setup() in ubitx_20 after initOscillators();
**********/

#include <Wire.h>
#include “Adafruit_TPA2016.h”

Adafruit_TPA2016 audioamp = Adafruit_TPA2016();

void setupTPA2016() {

audioamp.begin();
// See Datasheet page 22 for value -> dBV conversion table
// Serial.println(“Right off, Left On,”);
audioamp.enableChannel(false, true);

// Noise Gate Threshold: Below this value, the AGC holds the gain to prevent breathing effects.
//Select the threshold of the noise gate (1,4,10,20mV) (0-3)
// Serial.println(“Noise Gate Threshold,”);
//Disable NoiseGate, we want to hear everything, even weak signals….
audioamp.enableNoiseGate(false);
audioamp.setNoiseGateThreshold(0);

// Fixed Gain: The normal gain of the device when the AGC is inactive.
// The fixed gain is also the initial gain when the device comes out of shutdown mode or when the AGC is disabled.
// value 6 seems to work ok… based on datasheet. Where gain is from -28 (dB) to 30 (dB)
// Serial.println(“Setting Fixed Gain”);
audioamp.setGain(-12); //-27 is ok? -12 is too high local stations arnt clipped…

// Compression Ratio: The relation between input and output voltage.
// AGC can be TPA2016_AGC_OFF (no AGC) or
// TPA2016_AGC_2 (1:2 compression)
// TPA2016_AGC_4 (1:4 compression) * Datasheet – Voice
// TPA2016_AGC_8 (1:8 compression)
// Serial.println(“Setting AGC Compression”);
audioamp.setAGCCompression(TPA2016_AGC_8);

// Limiter Level: The value that sets the maximum allowed output amplitude.
// Serial.println(“Setting Limit Level”);
audioamp.setLimitLevelOn();
// or turn off with
//audioamp.setLimitLevelOff();
audioamp.setLimitLevel(30); // range from 0 (-6.5dBv) to 31 (9dBV) (8.5dBv(30) as per datasheet)

//Maximum Gain: The gain at the lower end of the compression region
// Serial.println(“Setting AGC Max Gain (18-30db – (0-12)”);
audioamp.setAGCMaxGain(12);

/*
* For voice systems the attack time should be in the 2-ms region, with a hang time of about 0.3 sec,
* followed by a gradual recovery time of up to 1 sec.
* http://www.qsl.net/va3iul/Files/Automatic_Gain_Control.pdf
*
*/

// See Datasheet page 23 for value -> ms conversion table
// Serial.println(“Setting AGC Attack (0.1-6.7ms – (0-63))”);
audioamp.setAttackControl(3);

// See Datasheet page 24 for value -> ms conversion table
// Serial.println(“Setting AGC Hold (0.0137-0.8631ms – (1-63))”);
audioamp.setHoldControl(0);

// See Datasheet page 24 for value -> ms conversion table
// Serial.println(“Setting AGC Release (0.0137-0.8631ms – (0-63))”);
audioamp.setReleaseControl(4);

}

Also, need to add this new function to Adafuit library after the existing enableChannel function:

// Turn on/off Noise Gate
void Adafruit_TPA2016::enableNoiseGate(boolean ng) {

uint8_t setup = read8(TPA2016_SETUP);
if (ng)
setup |= TPA2016_SETUP_NOISEGATE;
else
setup &= ~TPA2016_SETUP_NOISEGATE;

write8(TPA2016_SETUP, setup);
}

And the line for the header file:

void enableNoiseGate(boolean ng);

in .h file:
void setNoiseGateThreshold(uint8_t thresh);

in .cpp file

void Adafruit_TPA2016::setNoiseGateThreshold(uint8_t thresh){ //Added by VK4PLN
if (thresh > 3) return; // max threshold is 3 (20mV)
uint8_t agc = read8(TPA2016_AGCLIMIT);
  agc &= ~(0x20);  // mask off bottom 5 bits
  agc |= thresh;        // set the limit level.
  write8(TPA2016_AGCLIMIT, agc);
}
Reference

2 Replies to “AGC for uBITx controlled by I2C via Software”

Leave a Reply

Your email address will not be published. Required fields are marked *