412 lines
13 KiB
C
412 lines
13 KiB
C
|
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
|
||
|
/************************************************************************************
|
||
|
** **
|
||
|
** UHSDR **
|
||
|
** a powerful firmware for STM32 based SDR transceivers **
|
||
|
** **
|
||
|
**---------------------------------------------------------------------------------**
|
||
|
** **
|
||
|
** File name: **
|
||
|
** Description: **
|
||
|
** Last Modified: **
|
||
|
** Licence: GNU GPLv3 **
|
||
|
************************************************************************************/
|
||
|
/*
|
||
|
* radio_management.h
|
||
|
*
|
||
|
* Created on: 23.12.2016
|
||
|
* Author: danilo
|
||
|
*/
|
||
|
|
||
|
#ifndef DRIVERS_UI_RADIO_MANAGEMENT_H_
|
||
|
#define DRIVERS_UI_RADIO_MANAGEMENT_H_
|
||
|
|
||
|
#include "uhsdr_types.h"
|
||
|
#include "uhsdr_board.h"
|
||
|
// Frequency public structure
|
||
|
|
||
|
#define MAX_DIGITS 11
|
||
|
|
||
|
typedef struct DialFrequency
|
||
|
{
|
||
|
// pot values
|
||
|
//
|
||
|
// user visible frequency AKA dial frequency
|
||
|
// NOT the always LO frequency since we have an IQ TRX which
|
||
|
// uses frequency translation in many cases.
|
||
|
ulong tune_old; // current value
|
||
|
ulong tune_new; // requested value
|
||
|
|
||
|
// Current tuning step
|
||
|
ulong tuning_step; // selected step by user
|
||
|
ulong selected_idx; // id of step
|
||
|
ulong step_new; // Eth driver req step
|
||
|
|
||
|
ulong update_skip;
|
||
|
|
||
|
// TCXO routine factor/flag
|
||
|
int temp_factor;
|
||
|
bool temp_factor_changed;
|
||
|
uchar temp_enabled;
|
||
|
#define TCXO_MODE_MASK 0x0f
|
||
|
#define TCXO_UNIT_MASK 0x10
|
||
|
#define TCXO_UNIT_C 0x00
|
||
|
#define TCXO_UNIT_F 0x10
|
||
|
|
||
|
} DialFrequency;
|
||
|
|
||
|
// ------------------------------------------------
|
||
|
// Frequency public
|
||
|
extern DialFrequency df;
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
TCXO_OFF = 0, // TXCO temperature compensation off,
|
||
|
TCXO_ON = 1, // TCXO temperature compensation on
|
||
|
TCXO_STOP = 2, // TXCO temperature compensation off, but read temperature sensor
|
||
|
TCXO_STATE_NUMBER // Maximum setting for TCXO setting state
|
||
|
} Tcxo_Mode_t;
|
||
|
|
||
|
|
||
|
inline Tcxo_Mode_t RadioManagement_TcxoGetMode(void)
|
||
|
{
|
||
|
return (df.temp_enabled & TCXO_MODE_MASK);
|
||
|
}
|
||
|
inline void RadioManagement_TcxoSetMode(Tcxo_Mode_t mode)
|
||
|
{
|
||
|
df.temp_enabled = (df.temp_enabled & ~TCXO_MODE_MASK) | (mode & TCXO_MODE_MASK) ;
|
||
|
}
|
||
|
|
||
|
inline bool RadioManagement_TcxoIsEnabled(void)
|
||
|
{
|
||
|
return (RadioManagement_TcxoGetMode())!= TCXO_OFF;
|
||
|
}
|
||
|
|
||
|
inline void RadioManagement_TcxoSetUnit(uint8_t unit)
|
||
|
{
|
||
|
df.temp_enabled = (df.temp_enabled & ~TCXO_UNIT_MASK) | (unit & TCXO_UNIT_MASK);
|
||
|
}
|
||
|
|
||
|
inline bool RadioManagement_TcxoIsFahrenheit(void)
|
||
|
{
|
||
|
return (df.temp_enabled & TCXO_UNIT_MASK) == TCXO_UNIT_F;
|
||
|
}
|
||
|
|
||
|
// PA power level setting enumeration
|
||
|
// this order MUST match the order of entries in power_levels in radio_management.c !
|
||
|
typedef enum
|
||
|
{
|
||
|
PA_LEVEL_FULL = 0,
|
||
|
PA_LEVEL_HIGH,
|
||
|
PA_LEVEL_MEDIUM,
|
||
|
PA_LEVEL_LOW,
|
||
|
PA_LEVEL_MINIMAL,
|
||
|
PA_LEVEL_TUNE_KEEP_CURRENT
|
||
|
} power_level_t;
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
power_level_t id;
|
||
|
int32_t mW;
|
||
|
} power_level_desc_t;
|
||
|
|
||
|
typedef struct {
|
||
|
const power_level_desc_t* levels;
|
||
|
const uint32_t count;
|
||
|
} pa_power_levels_info_t;
|
||
|
|
||
|
extern const pa_power_levels_info_t mchf_power_levelsInfo;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char* name;
|
||
|
float32_t reference_power;
|
||
|
uint32_t max_freq;
|
||
|
uint32_t min_freq;
|
||
|
int32_t max_am_power;
|
||
|
int32_t max_power; // power level upper limit, used for display
|
||
|
} pa_info_t;
|
||
|
|
||
|
extern const pa_info_t mchf_pa;
|
||
|
|
||
|
|
||
|
#define PA_LEVEL_DEFAULT PA_LEVEL_MEDIUM // Default power level
|
||
|
|
||
|
#define DEFAULT_FREQ_OFFSET 3000 // Amount of offset (at LO freq) when loading "default" frequency
|
||
|
|
||
|
// this list MUST fit the order in the bandInfo structure defined in RadioManagement.h
|
||
|
typedef enum
|
||
|
{
|
||
|
BAND_MODE_80 = 0,
|
||
|
BAND_MODE_60 = 1,
|
||
|
BAND_MODE_40 = 2,
|
||
|
BAND_MODE_30 = 3,
|
||
|
BAND_MODE_20 = 4,
|
||
|
BAND_MODE_17 = 5,
|
||
|
BAND_MODE_15 = 6,
|
||
|
BAND_MODE_12 = 7,
|
||
|
BAND_MODE_10 = 8,
|
||
|
BAND_MODE_6 = 9,
|
||
|
BAND_MODE_4 = 10,
|
||
|
BAND_MODE_2 = 11,
|
||
|
BAND_MODE_70 = 12,
|
||
|
BAND_MODE_23 = 13,
|
||
|
BAND_MODE_2200 = 14,
|
||
|
BAND_MODE_630 = 15,
|
||
|
BAND_MODE_160 = 16,
|
||
|
BAND_MODE_GEN = 17 // General Coverage
|
||
|
} band_mode_t;
|
||
|
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
COUPLING_2200M = 0,
|
||
|
COUPLING_630M,
|
||
|
COUPLING_160M,
|
||
|
COUPLING_80M,
|
||
|
COUPLING_40M,
|
||
|
COUPLING_20M,
|
||
|
COUPLING_15M,
|
||
|
COUPLING_10M,
|
||
|
COUPLING_6M,
|
||
|
COUPLING_2M,
|
||
|
COUPLING_70CM,
|
||
|
COUPLING_23CM,
|
||
|
COUPLING_MAX
|
||
|
} filter_band_t;
|
||
|
|
||
|
typedef struct BandInfo
|
||
|
{
|
||
|
uint32_t tune;
|
||
|
uint32_t size;
|
||
|
const char* name;
|
||
|
uint32_t band_mode;
|
||
|
bool rx_only;
|
||
|
} BandInfo;
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param band
|
||
|
* @return true if band is the so called generic band (everything which is not ham tx)
|
||
|
*/
|
||
|
static inline bool RadioManagement_IsGenericBand(const BandInfo* band)
|
||
|
{
|
||
|
return band->size == 0;
|
||
|
}
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
const BandInfo** bands;
|
||
|
const char* name;
|
||
|
} BandInfoSet;
|
||
|
|
||
|
extern const BandInfoSet bandInfos[];
|
||
|
extern const int BAND_INFO_SET_NUM;
|
||
|
#define BAND_INFO_SET_DEFAULT 0 // first entry is default, this is a "catch all region"
|
||
|
extern uint8_t bandinfo_idx;
|
||
|
|
||
|
typedef const BandInfo BandInfo_c;
|
||
|
extern BandInfo_c **bandInfo;
|
||
|
|
||
|
typedef struct band_regs_s
|
||
|
{
|
||
|
VfoReg band[MAX_BAND_NUM];
|
||
|
} BandRegs;
|
||
|
|
||
|
extern bool band_enabled[MAX_BAND_NUM]; // we store which band is to be used (or ignored)
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
// VFO_WORK = 0
|
||
|
VFO_A = 0,
|
||
|
VFO_B,
|
||
|
VFO_MAX
|
||
|
} vfo_name_t;
|
||
|
// Working register plus VFO A and VFO B registers.
|
||
|
extern BandRegs vfo[VFO_MAX];
|
||
|
|
||
|
vfo_name_t get_active_vfo(void);
|
||
|
|
||
|
|
||
|
// SWR and RF power meter public
|
||
|
typedef struct SWRMeter
|
||
|
{
|
||
|
float fwd_calc; // forward power readings in A/D units
|
||
|
float rev_calc; // reverse power readings in A/D units
|
||
|
float fwd_pwr; // forward power in watts current measurement
|
||
|
float rev_pwr; // reverse power in watts current measurement
|
||
|
float fwd_pwr_avg; // forward power in watts averaged
|
||
|
float rev_pwr_avg; // reverse power in watts averaged
|
||
|
|
||
|
float fwd_dbm; // forward power in dBm
|
||
|
float rev_dbm; // reverse power in dBm
|
||
|
float vswr; // vswr
|
||
|
float vswr_dampened; // dampened VSWR reading
|
||
|
bool pwr_meter_disp; // TRUE if numerical FWD/REV power metering (in milliwatts) is to be displayed
|
||
|
bool pwr_meter_was_disp; // TRUE if numerical FWD/REV power metering WAS displayed (used to clear it)
|
||
|
uchar p_curr; // count used to update power meter
|
||
|
uchar sensor_null; // used to null out the sensor offset voltage
|
||
|
|
||
|
uint8_t coupling_calc[COUPLING_MAX];
|
||
|
|
||
|
bool high_vswr_detected;
|
||
|
|
||
|
} SWRMeter;
|
||
|
|
||
|
// New modes need to be added so that configuration compatibility is retained
|
||
|
// it is also necessary to extend the cw_mode_map in radio_management.c to include new modes
|
||
|
enum {
|
||
|
CW_OFFSET_USB_TX = 0, // CW in USB mode, display is TX frequency if received frequency was zero-beated
|
||
|
CW_OFFSET_LSB_TX, // CW in LSB mode, display is TX frequency if received frequency was zero-beated
|
||
|
CW_OFFSET_AUTO_TX, // Same as CW_OFFSET_USB_TX except LSB if frequency is < 10 MHz, USB if >= 10 MHz
|
||
|
CW_OFFSET_USB_RX, // CW in USB mode, display is RX frequency if received signal is matched to sidetone
|
||
|
CW_OFFSET_LSB_RX, // CW in LSB mode, display is RX frequency if received signal is matched to sidetone
|
||
|
CW_OFFSET_AUTO_RX, // Same as CW_OFFSET_USB_RX except LSB if frequency is < 10 MHz, USB if >= 10 MHz
|
||
|
CW_OFFSET_USB_SHIFT, // CW in USB mode, LO shifts, display is RX frequency if signal is matched to sidetone
|
||
|
CW_OFFSET_LSB_SHIFT, // CW in LSB mode, LO shifts, display is RX frequency if signal is matched to sidetone
|
||
|
CW_OFFSET_AUTO_SHIFT, // Same as "CW_OFFSET_USB_SHIFT" except LSB if frequency is <10 MHz, USB of >= 10 MHz
|
||
|
CW_OFFSET_NUM // Number of Modes
|
||
|
};
|
||
|
|
||
|
#define CW_OFFSET_MODE_DEFAULT CW_OFFSET_USB_TX // Default CW offset setting
|
||
|
|
||
|
typedef enum {
|
||
|
CW_SB_USB = 0,
|
||
|
CW_SB_LSB,
|
||
|
CW_SB_AUTO
|
||
|
} cw_sb_t;
|
||
|
|
||
|
typedef enum {
|
||
|
CW_OFFSET_TX = 0,
|
||
|
CW_OFFSET_RX,
|
||
|
CW_OFFSET_SHIFT
|
||
|
} cw_dial_t;
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
DigitalMode_None = 0,
|
||
|
#ifdef USE_FREEDV
|
||
|
DigitalMode_FreeDV,
|
||
|
#endif
|
||
|
DigitalMode_RTTY,
|
||
|
DigitalMode_BPSK,
|
||
|
DigitalMode_Num_Modes
|
||
|
} digital_modes_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
const char* label;
|
||
|
const uint32_t enabled;
|
||
|
} digital_mode_desc_t;
|
||
|
|
||
|
// The following descriptor table has to be in the order of the enum digital_modes_t in radio_management.h
|
||
|
// This table is stored in flash (due to const) and cannot be written to
|
||
|
// for operational data per mode [r/w], use a different table with order of modes
|
||
|
extern const digital_mode_desc_t digimodes[DigitalMode_Num_Modes];
|
||
|
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
cw_dial_t dial_mode;
|
||
|
cw_sb_t sideband_mode;
|
||
|
} cw_mode_map_entry_t;
|
||
|
|
||
|
extern const cw_mode_map_entry_t cw_mode_map[];
|
||
|
|
||
|
// SWR/Power meter
|
||
|
extern SWRMeter swrm;
|
||
|
|
||
|
inline bool RadioManagement_IsTxDisabled(void)
|
||
|
{
|
||
|
return (ts.tx_disable > 0);
|
||
|
}
|
||
|
|
||
|
inline bool RadioManagement_IsTxDisabledBy(uint8_t whom)
|
||
|
{
|
||
|
return ((ts.tx_disable & (whom)) > 0);
|
||
|
}
|
||
|
|
||
|
uint32_t RadioManagement_GetRealFreqTranslationMode(uint32_t txrx_mode, uint32_t dmod_mode, uint32_t iq_freq_mode);
|
||
|
const BandInfo* RadioManagement_GetBand(ulong freq);
|
||
|
bool RadioManagement_FreqIsInBand(BandInfo_c * bandinfo, const uint32_t freq);
|
||
|
bool RadioManagement_FreqIsInEnabledBand ( uint32_t freq );
|
||
|
const BandInfo* RadioManagement_GetBandInfo(uint8_t new_band_index);
|
||
|
bool RadioManagement_SetPowerLevel(const BandInfo* band, power_level_t power_level);
|
||
|
bool RadioManagement_Tune(bool tune);
|
||
|
bool RadioManagement_UpdatePowerAndVSWR(void);
|
||
|
void RadioManagement_ChangeCodec(uint32_t codec, bool enableCodec);
|
||
|
bool RadioManagement_ChangeFrequency(bool force_update, uint32_t dial_freq,uint8_t txrx_mode);
|
||
|
void RadioManagement_HandlePttOnOff(void);
|
||
|
void RadioManagement_MuteTemporarilyRxAudio(void);
|
||
|
|
||
|
uint32_t RadioManagement_NextNormalDemodMode(uint32_t loc_mode);
|
||
|
uint32_t RadioManagement_NextAlternativeDemodMode(uint32_t loc_mode);
|
||
|
|
||
|
Oscillator_ResultCodes_t RadioManagement_ValidateFrequencyForTX(uint32_t dial_freq);
|
||
|
bool RadioManagement_IsApplicableDemodMode(uint32_t demod_mode);
|
||
|
void RadioManagement_SwitchTxRx(uint8_t txrx_mode, bool tune_mode);
|
||
|
bool RadioManagement_LSBActive(uint16_t dmod_mode);
|
||
|
bool RadioManagement_USBActive(uint16_t dmod_mode);
|
||
|
void RadioManagement_SetPaBias(void);
|
||
|
bool RadioManagement_CalculateCWSidebandMode(void);
|
||
|
void RadioManagement_SetDemodMode(uint8_t new_mode);
|
||
|
void RadioManagement_HandleRxIQSignalCodecGain(void);
|
||
|
const cw_mode_map_entry_t* RadioManagement_CWConfigValueToModeEntry(uint8_t cw_offset_mode);
|
||
|
uint8_t RadioManagement_CWModeEntryToConfigValue(const cw_mode_map_entry_t* mode_entry);
|
||
|
bool RadioManagement_UsesBothSidebands(uint16_t dmod_mode);
|
||
|
bool RadioManagement_IsPowerFactorReduce(uint32_t freq);
|
||
|
bool RadioManagement_UsesTxSidetone(void);
|
||
|
void RadioManagement_ToggleVfoAB(void);
|
||
|
|
||
|
bool RadioManagement_FmDevIs5khz(void);
|
||
|
void RadioManagement_FmDevSet5khz(bool is5khz);
|
||
|
|
||
|
uint32_t RadioManagement_GetTXDialFrequency(void);
|
||
|
uint32_t RadioManagement_GetRXDialFrequency(void);
|
||
|
int32_t RadioManagement_GetCWDialOffset(void);
|
||
|
|
||
|
bool RadioManagement_Transverter_IsEnabled(void);
|
||
|
uint64_t RadioManagement_Transverter_GetFreq(const uint32_t dial_freq, const uint8_t trx_mode);
|
||
|
|
||
|
void RadioManagement_Request_TxOn(void);
|
||
|
void RadioManagement_Request_TxOff(void);
|
||
|
|
||
|
bool RadioManagement_SwitchTxRx_Possible(void);
|
||
|
bool RadioManagement_IsTxAtZeroIF(uint8_t dmod_mode, uint8_t digital_mode);
|
||
|
bool RadioManagement_CBFullPwrEnabled(void);
|
||
|
#ifdef SDR_AMBER
|
||
|
void RadioManagement_Set_PA_Bandcode(uint32_t freq);
|
||
|
#endif
|
||
|
|
||
|
inline void RadioManagement_ToggleVfoMem(void)
|
||
|
{
|
||
|
ts.vfo_mem_flag = ! ts.vfo_mem_flag;
|
||
|
}
|
||
|
|
||
|
inline bool is_demod_rtty(void)
|
||
|
{
|
||
|
return ts.dmod_mode == DEMOD_DIGI && ts.digital_mode == DigitalMode_RTTY;
|
||
|
}
|
||
|
|
||
|
inline bool is_demod_psk(void)
|
||
|
{
|
||
|
return ts.dmod_mode == DEMOD_DIGI && ts.digital_mode == DigitalMode_BPSK;
|
||
|
}
|
||
|
|
||
|
inline void RadioManagement_TxRxSwitching_Disable(void)
|
||
|
{
|
||
|
ts.txrx_switching_enabled = false;
|
||
|
}
|
||
|
|
||
|
inline void RadioManagement_TxRxSwitching_Enable(void)
|
||
|
{
|
||
|
ts.txrx_switching_enabled = true;
|
||
|
}
|
||
|
|
||
|
inline bool RadioManagement_TxRxSwitching_IsEnabled(void)
|
||
|
{
|
||
|
return ts.txrx_switching_enabled;
|
||
|
}
|
||
|
|
||
|
#endif /* DRIVERS_UI_RADIO_MANAGEMENT_H_ */
|