Wednesday, 19 November 2014

DSP Radio, SDR software for the Mac

An increasing number of people are using Macs as opposed to PCs. Quite a few Amateur radio programs are available for Mac OS X. One of the most interesting is the SDR program from DL2SDR called "DSP Radio". This posting is intended to help anyone setting up the program.

Physical connections

The setup described here is for an iMac, which has audio output (LS) and a built-in microphone, but no audio line-in. So an A-to-D/D-to-A convertor is used to provide wideband input/output audio channels. I use the Berlingher FCA202, which interfaces the iMac by Firewire (Apple persistently keeps messing around with their I/O protocols, so a couple of convertors are needed to convert the iMac's Thunderbolt to Firewire 800, then Firewire 800 to 400... £40-50!!!). The FCA202 has line-in which is the receive audio from the SDR and line-out which is the transmit audio to the SDR.

[If you lash out and buy a new MacBook it has only one I/O connector. The best solution here is to use an external A/D D/A convertor, e.g. the StarTech (look on Amazon), and connect with a USB-C to USB converter]

The computer microphone and LS are used for TX & RX listening.

I have tested the setup, so far, only with a simple SDR receiver board, the Softrock Lite. I modified this as described in a earlier posting to use a VFO built round an Arduino and DDS board. But the original with fixed XTAL control works just as well.

Audio MIDI Setup

The first thing to do is to set up the iMac audio channels using the utility Audio MIDI Setup. This is used to create an "Aggregate" device and connect the FCA202, Built-in Microphone and Built-in Output. To do this click on the '+' button lower left and select Aggregate device. Name this something like "SDR"

Screen Shot 2014 11 18 at 14 51 34

Make sure all the audio channels are set to 96kHz bandwidth, which will give the SDR about +/-48kHz tuning range.

DSP Radio setup

I am using the version 1.3.9 of DSP Radio as I have found bugs in the later version which I have yet to overcome. Launch the program and hit CTRL-A which will list the audio devices found on your iMac.

Screen Shot 2014 11 18 at 14 54 56

You can see here the Aggregate device you created in Audio MIDI Setup. Chose this for both Input and Output.

Next hit CTRL-C to create the RX & TX configurations. This means choosing the input/output channels for each, and setting the gain for the RX channel. The audio channels are, unfortunately not numbered the same as the numbers in Audio MIDI setup, so follow those shown here.

Screen Shot 2014 11 19 at 10 34 24

You can switch the AGC function on and off by clicking in the box, you can also set the input or output gain, the S-Meter gain and the gain applied to the spectrum display.

Using the DSP Radio

DSP Radio looks like this

Screen Shot 2014 11 19 at 10 37 00

On reception the spectrum displays, and you can listen to, stations about +/- 45-48kHz from the centre frequency of the oscillator on your SDR radio. Set the centre frequency by scrubbing up/down on RX Frequency/Centre QRG or double click and enter the value in kHz. SDR radios that work receiving commands from the computer over a USB connection, like the Softrock Ensemble, will tune themselves to the frequency entered. If you do not have USB control (as in the Softrock Lite RX which I am using) then you must set the Centre Frequency to the local oscillator frequency on the receiver (remember that the receiver operates at a frequency of the XTAL divided by four as it has a /4 Johnson counter to generate the internal quadrature signals for the detector).

Select the mode, for example LSB, you should now see received signals and moving the green band across the display with the mouse will allow you to listen to the stations. The filter bandwidth can be chosen by sliding the Bandwidth slider.

If you have a transmit also SDR then you must set the RIT/XIT frequency to be the same as the indicate RX frequency, do this by clicking on the button RIT/XIT and enter the receive frequency, then click on RIT/XIT again. This will set the TX frequency to the same value as the RX frequency.

Transmit

To transmit you hit the SPACE bar or the button at the bottom on the display. The DSP Radio will generate an output audio frequency the same as the receive frequency, with sideband modulation set by the mode. For example, with a Centre Frequency QRG of 7160kHz, and LSB selected, tuning to an RX frequency of 7187.100kHz and sending a 1000Hz tome will generate a TX audio output via the D-to-A convertor of 16.1kHz, thus generating a carrier output of 7186.100kHz (7160,00 + 16.1kHz.

Screen Shot 2014 11 19 at 10 50 57

The display will show the transmitted signals, which would look like this

Screen Shot 2014 11 19 at 10 51 45

Comments

SDR is the future, and once you have used an SDR radio you will not want to go back. The HUGE advantage is the ability to see all the stations and relative signal strengths across a wide part of the band. When tuning to a station you can clearly see the bandwidth it is occupying and get a picture of the audio quality. It also make it easy to chose an unused channel if you wish to make a CQ call.

Saturday, 15 November 2014

SDR first steps - the DDS

This is a new build of a DDS using the Adafruit Si5351 module. It adds a CD74ACT74 as a divide-by-four Johnson counter to generate IQ quadrature signals.

The DDS has two modes, SDR & VFO. It is tuned in programable steps (at the moment 10kHz for SDR & 100Hz for VFO) . The shield RF Bus outputs VFO and I & Q which are derived like this:

freq = indicated frequency on display

D5 HIGH	SDR mode	freq x4 clk0 = VFO x4 output
			freq x4 clk1 = Johnson /4 = I & Q x1 outputs
D5 LOW	VFO mode	freq x1 clk0 = VFO output


The input for tuning is a rotary encoder. An LCD display shows the band and the tuned frequency.

Three bands are generated, 40, 30, & 20m. These are selected in turn by the rotary encoder push button. Selecting a new band tunes a preset band frequency.

Photo 11 22 2014 13 38 00

The 5 connections across the left are for the Rotary Encoder and its Button and 4 for the I2C LCD display. This is documented in the source code.

The schematic diagram is:

Scanner Pro 1

Software

The software is a "Universal VFO" this software uses the new "Si5351.h" library from NT7S and implements a VFO switchable to 40, 30, & 20m bands. At the top of the code are defined constants, SDR & VFO, which determine the output frequency, x4 or x1. This value is set to SDR if you want an output x4 the indicated frequency on the VFO output, and a x4 drive to the onboard CD74ACT74 Johnson counter to generate I & Q signals. The VFO output in SDR mode can be used, for example, for the Softrock Lite SDR board. In VFO mode it changes to a single x1 output on the VFO RF bus pin.
The mode, SDR or VFO, is selected by a High or Low on pin D5, selected at start-up by the red jumper link. The constant STEP4 or STEP1 determine the step of the tuning, which can be, for example, 10kHz for driving an SDR, or 100Hz for a direct tuned radio.

The board thus has a VFO output which can be x1 or x4 the indicated frequency. When the hardware /4 Johnson counter is implemented and used, then two further outputs I & Q, provide outputs with the Si5351 running at x4 the frequency displayed. The VFO output is from CLK0, the IQ drive is from CLK1. Board outputs VFO, I & Q are on the RF bus (see previous post below).

Thus this design, with small changes in the software can satisfy diverse applications. Here's the code:

// Universal VFO, outputs for 40-30-20m
// V0.9
// Function
// Generates VHF & IQ outputs.
// Si 5351 output is x1 or x4 displayed frequency.
// Frequency selected in programmable steps by rotary encoder. Button changes bands 40-30-20m
// Change of band sets new frequency to band
// LCD displays frequency in kHz and band
// -----
// Shield has RF bus with VFO, I & Q outputs
// Two modes, set by link (pin D5):
// SDR (D5 HIGH) outputs x4 from clk0 to VFO, & x1 quadrature to I & Q. 10kHz steps
// VFO (D5 LOW) outputs x1 on clk0 to VFO out, 100Hz steps
// -----
// DDS I2C SI5351 
// SCL = A5
// SDA = A4
// I2C address 0x60
// ------
// display I2C LCD 16 * 2
// o A5 SCL (y)
// o A4 SDA (or)
// o +5     (r)
// o GND    (bwn)
// I2C address 0x27
// -----
// encoder KY-040
// o D2 DT  (y)
// o D3 CLK (g)
// o D4 SW  (or)
// o +5     (r)
// o GND    (bwn)
//-----
// D12-D13 TX-RX enable
// D10-D11 band switch relays 40-30-20
// -----

// I2C, Si5351, LCD and Rotary Encoder libraries
#include "Wire.h"
#include "si5351.h"
#include "LiquidCrystal_I2C.h"
#include "Rotary.h"

// XTAL freq, PLL multiplier, outputs 0-2, IQ Mult, steps (Hz)
#define XTAL 25
#define MULT 36
#define SDR 4
#define VFO 1
#define STEP4 10000
#define STEP1 100

// SDR/VFO link pin 5, button pin 4, Rotary Encoder pins 2 & 3 (A & B)
#define LINK 5
#define BUTTON 4
#define ROTA 2
#define ROTB 3

// dds object
Si5351 dds;

// lcd object
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Rotary Encoder object
Rotary rot = Rotary(ROTA, ROTB);

// start frequencies (Hz)
float bandStart[3] = {
  7000000, 10050000, 14000000};
char bandName[3][4] = {
  "40m", "30m", "20m"}; // band 0 = 40m, 1 = 30m, 2 = 20m

// band & freq, freq steps, mode
byte band;
float freq;
float steps;
byte mode;

void setup()
{
  // encoder, button, link, relays & TXRX pin config
  pinMode(ROTA, INPUT_PULLUP);
  pinMode(ROTB, INPUT_PULLUP);
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(LINK, INPUT_PULLUP); // default input = HIGH

  mode = digitalRead(LINK); // HIGH (default) = SDR, LOW = VFO
  if(mode == HIGH) steps = STEP4; // set steps STEP4 (SDR) or STEP1 (VFO)
  else steps = STEP1;

  dds.init(SI5351_CRYSTAL_LOAD_8PF); // init si5351

  lcd.init(); // init LCD & backlight
  lcd.backlight();

  // startup band & frequency
  band = 0; // 40m
  freq = bandStart[band];

  freqOut(freq);

  dispMenu(); // display menu
  dispFreq(freq); // display freq
  dispBand(bandName[band]); // display band
}

void loop()
{
  unsigned char dir; // tuning direction CW/CCW
  byte step;

  if(digitalRead(BUTTON) == LOW) // button pressed?
  {
    while(!digitalRead(BUTTON)); // wait for release
    if(band == 2) band = 0; // go around
    else band++;

    freq = bandStart[band]; // set centre freq of new band

    freqOut(freq); 
    dispFreq(freq); // update freq & band display
    dispBand(bandName[band]); 
  }

  dir = rot.process(); // read encoder
  if(dir != DIR_NONE) // turned?
  {
    if(dir == DIR_CW) freq += steps; // increment +/- STEP
    if(dir == DIR_CCW) freq -= steps;

    freqOut(freq);
    dispFreq(freq); // update freq display
  }
}

// freq out x IQ
void freqOut(float freq)
{
  if(mode == HIGH) // SDR mode
  {
    dds.set_freq(freq * SDR, 0, SI5351_CLK0); // VFO out, x4
    dds.set_freq(freq * SDR, 1, SI5351_CLK1); // CD74AC74 quadrature to I & Q
  }
  else
  {
    dds.set_freq(freq * VFO, 0, SI5351_CLK0); // direct VFO out, x1
  }
}

// display menu
void dispMenu()
{
  lcd.setCursor(1, 0); // display caption
  if(mode == HIGH)  lcd.print("SDR");
  else lcd.print("VFO");
  lcd.setCursor(1, 1);
  lcd.print("Band");
}

// display freq
void dispFreq(float f)
{
  float pf;
  pf = f /1000; // kHz

  lcd.setCursor(5, 0);
  lcd.print("       "); // clear last freq display
  if(pf < 9999.9) lcd.setCursor(6, 0);
  else lcd.setCursor(5, 0);
  lcd.print(pf, 1);
  lcd.setCursor(13, 0);
  lcd.print("kHz");
}

// display band
void dispBand(char b[])
{
  lcd.setCursor(5, 1);
  lcd.print("   "); // clear last band display
  lcd.print(b);
}