Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 56 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,80 @@
# uBiTXv6
# uBiTXv6 - modified by DL9OBN

This project is found at https://github.com/reedbn/ubitxv6/

It was forked from https://github.com/afarhan/ubitxv6/

The purpose of this project is to clean up (modularize) the source code, and add features that were not present
in Ashhar's original version of the project, without requiring any hardware modifications to a stock uBiTXv6.
The purpose of this fork is to adapt Reed Nightingale's very good and valuable work (https://github.com/reedbn/ubitxv6/) to my personal needs. While adding new functionality I focused on my main operating mode: CW.

New features include:

* Much faster screen refresh (vs Ashhar's 6.3.1 aka 6.0 release)
* Morse code readback for sightless operation
* Save/recall your favorite frequencies
* When adjusting settings, the existing/current setting is shown as reference
* Cancel touch recalibration
* A morse practice mode is available, where the TX line is muted while keying CW. The "CW audio mode" has been removed for this.
* Removed the option for "CW keying" with the PTT key, straight key or paddles are to be used for this exclusively.
* Tuning step size can be changed with a short tune button press in the main menu. The tuning step size changes between 10Hz - 20Hz - 50Hz - 100Hz and is displayed by little circles, in the middle between the two VFO frequencies. The "menu selection" mode, where a button is selected by the tune knob, can be entered and confirmed with a long button press of the tune button now.
* When the uBitX is started in CW mode (see `CW_IS_DEFAULT` config value below), the minimum frequency for each band will be used as start frequency.
* Simplified the setting of start frequency when changing bands (mainly to save some memory)
* Added display of current CW speed in the main screen. Since we need the space, the RIT frequency is now always displayed directly under "VFO A".
* Added support for setting the min/max frequencies of all bands, based on the configured IARU region (1/2/3)
* Added a check for the current TX frequency, if we're "out of band" the "TX" button isn't displayed and the TX line is muted.
* The "TX" button is now always visible when the current frequency is valid (see item before), and simply changes its colour when the uBitX goes into "TX" mode.
* Added support for a different GUI theme, which is more based on "Google Materials" (rounded buttons and such). In order for the program to still fit, I had to remove the "calibration" options from the setup menu and had to disable CAT support!

User Manual: https://docs.google.com/document/d/1jlllZbvFMCzO1MJLzlJDGb10HXSehlFNMDPsxGJZtvY/edit?usp=drivesdk

# Installing on Your Radio
# Installing on your radio

There are plenty of tutorials on how to upload sketches to Arduino Nanos. Just search for them. Addtionally,
Ashhar created a video explaining the process specifically for uBiTX v6: https://www.youtube.com/watch?v=3n_V3prSJ_E

I developed this code using the Arduino IDE 1.8.9 toolchain, with -Wall and -Wextra compiler options turned on.
Arduino IDE 1.8.13 was reported to compile too big (see https://groups.io/g/BITX20/topic/75008576), but this
should be resolved in this project's tag R1.5.1.
# Personalized config values

To edit e.g. the callsign displayed, open the file `config.h` and change the defines of the config values (defines)

<dl>
<dt>CALLSIGN_TEXT</dt>
<dd>Your callsign as it should be displayed in the main screen.</dd>

<dt>IARU_REGION</dt>
<dd>Sets the limit frequencies (min/max) for all bands according to regulations for regions 1, 2 and 3.</dd>

<dt>DISPLAY_CW_SPEED</dt>
<dd>Change whether you want to display the current CW speed as "wpm", "cpm" or "BpM".</dd>

<dt>CW_IS_DEFAULT</dt>
<dd>If set to "1", the uBitX will start up in CW mode.</dd>

<dt>DEFAULT_TUNING_STEP_SIZE</dt>
<dd>Set the default tuning step size (10Hz, 20Hz, 50Hz or 100Hz).</dd>

<dt>GUI_THEME</dt>
<dd>Set the GUI theming to either "0" (the default) or "1" (Google materials style). Be aware that for the latter option, the calibration and CAT functionalities had to be removed and aren't available!</dd>
</dl>

Then re-compile and upload.

# Comparison of GUI themes

## Default theme

These are some images for the default theme, as was used in the original version by Reed Nightingale.

![Main menu](./images/20230108_093317.jpg)

# Personalized Callsign
![Stored frequencies](./images/20230108_093331.jpg)

To edit the callsign displayed, open the file `callsign.cpp` and change the string. Then re-compile and upload.
![Enter frequency via numpad](./images/20230108_093343.jpg)

# Future Features/Modifications
![Settings menu](./images/20230108_093403.jpg)

There are some features that would be good to add, but I just didn't get around to.

* Setting to choose the tuning step size
* Setting to choose whether or not the knob tuning should accelerate (current behavior) or have a fixed interval
* Provide an option in each menu screen to load the default option for each setting
## New theme

While the current code (as of 2020-05-05) is ~100 bytes shy of the full 30720 available on the nano, there's still
opportunity to add new features by "creating" room. Below is a list of places you might create room:
Following some examples of my new theme, using Google Material features like rounded buttons and also
a reduced set of colors.

I added lots of bounds checking, especially on string writes, that, if removed, could free a good number of bytes.
While keeping them is best practice, for a non-IoT, non-critical piece of hardware, it shouldn't be a huge issue.

I added the RACK to the CAT to better emulate the FT-817 (I hope, at least!). Removing the RACK's and just leaving
the default ACK's will also free up bytes.
![Main menu](./images/20230108_101446.jpg)

I added a bunch of strings to the menuing with the intention of helping people understand their functions, but
technically they're not necessary, and could all be removed.
![Stored frequencies](./images/20230108_101458.jpg)

I switched to a smaller footprint font than Ashhar's original code, but there are MUCH smaller fonts out there.
Changing to a lower resolution, scaled up font can save hundreds or thousands of bytes, but won't look as pretty.
Also, the star, gear, and numpad icons will need to be either added to the new font, or replaced with characters.
![Enter frequency via numpad](./images/20230108_101511.jpg)

The first change I made to this fork was to replace Ashhar's original (incredibly slow) screen drawing routines
with PDQ. Since that change, Ashhar has updated his drawing routine to be MUCH faster than his original, but
still slightly slower than PDQ. It may be that Ashhar's new routines are smaller that PDQ, but I don't actually
know that for certain.
![Settings menu](./images/20230108_101535.jpg)

There are a good number of instances of back-to-back calls of strncpy_P and displayText. Creating a single
function that performs these operations together, and then calling that new function instead of the
back-to-back calls everywhere may save space.

# License

Expand Down
68 changes: 42 additions & 26 deletions bands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "bands.h"
#include "utils.h"
#include "config.h"

/*
* These are the bands for USA. Your bands may vary
Expand All @@ -16,20 +17,36 @@ struct Band_t {
const char UNKNOWN_BAND_NAME [] PROGMEM = "??";

constexpr Band_t bands [] PROGMEM {
// { 0UL, 255UL, 255, "U8"},//Utility conversion option
// { 0UL, 65535UL, 254, "UF"},//Utility conversion option
// { 530000UL, 1700000UL, 253, "AM"},//Broadcast AM, actually centers at 268, but uint8 can't do that
// { 1800000UL, 2000000UL, 160, "A0"},//0xA0 is 160
#if IARU_REGION == 1
// Africa, Europe, Middle East, and northern Asia
{ 3500000UL, 3800000UL, 80, "80"},
{ 7000000UL, 7200000UL, 40, "40"},
{10100000UL, 10150000UL, 30, "30"},
{14000000UL, 14350000UL, 20, "20"},
{18068000UL, 18168000UL, 17, "17"},
{21000000UL, 21450000UL, 15, "15"},
{28000000UL, 29700000UL, 10, "10"},
#else
#if IARU_REGION == 3
// the rest of Asia and the Pacific
{ 3500000UL, 3900000UL, 80, "80"},
{ 7000000UL, 7200000UL, 40, "40"},
{10110000UL, 10150000UL, 30, "30"},
{14000000UL, 14350000UL, 20, "20"},
{18068000UL, 18168000UL, 17, "17"},
{21000000UL, 21450000UL, 15, "15"},
{28000000UL, 29700000UL, 10, "10"},
#else
// The default - the Americas
{ 3500000UL, 4000000UL, 80, "80"},
// { 5330500UL, 5403500UL, 60, "60"},
{ 7000000UL, 7300000UL, 40, "40"},
{10100000UL, 10150000UL, 30, "30"},
{14000000UL, 14350000UL, 20, "20"},
{18068000UL, 18168000UL, 17, "17"},
{21000000UL, 21450000UL, 15, "15"},
// {24890000UL, 24990000UL, 12, "12"},
// {26965000UL, 27405000UL, 11, "CB"},//Citizen's Band
{28000000UL, 29700000UL, 10, "10"},
#endif // of: #if IARU_REGION == 3
#endif // of: #if IARU_REGION == 1
};
constexpr uint8_t NUM_BANDS = sizeof(bands)/sizeof(bands[0]);

Expand Down Expand Up @@ -87,25 +104,15 @@ uint32_t getFreqInBand(const uint32_t frequency,
return frequency;
}

//See if we're currrently in a valid band
int8_t current_band_index = findBandIndexFromFreq(frequency);

if(-1 == current_band_index){
//We're not in a known band - just go to the center of the target band
Band_t band;
memcpy_P(&band,&bands[target_band_index],sizeof(band));
return band.min + ((band.max - band.min)/2/100)*100;//midpoint truncated to 100Hz resolution
}
else{
//We're in a known band. Match the relative position in the target band.
Band_t current_band;
memcpy_P(&current_band,&bands[current_band_index],sizeof(current_band));
Band_t target_band;
memcpy_P(&target_band,&bands[target_band_index],sizeof(target_band));
const uint32_t range_current = current_band.max - current_band.min;
const uint32_t range_target = target_band.max - target_band.min;
return (((frequency - current_band.min) * (uint64_t)range_target / range_current + target_band.min)/100)*100;//truncated 100Hz
}
Band_t band;
memcpy_P(&band,&bands[target_band_index],sizeof(band));
#if CW_IS_DEFAULT == 0
// go to the center of the target band
return band.min + ((band.max - band.min)/2/100)*100;//midpoint truncated to 100Hz resolution
#else
// for CW we prefer the start of each band
return band.min;
#endif
}

bool isFreqInBand(const uint32_t frequency,
Expand All @@ -128,3 +135,12 @@ bool isFreqInBand(const uint32_t frequency,
return false;
}

/** Return false if the given frequency is outside of any ham band.
*
* This will be used to suppress TX when we're "out
* of band".
*/
bool freqInAnyBand(const uint32_t frequency)
{
return findBandIndexFromFreq(frequency) != -1;
}
4 changes: 3 additions & 1 deletion bands.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ uint32_t getFreqInBand(const uint32_t frequency,
const uint8_t target_band);

bool isFreqInBand(const uint32_t frequency,
const uint8_t band);
const uint8_t band);

bool freqInAnyBand(const uint32_t frequency);
38 changes: 16 additions & 22 deletions button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,6 @@

void drawButton(Button* button)
{
uint16_t tc = COLOR_INACTIVE_TEXT;
uint16_t bgc = COLOR_INACTIVE_BACKGROUND;
const uint16_t bdc = COLOR_INACTIVE_BORDER;
switch(button->status())
{
case ButtonStatus_e::Stateless://Fallthrough intended
case ButtonStatus_e::Inactive://Fallthrough intended
default:
{
//Colors are initialized for this, so we're done
break;
}
case ButtonStatus_e::Active:
{
tc = COLOR_ACTIVE_TEXT;
bgc = COLOR_ACTIVE_BACKGROUND;
break;
}
}


if(nullptr != button->text){
strncpy_P(b,button->text,sizeof(b));
}
Expand All @@ -40,7 +19,22 @@ void drawButton(Button* button)
//Serial.println(F("No text for button!"));
return;
}
displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc);
#if GUI_THEME == 0
if (button->status() == ButtonStatus_e::Active) {
displayText(b, button->x, button->y, button->w, button->h, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER);
} else {
displayText(b, button->x, button->y, button->w, button->h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER);
}
#else
displayFillrect(button->x, button->y, button->w, button->h, COLOR_BACKGROUND);
if (button->status() == ButtonStatus_e::Active) {
displayFillroundrect(button->x, button->y, button->w, button->h, button->h/2, COLOR_ACTIVE_BACKGROUND);
displayText(b, button->x, button->y, button->w, button->h, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_ACTIVE_BACKGROUND);
} else {
displayText(b, button->x, button->y, button->w, button->h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BACKGROUND);
displayRoundrect(button->x, button->y, button->w, button->h, button->h/2, COLOR_INACTIVE_TEXT);
}
#endif
}

void extractAndDrawButton(Button* button_out, const Button* button_P)
Expand Down
3 changes: 2 additions & 1 deletion callsign.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "callsign.h"
#include "config.h"

const char CALLSIGN_STRING_PRIVATE [] PROGMEM = "CALLSIGN";
const char CALLSIGN_STRING_PRIVATE [] PROGMEM = CALLSIGN_TEXT;
const char* const CALLSIGN_STRING = CALLSIGN_STRING_PRIVATE;
11 changes: 10 additions & 1 deletion color_theme.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#pragma once

#include "colors.h"
#include "config.h"

#if GUI_THEME == 0
static const unsigned int COLOR_TEXT = DISPLAY_WHITE;
static const unsigned int COLOR_BACKGROUND = DISPLAY_NAVY;

static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_WHITE;
static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_BLACK;
#else
static const unsigned int COLOR_TEXT = DISPLAY_GREEN;
static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK;

static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_BLACK;
static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_GREEN;
#endif

static const unsigned int COLOR_INACTIVE_VFO_TEXT = DISPLAY_GREEN;
static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_BLACK;
Expand All @@ -19,4 +28,4 @@ static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK;
static const unsigned int COLOR_ACTIVE_BACKGROUND = DISPLAY_ORANGE;
static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE;

static const unsigned int COLOR_VERSION_TEXT = DISPLAY_LIGHTGREY;
static const unsigned int COLOR_VERSION_TEXT = DISPLAY_LIGHTGREY;
5 changes: 5 additions & 0 deletions colors.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// Color definitions
//
// Note that the GFX library uses a 5-6-5 encoding
// for 16-bit color: the highest 5 bits are the red
// value, the middle 6 are green, and the lowest 5
// are blue.
static const uint16_t DISPLAY_BLACK = 0x0000; ///< 0, 0, 0
static const uint16_t DISPLAY_NAVY = 0x000F; ///< 0, 0, 123
static const uint16_t DISPLAY_DARKGREEN = 0x03E0; ///< 0, 125, 0
Expand Down
40 changes: 40 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once
//
// Header file that keeps some global configuration values
//

// The callsign that appears on the main menu
#define CALLSIGN_TEXT "CALLSIGN"

// The software version number of the ubitx firmware
#define VERSION_TEXT "R2.0.1"

// Set to your preferred region for the correct band frequencies
// 1 - Africa, Europe, Middle East, and northern Asia
// 2 - the Americas
// 3 - the rest of Asia and the Pacific
#define IARU_REGION 2

// Display CW speed as
// 0 - words per minute (wpm)
// 1 - chars per minute (cpm)
// 2 - Buchstaben pro Minute (BpM, German special)
#define DISPLAY_CW_SPEED 0

// Sets the default tuning mode to
// 0 - SSB
// 1 - CW
#define CW_IS_DEFAULT 0

// Sets the default tuning step size to
// 0 - 10Hz
// 1 - 20Hz
// 2 - 50Hz
// 3 - 100Hz
#define DEFAULT_TUNING_STEP_SIZE 2

// Sets the GUI theme to use
// 0 - default
// 1 - more oriented towards Google Materials (e.g. rounded buttons), be aware that for this
// option, the calibration and CAT functionalities had to be removed and aren't available!
#define GUI_THEME 0
Binary file added images/20230108_093317.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_093331.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_093343.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_093403.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_101446.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_101458.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_101511.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/20230108_101535.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading