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
56 changes: 45 additions & 11 deletions mchf-eclipse/drivers/ui/menu/ui_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@

#define CLR_OR_SET_BITMASK(cond,value,mask) ((value) = (((cond))? ((value) | (mask)): ((value) & ~(mask))))

// mimics UiDriver_UpdateFreqDisplay() a bit. Space every 3 digits as a separator.
// buffer must be >= MAX_DIGITS + MAX_DIGITS/MAX_DIGITS_SEP_EVERY + 1
#define MAX_DIGITS_SEP_EVERY 3
#define MAX_DIGITS_U64 (MAX_DIGITS + MAX_DIGITS/MAX_DIGITS_SEP_EVERY)
static char *u64_to_dec(uint64_t v, char buf[MAX_DIGITS_U64+1])
{
char *p = buf + MAX_DIGITS_U64; // safe end
*p = 0; // NUL-terminate

uint8_t count = 0;
do {
if (count == MAX_DIGITS_SEP_EVERY) {
*--p = ' ';
count = 0;
}
*--p = '0' + (v % 10);
v /= 10;
count++;
} while (v);

return p; // pointer to first char of the string
}

void float2fixedstr(char* buf, int maxchar, float32_t f, uint16_t digitsBefore, uint16_t digitsAfter)
{
char formatstr[16],numberstr[32];
Expand Down Expand Up @@ -90,6 +113,10 @@ void float2fixedstr(char* buf, int maxchar, float32_t f, uint16_t digitsBefore,
buf[idx] = '\0';
}

#define ONE_MHZ 1000000ULL
static inline unsigned long speedup_step(unsigned long step) {
return step >= ONE_MHZ ? step * 100ULL : step;
}

// LCD
#include "ui_lcd_draw.h" // for colors!
Expand Down Expand Up @@ -762,7 +789,8 @@ void UiMenu_UpdateItem(uint16_t select, MenuProcessingMode_t mode, int pos, int

const char* txt_ptr = NULL;
uint32_t clr = *clr_ptr;
uint8_t nr_step;
uint8_t nr_step;
ulong tstep; // temporary step speedup for transverter

// case statement local variables defined for convenience here
bool var_change = false;
Expand Down Expand Up @@ -2959,18 +2987,19 @@ void UiMenu_UpdateItem(uint16_t select, MenuProcessingMode_t mode, int pos, int
}
break;
case CONFIG_XVTR_FREQUENCY_OFFSET: // Adjust transverter Frequency offset
tstep = speedup_step(df.tuning_step);
if(var >= 1) // setting increase?
{
ts.menu_var_changed = 1; // indicate that a change has occurred
ts.xverter_offset += df.tuning_step;
ts.xverter_offset += tstep;
var_change = 1;
}
else if(var <= -1) // setting decrease?
{
ts.menu_var_changed = 1; // indicate that a change has occurred
if(ts.xverter_offset >= df.tuning_step) // subtract only if we have room to do so
if(ts.xverter_offset >= tstep) // subtract only if we have room to do so
{
ts.xverter_offset -= df.tuning_step;
ts.xverter_offset -= tstep;
}
else
{
Expand Down Expand Up @@ -2999,22 +3028,26 @@ void UiMenu_UpdateItem(uint16_t select, MenuProcessingMode_t mode, int pos, int
clr = Orange; // make number red to alert user of this!
}

uint32_t offset_offset = ts.xverter_offset > XVERTER_OFFSET_MAX_HZ? ((XVERTER_OFFSET_MAX_HZ)-(XVERTER_OFFSET_MAX_HZ)/1000):0;
snprintf(options,32, ts.xverter_offset > XVERTER_OFFSET_MAX_HZ? " %9ukHz" : " %9uHz", (uint)(ts.xverter_offset-offset_offset)); // print with nine digits
{
char tmp[MAX_DIGITS_U64+1];
char *digits = u64_to_dec(ts.xverter_offset, tmp);
snprintf(options, 32, " %15sHz", digits);
}
break;
case CONFIG_XVTR_FREQUENCY_OFFSET_TX: // Adjust transverter tx Frequency offset
tstep = speedup_step(df.tuning_step);
if(var >= 1) // setting increase?
{
ts.menu_var_changed = 1; // indicate that a change has occurred
ts.xverter_offset_tx += df.tuning_step;
ts.xverter_offset_tx += tstep;
var_change = 1;
}
else if(var <= -1) // setting decrease?
{
ts.menu_var_changed = 1; // indicate that a change has occurred
if(ts.xverter_offset_tx >= df.tuning_step) // subtract only if we have room to do so
if(ts.xverter_offset_tx >= tstep) // subtract only if we have room to do so
{
ts.xverter_offset_tx -= df.tuning_step;
ts.xverter_offset_tx -= tstep;
}
else
{
Expand Down Expand Up @@ -3045,8 +3078,9 @@ void UiMenu_UpdateItem(uint16_t select, MenuProcessingMode_t mode, int pos, int

if (ts.xverter_offset_tx != 0)
{
uint32_t offset_offset = ts.xverter_offset_tx > XVERTER_OFFSET_MAX_HZ? ((XVERTER_OFFSET_MAX_HZ)-(XVERTER_OFFSET_MAX_HZ)/1000):0;
snprintf(options,32, ts.xverter_offset_tx > XVERTER_OFFSET_MAX_HZ? " %9ukHz" : " %9uHz", (uint)(ts.xverter_offset_tx-offset_offset)); // print with nine digits
char tmp[MAX_DIGITS_U64+1];
char *digits = u64_to_dec(ts.xverter_offset_tx, tmp);
snprintf(options, 32, " %15sHz", digits);
}
else
{
Expand Down
5 changes: 1 addition & 4 deletions mchf-eclipse/drivers/ui/radio_management.c
Original file line number Diff line number Diff line change
Expand Up @@ -1952,10 +1952,7 @@ uint64_t RadioManagement_Transverter_GetFreq(const uint32_t dial_freq, const uin
{
uint32_t xverter_offset = (ts.xverter_offset_tx != 0 && trx_mode == TRX_MODE_TX) ? ts.xverter_offset_tx : ts.xverter_offset;

uint64_t offset_multiplier = xverter_offset>XVERTER_OFFSET_MAX_HZ? 1000 : 1;
uint64_t offset_offset = xverter_offset - (xverter_offset>XVERTER_OFFSET_MAX_HZ ? ((XVERTER_OFFSET_MAX_HZ)-XVERTER_OFFSET_MAX_HZ/1000) : 0);

return dial_freq * ts.xverter_mode + offset_offset * offset_multiplier;
return dial_freq * ts.xverter_mode + xverter_offset;
}

static void RadioManagement_InitBandSet()
Expand Down
96 changes: 92 additions & 4 deletions mchf-eclipse/drivers/ui/ui_configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,65 @@ static void UiReadSettingEEPROM_UInt32(uint16_t addrH, uint16_t addrL, volatile
}
}

// Reads a 48-bit value split across three 16-bit EEPROM words:
// - low32 is kept for backward compatibility: addr32_H (bits 31..16), addr32_L (bits 15..0)
// - ext16 is the new optional upper 16 bits: addrExt16 (bits 47..32)
// The assembled value is returned as uint64_t (with upper 16 bits zeroed).
//
// Behavior:
// - If low32 cannot be read, assigns default_val (like the 32-bit helper).
// - If ext16 is missing, it is treated as 0 (older EEPROMs).
// - Applies min/max clamp semantics via default on out-of-range or when load_default is true.
static void UiReadSettingEEPROM_UInt48(uint16_t addrExt16,
uint16_t addr32_H,
uint16_t addr32_L,
volatile uint64_t* val_ptr,
uint64_t default_val, uint64_t min_val, uint64_t max_val,
bool load_default)
{
uint16_t lH, lL;
uint16_t ext16_word;
uint32_t low32 = 0;
uint32_t hi16 = 0;

// Read legacy low 32 bits first; if that fails, fall back to default (like the 32-bit helper).
if (ConfigStorage_ReadVariable(addr32_H, &lH) == 0 &&
ConfigStorage_ReadVariable(addr32_L, &lL) == 0)
{
low32 = ((uint32_t)lH << 16) | (uint32_t)lL;

// Try to read the optional upper 16 bits (bits 47..32). If missing, default to 0.
if (ConfigStorage_ReadVariable(addrExt16, &ext16_word) == 0)
{
hi16 = (uint32_t)ext16_word;
}
else
{
hi16 = 0u; // old EEPROMs: no extended word => hi16 = 0
}

// Assemble 48-bit value into 64-bit container (upper 16 bits are zero).
uint64_t value = (((uint64_t)hi16) << 32) | (uint64_t)low32;

// (Optional) Mask to 48 bits to be extra safe against stray bits.
value &= 0x0000FFFFFFFFFFFFULL;

// Range/default handling.
if (load_default || value < min_val || value > max_val)
{
*val_ptr = default_val;
}
else
{
*val_ptr = value;
}
}
else
{
*val_ptr = default_val;
}
}

static uint16_t UiWriteSettingEEPROM_UInt16(uint16_t addr, uint16_t set_val)
{
return ConfigStorage_WriteVariable(addr, set_val);
Expand Down Expand Up @@ -504,6 +563,29 @@ static uint16_t UiWriteSettingEEPROM_UInt32(uint16_t addrH, uint16_t addrL, uint
return retval;
}

// Writes a 48-bit value split across three 16-bit EEPROM words:
// - low32 -> legacy locations: addr32_H (bits 31..16), addr32_L (bits 15..0)
// - hi16 -> new extension location: addrExt16 (bits 47..32)
// The value is passed as a uint64_t but masked to 48 bits before storage.
static uint16_t UiWriteSettingEEPROM_UInt48(uint16_t addrExt16, // single 16-bit word for bits 47..32
uint16_t addr32_H,
uint16_t addr32_L,
uint64_t set_val)
{
// Mask to 48 bits to avoid stray upper bits
uint64_t v48 = set_val & 0x0000FFFFFFFFFFFFULL;
uint32_t low32 = (uint32_t)(v48 & 0xFFFFFFFFULL);
uint16_t hi16 = (uint16_t)(v48 >> 32);

// 1) Write legacy low 32 bits (backward compatible).
uint16_t retval = UiWriteSettingEEPROM_UInt32(addr32_H, addr32_L, low32);
if (retval != HAL_OK)
return retval;

// 2) Write the upper 16 bits (always present in EEPROM).
return ConfigStorage_WriteVariable(addrExt16, hi16);
}

static uint32_t UiConfiguration_LimitFrequency(BandInfo_c* bandInfo, const uint32_t freq, bool set_to_default)
{
uint32_t retval = freq;
Expand Down Expand Up @@ -928,8 +1010,10 @@ void UiConfiguration_LoadEepromValues(bool load_freq_mode_defaults, bool load_ee
}


UiReadSettingEEPROM_UInt32( EEPROM_XVERTER_OFFSET_HIGH,EEPROM_XVERTER_OFFSET_LOW,&ts.xverter_offset,0,0,XVERTER_OFFSET_MAX, load_eeprom_defaults);
UiReadSettingEEPROM_UInt32( EEPROM_XVERTER_OFFSET_TX_HIGH,EEPROM_XVERTER_OFFSET_TX_LOW,&ts.xverter_offset_tx,0,0,XVERTER_OFFSET_MAX, load_eeprom_defaults);
UiReadSettingEEPROM_UInt48(EEPROM_XVERTER_OFFSET_EXT_LOW, EEPROM_XVERTER_OFFSET_HIGH, EEPROM_XVERTER_OFFSET_LOW,
&ts.xverter_offset, 0ULL, 0ULL, XVERTER_OFFSET_MAX, load_eeprom_defaults);
UiReadSettingEEPROM_UInt48(EEPROM_XVERTER_OFFSET_TX_EXT_LOW, EEPROM_XVERTER_OFFSET_TX_HIGH, EEPROM_XVERTER_OFFSET_TX_LOW,
&ts.xverter_offset_tx, 0ULL, 0ULL, XVERTER_OFFSET_MAX, load_eeprom_defaults);

UiReadSettingEEPROM_Filter(load_eeprom_defaults);

Expand Down Expand Up @@ -1023,11 +1107,15 @@ uint16_t UiConfiguration_SaveEepromValues(void)

if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(EEPROM_XVERTER_OFFSET_HIGH,EEPROM_XVERTER_OFFSET_LOW,ts.xverter_offset);
retval = UiWriteSettingEEPROM_UInt48(EEPROM_XVERTER_OFFSET_EXT_LOW, // hi32 (new)
EEPROM_XVERTER_OFFSET_HIGH, EEPROM_XVERTER_OFFSET_LOW, // low32 (legacy)
ts.xverter_offset);
}
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(EEPROM_XVERTER_OFFSET_TX_HIGH,EEPROM_XVERTER_OFFSET_TX_LOW,ts.xverter_offset_tx);
retval = UiWriteSettingEEPROM_UInt48(EEPROM_XVERTER_OFFSET_TX_EXT_LOW,// hi32 (new)
EEPROM_XVERTER_OFFSET_TX_HIGH, EEPROM_XVERTER_OFFSET_TX_LOW, // low32 (legacy)
ts.xverter_offset_tx);
}

if (retval == HAL_OK)
Expand Down
7 changes: 4 additions & 3 deletions mchf-eclipse/drivers/ui/ui_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ uint16_t UiConfiguration_SaveEepromValues(void);
//

#define XVERTER_MULT_MAX 10 // maximum LO multipler in xverter mode
#define XVERTER_OFFSET_MAX_HZ 999999000 // transverter offset is in Hz (999,999,999 Hz), above khz
#define XVERTER_OFFSET_MAX 1019999999 // Maximum transverter offset (19,999,999,999 kHz ~ 20 Ghz)
#define XVERTER_OFFSET_MAX 99999999999ULL // Maximum transverter offset in Hz (99 GHz)
//
#define AUTO_LSB_USB_OFF 0
#define AUTO_LSB_USB_ON 1
Expand Down Expand Up @@ -613,7 +612,9 @@ uint16_t UiConfiguration_SaveEepromValues(void);
#define EEPROM_CW_DECODER_FLAGS 430 // Various flags controlling operation of CW decoder
#define EEPROM_BAND_REGION 431 // store which region the TRX is being used in
#define EEPROM_SParkleFLAGS 432 // some flags holding SParkle specyfic setup
#define EEPROM_FIRST_UNUSED 433 // change this if new value ids are introduced, must be correct at any time
#define EEPROM_XVERTER_OFFSET_EXT_LOW 433 // lower 16 bits of upper 32 half of xverter 48bit frequency (48bit value in three 16bit eeprom entries)
#define EEPROM_XVERTER_OFFSET_TX_EXT_LOW 434 // lower 16 bits of upper 32 half of xverter 48bit tx frequency (48bit value in three 16bit eeprom entries)
#define EEPROM_FIRST_UNUSED 435 // change this if new value ids are introduced, must be correct at any time

#define MAX_VAR_ADDR (EEPROM_FIRST_UNUSED - 1)

Expand Down
4 changes: 2 additions & 2 deletions mchf-eclipse/hardware/uhsdr_board.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,8 @@ typedef struct TransceiverState
struct mchf_waterfall waterfall;

uint32_t xverter_mode; // TRUE if transverter mode active
uint32_t xverter_offset; // frequency offset for transverter (added to frequency display)
uint32_t xverter_offset_tx; // used for tx if set, frequency offset for transverter (added to frequency display)
uint64_t xverter_offset; // frequency offset for transverter (added to frequency display)
uint64_t xverter_offset_tx; // used for tx if set, frequency offset for transverter (added to frequency display)
//
// Calibration factors for output power, in percent (100 = 1.00)
//
Expand Down