Another suggestion I uses was, when the RIT function was active, I displayed the offset from the transmit frequency. I also changed the RIT tuning steps to 50 Hz. instead of 100. I still have several other settings I need to display on the screen, but it is starting to take shape.
One other thing I wanted to do was add was an analog meter. Mainly to use as a s-meter, but possibly as a power meter that will switch between modes on receive or transmit. I looked at and tried the code from several versions I found, but they were fairly large in code size and required quite a bit of processing to compute the needle movement. I decided I wanted top try something a little simpler. Instead of using sin and cos functions to compute the angular position of the needle, I would treat everything as a straight line value. This lets me just draw a line from a pivot point for the needle to some point near the top of the meter face. The line length would vary, but the effect would look close enough to an actual meter. This resulted in two very simple functions, one to draw the meter itself and the other to plot the needle. To move the needle, first it is drawn in the face color of the meter to erase the old value and then redrawn in the desired needle color.
The function to draw the meter is very simple
void drawMeter(int x, int y, int w, int h, int face_c, int bar_c, char *txt) {
tft.fillRoundRect(x, y, w, h, 5, face_c);
tft.fillRoundRect(x + 1, y + 1, w - 2, h / 5, 3, bar_c);
tft.drawRoundRect(x, y, w, h, 5, YELLOW);
tft.setTextSize(1);
tft.setTextColor(YELLOW);
tft.setCursor(x + 2, (y + (h/5))-12);
tft.print(txt);
}
Draw a filled rectangle with rounded corners at the desired position and size, then draw another that will serve as the background color for the meter scale. I also added another empty rectangle around the main one to highlight the meter. Then position the cursor and print the meter scale. I did not add auto sizing of the meter, so the actual size of the main rectangle, will have to be determined manually from the desired text on the meter scale. To draw the basic meter without needle is to give it a position, size , colors needed, and scale text.
// define some values for the meter position and size
#define MTR_X 160
#define MTR_Y 108
#define MTR_W 155
#define MTR_H 100
drawMeter(MTR_X, MTR_Y, MTR_W, MTR_H, WHITE, RED,"0 2 4 6 9 +20 +40 +60");
// define some values for the meter position and size
#define MTR_X 160
#define MTR_Y 108
#define MTR_W 155
#define MTR_H 100
drawMeter(MTR_X, MTR_Y, MTR_W, MTR_H, WHITE, RED,"0 2 4 6 9 +20 +40 +60");
Plotting the needle was simpler than I had expected. Since I was treating the meter range as a straight line value. I pass the function the same parameters for position and size as the drawMeter function, and add the value, max_value and color to draw the needle.
void plotNeedle(int x, int y, int w, int h, int value,int max_value,int color)
{
int tw;
int w2 = w/2;
tw = map(value, 0, max_value, 3, w-3 );
tft.drawLine(x + w2 , y + h - 4, x+tw , y + (h / 5)+4, color);
tft.drawLine(x + w2+1, y + h - 4, x+tw+1 , y + (h / 5)+4, color);
tft.drawLine(x + w2+2, y + h - 4, x+tw +2 , y + (h / 5)+4, color);
}
Then I used the Arduino map() function to return a value that represented the position along the meter scale based on the value read and the maximum value. Then just plot a straight line from the pivot point for the needle to just below the meter scale, which I compute depending on scale size. I draw this three times with a slight offset to make the needle more visible as it moves.
void plotNeedle(int x, int y, int w, int h, int value,int max_value,int color)
{
int tw;
int w2 = w/2;
tw = map(value, 0, max_value, 3, w-3 );
tft.drawLine(x + w2 , y + h - 4, x+tw , y + (h / 5)+4, color);
tft.drawLine(x + w2+1, y + h - 4, x+tw+1 , y + (h / 5)+4, color);
tft.drawLine(x + w2+2, y + h - 4, x+tw +2 , y + (h / 5)+4, color);
}
Then I used the Arduino map() function to return a value that represented the position along the meter scale based on the value read and the maximum value. Then just plot a straight line from the pivot point for the needle to just below the meter scale, which I compute depending on scale size. I draw this three times with a slight offset to make the needle more visible as it moves.
meter_reading=analogRead(A7)/2;
plotNeedle(MTR_X, MTR_Y, MTR_W, MTR_H,last_meter,1023,WHITE);
plotNeedle(MTR_X, MTR_Y, MTR_W, 1MTR_H,meter_reading,1023,BLACK);
last_meter=meter_reading;
Next I will see about building something to get a signal from the uBITX to display. I might start with a simple voltage doubler off the top of the volume control just to see how well it works. Later I will probably tap into the IF chain to get an actual S-Meter . Also thinking about adding a pickup off the antenna lead to measure power output, I can probably use the PTT signal to allow switching between meter readings from receive to transmit.
Update 1/10/2018
After playing around with several different versions of the display screen, I have come up with something I like. Following a couple of suggestions from N6QW, I now show options available in Cyan and any active settings in Yellow. On the screen you can see the second VFO frequency, and that RIT is optional.
Below the frequency read out, I have an area to display the command prompts from the uBITX, such as band change, VFO selection, RIT on/off.
When RIT is turned on the offset from transmit frequency is displayed. I did make a change to the original code to change in 50 Hz. steps instead of 100 Hz.
Finally I added a transmit indicator, and also checked the CW keying line and changed the mode display while a keying is present.
I am happy with the way the display looks, now to put everything in a box and see how it works. I think I will re-write the code I have for the BITX40 and use one of the VFO/BFO boards I designed. With that I have more Analog input pins available and should be able to implement power and SWR readings on the screen.
UPDATE 1/29/18
I have received several questions about the display I used on my uBIX. The ones that I am most interested in are the ones that use a ILI9340 or ILI9341 controller. They are available in 2.4" or 2.8 " models. I have found the response to be very fast using the standard SPI interface.
The main issue with them is that they usually require 3.3 volt logic levels instead of the 5 volt from Arduino, I have found a simple voltage divider does well in this application. I usually power the LED pin through a 100 ohm resistor to 5V. If a PWM pin was available, I would add backlight intensity control instead. Software changes in the main sketch ubitx_20 were fairly simple, and then I replaced the ubitx_ui file with a modified ubitx_tft_ui file. Changes to the ubitx_20 file are made in the declarations
/*
Comment out the original display driver and replace with the Adafruit drivers
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
/*
// WE ARE GOING TO USE A TFT DISPLAY
#include <Adafruit_GFX.h>
#include "Adafruit_ILI9340.h"
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 8
#define _dc 10
#define _rst 9
#define CALLSIGN "KV4QB"
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define GRAY 0x3333
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFF6
Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
and then in the setup code make these changes
// lcd.begin(16, 2); // using tft instead of lcd
// setup the tft display and draw basic display screen
tft.begin();
//tft.initR(INITR_BLACKTAB); //ST7735 depends on exact one used
tft.setRotation(1); // landsacape versus portrait
tft.fillScreen(BLUE);
//we print this line so this shows up even if the raduino
//crashes later in the code
printLine1("uBITX v0.20");
tft.setTextSize(3);
tft.setTextColor(YELLOW, BLUE);
tft.setCursor(22, 20);
tft.print("uBITX v0.20");
delay(1500);
tft.setCursor(22, 20);
tft.print(" ");
drawDisplay();
With the updated ubitx_tft_ui code I tried to keep the code in the other files as unchanged as possible. Except for the display, nothing else has been changed.
Here is a link to my modified uBITX sketch to support a TFT display instead of the normal 2 line LCD display. Hardware change is a small board with the voltage dividers that has a connector for the TFT display. Only the first 8 pins are used. Then there is a short cable that plugs in where the existing display plugs in on the Raduino board.
https://www.dropbox.com/sh/hhqxprggo9rct3v/AACrI9ceAKDYNnFPBH29Ig5ta?dl=0
Here is a link to my modified uBITX sketch to support a TFT display instead of the normal 2 line LCD display. Hardware change is a small board with the voltage dividers that has a connector for the TFT display. Only the first 8 pins are used. Then there is a short cable that plugs in where the existing display plugs in on the Raduino board.
https://www.dropbox.com/sh/hhqxprggo9rct3v/AACrI9ceAKDYNnFPBH29Ig5ta?dl=0