288 lines
10 KiB
C
288 lines
10 KiB
C
/* -*- 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
|