first commit

This commit is contained in:
2022-11-08 16:13:55 +01:00
commit f838fa66c4
2500 changed files with 2237507 additions and 0 deletions
@@ -0,0 +1,291 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
// Common
#include "uhsdr_board.h"
#include "ui_driver.h"
#include "stdlib.h"
#include "ui_rotary.h"
#include "tim.h"
// ------------------------------------------------
// Encoder 1-4 Array
__IO EncoderSelection encSel[4];
typedef struct
{
GPIO_TypeDef* pio;
uint16_t pin;
uint8_t af;
} pin_t;
typedef struct {
TIM_TypeDef* tim;
TIM_HandleTypeDef * htim;
pin_t pin[2];
} encoder_io_t;
const encoder_io_t encoderIO[4] =
{
{
.tim = TIM3,
.htim = &htim3,
.pin =
{
{ ENC_ONE_CH1_PIO, ENC_ONE_CH1, GPIO_AF2_TIM3 } ,
{ ENC_ONE_CH2_PIO, ENC_ONE_CH2, GPIO_AF2_TIM3 }
}
},
{
.tim = TIM4,
.htim = &htim4,
.pin =
{
{ ENC_TWO_CH1_PIO, ENC_TWO_CH1, GPIO_AF2_TIM4 } ,
{ ENC_TWO_CH2_PIO, ENC_TWO_CH2, GPIO_AF2_TIM4 }
}
},
{
.tim = TIM5,
.htim = &htim5,
.pin =
{
{ ENC_THREE_CH1_PIO, ENC_THREE_CH1, GPIO_AF2_TIM5 } ,
{ ENC_THREE_CH2_PIO, ENC_THREE_CH2, GPIO_AF2_TIM5 }
}
},
{
.tim = TIM8,
.htim = &htim8,
.pin =
{
{ FREQ_ENC_CH1_PIO, FREQ_ENC_CH1, GPIO_AF3_TIM8 } ,
{ FREQ_ENC_CH2_PIO, FREQ_ENC_CH2, GPIO_AF3_TIM8 }
}
}
};
void UiRotaryEncoderInit(uint8_t id)
{
const encoder_io_t* encIO = &encoderIO[id];
// Init encoder one
encSel[id].value_old = 0;
encSel[id].value_new = ENCODER_RANGE;
encSel[id].de_detent = 0;
encSel[id].tim = encIO->tim;
HAL_TIM_Encoder_Start(encIO->htim, TIM_CHANNEL_1 | TIM_CHANNEL_2);
#if 0
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
GPIO_InitStructure.Pull = GPIO_PULLUP;
for (uint32_t pinIdx = 0; pinIdx < 2; pinIdx++)
{
GPIO_InitStructure.Alternate = encIO->pin[pinIdx].af;
GPIO_InitStructure.Pin = encIO->pin[pinIdx].pin;
GPIO_Init(encIO->pin[pinIdx].pio, &GPIO_InitStructure);
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = (ENCODER_RANGE/ENCODER_LOG_D) + (ENCODER_FLICKR_BAND*2); // range + 3 + 3
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_EncoderInterfaceConfig(encIO->tim,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling,TIM_ICPolarity_Falling);
TIM_TimeBaseInit(encIO->tim, &TIM_TimeBaseStructure);
TIM_Cmd(encIO->tim, ENABLE);
#endif
}
//*----------------------------------------------------------------------------
//* Function Name : UiRotaryFreqEncoderInit
//* Object :
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
void UiRotaryFreqEncoderInit(void)
{
///RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
UiRotaryEncoderInit(ENCFREQ);
}
//*----------------------------------------------------------------------------
//* Function Name : UiRotaryEncoderOneInit
//* Object : audio gain
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
void UiRotaryEncoderOneInit(void)
{
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
UiRotaryEncoderInit(ENC1);
}
//*----------------------------------------------------------------------------
//* Function Name : UiRotaryEncoderTwoInit
//* Object : rfgain
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
void UiRotaryEncoderTwoInit(void)
{
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
UiRotaryEncoderInit(ENC2);
}
//*----------------------------------------------------------------------------
//* Function Name : UiRotaryEncoderThreeInit
//* Object :
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
void UiRotaryEncoderThreeInit(void)
{
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
UiRotaryEncoderInit(ENC3);
}
int UiDriverEncoderRead(const uint32_t encId)
{
bool no_change = false;
int pot_diff = 0;
int32_t delta;
if (encId < ENC_MAX)
{
encSel[encId].value_new = encSel[encId].tim->CNT;
if (encSel[encId].value_old != encSel[encId].value_new)
{
//checking for the overflow/underflow crossing
delta=encSel[encId].value_new - encSel[encId].value_old;
if(delta>(ENCODER_RANGE/2))
{
delta-=ENCODER_RANGE+1;
}
else if(delta<-(ENCODER_RANGE/2))
{
delta+=ENCODER_RANGE+1;
}
}
else
{
no_change = true;
}
// SW de-detent routine
//left this code but think that it is useless because in our encoders (detent count)=(steps per rotation). 03.06.2018 SP9BSL
if (no_change == false)
{
encSel[encId].de_detent+=abs(delta);// corrected detent behaviour
// double counts are now processed - not count lost!
if (encSel[encId].de_detent < USE_DETENTED_VALUE)
{
encSel[encId].value_old = encSel[encId].value_new; // update and skip
no_change = true;
}
else
{
encSel[encId].de_detent = 0;
}
}
// Encoder value to difference
if (no_change == false)
{
pot_diff = delta;
encSel[encId].value_old = encSel[encId].value_new;
}
}
// encoders reverse
// if(((ts.expflags1 & EXPFLAGS1_ENC123_REVERSE) && (encId < 3)) || ((ts.expflags1 & EXPFLAGS1_ENC4_REVERSE) && (encId == 3)))
if(((ts.expflags1 & EXPFLAGS1_ENC1_REVERSE) && (encId == 0)) ||
((ts.expflags2 & EXPFLAGS2_ENC2_REVERSE) && (encId == 1)) ||
((ts.expflags2 & EXPFLAGS2_ENC3_REVERSE) && (encId == 2)) ||
((ts.expflags1 & EXPFLAGS1_ENC4_REVERSE) && (encId == 3)))
{
pot_diff = -pot_diff;
}
return pot_diff;
}
//left for some time only for reference.
/*
int UiDriverEncoderRead(const uint32_t encId)
{
bool no_change = false;
int pot_diff = 0;
if (encId < ENC_MAX)
{
encSel[encId].value_new = encSel[encId].tim->CNT;
// Ignore lower value flickr
if (encSel[encId].value_new < ENCODER_FLICKR_BAND)
{
no_change = true;
}
else if (encSel[encId].value_new >
(ENCODER_RANGE / ENCODER_LOG_D) + ENCODER_FLICKR_BAND)
{
no_change = true;
}
else if (encSel[encId].value_old == encSel[encId].value_new)
{
no_change = true;
}
// SW de-detent routine
if (no_change == false)
{
encSel[encId].de_detent+=abs(encSel[encId].value_new - encSel[encId].value_old);// corrected detent behaviour
// double counts are now processed - not count lost!
if (encSel[encId].de_detent < USE_DETENTED_VALUE)
{
encSel[encId].value_old = encSel[encId].value_new; // update and skip
no_change = true;
}
else
{
encSel[encId].de_detent = 0;
}
}
// Encoder value to difference
if (no_change == false)
{
pot_diff = encSel[encId].value_new - encSel[encId].value_old;
encSel[encId].value_old = encSel[encId].value_new;
}
}
return pot_diff;
}
*/
@@ -0,0 +1,74 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#ifndef __UI_ROTARY_H
#define __UI_ROTARY_H
// Some encoders have detend and generate x
// ammount of pulses per click
#define USE_DETENTED_ENCODERS
#define USE_DETENTED_VALUE 4
// Protective band on top and bottom scale
// dependent on encoder quality and debounce
// capacitors
#define ENCODER_FLICKR_BAND 4
// Divider to create non linearity
#define ENCODER_LOG_D 1
// Audio Gain public structure
typedef struct EncoderSelection
{
// pot values
//
uint16_t value_old; // previous value
uint16_t value_new; // most current value
uint8_t de_detent; // sw de-detent flag
TIM_TypeDef* tim;
} EncoderSelection;
//left only for reference:
/*
typedef struct EncoderSelection
{
// pot values
//
ulong value_old; // previous value
ulong value_new; // most current value
uchar de_detent; // sw de-detent flag
TIM_TypeDef* tim;
} EncoderSelection;
*/
void UiRotaryFreqEncoderInit(void);
void UiRotaryEncoderOneInit(void);
void UiRotaryEncoderTwoInit(void);
void UiRotaryEncoderThreeInit(void);
enum EncoderId
{
ENC1 = 0,
ENC2,
ENC3,
ENCFREQ,
ENC_MAX // this needs to be the last entry
};
int UiDriverEncoderRead(const uint32_t encId);
#endif
@@ -0,0 +1,72 @@
# Tool to extract 8x8 font data, save to bitmap file, and apply modifications
# to source code after editing the bitmap.
from __future__ import print_function
from matplotlib.pyplot import imread, imsave, imshow, show
import numpy as np
import sys
# Where to find the font data - may need updated if code has changed.
source_file = 'ui_lcd_hy28_fonts.c'
start_marker = 'const uint8_t GL_ASCII8x8_Table [] ='
start_offset = 2 # Data starts this number of lines after start marker.
end_marker = '};' # Indicates end of font data.
# Image filename used in extract and insert modes.
image_file = 'font-8x8.png'
#mode = None
#mode = show
mode = extract
#mode = insert
if len(sys.argv) > 1:
mode = sys.argv[1]
if mode not in ('show', 'extract', 'insert'):
print("Usage: %s { show | extract | insert }" % sys.argv[0])
sys.exit(1)
# Get the literals used to populate the font array in the source file
lines = [line.rstrip() for line in open(source_file).readlines()]
start = lines.index(start_marker) + start_offset
end = start + lines[start:].index(end_marker)
data = str.join("", lines[start:end])
# Eval the literals to get the values into a numpy array
packed = eval("np.array([%s], np.uint8)" % data)
# Reorganise into a monochrome image, with the 96 8 x 8 characters
# laid out in 8 rows by 12 columns for easier viewing/editing
unpacked = np.unpackbits(packed)
bitmaps = unpacked.reshape(96, 8, 8)
indices = np.arange(96).reshape(8, 12)
image = np.block([[bitmaps[idx] for idx in row] for row in indices])
if mode == 'show':
# Display font image
imshow(image, cmap='binary')
show()
elif mode == 'extract':
# Save font image
imsave(image_file, image, format='png', cmap='binary')
elif mode == 'insert':
# Read in modified font image
image = imread(image_file)[:,:,0].astype(bool)
# Reorganise back to original order
bitmaps = np.vstack([np.vstack(np.split(row, 12, 1))
for row in np.split(image, 8)])
unpacked = bitmaps.reshape(-1)
packed = ~np.packbits(unpacked)
# Replace lines of file in same format as used before
grouped = packed.reshape(-1, 8)
for i, group in enumerate(grouped):
line = (" " + " 0x%02x," * 8) % tuple(group)
lines[start + i] = line
# Write out modified source file
open(source_file, 'w').writelines([line + "\n" for line in lines])
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,301 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#ifndef __UI_LCD_HY28_H
#define __UI_LCD_HY28_H
#include "uhsdr_types.h"
#define RGB(red,green,blue)(uint16_t)(((red>>3)<<11)|((green>>2)<<5)|(blue>> 3))
// Colors definitions, go to http://www.color-hex.com/
// choose a new one and declare here
//
#define White 0xFFFF
#define Black 0x0000
#ifdef GREY_STYLE
#define Grey 0xBDF5 //RGB(0xb8,0xbc,0xa8)
#define Blue 0x632C //RGB(0x66,0x66,0x66)
#define Blue2 0x4A69 //RGB(0x4C,0x4C,0x4C)
#define Blue3 0x1082 //RGB(0x10,0x10,0x10)
#define Red 0x8C51 //RGB(0x89,0x89,0x89)
#define Red2 0xA534 //RGB(0xA7,0xA7,0xA7)
#define Red3 0xD69A //RGB(0xD0,0xD0,0xD0)
#define Red4 0x18E3 //RGB(0x1C,0x1C,0x1C)
#define Magenta 0x94B2 //RGB(0x95,0x95,0x95)
#define Green 0xDEFB //RGB(0xDC,0xDC,0xDC)
#define Green2 0x31A6 //RGB(0x36,0x36,0x36)
#define Cyan 0xE73C //RGB(0xE5,0xE5,0xE5)
#define Yellow 0xF7BE //RGB(0xF7,0xF7,0xF7)
#define Orange 0xBDF7 //RGB(0xBC,0xBC,0xBC)
#define Cream 0xE73C //RGB(0xE7,0xE7,0xE7)
#define Grey1 0x8410 //RGB(0x80,0x80,0x80)
#define Grey2 0xC618 //RGB(0xC0,0xC0,0xC0)
#define Grey3 0xA555 //RGB(0xA6,0xA8,0xAD)
#define Grey4 0x4208 //RGB(0x40,0x40,0x40)
#define Grey5 0x630C //RGB(0x60,0x60,0x60)
#define Grey6 0x7BCF //RGB(0x78,0x78,0x78)
#define Grey7 0x2104 //RGB(0x20,0x20,0x20)
#define RX_Grey 0xBED5 //RGB(0xb8,0xdb,0xa8)
#define TX_Grey 0xED74 //RGB(0xe8,0xad,0xa0)
#define Brown 0x4A49 //RGB(0x4A,0x4A,0x4A)
#elif defined(SEPIA_STYLE)
#define Grey 0xD5AE //RGB(0xD6,0xB6,0x77)
#define Blue 0x7B28 //RGB(0x7A,0x64,0x45)
#define Blue2 0x5A46 //RGB(0x5C,0x4B,0x33)
#define Blue3 0x1061 //RGB(0x11,0x0E,0x0B)
#define Red 0xA42B //RGB(0xA2,0x86,0x5D)
#define Red2 0xC50E //RGB(0xC4,0xA2,0x73)
#define Red3 0xF651 //RGB(0xF3,0xCA,0x8F)
#define Red4 0x20C2 //RGB(0x21,0x1A,0x14)
#define Magenta 0xB48C //RGB(0xB1,0x92,0x67)
#define Green 0xFEB3 //RGB(0xFF,0xD7,0x9E)
#define Green2 0x41A4 //RGB(0x41,0x34,0x24)
#define Cyan 0xFFF6 //RGB(0xFF,0xFF,0xB5)
#define Yellow 0xFFDD //RGB(0xFF,0xF8,0xEC)
#define Orange 0xDDB0 //RGB(0xDC,0xB6,0x81)
#define Cream 0xFF37 //RGB(0xFF,0xE4,0xBC)
#define Grey1 0x93EA //RGB(0x96,0x7C,0x56)
#define Grey2 0xE5F0 //RGB(0xE0,0xBC,0x85)
#define Grey3 0xFEB2 //RGB(0xFF,0xD4,0x97)
#define Grey4 0x49E5 //RGB(0x4D,0x3E,0x2A)
#define Grey5 0x72E8 //RGB(0x72,0x5D,0x40)
#define Grey6 0x8BAA //RGB(0x8D,0x74,0x50)
#define Grey7 0x20E2 //RGB(0x27,0x1F,0x17)
#define RX_Grey 0xDDB0 //RGB(0xDB,0xB5,0x80)
#define TX_Grey 0xDDB0 //RGB(0xDB,0xB5,0x80)
#define Brown 0x5A46 //RGB(0x59,0x49,0x31)
#else
#define Grey 0xBDF5 //RGB(0xb8,0xbc,0xa8) //=0xBDF5
#define Blue 0x529F //RGB(0x50,0x50,0xFF) // Brighter Blue //Original - 0x001F =#0000FF
#define Blue2 0x051F // =#00A0FF
#define Blue3 0x000A //RGB(0x00,0x00,0x50)
#define Red 0xF9C7 //RGB(0xFF,0x38,0x38) // Brighter (easier to see) Red //Original 0xF800 =#FF0000
#define Red2 0xFC10 //RGB(0xFF,0x80,0x80) // Even "brighter" red (almost pink)
#define Red3 0xFE18 //RGB(0xFF,0xC0,0xC0) // A sort of pink-ish, pale red
#define Red4 0x4000 //RGB(0x40,0x00,0x00)
#define Magenta 0xF99F //RGB(0xFF,0x30,0xFF) // Brighter Magenta //Original 0xF81F =#FF00FF
#define Green 0x07E0 // =#00FF00
#define Green2 0x0200 //RGB(0x00,0x40,0x00)
#define Cyan 0x7FFF
#define Yellow 0xFFE4 //RGB(0xFF,0xFF,0x20) // "Yellower" and brighter //Original - 0xFFE0 =#FFFF00
#define Orange 0xFD44 //RGB(0xFF,0xA8,0x20) //"Orange-er" and brighter //Original - RGB(0xF6,0xA0,0x1A)
#define Cream 0xEF3A //RGB(0xED,0xE7,0xD7)
#define Grey1 0x8410 //RGB(0x80,0x80,0x80)
#define Grey2 0xC618 //RGB(0xC0,0xC0,0xC0)
#define Grey3 0xA555 //RGB(0xA6,0xA8,0xAD)
#define Grey4 0x4208 //RGB(0x40,0x40,0x40)
#define Grey5 0x630C //RGB(0x60,0x60,0x60)
#define Grey6 0x7BCF //RGB(0x78,0x78,0x78)
#define Grey7 0x2104 //RGB(0x20,0x20,0x20)
#define RX_Grey 0xBED5 //RGB(0xb8,0xdb,0xa8) // slightly green grey
#define TX_Grey 0xED74 //RGB(0xe8,0xad,0xa0) // slightly red(ish) grey (more magenta, actually...)
#define Brown 0x6204 //RGB(0x65,0x43,0x21)
#endif
#define SMALL_FONT_WIDTH 8
#define LARGE_FONT_WIDTH 16
#define LCD_DIR_HORIZONTAL 0x0000
#define LCD_DIR_VERTICAL 0x0001
#define GRADIENT_STEP 8
#define TOUCHSCREEN_NO_MIRROR_NOFLIP 0
#define TOUCHSCREEN_X_MIRROR_NOFLIP 1
#define TOUCHSCREEN_Y_MIRROR_NOFLIP 2
#define TOUCHSCREEN_XY_MIRROR_NOFLIP 3
#define TOUCHSCREEN_NO_MIRROR_FLIPXY 4
#define TOUCHSCREEN_X_MIRROR_FLIPXY 5
#define TOUCHSCREEN_Y_MIRROR_FLIPXY 6
#define TOUCHSCREEN_XY_MIRROR_FLIPXY 7
// ----------------------------------------------------------
typedef enum
{
DISPLAY_NONE = 0,
DISPLAY_HY28A_SPI,
DISPLAY_HY28B_SPI,
DISPLAY_HY28B_PARALLEL,
DISPLAY_RA8875_SPI,
DISPLAY_RA8875_PARALLEL,
DISPLAY_ILI9486_PARALLEL,
DISPLAY_ST7796_PARALLEL,
DISPLAY_RPI_SPI,
DISPLAY_HY32D_PARALLEL_SSD1289,
// keep this always at the end of the enum
DISPLAY_NUM
} mchf_display_types_t;
typedef struct {
uint16_t reg;
uint16_t val;
} RegisterValue_t;
typedef struct RegisterValueSetInfo_s {
const RegisterValue_t* addr;
size_t size;
} RegisterValueSetInfo_t;
#define REGVAL_DATA (0xffff) // we indicate that the value is to be written using WriteData instead of WriteReg
#define REGVAL_DELAY (0x0000) // we indicate that the value is to be used as delay in ms instead of WriteReg
typedef struct
{
mchf_display_types_t display_type;
const char* name;
uint16_t (*ReadDisplayId)();
void (*SetActiveWindow) (uint16_t XLeft, uint16_t XRight, uint16_t YTop, uint16_t YBottom);
void (*SetCursorA)( unsigned short Xpos, unsigned short Ypos );
void (*WriteRAM_Prepare) ();
void (*WriteDataSpiStart_Prepare)();
void (*WriteIndexSpi_Prepare)();
void (*WriteReg)(unsigned short LCD_Reg, unsigned short LCD_RegValue);
uint16_t (*ReadReg)( uint16_t LCD_Reg);
void (*DrawStraightLine)(uint16_t x, uint16_t y, uint16_t Length, uint8_t Direction,uint16_t color);
void (*DrawFullRect)(uint16_t Xpos, uint16_t Ypos, uint16_t Height, uint16_t Width ,uint16_t color);
void (*DrawColorPoint)(uint16_t Xpos, uint16_t Ypos, uint16_t point);
GPIO_TypeDef* spi_cs_port;
uint16_t spi_cs_pin;
uint16_t is_spi:1;
uint16_t spi_speed:1;
} uhsdr_display_info_t;
typedef struct
{
uint8_t display_type; // existence/identification of display type
uint16_t DeviceCode; // LCD ident code
bool use_spi;
int16_t lcd_cs;
uint16_t MAX_X;
uint16_t MAX_Y;
GPIO_TypeDef* lcd_cs_pio;
const RegisterValueSetInfo_t* reg_info;
void (*SetActiveWindow) (uint16_t XLeft, uint16_t XRight, uint16_t YTop, uint16_t YBottom);
void (*SetCursorA)( unsigned short Xpos, unsigned short Ypos );
void (*WriteRAM_Prepare) ();
void (*WriteDataSpiStart_Prepare)();
void (*WriteIndexSpi_Prepare)();
void (*WriteReg)(unsigned short LCD_Reg, unsigned short LCD_RegValue);
uint16_t (*ReadReg)( uint16_t LCD_Reg);
void (*DrawStraightLine)(uint16_t x, uint16_t y, uint16_t Length, uint8_t Direction,uint16_t color);
void (*DrawFullRect)(uint16_t Xpos, uint16_t Ypos, uint16_t Height, uint16_t Width ,uint16_t color);
void (*DrawColorPoint)(uint16_t Xpos, uint16_t Ypos, uint16_t point);
} mchf_display_t;
extern mchf_display_t mchf_display;
const uhsdr_display_info_t* UiLcdHy28_DisplayInfoGet(mchf_display_types_t display_type);
void UiLcdHy28_LcdClear(ushort Color);
//uint16_t UiLcdHy28_PrintText(uint16_t Xpos, uint16_t Ypos, const char *str,const uint32_t Color, const uint32_t bkColor, uchar font);
uint16_t UiLcdHy28_PrintText(uint16_t Xpos, uint16_t Ypos, const char *str, uint32_t Color, uint32_t bkColor, uchar font);
//uint16_t UiLcdHy28_PrintTextRight(uint16_t Xpos, uint16_t Ypos, const char *str,const uint32_t Color, const uint32_t bkColor, uchar font);
uint16_t UiLcdHy28_PrintTextRight(uint16_t Xpos, uint16_t Ypos, const char *str, uint32_t Color, uint32_t bkColor, uchar font);
uint16_t UiLcdHy28_PrintTextCentered(const uint16_t bbX,const uint16_t bbY,const uint16_t bbW,const char* txt,uint32_t clr_fg,uint32_t clr_bg,uint8_t font);
//void UiLcdHy28_PrintTextVertLen(uint16_t XposStart, uint16_t YposStart, const char *str, const uint16_t len, const uint32_t clr_fg, const uint32_t clr_bg);
void UiLcdHy28_PrintTextVertLen(uint16_t XposStart, uint16_t YposStart, const char *str, const uint16_t len, uint32_t clr_fg, uint32_t clr_bg);
uint16_t UiLcdHy28_TextWidth(const char *str, uchar font);
uint16_t UiLcdHy28_TextHeight(uint8_t font);
void UiLcdHy28_DrawStraightLine(ushort Xpos, ushort Ypos, ushort Length, uchar Direction,ushort color);
void UiLcdHy28_DrawStraightLineDouble(ushort Xpos, ushort Ypos, ushort Length, uchar Direction,ushort color);
void UiLcdHy28_DrawStraightLineTriple(ushort Xpos, ushort Ypos, ushort Length, uchar Direction,ushort color);
void UiLcdHy28_DrawHorizLineWithGrad(ushort Xpos, ushort Ypos, ushort Length,ushort gradient_start);
void UiLcdHy28_DrawEmptyRect(ushort Xpos, ushort Ypos, ushort Height, ushort Width, ushort color);
void UiLcdHy28_DrawBottomButton(ushort Xpos, ushort Ypos, ushort Height, ushort Width,ushort color);
void UiLcdHy28_DrawFullRect (ushort Xpos, ushort Ypos, ushort Height, ushort Width, ushort color);
void UiLcdHy28_DrawColorPoint(ushort x, ushort y, ushort color);
void UiLcdHy28_BulkPixel_OpenWrite(ushort x, ushort width, ushort y, ushort height);
void UiLcdHy28_BulkPixel_CloseWrite(void);
void UiLcdHy28_BulkPixel_Put(uint16_t pixel);
void UiLcdHy28_BulkPixel_PutBuffer(uint16_t* pixel_buffer, uint32_t len);
void UiLcdHy28_BulkPixel_BufferFlush(void);
uint8_t UiLcdHy28_Init(void);
void UiLcdHy28_BacklightEnable(bool on);
typedef struct
{
uint8_t state;
uint16_t xraw;
uint16_t yraw;
int16_t xraw_m1;
int16_t xraw_m2;
int16_t yraw_m1;
int16_t yraw_m2;
int16_t focus_xprev;
int16_t focus_yprev;
//int32_t xraw_avgBuff;
//int32_t yraw_avgBuff;
int16_t hr_x;
int16_t hr_y;
uint16_t xraw_prev;
uint16_t yraw_prev;
int32_t cal[6];
bool present;
} mchf_touchscreen_t;
#define TP_DATASETS_VALID 0x04 // number of sets that must be identical for marked as VALID
#define TP_DATASETS_WAIT 0x01 // first dataset received
#define TP_DATASETS_PROCESSED 0xff
#define TP_DATASETS_NONE 0x00
extern mchf_touchscreen_t mchf_touchscreen;
void UiLcdHy28_TouchscreenDetectPress(void);
void UiLcdHy28_TouchscreenReadCoordinates(void);
bool UiLcdHy28_TouchscreenHasProcessableCoordinates(void);
void UiLcdHy28_TouchscreenInit(uint8_t mirror);
/*
// FIXME: THIS MUST BE HANDLED DIFFERENTLY, IT DOES NOT ALWAYS SEES
// THE CONFIGURATION FROM uhsdr_board.h but due to dependency issues, we cannot include
// uhsdr_board.h at the top
#ifdef USE_DISP_480_320
#define MAX_X 480
#define MAX_Y 320
#elif defined(USE_DISP_800_480)
#define MAX_X 800
#define MAX_Y 480
#else
#ifdef Simulate320_240_on_480_320
#define MAX_X 480
#define MAX_Y 320
#else
#define MAX_X 320
#define MAX_Y 240
#endif
#endif
*/
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,41 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#ifndef __UI_LCD_HY28_FONTS_H
#define __UI_LCD_HY28_FONTS_H
typedef struct
{
const uint8_t width;
const void* data;
} symbolData_t;
typedef struct
{
const void *table;
uint8_t Width;
uint8_t Height;
uint16_t maxCode;
uint8_t BitCount;
uint8_t firstCode;
uint8_t Spacing;
#ifdef USE_8bit_FONT
const uint16_t *offsetTable;
const uint8_t *heightTable;
const uint8_t *widthTable;
#endif
} sFONT;
#endif //__UI_LCD_HY28_FONTS_H
@@ -0,0 +1,758 @@
/* -*- 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: ui_lcd_layouts.c **
** Description: Layout definitions file **
** Licence: GNU GPLv3 **
** Author: Slawomir Balon/SP9BSL **
************************************************************************************/
#ifndef BOOTLOADER_BUILD
#include "uhsdr_board.h"
#include "ui_lcd_layouts.h"
#include "ui_driver.h"
//------------------------------------------------------------------------------------------------------------------------------------------
//some local 480x320 calculations to make life easier in case of change something
#define R480320_TUNE_FREQ_X 280
#define R480320_TUNE_FREQ_Y 36
#define R480320_TUNE_SPLIT_FREQ_X (R480320_TUNE_FREQ_X+80)//Shift with a small split to the right to close the frequency digits.
#define R480320_TUNE_SPLIT_MARKER_X (R480320_TUNE_FREQ_X+40)
#define R480320_TUNE_SPLIT_FREQ_Y_TX (R480320_TUNE_FREQ_Y+12)
#define R480320_TUNE_SFREQ_X (R480320_TUNE_FREQ_X + 120)// Second frequency display control
#define R480320_TUNE_SFREQ_Y (R480320_TUNE_FREQ_Y - 20)
#define R480320_DisplayDbm_X (R480320_TUNE_FREQ_X+45)
#define R480320_DisplayDbm_Y (R480320_TUNE_FREQ_Y-36)
#define R480320_MEMORYLABEL_X (R480320_TUNE_FREQ_X+45+(SMALL_FONT_WIDTH * 11)+4)
#define R480320_MEMORYLABEL_Y (R480320_TUNE_FREQ_Y-36)
#define R480320_BAND_MODE_X (R480320_TUNE_FREQ_X + 160)
#define R480320_BAND_MODE_Y (R480320_TUNE_FREQ_Y + 7)
#define R480320_BAND_MODE_MASK_X (R480320_BAND_MODE_X - 1)
#define R480320_BAND_MODE_MASK_Y (R480320_BAND_MODE_Y - 1)
#define R480320_BAND_MODE_MASK_H 13
#define R480320_BAND_MODE_MASK_W 33
// Demodulator mode control
#define R480320_DEMOD_MODE_X (R480320_TUNE_FREQ_X -61)
#define R480320_DEMOD_MODE_Y (R480320_TUNE_FREQ_Y - 20)
#define R480320_DEMOD_MODE_MASK_X R480320_DEMOD_MODE_X
#define R480320_DEMOD_MODE_MASK_Y (R480320_DEMOD_MODE_Y - 1)
#define R480320_DEMOD_MODE_MASK_H 13
#define R480320_DEMOD_MODE_MASK_W 58 //same as R480320_DIGMODE_IND_W
// AGC display box
//#define R480320_AGC_MASK_X (R480320_DEMOD_MODE_MASK_X-41)
#define R480320_AGC_MASK_X (R480320_TUNE_FREQ_X)
#define R480320_AGC_MASK_Y R480320_DEMOD_MODE_MASK_Y
#define R480320_AGC_MASK_W 41
#define R480320_AGC_MASK_H R480320_DEMOD_MODE_MASK_H
// Tunning step control
#define R480320_TUNE_STEP_X (R480320_TUNE_FREQ_X + 45)
#define R480320_TUNE_STEP_Y (R480320_TUNE_FREQ_Y - 21)
#define R480320_TUNE_STEP_MASK_H 15
#define R480320_TUNE_STEP_MASK_W (SMALL_FONT_WIDTH*7)
#define R480320_PW_IND_X (R480320_TUNE_FREQ_X)
#define R480320_PW_IND_Y (R480320_DEMOD_MODE_Y - 16)
#define R480320_PW_IND_W 41
#define R480320_SM_IND_X 0
#define R480320_SM_IND_Y 0
#define R480320_SM_IND_W (200)
#define R480320_SM_IND_H (72 - 14)
#define R480320_LEFTBOXES_IND_X 0
#define R480320_LEFTBOXES_IND_Y 64
#define R480320_LEFTBOX_WIDTH 58 // used for the lower left side controls
#define R480320_LEFTBOX_ROW_H 31
#define R480320_LEFTBOX_ROW_2ND_OFF 15
#define R480320_ENCODER_IND_X 128
#define R480320_ENCODER_IND_Y 64
#define R480320_DIGMODE_IND_X R480320_DEMOD_MODE_MASK_X // 218
#define R480320_DIGMODE_IND_Y 0
#define R480320_DIGMODE_IND_W R480320_DEMOD_MODE_MASK_W
//------------------------------------------------------------------------------------------------------------------------------------------
//some local 320x240 calculations to make life easier in case of change something
#define R320240_TUNE_FREQ_X 116
#define R320240_TUNE_FREQ_Y 100
#define R320240_TUNE_SPLIT_FREQ_X (R320240_TUNE_FREQ_X+80)//Shift with a small split to the right to close the frequency digits.
#define R320240_TUNE_SPLIT_MARKER_X (R320240_TUNE_FREQ_X+40)
#define R320240_TUNE_SPLIT_FREQ_Y_TX (R320240_TUNE_FREQ_Y+12)
#define R320240_TUNE_SFREQ_X (R320240_TUNE_FREQ_X + 120)// Second frequency display control
#define R320240_TUNE_SFREQ_Y (R320240_TUNE_FREQ_Y - 20)
#define R320240_DisplayDbm_X (R320240_TUNE_FREQ_X+45)
#define R320240_DisplayDbm_Y (R320240_TUNE_FREQ_Y-36)
#define R320240_MEMORYLABEL_X (R320240_TUNE_FREQ_X+45+(SMALL_FONT_WIDTH * 11)+4)
#define R320240_MEMORYLABEL_Y (R320240_TUNE_FREQ_Y-36)
#define R320240_BAND_MODE_X (R320240_TUNE_FREQ_X + 160)
#define R320240_BAND_MODE_Y (R320240_TUNE_FREQ_Y + 7)
#define R320240_BAND_MODE_MASK_X (R320240_BAND_MODE_X - 1)
#define R320240_BAND_MODE_MASK_Y (R320240_BAND_MODE_Y - 1)
#define R320240_BAND_MODE_MASK_H 13
#define R320240_BAND_MODE_MASK_W 33
// Demodulator mode control
#define R320240_DEMOD_MODE_X (R320240_TUNE_FREQ_X + 1)
#define R320240_DEMOD_MODE_Y (R320240_TUNE_FREQ_Y - 20)
#define R320240_DEMOD_MODE_MASK_X (R320240_DEMOD_MODE_X - 1)
#define R320240_DEMOD_MODE_MASK_Y (R320240_DEMOD_MODE_Y - 1)
#define R320240_DEMOD_MODE_MASK_H 13
#define R320240_DEMOD_MODE_MASK_W 41
// AGC display box
#define R320240_AGC_MASK_X (R320240_DEMOD_MODE_MASK_X-41)
#define R320240_AGC_MASK_Y R320240_DEMOD_MODE_MASK_Y
#define R320240_AGC_MASK_W (R320240_DEMOD_MODE_MASK_W-6)
#define R320240_AGC_MASK_H R320240_DEMOD_MODE_MASK_H
// Tunning step control
#define R320240_TUNE_STEP_X (R320240_TUNE_FREQ_X + 45)
#define R320240_TUNE_STEP_Y (R320240_TUNE_FREQ_Y - 21)
#define R320240_TUNE_STEP_MASK_H 15
#define R320240_TUNE_STEP_MASK_W (SMALL_FONT_WIDTH*7)
#define R320240_PW_IND_X (R320240_DEMOD_MODE_X -1)
#define R320240_PW_IND_Y (R320240_DEMOD_MODE_Y - 16)
#define R320240_PW_IND_W 41
#define R320240_SM_IND_X 116
#define R320240_SM_IND_Y 0
#define R320240_SM_IND_W (200)
#define R320240_SM_IND_H (72 - 14)
#define R320240_LEFTBOXES_IND_X 0
#define R320240_LEFTBOXES_IND_Y 130
#define R320240_LEFTBOX_WIDTH 58 // used for the lower left side controls
#define R320240_LEFTBOX_ROW_H 28
#define R320240_LEFTBOX_ROW_2ND_OFF 13
#define R320240_ENCODER_IND_X 0
#define R320240_ENCODER_IND_Y 16
#define R320240_DIGMODE_IND_X 0
#define R320240_DIGMODE_IND_Y 191
#define R320240_DIGMODE_IND_W 58
//------------------------------------------------------------------------------------------------------------------------------------------
//Touchscreen definitions for 480x320
static const touchaction_descr_t R480320_touchactions_normal[] =
{
#ifndef SDR_AMBER_480_320
#ifndef OVI40_MOD_480_320
{ {R480320_SM_IND_X,R480320_SM_IND_Y,R480320_SM_IND_W,R480320_SM_IND_H}, UiAction_ChangeLowerMeterUp, NULL }, // Lower Meter: Meter Toggle
{ {0,110,160,16}, UiAction_ToggleWaterfallScopeDisplay, UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {(480/2)-16,110,48,16}, UiAction_ChangeSpectrumZoomLevelDown, UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {(480/2)+100,110,48,16}, UiAction_ChangeSpectrumZoomLevelUp, UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {R480320_TUNE_FREQ_X+16*7,R480320_TUNE_FREQ_Y,16*3,24}, UiAction_ChangeFrequencyToNextKhz, NULL }, // Frequency display, last three digits :Set last 3 digits to zero
{ {R480320_TUNE_FREQ_X,R480320_TUNE_FREQ_Y,16*7,24}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band
{ {R480320_DEMOD_MODE_X,R480320_DEMOD_MODE_Y,R480320_DEMOD_MODE_MASK_W,R480320_DEMOD_MODE_MASK_H}, UiVk_ModSelVirtualKeys, NULL }, // Demod Mode Box: mode switch
{ {R480320_PW_IND_X,R480320_PW_IND_Y,64,30}, UiAction_ChangePowerLevel, NULL }, // Power Box: TX Power Increase
{ {R480320_ENCODER_IND_X+ENC_COL_W*5+Xspacing*2,R480320_ENCODER_IND_Y,ENC_COL_W,ENC_ROW_H}, UiAction_ChangeAudioSource, NULL }, // Audio In Box: Switch Source
{ {R480320_BAND_MODE_X,R480320_BAND_MODE_Y,R480320_BAND_MODE_MASK_W/2,R480320_BAND_MODE_MASK_H}, UiAction_ChangeBandDownOrUp, NULL }, // Left Part Band Display: Band down
{ {R480320_BAND_MODE_X+R480320_BAND_MODE_MASK_W*3/4,R480320_BAND_MODE_Y,R480320_BAND_MODE_MASK_W/2,R480320_BAND_MODE_MASK_H}, UiAction_ChangeBandUpOrDown, NULL }, // Right Part Band Display: Band up
{ {R480320_LEFTBOXES_IND_X,R480320_LEFTBOXES_IND_Y,R480320_LEFTBOX_WIDTH,R480320_LEFTBOX_ROW_H}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box: Restart I2S
{ {0,110,480,176}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions}, // Scope Draw Area: Tune to Touch
{ {R480320_DIGMODE_IND_X,R480320_DIGMODE_IND_Y,R480320_DIGMODE_IND_W,16}, UiVk_ModSelVirtualKeys, NULL }, // Digital Mode Box: Switch Digi Mode
{ {R480320_TUNE_STEP_X,R480320_TUNE_STEP_Y,R480320_TUNE_STEP_MASK_W,R480320_TUNE_STEP_MASK_H}, UiAction_ChangeDynamicTuning, NULL }, // Step Box: Dynamic Tuning Toggle
{ {R480320_TUNE_STEP_X,R480320_TUNE_STEP_Y,R480320_TUNE_STEP_MASK_W,R480320_TUNE_STEP_MASK_H}, UiAction_ChangeDynamicTuning, NULL }, // Step Box: Dynamic Tuning Toggle
#else
{ {273,0,203,56}, UiAction_ChangeLowerMeterUp, NULL }, // Lower Meter: Meter Toggle
{ {0,124,120,16}, UiAction_ToggleWaterfallScopeDisplay, UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {180,124,120,16}, UiAction_ChangeSpectrumZoomLevelDown, UiAction_ZoomResetToOne }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {360,124,120,16}, UiAction_ChangeSpectrumZoomLevelUp, UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {384,90,37,23}, UiAction_ChangeFrequencyToNextKhz, NULL }, // Frequency display, last three digits :Set last 3 digits to zero
{ {276,90,104,23}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band
{ {122,0,63,12}, UiVk_ModSelVirtualKeys, UiAction_ChangeDigitalMode }, // Digi Mode Box: mode switch
{ {122,30,69,28}, UiVk_ModSelVirtualKeys, UiAction_ChangeDemodModeToAlternativeMode }, // Digi Mode Box: mode switch - double
{ {188,0,14,12}, UiAction_ChangeDemodModeToAlternativeMode, NULL }, // Demod Mode Box: sideband switch
{ {205,0,56,12}, UiAction_ChangePowerLevel, NULL }, // Power Box: TX Power Increase
{ {70,14,42,28}, UiDriver_RIT_Reset,NULL }, // RIT Box: RIT Reset
{ {70,45,42,30}, UiAction_ChangeAudioSource, NULL }, // Audio In Box: Switch Source
{ {446,88,14,15}, UiAction_ChangeBandDownOrUp, NULL }, // Left Part Band Display: Band down
{ {465,88,14,15}, UiAction_ChangeBandUpOrDown, NULL }, // Right Part Band Display: Band up
{ {193,30,69,28}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box
{ {0,141,480,158}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
{ {205,15,56,13}, UiAction_ChangeDynamicTuning, NULL }, // Step Box: Dynamic Tuning Toggle
#endif
#else //SDR_AMBER_480_320
//X,Y,W,H
{ {273,0,203,56}, UiAction_ChangeLowerMeterUp, NULL }, // Lower Meter: Meter Toggle
{ {0,124,120,16}, UiAction_ToggleWaterfallScopeDisplay, UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {180,124,120,16}, UiAction_ChangeSpectrumZoomLevelDown, UiAction_ZoomResetToOne }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {360,124,120,16}, UiAction_ChangeSpectrumZoomLevelUp, UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {384,90,37,23}, UiAction_ChangeFrequencyToNextKhz, NULL }, // Frequency display, last three digits :Set last 3 digits to zero
{ {276,90,104,23}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band
{ {122,0,63,12}, UiVk_ModSelVirtualKeys, UiAction_ChangeDigitalMode }, // Digi Mode Box: mode switch
{ {122,30,69,28}, UiVk_ModSelVirtualKeys, UiAction_ChangeDemodModeToAlternativeMode }, // Digi Mode Box: mode switch - double
{ {188,0,14,12}, UiAction_ChangeDemodModeToAlternativeMode, NULL }, // Demod Mode Box: sideband switch
{ {205,0,56,12}, UiAction_ChangePowerLevel, NULL }, // Power Box: TX Power Increase
{ {70,14,42,28}, UiDriver_RIT_Reset,NULL }, // RIT Box: RIT Reset
{ {70,45,42,30}, UiAction_ChangeAudioSource, NULL }, // Audio In Box: Switch Source
{ {446,88,14,15}, UiAction_ChangeBandDownOrUp, NULL }, // Left Part Band Display: Band down
{ {465,88,14,15}, UiAction_ChangeBandUpOrDown, NULL }, // Right Part Band Display: Band up
{ {193,30,69,28}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box
{ {0,141,480,158}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
{ {205,15,56,13}, UiAction_ChangeDynamicTuning, NULL }, // Step Box: Dynamic Tuning Toggle
{ {122,15,40,13}, UiAction_ChangeRXInputStateDown, NULL }, // Amber - Change RX Input State Down
{ {162,15,40,13}, UiAction_ChangeRXInputStateUp, NULL }, // Amber - Change RX Input State Up
#endif
};
// this is the map for menu mode, right now only used for debugging/experimental purposes
static const touchaction_descr_t R480320_touchactions_menu[] =
{
{ { R480320_SM_IND_X+R480320_SM_IND_W-16,R480320_SM_IND_Y,16,16 }, UiAction_ChangeDebugInfoDisplay, NULL}, // S-Meter db: toggle show tp coordinates
};
static const touchaction_list_descr_t R480320_touch_regions[] =
{
// ATTENTION: the size calculation only works for true arrays, not for pointers!
{ R480320_touchactions_normal, sizeof(R480320_touchactions_normal)/sizeof(*R480320_touchactions_normal) },
{ R480320_touchactions_menu, sizeof(R480320_touchactions_menu)/sizeof(*R480320_touchactions_menu) },
};
//------------------------------------------------------------------------------------------------------------------------------------------
//Touchscreen definitions for 320x240
static const touchaction_descr_t R320240_touchactions_normal[] =
{
{ {R320240_SM_IND_X,R320240_SM_IND_Y,R320240_SM_IND_W,R320240_SM_IND_H},UiAction_ChangeLowerMeterUp,NULL }, // Lower Meter: Meter Toggle
// { {64,128,60,16}, UiAction_ToggleWaterfallScopeDisplay,UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {60,128,64,16}, UiAction_ToggleWaterfallScopeDisplay,UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
// { {180,128,40,16}, UiAction_ChangeSpectrumZoomLevelDown,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {156,128,64,16}, UiAction_ChangeSpectrumZoomLevelDown,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Middle Part: Decrease Zoom Level
// { {280,128,40,16}, UiAction_ChangeSpectrumZoomLevelUp,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {252,128,64,16}, UiAction_ChangeSpectrumZoomLevelUp,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {R320240_TUNE_FREQ_X+16*7,R320240_TUNE_FREQ_Y,16*3,24},UiAction_ChangeFrequencyToNextKhz,NULL }, // Tune button:Set last 3 digits to zero
// { {R320240_TUNE_FREQ_X,R320240_TUNE_FREQ_Y,16*7,24}, UiVk_BndSelVirtualKeys, NULL }, // Frequency display, first digits :Select the band
{ {R320240_TUNE_FREQ_X,R320240_TUNE_FREQ_Y,16*7,24}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band/freq
// { {R320240_DEMOD_MODE_X,R320240_DEMOD_MODE_Y,R320240_DEMOD_MODE_MASK_W,R320240_DEMOD_MODE_MASK_H}, UiAction_ChangeDemodMode,NULL }, // Demod Mode Box: mode switch
{ {R320240_DEMOD_MODE_X,R320240_DEMOD_MODE_Y,R320240_DEMOD_MODE_MASK_W,R320240_DEMOD_MODE_MASK_H}, UiAction_ChangeDemodModeToAlternativeMode,NULL }, // Demod Mode Box: mode switch
{ {R320240_PW_IND_X,R320240_PW_IND_Y,64,16},UiAction_ChangePowerLevel,NULL }, // Power Box: TX Power Increase
{ {74,14,37,29}, UiDriver_RIT_Reset,NULL }, // RIT Box: RIT Reset
{ {R320240_ENCODER_IND_X+ENC_COL_W*2,R320240_ENCODER_IND_Y+ENC_ROW_H,ENC_COL_W,ENC_ROW_H}, UiAction_ChangeAudioSource,NULL }, // Audio In Box: Switch Source
{ {R320240_BAND_MODE_X,R320240_BAND_MODE_Y,R320240_BAND_MODE_MASK_W/2,R320240_BAND_MODE_MASK_H}, UiAction_ChangeBandDownOrUp,NULL }, // Left Part Band Display: Band down
{ {R320240_BAND_MODE_X+R320240_BAND_MODE_MASK_W*3/4,R320240_BAND_MODE_Y,R320240_BAND_MODE_MASK_W/2,R320240_BAND_MODE_MASK_H}, UiAction_ChangeBandUpOrDown,NULL }, // Right Part Band Display: Band up
{ {R320240_LEFTBOXES_IND_X,R320240_LEFTBOXES_IND_Y,R320240_LEFTBOX_WIDTH,R320240_LEFTBOX_ROW_H}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box: Restart I2S
// { {60,128,256,90}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
{ {60,146,256,72}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
{ {R320240_DIGMODE_IND_X,R320240_DIGMODE_IND_Y,R320240_DIGMODE_IND_W,16}, UiVk_ModeVirtualKeys,UiAction_ChangeDigitalMode }, // Digital Mode Box: Switch Digi Mode
{ {R320240_TUNE_STEP_X,R320240_TUNE_STEP_Y,R320240_TUNE_STEP_MASK_W,R320240_TUNE_STEP_MASK_H}, UiAction_ChangeDynamicTuning,NULL }, // Step Box: Dynamic Tuning Toggle
};
//------------------------------------------------------------------------------------------------------------------------------------------
////Touchscreen definitions for 320x240 Alternative wide spectrum mode
static const touchaction_descr_t R320240_touchactions_widespectrum[] =
{
#ifndef SDR_AMBER // not Amber
//{X, Y, W, H}
{ {113,0,203,52},UiAction_ChangeLowerMeterUp,NULL }, // Lower Meter: Meter Toggle
{ {0,136,80,13}, UiAction_ToggleWaterfallScopeDisplay,UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {120,136,80,13}, UiAction_ChangeSpectrumZoomLevelDown,UiAction_ZoomResetToOne }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {240,136,80,13}, UiAction_ChangeSpectrumZoomLevelUp,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {226,109,48,24},UiAction_ChangeFrequencyToNextKhz,NULL }, // Tune button:Set last 3 digits to zero
// { {118,109,105,24}, UiVk_BndSelVirtualKeys, NULL }, // Frequency display, first digits :Select the band
{ {118,109,105,24}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band/freq
// { {113,87,41,13}, UiAction_ChangeDemodMode,NULL }, // Demod Mode Box: mode switch
// { {113,87,41,13}, UiAction_ChangeDemodModeToAlternativeMode,NULL }, // Demod Mode Box: sideband switch
{ {138,71,16,12}, UiAction_ChangeDemodModeToAlternativeMode,NULL }, // Demod Mode Box: sideband switch
{ {113,56,41,13},UiAction_ChangePowerLevel,NULL }, // Power Box: TX Power Increase
{ {74,14,37,26}, UiDriver_RIT_Reset,NULL }, // RIT Box: RIT Reset
// { {70,36,41,31}, UiAction_ChangeAudioSource,NULL }, // Audio In Box: Switch Source
{ {74,41,37,26}, UiAction_ChangeAudioSource,NULL }, // Audio In Box: Switch Source
{ {287,108,15,16}, UiAction_ChangeBandDownOrUp,NULL }, // Left Part Band Display: Band down
{ {305,108,15,16}, UiAction_ChangeBandUpOrDown,NULL }, // Right Part Band Display: Band up
{ {217,56,58,29}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box: Restart I2S
{ {1,152,318,73}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
// { {74,71,80,13}, UiAction_ChangeDigitalMode,UiVk_ModeVirtualKeys }, // Digital Mode Box: Switch Digi Mode
{ {74,71,61,13}, UiVk_ModeVirtualKeys,UiAction_ChangeDigitalMode }, // Digital Mode Box: Switch Digi Mode
// { {157,87,57,13}, UiAction_ChangeDynamicTuning,NULL }, // Step Box: Dynamic Tuning Toggle
{ {113,87,41,13}, UiAction_ChangeDynamicTuning,NULL }, // Step Box: Dynamic Tuning Toggle
#else //Amber 320x240
//{X, Y, W, H}
{ {113,0,203,52}, UiAction_ChangeLowerMeterUp, NULL }, // Lower Meter: Meter Toggle
{ {0,136,80,13}, UiAction_ToggleWaterfallScopeDisplay,UiAction_ChangeSpectrumSize }, // Spectrum Bar Left Part: WaterfallScope Toggle
{ {120,136,80,13}, UiAction_ChangeSpectrumZoomLevelDown,UiAction_ZoomResetToOne }, // Spectrum Bar Middle Part: Decrease Zoom Level
{ {240,136,80,13}, UiAction_ChangeSpectrumZoomLevelUp,UiAction_CheckSpectrumTouchActions }, // Spectrum Bar Right Part: Increase Zoom Level
{ {226,109,48,24}, UiAction_ChangeFrequencyToNextKhz, NULL }, // Tune button:Set last 3 digits to zero
{ {118,109,105,24}, UiVk_BndSelVirtualKeys, UiVk_BndFreqSetVirtualKeys }, // Frequency display, first digits :Select the band/freq
{ {138,71,16,12}, UiAction_ChangeDemodModeToAlternativeMode, NULL }, // Demod Mode Box: sideband switch
{ {113,56,41,13}, UiAction_ChangePowerLevel, NULL }, // Power Box: TX Power Increase
{ {74,14,37,26}, UiDriver_RIT_Reset,NULL }, // RIT Box: RIT Reset
// { {70,36,41,31}, UiAction_ChangeAudioSource, NULL }, // Audio In Box: Switch Source
{ {74,41,37,26}, UiAction_ChangeAudioSource,NULL }, // Audio In Box: Switch Source
{ {287,108,15,16}, UiAction_ChangeBandDownOrUp, NULL }, // Left Part Band Display: Band down
{ {305,108,15,16}, UiAction_ChangeBandUpOrDown, NULL }, // Right Part Band Display: Band up
{ {217,56,58,28}, UiVk_DSPVirtualKeys, Codec_RestartI2S }, // DSP Box: Restart I2S
{ {1,152,318,73}, UiAction_ChangeFrequencyByTouch, UiAction_CheckSpectrumTouchActions }, // Scope Draw Area: Tune to Touch
// { {74,71,61,13}, UiAction_ChangeDigitalMode, UiVk_ModeVirtualKeys }, // Digital Mode Box: Switch Digi Mode
{ {74,71,61,13}, UiVk_ModeVirtualKeys, UiAction_ChangeDigitalMode }, // Digital Mode Box: Switch Digi Mode
{ {157,56,58,28}, UiVk_ModeVirtualKeys, UiAction_ChangeDigitalMode }, // Digital Mode Box - double touch zone
{ {157,86,57,13}, UiAction_ChangeDynamicTuning, NULL }, // Step Box: Dynamic Tuning Toggle
{ {74,86,40,13}, UiAction_ChangeRXInputStateDown, NULL }, // Amber - Change RX Input State Down
{ {114,86,40,13}, UiAction_ChangeRXInputStateUp, NULL }, // Amber - Change RX Input State Up
#endif
};
// this is the map for menu mode, right now only used for debugging/experimental purposes
static const touchaction_descr_t R320240_touchactions_menu[] =
{
{ { R320240_SM_IND_X+R320240_SM_IND_W-16,R320240_SM_IND_Y,16,16 }, UiAction_ChangeDebugInfoDisplay, NULL}, // S-Meter db: toggle show tp coordinates
};
static const touchaction_list_descr_t R320240__touch_regions[] =
{
// ATTENTION: the size calculation only works for true arrays, not for pointers!
{ R320240_touchactions_normal, sizeof(R320240_touchactions_normal)/sizeof(*R320240_touchactions_normal) },
{ R320240_touchactions_menu, sizeof(R320240_touchactions_menu)/sizeof(*R320240_touchactions_menu) },
};
static const touchaction_list_descr_t R320240__touch_regions_widespectrum[] =
{
// ATTENTION: the size calculation only works for true arrays, not for pointers!
{ R320240_touchactions_widespectrum, sizeof(R320240_touchactions_widespectrum)/sizeof(*R320240_touchactions_widespectrum) },
{ R320240_touchactions_menu, sizeof(R320240_touchactions_menu)/sizeof(*R320240_touchactions_menu) },
};
//------------------------------------------------------------------------------------------------------------------------------------------
const LcdLayout LcdLayouts[LcdLayoutsCount]=
{
//-----------------------------------------------------------------
{ //320x240
.Size = { 320, 240 },
.StartUpScreen_START = { 0, 10 },
.SpectrumWindow = { .x = 58, .y = 128, .w = 260, .h = 94 },
.SpectrumWindowPadding=2,
.TUNE_FREQ= { R320240_TUNE_FREQ_X, R320240_TUNE_FREQ_Y },
.TUNE_SPLIT_FREQ_X=R320240_TUNE_SPLIT_FREQ_X,
.TUNE_SPLIT_MARKER_X=R320240_TUNE_SPLIT_MARKER_X,
.TUNE_SPLIT_FREQ_Y_TX=R320240_TUNE_SPLIT_FREQ_Y_TX,
.TUNE_SFREQ = { R320240_TUNE_SFREQ_X, R320240_TUNE_SFREQ_Y },
.DisplayDbm = { R320240_DisplayDbm_X, R320240_DisplayDbm_Y },
.MEMORYLABEL= { R320240_MEMORYLABEL_X, R320240_MEMORYLABEL_Y} ,
.BAND_MODE = { R320240_BAND_MODE_X, R320240_BAND_MODE_Y},
.BAND_MODE_MASK = { .x = R320240_BAND_MODE_MASK_X, .y = R320240_BAND_MODE_MASK_Y, .h = R320240_BAND_MODE_MASK_H, .w = R320240_BAND_MODE_MASK_W },
.DEMOD_MODE_MASK = { .x = R320240_DEMOD_MODE_MASK_X, .y = R320240_DEMOD_MODE_MASK_Y, .h = R320240_DEMOD_MODE_MASK_H, .w = R320240_DEMOD_MODE_MASK_W},
.AGC_MASK = {.x = R320240_AGC_MASK_X, .y = R320240_AGC_MASK_Y, .h = R320240_AGC_MASK_H,
.w = R320240_AGC_MASK_W},
.TUNE_STEP={.x=R320240_TUNE_STEP_X, .y=R320240_TUNE_STEP_Y, .h=R320240_TUNE_STEP_MASK_H, .w=R320240_TUNE_STEP_MASK_W},
.ENCODER_IND = { R320240_ENCODER_IND_X, R320240_ENCODER_IND_Y},
.ENCODER_MODE=MODE_VERTICAL,
.DIGMODE={.x=R320240_DIGMODE_IND_X,.y=R320240_DIGMODE_IND_Y,.w=R320240_DIGMODE_IND_W},
.LEFTBOXES_IND = { .x=R320240_LEFTBOXES_IND_X, .y=R320240_LEFTBOXES_IND_Y, .w=R320240_LEFTBOX_WIDTH, .h=R320240_LEFTBOX_ROW_H},
.LEFTBOXES_MODE=MODE_VERTICAL,
.LEFTBOXES_ROW_2ND_OFF=R320240_LEFTBOX_ROW_2ND_OFF,
.PW_IND = { .x=R320240_PW_IND_X, .y=R320240_PW_IND_Y, .w=R320240_PW_IND_W},
.TEMP_IND={.x = 0, .y = 0},
.RTC_IND={.x= 0, .y = 79},
.LOADANDDEBUG_Y=95,
.DEBUG_X=0,
.LOAD_X=280,
.PWR_NUM_IND = { 1, 80},
.CW_DECODER_WPM = { 0, 108},
.SNAP_CARRIER = { 27, 122},
.TextMsgLine = { 5, 92},
.TextMsg_buffer_max=44,
.TextMsg_font=4,
.FREEDV_SNR = { 5, 116},
.FREEDV_BER = { 5, 104},
.FREEDV_FONT=4,
.SM_IND={.x=R320240_SM_IND_X,.y=R320240_SM_IND_Y,.h=R320240_SM_IND_H,.w=R320240_SM_IND_W},
.PWR_IND={.x = 4, .y = 193+15},
.BOTTOM_BAR={.x=0,.y=228, .h=16, .w=62},
.MENUSIZE=7,
.MENU_IND = { 60, 128},
.MENU_CHANGE_X=244,
.MENU_CURSOR_X=311,
.MENU_TEXT_SIZE_MAX=34,
.touchaction_list=R320240__touch_regions
},
//-----------------------------------------------------------------
{ //480x320
#ifndef SDR_AMBER //OVI40, Sparrow
#ifndef OVI40_MOD_480_320
.Size = { 480, 320},
.StartUpScreen_START ={ 80, 60},
.SpectrumWindow={ .x = 0, .y = 110, .w = 480, .h = 176 },
.SpectrumWindowPadding=0,
.TUNE_FREQ= { R480320_TUNE_FREQ_X, R480320_TUNE_FREQ_Y},
.TUNE_SPLIT_FREQ_X=R480320_TUNE_SPLIT_FREQ_X,
.TUNE_SPLIT_MARKER_X=R480320_TUNE_SPLIT_MARKER_X,
.TUNE_SPLIT_FREQ_Y_TX=R480320_TUNE_SPLIT_FREQ_Y_TX,
.TUNE_SFREQ = { R480320_TUNE_SFREQ_X, R480320_TUNE_SFREQ_Y},
.DisplayDbm = { R480320_DisplayDbm_X, R480320_DisplayDbm_Y},
.MEMORYLABEL = { R480320_MEMORYLABEL_X, R480320_MEMORYLABEL_Y},
.BAND_MODE = { R480320_BAND_MODE_X, R480320_BAND_MODE_Y},
.BAND_MODE_MASK = { .x = R480320_BAND_MODE_MASK_X, .y = R480320_BAND_MODE_MASK_Y, .h = R480320_BAND_MODE_MASK_H, .w= R480320_BAND_MODE_MASK_W},
.DEMOD_MODE_MASK = { .x = R480320_DEMOD_MODE_MASK_X, .y = R480320_DEMOD_MODE_MASK_Y, .h = R480320_DEMOD_MODE_MASK_H,
.w = R480320_DEMOD_MODE_MASK_W},
.AGC_MASK = {.x = R480320_AGC_MASK_X, .y = R480320_AGC_MASK_Y, .h = R480320_AGC_MASK_H,
.w = R480320_AGC_MASK_W},
.TUNE_STEP={.x=R480320_TUNE_STEP_X, .y=R480320_TUNE_STEP_Y, .h=R480320_TUNE_STEP_MASK_H, .w=R480320_TUNE_STEP_MASK_W},
.ENCODER_IND = { R480320_ENCODER_IND_X, R480320_ENCODER_IND_Y},
.ENCODER_MODE=MODE_HORIZONTAL,
.DIGMODE={.x=R480320_DIGMODE_IND_X,.y=R480320_DIGMODE_IND_Y,.w=R480320_DIGMODE_IND_W},
.LEFTBOXES_IND = { .x=R480320_LEFTBOXES_IND_X, .y=R480320_LEFTBOXES_IND_Y, .w=R480320_LEFTBOX_WIDTH, .h=R480320_LEFTBOX_ROW_H},
.LEFTBOXES_MODE=MODE_HORIZONTAL,
.LEFTBOXES_ROW_2ND_OFF=R480320_LEFTBOX_ROW_2ND_OFF,
.PW_IND = { .x=R480320_PW_IND_X, .y=R480320_PW_IND_Y, .w=R480320_PW_IND_W},
.TEMP_IND={.x = 370,.y = 64},
.RTC_IND={.x = 415,.y = 80},
.LOADANDDEBUG_Y=96,
.DEBUG_X=0,
.LOAD_X=280,
.PWR_NUM_IND ={ 320, 96},
.CW_DECODER_WPM = { 420, 290},
.SNAP_CARRIER= { 242, 29},
.TextMsgLine = { 0, 290 },
.TextMsg_buffer_max=50,
.TextMsg_font=0,
//.FREEDV_SNR = { 280, 28},
//.FREEDV_BER = {380, 28},
.FREEDV_SNR = {410,288},
.FREEDV_BER = {410,297},
.FREEDV_FONT=4,
.SM_IND={.x = R480320_SM_IND_X, .y = R480320_SM_IND_Y, .h = R480320_SM_IND_H, .w = R480320_SM_IND_W},
.PWR_IND={ .x = 420, .y = 307},
#ifdef UI_BRD_OVI40
.BOTTOM_BAR={.x=0,.y=308, .h=16, .w=74},
#else
.BOTTOM_BAR={.x=32,.y=308, .h=16, .w=74},
#endif
.MENUSIZE=14,
.MENU_IND = { 80, 110 },
.MENU_CHANGE_X=280,
.MENU_CURSOR_X=360,
.MENU_TEXT_SIZE_MAX=40,
.touchaction_list=R480320_touch_regions
#else
.Size = { 480, 320 },
.StartUpScreen_START = { 80, 60 },
.SpectrumWindow = { .x = 0, .y = 123, .w = 480, .h = 174 },
.SpectrumWindowPadding = 0,
.TUNE_FREQ = { 276, 90 },
.TUNE_SPLIT_FREQ_X = 290,
.TUNE_SPLIT_MARKER_X = 276,
.TUNE_SPLIT_FREQ_Y_TX = 276,
.TUNE_SFREQ = { 396, 60 },
.DisplayDbm = { 273, 60 },
.MEMORYLABEL = { 355, 60 },
.BAND_MODE = { 436, 90 },
.BAND_MODE_MASK = { .x = 435, .y = 89, .h = 13, .w = 33 },
.DEMOD_MODE_MASK = { .x = 186, .y = 0, .h = 13, .w = 16 },
.AGC_MASK = {.x = 122, .y = 15, .h = 13, .w = 80 },
.TUNE_STEP={.x = 205, .y = 15, .h = 13, .w = 56 },
.ENCODER_IND = { 0, 15 },
.ENCODER_MODE = MODE_VERTICAL,
.DIGMODE={.x = 122, .y = 0, .w = 63},
.LEFTBOXES_IND = { .x = 122, .y=30, .w = 69, .h = 28 },
.LEFTBOXES_MODE = MODE_HORIZONTAL,
.LEFTBOXES_ROW_2ND_OFF = 13,
.PW_IND = { .x = 205, .y = 0, .w = 56 },
.TEMP_IND = { .x = 0, .y = 0 },
.RTC_IND = { .x = 127, .y = 60 },
.LOADANDDEBUG_Y = 75,
.DEBUG_X = 0,
.LOAD_X = 440,
.PWR_NUM_IND = { 320, 99 },
.CW_DECODER_WPM = { 0, 92 },
.SNAP_CARRIER = { 27, 107 },
.TextMsgLine = { 0, 75 },
.TextMsg_buffer_max = 50,
.TextMsg_font = 0,
//.FREEDV_SNR = { 280, 28},
//.FREEDV_BER = {380, 28},
.FREEDV_SNR = { 0, 90 },
.FREEDV_BER = { 0, 102 },
.FREEDV_FONT = 4,
.SM_IND = { .x = 273, .y = 0, .h = 56, .w = 203 },
.PWR_IND = { .x = 207, .y = 60 },
.BOTTOM_BAR = {.x=0,.y=308, .h=16, .w=79},//.w=74},
.MENUSIZE = 14,
.MENU_IND = { 140, 129 },
.MENU_CHANGE_X = 280,
.MENU_CURSOR_X = 360,
.MENU_TEXT_SIZE_MAX = 40,
.touchaction_list = R480320_touch_regions
#endif
#else //Amber_480x320
.Size = { 480, 320 },
.StartUpScreen_START = { 80, 60 },
.SpectrumWindow = { .x = 0, .y = 123, .w = 480, .h = 174 },
.SpectrumWindowPadding = 0,
.TUNE_FREQ = { 276, 90 },
.TUNE_SPLIT_FREQ_X = 356,
.TUNE_SPLIT_MARKER_X = 316,
.TUNE_SPLIT_FREQ_Y_TX = 102,
.TUNE_SFREQ = { 396, 60 },
.DisplayDbm = { 273, 60 },
.MEMORYLABEL = { 355, 60 },
.BAND_MODE = { 436, 90 },
.BAND_MODE_MASK = { .x = 435, .y = 89, .h = 13, .w = 33 },
.DEMOD_MODE_MASK = { .x = 186, .y = 0, .h = 13, .w = 16 },
.AGC_MASK = {.x = 122, .y = 15, .h = 13, .w = 80 },
.TUNE_STEP={.x = 205, .y = 15, .h = 13, .w = 56 },
.ENCODER_IND = { 0, 15 },
.ENCODER_MODE = MODE_VERTICAL,
.DIGMODE={.x = 122, .y = 0, .w = 63},
.LEFTBOXES_IND = { .x = 122, .y=30, .w = 69, .h = 28 },
.LEFTBOXES_MODE = MODE_HORIZONTAL,
.LEFTBOXES_ROW_2ND_OFF = 13,
.PW_IND = { .x = 205, .y = 0, .w = 56 },
.TEMP_IND = { .x = 0, .y = 0 },
.RTC_IND = { .x = 127, .y = 60 },
.LOADANDDEBUG_Y = 75,
.DEBUG_X = 0,
.LOAD_X = 440,
.PWR_NUM_IND = { 320, 99 },
.CW_DECODER_WPM = { 0, 92 },
.SNAP_CARRIER = { 27, 107 },
.TextMsgLine = { 0, 75 },
.TextMsg_buffer_max = 50,
.TextMsg_font = 0,
//.FREEDV_SNR = { 280, 28},
//.FREEDV_BER = {380, 28},
.FREEDV_SNR = { 0, 90 },
.FREEDV_BER = { 0, 102 },
.FREEDV_FONT = 4,
.SM_IND = { .x = 273, .y = 0, .h = 56, .w = 203 },
.PWR_IND = { .x = 207, .y = 60 },
#ifndef SDR_AMBER_4INCH
.BOTTOM_BAR = {.x=0,.y=308, .h=16, .w=79},//.w=74},
#else
.BOTTOM_BAR = {.x=2,.y=308, .h=16, .w=67},
#endif
.MENUSIZE = 14,
.MENU_IND = { 140, 129 },//{ 80, 130 },
.MENU_CHANGE_X = 280,
.MENU_CURSOR_X = 430,//360,
.MENU_TEXT_SIZE_MAX = 40,
.touchaction_list = R480320_touch_regions
#endif
},
//-----------------------------------------------------------------
{ //800x480
.Size = { 800, 480},
.StartUpScreen_START ={ 80, 60},
.SpectrumWindow={ .x = 0, .y = 110, .w = 480, .h = 176 },
.SpectrumWindowPadding=0,
.TUNE_FREQ= { R480320_TUNE_FREQ_X, R480320_TUNE_FREQ_Y},
.TUNE_SPLIT_FREQ_X=R480320_TUNE_SPLIT_FREQ_X,
.TUNE_SPLIT_MARKER_X=R480320_TUNE_SPLIT_MARKER_X,
.TUNE_SPLIT_FREQ_Y_TX=R480320_TUNE_SPLIT_FREQ_Y_TX,
.TUNE_SFREQ = { R480320_TUNE_SFREQ_X, R480320_TUNE_SFREQ_Y},
.DisplayDbm = { R480320_DisplayDbm_X, R480320_DisplayDbm_Y},
.MEMORYLABEL = { R480320_MEMORYLABEL_X, R480320_MEMORYLABEL_Y},
.BAND_MODE = { R480320_BAND_MODE_X, R480320_BAND_MODE_Y},
.BAND_MODE_MASK = { .x = R480320_BAND_MODE_MASK_X, .y = R480320_BAND_MODE_MASK_Y, .h = R480320_BAND_MODE_MASK_H, .w= R480320_BAND_MODE_MASK_W},
.DEMOD_MODE_MASK = { .x = R480320_DEMOD_MODE_MASK_X, .y = R480320_DEMOD_MODE_MASK_Y, .h = R480320_DEMOD_MODE_MASK_H,
.w = R480320_DEMOD_MODE_MASK_W},
.AGC_MASK = {.x = R480320_AGC_MASK_X, .y = R480320_AGC_MASK_Y, .h = R480320_AGC_MASK_H,
.w = R480320_AGC_MASK_W},
.TUNE_STEP={.x=R480320_TUNE_STEP_X, .y=R480320_TUNE_STEP_Y, .h=R480320_TUNE_STEP_MASK_H, .w=R480320_TUNE_STEP_MASK_W},
.ENCODER_IND = { R480320_ENCODER_IND_X, R480320_ENCODER_IND_Y},
.ENCODER_MODE=MODE_HORIZONTAL,
.DIGMODE={.x=R480320_DIGMODE_IND_X,.y=R480320_DIGMODE_IND_Y,.w=R480320_DIGMODE_IND_W},
.LEFTBOXES_IND = { .x=R480320_LEFTBOXES_IND_X, .y=R480320_LEFTBOXES_IND_Y, .w=R480320_LEFTBOX_WIDTH, .h=R480320_LEFTBOX_ROW_H},
.LEFTBOXES_MODE=MODE_HORIZONTAL,
.LEFTBOXES_ROW_2ND_OFF=R480320_LEFTBOX_ROW_2ND_OFF,
.PW_IND = { .x=R480320_PW_IND_X, .y=R480320_PW_IND_Y, .w=R480320_PW_IND_W},
.TEMP_IND={.x = 370,.y = 64},
.RTC_IND={.x = 415,.y = 80},
.LOADANDDEBUG_Y=96,
.DEBUG_X=0,
.LOAD_X=280,
.PWR_NUM_IND ={ 320, 96},
.CW_DECODER_WPM = { 420, 290},
.SNAP_CARRIER= { 242, 29},
.TextMsgLine = { 0, 290 },
.TextMsg_buffer_max=50,
.TextMsg_font=0,
//.FREEDV_SNR = { 280, 28},
//.FREEDV_BER = {380, 28},
.FREEDV_SNR = {410,288},
.FREEDV_BER = {410,297},
.FREEDV_FONT=4,
.SM_IND={.x = R480320_SM_IND_X, .y = R480320_SM_IND_Y, .h = R480320_SM_IND_H, .w = R480320_SM_IND_W},
.PWR_IND={ .x = 420, .y = 307},
#ifdef UI_BRD_OVI40
.BOTTOM_BAR={.x=0,.y=308, .h=16, .w=74},
#else
.BOTTOM_BAR={.x=32,.y=308, .h=16, .w=74},
#endif
.MENUSIZE=14,
.MENU_IND = { 80, 110 },
.MENU_CHANGE_X=280,
.MENU_CURSOR_X=360,
.MENU_TEXT_SIZE_MAX=40,
.touchaction_list=R480320_touch_regions
// }
},
//-----------------------------------------------------------------
{ //320x240_wide_spectrum
.Size = { 320, 240 },
.StartUpScreen_START = { 0, 10 },
.SpectrumWindow = { .x = 4, .y = 136, .w = 312, .h = 89 },//x0_w320
.SpectrumWindowPadding = 0,
.TUNE_FREQ = { 116, 109 },
.TUNE_SPLIT_FREQ_X = 196,
.TUNE_SPLIT_MARKER_X = 167,
.TUNE_SPLIT_FREQ_Y_TX = 121,
.TUNE_SFREQ = { 236, 87 },
.DisplayDbm = { 277, 56 },
#ifdef SDR_AMBER
.MEMORYLABEL= { 64, 123 } ,
#else
.MEMORYLABEL= { 157, 87 } ,
#endif
.BAND_MODE = { 276, 112 },
.BAND_MODE_MASK = { .x = 275, .y = 111, .h = 13, .w = 33 },
.DEMOD_MODE_MASK = { .x = 138, .y = 71, .h = 12, .w = 16 },
#ifndef SDR_AMBER
// .DEMOD_MODE_MASK = { .x = 113, .y = 86, .h = 13, .w = 41 },
.AGC_MASK = { .x = 74, .y = 86, .h = 13, .w = 36 },
.TUNE_STEP={ .x = 113, .y = 86, .h = 13, .w = 41 },
#else
// .DEMOD_MODE_MASK = { .x = 138, .y = 71, .h = 12, .w = 16 },
.AGC_MASK = { .x = 74, .y = 86, .h = 13, .w = 80 },
.TUNE_STEP={ .x = 157, .y = 86, .h = 13, .w = 57 },
#endif
// .TUNE_STEP={ .x = 157, .y = 86, .h = 13, .w = 57 },
.ENCODER_IND = { 0, 15 },
.ENCODER_MODE = MODE_VERTICAL,
//#ifndef SDR_AMBER
// .DIGMODE= { .x = 74, .y = 71, .w = 80 },
//#else
.DIGMODE= { .x = 74, .y = 71, .w = 63 },
//#endif
.LEFTBOXES_IND = { .x = 157, .y = 56, .w = 58, .h = 28 },
.LEFTBOXES_MODE = MODE_HORIZONTAL,
.LEFTBOXES_ROW_2ND_OFF = 13,
.PW_IND = { .x = 113, .y = 56, .w = 41 },
.TEMP_IND={ .x = 0, .y = 0 },
// .RTC_IND={ .x= 5, .y = 72 },
.RTC_IND={ .x= 5, .y = 86 },
.LOADANDDEBUG_Y = 100,
.DEBUG_X = 0,
.LOAD_X = 280,
.PWR_NUM_IND = { 1, 100 },
.CW_DECODER_WPM = { 0, 113 },
.SNAP_CARRIER = { 27, 128 },
.TextMsgLine = { 5, 99 },
.TextMsg_buffer_max = 44,
.TextMsg_font = 4,
.FREEDV_SNR = { 5, 123 },
.FREEDV_BER = { 5, 113 },
.FREEDV_FONT = 4,
.SM_IND = { .x = 113, .y = 0, .h = 52, .w = 203 },
// .PWR_IND = { .x = 16, .y = 86 },
.PWR_IND = { .x = 16, .y = 72 },
.BOTTOM_BAR = { .x = 2, .y = 231, .h = 13, .w=62 },
.MENUSIZE = 7,
.MENU_IND = { 60, 140 },
.MENU_CHANGE_X = 244,
// .MENU_CURSOR_X = 311,
.MENU_CURSOR_X = 310,
.MENU_TEXT_SIZE_MAX = 34,
.touchaction_list = R320240__touch_regions_widespectrum
}
};
disp_resolution_t disp_resolution;
#endif
@@ -0,0 +1,160 @@
/* -*- 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: ui_lcd_layouts.h **
** Description: Layout definitions header file **
** Licence: GNU GPLv3 **
** Author: Slawomir Balon/SP9BSL **
************************************************************************************/
#ifndef UI_LCD_LAYOUTS_H_
#define UI_LCD_LAYOUTS_H_
#define COL_SPECTRUM_GRAD 0x40
#define Grid RGB(COL_SPECTRUM_GRAD,COL_SPECTRUM_GRAD,COL_SPECTRUM_GRAD) // COL_SPECTRUM_GRAD = 0x40
#define WATERFALL_HEIGHT 70
#define SPECTRUM_MAX_MARKER 3
#define SPECTRUM_SCOPE_GRID_VERT_COUNT 8
#define SPECTRUM_SCOPE_GRID_HORIZ 16
//#define LEFTBOX_WIDTH 58 // used for the lower left side controls
//#define LEFTBOX_ROW_H (28)
//#define LEFTBOX_ROW_2ND_OFF (13)
#define ENC_COL_W (37)
#define ENC_ROW_H (30)
#define ENC_ROW_2ND_OFF (14)
#define Xspacing 5
#define ui_txt_msg_buffer_size 51 //this defines the buffer size for text line in maximum possible configuration.
//Please adjust it to maximum value+1 of ts.Layout->TextMsg_buffer_max
typedef enum
{
RESOLUTION_320_240,
RESOLUTION_480_320,
RESOLUTION_800_480
} disp_resolution_t;
typedef struct {
uint16_t x;
uint16_t y;
uint16_t w;
uint16_t h;
} UiArea_t;
typedef struct
{
UiArea_t region;
void (*function_short_press)();
void (*function_long_press)();
} touchaction_descr_t;
typedef struct
{
const touchaction_descr_t* actions;
int32_t size;
} touchaction_list_descr_t;
typedef struct
{
uint16_t x;
uint16_t y;
} UiCoord_t ;
typedef struct {
UiCoord_t Size; // Lcd dimension
UiCoord_t StartUpScreen_START;
UiArea_t SpectrumWindow; // Definition of spectrum window parameters
UiCoord_t TUNE_FREQ; // Frequency display control
uint16_t TUNE_SPLIT_FREQ_X; //Shift with a small split to the right to close the frequency digits
uint16_t TUNE_SPLIT_MARKER_X;
uint16_t TUNE_SPLIT_FREQ_Y_TX;
UiCoord_t TUNE_SFREQ; // Second frequency display control
UiCoord_t BAND_MODE; // Band selection control
UiArea_t BAND_MODE_MASK;
UiArea_t DEMOD_MODE_MASK; // Demodulator mode control
UiArea_t AGC_MASK; //AGC display mask
UiArea_t TUNE_STEP; // Tunning step control
UiArea_t BOTTOM_BAR; // Bottom bar
UiCoord_t ENCODER_IND; // Encoder controls indicator
uint8_t ENCODER_MODE; //horizontal/vertical draw order
UiArea_t LEFTBOXES_IND; // Lower DSP box
uint16_t LEFTBOXES_ROW_2ND_OFF;
uint8_t LEFTBOXES_MODE;
UiArea_t PW_IND; // Power level
UiArea_t DIGMODE; // Digimode item
UiArea_t SM_IND; // S meter position
UiCoord_t PWR_IND; // Supply Voltage indicator
UiCoord_t TEMP_IND; // Temperature Indicator
UiCoord_t RTC_IND; // RTC
UiCoord_t CW_DECODER_WPM;
UiCoord_t TextMsgLine; // coordinates for text line (CW decoder or freedv output)
uint16_t TextMsg_buffer_max; // Text message buffer size
uint8_t TextMsg_font;
UiCoord_t SNAP_CARRIER; // central position of variable freq marker
UiCoord_t PWR_NUM_IND; // Location of numerical FWD/REV power indicator
UiCoord_t FREEDV_SNR; //freeDV coordinates for status display
UiCoord_t FREEDV_BER;
uint16_t FREEDV_FONT;
UiCoord_t DisplayDbm;
UiCoord_t MEMORYLABEL;
uint16_t LOADANDDEBUG_Y;
uint16_t DEBUG_X;
uint16_t LOAD_X;
uint16_t SpectrumWindowPadding;
uint16_t MENUSIZE; // number of menu items per page/screen
UiCoord_t MENU_IND; // X position of description of menu item being changed
uint16_t MENU_CHANGE_X; // Position of variable being changed
uint16_t MENU_CURSOR_X; // Position of cursor used to indicate selected item
uint8_t MENU_TEXT_SIZE_MAX; // One line maximum length
const touchaction_list_descr_t* touchaction_list;
} LcdLayout;
enum MODE_{
MODE_VERTICAL=0,
MODE_HORIZONTAL
};
enum LcdLayout_{
LcdLayout_320x240=0,
LcdLayout_480x320,
LcdLayout_800x480,
LcdLayout_320x240_ws, // full wide panoram
LcdLayoutsCount //this is last position enumerated used for layout array definition. Insert new layout name before this one
};
extern const LcdLayout LcdLayouts[LcdLayoutsCount];
extern disp_resolution_t disp_resolution;
#endif /* UI_LCD_LAYOUTS_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,287 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
#ifndef __UI_SPECTRUM_H
#define __UI_SPECTRUM_H
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#include "uhsdr_board.h"
#include "uhsdr_types.h"
#include "audio_driver.h"
#include "arm_const_structs.h"
#include "ui_lcd_layouts.h"
typedef struct
{
UiArea_t full;
UiArea_t draw;
UiArea_t title;
UiArea_t scope;
UiArea_t graticule;
UiArea_t wfall;
} SpectrumAreas_t;
void UiSpectrum_Init(void);
void UiSpectrum_Clear(void);
void UiSpectrum_Redraw(void);
void UiSpectrum_WaterfallClearData(void);
void UiSpectrum_CalculateDisplayFilterBW(float32_t* width_pixel_, float32_t* left_filter_border_pos_);
void UiSpectrum_DisplayFilterBW(void);
void UiSpectrum_InitCwSnapDisplay (bool visible);
void UiSpectrum_ResetSpectrum(void);
uint16_t UiSprectrum_CheckNewGraticulePos(uint16_t new_y);
// Settings for dB/division for spectrum display
enum
{
DB_DIV_UNUSED = 0,
DB_DIV_5,
DB_DIV_7,
DB_DIV_10,
DB_DIV_15,
DB_DIV_20,
S_1_DIV,
S_2_DIV,
S_3_DIV,
SCOPE_SCALE_NUM
};
#define DB_DIV_ADJUST_MIN DB_DIV_5
#define DB_DIV_ADJUST_MAX S_3_DIV
#define DB_DIV_ADJUST_DEFAULT DB_DIV_10
// Enumeration to select which waterfall palette to use
enum
{
WFALL_GRAY = 0,
WFALL_HOT_COLD,
WFALL_RAINBOW,
WFALL_BLUE,
WFALL_GRAY_INVERSE,
WFALL_FLAME,
WFALL_SUNSET,
WFALL_MATRIX,
WFALL_COLOR_NUM
};
//
#define WATERFALL_COLOR_MIN 0
#define WATERFALL_COLOR_MAX (WFALL_COLOR_NUM-1)
#define WATERFALL_COLOR_DEFAULT WFALL_GRAY
//
#define WATERFALL_STEP_SIZE_MIN 1
#define WATERFALL_STEP_SIZE_MAX 5
#define WATERFALL_STEP_SIZE_DEFAULT 2
//
#define WATERFALL_OFFSET_MIN 60
#define WATERFALL_OFFSET_MAX 140
#define WATERFALL_OFFSET_DEFAULT 100
//
#define WATERFALL_CONTRAST_MIN 10
#define WATERFALL_CONTRAST_MAX 225
#define WATERFALL_CONTRAST_DEFAULT 120
//
#define WATERFALL_SPEED_MIN 0
#define WATERFALL_SPEED_MAX 30
#define WATERFALL_SPEED_DEFAULT 10
//
#define WATERFALL_NOSIG_ADJUST_MIN 10
#define WATERFALL_NOSIG_ADJUST_MAX 30
#define WATERFALL_NOSIG_ADJUST_DEFAULT 20
//
#define WATERFALL_SPEED_WARN 1//5
#define WATERFALL_SPEED_WARN1 3//9
//
// Constants for waterfall size settings
//
enum
{
SPECTRUM_NORMAL=0,
SPECTRUM_BIG
};
enum
{
FFT_WINDOW_RECTANGULAR=0,
FFT_WINDOW_COSINE,
FFT_WINDOW_BARTLETT,
FFT_WINDOW_WELCH,
FFT_WINDOW_HANN,
FFT_WINDOW_HAMMING,
FFT_WINDOW_BLACKMAN,
FFT_WINDOW_NUTTALL,
FFT_WINDOW_MAX
};
enum
{
Redraw_SCOPE=1,
Redraw_WATERFALL=2
};
//#define FFT_WINDOW_DEFAULT FFT_WINDOW_BLACKMAN
#define SPECTRUM_SIZE_DEFAULT SPECTRUM_NORMAL
// Spectrum scope operational constants
#define SPECTRUM_SCOPE_SPEED_MIN 0 // minimum spectrum scope speed
#define SPECTRUM_SCOPE_SPEED_MAX 30 // maximum spectrum scope speed
#define SPECTRUM_SCOPE_SPEED_DEFAULT 5
//
#define SPECTRUM_FILTER_MIN 1 // minimum filter setting
#define SPECTRUM_FILTER_MAX 20 // maximum filter setting
#define SPECTRUM_FILTER_DEFAULT 4 // default filter setting
//
#define SPECTRUM_SCOPE_AGC_MIN 1 // minimum spectrum scope AGC rate setting
#define SPECTRUM_SCOPE_AGC_MAX 50 // maximum spectrum scope AGC rate setting
#define SPECTRUM_SCOPE_AGC_DEFAULT 25 // default spectrum scope AGC rate setting
//
#define SPECTRUM_SCOPE_NOSIG_ADJUST_MIN 10
#define SPECTRUM_SCOPE_NOSIG_ADJUST_MAX 30
#define SPECTRUM_SCOPE_NOSIG_ADJUST_DEFAULT 20
#define SPECTRUM_AGC_SCALING 25 // scaling factor by which the on-screen Spec. AGC Adj. is divided for adjustment.
#define SCOPE_PREAMP_GAIN 1000//200 // amount of "amplification" in front of the FFT used for the Spectrum Scope and Waterfall used to overcome mathematical "noise floor"
#define INIT_SPEC_AGC_LEVEL -80 // Initial offset for AGC level for spectrum/waterfall display
#define NUMBER_WATERFALL_COLOURS 64 // number of colors in the waterfall table
#ifdef USE_DISP_320_240
#define WATERFALL_MAX_LINES WATERFALL_MAX_SIZE
#endif
#ifdef USE_DISP_480_320
#ifdef STM32F7
#define WATERFALL_MAX_LINES WATERFALL_HEIGHT
#endif
#ifdef STM32F4
#define WATERFALL_MAX_LINES (WATERFALL_HEIGHT/2)
#endif
#endif
// FIXME: This is a temporary hack
// this needs to be as long at the longest scope width (in case of multiple resolutions)
// list highest resolution first
#ifdef USE_DISP_480_320
#define SPECTRUM_WIDTH_MAX 480
#elif defined(USE_DISP_320_240)
#define SPECTRUM_WIDTH_MAX 480
#endif
// Spectrum display
typedef struct SpectrumDisplay
{
// Samples buffer
float32_t FFT_RingBuffer[FFT_IQ_BUFF_LEN];
float32_t FFT_Samples[FFT_IQ_BUFF_LEN];
float32_t FFT_MagData[SPEC_BUFF_LEN];
float32_t FFT_AVGData[SPEC_BUFF_LEN]; // IIR low-pass filtered FFT buffer data
uint32_t FFT_frequency; // center frequency of stored FFT
// scope pixel data
uint16_t Old_PosData[SPECTRUM_WIDTH_MAX];
// Current data ptr
uint32_t samp_ptr;
volatile bool reading_ringbuffer;
// if the user level code wants to read the ring buffer
// simply set this, and the audio driver will stop writing
// to the buffer. This means we loose some samples here but this is not a problem I would think.
// if we don't want or should do this,
// we have to add a little extra space to the ringbuffer (one audio driver sample block), which gives sufficient
// space to add data to while we are reading.
// Addresses of vertical grid lines on x axis
ushort vert_grid_id[SPECTRUM_SCOPE_GRID_VERT_COUNT-1];
uint16_t vert_grid; // distance between vert grid lines
// Addresses of horizontal grid lines on x axis
ushort horz_grid_id[16];
uint8_t upper_horiz_gridline; // how many grid lines to use
// State machine current state
uchar state;
// Init done flag
uchar enabled;
// Variables used in spectrum display AGC
uint8_t magnify; // 2^magnify == zoom factor, max is 5
uint16_t spec_len;
uint16_t fft_iq_len;
const arm_cfft_instance_f32 * cfft_instance;
float display_offset; // "vertical" offset for spectral scope, gain adjust for waterfall
float agc_rate; // this holds AGC rate for the Spectrum Display
float db_scale; // scaling factor for dB/division
ushort wfall_line_update; // used to set the number of lines per update on the waterfall
float wfall_contrast; // used to adjust the contrast of the waterfall display
uint16_t waterfall_colours[NUMBER_WATERFALL_COLOURS+1]; // palette of colors for waterfall data
// uint8_t (*waterfall)[SPECTRUM_WIDTH]; //pointer to waterfall memory
uint8_t repeatWaterfallLine; //line repeating count for waterfall size grater than number of data lines in waterfall array
// uint8_t waterfall[WATERFALL_MAX_LINES*SPECTRUM_WIDTH]; // circular buffer used for storing waterfall data - remember to increase this if the waterfall is made larger!
uint8_t waterfall[(WATERFALL_HEIGHT+10)*256]; // circular buffer used for storing waterfall data - remember to increase this if the waterfall is made larger!
uint32_t waterfall_frequencies[(WATERFALL_HEIGHT+10)]; // we reserve hopefully enough frequency stores here. We store for each line in waterfall the center frequency of it.
//uint8_t wfall_DrawDirection; //0=upward (water fountain), 1=downward (real waterfall)
uint32_t wfall_line; // pointer to current line of waterfall data
uint32_t wfall_size; // vertical size of the waterfall data (number of stored fft results)
//uint16_t wfall_disp_lines; // vertical size of the waterfall on display
uint32_t wfall_ystart;
uint32_t scope_size;
uint32_t scope_ystart;
float32_t hz_per_pixel; // how many Hertz is one pixel in the spectrum
float32_t rx_carrier_pos; // where is the current receiving frequency carrier (in pixels)
float32_t marker_offset[SPECTRUM_MAX_MARKER]; // how is the current transmitting frequency carrier offset from rx carrier (in pixels)
float32_t marker_pos[SPECTRUM_MAX_MARKER]; // where is the current transmitting frequency carrier (in pixels)
uint16_t marker_line_pos_prev[SPECTRUM_MAX_MARKER]; // previous x-axis location of carrier line in screen coordinates, 0xffff indicates off screen
uint16_t marker_num; // how many marker lines we have right now
uint16_t marker_num_prev; // how many marker lines we had last time
uint32_t scope_centre_grid_colour_active; // active colour of the spectrum scope center grid line
uint32_t scope_grid_colour_active; // active color of spectrum scope grid;
uint32_t boxes_colour; // screen boxes colour
uint32_t txtline_colour; // ticker colour
uint16_t old_left_filter_border_pos; //previous BW highlight left border
uint16_t old_right_filter_border_pos; //previous BW highlight right border
uint8_t RedrawType;
SpectrumAreas_t* Slayout;
} SpectrumDisplay;
// Spectrum display
extern SpectrumDisplay sd;
//#define MinimumScopeSize 24
#define MinimumScopeSize 46
#define MinimumWaterfallSize 16
#endif
@@ -0,0 +1,586 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
#ifndef __WATERFALL_COLOURS_H
#define __WATERFALL_COLOURS_H
// Color palattes for waterfall displays
//
// Derived with the help of: http://www.perbang.dk/rgbgradient/ (Using the "gradient maker")
//
// NOTES:
//
// - The waterfall palettes range from [0] = weakest signal to [63] for the strongest signal
//
// - The last entry [64] (the 65th) is always reserved for the vertical line color. It is included in the table as a placeholder, but its value will always be overwritten.
//
// - The LCD uses a 16 bit (5,6,5) RGB palette where there are 5 Blue, 6 Green and 5 Red bits of color resolution, produced by the macro "RGB", below
//
//
#define RGB(red,green,blue)(uint16_t)(((red>>3)<<11)|((green>>2)<<5)|(blue>> 3))
//
//
// Waterfall Gray Colors: Weak = dark, strongest = white
//
const uint16_t waterfall_grey[] =
{
RGB(0x00,0x00,0x00),
RGB(0x04,0x04,0x04),
RGB(0x08,0x08,0x08),
RGB(0x0c,0x0c,0x0c),
RGB(0x10,0x10,0x10),
RGB(0x14,0x14,0x14),
RGB(0x18,0x18,0x18),
RGB(0x1c,0x1c,0x1c),
RGB(0x20,0x20,0x20),
RGB(0x24,0x24,0x24),
RGB(0x28,0x28,0x28),
RGB(0x2c,0x2c,0x2c),
RGB(0x30,0x30,0x30),
RGB(0x34,0x34,0x34),
RGB(0x38,0x38,0x38),
RGB(0x3c,0x3c,0x3c),
RGB(0x40,0x40,0x40),
RGB(0x44,0x44,0x44),
RGB(0x48,0x48,0x48),
RGB(0x4c,0x4c,0x4c),
RGB(0x50,0x50,0x50),
RGB(0x54,0x54,0x54),
RGB(0x59,0x59,0x59),
RGB(0x5d,0x5d,0x5d),
RGB(0x61,0x61,0x61),
RGB(0x65,0x65,0x65),
RGB(0x69,0x69,0x69),
RGB(0x6d,0x6d,0x6d),
RGB(0x71,0x71,0x71),
RGB(0x75,0x75,0x75),
RGB(0x79,0x79,0x79),
RGB(0x7d,0x7d,0x7d),
RGB(0x81,0x81,0x81),
RGB(0x85,0x85,0x85),
RGB(0x89,0x89,0x89),
RGB(0x8d,0x8d,0x8d),
RGB(0x91,0x91,0x91),
RGB(0x95,0x95,0x95),
RGB(0x99,0x99,0x99),
RGB(0x9d,0x9d,0x9d),
RGB(0xa1,0xa1,0xa1),
RGB(0xa5,0xa5,0xa5),
RGB(0xa9,0xa9,0xa9),
RGB(0xae,0xae,0xae),
RGB(0xb2,0xb2,0xb2),
RGB(0xb6,0xb6,0xb6),
RGB(0xba,0xba,0xba),
RGB(0xbe,0xbe,0xbe),
RGB(0xc2,0xc2,0xc2),
RGB(0xc6,0xc6,0xc6),
RGB(0xca,0xca,0xca),
RGB(0xce,0xce,0xce),
RGB(0xd2,0xd2,0xd2),
RGB(0xd6,0xd6,0xd6),
RGB(0xda,0xda,0xda),
RGB(0xde,0xde,0xde),
RGB(0xe2,0xe2,0xe2),
RGB(0xe6,0xe6,0xe6),
RGB(0xea,0xea,0xea),
RGB(0xee,0xee,0xee),
RGB(0xf2,0xf2,0xf2),
RGB(0xf6,0xf6,0xf6),
RGB(0xfa,0xfa,0xfa),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff)
};
// Waterfall Gray Colors - inverse (weak = light, strong = dark)
//
const uint16_t waterfall_grey_inverse[] =
{
RGB(0xff,0xff,0xff),
RGB(0xfa,0xfa,0xfa),
RGB(0xf6,0xf6,0xf6),
RGB(0xf2,0xf2,0xf2),
RGB(0xee,0xee,0xee),
RGB(0xea,0xea,0xea),
RGB(0xe6,0xe6,0xe6),
RGB(0xe2,0xe2,0xe2),
RGB(0xde,0xde,0xde),
RGB(0xda,0xda,0xda),
RGB(0xd6,0xd6,0xd6),
RGB(0xd2,0xd2,0xd2),
RGB(0xce,0xce,0xce),
RGB(0xca,0xca,0xca),
RGB(0xc6,0xc6,0xc6),
RGB(0xc2,0xc2,0xc2),
RGB(0xbe,0xbe,0xbe),
RGB(0xba,0xba,0xba),
RGB(0xb6,0xb6,0xb6),
RGB(0xb2,0xb2,0xb2),
RGB(0xae,0xae,0xae),
RGB(0xa9,0xa9,0xa9),
RGB(0xa5,0xa5,0xa5),
RGB(0xa1,0xa1,0xa1),
RGB(0x9d,0x9d,0x9d),
RGB(0x99,0x99,0x99),
RGB(0x95,0x95,0x95),
RGB(0x91,0x91,0x91),
RGB(0x8d,0x8d,0x8d),
RGB(0x89,0x89,0x89),
RGB(0x85,0x85,0x85),
RGB(0x81,0x81,0x81),
RGB(0x7d,0x7d,0x7d),
RGB(0x79,0x79,0x79),
RGB(0x75,0x75,0x75),
RGB(0x71,0x71,0x71),
RGB(0x6d,0x6d,0x6d),
RGB(0x69,0x69,0x69),
RGB(0x65,0x65,0x65),
RGB(0x61,0x61,0x61),
RGB(0x5d,0x5d,0x5d),
RGB(0x59,0x59,0x59),
RGB(0x54,0x54,0x54),
RGB(0x50,0x50,0x50),
RGB(0x4c,0x4c,0x4c),
RGB(0x48,0x48,0x48),
RGB(0x44,0x44,0x44),
RGB(0x40,0x40,0x40),
RGB(0x3c,0x3c,0x3c),
RGB(0x38,0x38,0x38),
RGB(0x34,0x34,0x34),
RGB(0x30,0x30,0x30),
RGB(0x2c,0x2c,0x2c),
RGB(0x28,0x28,0x28),
RGB(0x24,0x24,0x24),
RGB(0x20,0x20,0x20),
RGB(0x1c,0x1c,0x1c),
RGB(0x18,0x18,0x18),
RGB(0x14,0x14,0x14),
RGB(0x10,0x10,0x10),
RGB(0x0c,0x0c,0x0c),
RGB(0x08,0x08,0x08),
RGB(0x04,0x04,0x04),
RGB(0x00,0x00,0x00),
RGB(0xff,0xff,0xff)
};
// This palette has weak signals as "cold" (blue) and strong signals as hot (red)
//
const uint16_t waterfall_cold_hot[] =
{
RGB(0x00,0x00,0x22), //div 4 RGB(0x00,0x02,0x8a), - make the first few colors darker/"redder"
RGB(0x01,0x00,0x23), //div 3.8 RGB(0x04,0x02,0x87),
RGB(0x02,0x00,0x25), //div 3.6 RGB(0x08,0x02,0x85),
RGB(0x04,0x00,0x27), //div 3.4 RGB(0x0c,0x02,0x83),
RGB(0x05,0x00,0x28), //div 3.2 RGB(0x10,0x02,0x81),
RGB(0x07,0x00,0x2a), //div 3.0 RGB(0x14,0x02,0x7f),
RGB(0x09,0x01,0x2d), //div 2.8 RGB(0x18,0x03,0x7d),
RGB(0x0a,0x01,0x2f), //div 2.6 RGB(0x1c,0x03,0x7b),
RGB(0x0d,0x01,0x32), //div 2.4 RGB(0x20,0x03,0x79),
RGB(0x10,0x02,0x36), //div 2.2 RGB(0x24,0x03,0x77),
RGB(0x14,0x02,0x3b), //div 2.0 RGB(0x28,0x03,0x75),
RGB(0x18,0x02,0x40), //div 1.8 RGB(0x2c,0x04,0x73),
RGB(0x1e,0x02,0x47), //div 1.6 RGB(0x30,0x04,0x71),
RGB(0x25,0x02,0x4f), //div 1.4 RGB(0x34,0x04,0x6f),
RGB(0x2f,0x03,0x5b), //div 1.2 RGB(0x38,0x04,0x6d),
RGB(0x3c,0x04,0x6b),
RGB(0x40,0x05,0x69),
RGB(0x44,0x05,0x67),
RGB(0x48,0x05,0x65),
RGB(0x4c,0x05,0x63),
RGB(0x50,0x05,0x61),
RGB(0x55,0x06,0x5f),
RGB(0x59,0x06,0x5d),
RGB(0x5d,0x06,0x5b),
RGB(0x61,0x06,0x59),
RGB(0x65,0x06,0x57),
RGB(0x69,0x06,0x55),
RGB(0x6d,0x07,0x53),
RGB(0x71,0x07,0x51),
RGB(0x75,0x07,0x4f),
RGB(0x79,0x07,0x4d),
RGB(0x7d,0x07,0x4b),
RGB(0x81,0x08,0x48),
RGB(0x85,0x08,0x46),
RGB(0x89,0x08,0x44),
RGB(0x8d,0x08,0x42),
RGB(0x91,0x08,0x40),
RGB(0x95,0x09,0x3d),
RGB(0x99,0x09,0x3c),
RGB(0x9d,0x09,0x3a),
RGB(0xa1,0x09,0x38),
RGB(0xa5,0x09,0x36),
RGB(0xaa,0x0a,0x34),
RGB(0xae,0x0a,0x32),
RGB(0xb2,0x0a,0x30),
RGB(0xb6,0x0a,0x2e),
RGB(0xba,0x0a,0x2c),
RGB(0xbe,0x0a,0x2a),
RGB(0xc2,0x0b,0x28),
RGB(0xc6,0x0b,0x26),
RGB(0xca,0x0b,0x24),
RGB(0xce,0x0b,0x22),
RGB(0xd2,0x0b,0x20),
RGB(0xd6,0x0c,0x1e),
RGB(0xda,0x0c,0x1c),
RGB(0xde,0x0c,0x1a),
RGB(0xe2,0x0c,0x18),
RGB(0xe6,0x0c,0x16),
RGB(0xea,0x0d,0x14),
RGB(0xee,0x0d,0x12),
RGB(0xf2,0x0d,0x10),
RGB(0xf6,0x0d,0x0e),
RGB(0xfa,0x0d,0x0c),
RGB(0xff,0x0d,0x0a),
RGB(0xff,0xff,0xff),
};
//
// Waterfall Blue Colors: Weak = dark, strongest = white
//
const uint16_t waterfall_blue[] =
{
RGB(0x00,0x00,0x2e),
RGB(0x02,0x02,0x31),
RGB(0x05,0x05,0x34),
RGB(0x07,0x08,0x37),
RGB(0x0a,0x0b,0x3b),
RGB(0x0c,0x0d,0x3e),
RGB(0x0f,0x10,0x41),
RGB(0x12,0x13,0x45),
RGB(0x14,0x16,0x48),
RGB(0x17,0x19,0x4b),
RGB(0x19,0x1b,0x4f),
RGB(0x1c,0x1e,0x52),
RGB(0x1f,0x21,0x55),
RGB(0x21,0x24,0x59),
RGB(0x24,0x27,0x5c),
RGB(0x26,0x29,0x5f),
RGB(0x29,0x2c,0x63),
RGB(0x2b,0x2f,0x66),
RGB(0x2e,0x32,0x69),
RGB(0x31,0x35,0x6d),
RGB(0x33,0x37,0x70),
RGB(0x36,0x3a,0x73),
RGB(0x38,0x3d,0x76),
RGB(0x3b,0x40,0x7a),
RGB(0x3e,0x43,0x7d),
RGB(0x40,0x45,0x80),
RGB(0x43,0x48,0x84),
RGB(0x45,0x4b,0x87),
RGB(0x48,0x4e,0x8a),
RGB(0x4b,0x51,0x8e),
RGB(0x4d,0x53,0x91),
RGB(0x50,0x56,0x94),
RGB(0x52,0x59,0x98),
RGB(0x55,0x5c,0x9b),
RGB(0x57,0x5e,0x9e),
RGB(0x5a,0x61,0xa2),
RGB(0x5d,0x64,0xa5),
RGB(0x5f,0x67,0xa8),
RGB(0x62,0x6a,0xac),
RGB(0x64,0x6c,0xaf),
RGB(0x67,0x6f,0xb2),
RGB(0x6a,0x72,0xb6),
RGB(0x6c,0x75,0xb9),
RGB(0x6f,0x78,0xbc),
RGB(0x71,0x7a,0xbf),
RGB(0x74,0x7d,0xc3),
RGB(0x77,0x80,0xc6),
RGB(0x79,0x83,0xc9),
RGB(0x7c,0x86,0xcd),
RGB(0x7e,0x88,0xd0),
RGB(0x81,0x8d,0xd3),
RGB(0x83,0x8e,0xd7),
RGB(0x86,0x91,0xda),
RGB(0x89,0x94,0xdd),
RGB(0x8b,0x96,0xe1),
RGB(0x8e,0x99,0xe4),
RGB(0x90,0x9c,0xe7),
RGB(0x93,0x9f,0xeb),
RGB(0x96,0xa2,0xee),
RGB(0x98,0xa4,0xf1),
RGB(0x9b,0xa7,0xf5),
RGB(0x9d,0xda,0xf8),
RGB(0xa0,0xdf,0xfb),
RGB(0xa3,0xe5,0xff),
RGB(0xff,0xff,0xff)
};
const uint16_t waterfall_rainbow[] =
{
RGB(0x00,0x00,0x0b), //div 4.0 RGB(0x00,0x01,0x2d), // Make the first few colors "bluer"
RGB(0x00,0x01,0x0d), //div 3.8 RGB(0x00,0x04,0x30),
RGB(0x00,0x02,0x0e), //div 3.6 RGB(0x00,0x07,0x33),
RGB(0x00,0x03,0x10), //div 3.4 RGB(0x00,0x0b,0x37),
RGB(0x00,0x05,0x12), //div 3.2 RGB(0x00,0x10,0x3a),
RGB(0x00,0x07,0x14), //div 3.0 RGB(0x00,0x14,0x3d),
RGB(0x00,0x09,0x1b), //div 2.8 RGB(0x00,0x1a,0x4a),
RGB(0x00,0x0c,0x1a), //div 2.6 RGB(0x00,0x1f,0x44),
RGB(0x00,0x0f,0x1e), //div 2.4 RGB(0x00,0x25,0x47),
RGB(0x00,0x14,0x22), //div 2.2 RGB(0x00,0x2c,0x4b),
RGB(0x00,0x1a,0x27), //div 2.0 RGB(0x00,0x33,0x4e),
RGB(0x00,0x20,0x2d), //div 1.8 RGB(0x00,0x3a,0x51),
RGB(0x00,0x29,0x35), //div 1.6 RGB(0x00,0x42,0x54),
RGB(0x00,0x35,0x3f), //div 1.4 RGB(0x00,0x4a,0x58),
RGB(0x00,0x44,0x4c), //div 1.2 RGB(0x00,0x52,0x5b),
RGB(0x00,0x5b,0x5e),
RGB(0x00,0x62,0x5f),
RGB(0x01,0x65,0x5c),
RGB(0x01,0x68,0x59),
RGB(0x01,0x6c,0x55),
RGB(0x01,0x6f,0x50),
RGB(0x01,0x72,0x4c),
RGB(0x01,0x76,0x46),
RGB(0x01,0x79,0x41),
RGB(0x01,0x7c,0x3b),
RGB(0x01,0x80,0x35),
RGB(0x02,0x83,0x2e),
RGB(0x02,0x87,0x27),
RGB(0x02,0x8a,0x1f),
RGB(0x02,0x8d,0x18),
RGB(0x02,0x91,0x0f),
RGB(0x02,0x94,0x07),
RGB(0x08,0x97,0x03),
RGB(0x11,0x9b,0x03),
RGB(0x1c,0x9e,0x03),
RGB(0x26,0xa1,0x03),
RGB(0x31,0xa4,0x03),
RGB(0x3d,0xa8,0x03),
RGB(0x49,0xab,0x04),
RGB(0x55,0xaf,0x04),
RGB(0x61,0xb2,0x04),
RGB(0x6e,0xb5,0x04),
RGB(0x7c,0xb8,0x04),
RGB(0x8a,0xbc,0x05),
RGB(0x98,0xbf,0x05),
RGB(0xa6,0xc3,0x05),
RGB(0xb5,0xc6,0x05),
RGB(0xc5,0xc9,0x05),
RGB(0xcc,0xc4,0x06),
RGB(0xd0,0xbb,0x06),
RGB(0xd3,0xb1,0x06),
RGB(0xd7,0xa7,0x06),
RGB(0xda,0x9c,0x07),
RGB(0xdd,0x91,0x07),
RGB(0xe0,0x86,0x07),
RGB(0xe4,0x7a,0x07),
RGB(0xe7,0x6e,0x08),
RGB(0xeb,0x61,0x08),
RGB(0xee,0x54,0x08),
RGB(0xf1,0x47,0x08),
RGB(0xf4,0x39,0x09),
RGB(0xf8,0x2b,0x09),
RGB(0xfb,0x1c,0x09),
RGB(0xff,0x0e,0x09),
RGB(0xff,0xff,0xff),
};
//
// Waterfall Flame: Weak = dark blue -> light blue -> red -> yellow, strongest = white
//
const uint16_t waterfall_flame[] =
{
RGB(0x00,0x00,0x22),
RGB(0x01,0x00,0x23),
RGB(0x02,0x00,0x25),
RGB(0x04,0x00,0x27),
RGB(0x05,0x00,0x28),
RGB(0x07,0x00,0x2a),
RGB(0x09,0x01,0x2d),
RGB(0x0a,0x01,0x2f),
RGB(0x0d,0x01,0x32),
RGB(0x10,0x02,0x36),
RGB(0x14,0x02,0x3b),
RGB(0x18,0x02,0x40),
RGB(0x3f,0x00,0x00),
RGB(0x4d,0x00,0x00),
RGB(0x3f,0x00,0x00),
RGB(0x5a,0x00,0x00),
RGB(0x64,0x00,0x00),
RGB(0x6e,0x00,0x00),
RGB(0x78,0x00,0x00),
RGB(0x82,0x00,0x00),
RGB(0x97,0x00,0x00),
RGB(0xa1,0x00,0x00),
RGB(0xab,0x00,0x00),
RGB(0xb7,0x00,0x00),
RGB(0xc2,0x00,0x00),
RGB(0xcd,0x00,0x00),
RGB(0xd9,0x00,0x00),
RGB(0xe4,0x00,0x00),
RGB(0xef,0x00,0x00),
RGB(0xfa,0x00,0x00),
RGB(0xfa,0x18,0x00),
RGB(0xfa,0x2b,0x00),
RGB(0xfa,0x3c,0x00),
RGB(0xfa,0x4b,0x00),
RGB(0xfa,0x57,0x00),
RGB(0xfa,0x62,0x00),
RGB(0xfa,0x6d,0x00),
RGB(0xfa,0x76,0x00),
RGB(0xfa,0x7e,0x00),
RGB(0xfa,0x86,0x00),
RGB(0xfa,0x8d,0x00),
RGB(0xfa,0x94,0x00),
RGB(0xfa,0x9b,0x00),
RGB(0xfa,0xa1,0x00),
RGB(0xfa,0xa7,0x00),
RGB(0xfa,0xac,0x00),
RGB(0xfa,0xb2,0x00),
RGB(0xfa,0xb7,0x00),
RGB(0xfa,0xbe,0x00),
RGB(0xfa,0xc5,0x00),
RGB(0xfa,0xcb,0x00),
RGB(0xfa,0xd2,0x00),
RGB(0xfa,0xd8,0x00),
RGB(0xfa,0xdf,0x00),
RGB(0xfa,0xe6,0x00),
RGB(0xfa,0xee,0x00),
RGB(0xfa,0xf7,0x00),
RGB(0xfa,0xfa,0x2d),
RGB(0xfa,0xf8,0x51),
RGB(0xfa,0xf8,0x76),
RGB(0xfa,0xf8,0x9a),
RGB(0xfa,0xfa,0xbf),
RGB(0xfa,0xfa,0xe1),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff)
};
//
// Waterfall Sunset: sunset colours
//
const uint16_t waterfall_sunset[] =
{
RGB(0x00,0x00,0x00),
RGB(0x00,0x02,0x0f),
RGB(0x00,0x03,0x1f),
RGB(0x00,0x05,0x2f),
RGB(0x00,0x06,0x3e),
RGB(0x00,0x09,0x4e),
RGB(0x00,0x0a,0x5e),
RGB(0x00,0x0c,0x6d),
RGB(0x00,0x0d,0x7d),
RGB(0x00,0x0f,0x8c),
RGB(0x00,0x11,0x9d),
RGB(0x00,0x13,0xae),
RGB(0x00,0x15,0xbf),
RGB(0x00,0x16,0xd0),
RGB(0x00,0x18,0xe0),
RGB(0x00,0x1a,0xf1),
RGB(0x03,0x1c,0xfc),
RGB(0x14,0x1a,0xec),
RGB(0x24,0x18,0xdb),
RGB(0x34,0x16,0xca),
RGB(0x45,0x15,0xba),
RGB(0x56,0x12,0xa9),
RGB(0x66,0x11,0x99),
RGB(0x77,0x0e,0x87),
RGB(0x88,0x0d,0x77),
RGB(0x98,0x0c,0x67),
RGB(0xa8,0x0a,0x57),
RGB(0xb9,0x08,0x47),
RGB(0xc8,0x06,0x36),
RGB(0xd9,0x04,0x26),
RGB(0xe9,0x03,0x15),
RGB(0xfa,0x01,0x06),
RGB(0xff,0x06,0x00),
RGB(0xff,0x16,0x00),
RGB(0xff,0x26,0x00),
RGB(0xff,0x35,0x00),
RGB(0xff,0x45,0x00),
RGB(0xff,0x53,0x00),
RGB(0xff,0x63,0x00),
RGB(0xff,0x72,0x00),
RGB(0xff,0x81,0x00),
RGB(0xff,0x90,0x00),
RGB(0xff,0x9f,0x00),
RGB(0xff,0xad,0x00),
RGB(0xff,0xbc,0x00),
RGB(0xff,0xca,0x00),
RGB(0xff,0xd9,0x00),
RGB(0xff,0xe7,0x00),
RGB(0xff,0xf3,0x05),
RGB(0xff,0xf3,0x14),
RGB(0xff,0xf4,0x24),
RGB(0xff,0xf5,0x34),
RGB(0xff,0xf5,0x43),
RGB(0xff,0xf6,0x53),
RGB(0xff,0xf7,0x63),
RGB(0xff,0xf7,0x73),
RGB(0xff,0xf9,0x83),
RGB(0xff,0xf9,0x95),
RGB(0xff,0xfa,0xa6),
RGB(0xff,0xfb,0xb8),
RGB(0xff,0xfc,0xca),
RGB(0xff,0xfd,0xdc),
RGB(0xff,0xfe,0xed),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff)
};
//
// Waterfall Matrix: black-green-white
//
const uint16_t waterfall_matrix[] =
{
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x00,0x00,0x00),
RGB(0x0f,0x66,0x01),
RGB(0x0f,0x66,0x01),
RGB(0x0f,0x66,0x01),
RGB(0x0f,0x66,0x01),
RGB(0x14,0x86,0x01),
RGB(0x14,0x86,0x01),
RGB(0x14,0x86,0x01),
RGB(0x14,0x86,0x01),
RGB(0x19,0xa7,0x01),
RGB(0x19,0xa7,0x01),
RGB(0x19,0xa7,0x01),
RGB(0x19,0xa7,0x01),
RGB(0x21,0xc3,0x07),
RGB(0x21,0xc3,0x07),
RGB(0x21,0xc3,0x07),
RGB(0x21,0xc3,0x07),
RGB(0x30,0xdd,0x13),
RGB(0x30,0xdd,0x13),
RGB(0x30,0xdd,0x13),
RGB(0x30,0xdd,0x13),
RGB(0x45,0xf0,0x29),
RGB(0x45,0xf0,0x29),
RGB(0x45,0xf0,0x29),
RGB(0x45,0xf0,0x29),
RGB(0xa0,0xfd,0x91),
RGB(0xa0,0xfd,0x91),
RGB(0xa0,0xfd,0x91),
RGB(0xa0,0xfd,0x91),
RGB(0xb3,0xfe,0xa6),
RGB(0xb3,0xfe,0xa6),
RGB(0xb3,0xfe,0xa6),
RGB(0xb3,0xfe,0xa6),
RGB(0xc3,0xfe,0xb9),
RGB(0xc3,0xfe,0xb9),
RGB(0xc3,0xfe,0xb9),
RGB(0xc3,0xfe,0xb9),
RGB(0xd3,0xfe,0xcc),
RGB(0xd3,0xfe,0xcc),
RGB(0xd3,0xfe,0xcc),
RGB(0xd3,0xfe,0xcc),
RGB(0xdf,0xfe,0xda),
RGB(0xdf,0xfe,0xda),
RGB(0xdf,0xfe,0xda),
RGB(0xdf,0xfe,0xda),
RGB(0xef,0xfd,0xec),
RGB(0xef,0xfd,0xec),
RGB(0xef,0xfd,0xec),
RGB(0xef,0xfd,0xec),
RGB(0xef,0xfd,0xec),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff),
RGB(0xff,0xff,0xff)
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,101 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** mcHF QRP Transceiver **
** K Atanassov - M0NKA 2014 **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#ifndef __UI_MENU_H
#define __UI_MENU_H
#include "uhsdr_board.h"
//
// Exports
//
void UiMenu_MapColors(uint32_t color ,char* options,volatile uint32_t* clr_ptr);
// The supported mode values
typedef enum
{
MENU_RENDER_ONLY = 0, // no value change
MENU_PROCESS_VALUE_CHANGE, // user value change permitted
MENU_PROCESS_VALUE_SETDEFAULT, // set value to default, no user change
} MenuProcessingMode_t;
void UiMenu_RenderMenu(MenuProcessingMode_t mode);
void UiMenu_RenderChangeItemValue(int16_t pot_diff);
void UiMenu_RenderChangeItem(int16_t pot_diff);
void UiMenu_RenderLastScreen(void);
void UiMenu_RenderFirstScreen(void);
bool UiMenu_RenderNextScreen(void); // returns true if screen was changed, i.e. not last screen
bool UiMenu_RenderPrevScreen(void); // returns true if screen was changed, i.e. not first screen
enum MENU_INFO_ITEM
{
INFO_EEPROM,
INFO_DISPLAY,
INFO_DISPLAY_CTRL,
#ifdef USE_OSC_SI570
INFO_SI570,
#endif
INFO_OSC_NAME,
INFO_TP,
INFO_RFBOARD,
INFO_CPU,
INFO_FLASH,
INFO_RAM,
INFO_FW_VERSION,
INFO_BL_VERSION,
INFO_BUILD,
INFO_RTC,
INFO_VBAT,
INFO_LICENCE,
INFO_HWLICENCE,
INFO_CODEC,
INFO_CODEC_TWINPEAKS,
INFO_AMBER_IO8,
INFO_AMBER_IO4,
INFO_AMBER_DAC_PWR_TX,
};
const char* UiMenu_GetSystemInfo(uint32_t* m_clr_ptr, int info_item);
#define MAX_MENUSIZE 14 //memory allocation of displayed menuitems at once, must be higher or equal to highest ts.Layout->MENUSIZE
/*
#ifdef USE_DISP_480_320
//
#define MENUSIZE 14 // number of menu items per page/screen
//
// Starting position of configuration menu
//
#define POS_MENU_IND_X 80 // X position of description of menu item being changed
#define POS_MENU_IND_Y 110 // Y position of first (top) item being changed
#define POS_MENU_CHANGE_X 280 // Position of variable being changed
#define POS_MENU_CURSOR_X 360 // Position of cursor used to indicate selected item
#else
//
#define MENUSIZE 6 // number of menu items per page/screen
//
// Starting position of configuration menu
//
#define POS_MENU_IND_X 60 // X position of description of menu item being changed
#define POS_MENU_IND_Y 128 // Y position of first (top) item being changed
#define POS_MENU_CHANGE_X 244 // Position of variable being changed
#define POS_MENU_CURSOR_X 311 // Position of cursor used to indicate selected item
#endif
*/
#endif //__UI_MENU_H
@@ -0,0 +1,777 @@
/*
* ui_menu_internal.c
*
* Created on: 24.12.2016
* Author: danilo
*/
#include "ui_menu.h"
#include "ui_menu_internal.h"
#include "ui_lcd_hy28.h" // for colors!
#include <stdio.h>
// we show MENUSIZE items at the same time to the user.
// right now the render code uses this global variable since
// only a single active menu is supported right now.
//Because of dynamic resolution change we have to declare the maximum amount of items displayed at once for the highest option
MenuDisplaySlot menu[MAX_MENUSIZE];
bool init_done = false;
// actions [this is an internal, not necessarily complete or accurate sketch of the used algorithms /API
// read the source to find out how it is done. Left for the purpose of explaining the basic idea
// show menu -> was previously displayed -> yes -> simply display all slots
// -> no -> get first menu group, get first entry, fill first slot, run get next entry until all slots are filled
// find next MenuEntry -> is menu group -> yes -> is unfolded -> yes -> get first item from menu group
// -> no -> treat as normal menu entry
// -> is there one more entry in my menu group ? -> yes -> takes this one
// -> no -> go one level up -> get next entry in this group
// -> there is no such entry -> fill with dummy entry
// find prev MenuEntry -> there is prev entry in menu group -> yes -> is this unfolded menu group -> yes -> get last entry of this menu group
// -> no -> fill slot with entry
// -> no -> go one level up -> get prev entry of this level
// unfold menu group -> mark as unfold, run get next entry until all menu display slots are filled
// fold menu group -> mark as fold, run get next entry until all menu display slots are filled
// move to next/previous page -> (this is n times prev/next)
// ===================== BEGIN MENU LOW LEVEL MANAGEMENT =====================
const MenuGroupDescriptor* UiMenu_GetParentGroupForEntry(const MenuDescriptor* me)
{
return me==NULL?NULL:&groups[me->menuId];
}
const MenuGroupDescriptor* UiMenu_GetGroupForGroupEntry(const MenuDescriptor* me)
{
return me==NULL?NULL:&groups[me->number];
}
//inline bool UiMenu_IsEnabled(const MenuDescriptor *entry)
bool UiMenu_IsEnabled(const MenuDescriptor *entry)
{
return entry==NULL?false:(entry->enabled != NULL?*entry->enabled:true);
}
inline bool UiMenu_IsGroup(const MenuDescriptor *entry)
{
return entry==NULL?false:entry->kind == MENU_GROUP;
}
inline bool UiMenu_IsItem(const MenuDescriptor *entry)
{
return entry==NULL?false:entry->kind == MENU_ITEM;
}
inline bool UiMenu_IsInfo(const MenuDescriptor *entry)
{
return entry==NULL?false:entry->kind == MENU_INFO;
}
inline bool UiMenu_SlotIsEmpty(MenuDisplaySlot* slot)
{
return slot==NULL?false:slot->entryItem == NULL;
}
inline bool UiMenu_GroupIsUnfolded(const MenuDescriptor *group)
{
return group==NULL?false:groups[group->number].state->unfolded;
}
inline uint16_t UiMenu_MenuGroupMemberCount(const MenuGroupDescriptor* gd)
{
uint16_t retval = 0;
if (gd != NULL)
{
if (gd->state->count == 0)
{
const MenuDescriptor* entry;
for (entry = gd->entries; entry->kind != MENU_STOP; entry++)
{
gd->state->count++;
}
}
retval = gd->state->count;
}
return retval;
}
inline void UiMenu_GroupFold(const MenuDescriptor* entry, bool fold)
{
if (UiMenu_IsGroup(entry))
{
groups[entry->number].state->unfolded = fold == false;
}
}
inline const MenuDescriptor* UiMenu_GroupGetLast(const MenuGroupDescriptor *group)
{
const MenuDescriptor* retval = NULL;
uint16_t count = UiMenu_MenuGroupMemberCount(group);
if (count>0)
{
retval = &(group->entries[count-1]);
}
return retval;
}
inline const MenuDescriptor* UiMenu_GroupGetFirst(const MenuGroupDescriptor *group)
{
const MenuDescriptor* retval = NULL;
uint16_t count = UiMenu_MenuGroupMemberCount(group);
if (count>0)
{
retval = group->entries;
}
return retval;
}
const MenuDescriptor* UiMenu_GetNextEntryInGroup(const MenuDescriptor* me)
{
const MenuDescriptor* retval = NULL;
if (me != NULL)
{
const MenuGroupDescriptor* group_ptr = UiMenu_GetParentGroupForEntry(me);
for (const MenuDescriptor* nxt = me + 1; UiMenu_GroupGetLast(group_ptr)>= nxt; nxt++)
{
if (UiMenu_IsEnabled(nxt))
{
retval = nxt;
break;
}
}
}
return retval;
}
const MenuDescriptor* UiMenu_GetPrevEntryInGroup(const MenuDescriptor* me)
{
const MenuGroupDescriptor* group_ptr = UiMenu_GetParentGroupForEntry(me);
const MenuDescriptor* retval = NULL;
if (me != NULL && me != &group_ptr->entries[0])
{
for (const MenuDescriptor* prv = me - 1; prv >= &group_ptr->entries[0]; prv--)
{
if (UiMenu_IsEnabled(prv))
{
retval = prv;
break;
}
}
}
return retval;
}
const MenuDescriptor* UiMenu_GetParentForEntry(const MenuDescriptor* me)
{
const MenuDescriptor* retval = NULL;
if (me != NULL)
{
const MenuGroupDescriptor* gd = UiMenu_GetParentGroupForEntry(me);
if (gd->parent != NULL)
{
if (gd->state->me == NULL )
{
const MenuGroupDescriptor* gdp = &groups[gd->parent->menuId];
uint16_t count = UiMenu_MenuGroupMemberCount(gdp);
uint16_t idx;
for(idx = 0; idx < count; idx++)
{
if ((gdp->entries[idx].kind == MENU_GROUP) && (gdp->entries[idx].number == me->menuId))
{
gd->state->me = &gdp->entries[idx];
break;
}
}
}
retval = gd->state->me;
}
}
return retval;
}
/*
* @returns true if this is the last ACTIVE entry in the menu group
*/
inline bool UiMenu_IsLastActiveItemInMenuGroup(const MenuDescriptor* here)
{
const MenuGroupDescriptor* gd = UiMenu_GetParentGroupForEntry(here);
const MenuDescriptor* lastActive = UiMenu_GroupGetLast(gd);
for (; lastActive != NULL && UiMenu_IsEnabled(lastActive) == false && lastActive != here; lastActive = UiMenu_GetPrevEntryInGroup(lastActive) )
{
// we need to do nothing here
}
return lastActive == here;
}
inline bool UiMenu_IsFirstInMenuGroup(const MenuDescriptor* here)
{
const MenuGroupDescriptor* gd = UiMenu_GetParentGroupForEntry(here);
return UiMenu_GroupGetFirst(gd) == here;
}
// ===================== END MENU LOW LEVEL MANAGEMENT =====================
// ===================== BEGIN MENU ITERATION STRATEGY =====================
// this code implements a specific strategy to walk through a menu structure
// Helper Functions
const MenuDescriptor* UiMenu_FindNextEntryInUpperLevel(const MenuDescriptor* here)
{
const MenuDescriptor* next = NULL, *focus = here;
if (here != NULL)
{
while(focus != NULL && next == NULL)
{
// we have a parent group, we are member of a sub menu group,
// we need next entry in containing menu group, no matter if our menu group is folded or not
next = UiMenu_GetNextEntryInGroup(UiMenu_GetParentForEntry(focus));
if (next == NULL)
{
focus = UiMenu_GetParentForEntry(focus);
}
}
}
return next;
}
const MenuDescriptor* UiMenu_FindLastEntryInLowerLevel(const MenuDescriptor* here)
{
const MenuDescriptor *last = here;
while (UiMenu_IsGroup(here) && UiMenu_GroupIsUnfolded(here) && here == last)
{
const MenuDescriptor* last = UiMenu_GroupGetLast(UiMenu_GetGroupForGroupEntry(here));
if (last)
{
here = last;
}
}
return here;
}
// Main Strategy Functions
/*
* Strategy: Provide a 'virtual' flat list of menu entries, list members are dynamically inserted/removed if menu groups are (un)folded.
* External code navigates through only with next/prev operations.
*
*/
/*
* @brief Get next menu entry. If a menu group is unfolded, next entry after menu group item is first item from menu group
*
*/
const MenuDescriptor* UiMenu_NextMenuEntry(const MenuDescriptor* here)
{
const MenuDescriptor* next = NULL;
if (here != NULL)
{
if (UiMenu_IsGroup(here))
{
// is group entry
if (UiMenu_GroupIsUnfolded(here))
{
const MenuGroupDescriptor* group = &groups[here->number];
next = UiMenu_GroupGetFirst(group);
if (next == NULL)
{
// this is an empty menu group, should not happen, does make sense
// but we handle this anyway
next = UiMenu_FindNextEntryInUpperLevel(here);
}
}
else
{
// folded group, so we behave like a normal entry
next = UiMenu_GetNextEntryInGroup(here);
}
}
if (next == NULL)
{
// we are currently at a normal entry or a folded group or empty group (in this case these are treated as simple entries)
// only 3 cases possible:
// - final entry of menu, fill next slot with blank entry, return false
// - next entry is normal entry (group or entry, no difference), just use this one
// - last entry in menu group, go up, and search for next entry in this parent menu (recursively).
if (UiMenu_IsLastActiveItemInMenuGroup(here))
{
// we need the parent menu in order to ask for the entry after our
// menu group entry
// if we cannot find the parent group, we are top level and the last menu entry
// so there is no further entry
next = UiMenu_FindNextEntryInUpperLevel(here);
}
else
{
next = UiMenu_GetNextEntryInGroup(here);
}
}
}
return next;
}
/*
* @brief Get previous menu entry. If on first item of a menu group, show the last entry of the previous menu group/menu item
*
*/
const MenuDescriptor* UiMenu_PrevMenuEntry(const MenuDescriptor* here)
{
const MenuDescriptor* prev = NULL;
if (here != NULL)
{
if (UiMenu_IsFirstInMenuGroup(here))
{
// we go up, get previous entry
// if first entry, go one further level up, ...
// if not first entry -> get prev entry
// if normal entry or folded menu -> we are done
// if unfolded menu_entry -> go to last entry
// -> if normal entry or folded menu -> we are done
// -> if unfolded menu entry -> go to last entry
prev = UiMenu_GetParentForEntry(here);
}
else
{
prev = UiMenu_GetPrevEntryInGroup(here);
if (UiMenu_IsGroup(prev) && UiMenu_GroupIsUnfolded(prev))
{
prev = UiMenu_FindLastEntryInLowerLevel(prev);
}
}
}
return prev;
}
bool UiMenu_FillSlotWithEntry(MenuDisplaySlot* here, const MenuDescriptor* entry)
{
bool retval = false;
if (entry != NULL)
{
here->entryItem = entry;
retval = true;
}
else
{
here->entryItem = NULL;
}
return retval;
}
// DISPLAY SPECIFIC CODE BEGIN
void UiMenu_DisplayValue(const char* value,uint32_t clr,uint16_t pos)
{
UiLcdHy28_PrintTextRight(ts.Layout->MENU_CURSOR_X - 4, ts.Layout->MENU_IND.y + (pos * 12), value, clr, Black, 0); // yes, normal position
}
static void UiMenu_DisplayLabel(const char* label,uint32_t clr,uint16_t pos)
{
UiLcdHy28_PrintText(ts.Layout->MENU_IND.x, ts.Layout->MENU_IND.y + (12*(pos)),label,clr,Black,0);
}
static void UiMenu_DisplayCursor(const char* label,uint32_t clr,uint16_t pos)
{
UiLcdHy28_PrintText(ts.Layout->MENU_CURSOR_X, ts.Layout->MENU_IND.y + (12*(pos)),label,clr,Black,0);
}
// DISPLAY SPECIFIC CODE END
void UiMenu_MoveCursor(uint32_t newpos)
{
static uint32_t oldpos = 999; // y position of option cursor, previous
if(oldpos != 999) // was the position of a previous cursor stored?
{
UiMenu_DisplayCursor(" ", Green, oldpos);
}
oldpos = newpos; // save position of new "old" cursor position
if (newpos != 999)
{
UiMenu_DisplayCursor("<", Green, newpos);
}
}
static void UiMenu_UpdateHWInfoLines(uchar index, MenuProcessingMode_t mode, int pos)
{
uint32_t m_clr;
const char* outs = UiMenu_GetSystemInfo(&m_clr, index);
UiMenu_DisplayValue(outs,m_clr,pos);
}
/**
* @brief Display and and change line items
* @param select item to display/change
* @param mode 0=display/update 1=change item 3=set default
* @param pos (0-5) use this line as position
*/
static void UiMenu_UpdateLines(uint16_t select, MenuProcessingMode_t mode, int pos)
{
char options[32];
const char* txt_ptr = NULL; // if filled, we use this string for display, otherwise options
uint32_t clr = White; // color used it display of adjusted options
int var; // holder for the menu item value change
if(mode == MENU_RENDER_ONLY) // are we in update/display mode?
{
var = 0; // prevent any change of variable
}
else // this is "change" mode
{
var = ts.menu_var; // change from encoder
ts.menu_var = 0; // clear encoder change detect
}
strcpy(options, "ERROR"); // pre-load to catch error condition
UiMenu_UpdateItem(select, mode, pos, var, options,&txt_ptr , &clr);
if (txt_ptr == NULL)
{
txt_ptr = options;
}
UiMenu_DisplayValue(txt_ptr,clr,pos);
if(mode == MENU_PROCESS_VALUE_CHANGE) // Shifted over
{
UiMenu_MoveCursor(pos);
}
return;
}
/*
* Render a menu entry on a given menu position
*/
void UiMenu_UpdateMenuEntry(const MenuDescriptor* entry, MenuProcessingMode_t mode, uint8_t pos)
{
uint32_t m_clr;
m_clr = Yellow;
char out[40];
char blank[40] = " ";
blank[ts.Layout->MENU_TEXT_SIZE_MAX-1]=0;
//#else
// const char blank[34] = " ";
//#endif
if (entry != NULL && (entry->kind == MENU_ITEM || entry->kind == MENU_GROUP || entry->kind == MENU_INFO || entry->kind == MENU_TEXT) )
{
if (mode == MENU_RENDER_ONLY)
{
uint16_t level = 0;
const MenuDescriptor* parent = entry;
do
{
parent = UiMenu_GetParentForEntry(parent);
level++;
}
while (parent != NULL);
level--;
// level = 3;
// uint16_t labellen = strlen(entry->id)+strlen(entry->label) + 1;
uint16_t labellen = level+strlen(entry->label);
// snprintf(out,34,"%s-%s%s",entry->id,entry->label,(&blank[labellen>33?33:labellen]));
//#ifdef USE_DISP_480_320
//snprintf(out,ts.40,"%s%s%s",(&blank[level>5?37-5:37-level]),entry->label,(&blank[labellen>39?39:labellen]));
snprintf(out,ts.Layout->MENU_TEXT_SIZE_MAX,"%s%s%s",
(&blank[level>5?ts.Layout->MENU_TEXT_SIZE_MAX-8:ts.Layout->MENU_TEXT_SIZE_MAX-3-level]),
entry->label,(&blank[labellen>ts.Layout->MENU_TEXT_SIZE_MAX-1?ts.Layout->MENU_TEXT_SIZE_MAX-1:labellen]));
// snprintf(out,34,"%s%s%s",(&blank[level>5?31-5:31-level]),entry->label,(&blank[labellen>33?33:labellen]));
UiMenu_DisplayLabel(out,m_clr,pos);
}
switch(entry->kind)
{
case MENU_ITEM:
// TODO: Better Handler Selection with need for change in this location to add new handlers
UiMenu_UpdateLines(entry->number,mode,pos);
break;
case MENU_INFO:
UiMenu_UpdateHWInfoLines(entry->number,mode,pos);
break;
case MENU_TEXT:
break;
case MENU_GROUP:
if (mode == MENU_PROCESS_VALUE_CHANGE)
{
bool old_state = UiMenu_GroupIsUnfolded(entry);
if (ts.menu_var < 0 )
{
UiMenu_GroupFold(entry, !(ts.flags2 & FLAGS2_UI_INVERSE_SCROLLING));
}
if (ts.menu_var > 0 )
{
UiMenu_GroupFold(entry, ts.flags2 & FLAGS2_UI_INVERSE_SCROLLING);
}
if (old_state != UiMenu_GroupIsUnfolded(entry))
{
int idx;
for (idx = pos+1; idx < ts.Layout->MENUSIZE; idx++)
{
UiMenu_FillSlotWithEntry(&menu[idx],UiMenu_NextMenuEntry(menu[idx-1].entryItem));
UiMenu_UpdateMenuEntry(menu[idx].entryItem, MENU_RENDER_ONLY, idx);
}
}
ts.menu_var = 0;
}
UiMenu_DisplayValue(
UiMenu_GroupIsUnfolded(entry)?"HIDE":"SHOW",
m_clr,pos);
break;
}
}
else
{
UiMenu_DisplayLabel(blank,m_clr,pos);
}
if (mode == MENU_PROCESS_VALUE_CHANGE)
{
UiMenu_MoveCursor(pos);
}
}
void UiMenu_DisplayInitSlots(const MenuDescriptor* entry)
{
int idx;
for (idx=0; idx < ts.Layout->MENUSIZE; idx++)
{
UiMenu_FillSlotWithEntry(&menu[idx],entry);
entry = UiMenu_NextMenuEntry(entry);
}
}
void UiMenu_DisplayInitSlotsBackwards(const MenuDescriptor* entry)
{
int idx;
for (idx=ts.Layout->MENUSIZE; idx > 0; idx--)
{
UiMenu_FillSlotWithEntry(&menu[idx-1],entry);
entry = UiMenu_PrevMenuEntry(entry);
}
}
/*
* @returns true if at least one slot was moved, false if no change done
*/
bool UiMenu_DisplayMoveSlotsBackwards(int16_t change)
{
int idx;
int dist = (change % ts.Layout->MENUSIZE);
int screens = change / ts.Layout->MENUSIZE;
bool retval = false; // n
for (idx = 0; idx < screens; idx++)
{
const MenuDescriptor *prev = UiMenu_PrevMenuEntry(menu[0].entryItem);
if (prev != NULL)
{
retval = true;
UiMenu_DisplayInitSlotsBackwards(prev);
}
else
{
// we stop here, since no more previous elements.
// TODO: Decide if roll over, in this case we would have to get very last element and
// then continue from there.
dist = 0;
break;
}
}
if (dist != 0)
{
retval = true;
for (idx = ts.Layout->MENUSIZE-dist; idx > 0; idx--)
{
UiMenu_FillSlotWithEntry(&menu[ts.Layout->MENUSIZE-idx],menu[ts.Layout->MENUSIZE-(dist+idx)].entryItem);
}
for (idx = ts.Layout->MENUSIZE-dist; idx >0; idx--)
{
UiMenu_FillSlotWithEntry(&menu[idx-1],UiMenu_PrevMenuEntry(menu[idx].entryItem));
}
}
return retval;
}
/*
* @returns true if at least one slot was moved, false if no change done
*/
bool UiMenu_DisplayMoveSlotsForward(int16_t change)
{
int idx;
int dist = (change % ts.Layout->MENUSIZE);
int screens = change / ts.Layout->MENUSIZE;
bool retval = false;
// first jump screens. we have to iterate through the menu structure one by one
// in order to respect fold/unfold state etc.
for (idx = 0; idx < screens; idx++)
{
const MenuDescriptor *next = UiMenu_NextMenuEntry(menu[ts.Layout->MENUSIZE-1].entryItem);
if (next != NULL)
{
UiMenu_DisplayInitSlots(next);
retval = true;
}
else
{
// stop here
// TODO: Rollover?
dist = 0;
break;
}
}
if (dist != 0)
{
retval = true;
for (idx = 0; idx < ts.Layout->MENUSIZE-dist; idx++)
{
UiMenu_FillSlotWithEntry(&menu[idx],menu[dist+idx].entryItem);
}
for (idx = ts.Layout->MENUSIZE-dist; idx < ts.Layout->MENUSIZE; idx++)
{
UiMenu_FillSlotWithEntry(&menu[idx],UiMenu_NextMenuEntry(menu[idx-1].entryItem));
}
}
return retval;
}
/*
* @brief Display and change menu items
* @param mode 0=show all, 1=update current item, 3=restore default setting for selected item
*
*/
void UiMenu_RenderMenu(MenuProcessingMode_t mode)
{
if (init_done == false )
{
UiMenu_DisplayInitSlots(groups[MENU_START_IDX].entries);
init_done = true;
}
// UiMenu_DisplayMoveSlotsForward(6);
// UiMenu_DisplayMoveSlotsForward(3);
// UiMenu_DisplayMoveSlotsBackwards(10);
switch (mode)
{
case MENU_RENDER_ONLY: // (re)draw all labels and values
{
int idx;
for (idx = 0; idx < ts.Layout->MENUSIZE; idx++)
{
UiMenu_UpdateMenuEntry(menu[idx].entryItem,mode, idx);
}
UiMenu_MoveCursor(ts.menu_item%ts.Layout->MENUSIZE); //redraw of cursor
}
break;
case MENU_PROCESS_VALUE_SETDEFAULT:
case MENU_PROCESS_VALUE_CHANGE:
{
// wrapping to next screen (and from end to start and vice versa)
if (ts.menu_item >= ts.Layout->MENUSIZE)
{
if (UiMenu_RenderNextScreen() == false)
{
UiMenu_RenderFirstScreen();
}
}
else if (ts.menu_item < 0)
{
if (UiMenu_RenderPrevScreen() == false)
{
UiMenu_RenderLastScreen();
}
}
ts.menu_item%=ts.Layout->MENUSIZE;
if (ts.menu_item < 0) ts.menu_item+=ts.Layout->MENUSIZE;
uint16_t current_item = ts.menu_item%ts.Layout->MENUSIZE;
UiMenu_UpdateMenuEntry(menu[current_item].entryItem,mode, current_item);
}
break;
default:
break;
}
}
void UiMenu_RenderChangeItemValue(int16_t pot_diff)
{
if(pot_diff < 0)
{
ts.menu_var--; // increment selected item
}
else
{
ts.menu_var++; // decrement selected item
}
UiMenu_RenderMenu(MENU_PROCESS_VALUE_CHANGE); // perform update of selected item
}
void UiMenu_RenderChangeItem(int16_t pot_diff)
{
if(ts.flags2 & FLAGS2_UI_INVERSE_SCROLLING)
{
pot_diff = -pot_diff;
}
if(pot_diff < 0)
{
ts.menu_item--;
}
else if(pot_diff > 0)
{
ts.menu_item++;
}
ts.menu_var = 0; // clear variable that is used to change a menu item
UiMenu_RenderMenu(MENU_PROCESS_VALUE_CHANGE); // Update that menu item
}
void UiMenu_RenderLastScreen()
{
while (menu[ts.Layout->MENUSIZE-1].entryItem != NULL && UiMenu_NextMenuEntry(menu[ts.Layout->MENUSIZE-1].entryItem) != NULL )
{
UiMenu_DisplayMoveSlotsForward(ts.Layout->MENUSIZE);
}
UiMenu_RenderMenu(MENU_RENDER_ONLY);
}
void UiMenu_RenderFirstScreen()
{
init_done = false;
UiMenu_RenderMenu(MENU_RENDER_ONLY);
}
bool UiMenu_RenderNextScreen()
{
bool retval = UiMenu_DisplayMoveSlotsForward(ts.Layout->MENUSIZE);
if (retval)
{
UiMenu_RenderMenu(MENU_RENDER_ONLY);
}
return retval;
}
bool UiMenu_RenderPrevScreen()
{
bool retval = UiMenu_DisplayMoveSlotsBackwards(ts.Layout->MENUSIZE);
if (retval)
{
UiMenu_RenderMenu(MENU_RENDER_ONLY);
}
return retval;
}
@@ -0,0 +1,856 @@
/*
* ui_menu_internal.h
*
* Created on: 24.12.2016
* Author: danilo
*/
#ifndef DRIVERS_UI_UI_MENU_INTERNAL_H_
#define DRIVERS_UI_UI_MENU_INTERNAL_H_
#include "uhsdr_types.h"
#define UiMenuDesc(a)
//
// Enumeration for menu.
enum
{
MENU_DSP_NR_STRENGTH = 0,
MENU_AM_DISABLE,
MENU_CW_DISABLE,
MENU_DIGI_DISABLE,
MENU_DEMOD_SAM,
MENU_SSB_AUTO_MODE_SELECT,
MENU_CW_AUTO_MODE_SELECT,
MENU_FM_MODE_ENABLE,
MENU_FM_GEN_SUBAUDIBLE_TONE,
MENU_FM_DET_SUBAUDIBLE_TONE,
MENU_FM_TONE_BURST_MODE,
MENU_FM_DEV_MODE,
// MENU_AGC_MODE,
// MENU_RF_GAIN_ADJ,
// MENU_CUSTOM_AGC,
// MENU_AGC_WDSP_SWITCH,
MENU_AGC_WDSP_MODE,
MENU_AGC_WDSP_SLOPE,
MENU_AGC_WDSP_TAU_DECAY,
MENU_AGC_WDSP_THRESH,
MENU_AGC_WDSP_HANG_ENABLE,
MENU_AGC_WDSP_HANG_TIME,
MENU_AGC_WDSP_HANG_THRESH,
MENU_AGC_WDSP_TAU_HANG_DECAY,
MENU_CODEC_GAIN_MODE,
MENU_NOISE_BLANKER_SETTING,
MENU_RX_FREQ_CONV,
MENU_MIC_LINE_MODE,
MENU_MIC_TYPE,
MENU_MIC_GAIN,
MENU_LINE_GAIN,
MENU_ALC_RELEASE,
MENU_ALC_POSTFILT_GAIN,
MENU_TX_COMPRESSION_LEVEL,
MENU_KEYER_MODE,
MENU_KEYER_SPEED,
MENU_KEYER_WEIGHT,
MENU_SIDETONE_GAIN,
MENU_SIDETONE_FREQUENCY,
MENU_PADDLE_REVERSE,
MENU_CW_TX_RX_DELAY,
MENU_CW_OFFSET_MODE,
MENU_CW_DECODER,
MENU_CW_DECODER_THRESH,
// MENU_CW_DECODER_AVERAGE,
MENU_CW_DECODER_BLOCKSIZE,
// MENU_CW_DECODER_AGC,
MENU_CW_DECODER_NOISECANCEL,
MENU_CW_DECODER_SPIKECANCEL,
MENU_CW_DECODER_USE_3_GOERTZEL,
MENU_CW_DECODER_SNAP_ENABLE,
MENU_CW_DECODER_SHOW_CW_LED,
MENU_TCXO_MODE,
MENU_TCXO_C_F,
MENU_SCOPE_SPEED,
MENU_SPECTRUM_FILTER_STRENGTH,
MENU_SCOPE_TRACE_COLOUR,
MENU_SCOPE_TRACE_HL_COLOUR,
MENU_SCOPE_BACKGROUND_HL_COLOUR,
MENU_SCOPE_GRID_COLOUR,
MENU_SPECTRUM_FREQSCALE_COLOUR,
MENU_SPECTRUM_MAGNIFY,
MENU_SCOPE_AGC_ADJUST,
MENU_SCOPE_DB_DIVISION,
MENU_SPECTRUM_CENTER_LINE_COLOUR,
MENU_SCOPE_LIGHT_ENABLE,
MENU_SPECTRUM_MODE,
MENU_WFALL_COLOR_SCHEME,
MENU_WFALL_STEP_SIZE,
MENU_WFALL_OFFSET,
MENU_WFALL_CONTRAST,
MENU_WFALL_SPEED,
// MENU_SCOPE_NOSIG_ADJUST,
// MENU_WFALL_NOSIG_ADJUST,
// MENU_S_METER,
MENU_METER_COLOUR_UP,
MENU_METER_COLOUR_DOWN,
MENU_DBM_DISPLAY,
MENU_DBM_CALIBRATE,
MENU_UI_INVERSE_SCROLLING,
MENU_FREQ_FONT,
MENU_SPECTRUM_SIZE,
MENU_BACKUP_CONFIG,
MENU_RESTORE_CONFIG,
MENU_HARDWARE_INFO,
MENU_SAM_PLL_LOCKING_RANGE,
MENU_SAM_PLL_STEP_RESPONSE,
MENU_SAM_PLL_BANDWIDTH,
MENU_SAM_FADE_LEVELER,
// CONFIG_SAM_PLL_TAUR,
// CONFIG_SAM_PLL_TAUI,
// CONFIG_SAM_SIDEBAND,
MENU_CONFIG_ENABLE,
MENU_RESTART_CODEC,
CONFIG_FREQ_STEP_MARKER_LINE,
CONFIG_STEP_SIZE_BUTTON_SWAP,
CONFIG_BAND_BUTTON_SWAP,
CONFIG_TX_DISABLE,
CONFIG_TX_OUT_ENABLE,
CONFIG_AUDIO_MAIN_SCREEN_MENU_SWITCH,
CONFIG_MUTE_LINE_OUT_TX,
CONFIG_TXRX_SWITCH_AUDIO_MUTE,
CONFIG_LCD_AUTO_OFF_MODE,
CONFIG_VOLTMETER_CALIBRATION,
MENU_LOW_POWER_SHUTDOWN,
CONFIG_LOW_POWER_THRESHOLD,
CONFIG_DISP_FILTER_BANDWIDTH,
CONFIG_MAX_VOLUME,
// CONFIG_MAX_RX_GAIN,
CONFIG_LINEOUT_GAIN,
CONFIG_BEEP_ENABLE,
CONFIG_BEEP_FREQ,
CONFIG_BEEP_VOLUME,
CONFIG_CAT_ENABLE,
CONFIG_FREQUENCY_CALIBRATE,
CONFIG_FREQ_LIMIT_RELAX,
CONFIG_FREQ_MEM_LIMIT_RELAX,
CONFIG_IQ_AUTO_CORRECTION,
CONFIG_80M_RX_IQ_GAIN_BAL,
CONFIG_80M_RX_IQ_PHASE_BAL,
CONFIG_10M_RX_IQ_GAIN_BAL,
CONFIG_10M_RX_IQ_PHASE_BAL,
CONFIG_160M_TX_IQ_GAIN_BAL,
CONFIG_160M_TX_IQ_PHASE_BAL,
CONFIG_80M_TX_IQ_GAIN_BAL,
CONFIG_80M_TX_IQ_PHASE_BAL,
CONFIG_40M_TX_IQ_GAIN_BAL,
CONFIG_40M_TX_IQ_PHASE_BAL,
CONFIG_30M_TX_IQ_GAIN_BAL,
CONFIG_30M_TX_IQ_PHASE_BAL,
CONFIG_20M_TX_IQ_GAIN_BAL,
CONFIG_20M_TX_IQ_PHASE_BAL,
CONFIG_17M_TX_IQ_GAIN_BAL,
CONFIG_17M_TX_IQ_PHASE_BAL,
CONFIG_15M_TX_IQ_GAIN_BAL,
CONFIG_15M_TX_IQ_PHASE_BAL,
CONFIG_12M_TX_IQ_GAIN_BAL,
CONFIG_12M_TX_IQ_PHASE_BAL,
CONFIG_10M_TX_IQ_GAIN_BAL,
CONFIG_10M_TX_IQ_PHASE_BAL,
CONFIG_10M_UP_TX_IQ_GAIN_BAL,
CONFIG_10M_UP_TX_IQ_PHASE_BAL,
CONFIG_6M_TX_IQ_GAIN_BAL,
CONFIG_6M_TX_IQ_PHASE_BAL,
CONFIG_160M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_160M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_80M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_80M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_40M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_40M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_30M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_30M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_20M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_20M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_17M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_17M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_15M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_15M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_12M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_12M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_10M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_10M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_10M_UP_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_10M_UP_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_6M_TX_IQ_GAIN_BAL_TRANS_OFF,
CONFIG_6M_TX_IQ_PHASE_BAL_TRANS_OFF,
CONFIG_CW_PA_BIAS,
CONFIG_PA_BIAS,
CONFIG_FWD_REV_PWR_DISP,
CONFIG_RF_FWD_PWR_NULL,
CONFIG_FWD_REV_COUPLING_2200M_ADJ,
CONFIG_FWD_REV_COUPLING_630M_ADJ,
CONFIG_FWD_REV_COUPLING_160M_ADJ,
CONFIG_FWD_REV_COUPLING_80M_ADJ,
CONFIG_FWD_REV_COUPLING_40M_ADJ,
CONFIG_FWD_REV_COUPLING_20M_ADJ,
CONFIG_FWD_REV_COUPLING_15M_ADJ,
CONFIG_FWD_REV_COUPLING_10M_ADJ,
CONFIG_FWD_REV_COUPLING_6M_ADJ,
CONFIG_FWD_REV_COUPLING_2M_ADJ,
CONFIG_FWD_REV_COUPLING_70CM_ADJ,
CONFIG_FWD_REV_COUPLING_23CM_ADJ,
CONFIG_FWD_REV_SENSE_SWAP,
CONFIG_XVTR_OFFSET_MULT,
CONFIG_XVTR_FREQUENCY_OFFSET,
CONFIG_XVTR_FREQUENCY_OFFSET_TX,
CONFIG_2200M_5W_ADJUST,
CONFIG_630M_5W_ADJUST,
CONFIG_160M_5W_ADJUST,
CONFIG_80M_5W_ADJUST,
CONFIG_60M_5W_ADJUST,
CONFIG_40M_5W_ADJUST,
CONFIG_30M_5W_ADJUST,
CONFIG_20M_5W_ADJUST,
CONFIG_17M_5W_ADJUST,
CONFIG_15M_5W_ADJUST,
CONFIG_12M_5W_ADJUST,
CONFIG_10M_5W_ADJUST,
CONFIG_6M_5W_ADJUST,
CONFIG_4M_5W_ADJUST,
CONFIG_2M_5W_ADJUST,
CONFIG_70CM_5W_ADJUST,
CONFIG_23CM_5W_ADJUST,
CONFIG_2200M_FULL_POWER_ADJUST,
CONFIG_630M_FULL_POWER_ADJUST,
CONFIG_160M_FULL_POWER_ADJUST,
CONFIG_80M_FULL_POWER_ADJUST,
CONFIG_60M_FULL_POWER_ADJUST,
CONFIG_40M_FULL_POWER_ADJUST,
CONFIG_30M_FULL_POWER_ADJUST,
CONFIG_20M_FULL_POWER_ADJUST,
CONFIG_17M_FULL_POWER_ADJUST,
CONFIG_15M_FULL_POWER_ADJUST,
CONFIG_12M_FULL_POWER_ADJUST,
CONFIG_10M_FULL_POWER_ADJUST,
CONFIG_6M_FULL_POWER_ADJUST,
CONFIG_4M_FULL_POWER_ADJUST,
CONFIG_2M_FULL_POWER_ADJUST,
CONFIG_70CM_FULL_POWER_ADJUST,
CONFIG_23CM_FULL_POWER_ADJUST,
#ifdef OBSOLETE_NR
CONFIG_DSP_NR_DECORRELATOR_BUFFER_LENGTH,
CONFIG_DSP_NR_FFT_NUMTAPS,
// CONFIG_DSP_NR_POST_AGC_SELECT,
CONFIG_DSP_NOTCH_CONVERGE_RATE,
CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH,
CONFIG_DSP_NOTCH_FFT_NUMTAPS,
#endif
#ifdef USE_LMS_AUTONOTCH
CONFIG_DSP_NOTCH_CONVERGE_RATE,
CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH,
CONFIG_DSP_NOTCH_FFT_NUMTAPS,
#endif
// CONFIG_AGC_TIME_CONSTANT,
CONFIG_AM_TX_FILTER_DISABLE,
// CONFIG_SSB_TX_FILTER_DISABLE,
CONFIG_SSB_TX_FILTER,
CONFIG_TUNE_POWER_LEVEL,
CONFIG_TUNE_TONE_MODE,
// CONFIG_SPECTRUM_FFT_WINDOW_TYPE,
CONFIG_RESET_SER_EEPROM,
CONFIG_RESET_SER_EEPROM_SIGNATURE,
CONFIG_CAT_IN_SANDBOX,
CONFIG_CAT_XLAT,
CONFIG_CAT_PTT_RTS,
CONFIG_REDUCE_POWER_ON_LOW_BANDS,
CONFIG_REDUCE_POWER_ON_HIGH_BANDS,
MENU_FP_CW_01,
MENU_FP_CW_02,
MENU_FP_CW_03,
MENU_FP_CW_04,
MENU_FP_AM_01,
MENU_FP_AM_02,
MENU_FP_AM_03,
MENU_FP_AM_04,
MENU_FP_SSB_01,
MENU_FP_SSB_02,
MENU_FP_SSB_03,
MENU_FP_SSB_04,
// MENU_FP_SAM_01,
// MENU_FP_SAM_02,
// MENU_FP_SAM_03,
// MENU_FP_SAM_04,
MENU_DEBUG_TX_AUDIO,
CONFIG_I2C1_SPEED,
CONFIG_I2C2_SPEED,
MENU_DEBUG_ENABLE_INFO,
MENU_DEBUG_CLONEOUT,
MENU_DEBUG_CLONEIN,
// MENU_DEBUG_NEW_NB,
// MENU_DEBUG_NR_ENABLE,
// MENU_DEBUG_NR_GAIN_SMOOTH_ENABLE,
MENU_DEBUG_NR_GAIN_SHOW,
// MENU_DEBUG_NR_LONG_TONE_ENABLE,
// MENU_DEBUG_NR_LONG_TONE_THRESH,
// MENU_DEBUG_NR_LONG_TONE_ALPHA,
// MENU_DEBUG_NR_GAIN_SMOOTH_ALPHA,
// MENU_DEBUG_NR_ALPHA,
// MENU_DEBUG_NR_THRESH,
// MENU_DEBUG_NR_VAD_TYPE,
// MENU_DEBUG_NR_VAD_DELAY,
MENU_DEBUG_NR_BETA,
// MENU_DEBUG_NR_Mode,
//#if defined(STM32F7) || defined(STM32H7)
// MENU_DEBUG_NR_FFT_SIZE,
// MENU_DEBUG_NR_DEC_ENABLE,
//#endif
MENU_DEBUG_NR_ASNR,
MENU_DEBUG_NR_GAIN_SMOOTH_WIDTH,
MENU_DEBUG_NR_GAIN_SMOOTH_THRESHOLD,
// MENU_DEBUG_RTTY_ATC,
#ifdef USE_TWO_CHANNEL_AUDIO
MENU_DEBUG_ENABLE_STEREO,
#endif
// MENU_DEBUG_CW_DECODER,
#ifdef USE_LEAKY_LMS
MENU_DEBUG_LEAKY_LMS,
MENU_DEBUG_NR_POST_AGC_SELECT,
MENU_DEBUG_ANR_TAPS,
MENU_DEBUG_ANR_DELAY,
MENU_DEBUG_ANR_GAIN,
MENU_DEBUG_ANR_LEAK,
#endif
MENU_DEBUG_OSC_SI5351_PLLRESET,
MENU_DEBUG_HMC1023_COARSE,
MENU_DEBUG_HMC1023_FINE,
MENU_DEBUG_HMC1023_GAIN,
MENU_DEBUG_HMC1023_BYPASS,
MENU_DEBUG_HMC1023_OPAMP,
MENU_DEBUG_HMC1023_DRVR,
MENU_DEBUG_TWINPEAKS_CORR_RUN,
CONFIG_VSWR_PROTECTION_THRESHOLD,
MENU_DEBUG_FREEDV_MODE,
MENU_DEBUG_FREEDV_SQL_THRESHOLD,
CONFIG_RTC_START,
CONFIG_RTC_HOUR,
CONFIG_RTC_MIN,
CONFIG_RTC_SEC,
CONFIG_RTC_RESET,
CONFIG_RTC_CALIB,
MENU_DYNAMICTUNE,
MENU_DIGITAL_MODE_SELECT,
MENU_DEBUG_CW_OFFSET_SHIFT_KEEP_SIGNAL,
CONFIG_SMETER_ATTACK,
CONFIG_SMETER_DECAY,
MENU_DEBUG_SMOOTH_DYN_TUNE,
CONFIG_BANDEF_SELECT,
INFO_LO_TX_SUPR_DACs,
MENU_DEBUG_CAL_LO_TX_SUPR_0,
MENU_DEBUG_CAL_LO_TX_SUPR_1,
CONFIG_WIDE_SPEC_DEF,
MENU_NO_SHOW_BNDMEM,
CONFIG_BANDCH_JUMP_SWAP,
MENU_INPUT_STATE,
MENU_BOX_COLOUR,
MENU_TXTLINE_COLOUR,
CONFIG_ENC1_REVERSE,
CONFIG_ENC2_REVERSE,
CONFIG_ENC3_REVERSE,
CONFIG_ENC4_REVERSE,
MENU_CW_MACRO_INTERVAL,
MENU_CW_BEACON_INTERVAL,
MENU_DEBUG_SHOW_GREETING,
MENU_PEAK_IND_TUNE,
MENU_CLEAR_PAN_ON_TX,
MENU_SMETER_AM_NOT_LO,
MENU_CW_FAST_MACRO_1_2,
MENU_DEBUG_CLEAN_TX_CW_RTTY_BPSK,
MENU_CW_SMOOTH,
MENU_DEBUG_CB_27MC_TX_ENABLE,
MENU_DEBUG_CB_26MC_TX_ENABLE,
MENU_DEBUG_CB_12W_SSB_TX_ENABLE,
MENU_DEBUG_CB_10W_TX_ENABLE,
MENU_DEBUG_MEM_BW_MOD_BAND,
MENU_DEBUG_ILLUM_BUTT,
MENU_DEBUG_BPF_OPTION,
MENU_DEBUG_XVTR_OFF_PA,
MENU_DEBUG_BANDCODE,
MENU_DEBUG_DISABLE_TP,
MENU_DEBUG_FMENUS_SEL,
MENU_DEBUG_F6_IND_SEL,
MENU_DEBUG_F7_IND_SEL,
MENU_DEBUG_ALT_PWR_CTRL,
MENU_DEBUG_ALT_PWR_CTRL_VOL,
MENU_DEBUG_IMPROV_IQ_ADJ,
CONFIG_TX_REVERB_GAIN,
CONFIG_TX_REVERB_DELAY,
CONFIG_TX_EQ0,
CONFIG_TX_EQ1,
CONFIG_TX_EQ2,
CONFIG_TX_EQ3,
CONFIG_TX_EQ4,
MENU_DEBUG_BEEP_GEN,
MENU_DEBUG_BAND_OFF_160M,
MENU_DEBUG_BAND_OFF_80M,
MENU_DEBUG_BAND_OFF_60M,
MENU_DEBUG_BAND_OFF_40M,
MENU_DEBUG_BAND_OFF_30M,
MENU_DEBUG_BAND_OFF_20M,
MENU_DEBUG_BAND_OFF_17M,
MENU_DEBUG_BAND_OFF_15M,
MENU_DEBUG_BAND_OFF_12M,
MENU_DEBUG_BAND_OFF_10M,
MENU_DEBUG_BAND_OFF_6M,
MENU_DEBUG_REDUCE_POWER_ON_LOW_BANDS_MORE,
MENU_DEBUG_SHOW_SWR_ONLY_TUNE,
MENU_DEBUG_CONTEST,
// MENU_DEBUG_CONTEST_COLOUR,
MAX_RADIO_CONFIG_ITEM // Number of radio configuration menu items - This must ALWAYS remain as the LAST item!
};
// menu entry kind constants
enum MENU_KIND
{
MENU_STOP = 0, // last entry in a menu / group
MENU_ITEM, // standard menu entry
MENU_GROUP, // menu group entry
MENU_INFO, // just like a normal entry (read-only) but just for display purposes.
MENU_SEP, // separator line
MENU_BLANK, // blank
MENU_TEXT, // text output only
};
struct MenuGroupDescriptor_s;
// items are stored in RAM
// Each menu group has to have a MenuGroupItem pointing to the descriptor
// a MenuGroupItem is used to keep track of the fold/unfold state and to link the
// Descriptors are stored in flash
typedef struct
{
const uint16_t menuId; // backlink to the menu we are part of. That implies, an entry can only be part of a single menu group
const uint16_t kind; // use the enum defined above to indicate what this entry represents
const uint16_t number; // this is an identification number which is passed to the menu entry handled
// for standard items it is the id of the value to be changed, intepretation is left to handler
// MENU_GROUP: for menu groups this MUST BE the index in the menu group table, THIS IS USED INTERNALLY
volatile bool* enabled; // pointer to a variable which contains a boolean value to tell us if the menu entry is enabled right now, set to NULL if always enabled
// this was a visual 3 letter identification which may be display, depending on the render approach
const char* label; // this is the label which will be display, depending on the render approach
} MenuDescriptor;
typedef struct
{
bool unfolded; // runtime variable, tells if the user wants to have this groups items to be shown
uint16_t count; // number of menu entries. This will be filled automatically on first use by internal code
// do not write to this variable unless you know what you are doing.
const MenuDescriptor* me; // pointer to the MenuDescriptor of this menu group in its parent menu. This is the backlink to our parent.
// This will be filled automatically on first use by internal code in order to avoid search through the menu structure.
// do not write to this variable unless you know what you are doing.
} MenuGroupState;
#ifdef HELP_MENU
typedef struct
{
const uint16_t count; // number of menu entries
const char* txt; // text of help
} HelpDescriptor;
#endif
// This data structure is intended to be placed in flash
// all data is placed here at compile time
typedef struct MenuGroupDescriptor_s
{
const MenuDescriptor* entries; // array of member entries in the menu group
MenuGroupState* state; // writable data structure for menu management, pointer has to go into RAM
const MenuDescriptor* parent; // pointer to the first element of the array in which our menu group is located in. It does not have
// to point to the MENU_GROUP item, wich can be at any position in this array. Used to calculate the real
// pointer later and to identify the parent menu group of this menu.
// use NULL for top level menus here (i.e. no parent).
} MenuGroupDescriptor;
// Runtime management of menu entries for onscreen rendering.
typedef struct
{
const MenuDescriptor* entryItem;
} MenuDisplaySlot;
#define MENU_START_IDX 0
extern const MenuGroupDescriptor groups[];
void UiMenu_UpdateItem(uint16_t select, MenuProcessingMode_t mode, int pos, int var, char* options, const char** txt_ptr_ptr, uint32_t* clr_ptr);
void UiMenu_DisplayValue(const char* value,uint32_t clr,uint16_t pos);
#endif /* DRIVERS_UI_UI_MENU_INTERNAL_H_ */
#ifdef HELP_MENU
const HelpDescriptor Helps[] =
{
{ MENU_SSB_AUTO_MODE_SELECT, "If enabled, the appropriate sideband mode for SSB and FreeDV is chosen as default for each band by its frequency.\0"},
{ MENU_DIGI_DISABLE, "Disable appearance of digital modes when pressing Mode button.\0"},
{ MENU_CW_DISABLE, "Disable appearance of CW mode when pressing Mode button.\0"},
{ MENU_AM_DISABLE, "Disable appearance of AM mode when pressing Mode button.\0"},
{ MENU_DEMOD_SAM, "Disable appearance of SyncAM modes when pressing Mode button.\0"},
{ MENU_SAM_PLL_LOCKING_RANGE, "SAM PLL Locking Range in Hz: this determines how far up and down from the carrier frequency of an AM station we can offtune the receiver, so that the PLL will still lock to the carrier.\0"},
{ MENU_SAM_PLL_STEP_RESPONSE, "Step response = Zeta = damping factor of the SAM PLL. Sets the stability and transient response of the PLL. Larger values give faster lock even if you are offtune, but PLL is also more sensitive.\0"},
{ MENU_SAM_PLL_BANDWIDTH, "Bandwidth of the PLL loop = OmegaN in Hz: smaller bandwidth = more stable lock. FAST LOCK SAM PLL - set Step response and PLL bandwidth to large values [eg. 80 / 350]; DX (SLOW & STABLE) SAM PLL - set Step response and PLL bandwidth to small values [eg. 30 / 100].\0"},
{ MENU_SAM_FADE_LEVELER, "Fade leveler (in AM/SAM mode) ON/OFF. Fade leveler is helpful in situations with very fast QSB of the carrier ´flutter´. It is designed to remove the rapidly changing carrier and replace it with a more stable carrier. If there is no QSB on the carrier, there is no change.\0"},
{ MENU_FM_MODE_ENABLE, "Disable appearance of FM mode when pressing Mode button.\0"},
{ MENU_FM_GEN_SUBAUDIBLE_TONE, "Enable generation of CTCSS tones during FM transmissions.\0"},
{ MENU_FM_DET_SUBAUDIBLE_TONE, "Enable detection of CTCSS tones during FM receive. RX is muted unless tone is detected.\0"},
{ MENU_FM_TONE_BURST_MODE, "Enabled sending of short tone at beginning of each FM transmission. Used to open repeaters. Available frequencies are 1750 Hz and 2135 Hz.\0"},
{ MENU_FM_DEV_MODE, "Select between normal and narrow deviation (5 and 2.5kHz) for FM RX/TX.\0"},
{ MENU_DEBUG_FREEDV_MODE, "Change active FreeDV mode. Please note, you have to reboot to activate new mode.\0"},
{ MENU_DEBUG_FREEDV_SQL_THRESHOLD, "If not OFF, FreeDV will squelch if detected SNR is below set value.\0"},
{ MENU_AGC_WDSP_MODE, "Choose a bundle of preset AGC parameters for the WDSP AGC: FAST / MED / SLOW / LONG / very LONG or switch OFF the AGC.\0"},
{ MENU_AGC_WDSP_SLOPE, "Slope of the AGC is the difference between the loudest signal and the quietest signal after the AGC action has taken place. Given in dB.\0"},
{ MENU_AGC_WDSP_TAU_DECAY, "Time constant for the AGC decay (speed of recovery of the AGC gain) in milliseconds.\0"},
{ MENU_AGC_WDSP_THRESH, "Threshold = Knee of the AGC: input signal level from which on the AGC action takes place. AGC threshold should be placed/adjusted just above the band noise for every particular RX situation to allow for optimal AGC action. The blue AGC box indicates when AGC action takes place and helps in adjusting this threshold.\0"},
{ MENU_AGC_WDSP_HANG_ENABLE, "Enable/Disable Hang AGC function: If enabled: after the signal has decreased, the gain of the AGC is held constant for a certain time period (the hang time) in order to allow for speech pauses without disturbing noise because of fast acting AGC.\0"},
{ MENU_AGC_WDSP_HANG_TIME, "Hang AGC: hang time is the time period over which the AGC gain is held constant when in AGC Hang mode. After this period the gain is increased fast.\0"},
{ MENU_AGC_WDSP_HANG_THRESH, "´Threshold´ for the Hang AGC: Hang AGC is useful for medium to strong signals. The Hang threshold determines the signal strength a signal has to exceed for Hang AGC to take place.\0"},
{ MENU_AGC_WDSP_TAU_HANG_DECAY, "Time constant for the Hang AGC decay (speed of recovery of the AGC gain after hang time has expired) in milliseconds.\0"},
{ MENU_CODEC_GAIN_MODE, "Sets the Codec IQ signal gain. Higher values represent higher gain. If set to AUTO the mcHF controls the gain so that the best dynamic range is used.\0"},
{ MENU_RX_FREQ_CONV, "Controls offset of the receiver IQ signal base frequency from the dial frequency. Use of +/-12Khz is recommended. Switching it to OFF is not recommended as it disables certain features.\0"},
{ MENU_BACKUP_CONFIG, "Backup your I2C Configuration to flash. If you don't have suitable I2C EEPROM installed this function is not available.\0"},
{ MENU_RESTORE_CONFIG, "Restore your I2C Configuration from flash. If you don't have suitable I2C EEPROM installed this function is not available.\0"},
{ CONFIG_RESET_SER_EEPROM, "Clear the EEPROM so that at next start all stored configuration data is reset to the values stored in Flash (see Backup/Restore).\0"},
{ CONFIG_RESET_SER_EEPROM_SIGNATURE, "Clear the EEPROMi signature but keep all config values. This is mainly for debugging purposes).\0"},
{ CONFIG_BANDEF_SELECT, "Select which band definition to use for ham bands. Original UHSDR or IARU Region 1 - 3.\0"},
{ CONFIG_FREQ_MEM_LIMIT_RELAX, "Select ON to save and restore frequencies which do not fit into the band during configuration saving (Power-Off or long press on Menu button).\0"},
{ CONFIG_TX_OUT_ENABLE, "Permit low power transmission even if the frequency is out of the official ham bands. DO NOT USE WITH CONNECTED ANTENNA! Use a dummy load!\0"},
{ CONFIG_AUDIO_MAIN_SCREEN_MENU_SWITCH, "Control if the screen automatically adapts Encoder value focus when switching between RX and TX.\0"},
{ CONFIG_MUTE_LINE_OUT_TX, "During transmission with frequency translation off, line out will carry one of the two signal channels. Good for CW but not very useful otherwise. You may switch this signal off here.\0"},
{ CONFIG_TXRX_SWITCH_AUDIO_MUTE, "When switching from RX to TX the audio and HF output will be muted for roughly VALUE ms. There are now several minimum times for muting defined in the firmware:<br/><br/> Input from Mic: 40ms<br/> Input from Line In: 40ms<br/> Digital Inputs (CW, USB): less than 1ms.<br/><br/> If the user defined 'TX Initial Muting Time' is set to more than zero, the maximum of both fixed input time and user defined time is used. Your microphone PTT switch is a potential source of noise if Mic is input! You need to increase the delay or change switches!\0"},
{ CONFIG_MAX_VOLUME, "Set maximum speaker&headphone volume.\0"},
{ CONFIG_LINEOUT_GAIN, "Set the constant gain level for the analog lineout jack.\0"},
{ CONFIG_BEEP_FREQ, "Set key beep frequency in Hz.\0"},
{ CONFIG_BEEP_VOLUME, "Set key beep volume.\0"},
{ CONFIG_CAT_IN_SANDBOX, "If On, frequency Changes made via CAT will not automatically switch bands and affect the manually selected frequencies.\0"},
{ CONFIG_CAT_XLAT, "Select which frequency is reported via CAT Interface to the connected PC in Digital IQ Mode. If ON, it reports the displayed frequency. If OFF, it reports the center frequency, which is more useful with SDR programs.\0"},
{ CONFIG_CAT_PTT_RTS, "The virtual serial port signal RTS can be used to switch to TX. Use with care, many CAT-able programs also set RTS to aktiv and make the TRX go to TX mode.\0"},
{ CONFIG_XVTR_OFFSET_MULT, "When connecting to a transverter, set this to 1 and set the XVERTER Offset to the LO Frequency of it. The mcHF frequency is multiplied by this factor before the offset is added, so anything but 1 will result in each Hz in the mcHF being displayed as 2 to 10 Hz change on display.\0"},
{ CONFIG_XVTR_FREQUENCY_OFFSET, "When transverter mode is enabled, this value is added to the mcHF frequency after being multiplied with the XVTR Offs/Mult. Use Step+ to set a good step width, much less turns with the dial knob if it is set to 1Mhz.\0"},
{ CONFIG_XVTR_FREQUENCY_OFFSET_TX, "When transverter mode is enabled, this value is added to the displayed mcHF TX frequency after being multiplied with the XVTR Offs/Mult. Setting it to 0 uses RX offset for TX. Use Step+ to set a good step width, much less turns with the dial knob if it is set to 1Mhz.\0"},
{ CONFIG_STEP_SIZE_BUTTON_SWAP, "If ON, Step- behaves like Step+ and vice versa.\0"},
{ CONFIG_BAND_BUTTON_SWAP, "If ON, Band- behaves like Band+ and vice versa.\0"},
{ CONFIG_BANDCH_JUMP_SWAP, "If ON, LongAction of Band+/- is band change, ShortAction is jump by freq on panorama width.\0"},
{ CONFIG_ENC1_REVERSE, "If ON, encoder 1 are reversed.\0"},
{ CONFIG_ENC2_REVERSE, "If ON, encoder 2 are reversed.\0"},
{ CONFIG_ENC3_REVERSE, "If ON, encoder 3 are reversed.\0"},
{ CONFIG_ENC4_REVERSE, "If ON, encoder 4 are reversed.\0"},
{ CONFIG_VOLTMETER_CALIBRATION, "Adjusts the displayed value of the voltmeter.\0"},
{ CONFIG_LOW_POWER_THRESHOLD, "Voltage threshold for voltage warning colors and auto shutdown.\0"},
{ MENU_LOW_POWER_SHUTDOWN, "Shutdown automatically when supply voltage is below threshold for 60 seconds (only in RX).\0"},
{ CONFIG_FREQUENCY_CALIBRATE, "Adjust the frequency correction of the local oscillator. Measure TX frequency and adjust until both match. Or use receive a know reference signal and zero-beat it and then adjust. More information in the Wiki.\0"},
{ CONFIG_RF_FWD_PWR_NULL, "Set the forward and reverse power sensors ADC zero power offset. This setting is enabled ONLY when Disp. Pwr (mW), is enabled. Needs SWR meter hardware modification to work. See Wiki Adjustment and Calibration.\0"},
{ CONFIG_FWD_REV_SENSE_SWAP, "Exchange the assignment of the Power/SWR FWD and REV measurement ADC. Use if your power meter does not show anything during TX.\0"},
{ CONFIG_I2C1_SPEED, "Sets speed of the I2C1 bus (Si570 oscillator and MCP9801 temperature sensor). Higher speeds provide quicker RX/TX switching but may also cause tuning issues (red digits). Be careful with speeds above 200 kHz.\0"},
{ CONFIG_I2C2_SPEED, "Sets speed of the I2C2 bus (Audio Codec and I2C EEPROM). Higher speeds provide quicker RX/TX switching, configuration save and power off. Speeds above 200 kHz are not recommended for unmodified mcHF. Many modified mcHF seem to run with 300kHz without problems.\0"},
{ CONFIG_IQ_AUTO_CORRECTION, "Receive IQ phase and amplitude imbalance can be automatically adjusted by the mcHF. Switch ON/OFF here. If OFF, it takes the following menu values for compensating the imbalance. The automatic algorithm achieves up to 60dB mirror rejection. See Wiki Adjustments and Calibration.\0"},
{ CONFIG_80M_RX_IQ_GAIN_BAL, "IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.\0"},
{ CONFIG_80M_RX_IQ_PHASE_BAL, "IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.\0"},
{ CONFIG_10M_RX_IQ_GAIN_BAL, "IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.\0"},
{ CONFIG_10M_RX_IQ_PHASE_BAL, "IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable. See Wiki Adjustments and Calibration.\0"},
{ MENU_NOISE_BLANKER_SETTING, "Set the Noise Blanker strength. Higher values mean more agressive blanking. Also changeable using Encoder 2 if Noise Blanker is active.\0"},
#ifdef OBSOLETE_NR
{ CONFIG_DSP_NR_DECORRELATOR_BUFFER_LENGTH, "DSP LMS noise reduction: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.\0"},
{ CONFIG_DSP_NR_FFT_NUMTAPS, "DSP LMS noise reduction: Number of taps in the DSP noise reduction FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.\0"},
{ CONFIG_DSP_NOTCH_CONVERGE_RATE, "DSP LMS automatic notch filter: converge rate.\0"},
{ CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH, "DSP LMS automatic notch filter: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better -and the slower- the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.\0"},
{ CONFIG_DSP_NOTCH_FFT_NUMTAPS, "DSP LMS automatic notch filter: Number of taps in the DSP automatic notch FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.\0"},
#endif
#ifdef USE_LMS_AUTONOTCH
{ CONFIG_DSP_NOTCH_CONVERGE_RATE, "DSP LMS automatic notch filter: converge rate.\0"},
{ CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH, "DSP LMS automatic notch filter: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better -and the slower- the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.\0"},
{ CONFIG_DSP_NOTCH_FFT_NUMTAPS, "DSP LMS automatic notch filter: Number of taps in the DSP automatic notch FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.\0"},
#endif
{ MENU_DEBUG_NR_GAIN_SHOW, "Debugging: show gains of spectral noise reduction.\0"},
{ MENU_DSP_NR_STRENGTH, "Set the Noise Reduction Strength. Higher values mean more agressive noise reduction but also higher CPU load. Use with extreme care. Also changeable using Encoder 2 if DSP is active.\0"},
{ MENU_DEBUG_NR_BETA, "Time constant beta for spectral noise reduction, leave at 0.85.\0"},
{ MENU_DEBUG_NR_ASNR, "Devel 2 NR: asnr.\0"},
{ MENU_DEBUG_NR_GAIN_SMOOTH_WIDTH, "Devel 2 NR: width of gain smoothing window.\0"},
{ MENU_DEBUG_NR_GAIN_SMOOTH_THRESHOLD, "Devel 2 NR: threhold for gain smoothing.\0"},
{ MENU_DEBUG_NR_POST_AGC_SELECT, "DSP LMS noise reduction: Perform the DSP LMS noise reduction BEFORE or AFTER the AGC. NO = before AGC, YES = after AGC.\0"},
{ MENU_DEBUG_ANR_TAPS, "Number of taps of leaky LMS noise reduction.\0"},
{ MENU_DEBUG_ANR_DELAY, "Delay length of leaky LMS noise reduction.\0"},
{ MENU_DEBUG_ANR_GAIN, "Gain of leaky LMS noise reduction.\0"},
{ MENU_DEBUG_ANR_LEAK, "Leak of leaky LMS noise reduction.\0"},
{ CONFIG_WIDE_SPEC_DEF, "Wide mode of spectrum on screen 320x240 is default.\0"},
{ CONFIG_LCD_AUTO_OFF_MODE, "After x seconds LCD turns dark and LCD data sections stop. So power consumption is decreased and RX hum is decreased, too. LCD operation starts when using any button or the touchscreen.\0"},
{ MENU_CW_DECODER_SNAP_ENABLE, "Graphical tune helper: adjust frequency until yellow vertical line is in centre of green box --> right on CW carrier frequency.\0"},
{ CONFIG_FREQ_STEP_MARKER_LINE, "If enabled, you'll see a line under the digit which is currently representing the selected tuning step size.\0"},
{ MENU_NO_SHOW_BNDMEM, "Don't show BndMemory.\0"},
{ MENU_CLEAR_PAN_ON_TX, "Clear panoram on TX/TUNE.\0"},
{ CONFIG_DISP_FILTER_BANDWIDTH, "Colour of the horizontal Filter Bandwidth indicator bar.\0"},
{ MENU_SPECTRUM_SIZE, "Change height of spectrum display.\0"},
{ MENU_SPECTRUM_FILTER_STRENGTH, "Lowpass filter for the spectrum FFT. Low values: fast and nervous spectrum; High values: slow and calm spectrum.\0"},
{ MENU_SPECTRUM_FREQSCALE_COLOUR, "Colour of the small frequency digits under the spectrum display.\0"},
{ MENU_SPECTRUM_CENTER_LINE_COLOUR, "Colour of the vertical line indicating the TX carrier frequency in the spectrum or waterdall display.\0"},
{ MENU_SCOPE_LIGHT_ENABLE, "The scope uses bars (NORMAL) or points (LIGHT) to represent data. LIGHT is a little less resource intensive.\0"},
{ MENU_SCOPE_SPEED, "Lower Values: Higher refresh rate. Set to 0 to disable scope.\0"},
{ MENU_SCOPE_AGC_ADJUST, "Adjusting of scope / waterfall AGC for fitting graphs to screen.\0"},
{ MENU_SCOPE_TRACE_COLOUR, "Set colour of scope.\0"},
{ MENU_SCOPE_TRACE_HL_COLOUR, "Set colour of highlighted BW scope.\0"},
{ MENU_SCOPE_BACKGROUND_HL_COLOUR, "Set colour of highlighted BW background.\0"},
{ MENU_SCOPE_GRID_COLOUR, "Set colour of scope grid.\0"},
{ MENU_SCOPE_DB_DIVISION, "Set rf range for scope.\0"},
{ MENU_WFALL_SPEED, "Lower Values: Higher refresh rate. Set to 0 to disable waterfall.\0"},
{ MENU_WFALL_COLOR_SCHEME, "Select colour scheme for waterfall display.\0"},
{ MENU_WFALL_STEP_SIZE, "How many lines are moved in a single screen update.\0"},
{ MENU_WFALL_CONTRAST, "Adjust to fit your personal input level range to displayable colour range for waterfall.\0"},
{ MENU_METER_COLOUR_UP, "Set the colour of the scale of combined S/Power-Meter.\0"},
{ MENU_METER_COLOUR_DOWN, "Set the colour of the scale of combined SWR/AUD/ALC-Meter.\0"},
{ MENU_BOX_COLOUR, "Screen boxes colour.\0"},
{ MENU_TXTLINE_COLOUR, "Ticker colour.\0"},
{ MENU_DBM_DISPLAY, "RX signal power (measured within the filter bandwidth) can be displayed in dBm or normalized as dBm/Hz. This value is supposed to be quite accurate to +-3dB. Preferably use low spectrum display magnify settings. Accuracy is lower for very very weak and very very strong signals.\0"},
{ MENU_DBM_CALIBRATE, "dBm display calibration. Just an offset (in dB) that is added to the internally calculated dBm or dBm/Hz value.\0"},
{ CONFIG_SMETER_ATTACK, "Attack controls how quickly the S-Meter reacts to rising signal levels, higher values represent quicker reaction.\0"},
{ CONFIG_SMETER_DECAY, "Decay controls how quickly the S-Meter reacts to falling signal levels, higher values represent quicker reaction.\0"},
{ MENU_PEAK_IND_TUNE, "Tune/OFF S/PWR meter peak indicator.\0"},
{ MENU_SMETER_AM_NOT_LO, "Don't calculate LO in AM mode RX.\0"},
{ MENU_TCXO_MODE, "The software TCXO can be turned ON (set frequency is adjusted so that generated frequency matches the wanted frequency); OFF (no correction or measurement done); or STOP (no correction but measurement).\0"},
{ MENU_TCXO_C_F, "Show the measure TCXO temperature in Celsius or Fahrenheit.\0"},
{ CONFIG_RTC_START, "Start using the RTC and use the modified button layout. Will reboot your mcHF. Please use only if you completed the RTC mod otherwise you will need to disconnect battery and power and reboot to get a working mcHF. This menu is only visible if Backup RAM (VBat) was detected.\0"},
{ CONFIG_RTC_HOUR, "Sets the Real Time Clock Hour. Needs HW Modifications.\0"},
{ CONFIG_RTC_MIN, "Sets the Real Time Clock Minutes. Needs HW Modifications.\0"},
{ CONFIG_RTC_SEC, "Sets the Real Time Clock Seconds. Needs HW Modifications.\0"},
{ CONFIG_RTC_RESET, "Full Reset of STM32 RTC. Can be used to simulate first start with RTC mod completed.\0"},
{ CONFIG_RTC_CALIB, "Sets the Real Time Clock Frequency calibration value in ppm. 1s/day deviation equals 11.57 ppm deviation.\0"},
{ MENU_FREQ_FONT, "Font selection for frequency display. Allows selection of old/modern fonts.\0"},
{ MENU_UI_INVERSE_SCROLLING, "Inverts Enc2/Enc3 behavior in menu up/down and show/hide UI scrolling actions, used for side-mounted encoder dials.\0"},
{ MENU_KEYER_MODE, "Select how the mcHF interprets the connected keyer signals. Supported modes: Iambic A and B Keyer (IAM A/B), Straight Key (STR_K), and Ultimatic Keyer (ULTIM).\0"},
{ MENU_KEYER_SPEED, "Keyer Speed for the automatic keyer modes in WpM. Also changeable via Encoder 3 if in CW Mode.\0"},
{ MENU_KEYER_WEIGHT, "Keyer Dit/Pause ratio for the automatic keyer modes. Higher values increase length of dit, decreases length of pause so that the total time is still according to the set WpM value.\0"},
{ MENU_CW_SMOOTH, "Smooth of CW signal edges.\0"},
{ MENU_SIDETONE_GAIN, "Audio volume for the monitor sidetone in CW TX. Also changeable via Encoder 1 if in CW Mode.\0"},
{ MENU_SIDETONE_FREQUENCY, "Sidetone Frequency (also Offset frequency, see CW Freq. Offset below).\0"},
{ MENU_PADDLE_REVERSE, "Dit is Dah and Dah is Dit. Use if your keyer needs reverse meaning of the paddles.\0"},
{ MENU_CW_TX_RX_DELAY, "How long to stay in CW TX mode after stop sending a signal.\0"},
{ MENU_CW_OFFSET_MODE, "TX: display is TX frequency if received frequency was zero-beated. DISP: display is RX frequency if received signal is matched to sidetone. SHIFT: LO shifts, display is RX frequency if signal is matched to sidetone.\0"},
{ MENU_CW_AUTO_MODE_SELECT, "Set appropriate sideband mode for CW. If AUTO, sideband is chosen for bands by its frequency. A long press on Mode button gets the other sideband mode.\0"},
{ MENU_CW_DECODER, "Enable experimental CW decoding.\0"},
{ MENU_CW_DECODER_THRESH, "All signals above this threshold are intepreted as a dit or daah.\0"},
{ MENU_CW_DECODER_BLOCKSIZE, "How many samples are taken for the signal detection with the Goertzel algorithm?\0"},
{ MENU_CW_DECODER_NOISECANCEL, "Enable/disable noise canceler for CW decoder.\0"},
{ MENU_CW_DECODER_SPIKECANCEL, "Enable/disable spike canceler or short cancel for CW decoder.\0"},
{ MENU_CW_DECODER_USE_3_GOERTZEL, "Enable/disable AGC for CW decoder.\0"},
{ MENU_CW_DECODER_SHOW_CW_LED, "Enable/disable LED for CW decoder.\0"},
{ MENU_CW_MACRO_INTERVAL, "CW Macros Cycled TX interval, sec.\0"},
{ MENU_CW_BEACON_INTERVAL, "CW Beacon interval, min.\0"},
{ MENU_CW_FAST_MACRO_1_2, "Enable/disable fast TXing CW macro 1 and 2.\0"},
{ MENU_FP_SSB_01, "Filter bandwidth #1 when toggling with filter select button in LSB or USB.\0"},
{ MENU_FP_SSB_02, "Filter bandwidth #2 when toggling with filter select button in LSB or USB.\0"},
{ MENU_FP_SSB_03, "Filter bandwidth #3 when toggling with filter select button in LSB or USB.\0"},
{ MENU_FP_SSB_04, "Filter bandwidth #4 when toggling with filter select button in LSB or USB.\0"},
{ MENU_FP_CW_01, "Filter bandwidth #1 when toggling with filter select button in CW.\0"},
{ MENU_FP_CW_02, "Filter bandwidth #2 when toggling with filter select button in CW.\0"},
{ MENU_FP_CW_03, "Filter bandwidth #3 when toggling with filter select button in CW.\0"},
{ MENU_FP_CW_04, "Filter bandwidth #4 when toggling with filter select button in CW.\0"},
{ MENU_FP_AM_01, "Filter bandwidth #1 when toggling with filter select button in AM & SAM.\0"},
{ MENU_FP_AM_02, "Filter bandwidth #2 when toggling with filter select button in AM & SAM.\0"},
{ MENU_FP_AM_03, "Filter bandwidth #3 when toggling with filter select button in AM & SAM.\0"},
{ MENU_FP_AM_04, "Filter bandwidth #4 when toggling with filter select button in AM & SAM.\0"},
{ CONFIG_AM_TX_FILTER_DISABLE, "Select if AM-TX signal is filtered (strongly recommended to agree to regulations).\0"},
{ CONFIG_SSB_TX_FILTER, "Select if SSB-TX signal is filtered (strongly recommended to agree to regulations).\0"},
{ CONFIG_TX_REVERB_GAIN, "TX reverberation gain, OFF - disabled.\0"},
{ CONFIG_TX_REVERB_DELAY, "TX reverberation delay.\0"},
{ CONFIG_TX_EQ0, "Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.\0"},
{ CONFIG_TX_EQ1, "Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.\0"},
{ CONFIG_TX_EQ2, "Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.\0"},
{ CONFIG_TX_EQ3, "Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.\0"},
{ CONFIG_TX_EQ4, "Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.\0"},
{ CONFIG_TX_DISABLE, "Disable all transmissions unconditionally. In CW you will be able to hear a sidetone but no transmission is made.\0"},
{ CONFIG_VSWR_PROTECTION_THRESHOLD, "If not OFF, on TX/tune the bias of PA will be down to 0 etc when exceeding the specified value of VSWR.\0"},
{ MENU_MIC_TYPE, "Microphone type. Electret or Dynamic. ELECTRET is recommended. Selecting DYNAMIC when an Electret mic is present will likely cause terrible audio distortion.\0"},
{ MENU_MIC_GAIN, "Microphone gain. Also changeable via Encoder 3 if Microphone is selected as Input.\0"},
{ MENU_LINE_GAIN, "LineIn gain. Also changeable via Encoder 3 if LineIn Left (L>L) or LineIn Right (L>R) is selected as Input.\0"},
{ MENU_TX_COMPRESSION_LEVEL, "Control the TX audio compressor. Higher values give more compression. Set to CUSTOM for user defined compression parameters. See below. Also changeable via Encoder 1 (CMP).\0"},
{ MENU_ALC_RELEASE, "If Audio Compressor Config is set to CUSTOM, sets the value of the Audio Compressor Release time. Otherwise shows predefined value of selected compression level.\0"},
{ MENU_ALC_POSTFILT_GAIN, "If Audio Compressor Config is set to CUSTOM, sets the value of the ALC Input Gain. Otherwise shows predefined value of selected compression level.\0"},
{ CONFIG_TUNE_POWER_LEVEL, "Select the power level for TUNE operation. May be set using the selected power level or have a fixed power level.\0"},
{ CONFIG_TUNE_TONE_MODE, "Select if single tone or two tone is generated during TUNE operation. Not persistent.\0"},
{ CONFIG_CW_PA_BIAS, "If set to a value above 0, this BIAS is used during CW transmission; otherwise normal BIAS is used during CW.\0"},
{ CONFIG_REDUCE_POWER_ON_LOW_BANDS, "If set (recommended!) frequencies below 8Mhz (40m or lower) require higher power adjust values (four times). This permits better control of generated power on these frequencies.\0"},
{ CONFIG_REDUCE_POWER_ON_HIGH_BANDS, "If set frequencies above 8Mhz (30m or higher) require higher power adjust values (four times). This permits better control of generated power on these frequencies.\0"},
{ CONFIG_PA_BIAS, "Defines the BIAS value of the PA. See Adjustment and Calibration for more information.\0"},
{ CONFIG_2200M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_630M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_160M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_80M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_60M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_40M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_30M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_20M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_17M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_15M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_12M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_10M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_6M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_4M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_2M_5W_ADJUST, "RTFM.\0"},
{ CONFIG_70CM_5W_ADJUST, "RTFM.\0"},
{ CONFIG_23CM_5W_ADJUST, "RTFM.\0"},
{ CONFIG_2200M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_630M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_160M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_80M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_60M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_40M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_30M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_20M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_17M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_15M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_12M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_10M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_6M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_4M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_2M_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_70CM_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_23CM_FULL_POWER_ADJUST, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_2200M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_630M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_160M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_80M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_40M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_20M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_15M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_10M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_6M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_2M_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_70CM_ADJ, "RTFM.\0"},
{ CONFIG_FWD_REV_COUPLING_23CM_ADJ, "RTFM.\0"},
{ CONFIG_160M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_160M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_80M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_80M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_40M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_40M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_30M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_30M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_20M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_20M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_17M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_17M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_15M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_15M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_12M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_12M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_10M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_10M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_10M_UP_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_10M_UP_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_6M_TX_IQ_GAIN_BAL, "RTFM.\0"},
{ CONFIG_6M_TX_IQ_PHASE_BAL, "RTFM.\0"},
{ CONFIG_160M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_160M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_80M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_80M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_40M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_40M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_30M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_30M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_20M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_20M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_17M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_17M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_15M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_15M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_12M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_12M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_10M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_10M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_10M_UP_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_10M_UP_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_6M_TX_IQ_GAIN_BAL_TRANS_OFF, "RTFM.\0"},
{ CONFIG_6M_TX_IQ_PHASE_BAL_TRANS_OFF, "RTFM.\0"},
{ MENU_INPUT_STATE, "Amber - State of RX input group.\0"},
{ MENU_DYNAMICTUNE, "Toggles dynamic tune mode.\0"},
{ MENU_MIC_LINE_MODE, "Select the required signal input for transmit (except in CW). Also changeable via long press on M3.\0"},
{ MENU_SPECTRUM_MODE, "Select if you want a scope-like or a waterfall-like (actually a fountain) display.\0"},
{ MENU_SPECTRUM_MAGNIFY, "Select level of magnification (1x, 2x, 4x, 8x, 16x, 32x) of spectrum and waterfall display. Also changeable via touch screen. Refresh rate is much slower with high magnification settings. The dBm display has its maximum accuracy in magnify 1x setting.\0"},
{ MENU_RESTART_CODEC, "Sometimes there is a problem with the I2S IQ signal stream from the Codec, resulting in mirrored signal reception. Restarting the CODEC Stream will cure that problem. Try more than once, if first call did not help.\0"},
{ MENU_DIGITAL_MODE_SELECT, "Select the active digital mode (FreeDV,RTTY, ...).\0"},
{ INFO_DISPLAY, "Displays working mode (SPI/parallel.\0"},
{ INFO_DISPLAY_CTRL, "Identified LCD controller chip.\0"},
{ INFO_OSC_NAME, "Local oscillator type.\0"},
{ INFO_SI570, "Startup frequency and I2C address of local oscillator Type SI570.\0"},
{ INFO_EEPROM, "Type of serial EEPROM and its capacity.\0"},
{ INFO_TP, "Touchscreen state.\0"},
{ INFO_CPU, "Identification of fitted MCU.\0"},
{ INFO_FLASH, "Flash size of MCU.\0"},
{ INFO_RAM, "RAM size of MCU.\0"},
{ INFO_FW_VERSION, "Firmware version.\0"},
{ INFO_BUILD, "Firmware: timestamp of building.\0"},
{ INFO_BL_VERSION, "Bootloader version.\0"},
{ INFO_RFBOARD, "Displays the detected RF Board hardware identification.\0"},
{ INFO_CODEC, "Audio Codec I2C communication successfully tested? This is not a full test of the Audio Codec functionality, it only reports if I2C communication reported no problem talking to the codec.\0"},
{ INFO_CODEC_TWINPEAKS, "In some cases the audio codec needs to be restarted to produce correct IQ. The IQ auto correction detects this. If this fixes the problem, Done is displayed, Failed otherwise.\0"},
{ INFO_VBAT, "Battery Support for Backup RAM present?\0"},
{ INFO_RTC, "Battery Supported Real Time Clock present?\0"},
{ INFO_LO_TX_SUPR_DACs, "LO_TX Supression DACs (0/1) are present?\0"},
{ INFO_AMBER_IO8, "Amber - I/Ox8 PCF8574A is present?\0"},
{ INFO_AMBER_IO4, "Amber - I/Ox4 PCA9536 is present?\0"},
{ INFO_AMBER_DAC_PWR_TX, "Amber - DAC MCP4725 for TX PWR reg. is present?\0"},
{ INFO_LICENCE, "Display license of firmware.\0"},
{ INFO_HWLICENCE, "Display license of hardware.\0"},
{ MENU_DEBUG_ENABLE_INFO, "Enable debug outputs on LCD for testing purposes (touch screen coordinates, load) and audio interrupt duration indication via green led.\0"},
{ CONFIG_FWD_REV_PWR_DISP, "Shows the forward and reverse power values in mW, can be used to calibrate the SWR meter.\0"},
{ MENU_DEBUG_CW_OFFSET_SHIFT_KEEP_SIGNAL, "Enable automatic sidetone correction for CW OFFSET MODE = SHIFT. If you tuned in SSB to a CW signal around the sidetone frequency, you'll keep that signal when going to CW. Even if you switch from USB to CW-LSB etc.\0"},
{ MENU_DEBUG_TX_AUDIO, "If enabled, send generated audio to PC during TX.\0"},
{ MENU_DEBUG_CLONEOUT, "Will in future send out memory data to an FT817 Clone Info (to be used with CHIRP).\0"},
{ MENU_DEBUG_CLONEIN, "Will in future get memory data from an FT817 Clone Info (to be used with CHIRP).\0"},
#ifdef USE_TWO_CHANNEL_AUDIO
{ MENU_DEBUG_ENABLE_STEREO, "Enable stereo demodulation modes.\0"},
#endif
{ MENU_DEBUG_OSC_SI5351_PLLRESET, "Debug Setting: Select when the Si5351a does a PLL RESET.\0"},
{ MENU_DEBUG_HMC1023_COARSE, "Debug Setting: Change LPF HMC1023LP5E coarse bandwidth.\0"},
{ MENU_DEBUG_HMC1023_FINE, "Debug Setting: Change LPF HMC1023LP5E fine bandwidth.\0"},
{ MENU_DEBUG_HMC1023_GAIN, "Debug Setting: Switch LPF HMC1023LP5E +10db Amp on/off.\0"},
{ MENU_DEBUG_HMC1023_BYPASS, "Debug Setting: Set HMC1023 to bypass mode.\0"},
{ MENU_DEBUG_HMC1023_OPAMP, "Debug Setting: Switch LPF HMC1023LP5E Opamp Bias.\0"},
{ MENU_DEBUG_HMC1023_DRVR, "Debug Setting: Set HMC1023 Driver Bias.\0"},
{ MENU_DEBUG_TWINPEAKS_CORR_RUN, "Trigger Twinpeaks Correction Manually if IQ Auto Correction is enabled, otherwise you will see Not Possible.\0"},
{ MENU_DEBUG_CB_27MC_TX_ENABLE, "Enable transmitting (4W) on CB band 27 MHz (AM, FM, SSB, CW).\0"},
{ MENU_DEBUG_CB_26MC_TX_ENABLE, "Enable transmitting (4W) on CB band 26 MHz (AM, FM, SSB, CW).\0"},
{ MENU_DEBUG_CB_12W_SSB_TX_ENABLE, "Enable transmitting 12W SSB on CB bands, where TX is open.\0"},
{ MENU_DEBUG_CB_10W_TX_ENABLE, "Enable transmitting 10W for any mode on CB bands, where TX is open.\0"},
{ MENU_DEBUG_CAL_LO_TX_SUPR_0, "Calibration of LO_TX Supression on every band via balancing of TX mixer, channel 0.\0"},
{ MENU_DEBUG_CAL_LO_TX_SUPR_1, "Calibration of LO_TX Supression on every band via balancing of TX mixer, channel 1.\0"},
{ MENU_DEBUG_SHOW_GREETING, "Not for users.\0"},
{ MENU_DEBUG_SMOOTH_DYN_TUNE, "Activate smooth dynamic tune.\0"},
{ MENU_DEBUG_CLEAN_TX_CW_RTTY_BPSK, "Forming CW/RTTY/BPSK signal at intermediate frequency for clean TX.\0"},
{ MENU_DEBUG_MEM_BW_MOD_BAND, "Remember the filter settings of each mode in each range for the duration of the session.\0"},
{ MENU_DEBUG_ILLUM_BUTT, "Illumination of buttons.\0"},
{ MENU_DEBUG_BPF_OPTION, "3 extra BPF instead of 2 on Amber-RF board.\0"},
{ MENU_DEBUG_XVTR_OFF_PA, "Transverter mode - blocking PA on TX. The optional 'XVTR TX' SMA connector must be soldered and connected with coaxial cable to the output of the amplifier before PA driver (XVTR_TX contacts).\0"},
{ MENU_DEBUG_BANDCODE, "PA bandcode variant, if not OFF.\0"},
{ MENU_DEBUG_ALT_PWR_CTRL, "Alternative POWER lewel control ON/OFF.\0"},
{ MENU_DEBUG_ALT_PWR_CTRL_VOL, "Alternative POWER lewel control - DAC volume in points, 0-4096 (0-5V).\0"},
{ MENU_DEBUG_DISABLE_TP, "Disable touchscreen actions.\0"},
{ MENU_DEBUG_FMENUS_SEL, "Type of F-menus selection.\0"},
{ MENU_DEBUG_IMPROV_IQ_ADJ, "Improved I/Q adjusting. Added 160, 40, 30, 17, 12m.\0"},
{ MENU_DEBUG_BEEP_GEN, "Activate beep (as button beep set) when the band border is crossed.\0"},
{ MENU_DEBUG_F6_IND_SEL, "Amber 4 inch - Indication of F6 button.\0"},
{ MENU_DEBUG_F7_IND_SEL, "Amber 4 inch - Indication of F7 button.\0"},
{ MENU_DEBUG_BAND_OFF_160M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_80M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_60M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_40M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_30M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_20M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_17M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_15M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_12M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_10M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_BAND_OFF_6M, "Remove this band from switching queue.\0"},
{ MENU_DEBUG_REDUCE_POWER_ON_LOW_BANDS_MORE, "Reduce power x20 (instead of x4) for F < 8 MHz.\0"},
};
#endif
@@ -0,0 +1,716 @@
#include "ui_menu.h"
#include "ui_menu_internal.h"
#include "uhsdr_hmc1023.h"
#include "radio_management.h"
#include "soft_tcxo.h"
#include "ui_driver.h"
/*
* How to create a new menu entry in an existing menu:
* - Copy an existing entry of MENU_KIND and paste at the desired position
* - Just assign a unique number to the "number" attribute
* - Change the label, and implement handling
*
* How to create a menu group:
* - Add menu group id entry to enum below
* - Create a MenuDescriptor Array with the desired entries, make sure to have the MENU_STOP element at last position
* and that all elements have the enum value as first attribute (menuId)
* - Added the menu group entry in the parent menu descriptor array.
* - Create a MenuState element
* - Added the menu group descriptor to the groups list at the position corresponding to the enum value
* using the descriptor array, the address of the MenuState and the address of the parent menu descriptor array.
*
*
*/
// ATTENTION: The numbering here has to be match in the groups
// data structure found more or less at the end of this
// menu definition block ! Otherwise menu display will not work
// as expected and may crash mcHF
// If you move menus around, make sure to change the groups structure of the move
// menu to reflect the new parent menu!
enum MENU_GROUP_ITEM
{
MENU_TOP = 0,
MENU_BASE,
MENU_CONF,
MENU_DISPLAY,
MENU_CW,
MENU_FILTER,
MENU_POW,
MENU_MEN2TOUCH,
MENU_SYSINFO,
MENU_DEBUG,
MENU_HALL_OF_FAME,
};
const MenuDescriptor topGroup[] =
{
{ MENU_TOP, MENU_GROUP, MENU_BASE, NULL, "Standard Menu", UiMenuDesc("Operational parameters") },
{ MENU_TOP, MENU_GROUP, MENU_CONF, NULL, "Configuration Menu", UiMenuDesc("Configuration settings typically not so often to be changed") },
{ MENU_TOP, MENU_GROUP, MENU_DISPLAY, NULL, "Display Menu", UiMenuDesc("Everything related to how the display presents data such as colors or speed of display") },
{ MENU_TOP, MENU_GROUP, MENU_CW, NULL, "CW Mode Settings", UiMenuDesc("Everything related to CW Mode operation (except CW PA Bias)") },
{ MENU_TOP, MENU_GROUP, MENU_FILTER, NULL, "Filter Selection", UiMenuDesc("Select the filters for filter button by mode. Each mode can have up to 4 filters for quick selection via short press Filter button G4.") },
{ MENU_TOP, MENU_GROUP, MENU_POW, NULL, "PA Configuration", UiMenuDesc("Menu for power amplifier parameter and tune function adjustments") },
{ MENU_TOP, MENU_GROUP, MENU_MEN2TOUCH, NULL, "Touchscreen via Menu", UiMenuDesc("All functions which are available by touchscreen here are available as menu selectables") },
{ MENU_TOP, MENU_GROUP, MENU_SYSINFO, NULL, "System Info", UiMenuDesc("Lists various system info values") },
{ MENU_TOP, MENU_GROUP, MENU_DEBUG, NULL, "Debug/Exper. Settings", UiMenuDesc("As the name says, contains debug or expert settings usually not relevant for operating the mcHF") },
{ MENU_TOP, MENU_GROUP, MENU_HALL_OF_FAME, NULL, "Hall of Fame", UiMenuDesc("Thanks to all who contributed to the project") },
{ MENU_TOP, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor baseGroup[] =
{
// { MENU_BASE, MENU_ITEM, MENU_SSB_NARROW_FILT,"029","CW Filt in SSB Mode", UiMenuDesc(":soon:") },
{ MENU_BASE, MENU_ITEM, MENU_SSB_AUTO_MODE_SELECT, NULL, "LSB/USB Auto Select", UiMenuDesc("If enabled, the appropriate sideband mode for SSB and FreeDV is chosen as default for each band by its frequency.")},
{ MENU_BASE, MENU_ITEM, MENU_DIGI_DISABLE, NULL,"Digital Modes", UiMenuDesc("Disable appearance of digital modes when pressing Mode button")},
{ MENU_BASE, MENU_ITEM, MENU_CW_DISABLE, NULL, "CW Mode", UiMenuDesc("Disable appearance of CW mode when pressing Mode button")},
{ MENU_BASE, MENU_ITEM, MENU_AM_DISABLE, NULL, "AM Mode", UiMenuDesc("Disable appearance of AM mode when pressing Mode button")},
{ MENU_BASE, MENU_ITEM, MENU_DEMOD_SAM, NULL,"SyncAM Mode",UiMenuDesc("Disable appearance of SyncAM modes when pressing Mode button") },
{ MENU_BASE, MENU_ITEM, MENU_SAM_PLL_LOCKING_RANGE, NULL, "SAM PLL locking range", UiMenuDesc("SAM PLL Locking Range in Hz: this determines how far up and down from the carrier frequency of an AM station we can offtune the receiver, so that the PLL will still lock to the carrier.") },
{ MENU_BASE, MENU_ITEM, MENU_SAM_PLL_STEP_RESPONSE, NULL, "SAM PLL step response", UiMenuDesc("Step response = Zeta = damping factor of the SAM PLL. Sets the stability and transient response of the PLL. Larger values give faster lock even if you are offtune, but PLL is also more sensitive.") },
{ MENU_BASE, MENU_ITEM, MENU_SAM_PLL_BANDWIDTH, NULL, "SAM PLL bandwidth in Hz", UiMenuDesc("Bandwidth of the PLL loop = OmegaN in Hz: smaller bandwidth = more stable lock. FAST LOCK SAM PLL - set Step response and PLL bandwidth to large values [eg. 80 / 350]; DX (SLOW & STABLE) SAM PLL - set Step response and PLL bandwidth to small values [eg. 30 / 100].") },
{ MENU_BASE, MENU_ITEM, MENU_SAM_FADE_LEVELER, NULL, "SAM Fade Leveler", UiMenuDesc("Fade leveler (in AM/SAM mode) ON/OFF. Fade leveler is helpful in situations with very fast QSB of the carrier ´flutter´. It is designed to remove the rapidly changing carrier and replace it with a more stable carrier. If there is no QSB on the carrier, there is no change.") },
{ MENU_BASE, MENU_ITEM, MENU_FM_MODE_ENABLE, NULL, "FM Mode", UiMenuDesc("Disable appearance of FM mode when pressing Mode button")},
{ MENU_BASE, MENU_ITEM, MENU_FM_GEN_SUBAUDIBLE_TONE, NULL, "FM Sub Tone Gen", UiMenuDesc("Enable generation of CTCSS tones during FM transmissions.") },
{ MENU_BASE, MENU_ITEM, MENU_FM_DET_SUBAUDIBLE_TONE, NULL, "FM Sub Tone Det", UiMenuDesc("Enable detection of CTCSS tones during FM receive. RX is muted unless tone is detected.") },
{ MENU_BASE, MENU_ITEM, MENU_FM_TONE_BURST_MODE, NULL, "FM Tone Burst", UiMenuDesc("Enabled sending of short tone at beginning of each FM transmission. Used to open repeaters. Available frequencies are 1750 Hz and 2135 Hz.") },
{ MENU_BASE, MENU_ITEM, MENU_FM_DEV_MODE, NULL, "FM Deviation", UiMenuDesc("Select between normal and narrow deviation (5 and 2.5kHz) for FM RX/TX") },
#ifdef USE_FREEDV
{ MENU_BASE, MENU_ITEM, MENU_DEBUG_FREEDV_MODE, NULL, "FreeDV Mode", UiMenuDesc("Change active FreeDV mode. Please note, you have to reboot to activate new mode") },
{ MENU_BASE, MENU_ITEM, MENU_DEBUG_FREEDV_SQL_THRESHOLD, NULL, "FreeDV Squelch threshold", UiMenuDesc("If not OFF, FreeDV will squelch if detected SNR is below set value.") },
#endif
// { MENU_BASE, MENU_ITEM, MENU_RF_GAIN_ADJ, NULL, "RF Gain", UiMenuDesc("RF Receive Gain. This setting is also accessible via Encoder 2, RFG.") }, // also via knob
// { MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_SWITCH, NULL, "AGC Mode Switch", UiMenuDesc("You can choose between two different AGC systems here: ´Standard AGC´ and ´WDSP AGC´.") },
// { MENU_BASE, MENU_ITEM, MENU_AGC_MODE, NULL, "AGC STD Mode", UiMenuDesc("Standard AGC: Automatic Gain Control Mode setting. You may select preconfigured settings (SLOW,MED,FAST), define settings yourself (CUSTOM) or use MANUAL (no AGC, use RFG to control gain") },
// { MENU_BASE, MENU_ITEM, MENU_CUSTOM_AGC, NULL, "AGC STD Custom Speed (+=Slower)", UiMenuDesc("Standard AGC: If AGC STD Mode is set to CUSTOM, this controls the speed setting of AGC") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_MODE, NULL, "AGC WDSP Mode", UiMenuDesc("Choose a bundle of preset AGC parameters for the WDSP AGC: FAST / MED / SLOW / LONG / very LONG or switch OFF the AGC.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_SLOPE, NULL, "AGC WDSP Slope", UiMenuDesc("Slope of the AGC is the difference between the loudest signal and the quietest signal after the AGC action has taken place. Given in dB.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_TAU_DECAY, NULL, "AGC WDSP Decay", UiMenuDesc("Time constant for the AGC decay (speed of recovery of the AGC gain) in milliseconds.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_THRESH, NULL, "AGC WDSP Threshold", UiMenuDesc("Threshold = Knee of the AGC: input signal level from which on the AGC action takes place. AGC threshold should be placed/adjusted just above the band noise for every particular RX situation to allow for optimal AGC action. The blue AGC box indicates when AGC action takes place and helps in adjusting this threshold.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_HANG_ENABLE, NULL, "AGC WDSP Hang enable", UiMenuDesc("Enable/Disable Hang AGC function: If enabled: after the signal has decreased, the gain of the AGC is held constant for a certain time period (the hang time) in order to allow for speech pauses without disturbing noise because of fast acting AGC.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_HANG_TIME, NULL, "AGC WDSP Hang time", UiMenuDesc("Hang AGC: hang time is the time period over which the AGC gain is held constant when in AGC Hang mode. After this period the gain is increased fast.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_HANG_THRESH, NULL, "AGC WDSP Hang threshold", UiMenuDesc("´Threshold´ for the Hang AGC: Hang AGC is useful for medium to strong signals. The Hang threshold determines the signal strength a signal has to exceed for Hang AGC to take place.") },
{ MENU_BASE, MENU_ITEM, MENU_AGC_WDSP_TAU_HANG_DECAY, NULL, "AGC WDSP Hang Decay", UiMenuDesc("Time constant for the Hang AGC decay (speed of recovery of the AGC gain after hang time has expired) in milliseconds.") },
{ MENU_BASE, MENU_ITEM, MENU_CODEC_GAIN_MODE, NULL, "RX Codec Gain", UiMenuDesc("Sets the Codec IQ signal gain. Higher values represent higher gain. If set to AUTO the mcHF controls the gain so that the best dynamic range is used.") },
{ MENU_BASE, MENU_ITEM, MENU_RX_FREQ_CONV, NULL, "RX/TX Freq Xlate", UiMenuDesc("Controls offset of the receiver IQ signal base frequency from the dial frequency. Use of +/-12Khz is recommended. Switching it to OFF is not recommended as it disables certain features.") },
// { MENU_BASE, MENU_ITEM, MENU_MIC_TYPE, NULL, "Mic Type", UiMenuDesc("Microphone type. Electret or Dynamic. ELECTRET is recommended. Selecting DYNAMIC when an Electret mic is present will likely cause terrible audio distortion") },
// { MENU_BASE, MENU_ITEM, MENU_MIC_GAIN, NULL, "Mic Input Gain", UiMenuDesc("Microphone gain. Also changeable via Encoder 3 if Microphone is selected as Input") },
// { MENU_BASE, MENU_ITEM, MENU_LINE_GAIN, NULL, "Line Input Gain", UiMenuDesc("LineIn gain. Also changeable via Encoder 3 if LineIn Left (L>L) or LineIn Right (L>R) is selected as Input") },
// { MENU_BASE, MENU_ITEM, MENU_TX_COMPRESSION_LEVEL, NULL, "TX Audio Compress", UiMenuDesc("Control the TX audio compressor. Higher values give more compression. Set to CUSTOM for user defined compression parameters. See below. Also changeable via Encoder 1 (CMP).") },
// { MENU_BASE, MENU_ITEM, MENU_ALC_RELEASE, NULL, "TX ALC Release Time", UiMenuDesc("If Audio Compressor Config is set to CUSTOM, sets the value of the Audio Compressor Release time. Otherwise shows predefined value of selected compression level.") },
// { MENU_BASE, MENU_ITEM, MENU_ALC_POSTFILT_GAIN, NULL, "TX ALC Input Gain", UiMenuDesc("If Audio Compressor Config is set to CUSTOM, sets the value of the ALC Input Gain. Otherwise shows predefined value of selected compression level.") },
// { MENU_BASE, MENU_ITEM, MENU_NOISE_BLANKER_SETTING, NULL, "RX NB Setting", UiMenuDesc("Set the Noise Blanker strength. Higher values mean more agressive blanking. Also changeable using Encoder 2 if Noise Blanker is active.") },
// { MENU_BASE, MENU_ITEM, MENU_DSP_NR_STRENGTH, NULL, "DSP NR Strength", UiMenuDesc("Set the Noise Reduction Strength. Higher values mean more agressive noise reduction but also higher CPU load. Use with extreme care. Also changeable using Encoder 2 if DSP is active.") }, // via knob
// { MENU_BASE, MENU_ITEM, MENU_TCXO_MODE, NULL, "TCXO Off/On/Stop", UiMenuDesc("The software TCXO can be turned ON (set frequency is adjusted so that generated frequency matches the wanted frequency); OFF (no correction or measurement done); or STOP (no correction but measurement).") },
// { MENU_BASE, MENU_ITEM, MENU_TCXO_C_F, &lo.sensor_present, "TCXO Temp. (C/F)", UiMenuDesc("Show the measure TCXO temperature in Celsius or Fahrenheit.") },
//#ifdef USE_CONFIGSTORAGE_FLASH
// { MENU_BASE, MENU_ITEM, MENU_BACKUP_CONFIG, NULL, "Backup Config", UiMenuDesc("Backup your I2C Configuration to flash. If you don't have suitable I2C EEPROM installed this function is not available.") },
//#endif
// { MENU_BASE, MENU_ITEM, MENU_LOW_POWER_SHUTDOWN, NULL, "Low Voltage Shutdown", UiMenuDesc("Shutdown automatically when supply voltage is below threshold for 60 seconds (only in RX).") },
//#ifdef USE_CONFIGSTORAGE_FLASH
// { MENU_BASE, MENU_ITEM, MENU_RESTORE_CONFIG, NULL, "Restore Config", UiMenuDesc("Restore your I2C Configuration from flash. If you don't have suitable I2C EEPROM installed this function is not available.") },
//#endif
{ MENU_BASE, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor confGroup[] =
{
// Unused in firmware: { MENU_CONF, MENU_ITEM, CONFIG_FREQ_LIMIT_RELAX,"231","Freq. Limit Disable", UiMenuDesc(":soon:") },
#ifdef USE_CONFIGSTORAGE_FLASH
{ MENU_CONF, MENU_ITEM, MENU_BACKUP_CONFIG, NULL, "Backup Config", UiMenuDesc("Backup your I2C Configuration to flash. If you don't have suitable I2C EEPROM installed this function is not available.") },
{ MENU_CONF, MENU_ITEM, MENU_RESTORE_CONFIG, NULL, "Restore Config", UiMenuDesc("Restore your I2C Configuration from flash. If you don't have suitable I2C EEPROM installed this function is not available.") },
// Reset I2C Config EEPROM to empty state
{ MENU_CONF, MENU_ITEM, CONFIG_RESET_SER_EEPROM, NULL, "Rst Conf EEPROM", UiMenuDesc("Clear the EEPROM so that at next start all stored configuration data is reset to the values stored in Flash (see Backup/Restore).") },
{ MENU_CONF, MENU_ITEM, CONFIG_RESET_SER_EEPROM_SIGNATURE, NULL, "RstEEPROM&KeepConf", UiMenuDesc("Clear the EEPROMi signature but keep all config values. This is mainly for debugging purposes).") },
#endif
{ MENU_CONF, MENU_ITEM, CONFIG_BANDEF_SELECT, NULL, "Band Definition", UiMenuDesc("Select which band definition to use for ham bands (Original UHSDR or IARU Region 1 - 3") },
{ MENU_CONF, MENU_ITEM, CONFIG_FREQ_MEM_LIMIT_RELAX, NULL, "Save Out-Of-Band Freq.", UiMenuDesc("Select ON to save and restore frequencies which do not fit into the band during configuration saving (Power-Off or long press on Menu button)") },
{ MENU_CONF, MENU_ITEM, CONFIG_TX_OUT_ENABLE, NULL, "TX on Out-Of-Band Freq.", UiMenuDesc("Permit low power transmission even if the frequency is out of the official ham bands. DO NOT USE WITH CONNECTED ANTENNA! Use a dummy load!") },
// { MENU_CONF, MENU_ITEM, CONFIG_TX_DISABLE, NULL, "Transmit Disable", UiMenuDesc("Disable all transmissions unconditionally. In CW you will be able to hear a sidetone but no transmission is made.") },
// { MENU_CONF, MENU_ITEM, CONFIG_VSWR_PROTECTION_THRESHOLD, NULL, "VSWR Protect.threshold", UiMenuDesc("If not OFF, on TX/tune the bias of PA will be down to 0 etc when exceeding the specified value of VSWR") },
{ MENU_CONF, MENU_ITEM, CONFIG_AUDIO_MAIN_SCREEN_MENU_SWITCH, NULL, "Menu SW on TX disable", UiMenuDesc("Control if the screen automatically adapts Encoder value focus when switching between RX and TX.") },
{ MENU_CONF, MENU_ITEM, CONFIG_MUTE_LINE_OUT_TX, NULL, "TX Mute LineOut", UiMenuDesc("During transmission with frequency translation off, line out will carry one of the two signal channels. Good for CW but not very useful otherwise. You may switch this signal off here.") },
{ MENU_CONF, MENU_ITEM, CONFIG_TXRX_SWITCH_AUDIO_MUTE, NULL, "TX Initial Muting Time", UiMenuDesc("When switching from RX to TX the audio and HF output will be muted for roughly VALUE ms. There are now several minimum times for muting defined in the firmware:<br/><br/> Input from Mic: 40ms<br/> Input from Line In: 40ms<br/> Digital Inputs (CW, USB): less than 1ms.<br/><br/> If the user defined 'TX Initial Muting Time' is set to more than zero, the maximum of both fixed input time and user defined time is used. Your microphone PTT switch is a potential source of noise if Mic is input! You need to increase the delay or change switches!") },
{ MENU_CONF, MENU_ITEM, CONFIG_MAX_VOLUME, NULL, "Max Volume", UiMenuDesc("Set maximum speaker&headphone volume.") },
// { MENU_CONF, MENU_ITEM, CONFIG_MAX_RX_GAIN, NULL, "Max RX Gain (0=Max)", UiMenuDesc("Here you can set maximum gain for RX. A good choice is 3...5. If set to 0 RX is too sensitive in most working conditions.") },
{ MENU_CONF, MENU_ITEM, CONFIG_LINEOUT_GAIN, NULL, "Lineout Gain", UiMenuDesc("Set the constant gain level for the analog lineout jack") },
// UI Behavior / Key Beep
{ MENU_CONF, MENU_ITEM, CONFIG_BEEP_FREQ, NULL, "Key Beep Frequency", UiMenuDesc("Set key beep frequency in Hz.") },
{ MENU_CONF, MENU_ITEM, CONFIG_BEEP_VOLUME, NULL, "Key Beep Volume", UiMenuDesc("Set key beep volume.") },
// USB CAT Related
{ MENU_CONF, MENU_ITEM, CONFIG_CAT_IN_SANDBOX, NULL, "CAT Running In Sandbox", UiMenuDesc("If On, frequency Changes made via CAT will not automatically switch bands and affect the manually selected frequencies.") },
{ MENU_CONF, MENU_ITEM, CONFIG_CAT_XLAT, NULL, "CAT-DIQ-FREQ-XLAT", UiMenuDesc("Select which frequency is reported via CAT Interface to the connected PC in Digital IQ Mode. If ON, it reports the displayed frequency. If OFF, it reports the center frequency, which is more useful with SDR programs.") },
{ MENU_CONF, MENU_ITEM, CONFIG_CAT_PTT_RTS, NULL, "PTT via virtual RTS", UiMenuDesc("The virtual serial port signal RTS can be used to switch to TX. Use with care, many CAT-able programs also set RTS to aktiv and make the TRX go to TX mode.") },
// Transverter Configuration
{ MENU_CONF, MENU_ITEM, CONFIG_XVTR_OFFSET_MULT, NULL, "XVTR Offs/Mult", UiMenuDesc("When connecting to a transverter, set this to 1 and set the XVERTER Offset to the LO Frequency of it. The mcHF frequency is multiplied by this factor before the offset is added, so anything but 1 will result in each Hz in the mcHF being displayed as 2 to 10 Hz change on display.") },
// { MENU_CONF, MENU_ITEM, CONFIG_XVTR_FREQUENCY_OFFSET, NULL, "XVTR Offset", UiMenuDesc("When transverter mode is enabled, this value is added to the mcHF frequency after being multiplied with the XVTR Offs/Mult. Use Step+ to set a good step width, much less turns with the dial knob if it is set to 1Mhz") },
{ MENU_CONF, MENU_ITEM, CONFIG_XVTR_FREQUENCY_OFFSET, NULL, "XVTR Offs. RX", UiMenuDesc("When transverter mode is enabled, this value is added to the mcHF frequency after being multiplied with the XVTR Offs/Mult. Use Step+ to set a good step width, much less turns with the dial knob if it is set to 1Mhz") },
// { MENU_CONF, MENU_ITEM, CONFIG_XVTR_OFFSET_MULT, NULL, "XVTR Offs/Mult", UiMenuDesc("When connecting to a transverter, set this to 1 and set the XVERTER Offset to the LO Frequency of it. The mcHF frequency is multiplied by this factor before the offset is added, so anything but 1 will result in each Hz in the mcHF being displayed as 2 to 10 Hz change on display.") },
{ MENU_CONF, MENU_ITEM, CONFIG_XVTR_FREQUENCY_OFFSET_TX, NULL, "XVTR Offs. TX", UiMenuDesc("When transverter mode is enabled, this value is added to the displayed mcHF TX frequency after being multiplied with the XVTR Offs/Mult. Setting it to 0 uses RX offset for TX. Use Step+ to set a good step width, much less turns with the dial knob if it is set to 1Mhz") },
// Button Handling Setup
{ MENU_CONF, MENU_ITEM, CONFIG_STEP_SIZE_BUTTON_SWAP, NULL, "Step Button Swap", UiMenuDesc("If ON, Step- behaves like Step+ and vice versa.") },
{ MENU_CONF, MENU_ITEM, CONFIG_BAND_BUTTON_SWAP, NULL, "Band+/- Button Swap", UiMenuDesc("If ON, Band- behaves like Band+ and vice versa.") },
{ MENU_CONF, MENU_ITEM, CONFIG_BANDCH_JUMP_SWAP, NULL, "Band+/- BndCh/Jump Swap", UiMenuDesc("If ON, LongAction of Band+/- is band change, ShortAction is jump by freq on panorama width.") },
{ MENU_CONF, MENU_ITEM, CONFIG_ENC1_REVERSE, NULL, "Encoder 1 Reverse", UiMenuDesc("If ON, encoder 1 are reversed.") },
{ MENU_CONF, MENU_ITEM, CONFIG_ENC2_REVERSE, NULL, "Encoder 2 Reverse", UiMenuDesc("If ON, encoder 2 are reversed.") },
{ MENU_CONF, MENU_ITEM, CONFIG_ENC3_REVERSE, NULL, "Encoder 3 Reverse", UiMenuDesc("If ON, encoder 3 are reversed.") },
{ MENU_CONF, MENU_ITEM, CONFIG_ENC4_REVERSE, NULL, "Encoder 4 Reverse", UiMenuDesc("If ON, encoder 4 are reversed.") },
// // RTC Setup and Settings
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_START, &ts.vbat_present,"RTC Start", UiMenuDesc("Start using the RTC and use the modified button layout. Will reboot your mcHF. Please use only if you completed the RTC mod otherwise you will need to disconnect battery and power and reboot to get a working mcHF. This menu is only visible if Backup RAM (VBat) was detected.") },
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_HOUR, &ts.rtc_present,"RTC Hour", UiMenuDesc("Sets the Real Time Clock Hour. Needs HW Modifications.") },
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_MIN, &ts.rtc_present,"RTC Min", UiMenuDesc("Sets the Real Time Clock Minutes. Needs HW Modifications.") },
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_SEC, &ts.rtc_present,"RTC Seconds", UiMenuDesc("Sets the Real Time Clock Seconds. Needs HW Modifications.") },
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_RESET, &ts.vbat_present,"RTC Reset", UiMenuDesc("Full Reset of STM32 RTC. Can be used to simulate first start with RTC mod completed") },
// { MENU_CONF, MENU_ITEM, CONFIG_RTC_CALIB, &ts.rtc_present,"RTC Calibration", UiMenuDesc("Sets the Real Time Clock Frequency calibration value in ppm. 1s/day deviation equals 11.57 ppm deviation") },
// mcHF Setup Calibration (Initial Setup, never to be changed unless HW changes)
{ MENU_CONF, MENU_ITEM, CONFIG_VOLTMETER_CALIBRATION, NULL, "Voltmeter Cal.", UiMenuDesc("Adjusts the displayed value of the voltmeter.") },
{ MENU_CONF, MENU_ITEM, CONFIG_LOW_POWER_THRESHOLD, NULL, "Low Voltage Threshold", UiMenuDesc("Voltage threshold for voltage warning colors and auto shutdown.") },
{ MENU_CONF, MENU_ITEM, MENU_LOW_POWER_SHUTDOWN, NULL, "Low Voltage Shutdown", UiMenuDesc("Shutdown automatically when supply voltage is below threshold for 60 seconds (only in RX).") },
{ MENU_CONF, MENU_ITEM, CONFIG_FREQUENCY_CALIBRATE, NULL, "Freq. Calibrate", UiMenuDesc("Adjust the frequency correction of the local oscillator. Measure TX frequency and adjust until both match. Or use receive a know reference signal and zero-beat it and then adjust. More information in the Wiki.") },
// { MENU_CONF, MENU_ITEM, CONFIG_FWD_REV_PWR_DISP, NULL, "Pwr. Display mW", UiMenuDesc("Shows the forward and reverse power values in mW, can be used to calibrate the SWR meter.") },
{ MENU_CONF, MENU_ITEM, CONFIG_RF_FWD_PWR_NULL, NULL, "Pwr. Det. Null", UiMenuDesc(" Set the forward and reverse power sensors ADC zero power offset. This setting is enabled ONLY when Disp. Pwr (mW), is enabled. Needs SWR meter hardware modification to work. See Wiki Adjustment and Calibration.") },
{ MENU_CONF, MENU_ITEM, CONFIG_FWD_REV_SENSE_SWAP, NULL, "SWR/PWR Meter FWD/REV Swap", UiMenuDesc("Exchange the assignment of the Power/SWR FWD and REV measurement ADC. Use if your power meter does not show anything during TX.") },
#ifdef STM32F4
// Not supported on STM32F7 HAL
{ MENU_CONF, MENU_ITEM, CONFIG_I2C1_SPEED, NULL,"I2C1 Bus Speed", UiMenuDesc("Sets speed of the I2C1 bus (Si570 oscillator and MCP9801 temperature sensor). Higher speeds provide quicker RX/TX switching but may also cause tuning issues (red digits). Be careful with speeds above 200 kHz.") },
{ MENU_CONF, MENU_ITEM, CONFIG_I2C2_SPEED, NULL,"I2C2 Bus Speed", UiMenuDesc("Sets speed of the I2C2 bus (Audio Codec and I2C EEPROM). Higher speeds provide quicker RX/TX switching, configuration save and power off. Speeds above 200 kHz are not recommended for unmodified mcHF. Many modified mcHF seem to run with 300kHz without problems.") },
#endif
{ MENU_CONF, MENU_ITEM, CONFIG_IQ_AUTO_CORRECTION, NULL, "RX IQ Auto Correction", UiMenuDesc("Receive IQ phase and amplitude imbalance can be automatically adjusted by the mcHF. Switch ON/OFF here. If OFF, it takes the following menu values for compensating the imbalance. The automatic algorithm achieves up to 60dB mirror rejection. See Wiki Adjustments and Calibration.") },
{ MENU_CONF, MENU_ITEM, CONFIG_80M_RX_IQ_GAIN_BAL, &ts.display_rx_iq, "RX IQ Balance (80m)", UiMenuDesc("IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
{ MENU_CONF, MENU_ITEM, CONFIG_80M_RX_IQ_PHASE_BAL, &ts.display_rx_iq, "RX IQ Phase (80m)", UiMenuDesc("IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
{ MENU_CONF, MENU_ITEM, CONFIG_10M_RX_IQ_GAIN_BAL, &ts.display_rx_iq, "RX IQ Balance (10m)", UiMenuDesc("IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
{ MENU_CONF, MENU_ITEM, CONFIG_10M_RX_IQ_PHASE_BAL, &ts.display_rx_iq, "RX IQ Phase (10m)", UiMenuDesc("IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable. See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_80M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (80m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Requires USB or LSB mode to be changeable. See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_80M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (80m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Requires USB or LSB mode to be changeable. See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (20m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (20m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (15m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (15m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (10m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Requires USB or LSB mode to be changeable. See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (10m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Requires USB or LSB mode to be changeable. See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (10mUp)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (10mUp)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_80M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (80m,CW)", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_80M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (80m,CW)", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF).See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (20m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (20m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (15m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (15m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (10m,CW)", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF).See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (10m,CW)", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF).See Wiki Adjustments and Calibration.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (10mUp,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (10mUp,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
// { MENU_CONF, MENU_ITEM, CONFIG_AM_RX_GAIN_BAL,"244","AM RX IQ Bal.", UiMenuDesc(":soon:") },
// { MENU_CONF, MENU_ITEM, CONFIG_AM_RX_PHASE_BAL,"244b","AM RX IQ Phase", UiMenuDesc(":soon:") },
// { MENU_CONF, MENU_ITEM, CONFIG_FM_RX_GAIN_BAL,"245","FM RX IQ Bal.", UiMenuDesc(":soon:") },
//{ MENU_CONF, MENU_ITEM, CONFIG_AM_TX_GAIN_BAL,"254","AM TX IQ Bal.", UiMenuDesc(":soon:") },
//{ MENU_CONF, MENU_ITEM, CONFIG_FM_TX_GAIN_BAL,"255","FM TX IQ Bal.", UiMenuDesc(":soon:") },
{ MENU_CONF, MENU_ITEM, MENU_NOISE_BLANKER_SETTING, NULL, "RX NB Setting", UiMenuDesc("Set the Noise Blanker strength. Higher values mean more agressive blanking. Also changeable using Encoder 2 if Noise Blanker is active.") },
// { MENU_CONF, MENU_ITEM, MENU_DSP_NR_STRENGTH, NULL, "DSP NR Strength", UiMenuDesc("Set the Noise Reduction Strength. Higher values mean more agressive noise reduction but also higher CPU load. Use with extreme care. Also changeable using Encoder 2 if DSP is active.") }, // via knob
#ifdef OBSOLETE_NR
// DSP Configuration, probably never touched
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NR_DECORRELATOR_BUFFER_LENGTH, NULL, "DSP NR BufLen", UiMenuDesc("DSP LMS noise reduction: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NR_FFT_NUMTAPS, NULL, "DSP NR FIR NumTaps", UiMenuDesc("DSP LMS noise reduction: Number of taps in the DSP noise reduction FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.") },
// { MENU_CONF, MENU_ITEM, CONFIG_DSP_NR_POST_AGC_SELECT, NULL, "DSP NR Post-AGC", UiMenuDesc("DSP LMS noise reduction: Perform the DSP LMS noise reduction BEFORE or AFTER the AGC. NO = before AGC, YES = after AGC.") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_CONVERGE_RATE, NULL, "DSP Notch ConvRate", UiMenuDesc("DSP LMS automatic notch filter: ") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH, NULL, "DSP Notch BufLen", UiMenuDesc("DSP LMS automatic notch filter: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better -and the slower- the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_FFT_NUMTAPS, NULL, "DSP Notch FIRNumTap", UiMenuDesc("DSP LMS automatic notch filter: Number of taps in the DSP automatic notch FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.") },
// { MENU_CONF, MENU_ITEM, CONFIG_AGC_TIME_CONSTANT, NULL, "NB AGC T/C (<=Slow)", UiMenuDesc("Noise Blanker AGC time constant adjustment: Lower values are equivalent with slower Noise blanker AGC. While the menu is displayed, the noise blanker is switched OFF, so in order to test the effect of adjusting this parameter, leave the menu.") },
#endif
#ifdef USE_LMS_AUTONOTCH
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_CONVERGE_RATE, NULL, "DSP Notch ConvRate", UiMenuDesc("DSP LMS automatic notch filter: ") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_DECORRELATOR_BUFFER_LENGTH, NULL, "DSP Notch BufLen", UiMenuDesc("DSP LMS automatic notch filter: length of the audio buffer that is used for simulation of a reference for the LMS algorithm. The longer the buffer, the better -and the slower- the performance, but this buffer length must always be larger than the number of taps in the FIR filter used. Thus, a larger buffer (and larger FIR filter) uses more MCU resources.") },
{ MENU_CONF, MENU_ITEM, CONFIG_DSP_NOTCH_FFT_NUMTAPS, NULL, "DSP Notch FIRNumTap", UiMenuDesc("DSP LMS automatic notch filter: Number of taps in the DSP automatic notch FIR filter. The larger the number of taps in the filter, the better the performance, but the slower the performance of the filter and the mcHF.") },
#endif
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_GAIN_SHOW, NULL,"NR Show gains", UiMenuDesc("Debugging: show gains of spectral noise reduction") },
{ MENU_CONF, MENU_ITEM, MENU_DSP_NR_STRENGTH, NULL, "NR Strength", UiMenuDesc("Set the Noise Reduction Strength. Higher values mean more agressive noise reduction but also higher CPU load. Use with extreme care. Also changeable using Encoder 2 if DSP is active.") }, // via knob
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_BETA, NULL,"NR beta", UiMenuDesc("time constant beta for spectral noise reduction, leave at 0.85") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_ASNR, NULL,"NR asnr", UiMenuDesc("Devel 2 NR: asnr") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_WIDTH, NULL,"NR smooth wd.", UiMenuDesc("Devel 2 NR: width of gain smoothing window") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_THRESHOLD, NULL,"NR smooth thr.", UiMenuDesc("Devel 2 NR: threhold for gain smoothing") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_NR_POST_AGC_SELECT, NULL, "ANR after AGC", UiMenuDesc("DSP LMS noise reduction: Perform the DSP LMS noise reduction BEFORE or AFTER the AGC. NO = before AGC, YES = after AGC.") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_ANR_TAPS, NULL,"ANR num taps", UiMenuDesc("Number of taps of leaky LMS noise reduction") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_ANR_DELAY, NULL,"ANR corr. delay", UiMenuDesc("Delay length of leaky LMS noise reduction") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_ANR_GAIN, NULL,"ANR gain", UiMenuDesc("Gain of leaky LMS noise reduction") },
{ MENU_CONF, MENU_ITEM, MENU_DEBUG_ANR_LEAK, NULL,"ANR leak", UiMenuDesc("Leak of leaky LMS noise reduction") },
// { MENU_CONF, MENU_ITEM, CONFIG_SAM_PLL_TAUR, NULL, "SAM PLL tauR", UiMenuDesc(":soon:") },
// { MENU_CONF, MENU_ITEM, CONFIG_SAM_PLL_TAUI, NULL, "SAM PLL tauI", UiMenuDesc(":soon:") },
// { MENU_CONF, MENU_ITEM, CONFIG_SAM_SIDEBAND, NULL, "SAM Sideband", UiMenuDesc(":soon:") },
// // Reset I2C Config EEPROM to empty state
// { MENU_CONF, MENU_ITEM, CONFIG_RESET_SER_EEPROM, NULL, "Rst Conf EEPROM", UiMenuDesc("Clear the EEPROM so that at next start all stored configuration data is reset to the values stored in Flash (see Backup/Restore).") },
{ MENU_CONF, MENU_STOP, 0, NULL , NULL, UiMenuDesc("") }
};
const MenuDescriptor displayGroup[] =
{
#ifndef SDR_AMBER_480_320
{ MENU_DISPLAY, MENU_ITEM, CONFIG_WIDE_SPEC_DEF, NULL, "320x240 Def.Wide Spectrum", UiMenuDesc("Wide mode of spectrum on screen 320x240 is default.") },
# endif
{ MENU_DISPLAY, MENU_ITEM, CONFIG_LCD_AUTO_OFF_MODE, NULL, "LCD Auto Blank", UiMenuDesc("After x seconds LCD turns dark and LCD data sections stop. So power consumption is decreased and RX hum is decreased, too. LCD operation starts when using any button or the touchscreen.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_CW_DECODER_SNAP_ENABLE, NULL,"Show Tune Helper", UiMenuDesc("graphical tune helper: adjust frequency until yellow vertical line is in centre of green box --> right on CW carrier frequency") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_FREQ_STEP_MARKER_LINE, NULL, "Step Size Marker", UiMenuDesc("If enabled, you'll see a line under the digit which is currently representing the selected tuning step size") },
{ MENU_DISPLAY, MENU_ITEM, MENU_NO_SHOW_BNDMEM, NULL, "Don't Show BndMem", UiMenuDesc("Don't show BndMemory.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_CLEAR_PAN_ON_TX, NULL, "Clear Panoram on TX", UiMenuDesc("Clear panoram on TX/TUNE") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_DISP_FILTER_BANDWIDTH, NULL, "Filter BW Display", UiMenuDesc("Colour of the horizontal Filter Bandwidth indicator bar.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SPECTRUM_SIZE, NULL, "Spectrum Size", UiMenuDesc("Change height of spectrum display") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SPECTRUM_FILTER_STRENGTH, NULL, "Spectrum Filter", UiMenuDesc("Lowpass filter for the spectrum FFT. Low values: fast and nervous spectrum; High values: slow and calm spectrum.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SPECTRUM_FREQSCALE_COLOUR, NULL, "Spec FreqScale Colour", UiMenuDesc("Colour of the small frequency digits under the spectrum display.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SPECTRUM_CENTER_LINE_COLOUR, NULL, "TX Carrier Colour", UiMenuDesc("Colour of the vertical line indicating the TX carrier frequency in the spectrum or waterdall display.") },
// { MENU_DISPLAY, MENU_ITEM, CONFIG_SPECTRUM_FFT_WINDOW_TYPE, NULL, "Spectrum FFT Wind.", UiMenuDesc("Selects the window algorithm for the spectrum FFT. For low spectral leakage, Hann, Hamming or Blackman window is recommended.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_LIGHT_ENABLE, NULL, "Scope Light", UiMenuDesc("The scope uses bars (NORMAL) or points (LIGHT) to represent data. LIGHT is a little less resource intensive.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_SPEED, NULL, "Scope 1/Speed", UiMenuDesc("Lower Values: Higher refresh rate. Set to 0 to disable scope.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_AGC_ADJUST, NULL, "Scope AGC Adj.", UiMenuDesc("Adjusting of scope / waterfall AGC for fitting graphs to screen") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_TRACE_COLOUR, NULL, "Scope Trace Colour", UiMenuDesc("Set colour of scope") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_TRACE_HL_COLOUR, NULL, "Scope BW Trace Colour", UiMenuDesc("Set colour of highlighted BW scope") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_BACKGROUND_HL_COLOUR, NULL, "Scope BW BCKgr Colour", UiMenuDesc("Set colour of highlighted BW background") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_GRID_COLOUR, NULL, "Scope Grid Colour", UiMenuDesc("Set colour of scope grid") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_DB_DIVISION, NULL, "Scope Div.", UiMenuDesc("Set rf range for scope") },
// { MENU_DISPLAY, MENU_ITEM, MENU_SCOPE_NOSIG_ADJUST, NULL, "Scope NoSig Adj.", UiMenuDesc("Set scope line corresponding to NO SIGNAL") },
{ MENU_DISPLAY, MENU_ITEM, MENU_WFALL_SPEED, NULL, "Wfall 1/Speed", UiMenuDesc("Lower Values: Higher refresh rate. Set to 0 to disable waterfall.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_WFALL_COLOR_SCHEME, NULL, "Wfall Colours", UiMenuDesc("Select colour scheme for waterfall display.") },
{ MENU_DISPLAY, MENU_ITEM, MENU_WFALL_STEP_SIZE, NULL, "Wfall Step Size", UiMenuDesc("How many lines are moved in a single screen update") },
// { MENU_DISPLAY, MENU_ITEM, MENU_WFALL_OFFSET, NULL, "Wfall Brightness", UiMenuDesc("Set to input level which waterfall uses for lowest level") },
{ MENU_DISPLAY, MENU_ITEM, MENU_WFALL_CONTRAST, NULL, "Wfall Contrast", UiMenuDesc("Adjust to fit your personal input level range to displayable colour range for waterfall") },
// { MENU_DISPLAY, MENU_ITEM, MENU_WFALL_NOSIG_ADJUST, NULL, "Wfall NoSig Adj.", UiMenuDesc("Set NO SIGNAL state for waterfall") },
{ MENU_DISPLAY, MENU_ITEM, MENU_METER_COLOUR_UP, NULL, "Upper Meter Colour", UiMenuDesc("Set the colour of the scale of combined S/Power-Meter") },
{ MENU_DISPLAY, MENU_ITEM, MENU_METER_COLOUR_DOWN, NULL, "Lower Meter Colour", UiMenuDesc("Set the colour of the scale of combined SWR/AUD/ALC-Meter") },
{ MENU_DISPLAY, MENU_ITEM, MENU_BOX_COLOUR, NULL, "Boxes Colour", UiMenuDesc("Screen boxes colour") },
{ MENU_DISPLAY, MENU_ITEM, MENU_TXTLINE_COLOUR, NULL, "Ticker Colour", UiMenuDesc("Ticker colour") },
{ MENU_DISPLAY, MENU_ITEM, MENU_DBM_DISPLAY, NULL, "dBm display", UiMenuDesc("RX signal power (measured within the filter bandwidth) can be displayed in dBm or normalized as dBm/Hz. This value is supposed to be quite accurate to +-3dB. Preferably use low spectrum display magnify settings. Accuracy is lower for very very weak and very very strong signals.")},
{ MENU_DISPLAY, MENU_ITEM, MENU_DBM_CALIBRATE, NULL, "dBm calibrate", UiMenuDesc("dBm display calibration. Just an offset (in dB) that is added to the internally calculated dBm or dBm/Hz value.")},
{ MENU_DISPLAY, MENU_ITEM, CONFIG_SMETER_ATTACK, NULL, "S-Meter Attack", UiMenuDesc("Attack controls how quickly the S-Meter reacts to rising signal levels, higher values represent quicker reaction") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_SMETER_DECAY, NULL, "S-Meter Decay", UiMenuDesc("Decay controls how quickly the S-Meter reacts to falling signal levels, higher values represent quicker reaction") },
{ MENU_DISPLAY, MENU_ITEM, MENU_PEAK_IND_TUNE, NULL, "Peak Ind. Timer, ms", UiMenuDesc("Tune/OFF S/PWR meter peak indicator") },
{ MENU_DISPLAY, MENU_ITEM, MENU_SMETER_AM_NOT_LO, NULL, "S-Meter NotLO in AM", UiMenuDesc("Don't calculate LO in AM mode") },
{ MENU_DISPLAY, MENU_ITEM, MENU_TCXO_MODE, NULL, "TCXO Off/On/Stop", UiMenuDesc("The software TCXO can be turned ON (set frequency is adjusted so that generated frequency matches the wanted frequency); OFF (no correction or measurement done); or STOP (no correction but measurement).") },
{ MENU_DISPLAY, MENU_ITEM, MENU_TCXO_C_F, &lo.sensor_present, "TCXO Temp. (C/F)", UiMenuDesc("Show the measure TCXO temperature in Celsius or Fahrenheit.") },
// RTC Setup and Settings
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_START, &ts.vbat_present,"RTC Start", UiMenuDesc("Start using the RTC and use the modified button layout. Will reboot your mcHF. Please use only if you completed the RTC mod otherwise you will need to disconnect battery and power and reboot to get a working mcHF. This menu is only visible if Backup RAM (VBat) was detected.") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_HOUR, &ts.rtc_present,"RTC Hour", UiMenuDesc("Sets the Real Time Clock Hour. Needs HW Modifications.") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_MIN, &ts.rtc_present,"RTC Min", UiMenuDesc("Sets the Real Time Clock Minutes. Needs HW Modifications.") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_SEC, &ts.rtc_present,"RTC Seconds", UiMenuDesc("Sets the Real Time Clock Seconds. Needs HW Modifications.") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_RESET, &ts.vbat_present,"RTC Reset", UiMenuDesc("Full Reset of STM32 RTC. Can be used to simulate first start with RTC mod completed") },
{ MENU_DISPLAY, MENU_ITEM, CONFIG_RTC_CALIB, &ts.rtc_present,"RTC Calibration", UiMenuDesc("Sets the Real Time Clock Frequency calibration value in ppm. 1s/day deviation equals 11.57 ppm deviation") },
#ifdef USE_8bit_FONT
{ MENU_DISPLAY, MENU_ITEM, MENU_FREQ_FONT, NULL, "Freq display font", UiMenuDesc("Font selection for frequency display. Allows selection of old/modern fonts")},
#endif
{ MENU_DISPLAY, MENU_ITEM, MENU_UI_INVERSE_SCROLLING, NULL, "Menu Inverse Scrolling", UiMenuDesc("Inverts Enc2/Enc3 behavior in menu up/down and show/hide UI scrolling actions, used for side-mounted encoder dials.")},
{ MENU_DISPLAY, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor cwGroup[] =
{
// { MENU_CW, MENU_ITEM, MENU_CW_WIDE_FILT,"028","Wide Filt in CW Mode", UiMenuDesc(":soon:") },
{ MENU_CW, MENU_ITEM, MENU_KEYER_MODE, NULL, "CW Keyer Mode", UiMenuDesc("Select how the mcHF interprets the connected keyer signals. Supported modes: Iambic A and B Keyer (IAM A/B), Straight Key (STR_K), and Ultimatic Keyer (ULTIM)") },
{ MENU_CW, MENU_ITEM, MENU_KEYER_SPEED, NULL, "CW Keyer Speed", UiMenuDesc("Keyer Speed for the automatic keyer modes in WpM. Also changeable via Encoder 3 if in CW Mode.") },
{ MENU_CW, MENU_ITEM, MENU_KEYER_WEIGHT, NULL, "CW Keyer Weight", UiMenuDesc("Keyer Dit/Pause ratio for the automatic keyer modes. Higher values increase length of dit, decreases length of pause so that the total time is still according to the set WpM value.") },
{ MENU_CW, MENU_ITEM, MENU_CW_SMOOTH, NULL, "CW Sign.Eg.Smooth, ms", UiMenuDesc("Smooth of CW signal edges.") },
{ MENU_CW, MENU_ITEM, MENU_SIDETONE_GAIN, NULL, "CW Sidetone Gain", UiMenuDesc("Audio volume for the monitor sidetone in CW TX. Also changeable via Encoder 1 if in CW Mode.") },
{ MENU_CW, MENU_ITEM, MENU_SIDETONE_FREQUENCY, NULL, "CW Side/Offset Freq", UiMenuDesc("Sidetone Frequency (also Offset frequency, see CW Freq. Offset below)") },
{ MENU_CW, MENU_ITEM, MENU_PADDLE_REVERSE, NULL, "CW Paddle Reverse", UiMenuDesc("Dit is Dah and Dah is Dit. Use if your keyer needs reverse meaning of the paddles.") },
{ MENU_CW, MENU_ITEM, MENU_CW_TX_RX_DELAY, NULL, "CW TX->RX Delay", UiMenuDesc("How long to stay in CW TX mode after stop sending a signal.") },
{ MENU_CW, MENU_ITEM, MENU_CW_OFFSET_MODE, NULL, "CW Freq. Offset", UiMenuDesc("TX: display is TX frequency if received frequency was zero-beated. DISP: display is RX frequency if received signal is matched to sidetone. SHIFT: LO shifts, display is RX frequency if signal is matched to sidetone.") },
{ MENU_CW, MENU_ITEM, MENU_CW_AUTO_MODE_SELECT, NULL, "CW LSB/USB Select", UiMenuDesc("Set appropriate sideband mode for CW. If AUTO, sideband is chosen for bands by its frequency. A long press on Mode button gets the other sideband mode")},
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER, NULL,"CW decoder enable", UiMenuDesc("enable experimental CW decoding") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_THRESH, NULL,"Signal threshold", UiMenuDesc("All signals above this threshold are intepreted as a dit or daah") },
// { MENU_CW, MENU_ITEM, MENU_CW_DECODER_SNAP_ENABLE, NULL,"Tune helper", UiMenuDesc("graphical tune helper: adjust frequency until yellow vertical line is in centre of green box --> right on CW carrier frequency") },
// { MENU_CW, MENU_ITEM, MENU_CW_DECODER_AVERAGE, NULL,"Goertzel averager", UiMenuDesc("The CW tone is averaged over N Goertzel values") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_BLOCKSIZE, NULL,"Blocksize for Goertzel", UiMenuDesc("How many samples are taken for the signal detection with the Goertzel algorithm?") },
// { MENU_CW, MENU_ITEM, MENU_CW_DECODER_AGC, NULL,"AGC for decoder", UiMenuDesc("Enable/disable AGC for CW decoder") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_NOISECANCEL, NULL,"Noise cancel", UiMenuDesc("Enable/disable noise canceler for CW decoder") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_SPIKECANCEL, NULL,"Spike cancel", UiMenuDesc("Enable/disable spike canceler or short cancel for CW decoder") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_USE_3_GOERTZEL, NULL,"AGC for decoder", UiMenuDesc("Enable/disable AGC for CW decoder") },
{ MENU_CW, MENU_ITEM, MENU_CW_DECODER_SHOW_CW_LED, NULL,"Show CW LED", UiMenuDesc("Enable/disable LED for CW decoder") },
{ MENU_CW, MENU_ITEM, MENU_CW_MACRO_INTERVAL, NULL,"CW MacroCycledInterv, sec.", UiMenuDesc("CW Macros Cycled TX interval, sec.") },
{ MENU_CW, MENU_ITEM, MENU_CW_BEACON_INTERVAL, NULL,"CW Beacon Interval, min.", UiMenuDesc("CW Beacon interval, min.") },
{ MENU_CW, MENU_ITEM, MENU_CW_FAST_MACRO_1_2, NULL,"CW Fast Macro 1,2", UiMenuDesc("Enable/disable fast TXing CW macro 1 and 2") },
{ MENU_CW, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor filterGroup[] =
{
{ MENU_FILTER, MENU_ITEM, MENU_FP_SSB_01, NULL, "SSB Filter 1", UiMenuDesc("Filter bandwidth #1 when toggling with filter select button in LSB or USB.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_SSB_02, NULL, "SSB Filter 2", UiMenuDesc("Filter bandwidth #2 when toggling with filter select button in LSB or USB.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_SSB_03, NULL, "SSB Filter 3", UiMenuDesc("Filter bandwidth #3 when toggling with filter select button in LSB or USB.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_SSB_04, NULL, "SSB Filter 4", UiMenuDesc("Filter bandwidth #4 when toggling with filter select button in LSB or USB.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_CW_01, NULL, "CW Filter 1", UiMenuDesc("Filter bandwidth #1 when toggling with filter select button in CW.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_CW_02, NULL, "CW Filter 2", UiMenuDesc("Filter bandwidth #2 when toggling with filter select button in CW.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_CW_03, NULL, "CW Filter 3", UiMenuDesc("Filter bandwidth #3 when toggling with filter select button in CW.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_CW_04, NULL, "CW Filter 4", UiMenuDesc("Filter bandwidth #4 when toggling with filter select button in CW.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_AM_01, NULL, "AM/SAM Filter 1", UiMenuDesc("Filter bandwidth #1 when toggling with filter select button in AM & SAM.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_AM_02, NULL, "AM/SAM Filter 2", UiMenuDesc("Filter bandwidth #2 when toggling with filter select button in AM & SAM.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_AM_03, NULL, "AM/SAM Filter 3", UiMenuDesc("Filter bandwidth #3 when toggling with filter select button in AM & SAM.") },
{ MENU_FILTER, MENU_ITEM, MENU_FP_AM_04, NULL, "AM/SAM Filter 4", UiMenuDesc("Filter bandwidth #4 when toggling with filter select button in AM & SAM.") },
// not needed any more: AM & SAM use exactly the same filters
// { MENU_FILTER, MENU_ITEM, MENU_FP_SAM_01,"600", "SAM Filter 1", UiMenuDesc(":soon:") },
// { MENU_FILTER, MENU_ITEM, MENU_FP_SAM_02,"600", "SAM Filter 2", UiMenuDesc(":soon:") },
// { MENU_FILTER, MENU_ITEM, MENU_FP_SAM_03,"600", "SAM Filter 3", UiMenuDesc(":soon:") },
// { MENU_FILTER, MENU_ITEM, MENU_FP_SAM_04,"600", "SAM Filter 4", UiMenuDesc(":soon:") },
{ MENU_FILTER, MENU_ITEM, CONFIG_AM_TX_FILTER_DISABLE, NULL,"AM TX Audio Filter", UiMenuDesc("Select if AM-TX signal is filtered (strongly recommended to agree to regulations)") },
// { MENU_FILTER, MENU_ITEM, CONFIG_SSB_TX_FILTER_DISABLE, NULL,"SSB TX Audio Filter", UiMenuDesc(":soon:") },
{ MENU_FILTER, MENU_ITEM, CONFIG_SSB_TX_FILTER, NULL,"SSB TX Audio Filter2", UiMenuDesc("Select if SSB-TX signal is filtered (strongly recommended to agree to regulations)") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_REVERB_GAIN, NULL,"TX Reverb gain", UiMenuDesc("TX reverberation gain, OFF - disabled") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_REVERB_DELAY, NULL,"TX Reverb delay", UiMenuDesc("TX reverberation delay") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_EQ0, NULL,"TX EQ 175 Hz", UiMenuDesc("Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_EQ1, NULL,"TX EQ 350 Hz", UiMenuDesc("Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_EQ2, NULL,"TX EQ 700 Hz", UiMenuDesc("Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_EQ3, NULL,"TX EQ 1.4 kHz", UiMenuDesc("Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.") },
{ MENU_FILTER, MENU_ITEM, CONFIG_TX_EQ4, NULL,"TX EQ 2.8 kHz", UiMenuDesc("Equalizer band level adjustment -20 ... + 20 dB, 0 - no adjustment.") },
{ MENU_FILTER, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor powGroup[] =
{
{ MENU_POW, MENU_ITEM, CONFIG_TX_DISABLE, NULL, "Transmit Disable", UiMenuDesc("Disable all transmissions unconditionally. In CW you will be able to hear a sidetone but no transmission is made.") },
{ MENU_POW, MENU_ITEM, CONFIG_VSWR_PROTECTION_THRESHOLD, NULL, "VSWR Protect.threshold", UiMenuDesc("If not OFF, on TX/tune the bias of PA will be down to 0 etc when exceeding the specified value of VSWR") },
{ MENU_POW, MENU_ITEM, MENU_MIC_TYPE, NULL, "Mic Type", UiMenuDesc("Microphone type. Electret or Dynamic. ELECTRET is recommended. Selecting DYNAMIC when an Electret mic is present will likely cause terrible audio distortion") },
{ MENU_POW, MENU_ITEM, MENU_MIC_GAIN, NULL, "Mic Input Gain", UiMenuDesc("Microphone gain. Also changeable via Encoder 3 if Microphone is selected as Input") },
{ MENU_POW, MENU_ITEM, MENU_LINE_GAIN, NULL, "Line Input Gain", UiMenuDesc("LineIn gain. Also changeable via Encoder 3 if LineIn Left (L>L) or LineIn Right (L>R) is selected as Input") },
{ MENU_POW, MENU_ITEM, MENU_TX_COMPRESSION_LEVEL, NULL, "TX Audio Compress", UiMenuDesc("Control the TX audio compressor. Higher values give more compression. Set to CUSTOM for user defined compression parameters. See below. Also changeable via Encoder 1 (CMP).") },
{ MENU_POW, MENU_ITEM, MENU_ALC_RELEASE, NULL, "TX ALC Release Time", UiMenuDesc("If Audio Compressor Config is set to CUSTOM, sets the value of the Audio Compressor Release time. Otherwise shows predefined value of selected compression level.") },
{ MENU_POW, MENU_ITEM, MENU_ALC_POSTFILT_GAIN, NULL, "TX ALC Input Gain", UiMenuDesc("If Audio Compressor Config is set to CUSTOM, sets the value of the ALC Input Gain. Otherwise shows predefined value of selected compression level.") },
{ MENU_POW, MENU_ITEM, CONFIG_TUNE_POWER_LEVEL, NULL, "Tune Power Level", UiMenuDesc("Select the power level for TUNE operation. May be set using the selected power level or have a fixed power level.") },
{ MENU_POW, MENU_ITEM, CONFIG_TUNE_TONE_MODE, NULL, "Tune Tone (SSB)", UiMenuDesc("Select if single tone or two tone is generated during TUNE operation. Not persistent.") },
{ MENU_POW, MENU_ITEM, CONFIG_CW_PA_BIAS, NULL, "CW PA Bias (If >0 )", UiMenuDesc("If set to a value above 0, this BIAS is used during CW transmission; otherwise normal BIAS is used during CW") },
{ MENU_POW, MENU_ITEM, CONFIG_REDUCE_POWER_ON_LOW_BANDS, NULL, "Reduce Power on Low Bands", UiMenuDesc("If set (recommended!) frequencies below 8Mhz (40m or lower) require higher power adjust values (four times). This permits better control of generated power on these frequencies.") },
{ MENU_POW, MENU_ITEM, CONFIG_REDUCE_POWER_ON_HIGH_BANDS, NULL, "Reduce Power on High Bands", UiMenuDesc("If set frequencies above 8Mhz (30m or higher) require higher power adjust values (four times). This permits better control of generated power on these frequencies.") },
{ MENU_POW, MENU_ITEM, CONFIG_PA_BIAS, NULL, "PA Bias", UiMenuDesc("Defines the BIAS value of the PA. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_2200M_5W_ADJUST,&band_enabled[BAND_MODE_2200],"2200m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_630M_5W_ADJUST,&band_enabled[BAND_MODE_630],"630m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_5W_ADJUST, NULL, "160m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_5W_ADJUST, NULL, "80m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_60M_5W_ADJUST, NULL, "60m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_5W_ADJUST, NULL, "40m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_5W_ADJUST, NULL, "30m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_5W_ADJUST, NULL, "20m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_5W_ADJUST, NULL, "17m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_5W_ADJUST, NULL, "15m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_5W_ADJUST, NULL, "12m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_5W_ADJUST, NULL, "10m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_5W_ADJUST,&band_enabled[BAND_MODE_6],"6m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_4M_5W_ADJUST,&band_enabled[BAND_MODE_4],"4m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_2M_5W_ADJUST,&band_enabled[BAND_MODE_2],"2m 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_70CM_5W_ADJUST,&band_enabled[BAND_MODE_70],"70cm 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_23CM_5W_ADJUST,&band_enabled[BAND_MODE_23],"23cm 5W PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve 5W power on this band. See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_2200M_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_2200],"2200m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_630M_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_630],"630m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_FULL_POWER_ADJUST, NULL, "160m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_FULL_POWER_ADJUST, NULL, "80m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_60M_FULL_POWER_ADJUST, NULL, "60m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_FULL_POWER_ADJUST, NULL, "40m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_FULL_POWER_ADJUST, NULL, "30m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_FULL_POWER_ADJUST, NULL, "20m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_FULL_POWER_ADJUST, NULL, "17m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_FULL_POWER_ADJUST, NULL, "15m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_FULL_POWER_ADJUST, NULL, "12m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_FULL_POWER_ADJUST, NULL, "10m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_6],"6m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_4M_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_4],"4m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_2M_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_2],"2m Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_70CM_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_70],"70cm Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_23CM_FULL_POWER_ADJUST,&band_enabled[BAND_MODE_23],"23cm Full PWR Adjust", UiMenuDesc("Defines the internal power adjustment factor to achieve full power on this band. Check the output signal when adjusting for full power! See Adjustment and Calibration for more information.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_2200M_ADJ,&band_enabled[BAND_MODE_2200],"2200m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 2200m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_630M_ADJ,&band_enabled[BAND_MODE_630],"630m Coupling Adj.", UiMenuDesc("Power Adjustment factor for the 630m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_160M_ADJ, NULL, "160m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 160m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_80M_ADJ, NULL, "80m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 80m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_40M_ADJ, NULL, "40m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 40m and 60m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_20M_ADJ, NULL, "20m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 20m and 30m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_15M_ADJ, NULL, "15m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 15m - 12m bands power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_10M_ADJ, NULL, "10m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 10m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_6M_ADJ,&band_enabled[BAND_MODE_6], "6m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 6m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_2M_ADJ,&band_enabled[BAND_MODE_2], "2m Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 2m band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_70CM_ADJ,&band_enabled[BAND_MODE_70], "70cm Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 70cm band power values. See Wiki.") },
{ MENU_POW, MENU_ITEM, CONFIG_FWD_REV_COUPLING_23CM_ADJ,&band_enabled[BAND_MODE_23], "23cm Coupling Adj.", UiMenuDesc("Power Meter Adjustment factor for the 23cm band power values. See Wiki.") },
// { MENU_POW, MENU_ITEM, CONFIG_80M_RX_IQ_GAIN_BAL, &ts.display_rx_iq, "RX IQ Balance (80m)", UiMenuDesc("IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
// { MENU_POW, MENU_ITEM, CONFIG_80M_RX_IQ_PHASE_BAL, &ts.display_rx_iq, "RX IQ Phase (80m)", UiMenuDesc("IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
// { MENU_POW, MENU_ITEM, CONFIG_10M_RX_IQ_GAIN_BAL, &ts.display_rx_iq, "RX IQ Balance (10m)", UiMenuDesc("IQ Balance Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable.See Wiki Adjustments and Calibration.") },
// { MENU_POW, MENU_ITEM, CONFIG_10M_RX_IQ_PHASE_BAL, &ts.display_rx_iq, "RX IQ Phase (10m)", UiMenuDesc("IQ Phase Adjust for all receive if frequency translation is NOT OFF. Requires USB/LSB/CW mode to be changeable. See Wiki Adjustments and Calibration.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (160m)*", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 1.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (160m)*", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 1.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (80m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 3.600 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (80m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 3.600 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (40m)*", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 7.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (40m)*", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 7.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (30m)*", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 10.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (30m)*", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 10.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (20m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (20m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (17m)*", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 18.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (17m)*", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 18.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (15m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (15m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (12m)*", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 24.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (12m)*", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 24.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (10m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 28.100 MHz..") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (10m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 28.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (10mUp)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (10mUp)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (6m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 52.000 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (6m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 52.000 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (160m,CW)*", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 1.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_160M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (160m,CW)*", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 1.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (80m,CW)", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 3.600 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_80M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (80m,CW)", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 3.600 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (40m,CW)*", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 7.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_40M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (40m,CW)*", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 7.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (30m,CW)*", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 10.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_30M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (30m,CW)*", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 10.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (20m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (20m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (17m,CW)*", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 18.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_17M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (17m,CW)*", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 18.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (15m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (15m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (12m,CW)*", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 24.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_12M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (12m,CW)*", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 24.900 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (10m,CW)", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 28.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (10m,CW)", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 28.100 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (10mUp,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (10mUp,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (6m,CW)", UiMenuDesc("IQ Balance Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 52.000 MHz.") },
{ MENU_POW, MENU_ITEM, CONFIG_6M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (6m,CW)", UiMenuDesc("IQ Phase Adjust for CW transmissions (and all transmission if frequency translation is OFF). Calibrate on 52.000 MHz.") },
{ MENU_POW, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor men2touchGroup[] =
{
#ifdef SDR_AMBER
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_INPUT_STATE, NULL, "RX Input State", UiMenuDesc("Amber - State of RX input group.") },
#endif
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_DYNAMICTUNE, NULL, "Dynamic Tune", UiMenuDesc("Toggles dynamic tune mode") },
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_MIC_LINE_MODE, NULL, "Mic/Line Select", UiMenuDesc("Select the required signal input for transmit (except in CW). Also changeable via long press on M3") },
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_SPECTRUM_MODE, NULL, "Spectrum Type", UiMenuDesc("Select if you want a scope-like or a waterfall-like (actually a fountain) display") },
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_SPECTRUM_MAGNIFY, NULL, "Spectrum Magnify", UiMenuDesc("Select level of magnification (1x, 2x, 4x, 8x, 16x, 32x) of spectrum and waterfall display. Also changeable via touch screen. Refresh rate is much slower with high magnification settings. The dBm display has its maximum accuracy in magnify 1x setting.") },
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_RESTART_CODEC, NULL, "Restart Codec", UiMenuDesc("Sometimes there is a problem with the I2S IQ signal stream from the Codec, resulting in mirrored signal reception. Restarting the CODEC Stream will cure that problem. Try more than once, if first call did not help.") },
{ MENU_MEN2TOUCH, MENU_ITEM, MENU_DIGITAL_MODE_SELECT, NULL, "Digital Mode", UiMenuDesc("Select the active digital mode (FreeDV,RTTY, ...).") },
{ MENU_MEN2TOUCH, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor infoGroup[] =
{
{ MENU_SYSINFO, MENU_INFO, INFO_DISPLAY, NULL,"Display", UiMenuDesc("Displays working mode (SPI/parallel") },
{ MENU_SYSINFO, MENU_INFO, INFO_DISPLAY_CTRL, NULL,"Disp. Controller", UiMenuDesc("identified LCD controller chip") },
{ MENU_SYSINFO, MENU_INFO, INFO_OSC_NAME, NULL,"Oscillator", UiMenuDesc("Local oscillator type") },
#ifdef USE_OSC_SI570
{ MENU_SYSINFO, MENU_INFO, INFO_SI570, NULL,"SI570", UiMenuDesc("Startup frequency and I2C address of local oscillator Type SI570") },
#endif
{ MENU_SYSINFO, MENU_INFO, INFO_EEPROM, NULL,"EEPROM", UiMenuDesc("type of serial EEPROM and its capacity") },
{ MENU_SYSINFO, MENU_INFO, INFO_TP, NULL,"Touchscreen", UiMenuDesc("touchscreen state") },
{ MENU_SYSINFO, MENU_INFO, INFO_CPU, NULL,"CPU", UiMenuDesc("identification of fitted MCU") },
{ MENU_SYSINFO, MENU_INFO, INFO_FLASH, NULL,"Flash Size (kB)", UiMenuDesc("flash size of MCU") },
{ MENU_SYSINFO, MENU_INFO, INFO_RAM, NULL,"RAM Size (kB)", UiMenuDesc("RAM size of MCU") },
{ MENU_SYSINFO, MENU_INFO, INFO_FW_VERSION, NULL,"Firmware", UiMenuDesc("firmware version") },
{ MENU_SYSINFO, MENU_INFO, INFO_BUILD, NULL,"Build", UiMenuDesc("firmware: timestamp of building") },
{ MENU_SYSINFO, MENU_INFO, INFO_BL_VERSION, NULL,"Bootloader", UiMenuDesc("bootloader version") },
{ MENU_SYSINFO, MENU_INFO, INFO_RFBOARD, NULL,"RF Board", UiMenuDesc("Displays the detected RF Board hardware identification.") },
{ MENU_SYSINFO, MENU_INFO, INFO_CODEC, NULL,"Audio Codec Presence", UiMenuDesc("Audio Codec I2C communication successfully tested? This is not a full test of the Audio Codec functionality, it only reports if I2C communication reported no problem talking to the codec.") },
{ MENU_SYSINFO, MENU_INFO, INFO_CODEC_TWINPEAKS, NULL,"Audio Codec Twinpeaks Corr.", UiMenuDesc("In some cases the audio codec needs to be restarted to produce correct IQ. The IQ auto correction detects this. If this fixes the problem, Done is displayed, Failed otherwise") },
{ MENU_SYSINFO, MENU_INFO, INFO_VBAT, NULL,"Backup RAM Battery", UiMenuDesc("Battery Support for Backup RAM present?") },
{ MENU_SYSINFO, MENU_INFO, INFO_RTC, NULL,"Real Time Clock", UiMenuDesc("Battery Supported Real Time Clock present?") },
{ MENU_SYSINFO, MENU_INFO, INFO_LO_TX_SUPR_DACs, NULL,"LO_TX Supression DACs", UiMenuDesc("LO_TX Supression DACs (0/1) are present?") },
#ifdef SDR_AMBER
{ MENU_SYSINFO, MENU_INFO, INFO_AMBER_IO8, NULL,"Amber-I/Ox8", UiMenuDesc("Amber - I/Ox8 PCF8574A is present?") },
{ MENU_SYSINFO, MENU_INFO, INFO_AMBER_IO4, NULL,"Amber-I/Ox4", UiMenuDesc("Amber - I/Ox4 PCA9536 is present?") },
{ MENU_SYSINFO, MENU_INFO, INFO_AMBER_DAC_PWR_TX, NULL,"Amber-DAC_TX_PWR", UiMenuDesc("Amber - DAC MCP4725 for TX PWR reg. is present?") },
#endif
{ MENU_SYSINFO, MENU_INFO, INFO_LICENCE, NULL,"FW license", UiMenuDesc("Display license of firmware") },
{ MENU_SYSINFO, MENU_INFO, INFO_HWLICENCE, NULL,"HW license", UiMenuDesc("Display license of hardware") },
{ MENU_SYSINFO, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor debugGroup[] =
{
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ENABLE_INFO, NULL,"Enable Debug Info Display", UiMenuDesc("Enable debug outputs on LCD for testing purposes (touch screen coordinates, load) and audio interrupt duration indication via green led") },
{ MENU_DEBUG, MENU_ITEM, CONFIG_FWD_REV_PWR_DISP, NULL, "Pwr. F/R Display (mW)", UiMenuDesc("Shows the forward and reverse power values in mW, can be used to calibrate the SWR meter.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CW_OFFSET_SHIFT_KEEP_SIGNAL, NULL,"CW Shift Keeps Signal", UiMenuDesc("Enable automatic sidetone correction for CW OFFSET MODE = SHIFT. If you tuned in SSB to a CW signal around the sidetone frequency, you'll keep that signal when going to CW. Even if you switch from USB to CW-LSB etc.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_TX_AUDIO, NULL,"TX Audio via USB", UiMenuDesc("If enabled, send generated audio to PC during TX.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CLONEOUT, NULL,"FT817 Clone Transmit", UiMenuDesc("Will in future send out memory data to an FT817 Clone Info (to be used with CHIRP).") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CLONEIN, NULL,"FT817 Clone Receive", UiMenuDesc("Will in future get memory data from an FT817 Clone Info (to be used with CHIRP).") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NEW_NB, NULL,"New Noiseblanker", UiMenuDesc("New noiseblanker for testing purposes") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_ENABLE, NULL,"Spectral NR", UiMenuDesc("enable spectral noise reduction for testing purposes") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_LONG_TONE_ENABLE, NULL,"Long tone", UiMenuDesc("enable long tone detection in spectral noise reduction for testing purposes") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_GAIN_SHOW, NULL,"Show gains", UiMenuDesc("Debugging: show gains of spectral noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_LONG_TONE_ALPHA, NULL,"Long tone alpha", UiMenuDesc("time constant alpha for long tone detection in spectral noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_LONG_TONE_THRESH, NULL,"Long tone thresh", UiMenuDesc("threshold for long tone detection in spectral noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_ENABLE, NULL,"SNR gain smooth", UiMenuDesc("enable bin gain smoothing for spectral noise reduction for testing purposes") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_ALPHA, NULL,"SNR gain smooth alpha", UiMenuDesc("alpha = smoothing constant for spectral noise reduction for testing purposes") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_ALPHA, NULL,"NR alpha", UiMenuDesc("time constant alpha for spectral noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_THRESH, NULL,"NR thresh", UiMenuDesc("threshold for spectral noise reduction voice activity detector") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_VAD_TYPE, NULL,"NR VAD type", UiMenuDesc("VAD type for spectral noise reduction voice activity detector") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_VAD_DELAY, NULL,"NR VAD delay", UiMenuDesc("delay for spectral noise reduction voice activity detector") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_BETA, NULL,"NR beta", UiMenuDesc("time constant beta for spectral noise reduction, leave at 0.85") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_Mode, NULL,"NR Mode", UiMenuDesc("switch between the released NR and two development NRs") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_ASNR, NULL,"NR asnr", UiMenuDesc("Devel 2 NR: asnr") },
//#if defined(STM32F7) || defined(STM32H7)
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_FFT_SIZE, NULL,"NR FFT Size256", UiMenuDesc("enable FFT256 instead of FFT128 for devel2 NR") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_DEC_ENABLE, NULL,"NR decimation", UiMenuDesc("enable decimation-by-2 down to 6ksps for NR") },
//#endif
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_WIDTH, NULL,"NR smooth wd.", UiMenuDesc("Devel 2 NR: width of gain smoothing window") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_GAIN_SMOOTH_THRESHOLD, NULL,"NR smooth thr.", UiMenuDesc("Devel 2 NR: threhold for gain smoothing") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_RTTY_ATC, NULL,"RTTY ATC Enable", UiMenuDesc("Enable automatic threshold correction ATC for RTTY decoding") },
#ifdef USE_TWO_CHANNEL_AUDIO
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ENABLE_STEREO, NULL,"STEREO Enable", UiMenuDesc("Enable stereo demodulation modes") },
#endif
#ifdef USE_LEAKY_LMS
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_LEAKY_LMS, NULL,"ANR(LeakyLMS) Enable", UiMenuDesc("Use leaky LMS noise reduction instead of built-in CMSIS LMS algorithm") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_NR_POST_AGC_SELECT, NULL, "ANR after AGC", UiMenuDesc("DSP LMS noise reduction: Perform the DSP LMS noise reduction BEFORE or AFTER the AGC. NO = before AGC, YES = after AGC.") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ANR_TAPS, NULL,"ANR num taps", UiMenuDesc("Number of taps of leaky LMS noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ANR_DELAY, NULL,"ANR corr. delay", UiMenuDesc("Delay length of leaky LMS noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ANR_GAIN, NULL,"ANR gain", UiMenuDesc("Gain of leaky LMS noise reduction") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ANR_LEAK, NULL,"ANR leak", UiMenuDesc("Leak of leaky LMS noise reduction") },
#endif
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_OSC_SI5351_PLLRESET, NULL,"Si5351a PLL Reset", UiMenuDesc("Debug Setting: Select when the Si5351a does a PLL RESET") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_COARSE, &hmc1023.present,"HMC1023 Coarse", UiMenuDesc("Debug Setting: Change LPF HMC1023LP5E coarse bandwidth") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_FINE, &hmc1023.present,"HMC1023 Fine", UiMenuDesc("Debug Setting: Change LPF HMC1023LP5E fine bandwidth") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_GAIN, &hmc1023.present,"HMC1023 Gain 10db", UiMenuDesc("Debug Setting: Switch LPF HMC1023LP5E +10db Amp on/off") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_BYPASS, &hmc1023.present,"HMC1023 Bypass", UiMenuDesc("Debug Setting: Set HMC1023 to bypass mode") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_OPAMP, &hmc1023.present,"HMC1023 Opamp Bias", UiMenuDesc("Debug Setting: Switch LPF HMC1023LP5E Opamp Bias") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_HMC1023_DRVR, &hmc1023.present,"HMC1023 Driver Bias", UiMenuDesc("Debug Setting: Set HMC1023 Driver Bias") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_TWINPEAKS_CORR_RUN, NULL,"Trigger Twinpeaks Corr.", UiMenuDesc("Trigger Twinpeaks Correction Manually if IQ Auto Correction is enabled, otherwise you will see 'Not Possible'") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (20m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (20m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 14.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (15m)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (15m)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 21.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL, NULL, "TX IQ Balance (10mUp)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL, NULL, "TX IQ Phase (10mUp)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is NOT OFF. Calibrate on 29.650 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_20M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (20m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_20M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (20m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 14.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_15M_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (15m,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_15M_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (15m,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 21.100 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_10M_UP_TX_IQ_GAIN_BAL_TRANS_OFF, NULL, "TX IQ Balance (10mUp,CW)", UiMenuDesc("IQ Balance Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_10M_UP_TX_IQ_PHASE_BAL_TRANS_OFF, NULL, "TX IQ Phase (10mUp,CW)", UiMenuDesc("IQ Phase Adjust for all transmission if frequency translation is OFF. Calibrate on 29.650 MHz.") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_VSWR_PROTECTION_THRESHOLD, NULL, "VSWR Protect.threshold", UiMenuDesc("If not OFF, on TX/tune the bias of PA will be down to 0 etc when exceeding the specified value of VSWR") },
// { MENU_DEBUG, MENU_ITEM, CONFIG_RESET_SER_EEPROM_SIGNATURE, NULL, "Rst Conf EEPROM", UiMenuDesc("Clear the EEPROMi signature but keep all config values. This is mainly for debugging purposes).") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_FREEDV_MODE, NULL, "FreeDV Mode", UiMenuDesc("Change active FreeDV mode. Please note, you have to reboot to activate new mode") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_FREEDV_SQL_THRESHOLD, NULL, "FreeDV Squelch threshold", UiMenuDesc("If not OFF, FreeDV will squelch if detected SNR is below set value.") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BANDEF_SELECT, NULL, "Band Definition", UiMenuDesc("Select which band definition to use for ham bands (Original UHSDR or IARU Region 1 - 3") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_27MC_TX_ENABLE, NULL, "CB 27Mc TX Enable(max4W)", UiMenuDesc("Enable transmitting (4W) on CB band 27 MHz (AM, FM, SSB).") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_26MC_TX_ENABLE, NULL, "CB 26Mc TX Enable(max4W)", UiMenuDesc("Enable transmitting (4W) on CB band 26 MHz (AM, FM, SSB).") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_27MC_TX_ENABLE, NULL, "CB 27Mc TX Enable(max4W)", UiMenuDesc("Enable transmitting (4W) on CB band 27 MHz (AM, FM, SSB, CW).") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_26MC_TX_ENABLE, NULL, "CB 26Mc TX Enable(max4W)", UiMenuDesc("Enable transmitting (4W) on CB band 26 MHz (AM, FM, SSB, CW).") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_12W_SSB_TX_ENABLE, NULL, "CB 12W SSB TX Enable", UiMenuDesc("Enable transmitting 12W SSB on CB bands, where TX is open.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CB_10W_TX_ENABLE, NULL, "CB 10W TX Enable", UiMenuDesc("Enable transmitting 10W for any mode on CB bands, where TX is open.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CAL_LO_TX_SUPR_0, NULL, "Cal.LO_TX Supression C0", UiMenuDesc("Calibration of LO_TX Supression on every band via balancing of TX mixer, channel 0") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CAL_LO_TX_SUPR_1, NULL, "Cal.LO_TX Supression C1", UiMenuDesc("Calibration of LO_TX Supression on every band via balancing of TX mixer, channel 1") },
#ifdef SDR_AMBER
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_SHOW_GREETING, NULL, "Show FS Greeting", UiMenuDesc("Not for users.") },
#endif
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_SMOOTH_DYN_TUNE, NULL, "Smooth dynamic tune", UiMenuDesc("Activate smooth dynamic tune.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CLEAN_TX_CW_RTTY_BPSK, NULL, "Clear TX CW,RTTY,BPSK", UiMenuDesc("Forming CW/RTTY/BPSK signal at intermediate frequency for clean TX.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_MEM_BW_MOD_BAND, NULL, "Remember BWs on bands", UiMenuDesc("Remember the filter settings of each mode in each range for the duration of the session.") },
#ifdef SDR_AMBER
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ILLUM_BUTT, NULL, "Illum. of buttons", UiMenuDesc("Illumination of buttons.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BPF_OPTION, NULL, "RF - Amber BPF Option", UiMenuDesc("3 extra BPF instead of 2 on Amber-RF board.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_XVTR_OFF_PA, NULL, "XVTR - OFF PA", UiMenuDesc("Transverter mode - blocking PA on TX. The optional 'XVTR TX' SMA connector must be soldered and connected with coaxial cable to the output of the amplifier before PA driver ('XVTR_TX' contacts).") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BANDCODE, NULL, "Ext. PA Bandcode", UiMenuDesc("PA bandcode variant, if not OFF.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ALT_PWR_CTRL, NULL, "TX_PREAMP_DAC Option", UiMenuDesc("Alternative POWER lewel control ON/OFF") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_ALT_PWR_CTRL_VOL, NULL, "TX_PREAMP_DAC Vol.", UiMenuDesc("Alternative POWER lewel control - DAC volume in points, 0-4096 (0-5V).") },
#endif
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_WIDE_SPEC_DEF, NULL, "Wide Spectrum Default", UiMenuDesc("Wide mode of spectrum on screen 320x240 is default.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_DISABLE_TP, NULL, "Disable touchscreen", UiMenuDesc("Disable touchscreen actions.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_FMENUS_SEL, NULL, "Choice of F-menu", UiMenuDesc("Type of F-menus selection.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_IMPROV_IQ_ADJ, NULL, "Improved I/Q Adj.", UiMenuDesc("Improved I/Q adjusting. Added 160, 40, 30, 17, 12m.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BEEP_GEN, NULL, "Beep GEN", UiMenuDesc("Activate beep (as button beep set) when the band border is crossed.") },
#ifdef SDR_AMBER_4INCH
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_F6_IND_SEL, NULL, "F6 Ind.", UiMenuDesc("Amber 4'' - Indication of F6 button.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_F7_IND_SEL, NULL, "F7 Ind.", UiMenuDesc("Amber 4'' - Indication of F7 button.") },
#endif
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_160M, NULL, "Band OFF -160m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_80M, NULL, "Band OFF - 80m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_60M, NULL, "Band OFF - 60m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_40M, NULL, "Band OFF - 40m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_30M, NULL, "Band OFF - 30m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_20M, NULL, "Band OFF - 20m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_17M, NULL, "Band OFF - 17m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_15M, NULL, "Band OFF - 15m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_12M, NULL, "Band OFF - 12m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_10M, NULL, "Band OFF - 10m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_BAND_OFF_6M, NULL, "Band OFF - 6m", UiMenuDesc("Remove this band from switching queue.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_REDUCE_POWER_ON_LOW_BANDS_MORE, NULL, "ReducePWR_MoreOnLowBands", UiMenuDesc("Reduce power x20 (instead of x4) for F < 8 MHz.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_SHOW_SWR_ONLY_TUNE, NULL, "Show SWR only in TUNE", UiMenuDesc("Show SWR only in TUNE mode.") },
{ MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CONTEST, NULL, "Contest mode (MEMS)", UiMenuDesc("Contest mode long F3 activation is ON.") },
// { MENU_DEBUG, MENU_ITEM, MENU_DEBUG_CONTEST_COLOUR, NULL, "Contest mode COLOUR", UiMenuDesc("Contest mode mems colour.") },
{ MENU_DEBUG, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
const MenuDescriptor hall_of_fameGroup[] =
{
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"M0NKA (Chris) mcHF founder", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"KA7OEI (Clint) 1st great FW", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"DF8OE (Andreas)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"DL4SAI (Harald)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"DB4PLE (Danilo)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"DD4WH (Frank)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"DL2FW (Michael)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"HB9OCQ (Stephan)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL," (Asbjorn)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"YL3AKE (Eriks)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"PA7N (Erwin)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"UA9OLB (Dmitri)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"S53DZ (Bojan)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"SP9BSL (Slawek)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"HB9GND (Dimce)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"MM0MZW (Mike)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"UB8JDC (Yuri)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"RV9YW (Max)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"M0LNG (Martin)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"KB3CS (Chris)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_TEXT, 0, NULL,"F4IYT (Xav)", UiMenuDesc("") },
{ MENU_HALL_OF_FAME, MENU_STOP, 0, NULL, NULL, UiMenuDesc("") }
};
MenuGroupState topGroupState;
MenuGroupState baseGroupState;
MenuGroupState confGroupState;
MenuGroupState displayGroupState;
MenuGroupState cwGroupState;
MenuGroupState filterGroupState;
MenuGroupState powGroupState;
MenuGroupState men2touchState;
MenuGroupState infoGroupState;
MenuGroupState debugGroupState;
MenuGroupState hall_of_fameGroupState;
const MenuGroupDescriptor groups[] =
{
{ topGroup, &topGroupState, NULL}, // Group 0
{ baseGroup, &baseGroupState, topGroup}, // Group 1
{ confGroup, &confGroupState, topGroup}, // Group 2
{ displayGroup, &displayGroupState, topGroup }, // Group 3
{ cwGroup, &cwGroupState, topGroup }, // Group 4
{ filterGroup, &filterGroupState, topGroup }, // Group 5
{ powGroup, &powGroupState, topGroup }, // Group 6
{ men2touchGroup, &men2touchState, topGroup }, // Group 7
{ infoGroup, &infoGroupState, topGroup }, // Group 8
{ debugGroup, &debugGroupState, topGroup }, // Group 9
{ hall_of_fameGroup, &hall_of_fameGroupState, topGroup }, // Group 10
};
@@ -0,0 +1,111 @@
/* -*- 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 **
************************************************************************************/
// Common
#include "osc_interface.h"
#include "uhsdr_board.h"
#include "osc_si570.h"
#include "osc_si5351a.h"
#include "soft_tcxo.h"
// -------------------------------------------------------------------------------------
// Local Oscillator
// ------------------
static void OscDummy_Init(void);
const OscillatorInterface_t* osc;
static bool OscDummy_IsPresent(void)
{
return false;
}
static void OscDummy_SetPPM(float32_t ppm)
{
}
static Oscillator_ResultCodes_t OscDummy_PrepareNextFrequency(ulong freq, int temp_factor)
{
return OSC_OK;
}
static Oscillator_ResultCodes_t OscDummy_ChangeToNextFrequency(void)
{
return OSC_OK;
}
static bool OscDummy_IsNextStepLarge(void)
{
return false;
}
/**
* @brief Checks if all oscillator resources are available for switching frequency
* This function must be called before changing the oscillator in interrupts
* otherwise deadlocks may happen
* @return true if it is safe to call oscillator functions in an interrupt
*/
static bool OscDummy_ReadyForIrqCall(void)
{
return true;
}
static uint32_t OscDummy_getMinFrequency(void)
{
return 1; // 1 Hz
}
static uint32_t OscDummy_getMaxFrequency(void)
{
return UINT32_MAX-1;
}
const OscillatorInterface_t osc_dummy =
{
.init = OscDummy_Init,
.isPresent = OscDummy_IsPresent,
.setPPM = OscDummy_SetPPM,
.prepareNextFrequency = OscDummy_PrepareNextFrequency,
.changeToNextFrequency = OscDummy_ChangeToNextFrequency,
.isNextStepLarge = OscDummy_IsNextStepLarge,
.readyForIrqCall = OscDummy_ReadyForIrqCall,
.name = "Dummy",
.type = OSC_DUMMY,
.getMinFrequency = OscDummy_getMinFrequency,
.getMaxFrequency = OscDummy_getMaxFrequency,
};
static void OscDummy_Init()
{
osc = &osc_dummy;
}
void Osc_Init()
{
#ifdef USE_OSC_SI5351A
if (osc == NULL)
{
Si5351a_Init();
}
#endif
#ifdef USE_OSC_SI570
if (osc == NULL)
{
Si570_Init();
}
#endif
if (osc == NULL)
{
OscDummy_Init();
}
SoftTcxo_Init();
}
@@ -0,0 +1,66 @@
/* -*- 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 **
************************************************************************************/
#ifndef __OSC_INTERFACE
#define __OSC_INTERFACE
#include "uhsdr_types.h"
typedef enum
{
OSC_OK = 0, // tuning ok
OSC_TUNE_LIMITED, // tuning to freq close to desired freq, still ok
OSC_TUNE_IMPOSSIBLE, // did not tune, tune freq unknown
OSC_COMM_ERROR, // could not talk to Si570, tune freq unknown
OSC_ERROR_VERIFY, // register do not match, tune freq unknown
OSC_LARGE_STEP, // did not tune, just checking
} Oscillator_ResultCodes_t;
typedef enum
{
OSC_UNKNOWN,
OSC_DUMMY,
OSC_SI570,
OSC_SI5351A,
} Oscillator_Type_t;
typedef struct
{
// startup handling
void (*init)();
// presence information
bool (*isPresent)();
// startup/runtime reconfiguration
void (*setPPM)(float32_t ppm);
// normal operations interface
// freq is given in Hz, is QSD mixing frequency,
// internally multiplied by 4 for Johnson Counter clock counters if needed by circuit
Oscillator_ResultCodes_t (*prepareNextFrequency)(ulong freq, int temp_factor);
Oscillator_ResultCodes_t (*changeToNextFrequency)();
bool (*isNextStepLarge)();
bool (*readyForIrqCall)();
uint32_t (*getMinFrequency)();
uint32_t (*getMaxFrequency)();
const char* name;
const Oscillator_Type_t type;
} OscillatorInterface_t;
extern const OscillatorInterface_t *osc;
void Osc_Init();
#endif
@@ -0,0 +1,481 @@
/* -*- 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 **
************************************************************************************/
// Common
#include "uhsdr_board.h"
#include <math.h>
#include "uhsdr_hw_i2c.h"
#include "osc_si5351a.h"
#ifdef USE_OSC_SI5351A
// Will be removed and made a dynamic config element
#ifdef UI_BRD_OVI40
#define TEST_QUADRATURE
#endif
// reference oscillator xtal frequency
#define SI5351_XTAL_FREQ 27000000 // Crystal frequency
#define SI5351_MIN_PLL 405000000 // Min PLL frequency, officially it is 600 Mhz, but 405 seems to work just fine.
#define SI5351_MAX_PLL 900000000 // Max PLL frequency, officially it is 900 Mhz, tested with ~1168 Mhz
#define SI5351_MAX_DIVIDER 900
#define SI5351_MAX_DIVIDER_PHASE90 126
// Max value for a divider if we want 90 degree phased clock, must be even and <=127
#define SI5351_MIN_FREQ_PHASE90 ((SI5351_MIN_PLL/SI5351_MAX_DIVIDER_PHASE90)+1)
// Min PLL frequency / Max Divider for Phase 90 -> minimal frequency we can have 90 degree phase shift
// Register definitions
#define SI5351_CLK0_CONTROL 16
#define SI5351_CLK1_CONTROL 17
#define SI5351_CLK2_CONTROL 18
#define SI5351_SYNTH_PLL_A 26
#define SI5351_SYNTH_PLL_B 34
#define SI5351_SYNTH_MS_0 42
#define SI5351_SYNTH_MS_1 50
#define SI5351_SYNTH_MS_2 58
#define SI5351_CLK0_PHASE_OFFSET 165
#define SI5351_CLK1_PHASE_OFFSET 166
#define SI5351_CLK2_PHASE_OFFSET 167
#define SI5351_PLL_RESET 177
// R-division ratio definitions
#define SI5351_R_DIV_1 0b00000000
#define SI5351_R_DIV_2 0b00010000
#define SI5351_R_DIV_4 0b00100000
#define SI5351_R_DIV_8 0b00110000
#define SI5351_R_DIV_16 0b01000000
#define SI5351_R_DIV_32 0b01010000
#define SI5351_R_DIV_64 0b01100000
#define SI5351_R_DIV_128 0b01110000
#define SI5351_R_DIV_MASK 0b01110000
#define SI5351_DIV_BY_4 0b00001100
#define SI5351_CLK_SRC_PLL_A 0b00000000
#define SI5351_CLK_SRC_PLL_B 0b00100000
// Commands
#define SI5351_OUTPUT_OFF 0x80
#define SI5351_OUTPUT_ON 0x4F // see AN619 for details: this sets many options!
#define SI5351_PLLA_RESET 0x20
#define SI5351_PLLB_RESET 0x80
#define SI5351_I2C_WRITE 192 // I2C address for writing
#define SI5351_I2C_READ 193 // I2C address for reading
#define MAX_UINT20 1048575
static uint16_t Si5351a_WriteRegister(uint8_t reg, uint8_t val)
{
return UhsdrHw_I2C_WriteRegister(SI5351A_I2C, SI5351_I2C_WRITE, reg, 1, val);
}
static uint16_t Si5351a_WriteRegisters(uint8_t reg, uint8_t* val_p, uint32_t size)
{
return UhsdrHw_I2C_WriteBlock(SI5351A_I2C,SI5351_I2C_WRITE, reg, 1, val_p, size);
}
typedef struct
{
uint32_t frequency;
uint32_t pll_num;
uint32_t pll_denom;
uint32_t multisynth_divider;
uint8_t multisynth_rdiv;
uint32_t pll_mult;
bool phasedOutput;
bool pllreset;
} Si5351a_Config_t;
typedef struct
{
bool is_present;
Si5351a_Config_t current;
Si5351a_Config_t next;
uint32_t xtal_freq;
} Si5351a_State_t;
Si5351a_State_t si5351a_state;
// Set up PLL with mult, num and denom
// mult is 15...90
// num is 0...1048575
// denom is 0...1048575
static bool Si5351a_SetupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom)
{
uint32_t P1; // PLL config register P1
uint32_t P2; // PLL config register P2
uint32_t P3; // PLL config register P3
uint32_t fract = 128.0 * ((float32_t)num / (float32_t)denom);
P1 = 128 * (uint32_t)(mult) + fract - 512;
P2 = 128 * num - denom * fract;
P3 = denom;
uint8_t pll_data[8] =
{
(P3 & 0x0000FF00) >> 8,
P3 & 0x000000FF,
(P1 & 0x00030000) >> 16,
(P1 & 0x0000FF00) >> 8,
P1 & 0x000000FF,
((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16),
(P2 & 0x0000FF00) >> 8,
P2 & 0x000000FF
};
return Si5351a_WriteRegisters(pll, pll_data, 8) == HAL_OK;
}
// Set up MultiSynth with integer divider and R multisynth_divider
static bool Si5351a_SetupMultisynthInteger(uint8_t synth, uint32_t divider, uint8_t rDiv)
{
uint32_t P1; // Synth config register P1
uint32_t P2; // Synth config register P2
uint32_t P3; // Synth config register P3
P1 = 128 * divider - 512;
P2 = 0; // P2 = 0, P3 = 1 forces an integer value for the multisynth_divider
P3 = 1;
uint8_t synth_data[8] =
{
(P3 & 0x0000FF00) >> 8,
(P3 & 0x000000FF),
((P1 & 0x00030000) >> 16) | rDiv | (divider == 4?SI5351_DIV_BY_4:0),
(P1 & 0x0000FF00) >> 8,
(P1 & 0x000000FF),
((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16),
(P2 & 0x0000FF00) >> 8,
(P2 & 0x000000FF)
};
return Si5351a_WriteRegisters(synth, synth_data, 8) == HAL_OK;
}
static bool Si5351a_ValidateConfig(Si5351a_Config_t* config)
{
// we check against the data sheet and known limitations.
bool retval = (config->multisynth_divider == 4 || config->multisynth_divider == 6 || (config->multisynth_divider >= 8 && config->multisynth_divider <= SI5351_MAX_DIVIDER ));
if (retval == true && config->phasedOutput == true)
{
retval = config->multisynth_divider <= SI5351_MAX_DIVIDER_PHASE90 ;
}
// we check that only the relevant bits are set and no others, this will ensure no problems when setting the register using or.
// the value encodes the exponent of rdiv in the bits [6:4] , i.e. 0 -> 1, 7 -> 128
if (retval == true)
{
retval = (config->multisynth_rdiv & ~SI5351_R_DIV_MASK ) == 0;
}
if (retval == true)
{
retval = ((config->pll_mult >= 15 && config->pll_mult <= 90) && (config->pll_num <= MAX_UINT20) && (config->pll_denom <= MAX_UINT20));
}
return retval;
}
static bool Si5351a_CalculateConfigForDivider(Si5351a_Config_t* new_config, uint32_t divider)
{
uint32_t pllFreq = divider * new_config->frequency; // Calculate the pllFrequency: the multisynth_divider * desired output frequency
uint32_t l = pllFreq % si5351a_state.xtal_freq; // It has three parts:
float32_t f = l; // mult is an integer that must be in the range 15...90
f *= MAX_UINT20; // num and denom are the fractional parts, the numerator and denominator
f /= si5351a_state.xtal_freq; // each is 20 bits (range 0...1048575)
new_config->pll_mult = pllFreq / si5351a_state.xtal_freq; // Determine the multiplier to get to the required pllFrequency
new_config->pll_num = f; // the actual multiplier is pll_mult + pll_num / denom
new_config->pll_denom = MAX_UINT20; // For simplicity we set the denominator to the maximum 1048575
new_config->multisynth_divider = divider;
new_config->multisynth_rdiv = SI5351_R_DIV_1; // TODO: For lower frequencies we need to use R_DIV
return Si5351a_ValidateConfig(new_config);
}
static bool Si5351a_CalculateConfig(uint32_t frequency, Si5351a_Config_t* new_config, Si5351a_Config_t* cur_config)
{
bool retval = false;
new_config->frequency = frequency;
uint32_t divider_max = SI5351_MAX_PLL / frequency; // Calculate the division ratio
if ((new_config->phasedOutput == true || divider_max < 8) && divider_max % 2)
{
divider_max--; // Ensure an even integer division ratio
}
uint32_t divider_min = SI5351_MIN_PLL / frequency; // Calculate the division ratio
if (SI5351_MIN_PLL % frequency)
{
divider_min++;
}
if ( (new_config->phasedOutput == true || divider_min < 8) && divider_min % 2)
{
divider_min++; // Ensure an even integer division ratio
}
// In quadrature mode we cannot have dividers higher than SI5351_MAX_PHASE90_DIVIDER == 126
const uint32_t divider_limit = new_config->phasedOutput?SI5351_MAX_DIVIDER_PHASE90:SI5351_MAX_DIVIDER;
// reuse current divider if possible, theory is that we can get away without PLLRESET in this case
// TODO: Validate theory and validate need for skipping PLLRESET
if (cur_config->phasedOutput == new_config->phasedOutput && cur_config->multisynth_divider >= divider_min && cur_config->multisynth_divider <= divider_max)
{
retval = Si5351a_CalculateConfigForDivider(new_config, cur_config->multisynth_divider);
}
if ( retval == false && divider_max <= divider_limit)
{
retval = Si5351a_CalculateConfigForDivider(new_config, divider_max);
}
if (retval == false && divider_min >= 4)
{
retval = Si5351a_CalculateConfigForDivider(new_config, divider_min);
}
if (retval == false)
{
new_config->multisynth_divider = 0;
}
switch(ts.debug_si5351a_pllreset)
{
case 0:
new_config->pllreset = true;
break;
case 1:
new_config->pllreset = cur_config->multisynth_divider != new_config->multisynth_divider;
break;
case 2:
if (new_config->phasedOutput)
{
new_config->pllreset = cur_config->multisynth_divider != new_config->multisynth_divider;
}
break;
case 3:
new_config->pllreset = false;
}
return retval;
}
static bool Si5351a_ApplyConfig(Si5351a_Config_t* config)
{
// Set up PLL A with the calculated multiplication ratio
bool result = Si5351a_SetupPLL(SI5351_SYNTH_PLL_A, config->pll_mult, config->pll_num, config->pll_denom);
// Set up MultiSynth divider 0, with the calculated divider.
// The final R division stage can divide by a power of two, from 1...128
// represented by constants SI5351_R_DIV1 to SI5351_R_DIV128 (see si5351a.h header file)
// If you want to output frequencies below 1MHz, you have to use the
// final R division stage
if (result == true)
{
if (config->phasedOutput)
{
result = Si5351a_SetupMultisynthInteger(SI5351_SYNTH_MS_0, config->multisynth_divider, config->multisynth_rdiv);
result &= Si5351a_SetupMultisynthInteger(SI5351_SYNTH_MS_1, config->multisynth_divider, config->multisynth_rdiv);
}
else
{
result = Si5351a_SetupMultisynthInteger(SI5351_SYNTH_MS_2, config->multisynth_divider, config->multisynth_rdiv);
}
}
// Reset the PLL. This causes a glitch in the output. For small changes to
// the parameters, you don't need to reset the PLL, and there is no glitch
// Finally switch on the CLK0 output (0x4F)
// and set the MultiSynth0 input to be PLL A
if (result == true)
{
// only if phased output is active, we need to care about phase offset of CLK1
if (config->phasedOutput)
{
Si5351a_WriteRegister(SI5351_CLK1_PHASE_OFFSET, config->multisynth_divider);
}
#ifdef IQ_CLOCK_DIV4_SIG
if (config->phasedOutput)
{
GPIO_ResetBits(IQ_CLOCK_DIV4_SIG_PIO,IQ_CLOCK_DIV4_SIG);
}
else
{
GPIO_SetBits(IQ_CLOCK_DIV4_SIG_PIO,IQ_CLOCK_DIV4_SIG);
}
#endif
// Phase of CLK0 and CLK2 are never changed after startup, so we don't set it.
Si5351a_WriteRegister( SI5351_CLK0_CONTROL, config->phasedOutput==true?SI5351_OUTPUT_ON:SI5351_OUTPUT_OFF);
Si5351a_WriteRegister( SI5351_CLK1_CONTROL, config->phasedOutput==true?SI5351_OUTPUT_ON:SI5351_OUTPUT_OFF);
Si5351a_WriteRegister( SI5351_CLK2_CONTROL, config->phasedOutput==false?SI5351_OUTPUT_ON:SI5351_OUTPUT_OFF);
if (config->pllreset)
{
Si5351a_WriteRegister( SI5351_PLL_RESET, SI5351_PLLA_RESET);
}
}
return result;
}
bool Si5351a_IsPresent()
{
return si5351a_state.is_present;
}
static void Si5351a_SetPPM(float32_t ppm)
{
si5351a_state.xtal_freq = ((float64_t)SI5351_XTAL_FREQ) + (((float64_t)SI5351_XTAL_FREQ)*(float64_t)ppm/1000000.0);
}
static Oscillator_ResultCodes_t Si5351a_PrepareNextFrequency(uint32_t freq, int temp_factor)
#ifndef R928_PLUS // true M0NKA
{
UNUSED(temp_factor);
#ifdef TEST_QUADRATURE
// TODO: Replace this with a proper configurable switch point, the current limit is the minimum frequency we can do 90 degree phase
si5351a_state.next.phasedOutput = freq > SI5351_MIN_FREQ_PHASE90;
#else
si5351a_state.next.phasedOutput = false;
#endif
if (si5351a_state.next.phasedOutput == false)
{
freq *= 4;
// we are going to drive a johnson counter with 4x desired frequency
// to get two 1/4 clock aka 90 degrees phase shifted clocks with frequency freq
}
return Si5351a_CalculateConfig(freq, &si5351a_state.next, &si5351a_state.current) == true?OSC_OK:OSC_TUNE_IMPOSSIBLE;
}
#else // R928+ etc
{
si5351a_state.next.phasedOutput = freq > SI5351_MIN_FREQ_PHASE90;
freq *= 4;
return Si5351a_CalculateConfig(freq, &si5351a_state.next, &si5351a_state.current) == true?OSC_OK:OSC_TUNE_IMPOSSIBLE;
}
#endif
static Oscillator_ResultCodes_t Si5351a_ChangeToNextFrequency(void)
{
Oscillator_ResultCodes_t retval = OSC_COMM_ERROR;
if (Si5351a_ApplyConfig(&si5351a_state.next) == true)
{
memcpy(&si5351a_state.current, &si5351a_state.next, sizeof(si5351a_state.next));
retval = OSC_OK;
}
return retval;
}
static bool Si5351a_IsNextStepLarge(void)
{
return false;
}
/**
* @brief Checks if all oscillator resources are available for switching frequency
* It basically checks if the I2C is currently in use
* This function must be called before changing the oscillator in interrupts
* otherwise deadlocks may happen
* @return true if it is safe to call oscillator functions in an interrupt
*/
bool Si5351a_ReadyForIrqCall()
{
return (SI5351A_I2C->Lock == HAL_UNLOCKED);
}
// FIXME: The limits assume a 4x johnson counter, not the
// also working internal QSD generation
static uint32_t Si5351a_getMinFrequency(void)
{
return SI5351_MIN_PLL / (SI5351_MAX_DIVIDER / 4);
}
static uint32_t Si5351a_getMaxFrequency(void)
{
// this is an experimental value
// outside the spec sheet but still
// most if not all Si5351a can do it.
return 290000000 / 4;
}
const OscillatorInterface_t osc_si5351a =
{
.init = Si5351a_Init,
.isPresent = Si5351a_IsPresent,
.setPPM = Si5351a_SetPPM,
.prepareNextFrequency = Si5351a_PrepareNextFrequency,
.changeToNextFrequency = Si5351a_ChangeToNextFrequency,
.isNextStepLarge = Si5351a_IsNextStepLarge,
.readyForIrqCall = Si5351a_ReadyForIrqCall,
.name = "Si5351a",
.type = OSC_SI5351A,
.getMinFrequency = Si5351a_getMinFrequency,
.getMaxFrequency = Si5351a_getMaxFrequency,
};
void Si5351a_Init()
{
si5351a_state.current.frequency = 0;
si5351a_state.next.frequency = 0;
si5351a_state.current.multisynth_divider = 0;
si5351a_state.next.multisynth_divider = 0;
si5351a_state.is_present = UhsdrHw_I2C_DeviceReady(SI5351A_I2C,SI5351_I2C_WRITE) == HAL_OK;
if (si5351a_state.is_present)
{
Si5351a_WriteRegister(SI5351_CLK0_PHASE_OFFSET, 0);
Si5351a_WriteRegister(SI5351_CLK1_PHASE_OFFSET, 0);
Si5351a_WriteRegister(SI5351_CLK2_PHASE_OFFSET, 0);
Si5351a_WriteRegister( SI5351_CLK0_CONTROL, SI5351_OUTPUT_OFF);
Si5351a_WriteRegister( SI5351_CLK1_CONTROL, SI5351_OUTPUT_OFF);
Si5351a_WriteRegister( SI5351_CLK2_CONTROL, SI5351_OUTPUT_OFF);
}
osc = Si5351a_IsPresent()?&osc_si5351a:NULL;
}
#endif
@@ -0,0 +1,22 @@
/* -*- 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 **
************************************************************************************/
#ifndef __HW_SI5351A
#define __HW_SI5351A
#include "osc_interface.h"
void Si5351a_Init(void);
bool Si5351a_IsPresent(void);
#endif
@@ -0,0 +1,780 @@
/* -*- 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 **
************************************************************************************/
// Common
#include "uhsdr_board.h"
#include "codec.h"
//
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "uhsdr_hw_i2c.h"
#include "osc_si570.h"
// -------------------------------------------------------------------------------------
// Local Oscillator
// ------------------
/* There are two supported alternative choices for the Si570:
USE_SI570_CMOS frequencies up to 160/220 Mhz, used in most boards
USE_SI570_CGRADE frequencies up to 280 Mhz, used in Lapwing
*/
#ifndef RF_BRD_LAPWING
#define USE_SI570_CMOS
#else
#define USE_SI570_CGRADE
#endif
// The SI570 Min/Max frequencies id spec sheet
// The "hard limits" frequencies below/above which the synthesizer cannot be adjusted or else the system may crash
// Lower limits apply to all cases
#define SI570_MIN_FREQ 10000000 //10.0=2.5 MHz
#define SI570_HARD_MIN_FREQ 3500000 // 3.5=0.875 MHz
#ifdef USE_SI570_CGRADE
#define SI570_MAX_FREQ 280000000 // 280=70 Mhz
#define SI570_HARD_MAX_FREQ 280000000 // 280=70 MHz
#endif
#ifdef USE_SI570_CMOS
#define SI570_MAX_FREQ 160000000 // 160=40 Mhz
#define SI570_HARD_MAX_FREQ 220000000 // 220=55 MHz
#endif
#define SI570_RECALL (1<<0)
#define SI570_FREEZE_DCO (1<<4)
#define SI570_FREEZE_M (1<<5)
#define SI570_NEW_FREQ (1<<6)
#define SI570_REG_135 135
#define SI570_REG_137 137
#define FACTORY_FXTAL 114.285
// VCO range
#define FDCO_MAX 5670
#define FDCO_MIN 4850
#define POW_2_28 268435456.0
typedef struct {
uint8_t hsdiv;
uint8_t n1;
float64_t fdco;
float64_t rfreq;
float64_t freq;
} Si570_FreqConfig;
typedef struct OscillatorState
{
Si570_FreqConfig cur_config;
Si570_FreqConfig next_config;
float64_t fxtal; // base fxtal value
float64_t fxtal_ppm; // Frequency Correction of fxtal_calc
float64_t fxtal_calc; // ppm corrected fxtal value
uint8_t cur_regs[6];
bool next_is_small;
float fout; // contains startup frequency info of Si570
unsigned short si570_address;
uint8_t base_reg;
bool present; // is a working Si570 present?
} OscillatorState;
#define SMOOTH_DELTA (0.0035)
// Datasheet says 0.0035 == 3500PPM but there have been issues if we get close to that value.
// to play it safe, we make the delta range a little smaller.
// if you want to play with it, tune to the end of the 10m band, set 100 khz step width and dial around
// sooner or later jumps with delta close to 0.0035 (actually a calculated delta of 0.00334) cause a "crash" of Si570
static const uchar hs_div[6] = {11, 9, 7, 6, 5, 4};
static const float fdco_max = FDCO_MAX;
static const float fdco_min = FDCO_MIN;
OscillatorState os;
/*
* @brief Returns startup frequency value of Si570, call only after init of Si570
*
* @returns Startup frequency in Mhz
*/
//*----------------------------------------------------------------------------
//* Function Name : ui_si570_setbits
//* Object :
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
static uchar Si570_SetBits(unsigned char original, unsigned char reset_mask, unsigned char new_val)
{
return ((original & reset_mask) | new_val);
}
static uint16_t Si570_ReadRegisters(uint8_t* regs)
{
return UhsdrHw_I2C_ReadBlock(SI570_I2C, os.si570_address, os.base_reg, 1, regs, 6);
}
/*
* @brief reads Si570 registers and verifies match with local copy of settings
* @returns SI570_OK if matching, SI570_I2C_ERROR if I2C is not working, SI570_ERROR otherwise
*/
static Oscillator_ResultCodes_t Si570_VerifyFrequencyRegisters(void)
{
Oscillator_ResultCodes_t retval = OSC_OK;
uchar regs[6];
// Read all regs
if (Si570_ReadRegisters(&regs[0]))
{
retval = OSC_COMM_ERROR;
}
if (retval == OSC_OK)
{
// Not working - need fix
// memset(regs, 0, 6);
// trx4m_hw_i2c_ReadData(os.si570_address, 7, regs, 5);
if(memcmp(regs, (uchar*)os.cur_regs, 6) != 0)
{
retval = OSC_ERROR_VERIFY;
}
}
return retval;
}
static uint16_t Si570_SetRegisterBits(uint8_t si570_address, uint8_t regaddr ,uint8_t* reg_ptr,uint8_t val){
uint16_t retval = UhsdrHw_I2C_ReadRegister(SI570_I2C, si570_address, regaddr, 1, reg_ptr);
if (retval == 0)
{
retval = UhsdrHw_I2C_WriteRegister(SI570_I2C, si570_address, regaddr, 1, (*reg_ptr|val));
}
return retval;
}
static uint16_t Si570_ClearRegisterBits(uint8_t si570_address, uint8_t regaddr ,uint8_t* reg_ptr,uint8_t val){
uint16_t retval = UhsdrHw_I2C_ReadRegister(SI570_I2C, si570_address, regaddr, 1, reg_ptr);
if (retval == 0)
{
retval = UhsdrHw_I2C_WriteRegister(SI570_I2C, si570_address, regaddr, 1, (*reg_ptr & ~val));
}
return retval;
}
//*----------------------------------------------------------------------------
//* Function Name : ui_si570_small_frequency_change
//* Object : small frequency changes handling
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
static Oscillator_ResultCodes_t Si570_SmallFrequencyChange(void)
{
uint16_t ret;
Oscillator_ResultCodes_t retval = OSC_OK;
uchar reg_135;
// Read current
ret = Si570_SetRegisterBits(os.si570_address, SI570_REG_135, &reg_135, SI570_FREEZE_M);
if (ret == 0)
{
// Write as block, registers 7-12
ret = UhsdrHw_I2C_WriteBlock(SI570_I2C, os.si570_address, os.base_reg, 1, (uchar*)os.cur_regs, 6);
if (ret == 0)
{
retval = Si570_VerifyFrequencyRegisters();
}
else
{
retval = OSC_COMM_ERROR;
}
}
Si570_ClearRegisterBits(os.si570_address, SI570_REG_135, &reg_135, SI570_FREEZE_M);
return retval;
}
//*----------------------------------------------------------------------------
//* Function Name : ui_si570_large_frequency_change
//* Object : large frequency changes handling
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
static Oscillator_ResultCodes_t Si570_LargeFrequencyChange(void)
{
uint16_t ret;
uint8_t reg_135, reg_137;
Oscillator_ResultCodes_t retval = OSC_COMM_ERROR;
if (Si570_SetRegisterBits(os.si570_address, SI570_REG_137, &reg_137, SI570_FREEZE_DCO) == 0)
{
// Write as block, registers 7-12
if(UhsdrHw_I2C_WriteBlock(SI570_I2C, os.si570_address, os.base_reg, 1, (uchar*)os.cur_regs, 6) == 0)
{
retval = Si570_VerifyFrequencyRegisters();
}
}
// no matter what happened, try to unfreeze the Si570
ret = Si570_ClearRegisterBits(os.si570_address, SI570_REG_137, &reg_137, SI570_FREEZE_DCO);
if (ret == 0 && retval == OSC_OK)
{
if (Si570_SetRegisterBits(os.si570_address, SI570_REG_135, &reg_135, SI570_NEW_FREQ) == 0)
{
// Wait for action completed
do
{
ret = UhsdrHw_I2C_ReadRegister(SI570_I2C, os.si570_address, SI570_REG_135, 1, &reg_135);
} while(ret == 0 && (reg_135 & SI570_NEW_FREQ));
}
}
return ret!=0?OSC_COMM_ERROR:retval;
}
static void Si570_ClearConfig(Si570_FreqConfig *in) {
memset(in,0,sizeof(Si570_FreqConfig));
}
static void Si570_CopyConfig(Si570_FreqConfig *in, Si570_FreqConfig* out) {
memcpy(out,in,sizeof(Si570_FreqConfig));
}
static float64_t Si570_FDCO_InRange(float64_t fdco){
return (fdco >= fdco_min && fdco <= fdco_max);
}
static float64_t Si570_GetFDCOForFreq(float64_t new_freq, uint8_t n1, uint8_t hsdiv){
return (new_freq * (float64_t)(n1 * hsdiv));
}
static bool Si570_FindSmoothRFreqForFreq(const Si570_FreqConfig* cur_config, Si570_FreqConfig* new_config) {
float64_t fdco = Si570_GetFDCOForFreq(new_config->freq, cur_config->n1, cur_config->hsdiv);
bool retval = false;
float64_t fdiff = (fdco - cur_config->fdco)/cur_config->fdco;
if (fdiff < 0.0)
{
fdiff = -fdiff;
}
if (fdiff <= SMOOTH_DELTA && Si570_FDCO_InRange(fdco))
{
new_config->rfreq = fdco / (float64_t)os.fxtal_calc;
new_config->fdco = cur_config->fdco; // since we do only a small step, our fdco remains the same, so that we can keep an eye on the +/-3500ppm rule
new_config->n1 = cur_config->n1;
new_config->hsdiv = cur_config->hsdiv;
retval = true;
}
return retval;
}
static bool Si570_FindConfigForFreq(Si570_FreqConfig* config) {
uchar i;
uint16_t divider_max, curr_div;
bool retval = false;
bool n1_found = false;
uint8_t n1 = 1; // this is to shut up gcc 4.9.x regarding uninitalized variable
uint8_t hsdiv;
float64_t fdco;
divider_max = (ushort)floorf(fdco_max / config->freq);
curr_div = (ushort)ceilf (fdco_min / config->freq);
// for each available divisor hsdiv we calculate the n1 range
// and see if an acceptable n1 (1,all even numbers between 2..128)
// is available for the given divisor.
// this requires at most 12 float division
// for frequencies in the range from 3,45 to 120Mhz at most
for(i = 0; i < 6 && n1_found == false; i++)
{
hsdiv = hs_div[i];
uint8_t n1_cand_min = ceilf((float)curr_div / (float)hsdiv);
uint8_t n1_cand_max = floorf((float)divider_max / (float)hsdiv);
if ((n1_cand_max >= 1) && (n1_cand_min <= 128) ) {
if (n1_cand_min <= 1)
{
n1 = 1;
n1_found = true;
} else {
n1 = ((n1_cand_min+1)& ~1);
// get the closest even number (towards higher numbers)
if (n1 <= n1_cand_max) {
n1_found = true;
}
}
}
}
if (n1_found) {
fdco = Si570_GetFDCOForFreq(config->freq,n1,hsdiv);
if (Si570_FDCO_InRange(fdco)) {
config->n1 =n1;
config->hsdiv = hsdiv;
config->fdco = fdco;
config->rfreq = fdco / os.fxtal_calc;
retval = true;
}
}
return retval;
}
static Oscillator_ResultCodes_t Si570_ConfigToRegs(Si570_FreqConfig* config, uint8_t regs[6]) {
uint32_t frac_bits;
uint16_t whole;
uint8_t n1_regVal = config->n1 - 1;
uint8_t hsdiv_regVal = config->hsdiv - 4;
uint8_t i;
// the written value is n1 - 1, hsdiv -4 according to the datasheet
Oscillator_ResultCodes_t retval = OSC_OK;
for(i = 0; i < 6; i++)
{
regs[i] = 0;
}
regs[0] = (hsdiv_regVal << 5);
regs[0] = Si570_SetBits(regs[0], 0xE0, (n1_regVal >> 2));
regs[1] = (n1_regVal & 3) << 6;
whole = floorf(config->rfreq);
frac_bits = floorf((config->rfreq - whole) * POW_2_28);
for(i = 5; i >= 3; i--)
{
regs[i] = frac_bits & 0xFF;
frac_bits = frac_bits >> 8;
}
regs[2] = Si570_SetBits(regs[2], 0xF0, (frac_bits & 0xF));
regs[2] = Si570_SetBits(regs[2], 0x0F, (whole & 0xF) << 4);
regs[1] = Si570_SetBits(regs[1], 0xC0, (whole >> 4) & 0x3F);
return retval;
}
static Oscillator_ResultCodes_t Si570_WriteRegs(bool is_small) {
Oscillator_ResultCodes_t retval = OSC_OK;
if(is_small)
{
retval = Si570_SmallFrequencyChange();
}
else
{
retval = Si570_LargeFrequencyChange();
}
if(retval == OSC_OK)
{
// Verify second time - we might be transmitting, so
// it is absolutely unacceptable to be on startup
// SI570 frequency if any I2C error or chip reset occurs!
retval = Si570_VerifyFrequencyRegisters();
}
return retval;
}
static Oscillator_ResultCodes_t Si570_PrepareChangeFrequency(float64_t new_freq)
{
Oscillator_ResultCodes_t retval = OSC_OK;
Si570_FreqConfig* next_config_ptr = &os.next_config;
Si570_FreqConfig* cur_config_ptr = &os.cur_config;
next_config_ptr->freq = new_freq;
os.next_is_small = Si570_FindSmoothRFreqForFreq(cur_config_ptr,next_config_ptr);
if (os.next_is_small == false && Si570_FindConfigForFreq(next_config_ptr) == false)
{
retval = OSC_TUNE_IMPOSSIBLE;
}
else
{
retval = Si570_ConfigToRegs(next_config_ptr,os.cur_regs);
}
return retval;
}
/**
* @returns true if the next prepared step will be a large one, requiring sound muting etc. Requires a call to Si570_PrepareNextFrequency to have correct information
*/
static bool Si570_IsNextStepLarge(void)
{
return os.next_is_small == false;
}
/**
* @brief execute the prepared frequency change. May be called multiple times in case of I2C issues
* @returns SI570_OK or SI570_I2C_ERROR if I2C communication failed (which can happen at very high I2C speeds). SI570_ERROR_VERIFY should never happen anymore.
*/
static Oscillator_ResultCodes_t Si570_ChangeToNextFrequency(void)
{
Oscillator_ResultCodes_t retval = OSC_OK;
Si570_FreqConfig* next_config_ptr = &os.next_config;
Si570_FreqConfig* cur_config_ptr = &os.cur_config;
retval = Si570_WriteRegs(os.next_is_small);
// TODO: remove this handling, since it was almost certainly caused
// by a wrong interpretation of the data sheet regarding small steps.
if (retval == OSC_ERROR_VERIFY && os.next_is_small == true)
{
//
// sometimes the small change simply does not work
// for unknown reasons, so we execute a large step
// instead to recover.
retval = Si570_WriteRegs(false);
}
// If everything is fine, get on with remembering our current configuration
if (retval == OSC_OK) {
Si570_CopyConfig(next_config_ptr,cur_config_ptr);
}
else
{
Si570_ClearConfig(cur_config_ptr);
}
return retval;
}
//
// by DF8OE
//
// startupfrequency-subroutine
static void Si570_CalcSufHelper(void)
{
uchar si_regs[6];
int hs_div;
int n1;
float rsfreq;
Si570_ReadRegisters(si_regs);
// calculate startup frequency
rsfreq = (float)((si_regs[5] + (si_regs[4] * 0x100) + (si_regs[3] * 0x10000) + (double)((double)si_regs[2] * (double)0x1000000) + (double)((double)(si_regs[1] & 0x3F) * (double)0x100000000)) / (double)POW_2_28);
hs_div = (si_regs[0] & 0xE0) / 32 + 4;
n1 = (si_regs[1] & 0xC0) / 64 + (si_regs[0] & 0x1F) *4 + 1;
if (n1 %2 != 0 && n1 != 1)
{
n1++;
}
os.fout = roundf((1142850 * rsfreq) / (hs_div * n1)) / 10000;
}
float Si570_GetStartupFrequency()
{
return os.fout;
}
uint8_t Si570_GetI2CAddress()
{
return os.si570_address;
}
/**
* @brief Sets a new PPM value AND corrects the internally used xtal frequency accordingly
* @param ppm ppm value
*/
static void Si570_SetPPM(float32_t ppm)
{
os.fxtal_ppm = ppm;
os.fxtal_calc = os.fxtal + (os.fxtal / (float64_t)1000000.0) * os.fxtal_ppm;
if (Si570_PrepareChangeFrequency(os.cur_config.freq) == OSC_OK)
{
Si570_ChangeToNextFrequency();
}
}
static uint8_t Si570_ResetConfiguration(void)
{
uint8_t retval = 0;
short res;
ulong rfreq_frac;
ulong rfreq_int;
uchar hsdiv_curr;
uchar n1_curr;
// Reset publics
os.fxtal = FACTORY_FXTAL;
os.present = false;
res = UhsdrHw_I2C_WriteRegister(SI570_I2C, os.si570_address, SI570_REG_135, 1, SI570_RECALL);
if(res != 0)
{
retval = 1;
}
else
{
uint8_t ret;
int i = 0;
do
{
res = UhsdrHw_I2C_ReadRegister(SI570_I2C, os.si570_address, SI570_REG_135, 1, &ret);
if(res != 0)
{
retval = 2;
break;
}
i++;
if(i == 30)
{
retval = 3;
break;
}
} while(ret & SI570_RECALL);
if (retval == 0 && Si570_ReadRegisters(&(os.cur_regs[0])) != 0)
{
retval = 4;
}
else
{
hsdiv_curr = ((os.cur_regs[0] & 0xE0) >> 5) + 4;
n1_curr = 1 + ((os.cur_regs[0] & 0x1F) << 2) + ((os.cur_regs[1] & 0xC0) >> 6);
rfreq_int = (os.cur_regs[1] & 0x3F);
rfreq_int = (rfreq_int << 4) + ((os.cur_regs[2] & 0xF0) >> 4);
rfreq_frac = (os.cur_regs[2] & 0x0F);
rfreq_frac = (rfreq_frac << 8) + os.cur_regs[3];
rfreq_frac = (rfreq_frac << 8) + os.cur_regs[4];
rfreq_frac = (rfreq_frac << 8) + os.cur_regs[5];
float64_t rfreq = rfreq_int + (float64_t)rfreq_frac / POW_2_28;
os.fxtal = ((float64_t)os.fout * (float64_t)(n1_curr *hsdiv_curr)) / rfreq;
Si570_SetPPM(os.fxtal_ppm);
os.cur_config.rfreq = rfreq;
os.cur_config.n1 = n1_curr;
os.cur_config.hsdiv = hsdiv_curr;
os.cur_config.fdco = Si570_GetFDCOForFreq(os.fout,n1_curr,hsdiv_curr);
os.present = true;
}
}
return retval;
}
static Oscillator_ResultCodes_t Si570_PrepareNextFrequency(ulong freq, int temp_factor);
/**
* @brief Checks if all oscillator resources are available for switching frequency
* It basically checks if the I2C is currently in use
* This function must be called before changing the oscillator in interrupts
* otherwise deadlocks may happen
* @return true if it safe to call oscillator functions in an interrupt
*/
bool Si570_ReadyForIrqCall()
{
return (SI570_I2C->Lock == HAL_UNLOCKED);
}
static bool Oscillator_IsPresent(void)
{
return os.present;
}
static uint32_t Si570_getMinFrequency(void)
{
#ifdef RF_BRD_LAPWING
return 1240000000L;
#else
return SI570_HARD_MIN_FREQ/4;
#endif
}
static uint32_t Si570_getMaxFrequency(void)
{
#ifdef RF_BRD_LAPWING
return 1300000000L;
#else
return SI570_HARD_MAX_FREQ/4;
#endif
}
static uint32_t Si570_translateExt2Osc(uint32_t freq)
{
#ifdef RF_BRD_LAPWING
return freq - 1124500000L;
#else
return freq * 4;
// frequency multiplied with 4 since we drive a johnson counter for phased clock generation
#endif
}
const OscillatorInterface_t osc_si570 =
{
.init = Si570_Init,
.isPresent = Oscillator_IsPresent,
.setPPM = Si570_SetPPM,
.prepareNextFrequency = Si570_PrepareNextFrequency,
.changeToNextFrequency = Si570_ChangeToNextFrequency,
.isNextStepLarge = Si570_IsNextStepLarge,
.readyForIrqCall = Si570_ReadyForIrqCall,
.name = "Si570",
.type = OSC_SI570,
.getMinFrequency = Si570_getMinFrequency,
.getMaxFrequency = Si570_getMaxFrequency,
};
void Si570_Init()
{
os.base_reg = 13; // first test with regs 13+ for 7ppm SI570
uchar dummy;
// test for hardware address of SI570
os.si570_address = (0x55 << 1);
if(UhsdrHw_I2C_ReadRegister(SI570_I2C,os.si570_address, (os.base_reg),1, &dummy) != 0)
{
os.si570_address = (0x50 << 1);
if(UhsdrHw_I2C_ReadRegister(SI570_I2C,os.si570_address, (os.base_reg),1, &dummy) != 0)
{
os.si570_address = (0x01 << 1);
}
}
if (UhsdrHw_I2C_DeviceReady(SI570_I2C,os.si570_address) == HAL_OK)
{
// make sure everything is cleared and in initial state
Si570_ResetConfiguration();
Si570_CalcSufHelper();
if(os.fout > 39.2 && os.fout < 39.3)
{
// its a 20 or 50 ppm device, use regs 7+
os.base_reg = 7;
Si570_CalcSufHelper();
}
// all known startup frequencies
static const float suf_table[] =
{
10,
10.356,
14.05,
14.1,
15,
16.0915,
22.5792,
34.285,
56.32,
63,
76.8,
100,
122,
125,
156.25,
0
};
// test if startup frequency is known
for (int i = 0; suf_table[i] != 0; i++)
{
float test = os.fout - suf_table[i];
if (test < 0)
{
test = -test;
}
if (test < 0.2)
{
os.fout = suf_table[i];
break;
}
}
// we wait a little and then reset again
HAL_Delay(40);
Si570_ResetConfiguration();
}
osc = os.present?&osc_si570:NULL;
}
/**
* @brief prepares all necessary information for the next frequency change
* @param freq frequency in Hz to which the LO should be tuned.
* @param calib the calibration correction value for the real vs. data sheet frequency of the Si570.
* @param temp_factor the SoftTCXO code calculates a temperature correct value which is used to make a virtual tcxo out of the Si570.
*
* @returns SI570_TUNE_IMPOSSIBLE if tuning to the desired frequency is not possible at all (multiple reasons), SI570_OK if it is possible and within spec, SI570_TUNE_LIMITED if possible but out of spec
*/
static Oscillator_ResultCodes_t Si570_PrepareNextFrequency(ulong freq, int temp_factor)
{
Oscillator_ResultCodes_t retval = OSC_TUNE_IMPOSSIBLE;
if (osc->isPresent() == true) {
float64_t freq_calc, temp_scale;
freq_calc = Si570_translateExt2Osc(freq);
temp_scale = ((float64_t)temp_factor)/14000000.0;
// calculate scaling factor for the temperature correction (referenced to 14.000 MHz)
freq_calc *= (1 + temp_scale); // rescale by temperature correction factor
// when tuning frequency is outside SI570 hard limits, don't do it
if (freq_calc <= SI570_HARD_MAX_FREQ && freq_calc >= SI570_HARD_MIN_FREQ)
{
// tuning inside known working spec
retval = Si570_PrepareChangeFrequency(freq_calc/((float64_t)1000000.0));
if ((freq_calc > SI570_MAX_FREQ || freq_calc < SI570_MIN_FREQ))
{
// outside official spec but known to work
if (retval == OSC_OK)
{
retval = OSC_TUNE_LIMITED;
}
}
}
}
return retval;
}
@@ -0,0 +1,26 @@
/* -*- 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 **
************************************************************************************/
#ifndef __HW_SI570
#define __HW_SI570
#include "osc_interface.h"
void Si570_Init(void);
// non-critical device information reading
float32_t Si570_GetStartupFrequency(void);
uint8_t Si570_GetI2CAddress(void);
#endif
@@ -0,0 +1,329 @@
/* -*- 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 **
************************************************************************************/
//
// SI570 frequency shift table
// 0-100 degrees C range
// shots from 20m band (56Mhz)
//
// This frequency compensation table referenced to 14.000 MHz by KA7OEI, 10/14 using
// a GPS reference in a temperature-controlled environment, extrapolated below 17C and above
// 70C.
//
// Temperature normalized to 43C, a temperature achieved very soon after power-up
// with both the Si570 and the temperature sensor thermally bonded.
//
// Note: The exact frequency/temperature dependencies will likely vary from unit to unit
// for each Si570, but the values below appear to approximately follow typical AT-cut
// temperature-frequency curves.
//
#include "uhsdr_board.h"
#include "soft_tcxo.h"
#include "radio_management.h"
#include "uhsdr_hw_i2c.h"
LoTcxo lo;
// -------------------------------------------------------------------------------------
// Temperature sensor
// ------------------
#define MCP_ADDR (0x90)
// MCP registers
#define MCP_TEMP (0x00)
#define MCP_CONFIG (0x01)
#define MCP_HYSTR (0x02)
#define MCP_LIMIT (0x03)
// MCP CONFIG register bits
#define MCP_ONE_SHOT (7)
#define MCP_ADC_RES (5)
#define MCP_FAULT_QUEUE (3)
#define MCP_ALERT_POL (2)
#define MCP_INT_MODE (1)
#define MCP_SHUTDOWN (0)
#define R_BIT (1)
#define W_BIT (0)
#define MCP_ADC_RES_9 0
#define MCP_ADC_RES_10 1
#define MCP_ADC_RES_11 2
#define MCP_ADC_RES_12 3
#define MCP_POWER_UP 0
#define MCP_POWER_DOWN 1
static int32_t MCP9801_ConvExternalTemp(uint8_t *temp)
{
int32_t ts = 0;
ts = temp[1];
ts += (int8_t)temp[0] << 8;
ts *= 10000;
ts /= 256;
return ts;
}
/*
* @brief configures the MCP9801 external temperature sensor for monitoring Si570 temperature
* @returns 0 if detected and working, 1 if not detected on I2C, 2 for other errors
*/
static uint8_t MCP9801_InitExternalTempSensor(void)
{
uint8_t config, retval = 0;
uint16_t res;
// Read config reg
res = UhsdrHw_I2C_ReadRegister(MCP_I2C, MCP_ADDR, MCP_CONFIG, 1, &config);
if(res != 0)
{
retval = 1;
}
else
{
// Modify resolution
config &= ~(3 << MCP_ADC_RES);
config |= (MCP_ADC_RES_12 << MCP_ADC_RES);
// Modify power mode
config &= ~(1 << MCP_SHUTDOWN);
config |= (MCP_POWER_UP << MCP_SHUTDOWN);
// Write config reg
res = UhsdrHw_I2C_WriteRegister(MCP_I2C, MCP_ADDR, MCP_CONFIG, 1, config);
if(res != 0)
{
retval = 2;
}
}
return retval;
}
static uint8_t MCP9801_ReadExternalTempSensor(int32_t *temp)
{
uint8_t data[2];
uint8_t retval = 0;
// Read temperature
if(temp != NULL && UhsdrHw_I2C_ReadBlock(MCP_I2C, MCP_ADDR, MCP_TEMP, 1, data, 2) == 0)
{
*temp = MCP9801_ConvExternalTemp(data);
}
else
{
retval = 2;
}
return retval;
}
#define TCXO_TBL_SIZE 100
const short tcxo_table_20m[TCXO_TBL_SIZE] =
{
-165 // 0 C
-162, // 1 C
-160, // 2 C
-157, // 3 C
-155, // 4 C
-152, // 5 C
-150, // 6 C
-148, // 7 C
-144, // 8 C
-142, // 9 C
-136, // 10 C
-132, // 11 C
-130, // 12 C
-129, // 13 C
-126, // 14 C
-121, // 15 C
-116, // 16 C
-112, // 17 C
-108, // 18 C
-103, // 19 C
-99, // 20 C
-95, // 21 C
-90, // 22 C
-86, // 23 C
-81, // 24 C
-75, // 25 C
-70, // 26 C
-66, // 27 C
-61, // 28 C
-57, // 29 C
-53, // 30 C
-46, // 31 C
-42, // 32 C
-38, // 33 C
-32, // 34 C
-28, // 35 C
-25, // 36 C
-20, // 37 C
-17, // 38 C
-13, // 39 C
-9, // 40 C
-5, // 41 C
-2, // 42 C
1, // 43 C
4, // 44 C
7, // 45 C
10, // 46 C
12, // 47 C
15, // 48 C
16, // 49 C
18, // 50 C
20, // 51 C
21, // 52 C
22, // 53 C
23, // 54 C
23, // 55 C
24, // 56 C
23, // 57 C
23, // 58 C
22, // 59 C
21, // 60 C
20, // 61 C
18, // 62 C
16, // 63 C
14, // 64 C
11, // 65 C
7, // 66 C
3, // 67 C
-1, // 68 C
-5, // 69 C
-11,// 70 C
-17, // 71 C
-24, // 72 C
-31, // 73 C
-38, // 74 C
-45, // 75 C
-52, // 76 C
-58, // 77 C
-67, // 78 C
-71, // 79 C
-77, // 80 C
-83, // 81 C
-89, // 82 C
-95, // 83 C
-102, // 84 C
-108, // 85 C
-115, // 86 C
-121, // 87 C
-127, // 88 C
-134, // 89 C
-141, // 90 C
-147, // 91 C
-153, // 92 C
-159, // 93 C
-166, // 94 C
-177, // 95 C
-184, // 96 C
-190, // 97 C
-197, // 98 C
-203 // 99 C
};
void SoftTcxo_Init()
{
lo.comp = 0;
// Temp sensor setup
lo.sensor_present = MCP9801_InitExternalTempSensor() == 0;
}
/*
* @brief measure local oscillator temperature and calculates compensation value
* @return true if the temperature value has been measured
*/
bool SoftTcxo_HandleLoTemperatureDrift()
{
int32_t temp = 0;
int comp, comp_p;
float dtemp, remain, t_index;
uchar tblp;
uint8_t temp_mode = RadioManagement_TcxoGetMode();
bool retval = false;
// No need to process if no chip avail or tcxo is disabled
if((lo.sensor_present == true) && RadioManagement_TcxoIsEnabled())
{
{
// Get current temperature
if(MCP9801_ReadExternalTempSensor(&temp) == 0)
{
// Get temperature from sensor with its maximum precision
dtemp = (float)temp; // get temperature
dtemp /= 10000; // convert to decimal degrees
remain = truncf(dtemp); // get integer portion of temperature
remain = dtemp - remain; // get fractional portion
// Compensate only if enabled
if((temp_mode == TCXO_ON))
{
// Temperature to unsigned table pointer
t_index = (uchar)((temp%1000000)/100000);
t_index *= 10;
t_index += (uchar)((temp%100000)/10000);
// Check for overflow - keep within the lookup table
if((t_index < 0) || (t_index > 150)) // the temperature sensor function "wraps around" below zero
{
t_index = 0; // point at the bottom of the temperature table
dtemp = 0; // zero out fractional calculations
remain = 0;
}
else if(t_index > TCXO_TBL_SIZE - 2) // High temperature - limit to maximum
{
t_index = TCXO_TBL_SIZE - 2; // Point to (near) top of table
dtemp = 0; // zero out fractional calculations
remain = 0;
}
tblp = (uchar)t_index; // convert to index
comp = tcxo_table_20m[tblp]; // get the first entry in the table
comp_p = tcxo_table_20m[tblp + 1]; // get the next entry in the table to determine fraction of frequency step
comp_p = comp_p - comp; // // get frequency difference between the two steps
dtemp = (float)comp_p; // change it to float for the calculation
dtemp *= remain; // get proportion of temperature difference between the two steps using the fraction
comp += (int)dtemp; // add the compensation value to the lower of the two frequency steps
// Change needed ?
if(lo.comp != comp) // is it there a difference?
{
// Update frequency, without reflecting it on the LCD
df.temp_factor = comp;
df.temp_factor_changed = true;
lo.comp = comp;
}
}
// Refresh UI
retval = true;
lo.temp = temp;
}
}
}
return retval;
}
@@ -0,0 +1,50 @@
/* -*- 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 **
************************************************************************************/
//
// SI570 frequency shift table
// 0-100 degrees C range
// shots from 20m band (56Mhz)
//
// This frequency compensation table referenced to 14.000 MHz by KA7OEI, 10/14 using
// a GPS reference in a temperature-controlled environment, extrapolated below 17C and above
// 70C.
//
// Temperature normalized to 43C, a temperature achieved very soon after power-up
// with both the Si570 and the temperature sensor thermally bonded.
//
// Note: The exact frequency/temperature dependencies will likely vary from unit to unit
// for each Si570, but the values below appear to approximately follow typical AT-cut
// temperature-frequency curves.
//
#include "uhsdr_types.h"
// LO temperature compensation
typedef struct LoTcxo
{
// Current compensation value
// loaded to LO
int32_t comp;
int32_t temp;
bool sensor_present;
} LoTcxo;
// ------------------------------------------------
// LO Tcxo
extern LoTcxo lo;
bool SoftTcxo_HandleLoTemperatureDrift(void);
void SoftTcxo_Init(void);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,411 @@
/* -*- 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_ */
@@ -0,0 +1,22 @@
/* -*- 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 **
************************************************************************************/
#ifndef __UI_H
#define __UI_H
#include "uhsdr_board.h"
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,712 @@
/* -*- 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 **
************************************************************************************/
#ifndef DRIVERS_UI_UI_CONFIGURATION_H_
#define DRIVERS_UI_UI_CONFIGURATION_H_
#include "uhsdr_board.h"
enum
{
ConfigEntry_Stop = 0,
ConfigEntry_UInt8,
ConfigEntry_UInt16,
ConfigEntry_UInt32_16,
ConfigEntry_Int32_16,
ConfigEntry_Int16,
ConfigEntry_Int32, //this type saves and reads two subsequent 16bit words
ConfigEntry_UInt8x2, // this type saves and reads two indepent 8 bit values stored in a 16bit structure. This is relevant for defaults, which are independent
// ConfigEntry_Bool,
Calib_Val = 0x10000000, // if this is "or"ed with a normal ConfigEntry_... value, it indicates this parameter is a hardware calibration parameter.
ConfigEntry_TypeMask = 0x0000ffff, // we support 2^16 different types, this is plenty.
};
typedef struct
{
int typeId;
uint16_t id;
volatile void* val_ptr;
int32_t val_default;
int32_t val_min;
int32_t val_max;
// uint16_t item_count; // 0 or 1 indicates single value; higher values indicate arrays
// uint16_t item_data_spacing; // only used for 32bit values; indicates the distance of the higher 16 bits from the lower 16bits
} ConfigEntryDescriptor;
const ConfigEntryDescriptor* UiConfiguration_GetEntry(uint16_t id);
void UiConfiguration_LoadEepromValues(bool load_freq_mode_defaults, bool load_eeprom_defaults);
uint16_t UiConfiguration_SaveEepromValues(void);
void UiConfiguration_UpdateMacroCap(void);
// Configuration Value Definitions Follow
//
//
#define SIDETONE_MAX_GAIN 15 // Maximum sidetone gain
#define DEFAULT_SIDETONE_GAIN 5 // Default sidetone gain
//
#define CW_KEYER_SPEED_MIN 5 // Minimum keyer speed
#define CW_KEYER_SPEED_MAX 48 // Maximum keyer speed
#define CW_KEYER_SPEED_DEFAULT 20 // Default keyer speed
//
//
#define USB_FREQ_THRESHOLD (10000000) // dial frequency at and above which the default is USB, Hz
//
//
#define MIN_RIT_VALUE -60 // Minimum RIT Value -1.2 kHz
#define MAX_RIT_VALUE 60 // Maximum RIT Value +1.2 kHz
#define LINEOUT_GAIN_DEFAULT 0x49 // Default lineout gain setting in dB steps
#define LINEOUT_GAIN_MIN 1 // min lineout gain setting in dB steps
#define LINEOUT_GAIN_MAX 0x50 // max lineout gain setting in dB steps
#define AUDIO_GAIN_DEFAULT 16 // Default audio gain
#define AUDIO_GAIN_MAX 30 // Maximum audio gain setting
#define DIG_GAIN_MAX 31 // Maximum audio gain setting
#define DIG_GAIN_DEFAULT 16 // Default audio gain
//
// The following are used in the max volume setting in the menu system
//
#define MAX_VOLUME_MIN 8 // Minimum setting for maximum volume
#define MAX_VOLUME_MAX AUDIO_GAIN_MAX // Maximum setting for maximum volume
#define MAX_VOLUME_DEFAULT AUDIO_GAIN_DEFAULT
//
#define MAX_VOLUME_RED_THRESH 10 // "MAX VOLUME" setting at or below which number will be RED to warn user
#define MAX_VOLUME_YELLOW_THRESH 16 // "MAX VOLUME" setting at or below which number will be YELLOW to warn user
#define MAGNIFY_MIN 0
#define MAGNIFY_MAX 5
#define MAGNIFY_DEFAULT 0
#define MAGNIFY_NUM (MAGNIFY_MAX+1)
//
#define PA_BIAS_MAX 115 // Maximum PA Bias Setting
#define PA_BIAS_DEFAULT 0 // Default PA Bias setting
#define PA_BIAS_LOW_LIMIT 20 // Minimum bias setting. (Below this, number is red)
//
#define BIAS_OFFSET 25 // Offset value to be added to bias setting
// DA value = (OFFSET + (2*setting)) where DA value is 0-255
//
#define XVERTER_MULT_MAX 10 // maximum LO multipler in xverter mode
//#define XVERTER_OFFSET_MAX 999000000 // Maximum transverter offset (999 MHz)
#define XVERTER_OFFSET_MAX_HZ 499999999 // Maximum transverter offset, setting in Hz. More - in kHz
#define XVERTER_OFFSET_MAX 1999999999 // Maximum transverter offset
//
#define AUTO_LSB_USB_OFF 0
#define AUTO_LSB_USB_ON 1
#define AUTO_LSB_USB_60M 2
#define AUTO_LSB_USB_MAX 2
#define AUTO_LSB_USB_DEFAULT AUTO_LSB_USB_60M
// used to limit the voltmeter calibration parameters
//
#define POWER_VOLTMETER_CALIBRATE_DEFAULT 100
#define POWER_VOLTMETER_CALIBRATE_MIN 00
#define POWER_VOLTMETER_CALIBRATE_MAX 200
#define LOW_POWER_CONFIG_DEFAULT (90-LOW_POWER_THRESHOLD_OFFSET)
#define LOW_POWER_CONFIG_MIN 0
#define LOW_POWER_CONFIG_MAX (LOW_POWER_ENABLE_MASK + LOW_POWER_THRESHOLD_MAX)
#define SWR_CAL_MIN 75
#define SWR_CAL_MAX 150
#define SWR_CAL_DEFAULT 100
//
#define SENSOR_NULL_MIN 75
#define SENSOR_NULL_MAX 125
#define SENSOR_NULL_DEFAULT 100
#define SPEC_COLOUR_TRACE_DEFAULT SPEC_WHITE
#define SPEC_COLOUR_TRACEBW_DEFAULT SPEC_WHITE
#define SPEC_COLOUR_BACKGRBW_DEFAULT 20
#define SPEC_COLOUR_GRID_DEFAULT SPEC_GREY4
#define SPEC_COLOUR_SCALE_DEFAULT SPEC_GREY4
#define FILTER_DISP_COLOUR_DEFAULT SPEC_GREY4
//
// *************************************************************************************************************************
//
// EEPROM Items IDs
//
// These do NOT use "enum" as it is important that the number *NOT* change
// by the insertion of new variables: All NEW variable should be placed at
// the END of the list to maintain compatibility with older versions and the settings!
// If a firmware no longer uses an ID, do not delete the ID entry, just comment it out!
// This allows to track former use of an ID for a particular purpose.
// DO NOT REUSE PREVIOUSLY USED IDs without thinking twice. Old entries from former
// use may cause unexpected behavior with the new firmware and vice versa
// if downgrading from a new one to an old firmware.
//
//
#define EEPROM_ZERO_LOC 0
#define EEPROM_BAND_MODE 1
#define EEPROM_FREQ_HIGH 2
#define EEPROM_FREQ_LOW 3
#define EEPROM_FREQ_STEP 4
#define EEPROM_TX_AUDIO_SRC 5
#define EEPROM_TCXO_STATE 6
#define EEPROM_PA_BIAS 7
#define EEPROM_AUDIO_GAIN 8
#define EEPROM_RX_CODEC_GAIN 9
#define EEPROM_MAX_VOLUME 10
#define EEPROM_POWER_STATE 11
#define EEPROM_TX_POWER_LEVEL 12
#define EEPROM_CW_KEYER_SPEED 13
#define EEPROM_CW_KEYER_MODE 14
#define EEPROM_CW_SIDETONE_GAIN 15
#define EEPROM_MIC_BOOST 16
#define EEPROM_TX_IQ_80M_GAIN_BALANCE 17 // TX gain balance
#define EEPROM_TX_IQ_80M_PHASE_BALANCE 18 // TX phase balance
#define EEPROM_RX_IQ_80M_GAIN_BALANCE 19
#define EEPROM_RX_IQ_80M_PHASE_BALANCE 20
#if 0 /* config value locations below are no longer in use since 2.5.18 */
#define EEPROM_BAND0_MODE 21 // Band/mode/filter memory per-band - bands indexed from here
#define EEPROM_BAND1_MODE 22
#define EEPROM_BAND2_MODE 23
#define EEPROM_BAND3_MODE 24
#define EEPROM_BAND4_MODE 25
#define EEPROM_BAND5_MODE 26
#define EEPROM_BAND6_MODE 27
#define EEPROM_BAND7_MODE 28
#define EEPROM_BAND8_MODE 29
#define EEPROM_BAND9_MODE 30
#define EEPROM_BAND10_MODE 31
#define EEPROM_BAND11_MODE 32
#define EEPROM_BAND12_MODE 33
#define EEPROM_BAND13_MODE 34
#define EEPROM_BAND14_MODE 35
#define EEPROM_BAND15_MODE 36
#define EEPROM_BAND16_MODE 37
#define EEPROM_BAND17_MODE 38 // "Floating" General coverage band
//
//
#define EEPROM_BAND0_FREQ_HIGH 39 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_HIGH 40
#define EEPROM_BAND2_FREQ_HIGH 41
#define EEPROM_BAND3_FREQ_HIGH 42
#define EEPROM_BAND4_FREQ_HIGH 43
#define EEPROM_BAND5_FREQ_HIGH 44
#define EEPROM_BAND6_FREQ_HIGH 45
#define EEPROM_BAND7_FREQ_HIGH 46
#define EEPROM_BAND8_FREQ_HIGH 47
#define EEPROM_BAND9_FREQ_HIGH 48
#define EEPROM_BAND10_FREQ_HIGH 49
#define EEPROM_BAND11_FREQ_HIGH 50
#define EEPROM_BAND12_FREQ_HIGH 51
#define EEPROM_BAND13_FREQ_HIGH 52
#define EEPROM_BAND14_FREQ_HIGH 53
#define EEPROM_BAND15_FREQ_HIGH 54
#define EEPROM_BAND16_FREQ_HIGH 55
#define EEPROM_BAND17_FREQ_HIGH 56 // "Floating" General coverage band
//
//
#define EEPROM_BAND0_FREQ_LOW 57 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_LOW 58
#define EEPROM_BAND2_FREQ_LOW 59
#define EEPROM_BAND3_FREQ_LOW 60
#define EEPROM_BAND4_FREQ_LOW 61
#define EEPROM_BAND5_FREQ_LOW 62
#define EEPROM_BAND6_FREQ_LOW 63
#define EEPROM_BAND7_FREQ_LOW 64
#define EEPROM_BAND8_FREQ_LOW 65
#define EEPROM_BAND9_FREQ_LOW 66
#define EEPROM_BAND10_FREQ_LOW 67
#define EEPROM_BAND11_FREQ_LOW 68
#define EEPROM_BAND12_FREQ_LOW 69
#define EEPROM_BAND13_FREQ_LOW 70
#define EEPROM_BAND14_FREQ_LOW 71
#define EEPROM_BAND15_FREQ_LOW 72
#define EEPROM_BAND16_FREQ_LOW 73
#define EEPROM_BAND17_FREQ_LOW 74 // "Floating" General coverage band
#endif
//
//
#define EEPROM_FREQ_CAL 75 // Frequency calibration
#define EEPROM_NB_SETTING 76 // Noise Blanker Setting
//#define EEPROM_AGC_MODE 77 // AGC setting
#define EEPROM_MIC_GAIN 78 // Mic gain setting
#define EEPROM_LINE_GAIN 79 // Line gain setting
#define EEPROM_SIDETONE_FREQ 80 // Sidetone frequency (Hz)
#define EEPROM_SPEC_SCOPE_SPEED 81 // Spectrum Scope Speed
#define EEPROM_SPECTRUM_FILTER 82 // Spectrum Scope filter strength
//#define EEPROM_RX_GAIN 83 // RX Gain setting (e.g. minimum RF gain as might be used for manual AGC)
//#define EEPROM_AGC_CUSTOM_DECAY 84 // Custom setting for AGC decay rate
#define EEPROM_SPECTRUM_TRACE_COLOUR 85 // Custom setting for spectrum scope trace colour
#define EEPROM_SPECTRUM_GRID_COLOUR 86 // Custom setting for spectrum scope grid colour
#define EEPROM_SPECTRUM_SCALE_COLOUR 87 // Custom setting for spectrum scope frequency scale colour
#define EEPROM_PADDLE_REVERSE 88 // TRUE if paddle is to be reversed
#define EEPROM_CW_RX_DELAY 89 // Delay after last CW element before returning to receive
#define EEPROM_SPECTRUM_CENTRE_LINE_COLOUR 90 // Custom setting for spectrum scope grid center marker colour
//
#define EEPROM_DETECTOR_COUPLING_COEFF_2200M 91 // Calibration coupling coefficient for FWD/REV power sensor for 80 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_630M 92 // Calibration coupling coefficient for FWD/REV power sensor for 80 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_80M 93 // Calibration coupling coefficient for FWD/REV power sensor for 80 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_40M 94 // Calibration coupling coefficient for FWD/REV power sensor for 60/40 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_20M 95 // Calibration coupling coefficient for FWD/REV power sensor for 30/20/17 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_15M 96 // Calibration coupling coefficient for FWD/REV power sensor for 15/12 meters
//
// The following are the coefficients used to set the RF output power settings
//
#define EEPROM_BAND0_5W 97 // 5 watt power setting, 80m
#define EEPROM_BAND1_5W 98 // 5 watt power setting, 60m
#define EEPROM_BAND2_5W 99 // 5 watt power setting, 40m
#define EEPROM_BAND3_5W 100 // 5 watt power setting, 30m
#define EEPROM_BAND4_5W 101 // 5 watt power setting, 20m
#define EEPROM_BAND5_5W 102 // 5 watt power setting, 17m
#define EEPROM_BAND6_5W 103 // 5 watt power setting, 15m
#define EEPROM_BAND7_5W 104 // 5 watt power setting, 12m
#define EEPROM_BAND8_5W 105 // 5 watt power setting, 10m
#define EEPROM_BAND9_5W 106 // 5 watt power setting, 6m
#define EEPROM_BAND10_5W 107 // 5 watt power setting, 4m
#define EEPROM_BAND11_5W 108 // 5 watt power setting, 2m
#define EEPROM_BAND12_5W 109 // 5 watt power setting, 70cm
#define EEPROM_BAND13_5W 110 // 5 watt power setting, 23cm
#define EEPROM_BAND14_5W 111 // 5 watt power setting, 2200m
#define EEPROM_BAND15_5W 112 // 5 watt power setting, 630m
#define EEPROM_BAND16_5W 113 // 5 watt power setting, 160m
#define EEPROM_BAND17_5W 114 // reserved
//
#define EEPROM_BAND0_FULL 115 // "FULL" power setting, 80m
#define EEPROM_BAND1_FULL 116 // "FULL" power setting, 60m
#define EEPROM_BAND2_FULL 117 // "FULL" power setting, 40m
#define EEPROM_BAND3_FULL 118 // "FULL" power setting, 30m
#define EEPROM_BAND4_FULL 119 // "FULL" power setting, 20m
#define EEPROM_BAND5_FULL 120 // "FULL" power setting, 17m
#define EEPROM_BAND6_FULL 121 // "FULL" power setting, 15m
#define EEPROM_BAND7_FULL 122 // "FULL" power setting, 12m
#define EEPROM_BAND8_FULL 123 // "FULL" power setting, 10m
#define EEPROM_BAND9_FULL 124 // "FULL" power setting, 6m
#define EEPROM_BAND10_FULL 125 // "FULL" power setting, 4m
#define EEPROM_BAND11_FULL 126 // "FULL" power setting, 2m
#define EEPROM_BAND12_FULL 127 // "FULL" power setting, 70cm
#define EEPROM_BAND13_FULL 128 // "FULL" power setting, 23cm
#define EEPROM_BAND14_FULL 129 // "FULL" power setting, 2200m
#define EEPROM_BAND15_FULL 130 // "FULL" power setting, 630m
#define EEPROM_BAND16_FULL 131 // "FULL" power setting, 160m
#define EEPROM_BAND17_FULL 132 // reserved
//
#if 0 // No longer being used, superseded by filter path
#define EEPROM_FILTER_300HZ_SEL 133 // Selection of 300 Hz filter
#define EEPROM_FILTER_500HZ_SEL 134 // Selection of 500 Hz filter
#define EEPROM_FILTER_1K8_SEL 135 // Selection of 1.8 kHz filter
#define EEPROM_FILTER_2K3_SEL 136 // Selection of 2.3 kHz filter
#define EEPROM_FILTER_3K6_SEL 137 // Selection of 3.6 kHz filter
#define EEPROM_FILTER_WIDE_SEL 138 // Selection of "Wide" filter (>3.6kHz)
//
#endif
#define EEPROM_TX_IQ_10M_GAIN_BALANCE 139 // TX gain balance
#define EEPROM_TX_IQ_10M_PHASE_BALANCE 140 // TX phase balance
#define EEPROM_RX_IQ_10M_GAIN_BALANCE 141
#define EEPROM_RX_IQ_10M_PHASE_BALANCE 142
#define EEPROM_SENSOR_NULL 143 // Power meter sensor null calibrate
//#define EEPROM_REV_PWR_CAL 144 // REV power meter calibrate
//
#define EEPROM_XVERTER_DISP 145 // TRUE if display is offset with transverter frequency offset
#define EEPROM_XVERTER_OFFSET_HIGH 146 // Frequency by which the display is offset for transverter use, high byte
//
#define EEPROM_VFO_MEM_MODE 147 // settings of VFO/SPLIT/Memory configuration bits - see variable "vfo_mem_mode" for information.
//
#define EEPROM_XVERTER_OFFSET_LOW 148 // Low byte of above
//
#define EEPROM_SPECTRUM_MAGNIFY 149 // TRUE if spectrum scope is to be magnified
//
//#define EEPROM_WIDE_FILT_CW_DISABLE 150 // TRUE if wide filters are to be disabled in CW mode
//#define EEPROM_NARROW_FILT_SSB_DISABLE 151 // TRUE if narrow filters are to be disabled in SSB mode
//
#define EEPROM_AM_MODE_DISABLE 152 // TRUE if AM mode is to be disabled
//
#define EEPROM_PA_CW_BIAS 153 // If non-zero, this is the PA bias setting when in CW mode
//
#define EEPROM_SPECTRUM_DB_DIV 154 // Spectrum Scope dB/Division
#define EEPROM_SPECTRUM_AGC_RATE 155 // AGC setting for spectrum scope
//
#define EEPROM_METER_MODE 156 // Stored setting of meter mode
//
#define EEPROM_ALC_DECAY_TIME 157 // ALC Decay time
#define EEPROM_ALC_POSTFILT_TX_GAIN 158 // ALC post-filter TX audio gain
//
#define EEPROM_STEP_SIZE_CONFIG 159 // TRUE if there is to be a line under the frequency digit indicating step size
//
#define EEPROM_DSP_MODE 160 // Stores the DSP operational mode
#define EEPROM_DSP_NR_STRENGTH 161 // Stores the DSP Noise Reduction operational strength
#ifdef OBSOLETE_NR
#define EEPROM_DSP_NR_DECOR_BUFLEN 162 // DSP Noise Reduction De-correlator buffer length
#define EEPROM_DSP_NR_FFT_NUMTAPS 163 // DSP Noise Reduction FFT number of taps
#define EEPROM_DSP_NOTCH_DECOR_BUFLEN 164 // DSP Notch De-correlator buffer length
#define EEPROM_DSP_NOTCH_CONV_RATE 165 // DSP Notch convergence rate
#endif
#ifdef USE_LMS_AUTONOTCH
#define EEPROM_DSP_NOTCH_DECOR_BUFLEN 164 // DSP Notch De-correlator buffer length
#define EEPROM_DSP_NOTCH_CONV_RATE 165 // DSP Notch convergence rate
#endif
//
//#define EEPROM_MAX_RX_GAIN 166 // Maximum RX gain - adjusts maximum allowed AGC gain in S-units
#define EEPROM_TX_AUDIO_COMPRESS 167 // TX audio compressor setting, used to calculate other values
//
#define EEPROM_TX_IQ_80M_GAIN_BALANCE_TRANS_OFF 168 // IQ Gain balance for AM reception
//
#define EEPROM_TX_DISABLE 169 // TRUE of transmit is to be disabled
#define EEPROM_FLAGS1 170 // Miscellaneous status flag, saved in EEPROM - see variable "flags1"
#define EEPROM_VERSION_RELEASE 171 // Storage of current version release - used to detect change of firmware
#define EEPROM_NB_AGC_TIME_CONST 172 // Noise blanker AGC time constant setting
#define EEPROM_CW_OFFSET_MODE 173 // CW Offset mode
#define EEPROM_FREQ_CONV_MODE 174 // Frequency Conversion Mode (e.g. I/Q frequency conversion done in receive/transmit to offset from zero)
#define EEPROM_LSB_USB_AUTO_SELECT 175 // Auto selection of LSB/USB above/below 10 MHz (including 60 meters)
#define EEPROM_VERSION_MAJOR 176 // Storage of current version build number - used to detect change of firmware
#define EEPROM_LCD_BLANKING_CONFIG 177 // Configuration of automatic LCD blanking mode settings
#define EEPROM_VOLTMETER_CALIBRATE 178 // Holder for calibration of the on-screen voltmeter
#define EEPROM_WATERFALL_COLOR_SCHEME 179 // Color scheme for waterfall display
#define EEPROM_WATERFALL_VERTICAL_STEP_SIZE 180 // Number of vertical steps of waterfall per iteration
#define EEPROM_WATERFALL_OFFSET 181 // Palette offset for waterfall
#define EEPROM_WATERFALL_CONTRAST 182 // Palette contrast multiplier for waterfall
//
// VFO A storage
//
#define EEPROM_BAND0_MODE_A 183 // Band/mode/filter memory per-band - bands indexed from here
#define EEPROM_BAND1_MODE_A 184
#define EEPROM_BAND2_MODE_A 185
#define EEPROM_BAND3_MODE_A 186
#define EEPROM_BAND4_MODE_A 187
#define EEPROM_BAND5_MODE_A 188
#define EEPROM_BAND6_MODE_A 189
#define EEPROM_BAND7_MODE_A 190
#define EEPROM_BAND8_MODE_A 191
#define EEPROM_BAND9_MODE_A 192
#define EEPROM_BAND10_MODE_A 193
#define EEPROM_BAND11_MODE_A 194
#define EEPROM_BAND12_MODE_A 195
#define EEPROM_BAND13_MODE_A 196
#define EEPROM_BAND14_MODE_A 197
#define EEPROM_BAND15_MODE_A 198
#define EEPROM_BAND16_MODE_A 199
#define EEPROM_BAND17_MODE_A 200 // "Floating" General coverage band
//
#define EEPROM_BAND0_FREQ_HIGH_A 201 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_HIGH_A 202
#define EEPROM_BAND2_FREQ_HIGH_A 203
#define EEPROM_BAND3_FREQ_HIGH_A 204
#define EEPROM_BAND4_FREQ_HIGH_A 205
#define EEPROM_BAND5_FREQ_HIGH_A 206
#define EEPROM_BAND6_FREQ_HIGH_A 207
#define EEPROM_BAND7_FREQ_HIGH_A 208
#define EEPROM_BAND8_FREQ_HIGH_A 209
#define EEPROM_BAND9_FREQ_HIGH_A 210
#define EEPROM_BAND10_FREQ_HIGH_A 211
#define EEPROM_BAND11_FREQ_HIGH_A 212
#define EEPROM_BAND12_FREQ_HIGH_A 213
#define EEPROM_BAND13_FREQ_HIGH_A 214
#define EEPROM_BAND14_FREQ_HIGH_A 215
#define EEPROM_BAND15_FREQ_HIGH_A 216
#define EEPROM_BAND16_FREQ_HIGH_A 217
#define EEPROM_BAND17_FREQ_HIGH_A 218 // "Floating" General coverage band
//
#define EEPROM_BAND0_FREQ_LOW_A 219 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_LOW_A 220
#define EEPROM_BAND2_FREQ_LOW_A 221
#define EEPROM_BAND3_FREQ_LOW_A 222
#define EEPROM_BAND4_FREQ_LOW_A 223
#define EEPROM_BAND5_FREQ_LOW_A 224
#define EEPROM_BAND6_FREQ_LOW_A 225
#define EEPROM_BAND7_FREQ_LOW_A 226
#define EEPROM_BAND8_FREQ_LOW_A 227
#define EEPROM_BAND9_FREQ_LOW_A 228
#define EEPROM_BAND10_FREQ_LOW_A 229
#define EEPROM_BAND11_FREQ_LOW_A 230
#define EEPROM_BAND12_FREQ_LOW_A 231
#define EEPROM_BAND13_FREQ_LOW_A 232
#define EEPROM_BAND14_FREQ_LOW_A 233
#define EEPROM_BAND15_FREQ_LOW_A 234
#define EEPROM_BAND16_FREQ_LOW_A 235
#define EEPROM_BAND17_FREQ_LOW_A 236 // "Floating" General coverage band
//
// VFO B storage
//
#define EEPROM_BAND0_MODE_B 237 // Band/mode/filter memory per-band - bands indexed from here
#define EEPROM_BAND1_MODE_B 238
#define EEPROM_BAND2_MODE_B 239
#define EEPROM_BAND3_MODE_B 240
#define EEPROM_BAND4_MODE_B 241
#define EEPROM_BAND5_MODE_B 242
#define EEPROM_BAND6_MODE_B 243
#define EEPROM_BAND7_MODE_B 244
#define EEPROM_BAND8_MODE_B 245
#define EEPROM_BAND9_MODE_B 246
#define EEPROM_BAND10_MODE_B 247
#define EEPROM_BAND11_MODE_B 248
#define EEPROM_BAND12_MODE_B 249
#define EEPROM_BAND13_MODE_B 250
#define EEPROM_BAND14_MODE_B 251
#define EEPROM_BAND15_MODE_B 252
#define EEPROM_BAND16_MODE_B 253
#define EEPROM_BAND17_MODE_B 254 // "Floating" General coverage band
//
//
#define EEPROM_BAND0_FREQ_HIGH_B 255 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_HIGH_B 256
#define EEPROM_BAND2_FREQ_HIGH_B 257
#define EEPROM_BAND3_FREQ_HIGH_B 258
#define EEPROM_BAND4_FREQ_HIGH_B 259
#define EEPROM_BAND5_FREQ_HIGH_B 260
#define EEPROM_BAND6_FREQ_HIGH_B 261
#define EEPROM_BAND7_FREQ_HIGH_B 262
#define EEPROM_BAND8_FREQ_HIGH_B 263
#define EEPROM_BAND9_FREQ_HIGH_B 264
#define EEPROM_BAND10_FREQ_HIGH_B 265
#define EEPROM_BAND11_FREQ_HIGH_B 266
#define EEPROM_BAND12_FREQ_HIGH_B 267
#define EEPROM_BAND13_FREQ_HIGH_B 268
#define EEPROM_BAND14_FREQ_HIGH_B 269
#define EEPROM_BAND15_FREQ_HIGH_B 270
#define EEPROM_BAND16_FREQ_HIGH_B 271
#define EEPROM_BAND17_FREQ_HIGH_B 272 // "Floating" General coverage band
//
//
#define EEPROM_BAND0_FREQ_LOW_B 273 // Per-band frequency, high word - bands indexed from here
#define EEPROM_BAND1_FREQ_LOW_B 274
#define EEPROM_BAND2_FREQ_LOW_B 275
#define EEPROM_BAND3_FREQ_LOW_B 276
#define EEPROM_BAND4_FREQ_LOW_B 277
#define EEPROM_BAND5_FREQ_LOW_B 278
#define EEPROM_BAND6_FREQ_LOW_B 279
#define EEPROM_BAND7_FREQ_LOW_B 280
#define EEPROM_BAND8_FREQ_LOW_B 281
#define EEPROM_BAND9_FREQ_LOW_B 282
#define EEPROM_BAND10_FREQ_LOW_B 283
#define EEPROM_BAND11_FREQ_LOW_B 284
#define EEPROM_BAND12_FREQ_LOW_B 285
#define EEPROM_BAND13_FREQ_LOW_B 286
#define EEPROM_BAND14_FREQ_LOW_B 287
#define EEPROM_BAND15_FREQ_LOW_B 288
#define EEPROM_BAND16_FREQ_LOW_B 289
#define EEPROM_BAND17_FREQ_LOW_B 290 // "Floating" General coverage band
//
#define EEPROM_WATERFALL_SPEED 291 // Spectrum Scope Speed
#define EEPROM_SPECTRUM_SCOPE_NOSIG_ADJUST 292 // adjustment for no-signal conditions of spectrum scope
#define EEPROM_WATERFALL_NOSIG_ADJUST 293 // adjustment for no-signal conditions of waterfall
#define EEPROM_DSP_NOTCH_FFT_NUMTAPS 294 // DSP Notch FFT number of taps
#define EEPROM_SPECTRUM_SIZE 295 // size of waterfall display (and other parameters) - size setting is in lower nybble, upper nybble/byte reserved
#define EEPROM_FFT_WINDOW 296 // FFT Window information (lower nybble currently used - upper nybble reserved)
#define EEPROM_TXRX_SWITCH_AUDIO_MUTE_DELAY 297 // timer used for muting TX audio when keying PTT to suppress "click" or "thump"
#define EEPROM_FLAGS2 298 // Miscellaneous status flag, saved in EEPROM - see variable "flags2"
#define EEPROM_FILTER_DISP_COLOUR 299 // This contains the color of the line under the spectrum/waterfall display
#define EEPROM_TX_IQ_10M_GAIN_BALANCE_TRANS_OFF 300 // IQ Gain balance for AM transmission
#define EEPROM_TX_IQ_10M_PHASE_BALANCE_TRANS_OFF 301 // IQ Gain balance for FM transmission
#define EEPROM_FM_SUBAUDIBLE_TONE_GEN 302 // index for storage of subaudible tone generation
#define EEPROM_FM_TONE_BURST_MODE 303 // tone burst mode
#define EEPROM_FM_SQUELCH_SETTING 304 // FM squelch setting
#define EEPROM_FM_RX_BANDWIDTH 305 // bandwidth setting for FM reception
#define EEPROM_RX_IQ_FM_GAIN_BALANCE 306 // IQ Gain balance for AM reception
#define EEPROM_FM_SUBAUDIBLE_TONE_DET 307 // index for storage of subaudible tone detection
#define EEPROM_KEYBOARD_BEEP_FREQ 308 // keyboard beep frequency (in Hz)
#define EEPROM_BEEP_LOUDNESS 309 // loudness of beep (keyboard, sidetone test)
#define EEPROM_VERSION_MINOR 310 // Storage of current minor version number - used to detect change of firmware
#define EEPROM_DETECTOR_COUPLING_COEFF_160M 311 // Calibration coupling coefficient for FWD/REV power sensor for 160 meters
#define EEPROM_DETECTOR_COUPLING_COEFF_6M 312 // Calibration coupling coefficient for FWD/REV power sensor for 6 meters
#define EEPROM_TUNE_POWER_LEVEL 313
// #define EEPROM_CAT_MODE_ACTIVE 314
#define EEPROM_CAT_XLAT 315
//#define EEPROM_CAT_IN_SANDBOX 316
#define EEPROM_METER_COLOUR_UP 327
#define EEPROM_METER_COLOUR_DOWN 328
#define EEPROM_FILTER_PATH_MAP_BASE 329 //
#define EEPROM_FILTER_PATH_MAP_END (329 + FILTER_MODE_MAX*FILTER_PATH_MEM_MAX) // this is currently 5*5 = 25
//#define EEPROM_SPECTRUM_LIGHT_ENABLE 355
#define EEPROM_MANUAL_NOTCH 356
#define EEPROM_MANUAL_PEAK 357
#define EEPROM_TX_IQ_80M_PHASE_BALANCE_TRANS_OFF 358 // IQ Gain balance for AM reception
#define EEPROM_DISPLAY_DBM 359 // dbm display
#define EEPROM_BASS_GAIN 360 // bass gain lowShelf filter
#define EEPROM_TREBLE_GAIN 361 // treble gain highShelf filter
//#define EEPROM_S_METER 362 // S-Meter configuration
#define EEPROM_TX_FILTER 363 // TX_Filter configuration
//#define EEPROM_TX_BASS_GAIN 364 // TX bass gain lowShelf filter
//#define EEPROM_TX_TREBLE_GAIN 365 // TX treble gain highShelf filter
#define EEPROM_TX_EQ0_GAIN 364 // TX bass EQ filter
#define EEPROM_TX_EQ4_GAIN 365 // TX treble EQ filter
#define EEPROM_SAM_PLL_LOCKING_RANGE 366 //
#define EEPROM_SAM_PLL_STEP_RESPONSE 367 //
#define EEPROM_SAM_PLL_BANDWIDTH 368 //
#define EEPROM_I2C1_SPEED 369 //
#define EEPROM_I2C2_SPEED 370 //
#define EEPROM_SAM_FADE_LEVELER 371
#define EEPROM_LINEOUT_GAIN 372
#define EEPROM_IQ_AUTO_CORRECTION 373 // Receive IQ auto correction ON/OFF
//#define EEPROM_AGC_WDSP_SWITCH 374
#define EEPROM_AGC_WDSP_MODE 375
#define EEPROM_AGC_WDSP_THRESH 376
#define EEPROM_AGC_WDSP_SLOPE 377
#define EEPROM_AGC_WDSP_HANG 378
#define EEPROM_DBM_CALIBRATE 379
#define EEPROM_AGC_WDSP_TAU_DECAY_0 380
#define EEPROM_AGC_WDSP_TAU_HANG_DECAY 381
#define EEPROM_RTC_CALIB 382
#define EEPROM_AGC_WDSP_TAU_DECAY_1 383
#define EEPROM_AGC_WDSP_TAU_DECAY_2 384
#define EEPROM_AGC_WDSP_TAU_DECAY_3 385
#define EEPROM_AGC_WDSP_TAU_DECAY_4 386
#define EEPROM_LOW_POWER_CONFIG 387
#define EEPROM_CW_KEYER_WEIGHT 388
#define EEPROM_DIGI_MODE_CONF 389
#define EEPROM_Scope_TRACE_HL_BW 390
#define EEPROM_Scope_TRACE_HL_BW_BGR 391
#define EEPROM_TScal0_High 392 //callibration data for touchscreen (all data are int32_t divided in two 16bit chunks)
#define EEPROM_TScal0_Low 393
#define EEPROM_TScal1_High 394
#define EEPROM_TScal1_Low 395
#define EEPROM_TScal2_High 396
#define EEPROM_TScal2_Low 397
#define EEPROM_TScal3_High 398
#define EEPROM_TScal3_Low 399
#define EEPROM_TScal4_High 400
#define EEPROM_TScal4_Low 401
#define EEPROM_TScal5_High 402
#define EEPROM_TScal5_Low 403
#define EEPROM_CW_DECODER_ENABLE 404
#define EEPROM_Scope_Graticule_Ypos 405
#define EEPROM_Freq_Display_Font 406
#define EEPROM_NUMBER_OF_ENTRIES 407 // this is the index of the config value which holds the number of used config entries
// , not the value itself (which is in fact EEPROM_FIRST_UNUSED)
#define EEPROM_DSP_MODE_MASK 408
#define EEPROM_ENABLE_PTT_RTS 409
#define EEPROM_CW_DECODER_THRESH 410
#define EEPROM_CW_DECODER_BLOCKSIZE 411
#define EEPROM_SMETER_ALPHAS 412
#define EEPROM_ADJ_TX_IQ_SOMEBANDS 413 // unused, may be reused due to short usage time in its original
#define EEPROM_TX_IQ_20M_GAIN_BALANCE 414
#define EEPROM_TX_IQ_20M_PHASE_BALANCE 415
#define EEPROM_TX_IQ_15M_GAIN_BALANCE 416
#define EEPROM_TX_IQ_15M_PHASE_BALANCE 417
#define EEPROM_TX_IQ_10M_UP_GAIN_BALANCE 418
#define EEPROM_TX_IQ_10M_UP_PHASE_BALANCE 419
#define EEPROM_TX_IQ_20M_GAIN_BALANCE_TRANS_OFF 420
#define EEPROM_TX_IQ_20M_PHASE_BALANCE_TRANS_OFF 421
#define EEPROM_TX_IQ_15M_GAIN_BALANCE_TRANS_OFF 422
#define EEPROM_TX_IQ_15M_PHASE_BALANCE_TRANS_OFF 423
#define EEPROM_TX_IQ_10M_UP_GAIN_BALANCE_TRANS_OFF 424
#define EEPROM_TX_IQ_10M_UP_PHASE_BALANCE_TRANS_OFF 425
#define EEPROM_VSWR_PROTECTION_THRESHOLD 426
#define EEPROM_EXPFLAGS1 427 // Flags for options in Debug/Expert menu - see variable "expflags1"
//#define EEPROM_FIRST_UNUSED 428 // change this if new value ids are introduced, must be correct at any time
#define EEPROM_LO_TX_SUPR0_0 428
#define EEPROM_LO_TX_SUPR0_1 429
#define EEPROM_LO_TX_SUPR0_2 430
#define EEPROM_LO_TX_SUPR0_3 431
#define EEPROM_LO_TX_SUPR0_4 432
#define EEPROM_LO_TX_SUPR0_5 433
#define EEPROM_LO_TX_SUPR0_6 434
#define EEPROM_LO_TX_SUPR0_7 435
#define EEPROM_LO_TX_SUPR0_8 436
#define EEPROM_LO_TX_SUPR0_9 437
#define EEPROM_LO_TX_SUPR0_10 438
#define EEPROM_LO_TX_SUPR0_11 439
#define EEPROM_LO_TX_SUPR0_12 440
#define EEPROM_LO_TX_SUPR1_0 441
#define EEPROM_LO_TX_SUPR1_1 442
#define EEPROM_LO_TX_SUPR1_2 443
#define EEPROM_LO_TX_SUPR1_3 444
#define EEPROM_LO_TX_SUPR1_4 445
#define EEPROM_LO_TX_SUPR1_5 446
#define EEPROM_LO_TX_SUPR1_6 447
#define EEPROM_LO_TX_SUPR1_7 448
#define EEPROM_LO_TX_SUPR1_8 449
#define EEPROM_LO_TX_SUPR1_9 450
#define EEPROM_LO_TX_SUPR1_10 451
#define EEPROM_LO_TX_SUPR1_11 452
#define EEPROM_LO_TX_SUPR1_12 453
#define EEPROM_BOX_COLOUR 454
#define EEPROM_DETECTOR_COUPLING_COEFF_10M 455 // Calibration coupling coefficient for FWD/REV power sensor for 10 meters
#define EEPROM_TX_IQ_6M_GAIN_BALANCE 456
#define EEPROM_TX_IQ_6M_PHASE_BALANCE 457
#define EEPROM_TX_IQ_6M_GAIN_BALANCE_TRANS_OFF 458
#define EEPROM_TX_IQ_6M_PHASE_BALANCE_TRANS_OFF 459
#define EEPROM_TX_IQ_6M_PHASE_BALANCE_TRANS_OFF 459
#define EEPROM_PEAK_IND_TUNE 460 // in 1/4 sec, 0 is OFF
#define EEPROM_XVERTER_OFFSET_TX_HIGH 461 // Secondary frequency by which the display is offset for transverter use, high word
#define EEPROM_XVERTER_OFFSET_TX_LOW 462 // Secondary frequency by which the display is offset for transverter use, low word
#define EEPROM_LO_TX_SUPR0_13 463 // Wild zone
#define EEPROM_LO_TX_SUPR1_13 464 // Wild zone
#define EEPROM_LO_TX_SUPR0_14 465 // 28 MHz Up
#define EEPROM_LO_TX_SUPR1_14 466 // 28 MHz Up
#define EEPROM_TXTLINE_COLOUR 467 // Ticker colour
#define EEPROM_CW_SMOOTH 468 // Smooth of CW signal edges
#define EEPROM_PWR_SCALE_GEN 469 // Power scale for Gen band 5W
#define EEPROM_EXPFLAGS2 470 // Flags for options in the system menu - see variable "expflags2"
#define EEPROM_PWR_SCALE_GEN_FULL 471 // Power scale for Gen band FULL POWER
#define EEPROM_AMBER_BANDCODE 472
#define EEPROM_ANR_N_TAPS 473
#define EEPROM_ANR_DELAY 474
#define EEPROM_ANR_TWO_MU_INT 475
#define EEPROM_ANR_GAMMA_INT 476
#define EEPROM_CW_DECODER_FLAGS 477 // Various flags controlling operation of CW decoder
#define EEPROM_BAND_REGION 478 // store which region the TRX is being used in
#define EEPROM_TX_IQ_160M_GAIN_BALANCE 479 // Advanced I/Q justify
#define EEPROM_TX_IQ_160M_PHASE_BALANCE 480
#define EEPROM_TX_IQ_40M_GAIN_BALANCE 481
#define EEPROM_TX_IQ_40M_PHASE_BALANCE 482
#define EEPROM_TX_IQ_30M_GAIN_BALANCE 483
#define EEPROM_TX_IQ_30M_PHASE_BALANCE 484
#define EEPROM_TX_IQ_17M_GAIN_BALANCE 485
#define EEPROM_TX_IQ_17M_PHASE_BALANCE 486
#define EEPROM_TX_IQ_12M_GAIN_BALANCE 487
#define EEPROM_TX_IQ_12M_PHASE_BALANCE 488
#define EEPROM_TX_IQ_160M_GAIN_BALANCE_TRANS_OFF 489
#define EEPROM_TX_IQ_160M_PHASE_BALANCE_TRANS_OFF 490
#define EEPROM_TX_IQ_40M_GAIN_BALANCE_TRANS_OFF 491
#define EEPROM_TX_IQ_40M_PHASE_BALANCE_TRANS_OFF 492
#define EEPROM_TX_IQ_30M_GAIN_BALANCE_TRANS_OFF 493
#define EEPROM_TX_IQ_30M_PHASE_BALANCE_TRANS_OFF 494
#define EEPROM_TX_IQ_17M_GAIN_BALANCE_TRANS_OFF 495
#define EEPROM_TX_IQ_17M_PHASE_BALANCE_TRANS_OFF 496
#define EEPROM_TX_IQ_12M_GAIN_BALANCE_TRANS_OFF 497
#define EEPROM_TX_IQ_12M_PHASE_BALANCE_TRANS_OFF 498
#define EEPROM_TX_REVERB_GAIN 499
#define EEPROM_TX_REVERB_DELAY 500
#define EEPROM_TX_EQ1_GAIN 501
#define EEPROM_TX_EQ2_GAIN 502
#define EEPROM_TX_EQ3_GAIN 503
#define EEPROM_IQ_FREQ_DELTA 504
#define EEPROM_EXPFLAGS3 505 // Flags for options in the system menu - see variable "expflags3"
#define EEPROM_INPUT_STATE 506 // State of input group - TRX Amber etc.
//#define EEPROM_CQ_COLOUR 507
#define EEPROM_FIRST_UNUSED 507 // change this if new value ids are introduced, must be correct at any time
#define MAX_VAR_ADDR (EEPROM_FIRST_UNUSED - 1) // Max 511
// Note: EEPROM addresses up to 383 are currently defined. If this value is passed you
// need to modify virtual EEPROM routines otherwise system may crash
//#define EEPROM_KEYER_MEMORY_ADDRESS 0x1000
#define EEPROM_KEYER_MEMORY_ADDRESS 0x3C30
#define EEPROM_MEMS_MEMORY_ADDRESS 0x3F5C
#define EEPROM_XVTR_MEMORY_ADDRESS 0x535D
#endif /* DRIVERS_UI_UI_CONFIGURATION_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,321 @@
/* -*- 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 **
************************************************************************************/
#ifndef __UI_DRIVER_H
#define __UI_DRIVER_H
#include "uhsdr_board.h"
// used by UpdateFrequency* family of functions
enum UpdateFrequencyMode_t
{
UFM_AUTOMATIC = 0,
UFM_LARGE,
UFM_SMALL_RX,
UFM_SMALL_TX,
UFM_SECONDARY
};
// SI570 startup value (receive freq * 4)
//#define STARTUP_FREQ 112000000
#define STARTUP_FREQ 56000000
#define T_STEP_1HZ 1
#define T_STEP_5HZ 5
#define T_STEP_10HZ 10
#define T_STEP_50HZ 50
#define T_STEP_100HZ 100
#define T_STEP_500HZ 500
#define T_STEP_1KHZ 1000
#define T_STEP_5KHZ 5000
#define T_STEP_9KHZ 9000
#define T_STEP_10KHZ 10000
#define T_STEP_100KHZ 100000
#define T_STEP_1MHZ 1000000 // Used for transverter offset adjust
#define T_STEP_10MHZ 10000000 // Used for transverter offset adjust
//
enum
{
T_STEP_1HZ_IDX = 0,
T_STEP_5HZ_IDX,
T_STEP_10HZ_IDX,
T_STEP_50HZ_IDX,
T_STEP_100HZ_IDX,
T_STEP_500HZ_IDX,
T_STEP_1KHZ_IDX,
T_STEP_5KHZ_IDX,
T_STEP_9KHZ_IDX,
T_STEP_10KHZ_IDX,
T_STEP_100KHZ_IDX,
T_STEP_1MHZ_IDX,
T_STEP_10MHZ_IDX,
T_STEP_MAX_STEPS
};
//#define MAX_STEPS 6
// S meter
#define S_METER_V_POS 55
#define S_METER_SIZE 9
#define S_VERTI_SIZE 10
#define S_LEFT_SHIFT 20
#define S_BLOCK_GAP 2
#define S_COLOR_INCR 1
#define S_HEIGHT_INCR 12
// Button Definitions
#define BUTTON_NONE 0
#define BUTTON_PRESS_DEBOUNCE 75 // time to debounce normal button press
#define BUTTON_HOLD_TIME 1000 // time of press-and-hold
#define AUTO_BLINK_TIME 200000
#define DEBOUNCE_TIME_MAX 50000 // ceiling time of debounce counter to prevent overflow
typedef struct KeypadState
{
// Actual time the button is pressed
ulong debounce_time;
// ID of button as GPIO bit
ulong button_id;
// Flag to indicate click event
bool button_pressed;
// Flag to indicate release event
bool button_released;
// Flag to indicate under process
bool button_processed;
// Flag to indicate that the button had been continued to be pressed during debounce
bool button_just_pressed;
// Flag to indicate that debounce check was complete
bool debounce_check_complete;
// Flag to indicate a "press-and-hold" condition
bool press_hold;
uchar dummy;
} KeypadState;
#define PRESS_HOLD_RELEASE_DELAY_TIME 10 // time after button being released before resetting press-and-hold flag
#define S_METER_MAX 34
//
// --------------------------------------------------------------------------
// Controls positions and some related colours
// --------------------
//
#define PWR_DAMPENING_FACTOR 0.10 // dampening/averaging factor (e.g. amount of "new" reading each time) - for numerical power reading ONLY
//
// Coupling adjustment limits
//
#define SWR_COUPLING_MIN 50
#define SWR_COUPLING_MAX 150
#define SWR_COUPLING_DEFAULT 100
//
//
//
#define SWR_MIN_CALC_POWER 0.25 // Minimum forward power required for SWR calculation
//
//
#define VSWR_DAMPENING_FACTOR 0.25 // dampening/averaging factor (e.g. amount of "new" reading each time) - for VSWR meter indication ONLY
//
#define MAX_VSWR_MOD_VALUE 75 // Maximum A/D value from FWD/REV power sensors before warning is displayed about not having done resistor modification
//
// Volt (DC power) meter
//
#define POWER_SAMPLES_CNT 32
//
//
#define VOLTMETER_ADC_FULL_SCALE 4095
//
//
// Power supply
typedef struct PowerMeter
{
uint32_t pwr_aver;
uint32_t p_curr;
uint32_t voltage;
bool undervoltage_detected;
} PowerMeter;
typedef enum
{
SPECTRUM_BLANK = 0,
SPECTRUM_WATERFALL = 1,
SPECTRUM_SCOPE = 2,
SPECTRUM_DUAL = 3
} SpectrumMode_t;
typedef struct
{
uint8_t dmod_mode;
uint8_t digital_mode;
} ui_driver_mode_t;
//
// --------------------------------------------------------------------------
// Exports
void UiDriver_Init(void);
void UiDriver_TaskHandler_MainTasks(void);
void UiDriver_CreateTemperatureDisplay(void);
void UiDriver_UpdateFrequency(bool force_update, enum UpdateFrequencyMode_t mode);
void UiDriver_FrequencyUpdateLOandDisplay(bool full_update);
void UiDriver_RefreshEncoderDisplay(void);
void UiDriver_DrawFButtonLabel(uint8_t button_num, const char* label, uint32_t label_color) ;
void UiDriver_DisplayFreqStepSize(void);
void UiDriver_DisplayDemodMode(void);
void UiDriver_LcdBlankingStartTimer(void);
void UiDriver_SpectrumChangeLayoutParameters(void);
void UiDriver_DebugInfo_DisplayEnable(bool enable);
void UiDriver_ChangeTuningStep(uchar is_up);
void UiDriver_UpdateDisplayAfterParamChange(void);
void UiDriver_UpdateDemodSpecificDisplayAfterParamChange(void);
void UiDriver_SetDemodMode(uint8_t new_mode);
void UiDriver_StartUpScreenInit();
void UiDriver_StartUpScreenFinish();
void UiDriver_DoCrossCheck(int16_t cross[]);
void UiAction_ToggleVfoAB(void);
void UiDriver_SetSplitMode(bool mode_active);
void UiDriver_StartupScreen_LogIfProblem(bool isError, const char* txt);
void UiDriver_BacklightDimHandler(void);
void UiDriver_TextMsgPutChar(char ch);
void UiDriver_TextMsgPutSign(const char *s);
void UiDriver_TextMsgDisplay(void);
void UiDriver_TextMsgClear(void);
void UiDriver_DisplayFButton_F1MenuExit(void);
void UiDriver_SetSpectrumMode(SpectrumMode_t mode);
SpectrumMode_t UiDriver_GetSpectrumMode(void);
//some exports for layout definitions
void UiAction_ChangeLowerMeterUp(void);
void UiAction_ToggleWaterfallScopeDisplay(void);
void UiAction_ChangeSpectrumSize(void);
void UiAction_ChangeSpectrumZoomLevelDown(void);
void UiAction_ChangeSpectrumZoomLevelUp(void);
void UiAction_ZoomResetToOne(void);
void UiAction_CheckSpectrumTouchActions(void);
void UiAction_ChangeFrequencyToNextKhz(void);
void UiAction_ChangeDemodMode(void);
void UiAction_ChangeDemodModeToAlternativeMode(void);
void UiAction_ChangePowerLevel(void);
void UiAction_ChangeAudioSource(void);
void UiAction_ChangeBandDownOrUp(void);
void UiAction_ChangeBandUpOrDown(void);
void UiAction_ChangeDigitalMode(void);
void UiAction_ChangeDynamicTuning(void);
void UiAction_ChangeRXInputStateDown(void);
void UiAction_ChangeRXInputStateUp(void);
void UiAction_ChangeDebugInfoDisplay(void);
void UiAction_ChangeRfModPresence(void);
void UiAction_ChangeVhfUhfModPresence(void);
void UiAction_ChangeFrequencyByTouch(void);
void Codec_RestartI2S(void);
uint32_t UiDriver_GetActiveDSPFunctions(void);
void UiDriver_UpdateDSPmode(uint8_t new_dsp_mode);
bool UiDriver_CheckTouchRegion(const UiArea_t* tr_p);
void UiDriver_Power2String(char* txt, size_t txt_len,uint32_t power_mW);
uint32_t UiDriver_GetNBColor(void);
void UiDriver_InitBandSet(void);
void UiDriver_SelectBandMemory(uint16_t vfo_sel, uint8_t new_band_index);
void UiDriver_Callback_AudioISR(void);
void UiDriver_ToggleWideSpectrum(void);
void UiDriver_ClearMemoryLabel(void);
void UiDriver_DisplayMemoryLabel(void);
void UiDriver_RIT_Reset(void);
void UiDriver_CreateMainFreqDisplay(bool all_digits);
void UiDriver_StoreBwData(void);
void UiDriver_CreateFunctionButtons(bool full_repaint);
void UiDriver_RefreshPowerLevel(const BandInfo* band, uint8_t power_level);
bool UiDriver_NotLockedBand(uint32_t idx);
// Items that are timed using ts.sysclock (operates at 100 Hz)
//
#define DSP_STARTUP_DELAY 350 // Delay, in 100ths of seconds, after startup, before allowing DSP NR or Notch to be enabled.
#define DSP_REENABLE_DELAY 13 // Delay, in 100ths of seconds, after return to RX before allowing DSP NR or Notch to be re-enabled
#define DSP_BAND_CHANGE_DELAY 100 // Delay, in 100ths of a second, after changing bands before restoring DSP NR
//
#define TUNING_LARGE_STEP_MUTING_TIME_DSP_ON 5 // Delay, in 100ths of a second, for audio to be muted after a "large" frequency step (to avoid audio "POP") when DSP on
#define TUNING_LARGE_STEP_MUTING_TIME_DSP_OFF 3 // Delay, in 100ths of a second, for audio to be muted after a "large" frequency step (to avoid audio "POP") when DSP on
#define RX_MUTE_START_DELAY (DSP_STARTUP_DELAY + TUNING_LARGE_STEP_MUTING_TIME_DSP_ON) // establish earliest time after system start before audio muting will work
//
#define THREAD_TIMING_DELAY 1 // Delay, in 100ths of a second, between thread tasks
//
#define TXRX_SWITCH_AUDIO_MUTE_DELAY_DEFAULT 1 // Default, in 100ths of a second, that audio will be muted after PTT (key-up/key-down) to prevent "clicks" and "clunks"
#define TXRX_SWITCH_AUDIO_MUTE_DELAY_MAX 25 // Maximum delay, in 100ths of a second, that audio will be muted after PTT (key-up/key-down) to prevent "clicks" and "clunks"
// UI Driver State machine definitions
enum
{
STATE_S_METER = 0,
STATE_HANDLE_POWERSUPPLY,
STATE_LO_TEMPERATURE,
STATE_TASK_CHECK,
STATE_UPDATE_FREQUENCY,
STATE_PROCESS_KEYBOARD,
STATE_DISPLAY_SAM_CARRIER,
STATE_MAX
};
//
// Used for press-and-hold "temporary" step size adjust
//
#define STEP_PRESS_OFF 0
#define STEP_PRESS_MINUS 1
#define STEP_PRESS_PLUS 2
//
// ------------------------------------------------
// Keypad state
extern __IO KeypadState ks;
// ------------------------------------------------
// Power supply meter
extern PowerMeter pwmt;
// ------------------------------------------------
extern const ulong tune_steps[T_STEP_MAX_STEPS];
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,82 @@
/* -*- 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: ui_vkeybrd.h **
** Description: Virtual keyboard definitions header file **
** Licence: GNU GPLv3 **
** Author: Slawomir Balon/SP9BSL **
************************************************************************************/
#ifndef UI_UI_VKEYBRD_H_
#define UI_UI_VKEYBRD_H_
typedef uint8_t (*VKeyStateFunc)(uint8_t KeyNum, uint32_t param);
typedef void (*TouchFunc)(uint8_t KeyNum, uint32_t param);
typedef void (*VKeyRedrawFunc)(void);
typedef struct
{
char KeyText[16];
uint8_t SizeX; //multiply of normal key size, 0=normal size defined by VKeypad's KeyWidth
uint8_t SizeY; //multiply of normal key size, 0=normal size defined by VKeypad's KeyHeight
VKeyStateFunc KeyWarning; //if function is present, this key will be marked with warning if result of function is 1
uint16_t TextColor; //Color Of Key Text when key is not pressed
uint16_t PressedTextColor; //Color Of Key Text when key is pressed
TouchFunc ShortFnc; //called function for short press
uint32_t ShortPar; //short press function calling parameter
TouchFunc LongFnc; //called function for short press
uint32_t LongPar; //long press function calling parameter
uint8_t KeyFont; //font number
} VKey;
typedef struct
{
uint8_t NumberOfKeys; //Number of keys in keyborad (see UiVk_MaxKeyCount and increase if more wanted)
uint8_t Rows; //Numer of rows
uint8_t Columns; //Numer of columns
uint16_t KeyWidth; //Width of single key
uint16_t KeyHeight; //Height of single key
uint8_t KeySpacing; //gap between keys
uint8_t Backgr_Wnlarge; //background of keyboard width enlarge
uint8_t Backgr_Hnlarge; //background of keyboard width enlarge
const VKey* Keys; //pointer to keyboard data
uint8_t VKeyGroupMode; //type of key press: see Vkey_Group_
VKeyStateFunc VKeyStateCallBack; //pointer to callback function which controls the displayed state of the button
uint16_t YtopMargin; //size of additional top margin between top edge and first key
VKeyRedrawFunc RedrawFunct; //pointer to callback function for redraw
} VKeypad;
#define UiVk_MaxKeyCount 24
#define Vbtn_State_Normal 0
#define Vbtn_State_Selected 1
#define Vbtn_State_Disabled 2
#define Vbtn_State_Pressed 8
enum Vkey_Group_ {Vkey_Group_OneAllowed=0, Vkey_Group_MultipleAllowed};
//void UiVk_RedrawDSPVirtualKeys();
bool UiVk_Process_VirtualKeypad(bool LongPress);
void UiVk_Redraw(void);
void UiVk_DSPVirtualKeys(void);
void UiVk_ModeVirtualKeys(void);
void UiVk_RedrawModeVirtualKeys(void);
//void UiVk_RedrawBndSelVirtualKeys();
void UiVk_BndSelVirtualKeys(void);
//void UiVk_RedrawBndFreqSetVirtualKeys();
void UiVk_BndFreqSetVirtualKeys(void);
//void UiVk_RedrawModSelVirtualKeys();
void UiVk_ModSelVirtualKeys(void);
#endif /* UI_UI_VKEYBRD_H_ */