Add SWR meter support (TNX Alain K1FM)

pull/51/head
guido 2021-03-11 14:22:09 +01:00
commit 6fd354a6ec
1 zmienionych plików z 74 dodań i 42 usunięć

Wyświetl plik

@ -32,6 +32,7 @@
#define VOX_ENABLE 1 // Voice-On-Xmit which is switching the transceiver into transmit as soon audio is detected (above noise gate level)
//#define MOX_ENABLE 1 // Monitor-On-Xmit which is audio monitoring on speaker during transmit
//#define VSS_METER 1 // Supports Vss measurement (as s-meter option)
//#define SWR_METER 1 // Support SWR meter with bridge on A6/A7 (LQPF ATMEGA328P) by Alain, K1FM, see: https://groups.io/g/ucx/message/6262 and https://groups.io/g/ucx/message/6361
//#define CW_FREQS_QRP 1 // Defaults to CW QRP frequencies when changing bands
//#define CW_FREQS_FISTS 1 // Defaults to CW FISTS frequencies when changing bands
//#define ONEBUTTON 1 // Use single (encoder) button to control full the rig; optionally use L/R buttons to completely replace rotory encoder function
@ -90,6 +91,15 @@
#undef MOX_ENABLE
#endif //!TX_ENABLE
#ifdef SWR_METER
float FWD;
float SWR;
float ref_V = 5 * 1.15;
static uint32_t stimer;
#define vin_FWD A6
#define vin_REF A7
#endif
/*
// UCX installation: On blank chip, use (standard Arduino Uno) fuse settings (E:FD, H:DE, L:FF), and use customized Optiboot bootloader for 20MHz clock, then upload via serial interface (with RX, TX and DTR lines connected to pin 1, 2, 3 respectively)
// UCX pin defintions
@ -1940,6 +1950,9 @@ void dsp_tx_fm()
#define MLEA(y, x, L, M) (y) = (y) + ((((x) - (y)) >> (L)) - (((x) - (y)) >> (M))); // multiplierless exponental averaging [Lyons 13.33.1], with alpha=1/2^L - 1/2^M
volatile uint8_t cwdec = 1;
#ifdef SWR_METER
volatile uint8_t swrmeter = 1;
#endif
static int32_t avg = 256;
static uint8_t sym;
const char m2c[] PROGMEM = "~ ETIANMSURWDKGOHVF*L*PJBXCYZQ**54S3***2**+***J16=/***H*7*G*8*90************?_****\"**.****@***'**-********;!*)*****,****:****";
@ -3483,6 +3496,9 @@ void switch_rxtx(uint8_t tx_enable){
#ifdef RIT_ENABLE
si5351.freq_calc_fast(rit); si5351.SendPLLRegisterBulk(); // restore original PLL RX frequency
#endif //RIT_ENABLE
#ifdef SWR_METER
if(swrmeter > 0) { show_banner(); lcd.print(" "); }
#endif
lcd.setCursor(15, 1); lcd.print((vox) ? 'V' : 'R');
#ifdef _SERIAL
if(!vox) if(cat_active){ DDRC |= (1<<2); } // enable PC2, so that ADC2 is pulled-down so that CAT TX is not disrupted via mic input
@ -3773,6 +3789,9 @@ const char* smode_label[] = { "OFF", "dBm", "S", "S-bar", "wpm", "Vss" };
#else
const char* smode_label[] = { "OFF", "dBm", "S", "S-bar", "wpm" };
#endif
#ifdef SWR_METER
const char* swr_label[] = { "OFF", "FWD-SWR", "FWD-REF", "VFWD-VREF" };
#endif
const char* cw_tone_label[] = { "700", "600" };
#ifdef KEYER
const char* keyer_mode_label[] = { "Iambic A", "Iambic B","Straight" };
@ -3780,11 +3799,11 @@ const char* keyer_mode_label[] = { "Iambic A", "Iambic B","Straight" };
#define _N(a) sizeof(a)/sizeof(a[0])
#define N_PARAMS 36 // number of (visible) parameters
#define N_PARAMS 37 // number of (visible) parameters
#define N_ALL_PARAMS (N_PARAMS+5) // number of parameters
enum params_t {_NULL, VOLUME, MODE, FILTER, BAND, STEP, VFOSEL, RIT, AGC, NR, ATT, ATT2, SMETER, CWDEC, CWTONE, CWOFF, SEMIQSK, KEY_WPM, KEY_MODE, KEY_PIN, KEY_TX, VOX, VOXGAIN, DRIVE, TXDELAY, MOX, PWM_MIN, PWM_MAX, SIFXTAL, IQ_ADJ, CALIB, SR, CPULOAD, PARAM_A, PARAM_B, PARAM_C, BACKL, FREQA, FREQB, MODEA, MODEB, VERS, ALL=0xff};
enum params_t {_NULL, VOLUME, MODE, FILTER, BAND, STEP, VFOSEL, RIT, AGC, NR, ATT, ATT2, SMETER, SWRMETER, CWDEC, CWTONE, CWOFF, SEMIQSK, KEY_WPM, KEY_MODE, KEY_PIN, KEY_TX, VOX, VOXGAIN, MOX, DRIVE, TXDELAY, SIFXTAL, PWM_MIN, PWM_MAX, IQ_ADJ, CALIB, SR, CPULOAD, PARAM_A, PARAM_B, PARAM_C, BACKL, FREQA, FREQB, MODEA, MODEB, VERS, ALL=0xff};
int8_t paramAction(uint8_t action, uint8_t id = ALL) // list of parameters
{
@ -3809,8 +3828,11 @@ int8_t paramAction(uint8_t action, uint8_t id = ALL) // list of parameters
case ATT: paramAction(action, att, 0x1A, F("ATT"), att_label, 0, 7, false); break;
case ATT2: paramAction(action, att2, 0x1B, F("ATT2"), NULL, 0, 16, false); break;
case SMETER: paramAction(action, smode, 0x1C, F("S-meter"), smode_label, 0, _N(smode_label) - 1, false); break;
case CWDEC: paramAction(action, cwdec, 0x21, F("CW Decoder"), offon_label, 0, 1, false); break;
#ifdef SWR_METER
case SWRMETER: paramAction(action, swrmeter, 0x1D, F("SWR Meter"), swr_label, 0, _N(swr_label) - 1, false); break;
#endif
#ifdef FILTER_700HZ
case CWDEC: paramAction(action, cwdec, 0x21, F("CW Decoder"), offon_label, 0, 1, false); break;
case CWTONE: if(dsp_cap) paramAction(action, cw_tone, 0x22, F("CW Tone"), cw_tone_label, 0, 1, false); break;
#endif
#ifdef QCX
@ -3899,6 +3921,10 @@ void initPins(){
digitalWrite(PTX, LOW);
pinMode(PTX, OUTPUT);
#endif //PTX
#ifdef SWR_METER
pinMode(vin_FWD, INPUT);
pinMode(vin_REF, INPUT);
#endif
#ifdef OLED // assign unused LCD pins
pinMode(PD4, OUTPUT);
pinMode(PD5, OUTPUT);
@ -4256,6 +4282,48 @@ void build_lut()
//lut[i] = min(pwm_max, (float)106*log(i) + pwm_min); // compressed microphone output: drive=0, pwm_min=115, pwm_max=220
}
#ifdef SWR_METER
void readSWR()
// reads FWD / REF values from A6 and A7 and computes SWR
// credit Duwayne, KV4QB
{
float v_FWD = 0;
float v_REF = 0;
for (int i = 0; i <= 7; i++) {
v_FWD = v_FWD + (ref_V / 1023) * (int) analogRead(vin_FWD);
v_REF = v_REF + (ref_V / 1023) * (int) analogRead(vin_REF);
delay(5);
}
v_FWD = v_FWD / 8;
v_REF = v_REF / 8;
float p_FWD = sq(v_FWD);
float p_REV = sq(v_REF);
float vRatio = v_REF / v_FWD;
float VSWR = (1 + vRatio) / (1 - vRatio);
if ((VSWR > 9.99) || (VSWR < 1) )VSWR = 9.99;
if (p_FWD != FWD || VSWR != SWR) {
lcd.noCursor();
lcd.setCursor(0,0);
switch(swrmeter) {
case 1:
lcd.print(" "); lcd.print(floor(100*p_FWD)/100); lcd.print("W SWR:"); lcd.print(floor(100*VSWR)/100);
break;
case 2:
lcd.print(" F:"); lcd.print(floor(100*p_FWD)/100); lcd.print("W R:"); lcd.print(floor(100*p_REV)/100); lcd.print("W");
break;
case 3:
lcd.print(" F:"); lcd.print(floor(100*v_FWD)/100); lcd.print("V R:"); lcd.print(floor(100*v_REF)/100); lcd.print("V");
break;
}
FWD = p_FWD;
SWR = VSWR;
}
}
#endif
void setup()
{
digitalWrite(KEY_OUT, LOW); // for safety: to prevent exploding PA MOSFETs, in case there was something still biasing them.
@ -4705,6 +4773,9 @@ void loop()
for(; !_digitalRead(DIT) ;){ // until released
#endif
wdt_reset();
#ifdef SWR_METER
if(smeter > 0 && mode == CW && millis() >= stimer) { readSWR(); stimer = millis() + 500; }
#endif
if(inv ^ _digitalRead(BUTTONS)) break; // break if button is pressed (to prevent potential lock-up)
}
switch_rxtx(0);
@ -5206,43 +5277,4 @@ line 40: #define DIT 11 //GNI swaped PB5 (pin 19) (pin 17 nano D
(because of resistor with LED connected to D13 on Nano module)
remove unnecessary menu options (2.4, 2.5, 2.6, 2.7, 2.8, 3.1, 3.4, 3.5, 8.2, 8.3).
---
https://groups.io/g/ucx/message/6262
#ifdef SWR_METER
if(mode == CW && tx) readSWR();
#endif
#ifdef SWR_METER
void readSWR()
{
float v_FWD = 0;
float v_REV = 0;
for (int i = 0; i <= 7; i++) {
v_FWD = v_FWD + (ref_V / 1023) * analogSafeRead(vin_FWD);
v_REV = v_REV + (ref_V / 1023) * analogSafeRead(vin_REV);
delay(5);
}
v_FWD = v_FWD / 8;
v_REV = v_REV / 8;
float p_FWD = sq(v_FWD);
float p_REV = sq(v_REV);
float vRatio = v_REV / v_FWD;
float VSWR = (1 + vRatio) / (1 - vRatio);
if ((VSWR > 9.99) || (VSWR < 1) )VSWR = 9.99;
//if (1) {
if (p_FWD != FWD || VSWR != SWR) {
lcd.noCursor();
lcd.setCursor(0,0);
lcd.print(floor(100*p_FWD)/100); lcd.print("W SWR:"); lcd.print(floor(100*VSWR)/100);
FWD = p_FWD;
SWR = VSWR;
}
}
#endif
*/