kopia lustrzana https://github.com/afarhan/ubitx4
Merge 77af2ec047
into 1ae2af55db
commit
3aae0451ee
10
README.md
10
README.md
|
@ -1 +1,11 @@
|
||||||
#ubitx4
|
#ubitx4
|
||||||
|
|
||||||
|
This is adrian's fork of the ubitx v4 firmware.
|
||||||
|
|
||||||
|
It currently is tailored to run on a stock ubitx4 with bugfixes
|
||||||
|
brought in from other branches and derivatives.
|
||||||
|
|
||||||
|
|
||||||
|
Adrian Chadd / KK6VQK / adrian.chadd@gmail.com
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,14 @@
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
|
|
||||||
|
#include "ubitx4_eeprom_defs.h"
|
||||||
|
#include "ubitx4_pin_config.h"
|
||||||
|
#include "ubitx4_defaults.h"
|
||||||
|
|
||||||
|
#include "ubitx4_txfilt.h"
|
||||||
|
|
||||||
|
#include "ubitx_ui.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The main chip which generates upto three oscillators of various frequencies in the
|
The main chip which generates upto three oscillators of various frequencies in the
|
||||||
Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet
|
Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet
|
||||||
|
@ -44,57 +52,9 @@
|
||||||
code). Here are some defines and declarations used by Jerry's routines:
|
code). Here are some defines and declarations used by Jerry's routines:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We need to carefully pick assignment of pin for various purposes.
|
|
||||||
* There are two sets of completely programmable pins on the Raduino.
|
|
||||||
* First, on the top of the board, in line with the LCD connector is an 8-pin connector
|
|
||||||
* that is largely meant for analog inputs and front-panel control. It has a regulated 5v output,
|
|
||||||
* ground and six pins. Each of these six pins can be individually programmed
|
|
||||||
* either as an analog input, a digital input or a digital output.
|
|
||||||
* The pins are assigned as follows (left to right, display facing you):
|
|
||||||
* Pin 1 (Violet), A7, SPARE
|
|
||||||
* Pin 2 (Blue), A6, KEYER (DATA)
|
|
||||||
* Pin 3 (Green), +5v
|
|
||||||
* Pin 4 (Yellow), Gnd
|
|
||||||
* Pin 5 (Orange), A3, PTT
|
|
||||||
* Pin 6 (Red), A2, F BUTTON
|
|
||||||
* Pin 7 (Brown), A1, ENC B
|
|
||||||
* Pin 8 (Black), A0, ENC A
|
|
||||||
*Note: A5, A4 are wired to the Si5351 as I2C interface
|
|
||||||
* *
|
|
||||||
* Though, this can be assigned anyway, for this application of the Arduino, we will make the following
|
|
||||||
* assignment
|
|
||||||
* A2 will connect to the PTT line, which is the usually a part of the mic connector
|
|
||||||
* A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc.
|
|
||||||
* A6 is to implement a keyer, it is reserved and not yet implemented
|
|
||||||
* A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to
|
|
||||||
* ground and +5v lines available on the connector. This implments the tuning mechanism
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ENC_A (A0)
|
|
||||||
#define ENC_B (A1)
|
|
||||||
#define FBUTTON (A2)
|
|
||||||
#define PTT (A3)
|
|
||||||
#define ANALOG_KEYER (A6)
|
|
||||||
#define ANALOG_SPARE (A7)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors:
|
|
||||||
*
|
|
||||||
* First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be
|
|
||||||
* configured to be used as digital input or output pins. These are referred to as A0,A1,A2,
|
|
||||||
* A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to
|
|
||||||
* talk to the Si5351 over I2C protocol.
|
|
||||||
*
|
|
||||||
* Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2
|
|
||||||
* LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work:
|
|
||||||
* Lines used are : RESET, ENABLE, D4, D5, D6, D7
|
|
||||||
* We include the library and declare the configuration of the LCD panel too
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LiquidCrystal.h>
|
#include <LiquidCrystal.h>
|
||||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
LiquidCrystal lcd(LCD_PIN_RESET, LCD_PIN_ENABLE,
|
||||||
|
LCD_PIN_D4, LCD_PIN_D5, LCD_PIN_D6, LCD_PIN_D7);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
|
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
|
||||||
|
@ -111,77 +71,6 @@ char c[30], b[30];
|
||||||
char printBuff[2][31]; //mirrors what is showing on the two lines of the display
|
char printBuff[2][31]; //mirrors what is showing on the two lines of the display
|
||||||
int count = 0; //to generally count ticks, loops, etc
|
int count = 0; //to generally count ticks, loops, etc
|
||||||
|
|
||||||
/**
|
|
||||||
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
|
|
||||||
* This assignment is as follows :
|
|
||||||
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
|
||||||
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
|
|
||||||
* These too are flexible with what you may do with them, for the Raduino, we use them to :
|
|
||||||
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
|
|
||||||
* - CW_KEY line : turns on the carrier for CW
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TX_RX (7)
|
|
||||||
#define CW_TONE (6)
|
|
||||||
#define TX_LPF_A (5)
|
|
||||||
#define TX_LPF_B (4)
|
|
||||||
#define TX_LPF_C (3)
|
|
||||||
#define CW_KEY (2)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are the indices where these user changable settinngs are stored in the EEPROM
|
|
||||||
*/
|
|
||||||
#define MASTER_CAL 0
|
|
||||||
#define LSB_CAL 4
|
|
||||||
#define USB_CAL 8
|
|
||||||
#define SIDE_TONE 12
|
|
||||||
//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values
|
|
||||||
#define VFO_A 16
|
|
||||||
#define VFO_B 20
|
|
||||||
#define CW_SIDETONE 24
|
|
||||||
#define CW_SPEED 28
|
|
||||||
|
|
||||||
//These are defines for the new features back-ported from KD8CEC's software
|
|
||||||
//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version
|
|
||||||
#define VFO_A_MODE 256 // 2: LSB, 3: USB
|
|
||||||
#define VFO_B_MODE 257
|
|
||||||
|
|
||||||
//values that are stroed for the VFO modes
|
|
||||||
#define VFO_MODE_LSB 2
|
|
||||||
#define VFO_MODE_USB 3
|
|
||||||
|
|
||||||
// handkey, iambic a, iambic b : 0,1,2f
|
|
||||||
#define CW_KEY_TYPE 358
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
|
||||||
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
|
||||||
* this shift is due to the loading on the 45 Mhz crystal filter by the matching
|
|
||||||
* L-network used on it's either sides.
|
|
||||||
* The first oscillator works between 48 Mhz and 75 MHz. The signal is subtracted
|
|
||||||
* from the first oscillator to arriive at 45 Mhz IF. Thus, it is inverted : LSB becomes USB
|
|
||||||
* and USB becomes LSB.
|
|
||||||
* The second IF of 12 Mhz has a ladder crystal filter. If a second oscillator is used at
|
|
||||||
* 57 Mhz, the signal is subtracted FROM the oscillator, inverting a second time, and arrives
|
|
||||||
* at the 12 Mhz ladder filter thus doouble inversion, keeps the sidebands as they originally were.
|
|
||||||
* If the second oscillator is at 33 Mhz, the oscilaltor is subtracated from the signal,
|
|
||||||
* thus keeping the signal's sidebands inverted. The USB will become LSB.
|
|
||||||
* We use this technique to switch sidebands. This is to avoid placing the lsbCarrier close to
|
|
||||||
* 12 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic
|
|
||||||
*/
|
|
||||||
|
|
||||||
// the second oscillator should ideally be at 57 MHz, however, the crystal filter's center frequency
|
|
||||||
// is shifted down a little due to the loading from the impedance matching L-networks on either sides
|
|
||||||
#define SECOND_OSC_USB (56995000l)
|
|
||||||
#define SECOND_OSC_LSB (32995000l)
|
|
||||||
|
|
||||||
|
|
||||||
//these are the two default USB and LSB frequencies. The best frequencies depend upon your individual taste and filter shape
|
|
||||||
#define INIT_USB_FREQ (11996500l)
|
|
||||||
// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz
|
|
||||||
#define LOWEST_FREQ (100000l)
|
|
||||||
#define HIGHEST_FREQ (30000000l)
|
|
||||||
|
|
||||||
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
||||||
//these are the parameter passed to startTx
|
//these are the parameter passed to startTx
|
||||||
#define TX_SSB 0
|
#define TX_SSB 0
|
||||||
|
@ -193,7 +82,7 @@ int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
||||||
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier;
|
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier;
|
||||||
char isUsbVfoA=0, isUsbVfoB=1;
|
char isUsbVfoA=0, isUsbVfoB=1;
|
||||||
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
||||||
unsigned long firstIF = 45000000L;
|
unsigned long firstIF = DEFAULT_FIRSTIF;
|
||||||
|
|
||||||
//these are variables that control the keyer behaviour
|
//these are variables that control the keyer behaviour
|
||||||
int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
||||||
|
@ -238,46 +127,6 @@ void active_delay(int delay_by){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Select the properly tx harmonic filters
|
|
||||||
* The four harmonic filters use only three relays
|
|
||||||
* the four LPFs cover 30-21 Mhz, 18 - 14 Mhz, 7-10 MHz and 3.5 to 5 Mhz
|
|
||||||
* Briefly, it works like this,
|
|
||||||
* - When KT1 is OFF, the 'off' position routes the PA output through the 30 MHz LPF
|
|
||||||
* - When KT1 is ON, it routes the PA output to KT2. Which is why you will see that
|
|
||||||
* the KT1 is on for the three other cases.
|
|
||||||
* - When the KT1 is ON and KT2 is off, the off position of KT2 routes the PA output
|
|
||||||
* to 18 MHz LPF (That also works for 14 Mhz)
|
|
||||||
* - When KT1 is On, KT2 is On, it routes the PA output to KT3
|
|
||||||
* - KT3, when switched on selects the 7-10 Mhz filter
|
|
||||||
* - KT3 when switched off selects the 3.5-5 Mhz filter
|
|
||||||
* See the circuit to understand this
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setTXFilters(unsigned long freq){
|
|
||||||
|
|
||||||
if (freq > 21000000L){ // the default filter is with 35 MHz cut-off
|
|
||||||
digitalWrite(TX_LPF_A, 0);
|
|
||||||
digitalWrite(TX_LPF_B, 0);
|
|
||||||
digitalWrite(TX_LPF_C, 0);
|
|
||||||
}
|
|
||||||
else if (freq >= 14000000L){ //thrown the KT1 relay on, the 30 MHz LPF is bypassed and the 14-18 MHz LPF is allowd to go through
|
|
||||||
digitalWrite(TX_LPF_A, 1);
|
|
||||||
digitalWrite(TX_LPF_B, 0);
|
|
||||||
digitalWrite(TX_LPF_C, 0);
|
|
||||||
}
|
|
||||||
else if (freq > 7000000L){
|
|
||||||
digitalWrite(TX_LPF_A, 1);
|
|
||||||
digitalWrite(TX_LPF_B, 1);
|
|
||||||
digitalWrite(TX_LPF_C, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
digitalWrite(TX_LPF_A, 1);
|
|
||||||
digitalWrite(TX_LPF_B, 1);
|
|
||||||
digitalWrite(TX_LPF_C, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the most frequently called function that configures the
|
* This is the most frequently called function that configures the
|
||||||
* radio to a particular frequeny, sideband and sets up the transmit filters
|
* radio to a particular frequeny, sideband and sets up the transmit filters
|
||||||
|
@ -318,7 +167,18 @@ void setFrequency(unsigned long f){
|
||||||
void startTx(byte txMode){
|
void startTx(byte txMode){
|
||||||
unsigned long tx_freq = 0;
|
unsigned long tx_freq = 0;
|
||||||
|
|
||||||
|
// Turn off the main mixer oscillator and wait for RX->TX burst before
|
||||||
|
// TX is flipped on. Then we will re-enable the clocks.
|
||||||
|
si5351bx_setfreq(2, 0);
|
||||||
|
|
||||||
|
// Wait so things settle.
|
||||||
|
delay(TX_DELAY_OSC_OFF);
|
||||||
|
|
||||||
|
// Flip to TX.
|
||||||
digitalWrite(TX_RX, 1);
|
digitalWrite(TX_RX, 1);
|
||||||
|
|
||||||
|
// Wait for relays, etc to settle.
|
||||||
|
delay(TX_DELAY_ENABLE);
|
||||||
inTx = 1;
|
inTx = 1;
|
||||||
|
|
||||||
if (ritOn){
|
if (ritOn){
|
||||||
|
@ -357,12 +217,19 @@ void startTx(byte txMode){
|
||||||
si5351bx_setfreq(2, frequency - sideTone);
|
si5351bx_setfreq(2, frequency - sideTone);
|
||||||
}
|
}
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
clearMeterDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopTx(){
|
void stopTx(){
|
||||||
inTx = 0;
|
inTx = 0;
|
||||||
|
|
||||||
|
// Turn off the main vfo before disabling TX. setFrequency() will fix
|
||||||
|
// it.
|
||||||
|
si5351bx_setfreq(2, 0); // disable the VFO oscillator.
|
||||||
|
delay(TX_DELAY_OSC_OFF);
|
||||||
|
|
||||||
digitalWrite(TX_RX, 0); //turn off the tx
|
digitalWrite(TX_RX, 0); //turn off the tx
|
||||||
|
delay(TX_DELAY_ENABLE); // wait for relays to settle
|
||||||
si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off
|
si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off
|
||||||
|
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
|
@ -459,23 +326,49 @@ void checkButton(){
|
||||||
void doTuning(){
|
void doTuning(){
|
||||||
int s;
|
int s;
|
||||||
unsigned long prev_freq;
|
unsigned long prev_freq;
|
||||||
|
int freq_delta = 0;
|
||||||
|
|
||||||
s = enc_read();
|
s = enc_read();
|
||||||
if (s != 0){
|
if (s != 0){
|
||||||
prev_freq = frequency;
|
prev_freq = frequency;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that we don't tune below LOWEST_FREQ/HIGHEST_FREQ.
|
||||||
|
* We need to be sure that frequency doesn't underflow!
|
||||||
|
*/
|
||||||
|
|
||||||
if (s > 4)
|
if (s > 4)
|
||||||
frequency += 10000l;
|
freq_delta = 10000;
|
||||||
else if (s > 2)
|
else if (s > 2)
|
||||||
frequency += 500;
|
freq_delta = 500;
|
||||||
else if (s > 0)
|
else if (s > 0)
|
||||||
frequency += 50l;
|
freq_delta = 50;
|
||||||
else if (s > -2)
|
else if (s > -2)
|
||||||
frequency -= 50l;
|
freq_delta = -50;
|
||||||
else if (s > -4)
|
else if (s > -4)
|
||||||
frequency -= 500l;
|
freq_delta = -500;
|
||||||
else
|
else
|
||||||
frequency -= 10000l;
|
freq_delta = -10000;
|
||||||
|
|
||||||
|
/* Be super careful we don't underflow! */
|
||||||
|
if (freq_delta < 0) {
|
||||||
|
unsigned long offset;
|
||||||
|
offset = frequency - LOWEST_FREQ;
|
||||||
|
if (offset < (-freq_delta)) {
|
||||||
|
frequency = LOWEST_FREQ;
|
||||||
|
freq_delta = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not so likely to overflow here; a straight comparison is fine */
|
||||||
|
if (freq_delta > 0) {
|
||||||
|
if (frequency + freq_delta > HIGHEST_FREQ) {
|
||||||
|
frequency = HIGHEST_FREQ;
|
||||||
|
freq_delta = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frequency += freq_delta;
|
||||||
|
|
||||||
if (prev_freq < 10000000l && frequency > 10000000l)
|
if (prev_freq < 10000000l && frequency > 10000000l)
|
||||||
isUSB = true;
|
isUSB = true;
|
||||||
|
@ -483,8 +376,14 @@ void doTuning(){
|
||||||
if (prev_freq > 10000000l && frequency < 10000000l)
|
if (prev_freq > 10000000l && frequency < 10000000l)
|
||||||
isUSB = false;
|
isUSB = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't hammer on setting frequency / updating display if
|
||||||
|
* we are at the edges already and we're being clamped above.
|
||||||
|
*/
|
||||||
|
// if (prev_freq != frequency) {
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,10 +422,10 @@ void initSettings(){
|
||||||
EEPROM.get(VFO_B, vfoB);
|
EEPROM.get(VFO_B, vfoB);
|
||||||
EEPROM.get(CW_SIDETONE, sideTone);
|
EEPROM.get(CW_SIDETONE, sideTone);
|
||||||
EEPROM.get(CW_SPEED, cwSpeed);
|
EEPROM.get(CW_SPEED, cwSpeed);
|
||||||
|
EEPROM.get(CAL_FIRST_IF_FREQ, firstIF);
|
||||||
|
|
||||||
if (usbCarrier > 12000000l || usbCarrier < 11990000l)
|
if (usbCarrier > 12000000l || usbCarrier < 11990000l)
|
||||||
usbCarrier = 11997000l;
|
usbCarrier = INIT_USB_FREQ;
|
||||||
if (vfoA > 35000000l || 3500000l > vfoA)
|
if (vfoA > 35000000l || 3500000l > vfoA)
|
||||||
vfoA = 7150000l;
|
vfoA = 7150000l;
|
||||||
if (vfoB > 35000000l || 3500000l > vfoB)
|
if (vfoB > 35000000l || 3500000l > vfoB)
|
||||||
|
@ -535,6 +434,8 @@ void initSettings(){
|
||||||
sideTone = 800;
|
sideTone = 800;
|
||||||
if (cwSpeed < 10 || 1000 < cwSpeed)
|
if (cwSpeed < 10 || 1000 < cwSpeed)
|
||||||
cwSpeed = 100;
|
cwSpeed = 100;
|
||||||
|
if (firstIF < 44500000 || firstIF > 45500000)
|
||||||
|
firstIF = DEFAULT_FIRSTIF;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The VFO modes are read in as either 2 (USB) or 3(LSB), 0, the default
|
* The VFO modes are read in as either 2 (USB) or 3(LSB), 0, the default
|
||||||
|
@ -631,17 +532,22 @@ void setup()
|
||||||
Serial.begin(38400);
|
Serial.begin(38400);
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
lcd.begin(16, 2);
|
lcd.begin(16, 2);
|
||||||
|
lcd.clear();
|
||||||
|
initMeter();
|
||||||
|
|
||||||
//we print this line so this shows up even if the raduino
|
//we print this line so this shows up even if the raduino
|
||||||
//crashes later in the code
|
//crashes later in the code
|
||||||
printLine2("uBITX v4.3");
|
printLineF2(F("uBITX v4.3b"));
|
||||||
//active_delay(500);
|
//active_delay(500);
|
||||||
|
|
||||||
// initMeter(); //not used in this build
|
|
||||||
initSettings();
|
initSettings();
|
||||||
initPorts();
|
initPorts();
|
||||||
initOscillators();
|
initOscillators();
|
||||||
|
|
||||||
|
si5351bx_set_drive(0, 1); // 4ma
|
||||||
|
si5351bx_set_drive(1, 1); // 4ma
|
||||||
|
si5351bx_set_drive(2, 1); // 4ma
|
||||||
|
|
||||||
frequency = vfoA;
|
frequency = vfoA;
|
||||||
setFrequency(vfoA);
|
setFrequency(vfoA);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
@ -663,12 +569,14 @@ void loop(){
|
||||||
checkPTT();
|
checkPTT();
|
||||||
checkButton();
|
checkButton();
|
||||||
|
|
||||||
//tune only when not tranmsitting
|
//tune / display s-meter only when not tranmsitting
|
||||||
if (!inTx){
|
if (!inTx){
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
doRIT();
|
doRIT();
|
||||||
else
|
else
|
||||||
doTuning();
|
doTuning();
|
||||||
|
// TODO: only update this every few milliseconds? Not constantly?
|
||||||
|
updateMeterDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
//we check CAT after the encoder as it might put the radio into TX
|
//we check CAT after the encoder as it might put the radio into TX
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* This source file is under General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UBITX4_EEPROM_DEFAULTS_H__
|
||||||
|
#define __UBITX4_EEPROM_DEFAULTS_H__
|
||||||
|
|
||||||
|
// Delay when switching between TX and RX.
|
||||||
|
// This prevents spurious bursts when switching RX->TX.
|
||||||
|
#define TX_DELAY_OSC_OFF 15 // wait 15ms after turning off si5351 for it to be off off
|
||||||
|
#define TX_DELAY_ENABLE 30 // wait 30ms after enabling PTT to let things settle.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
||||||
|
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
||||||
|
* this shift is due to the loading on the 45 Mhz crystal filter by the matching
|
||||||
|
* L-network used on it's either sides.
|
||||||
|
* The first oscillator works between 48 Mhz and 75 MHz. The signal is subtracted
|
||||||
|
* from the first oscillator to arriive at 45 Mhz IF. Thus, it is inverted : LSB becomes USB
|
||||||
|
* and USB becomes LSB.
|
||||||
|
* The second IF of 12 Mhz has a ladder crystal filter. If a second oscillator is used at
|
||||||
|
* 57 Mhz, the signal is subtracted FROM the oscillator, inverting a second time, and arrives
|
||||||
|
* at the 12 Mhz ladder filter thus doouble inversion, keeps the sidebands as they originally were.
|
||||||
|
* If the second oscillator is at 33 Mhz, the oscilaltor is subtracated from the signal,
|
||||||
|
* thus keeping the signal's sidebands inverted. The USB will become LSB.
|
||||||
|
* We use this technique to switch sidebands. This is to avoid placing the lsbCarrier close to
|
||||||
|
* 12 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic
|
||||||
|
*/
|
||||||
|
|
||||||
|
// the second oscillator should ideally be at 57 MHz, however, the crystal filter's center frequency
|
||||||
|
// is shifted down a little due to the loading from the impedance matching L-networks on either sides
|
||||||
|
#define SECOND_OSC_USB (56995000l)
|
||||||
|
#define SECOND_OSC_LSB (32995000l)
|
||||||
|
|
||||||
|
//these are the two default USB and LSB frequencies. The best frequencies depend upon your individual taste and filter shape
|
||||||
|
#define INIT_USB_FREQ (11996500l)
|
||||||
|
|
||||||
|
// Default first IF frequency (can be tuned via EEPROM)
|
||||||
|
#define DEFAULT_FIRSTIF 45000000L
|
||||||
|
|
||||||
|
// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz
|
||||||
|
#define LOWEST_FREQ (100000l)
|
||||||
|
#define HIGHEST_FREQ (30000000l)
|
||||||
|
#define FAST_TUNE_STEP (200000L)
|
||||||
|
|
||||||
|
#endif /* __UBITX4_EEPROM_DEFAULTS_H__ */
|
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* This source file is under General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UBITX4_EEPROM_DEFS_H__
|
||||||
|
#define __UBITX4_EEPROM_DEFS_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the indices where these user changable settinngs are stored in the EEPROM
|
||||||
|
*/
|
||||||
|
#define MASTER_CAL 0
|
||||||
|
#define LSB_CAL 4
|
||||||
|
#define USB_CAL 8
|
||||||
|
#define SIDE_TONE 12
|
||||||
|
//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values
|
||||||
|
#define VFO_A 16
|
||||||
|
#define VFO_B 20
|
||||||
|
#define CW_SIDETONE 24
|
||||||
|
#define CW_SPEED 28
|
||||||
|
|
||||||
|
// Adrian's custom values
|
||||||
|
#define CAL_FIRST_IF_FREQ 252 // 252-255 - first IF freq calibrated value
|
||||||
|
|
||||||
|
//These are defines for the new features back-ported from KD8CEC's software
|
||||||
|
//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version
|
||||||
|
#define VFO_A_MODE 256 // 2: LSB, 3: USB
|
||||||
|
#define VFO_B_MODE 257
|
||||||
|
|
||||||
|
//values that are stored for the VFO modes
|
||||||
|
#define VFO_MODE_LSB 2
|
||||||
|
#define VFO_MODE_USB 3
|
||||||
|
|
||||||
|
// handkey, iambic a, iambic b : 0,1,2f
|
||||||
|
#define CW_KEY_TYPE 358
|
||||||
|
|
||||||
|
#endif /* __UBITX4_EEPROM_DEFS_H__ */
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* This source file is under General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UBITX4_PIN_CONFIG_H__
|
||||||
|
#define __UBITX4_PIN_CONFIG_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need to carefully pick assignment of pin for various purposes.
|
||||||
|
* There are two sets of completely programmable pins on the Raduino.
|
||||||
|
* First, on the top of the board, in line with the LCD connector is an 8-pin connector
|
||||||
|
* that is largely meant for analog inputs and front-panel control. It has a regulated 5v output,
|
||||||
|
* ground and six pins. Each of these six pins can be individually programmed
|
||||||
|
* either as an analog input, a digital input or a digital output.
|
||||||
|
* The pins are assigned as follows (left to right, display facing you):
|
||||||
|
* Pin 1 (Violet), A7, S-METER / SPARE
|
||||||
|
* Pin 2 (Blue), A6, KEYER (DATA)
|
||||||
|
* Pin 3 (Green), +5v
|
||||||
|
* Pin 4 (Yellow), Gnd
|
||||||
|
* Pin 5 (Orange), A3, PTT
|
||||||
|
* Pin 6 (Red), A2, F BUTTON
|
||||||
|
* Pin 7 (Brown), A1, ENC B
|
||||||
|
* Pin 8 (Black), A0, ENC A
|
||||||
|
*Note: A5, A4 are wired to the Si5351 as I2C interface
|
||||||
|
* *
|
||||||
|
* - A0 and A1 are used for the rotary encoder
|
||||||
|
* - A2 is used for the menu push button
|
||||||
|
* - A3 is PTT to the microphone
|
||||||
|
* - A6 is hooked up to the CW key jack via resistors, to implement
|
||||||
|
* either a straight key or paddle support
|
||||||
|
* - A7 is spare, but is currently used to drive an S-meter menu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ENC_A (A0)
|
||||||
|
#define ENC_B (A1)
|
||||||
|
#define FBUTTON (A2)
|
||||||
|
#define PTT (A3)
|
||||||
|
#define ANALOG_KEYER (A6)
|
||||||
|
#define ANALOG_SPARE (A7)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 16x2 LCD panel is connected to digital pins as:
|
||||||
|
* RESET : 8
|
||||||
|
* ENABLE : 9
|
||||||
|
* D4 : 10
|
||||||
|
* D5 : 11
|
||||||
|
* D6 : 12
|
||||||
|
* D7 : 13
|
||||||
|
*/
|
||||||
|
#define LCD_PIN_RESET 8
|
||||||
|
#define LCD_PIN_ENABLE 9
|
||||||
|
#define LCD_PIN_D4 10
|
||||||
|
#define LCD_PIN_D5 11
|
||||||
|
#define LCD_PIN_D6 12
|
||||||
|
#define LCD_PIN_D7 13
|
||||||
|
/**
|
||||||
|
* The second set of 16 pins on the Raduino's bottom connector are have the
|
||||||
|
* three clock outputs and the digital lines to control the rig.
|
||||||
|
* This assignment is as follows :
|
||||||
|
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||||
|
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
|
||||||
|
* These too are flexible with what you may do with them, for the Raduino, we use them to :
|
||||||
|
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
|
||||||
|
* - CW_KEY line : turns on the carrier for CW
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TX_RX (7)
|
||||||
|
#define CW_TONE (6)
|
||||||
|
#define TX_LPF_A (5)
|
||||||
|
#define TX_LPF_B (4)
|
||||||
|
#define TX_LPF_C (3)
|
||||||
|
#define CW_KEY (2)
|
||||||
|
|
||||||
|
#endif /* __UBITX4_PIN_CONFIG_H__ */
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef __UBITX4_TXFILT_H__
|
||||||
|
#define __UBITX4_TXFILT_H__
|
||||||
|
|
||||||
|
extern void setTXFilters(unsigned long freq);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* This source file is under General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ubitx4_eeprom_defs.h"
|
||||||
|
#include "ubitx4_pin_config.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the properly tx harmonic filters
|
||||||
|
*
|
||||||
|
* This is valid for the ubitx v4 board; different boards have different TX filter
|
||||||
|
* configurations and thus will need a different filter mapping routine here!
|
||||||
|
*
|
||||||
|
* The four harmonic filters use only three relays
|
||||||
|
* the four LPFs cover 30-21 Mhz, 18 - 14 Mhz, 7-10 MHz and 3.5 to 5 Mhz
|
||||||
|
* Briefly, it works like this,
|
||||||
|
* - When KT1 is OFF, the 'off' position routes the PA output through the 30 MHz LPF
|
||||||
|
* - When KT1 is ON, it routes the PA output to KT2. Which is why you will see that
|
||||||
|
* the KT1 is on for the three other cases.
|
||||||
|
* - When the KT1 is ON and KT2 is off, the off position of KT2 routes the PA output
|
||||||
|
* to 18 MHz LPF (That also works for 14 Mhz)
|
||||||
|
* - When KT1 is On, KT2 is On, it routes the PA output to KT3
|
||||||
|
* - KT3, when switched on selects the 7-10 Mhz filter
|
||||||
|
* - KT3 when switched off selects the 3.5-5 Mhz filter
|
||||||
|
* See the circuit to understand this
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
setTXFilters(unsigned long freq)
|
||||||
|
{
|
||||||
|
if (freq > 21000000L){ // the default filter is with 35 MHz cut-off
|
||||||
|
digitalWrite(TX_LPF_A, 0);
|
||||||
|
digitalWrite(TX_LPF_B, 0);
|
||||||
|
digitalWrite(TX_LPF_C, 0);
|
||||||
|
}
|
||||||
|
else if (freq >= 14000000L){
|
||||||
|
/*
|
||||||
|
* throw the KT1 relay on, the 30 MHz LPF is bypassed and
|
||||||
|
* the 14-18 MHz LPF is allowedd to go through
|
||||||
|
*/
|
||||||
|
digitalWrite(TX_LPF_A, 1);
|
||||||
|
digitalWrite(TX_LPF_B, 0);
|
||||||
|
digitalWrite(TX_LPF_C, 0);
|
||||||
|
}
|
||||||
|
else if (freq > 7000000L){
|
||||||
|
digitalWrite(TX_LPF_A, 1);
|
||||||
|
digitalWrite(TX_LPF_B, 1);
|
||||||
|
digitalWrite(TX_LPF_C, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digitalWrite(TX_LPF_A, 1);
|
||||||
|
digitalWrite(TX_LPF_B, 1);
|
||||||
|
digitalWrite(TX_LPF_C, 1);
|
||||||
|
}
|
||||||
|
}
|
277
ubitx_menu.ino
277
ubitx_menu.ino
|
@ -11,10 +11,11 @@
|
||||||
* - If the menu item is NOT clicked on, then the menu's prompt is to be displayed
|
* - If the menu item is NOT clicked on, then the menu's prompt is to be displayed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "ubitx4_defaults.h"
|
||||||
|
|
||||||
/** A generic control to read variable values
|
/** A generic control to read variable values
|
||||||
*/
|
*/
|
||||||
int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix)
|
int getValueByKnob(int minimum, int maximum, int step_size, int initial, const char* prefix, const char *postfix)
|
||||||
{
|
{
|
||||||
int knob = 0;
|
int knob = 0;
|
||||||
int knob_value;
|
int knob_value;
|
||||||
|
@ -55,20 +56,17 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
||||||
|
|
||||||
//# Menu: 1
|
//# Menu: 1
|
||||||
|
|
||||||
int menuBand(int btn){
|
void menuBand(int btn){
|
||||||
int knob = 0;
|
int knob = 0;
|
||||||
int band;
|
int band;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
||||||
// band = frequency/1000000l;
|
|
||||||
// offset = frequency % 1000000l;
|
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Band Select \x7E");
|
printLineF2(F("Band Select \x7E"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printLine2("Band Select:");
|
printLineF2(F("Band Select:"));
|
||||||
//wait for the button menu select button to be lifted)
|
//wait for the button menu select button to be lifted)
|
||||||
while (btnDown())
|
while (btnDown())
|
||||||
active_delay(50);
|
active_delay(50);
|
||||||
|
@ -80,19 +78,27 @@ int menuBand(int btn){
|
||||||
knob = enc_read();
|
knob = enc_read();
|
||||||
if (knob != 0){
|
if (knob != 0){
|
||||||
/*
|
/*
|
||||||
if (band > 3 && knob < 0)
|
* Ensure that we cap the band select between LOWEST_FREQ
|
||||||
band--;
|
* and HIGHEST_FREQ.
|
||||||
if (band < 30 && knob > 0)
|
*/
|
||||||
band++;
|
if ((knob < 0) && (frequency > LOWEST_FREQ)) {
|
||||||
if (band > 10)
|
/* Ensure we don't tune below LOWEST_FREQ */
|
||||||
isUSB = true;
|
if (frequency > (FAST_TUNE_STEP * 2)) {
|
||||||
else
|
setFrequency(frequency - FAST_TUNE_STEP);
|
||||||
isUSB = false;
|
} else {
|
||||||
setFrequency(((unsigned long)band * 1000000l) + offset); */
|
setFrequency(LOWEST_FREQ);
|
||||||
if (knob < 0 && frequency > 3000000l)
|
}
|
||||||
setFrequency(frequency - 200000l);
|
}
|
||||||
if (knob > 0 && frequency < 30000000l)
|
if ((knob > 0) && (frequency < HIGHEST_FREQ)) {
|
||||||
setFrequency(frequency + 200000l);
|
/* Ensure we don't tune above HIGHEST_FREQ */
|
||||||
|
if ((frequency + FAST_TUNE_STEP) > HIGHEST_FREQ) {
|
||||||
|
setFrequency(HIGHEST_FREQ);
|
||||||
|
} else {
|
||||||
|
setFrequency(frequency + FAST_TUNE_STEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust mode to be USB/LSB across 10MHz */
|
||||||
if (frequency > 10000000l)
|
if (frequency > 10000000l)
|
||||||
isUSB = true;
|
isUSB = true;
|
||||||
else
|
else
|
||||||
|
@ -107,7 +113,7 @@ int menuBand(int btn){
|
||||||
active_delay(50);
|
active_delay(50);
|
||||||
active_delay(50);
|
active_delay(50);
|
||||||
|
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
@ -116,24 +122,24 @@ int menuBand(int btn){
|
||||||
void menuRitToggle(int btn){
|
void menuRitToggle(int btn){
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (ritOn == 1)
|
if (ritOn == 1)
|
||||||
printLine2("RIT On \x7E Off");
|
printLineF2(F("RIT On \x7E Off"));
|
||||||
else
|
else
|
||||||
printLine2("RIT Off \x7E On");
|
printLineF2(F("RIT Off \x7E On"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ritOn == 0){
|
if (ritOn == 0){
|
||||||
//enable RIT so the current frequency is used at transmit
|
//enable RIT so the current frequency is used at transmit
|
||||||
ritEnable(frequency);
|
ritEnable(frequency);
|
||||||
printLine2("RIT is On");
|
printLineF2(F("RIT is On"));
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ritDisable();
|
ritDisable();
|
||||||
printLine2("RIT is Off");
|
printLineF2(F("RIT is Off"));
|
||||||
}
|
}
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,9 +150,9 @@ void menuVfoToggle(int btn){
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (vfoActive == VFO_A)
|
if (vfoActive == VFO_A)
|
||||||
printLine2("VFO A \x7E B");
|
printLineF2(F("VFO A \x7E B"));
|
||||||
else
|
else
|
||||||
printLine2("VFO B \x7E A");
|
printLineF2(F("VFO B \x7E A"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (vfoActive == VFO_B){
|
if (vfoActive == VFO_B){
|
||||||
|
@ -159,7 +165,7 @@ void menuVfoToggle(int btn){
|
||||||
EEPROM.put(VFO_B_MODE, VFO_MODE_LSB);
|
EEPROM.put(VFO_B_MODE, VFO_MODE_LSB);
|
||||||
|
|
||||||
vfoActive = VFO_A;
|
vfoActive = VFO_A;
|
||||||
// printLine2("Selected VFO A ");
|
// printLineF2(F("Selected VFO A "));
|
||||||
frequency = vfoA;
|
frequency = vfoA;
|
||||||
isUSB = isUsbVfoA;
|
isUSB = isUsbVfoA;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +179,7 @@ void menuVfoToggle(int btn){
|
||||||
EEPROM.put(VFO_A_MODE, VFO_MODE_LSB);
|
EEPROM.put(VFO_A_MODE, VFO_MODE_LSB);
|
||||||
|
|
||||||
vfoActive = VFO_B;
|
vfoActive = VFO_B;
|
||||||
// printLine2("Selected VFO B ");
|
// printLineF2(F("Selected VFO B "));
|
||||||
frequency = vfoB;
|
frequency = vfoB;
|
||||||
isUSB = isUsbVfoB;
|
isUSB = isUsbVfoB;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +187,7 @@ void menuVfoToggle(int btn){
|
||||||
ritDisable();
|
ritDisable();
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
//exit the menu
|
//exit the menu
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
@ -191,31 +197,35 @@ void menuVfoToggle(int btn){
|
||||||
void menuSidebandToggle(int btn){
|
void menuSidebandToggle(int btn){
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (isUSB == true)
|
if (isUSB == true)
|
||||||
printLine2("USB \x7E LSB");
|
printLineF2(F("USB \x7E LSB"));
|
||||||
else
|
else
|
||||||
printLine2("LSB \x7E USB");
|
printLineF2(F("LSB \x7E USB"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isUSB == true){
|
if (isUSB == true){
|
||||||
isUSB = false;
|
isUSB = false;
|
||||||
printLine2("LSB Selected");
|
printLineF2(F("LSB Selected"));
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isUSB = true;
|
isUSB = true;
|
||||||
printLine2("USB Selected");
|
printLineF2(F("USB Selected"));
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
}
|
}
|
||||||
//Added by KD8CEC
|
//Added by KD8CEC
|
||||||
if (vfoActive == VFO_B){
|
if (vfoActive == VFO_B){
|
||||||
isUsbVfoB = isUSB;
|
isUsbVfoB = isUSB;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isUsbVfoB = isUSB;
|
isUsbVfoA = isUSB;
|
||||||
}
|
}
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
|
||||||
|
// Update the programmed frequency immediately so the band flips.
|
||||||
|
setFrequency(frequency);
|
||||||
|
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,29 +235,29 @@ void menuSidebandToggle(int btn){
|
||||||
void menuSplitToggle(int btn){
|
void menuSplitToggle(int btn){
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (splitOn == 0)
|
if (splitOn == 0)
|
||||||
printLine2("Split Off \x7E On");
|
printLineF2(F("Split Off \x7E On"));
|
||||||
else
|
else
|
||||||
printLine2("Split On \x7E Off");
|
printLineF2(F("Split On \x7E Off"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (splitOn == 1){
|
if (splitOn == 1){
|
||||||
splitOn = 0;
|
splitOn = 0;
|
||||||
printLine2("Split ON");
|
printLineF2(F("Split ON"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
splitOn = 1;
|
splitOn = 1;
|
||||||
if (ritOn == 1)
|
if (ritOn == 1)
|
||||||
ritOn = 0;
|
ritOn = 0;
|
||||||
printLine2("Split Off");
|
printLineF2(F("Split Off"));
|
||||||
}
|
}
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int menuCWSpeed(int btn){
|
void menuCWSpeed(int btn){
|
||||||
int knob = 0;
|
int knob = 0;
|
||||||
int wpm;
|
int wpm;
|
||||||
|
|
||||||
|
@ -295,12 +305,12 @@ int menuCWSpeed(int btn){
|
||||||
*/
|
*/
|
||||||
wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM>");
|
wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM>");
|
||||||
|
|
||||||
printLine2("CW Speed set!");
|
printLineF2(F("CW Speed set!"));
|
||||||
cwSpeed = 1200/wpm;
|
cwSpeed = 1200/wpm;
|
||||||
EEPROM.put(CW_SPEED, cwSpeed);
|
EEPROM.put(CW_SPEED, cwSpeed);
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
|
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
@ -308,12 +318,12 @@ int menuCWSpeed(int btn){
|
||||||
void menuExit(int btn){
|
void menuExit(int btn){
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Exit Menu \x7E");
|
printLineF2(F("Exit Menu \x7E"));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
printLine2("Exiting...");
|
printLineF2(F("Exiting..."));
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
@ -326,23 +336,23 @@ void menuExit(int btn){
|
||||||
int menuSetup(int btn){
|
int menuSetup(int btn){
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (!modeCalibrate)
|
if (!modeCalibrate)
|
||||||
printLine2("Settings \x7E");
|
printLineF2(F("Settings \x7E"));
|
||||||
else
|
else
|
||||||
printLine2("Settings \x7E Off");
|
printLineF2(F("Settings \x7E Off"));
|
||||||
}else {
|
}else {
|
||||||
if (!modeCalibrate){
|
if (!modeCalibrate){
|
||||||
modeCalibrate = true;
|
modeCalibrate = true;
|
||||||
printLine2("Settings On");
|
printLineF2(F("Settings On"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
modeCalibrate = false;
|
modeCalibrate = false;
|
||||||
printLine2("Settings Off");
|
printLineF2(F("Settings Off"));
|
||||||
}
|
}
|
||||||
|
|
||||||
while(btnDown())
|
while(btnDown())
|
||||||
active_delay(100);
|
active_delay(100);
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -410,7 +420,7 @@ int calibrateClock(){
|
||||||
keyDown = 0;
|
keyDown = 0;
|
||||||
stopTx();
|
stopTx();
|
||||||
|
|
||||||
printLine2("Calibration set!");
|
printLineF2(F("Calibration set!"));
|
||||||
EEPROM.put(MASTER_CAL, calibration);
|
EEPROM.put(MASTER_CAL, calibration);
|
||||||
initOscillators();
|
initOscillators();
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
|
@ -426,12 +436,12 @@ int menuSetupCalibration(int btn){
|
||||||
int32_t prev_calibration;
|
int32_t prev_calibration;
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Setup:Calibrate\x7E");
|
printLineF2(F("Setup:Calibrate\x7E"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printLine1("Press PTT & tune");
|
printLineF1(F("Press PTT & tune"));
|
||||||
printLine2("to exactly 10 MHz");
|
printLineF2(F("to exactly 10 MHz"));
|
||||||
active_delay(2000);
|
active_delay(2000);
|
||||||
calibrateClock();
|
calibrateClock();
|
||||||
}
|
}
|
||||||
|
@ -451,21 +461,30 @@ void printCarrierFreq(unsigned long freq){
|
||||||
printLine2(c);
|
printLine2(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printFreq(unsigned long freq)
|
||||||
|
{
|
||||||
|
memset(c, 0, sizeof(c));
|
||||||
|
memset(b, 0, sizeof(b));
|
||||||
|
ultoa(freq, b, DEC);
|
||||||
|
printLine2(b);
|
||||||
|
}
|
||||||
|
|
||||||
void menuSetupCarrier(int btn){
|
void menuSetupCarrier(int btn){
|
||||||
int knob = 0;
|
int knob = 0;
|
||||||
unsigned long prevCarrier;
|
unsigned long prevCarrier;
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Setup:BFO \x7E");
|
printLineF2(F("Setup:BFO \x7E"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevCarrier = usbCarrier;
|
prevCarrier = usbCarrier;
|
||||||
printLine1("Tune to best Signal");
|
printLineF1(F("Tune to best Signal"));
|
||||||
printLine2("Press to confirm. ");
|
printLineF2(F("Press to confirm. "));
|
||||||
active_delay(1000);
|
active_delay(1000);
|
||||||
|
|
||||||
usbCarrier = 11995000l;
|
usbCarrier = INIT_USB_FREQ;
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, usbCarrier);
|
||||||
printCarrierFreq(usbCarrier);
|
printCarrierFreq(usbCarrier);
|
||||||
|
|
||||||
|
@ -486,14 +505,62 @@ void menuSetupCarrier(int btn){
|
||||||
active_delay(100);
|
active_delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
printLine2("Carrier set! ");
|
printLineF2(F("Carrier set! "));
|
||||||
EEPROM.put(USB_CAL, usbCarrier);
|
EEPROM.put(USB_CAL, usbCarrier);
|
||||||
active_delay(1000);
|
active_delay(1000);
|
||||||
|
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, usbCarrier);
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
|
menuOn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calibrate the IF frequency
|
||||||
|
void menuSetupFreqIF(int btn){
|
||||||
|
int knob = 0;
|
||||||
|
unsigned long prevIF;
|
||||||
|
|
||||||
|
if (!btn){
|
||||||
|
printLineF2(F("Setup:IF \x7E"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevIF = firstIF;
|
||||||
|
printLineF1(F("Tune to loudest signal"));
|
||||||
|
printLineF2(F("Press to confirm. "));
|
||||||
|
active_delay(1000);
|
||||||
|
|
||||||
|
setFrequency(frequency);
|
||||||
|
printFreq(firstIF);
|
||||||
|
|
||||||
|
//disable all clock 1 and clock 2
|
||||||
|
while (!btnDown()){
|
||||||
|
knob = enc_read();
|
||||||
|
|
||||||
|
if (knob > 0)
|
||||||
|
firstIF += 50;
|
||||||
|
else if (knob < 0)
|
||||||
|
firstIF -= 50;
|
||||||
|
|
||||||
|
checkPTT();
|
||||||
|
|
||||||
|
if (knob == 0)
|
||||||
|
continue; //don't update the frequency or the display
|
||||||
|
|
||||||
|
setFrequency(frequency);
|
||||||
|
printFreq(firstIF);
|
||||||
|
|
||||||
|
active_delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
printLineF2(F("IF set! "));
|
||||||
|
|
||||||
|
EEPROM.put(CAL_FIRST_IF_FREQ, firstIF);
|
||||||
|
active_delay(1000);
|
||||||
|
setFrequency(frequency);
|
||||||
|
updateDisplay();
|
||||||
|
printLineF2(F(""));
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,13 +569,13 @@ void menuSetupCwTone(int btn){
|
||||||
int prev_sideTone;
|
int prev_sideTone;
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Setup:CW Tone \x7E");
|
printLineF2(F("Setup:CW Tone \x7E"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_sideTone = sideTone;
|
prev_sideTone = sideTone;
|
||||||
printLine1("Tune CW tone");
|
printLineF1(F("Tune CW tone"));
|
||||||
printLine2("PTT to confirm. ");
|
printLineF2(F("PTT to confirm. "));
|
||||||
active_delay(1000);
|
active_delay(1000);
|
||||||
tone(CW_TONE, sideTone);
|
tone(CW_TONE, sideTone);
|
||||||
|
|
||||||
|
@ -534,14 +601,14 @@ void menuSetupCwTone(int btn){
|
||||||
noTone(CW_TONE);
|
noTone(CW_TONE);
|
||||||
//save the setting
|
//save the setting
|
||||||
if (digitalRead(PTT) == LOW){
|
if (digitalRead(PTT) == LOW){
|
||||||
printLine2("Sidetone set! ");
|
printLineF2(F("Sidetone set! "));
|
||||||
EEPROM.put(CW_SIDETONE, sideTone);
|
EEPROM.put(CW_SIDETONE, sideTone);
|
||||||
active_delay(2000);
|
active_delay(2000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sideTone = prev_sideTone;
|
sideTone = prev_sideTone;
|
||||||
|
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
@ -551,7 +618,7 @@ void menuSetupCwDelay(int btn){
|
||||||
int prev_cw_delay;
|
int prev_cw_delay;
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("Setup:CW Delay \x7E");
|
printLineF2(F("Setup:CW Delay \x7E"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,8 +626,8 @@ void menuSetupCwDelay(int btn){
|
||||||
prev_cw_delay = cwDelayTime;
|
prev_cw_delay = cwDelayTime;
|
||||||
cwDelayTime = getValueByKnob(10, 1000, 50, cwDelayTime, "CW Delay>", " msec");
|
cwDelayTime = getValueByKnob(10, 1000, 50, cwDelayTime, "CW Delay>", " msec");
|
||||||
|
|
||||||
printLine1("CW Delay Set!");
|
printLineF1(F("CW Delay Set!"));
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
|
@ -571,11 +638,11 @@ void menuSetupKeyer(int btn){
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
if (!Iambic_Key)
|
if (!Iambic_Key)
|
||||||
printLine2("Setup:CW(Hand)\x7E");
|
printLineF2(F("Setup:CW(Hand)\x7E"));
|
||||||
else if (keyerControl & IAMBICB)
|
else if (keyerControl & IAMBICB)
|
||||||
printLine2("Setup:CW(IambA)\x7E");
|
printLineF2(F("Setup:CW(IambA)\x7E"));
|
||||||
else
|
else
|
||||||
printLine2("Setup:CW(IambB)\x7E");
|
printLineF2(F("Setup:CW(IambB)\x7E"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,11 +667,11 @@ void menuSetupKeyer(int btn){
|
||||||
tmp_key = 0;
|
tmp_key = 0;
|
||||||
|
|
||||||
if (tmp_key == 0)
|
if (tmp_key == 0)
|
||||||
printLine1("Hand Key?");
|
printLineF1(F("Hand Key?"));
|
||||||
else if (tmp_key == 1)
|
else if (tmp_key == 1)
|
||||||
printLine1("Iambic A?");
|
printLineF1(F("Iambic A?"));
|
||||||
else if (tmp_key == 2)
|
else if (tmp_key == 2)
|
||||||
printLine1("Iambic B?");
|
printLineF1(F("Iambic B?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
active_delay(500);
|
active_delay(500);
|
||||||
|
@ -621,32 +688,67 @@ void menuSetupKeyer(int btn){
|
||||||
|
|
||||||
EEPROM.put(CW_KEY_TYPE, tmp_key);
|
EEPROM.put(CW_KEY_TYPE, tmp_key);
|
||||||
|
|
||||||
printLine1("Keyer Set!");
|
printLineF1(F("Keyer Set!"));
|
||||||
active_delay(600);
|
active_delay(600);
|
||||||
printLine1("");
|
printLineF1(F(""));
|
||||||
|
|
||||||
//Added KD8CEC
|
//Added KD8CEC
|
||||||
printLine2("");
|
printLineF2(F(""));
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menuReadADC(int btn){
|
void menuReadADC(int btn){
|
||||||
int adc;
|
int adc;
|
||||||
|
char a = 0, al; // Go from A0 -> A7
|
||||||
|
int knob;
|
||||||
|
|
||||||
if (!btn){
|
if (!btn){
|
||||||
printLine2("6:Setup>Read ADC>");
|
printLineF2(F("6:Setup>Read ADC>"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
while (!btnDown()){
|
while (!btnDown()){
|
||||||
adc = analogRead(ANALOG_KEYER);
|
// Assemble the display string, showing the A line and value
|
||||||
|
c[0] = 0;
|
||||||
|
strcat(c, "A");
|
||||||
|
itoa(a, b, 10);
|
||||||
|
strcat(c, b);
|
||||||
|
strcat(c, " = ");
|
||||||
|
|
||||||
|
// Map A line to value, yeah, I wish it were easier?
|
||||||
|
switch (a) {
|
||||||
|
case 0: al = A0; break;
|
||||||
|
case 1: al = A1; break;
|
||||||
|
case 2: al = A2; break;
|
||||||
|
case 3: al = A3; break;
|
||||||
|
case 4: al = A4; break;
|
||||||
|
case 5: al = A5; break;
|
||||||
|
case 6: al = A6; break;
|
||||||
|
case 7: al = A7; break;
|
||||||
|
}
|
||||||
|
adc = analogRead(al);
|
||||||
itoa(adc, b, 10);
|
itoa(adc, b, 10);
|
||||||
printLine1(b);
|
strcat(c, b);
|
||||||
|
printLine1(c);
|
||||||
|
|
||||||
|
// Read the encoder, see if we need to change the ADC
|
||||||
|
knob = enc_read();
|
||||||
|
if ((knob > 4) && (a < 7)) {
|
||||||
|
a++;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
if ((knob < -4) && (a > 0)) {
|
||||||
|
a--;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printLine1("");
|
printLineF1(F(""));
|
||||||
|
|
||||||
|
// Debounce the menu select
|
||||||
|
delay(500);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +767,7 @@ void doMenu(){
|
||||||
btnState = btnDown();
|
btnState = btnDown();
|
||||||
|
|
||||||
if (i > 0){
|
if (i > 0){
|
||||||
if (modeCalibrate && select + i < 150)
|
if (modeCalibrate && select + i < 160)
|
||||||
select += i;
|
select += i;
|
||||||
if (!modeCalibrate && select + i < 80)
|
if (!modeCalibrate && select + i < 80)
|
||||||
select += i;
|
select += i;
|
||||||
|
@ -701,6 +803,8 @@ void doMenu(){
|
||||||
menuReadADC(btnState);
|
menuReadADC(btnState);
|
||||||
else if (select < 140 && modeCalibrate)
|
else if (select < 140 && modeCalibrate)
|
||||||
menuSetupKeyer(btnState);
|
menuSetupKeyer(btnState);
|
||||||
|
else if (select < 150 && modeCalibrate)
|
||||||
|
menuSetupFreqIF(btnState);
|
||||||
else
|
else
|
||||||
menuExit(btnState);
|
menuExit(btnState);
|
||||||
}
|
}
|
||||||
|
@ -712,4 +816,3 @@ void doMenu(){
|
||||||
|
|
||||||
checkCAT();
|
checkCAT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,12 @@ void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array
|
||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call to set the drive strength, takes effect next frequency
|
||||||
|
// set.
|
||||||
|
void si5351bx_set_drive(uint8_t clknum, uint8_t drv)
|
||||||
|
{
|
||||||
|
si5351bx_drive[clknum] = drv & 0x3;
|
||||||
|
}
|
||||||
|
|
||||||
void si5351bx_init() { // Call once at power-up, start PLLA
|
void si5351bx_init() { // Call once at power-up, start PLLA
|
||||||
uint8_t reg; uint32_t msxp1;
|
uint8_t reg; uint32_t msxp1;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef __UBITX_UI_H__
|
||||||
|
#define __UBITX_UI_H__
|
||||||
|
|
||||||
|
extern int btnDown(void);
|
||||||
|
extern void initMeter(void);
|
||||||
|
extern void drawMeter(uint8_t needle);
|
||||||
|
extern void printLine(char linenmbr, const char *c);
|
||||||
|
extern void printLineF(char linenmbr, const __FlashStringHelper *c);
|
||||||
|
|
||||||
|
|
||||||
|
#define printLine1(c) printLine(1, (c))
|
||||||
|
#define printLine2(c) printLine(0, (c))
|
||||||
|
|
||||||
|
#define printLineF1(c) printLineF(1, (c))
|
||||||
|
#define printLineF2(c) printLineF(0, (c))
|
||||||
|
|
||||||
|
extern void updateDisplay(void);
|
||||||
|
extern void updateMeterDisplay(void);
|
||||||
|
extern void clearMeterDisplay(void);
|
||||||
|
extern byte enc_state (void);
|
||||||
|
extern int enc_read(void);
|
||||||
|
|
||||||
|
#endif
|
177
ubitx_ui.ino
177
ubitx_ui.ino
|
@ -6,8 +6,14 @@
|
||||||
* quickly cleared up.
|
* quickly cleared up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "ubitx4_eeprom_defs.h"
|
||||||
|
#include "ubitx4_pin_config.h"
|
||||||
|
|
||||||
|
#include "ubitx_ui.h"
|
||||||
|
|
||||||
//returns true if the button is pressed
|
//returns true if the button is pressed
|
||||||
int btnDown(){
|
int btnDown(void)
|
||||||
|
{
|
||||||
if (digitalRead(FBUTTON) == HIGH)
|
if (digitalRead(FBUTTON) == HIGH)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
|
@ -24,65 +30,59 @@ int btnDown(){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
char meter[17];
|
char meter[2];
|
||||||
|
|
||||||
const byte PROGMEM s_meter_bitmap[] = {
|
const PROGMEM uint8_t s_meter_bitmap[64] = {
|
||||||
B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011,
|
B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111, //shortest bar
|
||||||
B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011,
|
B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111,
|
||||||
B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011,
|
B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111,
|
||||||
B00100,B00100,B00100,B00100,B00100,B00100,B00100,B11011,
|
B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111,
|
||||||
B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011,
|
B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111,
|
||||||
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011,
|
B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111,
|
||||||
B10000,B11000,B11100,B11110,B11100,B11000,B10000,B00000,
|
B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111,
|
||||||
B00001,B00011,B00111,B01111,B00111,B00011,B00001,B00000
|
B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111, // tallest bar
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Initialise the custom character out of program memory
|
||||||
|
static void
|
||||||
|
initLcdChar(char lcd_char, char s_meter_bitmap_offset)
|
||||||
|
{
|
||||||
|
uint8_t tmp_bytes[8];
|
||||||
|
char i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
tmp_bytes[i] = pgm_read_byte(&s_meter_bitmap[s_meter_bitmap_offset + i]);
|
||||||
|
}
|
||||||
|
lcd.createChar(lcd_char, tmp_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
// initializes the custom characters
|
// initializes the custom characters
|
||||||
// we start from char 1 as char 0 terminates the string!
|
void initMeter(void)
|
||||||
void initMeter(){
|
{
|
||||||
lcd.createChar(1, s_meter_bitmap);
|
lcd.setCursor(0, 0); // Ensure we've reset to display RAM
|
||||||
lcd.createChar(2, s_meter_bitmap + 8);
|
initLcdChar(0, 0); // First call - points to chargen RAM
|
||||||
lcd.createChar(3, s_meter_bitmap + 16);
|
initLcdChar(1, 8);
|
||||||
lcd.createChar(4, s_meter_bitmap + 24);
|
initLcdChar(2, 16);
|
||||||
lcd.createChar(5, s_meter_bitmap + 32);
|
initLcdChar(3, 24);
|
||||||
lcd.createChar(6, s_meter_bitmap + 40);
|
initLcdChar(4, 32);
|
||||||
lcd.createChar(0, s_meter_bitmap + 48);
|
initLcdChar(5, 40);
|
||||||
lcd.createChar(7, s_meter_bitmap + 56);
|
initLcdChar(6, 48);
|
||||||
|
initLcdChar(7, 56);
|
||||||
|
lcd.setCursor(0, 0); // Finish up - point to display RAM again
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The meter is drawn with special characters.
|
* The meter is drawn with special characters from 0..255
|
||||||
* character 1 is used to simple draw the blocks of the scale of the meter
|
|
||||||
* characters 2 to 6 are used to draw the needle in positions 1 to within the block
|
|
||||||
* This displays a meter from 0 to 100, -1 displays nothing
|
|
||||||
*/
|
*/
|
||||||
|
void drawMeter(uint8_t needle)
|
||||||
void drawMeter(int8_t needle){
|
{
|
||||||
int16_t best, i, s;
|
meter[0] = needle / 32;
|
||||||
|
meter[1] = needle / 32;
|
||||||
if (needle < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = (needle * 4)/10;
|
|
||||||
for (i = 0; i < 8; i++){
|
|
||||||
if (s >= 5)
|
|
||||||
meter[i] = 1;
|
|
||||||
else if (s >= 0)
|
|
||||||
meter[i] = 2 + s;
|
|
||||||
else
|
|
||||||
meter[i] = 1;
|
|
||||||
s = s - 5;
|
|
||||||
}
|
|
||||||
if (needle >= 40)
|
|
||||||
meter[i-1] = 6;
|
|
||||||
meter[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The generic routine to display one line on the LCD
|
// The generic routine to display one line on the LCD
|
||||||
void printLine(char linenmbr, char *c) {
|
void printLine(char linenmbr, const char *c) {
|
||||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||||
lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||||
lcd.print(c);
|
lcd.print(c);
|
||||||
|
@ -94,18 +94,26 @@ void printLine(char linenmbr, char *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char tmp[17]; // XXX TODO: figure out how to do this inline without the buffer
|
||||||
|
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||||
|
unsigned char ch;
|
||||||
|
|
||||||
// short cut to print to the first line
|
for (i = 0; i < 17; i++) {
|
||||||
void printLine1(char *c){
|
ch = pgm_read_byte(p++);
|
||||||
printLine(1,c);
|
tmp[i] = ch;
|
||||||
|
if (ch == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// short cut to print to the first line
|
printLine(linenmbr, tmp);
|
||||||
void printLine2(char *c){
|
|
||||||
printLine(0,c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this builds up the top line of the display with frequency and mode
|
// this builds up the top line of the display with frequency and mode
|
||||||
void updateDisplay() {
|
void updateDisplay(void)
|
||||||
|
{
|
||||||
// tks Jack Purdum W8TEE
|
// tks Jack Purdum W8TEE
|
||||||
// replaced fsprint commmands by str commands for code size reduction
|
// replaced fsprint commmands by str commands for code size reduction
|
||||||
|
|
||||||
|
@ -135,18 +143,24 @@ void updateDisplay() {
|
||||||
strcat(c, "B:");
|
strcat(c, "B:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* + zero mhz digit/one less dot if less than 1MHz
|
||||||
//one mhz digit if less than 10 M, two digits if more
|
* + one mhz digit if less than 10MHz
|
||||||
if (frequency < 10000000l){
|
* + two digits if more
|
||||||
|
*/
|
||||||
|
if (frequency < 1000000L) {
|
||||||
|
c[6] = ' '; c[7] = ' '; c[8] = ' ';
|
||||||
|
strncat(c, &b[0], 3);
|
||||||
|
strcat(c, ".");
|
||||||
|
strncat(c, &b[3], 3);
|
||||||
|
} else if (frequency < 10000000l){
|
||||||
c[6] = ' ';
|
c[6] = ' ';
|
||||||
c[7] = b[0];
|
c[7] = b[0];
|
||||||
strcat(c, ".");
|
strcat(c, ".");
|
||||||
strncat(c, &b[1], 3);
|
strncat(c, &b[1], 3);
|
||||||
strcat(c, ".");
|
strcat(c, ".");
|
||||||
strncat(c, &b[4], 3);
|
strncat(c, &b[4], 3);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
strncat(c, b, 2);
|
strncat(c, b, 2);
|
||||||
strcat(c, ".");
|
strcat(c, ".");
|
||||||
strncat(c, &b[2], 3);
|
strncat(c, &b[2], 3);
|
||||||
|
@ -157,22 +171,41 @@ void updateDisplay() {
|
||||||
if (inTx)
|
if (inTx)
|
||||||
strcat(c, " TX");
|
strcat(c, " TX");
|
||||||
printLine(1, c);
|
printLine(1, c);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//now, the second line
|
* Update the meter display!
|
||||||
memset(c, 0, sizeof(c));
|
*/
|
||||||
memset(b, 0, sizeof(b));
|
void
|
||||||
|
updateMeterDisplay(void)
|
||||||
|
{
|
||||||
|
int meter_reading = 0;
|
||||||
|
|
||||||
if (inTx)
|
// Second line, meter on A7 (ANALOG_SPARE)
|
||||||
strcat(c, "TX ");
|
meter_reading = analogRead(ANALOG_SPARE);
|
||||||
else if (ritOn)
|
|
||||||
strcpy(c, "RIT");
|
|
||||||
|
|
||||||
strcpy(c, " \xff");
|
// TODO - there's no mapping table here yet! Just linear it!
|
||||||
drawMeter(meter_reading);
|
if (meter_reading > 255) {
|
||||||
strcat(c, meter);
|
// Ensure we definitely don't overflow an int here
|
||||||
strcat(c, "\xff");
|
meter_reading = 255;
|
||||||
printLine2(c);*/
|
}
|
||||||
|
drawMeter(meter_reading); // this takes uint8_t
|
||||||
|
lcd.setCursor(14, 0);
|
||||||
|
lcd.write(meter[0]);
|
||||||
|
lcd.setCursor(15, 0);
|
||||||
|
lcd.write(meter[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the meter - used during transmit
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clearMeterDisplay(void)
|
||||||
|
{
|
||||||
|
lcd.setCursor(14, 0);
|
||||||
|
lcd.write(' ');
|
||||||
|
lcd.setCursor(15, 0);
|
||||||
|
lcd.write(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
int enc_prev_state = 3;
|
int enc_prev_state = 3;
|
||||||
|
@ -234,5 +267,3 @@ int enc_read(void) {
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue