RF Power amplifier based on the W6JL amp. The intent is to use readily available parts in the first instant. These may be swapped out depending on how well they perform.
See YouTube for videos. https://www.youtube.com/channel/UCSNPW3_gzuMJcX_ErBZTv2g
The original circuit (minus the biasing RFCs)
My version of the bias network
The final amp has used a BN-43-202 for T1 (8:4) and a BN-43-3312 for T2 (1:3). I also left off the RFCs for the YouTube video. Adding the RFCs would increase the gain a little.
Friday, 15 March 2019
Friday, 8 March 2019
Homebrew Panadapter
Homebrew panadapter using a Teensy 3.5.
Test Code
#include "SPI.h"
#include "ILI9341_t3.h"
#include <si5351.h> // Si5351Jason library
#include <Audio.h>
//const int myInput = AUDIO_INPUT_MIC;
const int myInput = AUDIO_INPUT_LINEIN;
uint16_t WaterfallData[100][128] = {1};
int Gain = 50;
static const long bandInit = 9008450; // 8800000 8565000 to initially set the frequency. Was 9020000
volatile long freq = bandInit ;
// For optimized ILI9341_t3 library
#define TFT_DC 20
#define TFT_CS 21
#define TFT_RST 255 // 255 = unused, connect to 3.3V
#define TFT_MOSI 7
#define TFT_SCLK 14
#define TFT_MISO 12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
Si5351 si5351; // Name for the Si5351 DDS
// Setup audio shield
AudioInputI2S audioInput;
AudioMixer4 InputAmp;
AudioAnalyzeFFT256 FFT;
// Setup the audio connections
AudioConnection patchCord1(audioInput, 0, InputAmp, 0);
AudioConnection patchCord2(InputAmp, 0, FFT, 0);
// Instantiate the Audio Shield
AudioControlSGTL5000 audioShield;
void setup()
{
Serial.begin(9600);
// Setup screen
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.drawRect(31, 0, 257, 37, ILI9341_YELLOW);
tft.drawRect(31, 36, 257, 103, ILI9341_YELLOW);
tft.drawRect(31, 138, 257, 102, ILI9341_YELLOW);
// Setup audio shield.
AudioMemory(12);
audioShield.enable();
audioShield.inputSelect(myInput);
InputAmp.gain(0, Gain);
FFT.windowFunction(AudioWindowHanning256);
FFT.averageTogether(30);
// Setup the DDS
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
si5351.set_freq(freq * 100ULL, SI5351_CLK1);
}
void loop()
{
if (FFT.available())
UpdateDisplay();
if (Serial.available() > 0)
{
char c = Serial.read();
switch (c)
{
case 'w': Gain = Gain + 10; break;
case 's': Gain = Gain - 10; break;
}
Serial.println(Gain);
InputAmp.gain(0, Gain);
}
}
void UpdateDisplay()
{
int bar = 0;
int xPos = 0;
int low = 0;
// Spectrum
for (int x = 0; x <= 127; x++)
{
WaterfallData[0][x] = abs(FFT.output[x]);
bar = WaterfallData[0][x];
if (bar > 100)
bar = 100;
tft.drawFastVLine(32 + (xPos * 2), 138 - bar, bar, ILI9341_GREEN); //draw green bar
tft.drawFastVLine(32 + (xPos * 2), 38, 100 - bar, ILI9341_BLACK); //finish off with black to the top of the screen
xPos++;
}
// Waterfall
for (int row = 99; row >= 0; row--)
for (int col = 0; col <= 127; col++)
{
WaterfallData[row][col] = WaterfallData[row - 1][col];
if (WaterfallData[row][col] >= low + 75)
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_RED);
else if ((WaterfallData[row][col] >= low + 50) && (WaterfallData[row][col] < low + 75))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_MAGENTA);
else if ((WaterfallData[row][col] >= low + 30) && (WaterfallData[row][col] < low + 50))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_YELLOW);
else if ((WaterfallData[row][col] >= low + 20) && (WaterfallData[row][col] < low + 30))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_BLUE);
else if (WaterfallData[row][col] < low + 20)
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_BLACK);
}
}
void SendFrequency()
{
si5351.set_freq(freq * 100ULL, SI5351_CLK1);
}
Test Code
#include "SPI.h"
#include "ILI9341_t3.h"
#include <si5351.h> // Si5351Jason library
#include <Audio.h>
//const int myInput = AUDIO_INPUT_MIC;
const int myInput = AUDIO_INPUT_LINEIN;
uint16_t WaterfallData[100][128] = {1};
int Gain = 50;
static const long bandInit = 9008450; // 8800000 8565000 to initially set the frequency. Was 9020000
volatile long freq = bandInit ;
// For optimized ILI9341_t3 library
#define TFT_DC 20
#define TFT_CS 21
#define TFT_RST 255 // 255 = unused, connect to 3.3V
#define TFT_MOSI 7
#define TFT_SCLK 14
#define TFT_MISO 12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
Si5351 si5351; // Name for the Si5351 DDS
// Setup audio shield
AudioInputI2S audioInput;
AudioMixer4 InputAmp;
AudioAnalyzeFFT256 FFT;
// Setup the audio connections
AudioConnection patchCord1(audioInput, 0, InputAmp, 0);
AudioConnection patchCord2(InputAmp, 0, FFT, 0);
// Instantiate the Audio Shield
AudioControlSGTL5000 audioShield;
void setup()
{
Serial.begin(9600);
// Setup screen
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.drawRect(31, 0, 257, 37, ILI9341_YELLOW);
tft.drawRect(31, 36, 257, 103, ILI9341_YELLOW);
tft.drawRect(31, 138, 257, 102, ILI9341_YELLOW);
// Setup audio shield.
AudioMemory(12);
audioShield.enable();
audioShield.inputSelect(myInput);
InputAmp.gain(0, Gain);
FFT.windowFunction(AudioWindowHanning256);
FFT.averageTogether(30);
// Setup the DDS
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
si5351.set_freq(freq * 100ULL, SI5351_CLK1);
}
void loop()
{
if (FFT.available())
UpdateDisplay();
if (Serial.available() > 0)
{
char c = Serial.read();
switch (c)
{
case 'w': Gain = Gain + 10; break;
case 's': Gain = Gain - 10; break;
}
Serial.println(Gain);
InputAmp.gain(0, Gain);
}
}
void UpdateDisplay()
{
int bar = 0;
int xPos = 0;
int low = 0;
// Spectrum
for (int x = 0; x <= 127; x++)
{
WaterfallData[0][x] = abs(FFT.output[x]);
bar = WaterfallData[0][x];
if (bar > 100)
bar = 100;
tft.drawFastVLine(32 + (xPos * 2), 138 - bar, bar, ILI9341_GREEN); //draw green bar
tft.drawFastVLine(32 + (xPos * 2), 38, 100 - bar, ILI9341_BLACK); //finish off with black to the top of the screen
xPos++;
}
// Waterfall
for (int row = 99; row >= 0; row--)
for (int col = 0; col <= 127; col++)
{
WaterfallData[row][col] = WaterfallData[row - 1][col];
if (WaterfallData[row][col] >= low + 75)
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_RED);
else if ((WaterfallData[row][col] >= low + 50) && (WaterfallData[row][col] < low + 75))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_MAGENTA);
else if ((WaterfallData[row][col] >= low + 30) && (WaterfallData[row][col] < low + 50))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_YELLOW);
else if ((WaterfallData[row][col] >= low + 20) && (WaterfallData[row][col] < low + 30))
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_BLUE);
else if (WaterfallData[row][col] < low + 20)
tft.drawPixel(32 + (col * 2), 139 + row, ILI9341_BLACK);
}
}
void SendFrequency()
{
si5351.set_freq(freq * 100ULL, SI5351_CLK1);
}