Add SetGUI and PTT support to Triple VFO

This commit is contained in:
Armel FAUVEAU committed 2026-08-30 17:28:33 +02:00
1 parent 048e7e483b
commit 2f80e60c01
3 files changed
+80 -26

No files matched your search

+3 -1
View File
@@ -107,6 +107,8 @@ enum {
APP_TRIVFO_TX = 1u << 3, APP_TRIVFO_TX = 1u << 3,
APP_TRIVFO_USER_POWER = 1u << 4, APP_TRIVFO_USER_POWER = 1u << 4,
APP_TRIVFO_AUDIO_BAR = 1u << 5, APP_TRIVFO_AUDIO_BAR = 1u << 5,
APP_TRIVFO_GUI_CLASSIC = 1u << 6,
APP_TRIVFO_PTT_ONEPUSH = 1u << 7,
}; };
enum { enum {
@@ -218,7 +220,7 @@ typedef struct app_api {
void (*trivfo_select)(uint8_t vfo); void (*trivfo_select)(uint8_t vfo);
uint16_t (*trivfo_step)(uint8_t vfo, int8_t direction); uint16_t (*trivfo_step)(uint8_t vfo, int8_t direction);
uint8_t (*trivfo_tick)(void); uint8_t (*trivfo_tick)(void);
uint8_t (*trivfo_ptt)(bool pressed); /* 0 OK; non-zero TX denial/timeout */ uint8_t (*trivfo_ptt)(bool pressed); /* physical PTT edge; resident applies SetPTT */
} app_api_t; } app_api_t;
/* BK4819 AF modes for set_af (mirror driver/bk4819.h values). */ /* BK4819 AF modes for set_af (mirror driver/bk4819.h values). */
+30 -12
View File
@@ -101,8 +101,11 @@ static bool app_trivfo_ctcss_ok;
static bool app_trivfo_cdcss_ok; static bool app_trivfo_cdcss_ok;
static bool app_trivfo_ab_dirty; static bool app_trivfo_ab_dirty;
static bool app_trivfo_restore_selection; static bool app_trivfo_restore_selection;
static bool app_trivfo_onepush_stop_armed;
static uint8_t app_trivfo_freq_dirty; static uint8_t app_trivfo_freq_dirty;
static void app_trivfo_end_tx(void);
static VFO_Info_t *app_trivfo_vfo(uint8_t vfo) static VFO_Info_t *app_trivfo_vfo(uint8_t vfo)
{ {
return vfo < 2u ? &gEeprom.VfoInfo[vfo] : &app_trivfo_c; return vfo < 2u ? &gEeprom.VfoInfo[vfo] : &app_trivfo_c;
@@ -228,6 +231,7 @@ static uint16_t app_trivfo_enter(uint16_t c_channel)
app_trivfo_hold = 0; app_trivfo_hold = 0;
app_trivfo_running = true; app_trivfo_running = true;
app_trivfo_transmitting = false; app_trivfo_transmitting = false;
app_trivfo_onepush_stop_armed = false;
app_trivfo_ab_dirty = false; app_trivfo_ab_dirty = false;
app_trivfo_freq_dirty = 0; app_trivfo_freq_dirty = 0;
app_trivfo_tune(0); app_trivfo_tune(0);
@@ -238,10 +242,8 @@ static void app_trivfo_leave(void)
{ {
if (!app_trivfo_running) if (!app_trivfo_running)
return; return;
if (app_trivfo_transmitting) { if (app_trivfo_transmitting)
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); app_trivfo_end_tx();
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false);
}
AUDIO_AudioPathOff(); AUDIO_AudioPathOff();
gEnableSpeaker = false; gEnableSpeaker = false;
app_trivfo_running = false; app_trivfo_running = false;
@@ -289,6 +291,8 @@ static void app_trivfo_get(uint8_t index, app_trivfo_info_t *info)
#ifdef ENABLE_AUDIO_BAR #ifdef ENABLE_AUDIO_BAR
if (gSetting_mic_bar) info->flags |= APP_TRIVFO_AUDIO_BAR; if (gSetting_mic_bar) info->flags |= APP_TRIVFO_AUDIO_BAR;
#endif #endif
if (gSetting_set_gui) info->flags |= APP_TRIVFO_GUI_CLASSIC;
if (gSetting_set_ptt_session) info->flags |= APP_TRIVFO_PTT_ONEPUSH;
if (IS_MR_CHANNEL(vfo->CHANNEL_SAVE)) if (IS_MR_CHANNEL(vfo->CHANNEL_SAVE))
memcpy(info->name, vfo->Name, sizeof(info->name) - 1u); memcpy(info->name, vfo->Name, sizeof(info->name) - 1u);
} }
@@ -340,7 +344,17 @@ static uint16_t app_trivfo_step(uint8_t index, int8_t direction)
return channel; return channel;
} }
static uint8_t app_trivfo_ptt(bool pressed); static void app_trivfo_end_tx(void)
{
if (!app_trivfo_transmitting)
return;
RADIO_SendEndOfTransmission();
app_trivfo_transmitting = false;
app_trivfo_onepush_stop_armed = false;
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false);
app_trivfo_hold = APP_TRIVFO_TX_HOLD_TICKS;
app_trivfo_tune(app_trivfo_selected);
}
static uint8_t app_trivfo_tick(void) static uint8_t app_trivfo_tick(void)
{ {
@@ -349,7 +363,7 @@ static uint8_t app_trivfo_tick(void)
if (app_trivfo_transmitting) { if (app_trivfo_transmitting) {
const uint32_t timeout = ((uint32_t)gEeprom.TX_TIMEOUT_TIMER + 1u) * 250u; const uint32_t timeout = ((uint32_t)gEeprom.TX_TIMEOUT_TIMER + 1u) * 250u;
if (++app_trivfo_tx_ticks >= timeout) { if (++app_trivfo_tx_ticks >= timeout) {
app_trivfo_ptt(false); app_trivfo_end_tx();
return APP_TRIVFO_HOLD; return APP_TRIVFO_HOLD;
} }
return APP_TRIVFO_TX_STATE; return APP_TRIVFO_TX_STATE;
@@ -420,15 +434,18 @@ static uint8_t app_trivfo_ptt(bool pressed)
if (!pressed) { if (!pressed) {
if (!app_trivfo_transmitting) if (!app_trivfo_transmitting)
return 0; return 0;
RADIO_SendEndOfTransmission(); /* ONEPUSH mirrors the resident PTT sequence: the first release keeps
app_trivfo_transmitting = false; * TX keyed; the release following the second press ends TX. */
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); if (gSetting_set_ptt_session && !app_trivfo_onepush_stop_armed)
app_trivfo_hold = APP_TRIVFO_TX_HOLD_TICKS; return 0;
app_trivfo_tune(app_trivfo_selected); app_trivfo_end_tx();
return 0; return 0;
} }
if (app_trivfo_transmitting) if (app_trivfo_transmitting) {
if (gSetting_set_ptt_session)
app_trivfo_onepush_stop_armed = true;
return 0; return 0;
}
VFO_Info_t *vfo = app_trivfo_vfo(app_trivfo_selected); VFO_Info_t *vfo = app_trivfo_vfo(app_trivfo_selected);
if ((TX_freq_check(vfo->pTX->Frequency) != 0 && vfo->TX_LOCK) || if ((TX_freq_check(vfo->pTX->Frequency) != 0 && vfo->TX_LOCK) ||
@@ -447,6 +464,7 @@ static uint8_t app_trivfo_ptt(bool pressed)
app_trivfo_current = app_trivfo_selected; app_trivfo_current = app_trivfo_selected;
app_trivfo_receiving = false; app_trivfo_receiving = false;
app_trivfo_transmitting = true; app_trivfo_transmitting = true;
app_trivfo_onepush_stop_armed = false;
app_trivfo_tx_ticks = 0; app_trivfo_tx_ticks = 0;
return 0; return 0;
} }
+47 -13
View File
@@ -14,6 +14,7 @@
#define CFG_MAGIC 0xC3u #define CFG_MAGIC 0xC3u
#define VFO_COUNT 3u #define VFO_COUNT 3u
#define MR_MAX 1024u #define MR_MAX 1024u
#define STATUS_PTT_X 54u
static const app_api_t *A; static const app_api_t *A;
static app_trivfo_info_t vi[VFO_COUNT]; static app_trivfo_info_t vi[VFO_COUNT];
@@ -30,6 +31,16 @@ static const uint8_t fontF[8] = {
0x7f, 0x00, 0x76, 0x76, 0x76, 0x76, 0x7e, 0x7f 0x7f, 0x00, 0x76, 0x76, 0x76, 0x76, 0x7e, 0x7f
}; };
/* Same two 2x6 glyphs and same x=54 slot as UI_DisplayStatus(). */
static const uint8_t fontPttOnePush[12] = {
0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e,
0x00, 0x7f, 0x09, 0x09, 0x09, 0x06
};
static const uint8_t fontPttClassic[12] = {
0x00, 0x3e, 0x41, 0x41, 0x41, 0x22,
0x00, 0x7f, 0x40, 0x40, 0x40, 0x40
};
static uint8_t slen(const char *s){ uint8_t n=0; while(s[n])n++; return n; } static uint8_t slen(const char *s){ uint8_t n=0; while(s[n])n++; return n; }
static bool copyName(char *d,const char *s){ static bool copyName(char *d,const char *s){
uint8_t n=0; uint8_t n=0;
@@ -93,6 +104,11 @@ static void drawMeter(const app_trivfo_info_t *v){
} }
} }
static void drawPttStatus(void){
const uint8_t *glyph=(vi[0].flags&APP_TRIVFO_PTT_ONEPUSH)?fontPttOnePush:fontPttClassic;
for(uint8_t i=0;i<12u;i++) A->status_line[STATUS_PTT_X+i]=glyph[i];
}
static void drawVfo(uint8_t n){ static void drawVfo(uint8_t n){
const app_trivfo_info_t *v=&vi[n]; const app_trivfo_info_t *v=&vi[n];
uint8_t mainLine=(uint8_t)(n*2u+1u), techLine=(uint8_t)(mainLine+1u); uint8_t mainLine=(uint8_t)(n*2u+1u), techLine=(uint8_t)(mainLine+1u);
@@ -114,22 +130,39 @@ static void drawVfo(uint8_t n){
} }
const char *mod=v->modulation==0u?"FM":v->modulation==1u?"AM":v->modulation==2u?"USB":v->modulation==3u?"BYP":v->modulation==4u?"RAW":"?"; const char *mod=v->modulation==0u?"FM":v->modulation==1u?"AM":v->modulation==2u?"USB":v->modulation==3u?"BYP":v->modulation==4u?"RAW":"?";
A->print_tiny(mod,3,techY,false,true);
static const char *const power[7]={"LOW1","LOW2","LOW3","LOW4","LOW5","MID","HIGH"}; static const char *const power[7]={"LOW1","LOW2","LOW3","LOW4","LOW5","MID","HIGH"};
uint8_t p=(v->power>=1u&&v->power<=7u)?(uint8_t)(v->power-1u):0u; uint8_t p=(v->power>=1u&&v->power<=7u)?(uint8_t)(v->power-1u):0u;
A->print_tiny(power[p],24,techY,false,true); if(v->flags&APP_TRIVFO_GUI_CLASSIC){
if(v->flags&APP_TRIVFO_USER_POWER){ A->print_normal(mod,2,0,techLine);
A->fb[techLine][19]=0x3e; A->fb[techLine][20]=0x1c; A->fb[techLine][21]=0x08; if(v->modulation==0u&&v->code_type==1u) A->print_normal("CT",22,0,techLine);
else if(v->modulation==0u&&(v->code_type==2u||v->code_type==3u)) A->print_normal("DC",22,0,techLine);
static const char *const powerShort[7]={"L1","L2","L3","L4","L5","M","H"};
A->print_normal(powerShort[p],42,0,techLine);
if(v->flags&APP_TRIVFO_USER_POWER){
A->fb[techLine][38]=0x3e; A->fb[techLine][39]=0x1c; A->fb[techLine][40]=0x08;
}
if(v->offset_direction==1u) A->print_normal("+",60,0,techLine);
else if(v->offset_direction==2u) A->print_normal("-",60,0,techLine);
if(v->reverse) A->print_normal("R",68,0,techLine);
A->print_normal(v->bandwidth==0u?"W":v->bandwidth==1u?"N":"N+",80,0,techLine);
text[0]='S'; text[1]='Q'; text[2]='L'; text[3]=(char)('0'+(v->squelch%10u)); text[4]='\0';
A->print_normal(text,98,0,techLine);
} else {
A->print_tiny(mod,3,techY,false,true);
A->print_tiny(power[p],24,techY,false,true);
if(v->flags&APP_TRIVFO_USER_POWER){
A->fb[techLine][19]=0x3e; A->fb[techLine][20]=0x1c; A->fb[techLine][21]=0x08;
}
if(v->offset_direction==1u) A->print_normal("+",41,0,techLine);
else if(v->offset_direction==2u) A->print_normal("-",41,0,techLine);
if(v->reverse) A->print_tiny("R",51,techY,false,true);
if(v->code_type==1u){ A->print_tiny("CT",58,techY,false,true); formatCode(text,v); A->print_tiny(text,68,techY,false,true); }
else if(v->code_type==2u||v->code_type==3u){ A->print_tiny("DC",58,techY,false,true); formatCode(text,v); A->print_tiny(text,68,techY,false,true); }
else { formatStep(text,v->step); A->print_tiny(text,58,techY,false,true); }
A->print_tiny(v->bandwidth==0u?"WIDE":v->bandwidth==1u?"NAR":"NAR+",91,techY,false,true);
text[0]='S'; text[1]='Q'; text[2]='L'; text[3]=(char)('0'+(v->squelch%10u)); text[4]='\0';
A->print_tiny(text,110,techY,false,true);
} }
if(v->offset_direction==1u) A->print_normal("+",41,0,techLine);
else if(v->offset_direction==2u) A->print_normal("-",41,0,techLine);
if(v->reverse) A->print_tiny("R",51,techY,false,true);
if(v->code_type==1u){ A->print_tiny("CT",58,techY,false,true); formatCode(text,v); A->print_tiny(text,68,techY,false,true); }
else if(v->code_type==2u||v->code_type==3u){ A->print_tiny("DC",58,techY,false,true); formatCode(text,v); A->print_tiny(text,68,techY,false,true); }
else { formatStep(text,v->step); A->print_tiny(text,58,techY,false,true); }
A->print_tiny(v->bandwidth==0u?"WIDE":v->bandwidth==1u?"NAR":"NAR+",91,techY,false,true);
text[0]='S'; text[1]='Q'; text[2]='L'; text[3]=(char)('0'+(v->squelch%10u)); text[4]='\0';
A->print_tiny(text,110,techY,false,true);
} }
static void draw(void){ static void draw(void){
@@ -144,6 +177,7 @@ static void draw(void){
/* Keep the application title in the resident upper-left position. */ /* Keep the application title in the resident upper-left position. */
A->draw_battery(); A->draw_battery();
A->print_inverse("TRIPLE VFO",2,0,true,true,42); A->print_inverse("TRIPLE VFO",2,0,true,true,42);
drawPttStatus();
if(fArm){ for(uint8_t i=0;i<8u;i++) A->status_line[69u+i]=fontF[i]; } if(fArm){ for(uint8_t i=0;i<8u;i++) A->status_line[69u+i]=fontF[i]; }
for(uint8_t i=0;i<VFO_COUNT;i++) drawVfo(i); for(uint8_t i=0;i<VFO_COUNT;i++) drawVfo(i);
if(state==APP_TRIVFO_TX_STATE&&(vi[selected].flags&APP_TRIVFO_AUDIO_BAR)) if(state==APP_TRIVFO_TX_STATE&&(vi[selected].flags&APP_TRIVFO_AUDIO_BAR))