kopia lustrzana https://github.com/ArjanteMarvelde/uSDR-pico
v1.5
rodzic
ee39455791
commit
493756488a
Plik binarny nie jest wyświetlany.
75
dsp.c
75
dsp.c
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "dsp.h"
|
||||
|
||||
|
||||
/*
|
||||
* DAC_RANGE defines PWM cycle, determining DAC resolution and PWM frequency.
|
||||
* DAC resolution = Vcc / DAC_RANGE
|
||||
|
@ -66,10 +67,48 @@
|
|||
* AGC reference level is log2(64) = 6, where 64 is the MSB of half DAC_RANGE
|
||||
* 1/AGC_DECAY and 1/AGC_ATTACK are multipliers before agc_gain value integrator
|
||||
* These values should ultimately be set by the HMI.
|
||||
* The time it takes to effect in a gain change is the ( (Set time)/(signal delta) ) / samplerate
|
||||
* So when delta is 1, and attack is 64, the time is 64/15625 = 4msec (fast attack)
|
||||
* The decay time is about 100x this value
|
||||
* Slow attack would be about 4096
|
||||
*/
|
||||
#define AGC_REF 6
|
||||
#define AGC_DECAY 1024
|
||||
#define AGC_ATTACK 128
|
||||
#define AGC_DECAY 8192
|
||||
#define AGC_FAST 64
|
||||
#define AGC_SLOW 4096
|
||||
#define AGC_OFF 65534
|
||||
volatile uint16_t agc_decay = AGC_OFF;
|
||||
volatile uint16_t agc_attack = AGC_OFF;
|
||||
void dsp_setagc(int agc)
|
||||
{
|
||||
switch(agc)
|
||||
{
|
||||
case 1: //SLOW, for values see hmi.c
|
||||
agc_attack = AGC_SLOW;
|
||||
agc_decay = AGC_DECAY;
|
||||
break;
|
||||
case 2: //FAST
|
||||
agc_attack = AGC_FAST;
|
||||
agc_decay = AGC_DECAY;
|
||||
break;
|
||||
default: //OFF
|
||||
agc_attack = AGC_OFF;
|
||||
agc_decay = AGC_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MODE is modulation/demodulation
|
||||
* This setting steers the signal processing branch chosen
|
||||
*/
|
||||
volatile uint16_t dsp_mode; // For values see hmi.c
|
||||
void dsp_setmode(int mode)
|
||||
{
|
||||
dsp_mode = (uint16_t)mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Low pass filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/)
|
||||
|
@ -88,6 +127,7 @@ volatile uint32_t fifo_overrun, fifo_rx, fifo_tx, fifo_xx, fifo_incnt;
|
|||
volatile bool tx_enabled;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Some macro's
|
||||
* See Alpha Max plus Beta Min algorithm for MAG (vector length)
|
||||
|
@ -203,7 +243,9 @@ bool rx(void)
|
|||
|
||||
|
||||
/*** DEMODULATION ***/
|
||||
|
||||
switch(dsp_mode)
|
||||
{
|
||||
case 0: //USB
|
||||
/*
|
||||
* USB demodulate: I[7] - Qh,
|
||||
* Qh is Classic Hilbert transform 15 taps, 12 bits (see Iowa Hills calculator)
|
||||
|
@ -211,13 +253,26 @@ bool rx(void)
|
|||
q_accu = (q_s[0]-q_s[14])*315L + (q_s[2]-q_s[12])*440L + (q_s[4]-q_s[10])*734L + (q_s[6]-q_s[ 8])*2202L;
|
||||
qh = q_accu >> 12;
|
||||
a_sample = i_s[7] - qh;
|
||||
|
||||
break;
|
||||
case 1: //LSB
|
||||
/*
|
||||
* USB demodulate: I[7] - Qh,
|
||||
* Qh is Classic Hilbert transform 15 taps, 12 bits (see Iowa Hills calculator)
|
||||
*/
|
||||
q_accu = (q_s[0]-q_s[14])*315L + (q_s[2]-q_s[12])*440L + (q_s[4]-q_s[10])*734L + (q_s[6]-q_s[ 8])*2202L;
|
||||
qh = q_accu >> 12;
|
||||
a_sample = i_s[7] + qh;
|
||||
break;
|
||||
case 2: //AM
|
||||
/*
|
||||
* AM demodulate: sqrt(sqr(i)+sqr(q))
|
||||
* Approximated with MAG(i,q)
|
||||
*/
|
||||
// a_sample = MAG(i_s[14], q_s[14]);
|
||||
|
||||
a_sample = MAG(i_s[14], q_s[14]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*** AUDIO GENERATION ***/
|
||||
/*
|
||||
|
@ -231,14 +286,14 @@ bool rx(void)
|
|||
if (i&0x000c) {k+=2; i>>=2;}
|
||||
if (i&0x0002) {k+=1;}
|
||||
agc_accu += (k - AGC_REF); // Add difference with target to integrator (Acc += Xn - R)
|
||||
if (agc_accu > AGC_ATTACK) // Attack time, gain correction in case of high level
|
||||
if (agc_accu > agc_attack) // Attack time, gain correction in case of high level
|
||||
{
|
||||
agc_gain--; // Decrease gain
|
||||
agc_accu -= AGC_ATTACK; // Reset integrator
|
||||
} else if (agc_accu < -(AGC_DECAY)) // Decay time, gain correction in case of low level
|
||||
agc_accu -= agc_attack; // Reset integrator
|
||||
} else if (agc_accu < -(agc_decay)) // Decay time, gain correction in case of low level
|
||||
{
|
||||
agc_gain++; // Increase gain
|
||||
agc_accu += AGC_DECAY; // Reset integrator
|
||||
agc_accu += agc_decay; // Reset integrator
|
||||
}
|
||||
|
||||
|
||||
|
|
7
dsp.h
7
dsp.h
|
@ -13,7 +13,14 @@
|
|||
#include "hardware/adc.h"
|
||||
#include "hardware/pwm.h"
|
||||
|
||||
|
||||
void dsp_setagc(int agc);
|
||||
void dsp_setmode(int mode);
|
||||
|
||||
extern volatile bool tx_enabled;
|
||||
#define DSP_SETPTT(on) tx_enabled = (on)
|
||||
|
||||
|
||||
void dsp_init();
|
||||
|
||||
|
||||
|
|
209
hmi.c
209
hmi.c
|
@ -51,36 +51,36 @@
|
|||
#define GP_MASK_IN ((1<<GP_ENC_A)|(1<<GP_ENC_B)|(1<<GP_AUX_0)|(1<<GP_AUX_1)|(1<<GP_AUX_2)|(1<<GP_AUX_3)|(1<<GP_PTT))
|
||||
|
||||
/*
|
||||
* Events: GPIO_IRQ_LEVEL_LOW, GPIO_IRQ_LEVEL_HIGH, GPIO_IRQ_EDGE_FALL, GPIO_IRQ_EDGE_RISE
|
||||
* Event flags
|
||||
*/
|
||||
#define GPIO_IRQ_ALL (GPIO_IRQ_LEVEL_LOW|GPIO_IRQ_LEVEL_HIGH|GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE)
|
||||
#define GPIO_IRQ_EDGE_ALL (GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE)
|
||||
|
||||
/*
|
||||
* Display layout: +----------------+
|
||||
* |USB 14074.0 920| --> USB mode, 14074.0 kHz, S9+20dB
|
||||
* |Tune Att Fast| --> Menu:Tune, Attenuator, Fast AGC
|
||||
* Display layout:
|
||||
* +----------------+
|
||||
* LEFT and RIGHT buttons (or encoder) are used to navigate sub-menus such as {tune,mode,agc,pre}.
|
||||
* ENTER is used to get into the sub-menu.
|
||||
* ENTER is used again to exit and accept changes or ESCAPE to exit without changes.
|
||||
* |USB 14074.0 R920| --> mode=USB, freq=14074.0kHz, state=Rx,S9+20dB
|
||||
* | Fast -10dB| --> ..., AGC=Fast, Pre=-10dB
|
||||
* +----------------+
|
||||
* In this HMI state only tuning is possible,
|
||||
* using Left/Right for digit and ENC for value, Enter to commit change.
|
||||
* Press ESC to enter the submenu states (there is only one sub menu level):
|
||||
*
|
||||
* When entered in a submenu:
|
||||
* Menu Values Encoder Enter Escape Left Right
|
||||
* Submenu Values ENC Enter Escape Left Right
|
||||
* -------------------------------------------------------------------------------------
|
||||
* Mode USB, LSB, AM, CW <value> Accept Exit <value> <value>
|
||||
* Tune Frequency (digit) <value> Accept Exit <=dig dig=>
|
||||
* AGC Fast, Slow, Off <value> Accept Exit <value> <value>
|
||||
* Pre +20dB, 0, -20dB <value> Accept Exit <value> <value>
|
||||
* Mode USB, LSB, AM, CW change commit exit prev next
|
||||
* AGC Fast, Slow, Off change commit exit prev next
|
||||
* Pre +10dB, 0, -10dB, -20dB change commit exit prev next
|
||||
*
|
||||
* --will be extended--
|
||||
*/
|
||||
|
||||
/* State definitions */
|
||||
#define HMI_S_MENU 0
|
||||
#define HMI_S_TUNE 1
|
||||
#define HMI_S_MODE 2
|
||||
#define HMI_S_AGC 3
|
||||
#define HMI_S_PRE 4
|
||||
#define HMI_NSTATES 5
|
||||
#define HMI_S_TUNE 0
|
||||
#define HMI_S_MODE 1
|
||||
#define HMI_S_AGC 2
|
||||
#define HMI_S_PRE 3
|
||||
#define HMI_NSTATES 4
|
||||
|
||||
/* Event definitions */
|
||||
#define HMI_E_NOEVENT 0
|
||||
|
@ -97,20 +97,25 @@
|
|||
/* Sub menu option string sets */
|
||||
#define HMI_NMODE 4
|
||||
#define HMI_NAGC 3
|
||||
#define HMI_NPRE 3
|
||||
char hmi_o_menu[HMI_NSTATES][8] = {"Menu","Tune","Mode","AGC ","Pre "}; // Selected by hmi_state
|
||||
char hmi_o_mode[HMI_NMODE][8] = {"USB", "LSB", "AM ", "CW "}; // Selected by hmi_option/hmi_mode
|
||||
char hmi_o_agc [HMI_NAGC][8] = {"NoGC", "Slow", "Fast"}; // Selected by hmi_option/hmi_agc
|
||||
char hmi_o_pre [HMI_NPRE][8] = {"Off", "Amp", "Att"}; // Selected by hmi_option/hmi_pre
|
||||
#define HMI_NPRE 4
|
||||
char hmi_o_menu[HMI_NSTATES][8] = {"Tune","Mode","AGC ","Pre "}; // Indexed by hmi_state
|
||||
char hmi_o_mode[HMI_NMODE][8] = {"USB", "LSB", "AM ", "CW "}; // Indexed by hmi_sub[HMI_S_MODE]
|
||||
char hmi_o_agc [HMI_NAGC][8] = {"NoGC", "Slow", "Fast"}; // Indexed by hmi_sub[HMI_S_AGC]
|
||||
char hmi_o_pre [HMI_NPRE][8] = {"-20dB", "-10dB", "0dB", "+10dB"}; // Indexed by hmi_sub[HMI_S_PRE]
|
||||
|
||||
uint8_t hmi_state, hmi_option; // Current state and option selection
|
||||
uint8_t hmi_sub[HMI_NSTATES] = {4,0,0,0}; // Stored option selection per state
|
||||
|
||||
uint8_t hmi_state, hmi_option; // Current state and option
|
||||
uint8_t hmi_sub[HMI_NSTATES] = {0,4,0,0,0}; // Stored option per state
|
||||
uint32_t hmi_freq; // Frequency from Tune state
|
||||
uint32_t hmi_step[6] = {10000000, 1000000, 100000, 10000, 1000, 100}; // Frequency digit increments
|
||||
#define HMI_MAXFREQ 30000000
|
||||
#define HMI_MINFREQ 100
|
||||
#define HMI_MULFREQ 1 // Factor between HMI and actual frequency
|
||||
// Set to 2 for certain types of mixer
|
||||
|
||||
/*
|
||||
* Some macros
|
||||
*/
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) ((x)<(y)?(x):(y)) // Get min value
|
||||
#endif
|
||||
|
@ -119,107 +124,118 @@ uint32_t hmi_step[6] = {10000000, 1000000, 100000, 10000, 1000, 100}; // Frequen
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Finite State Machine,
|
||||
* HMI State Machine,
|
||||
* Handle event according to current state
|
||||
* Code needs to be optimized
|
||||
*/
|
||||
void hmi_handler(uint8_t event)
|
||||
{
|
||||
switch(hmi_state)
|
||||
/* Special case for TUNE state */
|
||||
if (hmi_state == HMI_S_TUNE)
|
||||
{
|
||||
case HMI_S_MENU:
|
||||
if ((event==HMI_E_INCREMENT)||(event==HMI_E_RIGHT))
|
||||
hmi_option = (hmi_option<HMI_NSTATES-1)?hmi_option+1:HMI_NSTATES-1;
|
||||
if ((event==HMI_E_DECREMENT)||(event==HMI_E_LEFT))
|
||||
hmi_option = (hmi_option>1)?hmi_option-1:0;
|
||||
if (event==HMI_E_ENTER)
|
||||
if (event==HMI_E_ENTER) // Commit current value
|
||||
{
|
||||
hmi_state = hmi_option; // Enter new submenu
|
||||
hmi_option = hmi_sub[hmi_state]; // Restore option
|
||||
}
|
||||
break;
|
||||
case HMI_S_TUNE:
|
||||
if (event==HMI_E_ENTER)
|
||||
{
|
||||
hmi_sub[hmi_state] = hmi_option; // Store option
|
||||
SI_SETFREQ(0, HMI_MULFREQ*hmi_freq); // Commit frequency
|
||||
}
|
||||
if (event==HMI_E_ESCAPE)
|
||||
if (event==HMI_E_ESCAPE) // Enter submenus
|
||||
{
|
||||
hmi_sub[hmi_state] = hmi_option; // Store option
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
hmi_sub[hmi_state] = hmi_option; // Store selection (i.e. digit)
|
||||
hmi_state = HMI_S_MODE; // Should remember last one
|
||||
hmi_option = hmi_sub[hmi_state]; // Restore selection of new state
|
||||
}
|
||||
if (event==HMI_E_INCREMENT)
|
||||
{
|
||||
hmi_freq+= hmi_step[hmi_option];
|
||||
hmi_freq = MIN(hmi_freq , HMI_MAXFREQ);
|
||||
if (hmi_freq < (HMI_MAXFREQ - hmi_step[hmi_option])) // Boundary check
|
||||
hmi_freq += hmi_step[hmi_option]; // Increment selected digit
|
||||
}
|
||||
if (event==HMI_E_DECREMENT)
|
||||
hmi_freq = (hmi_freq>hmi_step[hmi_option]+HMI_MINFREQ)?hmi_freq-hmi_step[hmi_option]:HMI_MINFREQ;
|
||||
{
|
||||
if (hmi_freq > (hmi_step[hmi_option] + HMI_MINFREQ)) // Boundary check
|
||||
hmi_freq -= hmi_step[hmi_option]; // Decrement selected digit
|
||||
}
|
||||
if (event==HMI_E_RIGHT)
|
||||
hmi_option = (hmi_option<6)?hmi_option+1:6;
|
||||
{
|
||||
hmi_option = (hmi_option<6)?hmi_option+1:6; // Digit to the right
|
||||
}
|
||||
if (event==HMI_E_LEFT)
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0;
|
||||
break;
|
||||
{
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0; // Digit to the left
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Submenu states */
|
||||
switch(hmi_state)
|
||||
{
|
||||
case HMI_S_MODE:
|
||||
if (event==HMI_E_ENTER)
|
||||
{
|
||||
// Set Mode
|
||||
hmi_sub[hmi_state] = hmi_option; // Store option
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
dsp_setmode(hmi_option); // Commit Mode
|
||||
hmi_sub[hmi_state] = hmi_option; // Store selected option
|
||||
}
|
||||
if (event==HMI_E_ESCAPE)
|
||||
if (event==HMI_E_INCREMENT)
|
||||
{
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
}
|
||||
if ((event==HMI_E_INCREMENT)||(event==HMI_E_RIGHT))
|
||||
hmi_option = (hmi_option<HMI_NMODE-1)?hmi_option+1:HMI_NMODE-1;
|
||||
if ((event==HMI_E_DECREMENT)||(event==HMI_E_LEFT))
|
||||
}
|
||||
if (event==HMI_E_DECREMENT)
|
||||
{
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0;
|
||||
}
|
||||
|
||||
break;
|
||||
case HMI_S_AGC:
|
||||
if (event==HMI_E_ENTER)
|
||||
{
|
||||
// Set AGC
|
||||
hmi_sub[hmi_state] = hmi_option; // Store option
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
dsp_setagc(hmi_option); // Commit AGC
|
||||
hmi_sub[hmi_state] = hmi_option; // Store selected option
|
||||
}
|
||||
if (event==HMI_E_ESCAPE)
|
||||
if (event==HMI_E_INCREMENT)
|
||||
{
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
}
|
||||
if ((event==HMI_E_INCREMENT)||(event==HMI_E_RIGHT))
|
||||
hmi_option = (hmi_option<HMI_NAGC-1)?hmi_option+1:HMI_NAGC-1;
|
||||
if ((event==HMI_E_DECREMENT)||(event==HMI_E_LEFT))
|
||||
}
|
||||
if (event==HMI_E_DECREMENT)
|
||||
{
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0;
|
||||
}
|
||||
break;
|
||||
case HMI_S_PRE:
|
||||
if (event==HMI_E_ENTER)
|
||||
{
|
||||
// Set Preamp
|
||||
hmi_sub[hmi_state] = hmi_option; // Store option
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
// Set PRE
|
||||
hmi_sub[hmi_state] = hmi_option; // Store selected option
|
||||
}
|
||||
if (event==HMI_E_INCREMENT)
|
||||
{
|
||||
hmi_option = (hmi_option<HMI_NPRE-1)?hmi_option+1:HMI_NPRE-1;
|
||||
}
|
||||
if (event==HMI_E_DECREMENT)
|
||||
{
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* General actions for submenus */
|
||||
if (event==HMI_E_ESCAPE)
|
||||
{
|
||||
hmi_option = hmi_state;
|
||||
hmi_state = HMI_S_MENU; // Leave submenu
|
||||
hmi_state = HMI_S_TUNE; // Leave submenus
|
||||
hmi_option = hmi_sub[hmi_state]; // Restore selection of new state
|
||||
}
|
||||
if ((event==HMI_E_INCREMENT)||(event==HMI_E_RIGHT))
|
||||
hmi_option = (hmi_option<HMI_NPRE-1)?hmi_option+1:HMI_NPRE-1;
|
||||
if ((event==HMI_E_DECREMENT)||(event==HMI_E_LEFT))
|
||||
hmi_option = (hmi_option>0)?hmi_option-1:0;
|
||||
break;
|
||||
if (event==HMI_E_RIGHT)
|
||||
{
|
||||
hmi_state = (hmi_state<HMI_NSTATES-1)?(hmi_state+1):1; // Change submenu
|
||||
hmi_option = hmi_sub[hmi_state]; // Restore selection of new state
|
||||
}
|
||||
if (event==HMI_E_LEFT)
|
||||
{
|
||||
hmi_state = (hmi_state>1)?(hmi_state-1):HMI_NSTATES-1; // Change submenu
|
||||
hmi_option = hmi_sub[hmi_state]; // Restore selection of new state
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO IRQ callback routine
|
||||
* Sets the detected event and invokes the HMI state machine
|
||||
*/
|
||||
void hmi_callback(uint gpio, uint32_t events)
|
||||
{
|
||||
|
@ -249,15 +265,15 @@ void hmi_callback(uint gpio, uint32_t events)
|
|||
break;
|
||||
case GP_PTT: // PTT
|
||||
if (events&GPIO_IRQ_EDGE_FALL)
|
||||
tx_enabled = true;
|
||||
DSP_SETPTT(true);
|
||||
else
|
||||
tx_enabled = false;
|
||||
DSP_SETPTT(false);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
hmi_handler(evt);
|
||||
hmi_handler(evt); // Invoke state machine
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -304,38 +320,37 @@ void hmi_init(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* Redraw the LCD, representing current state
|
||||
* Redraw the display, representing current state
|
||||
* This function is called regularly from the main loop.
|
||||
*/
|
||||
void hmi_evaluate(void)
|
||||
{
|
||||
char s[20];
|
||||
char s[32];
|
||||
|
||||
// Print top line of display
|
||||
sprintf(s, "%s %7.1f %c%3d", hmi_o_mode[hmi_sub[HMI_S_MODE]], (double)hmi_freq/1000.0, (tx_enabled?'T':'R'),920);
|
||||
lcd_writexy(0,0,s);
|
||||
|
||||
// Print bottom line of dsiplay, depending on state
|
||||
switch (hmi_state)
|
||||
{
|
||||
case HMI_S_MENU:
|
||||
sprintf(s, "=> %s ", hmi_o_menu[hmi_option]);
|
||||
lcd_writexy(0,1,s);
|
||||
lcd_curxy(2, 1, false);
|
||||
break;
|
||||
case HMI_S_TUNE:
|
||||
sprintf(s, "%s %s %s", hmi_o_menu[HMI_S_TUNE], hmi_o_pre[hmi_sub[HMI_S_PRE]], hmi_o_agc[hmi_sub[HMI_S_AGC]]);
|
||||
sprintf(s, " %s %s", hmi_o_agc[hmi_sub[HMI_S_AGC]], hmi_o_pre[hmi_sub[HMI_S_PRE]]);
|
||||
lcd_writexy(0,1,s);
|
||||
lcd_curxy(4+(hmi_option>4?6:hmi_option), 0, true);
|
||||
break;
|
||||
case HMI_S_MODE:
|
||||
sprintf(s, "=> Mode: %s ", hmi_o_mode[hmi_option]);
|
||||
sprintf(s, "Set Mode: %s ", hmi_o_mode[hmi_option]);
|
||||
lcd_writexy(0,1,s);
|
||||
lcd_curxy(9, 1, false);
|
||||
break;
|
||||
case HMI_S_AGC:
|
||||
sprintf(s, "=> AGC: %s ", hmi_o_agc[hmi_option]);
|
||||
sprintf(s, "Set AGC: %s ", hmi_o_agc[hmi_option]);
|
||||
lcd_writexy(0,1,s);
|
||||
lcd_curxy(8, 1, false);
|
||||
break;
|
||||
case HMI_S_PRE:
|
||||
sprintf(s, "=> Pre: %s ", hmi_o_pre[hmi_option]);
|
||||
sprintf(s, "Set Pre: %s ", hmi_o_pre[hmi_option]);
|
||||
lcd_writexy(0,1,s);
|
||||
lcd_curxy(8, 1, false);
|
||||
break;
|
||||
|
|
Ładowanie…
Reference in New Issue