mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
Optimize overlay apps and shared audio scope
This commit is contained in:
1 parent
88e76b0e9b
commit
048e7e483b
6 files changed
+90
-108
No files matched your search
+2
-1
@@ -40,7 +40,7 @@
|
|||||||
* reorder, a removal, or an append - MUST bump this. Keep in sync with the
|
* reorder, a removal, or an append - MUST bump this. Keep in sync with the
|
||||||
* value read by pack_app.py, which
|
* value read by pack_app.py, which
|
||||||
* stamps the blob the loader checks against. */
|
* stamps the blob the loader checks against. */
|
||||||
#define APP_ABI_VERSION 5u
|
#define APP_ABI_VERSION 6u
|
||||||
|
|
||||||
/* KEY codes mirrored from driver/keyboard.h (enum KEY_Code_e). Kept in sync by
|
/* KEY codes mirrored from driver/keyboard.h (enum KEY_Code_e). Kept in sync by
|
||||||
* value so the app stays independent of the firmware headers. */
|
* value so the app stays independent of the firmware headers. */
|
||||||
@@ -174,6 +174,7 @@ typedef struct app_api {
|
|||||||
void (*battery_sample)(void); /* periodic ADC sample so the level stays live */
|
void (*battery_sample)(void); /* periodic ADC sample so the level stays live */
|
||||||
void (*backlight_on)(void); /* BACKLIGHT_TurnOn */
|
void (*backlight_on)(void); /* BACKLIGHT_TurnOn */
|
||||||
void (*backlight_update)(void); /* BACKLIGHT_Update (fade step) */
|
void (*backlight_update)(void); /* BACKLIGHT_Update (fade step) */
|
||||||
|
void (*audio_scope)(uint8_t line, bool active); /* shared MAIN microphone scope */
|
||||||
|
|
||||||
uint8_t *status_line; /* -> gStatusLine (for status-bar icons) */
|
uint8_t *status_line; /* -> gStatusLine (for status-bar icons) */
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "driver/backlight.h"
|
#include "driver/backlight.h"
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "ui/helper.h"
|
#include "ui/helper.h"
|
||||||
|
#include "ui/main.h"
|
||||||
#include "ui/status.h"
|
#include "ui/status.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
@@ -276,7 +277,8 @@ static void app_trivfo_get(uint8_t index, app_trivfo_info_t *info)
|
|||||||
#endif
|
#endif
|
||||||
info->code_type = vfo->pRX->CodeType;
|
info->code_type = vfo->pRX->CodeType;
|
||||||
info->code = vfo->pRX->Code;
|
info->code = vfo->pRX->Code;
|
||||||
info->offset_direction = vfo->TX_OFFSET_FREQUENCY_DIRECTION;
|
info->offset_direction = (vfo->freq_config_RX.Frequency != vfo->freq_config_TX.Frequency)
|
||||||
|
? vfo->TX_OFFSET_FREQUENCY_DIRECTION : 0u;
|
||||||
info->reverse = vfo->FrequencyReverse;
|
info->reverse = vfo->FrequencyReverse;
|
||||||
info->squelch = gEeprom.SQUELCH_LEVEL;
|
info->squelch = gEeprom.SQUELCH_LEVEL;
|
||||||
if (index == app_trivfo_selected) info->flags |= APP_TRIVFO_SELECTED;
|
if (index == app_trivfo_selected) info->flags |= APP_TRIVFO_SELECTED;
|
||||||
@@ -640,6 +642,7 @@ static const app_api_t app_api = {
|
|||||||
.battery_sample = app_battery_sample,
|
.battery_sample = app_battery_sample,
|
||||||
.backlight_on = BACKLIGHT_TurnOn,
|
.backlight_on = BACKLIGHT_TurnOn,
|
||||||
.backlight_update = BACKLIGHT_Update,
|
.backlight_update = BACKLIGHT_Update,
|
||||||
|
.audio_scope = UI_DisplayAudioScopeOverlay,
|
||||||
.status_line = gStatusLine,
|
.status_line = gStatusLine,
|
||||||
.tx_state = app_tx_state,
|
.tx_state = app_tx_state,
|
||||||
.tx_set_params = app_tx_set_params,
|
.tx_set_params = app_tx_set_params,
|
||||||
|
|||||||
@@ -104,9 +104,10 @@ static char str[16];
|
|||||||
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 char *put(char *o,const char *s){ while(*s)*o++=*s++; return o; }
|
static char *put(char *o,const char *s){ while(*s)*o++=*s++; return o; }
|
||||||
static char *puti(char *o,int v){
|
static char *puti(char *o,int v){
|
||||||
if(v<0){*o++='-';v=-v;}
|
uint32_t u;
|
||||||
|
if(v<0){*o++='-';u=(uint32_t)(-v);} else u=(uint32_t)v;
|
||||||
char t[6]; int8_t n=0;
|
char t[6]; int8_t n=0;
|
||||||
do{t[n++]=(char)('0'+v%10);v/=10;}while(v&&n<6);
|
do{t[n++]=(char)('0'+u%10u);u/=10u;}while(u&&n<6);
|
||||||
while(n--)*o++=t[n];
|
while(n--)*o++=t[n];
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,11 @@ static void setAudio(void){
|
|||||||
static int32_t lerp(int16_t dbm,int32_t lo,int32_t hi){
|
static int32_t lerp(int16_t dbm,int32_t lo,int32_t hi){
|
||||||
if(dbm<=DBM_FLOOR) return lo;
|
if(dbm<=DBM_FLOOR) return lo;
|
||||||
if(dbm>=DBM_CEIL) return hi;
|
if(dbm>=DBM_CEIL) return hi;
|
||||||
return lo + ((int32_t)(dbm-DBM_FLOOR)*(hi-lo))/(DBM_CEIL-DBM_FLOOR);
|
const int32_t delta = hi - lo;
|
||||||
|
const uint32_t distance = ((uint32_t)(dbm-DBM_FLOOR) *
|
||||||
|
(uint32_t)(delta < 0 ? -delta : delta)) /
|
||||||
|
(uint32_t)(DBM_CEIL-DBM_FLOOR);
|
||||||
|
return lo + (delta < 0 ? -(int32_t)distance : (int32_t)distance);
|
||||||
}
|
}
|
||||||
static void blip(uint16_t freq){
|
static void blip(uint16_t freq){
|
||||||
A->prepare_tone();
|
A->prepare_tone();
|
||||||
@@ -144,23 +149,37 @@ static void blip(uint16_t freq){
|
|||||||
static uint8_t fillCount(int16_t dbm){
|
static uint8_t fillCount(int16_t dbm){
|
||||||
int16_t n;
|
int16_t n;
|
||||||
if(dbm<-141) return 0;
|
if(dbm<-141) return 0;
|
||||||
if(dbm<=-93) n=1+(dbm+141)/6;
|
if(dbm<=-93) n=(int16_t)(1u+(uint16_t)(dbm+141)/6u);
|
||||||
else n=9+(dbm+93)/10;
|
else n=(int16_t)(9u+(uint16_t)(dbm+93)/10u);
|
||||||
if(n>SEG_COUNT) n=SEG_COUNT;
|
if(n>SEG_COUNT) n=SEG_COUNT;
|
||||||
return (uint8_t)n;
|
return (uint8_t)n;
|
||||||
}
|
}
|
||||||
static void buildS(char *out,int16_t dbm){
|
static void buildS(char *out,int16_t dbm){
|
||||||
if(dbm>=-93){ int16_t o=dbm-(-93); if(o>40)o=40; char *p=put(out,"S9+"); if(o<10)*p++='0'; i2str(p,o); }
|
if(dbm>=-93){ int16_t o=dbm-(-93); if(o>40)o=40; char *p=put(out,"S9+"); if(o<10)*p++='0'; i2str(p,o); }
|
||||||
else if(dbm<-141) put(out,"S0")[0]='\0';
|
else if(dbm<-141) put(out,"S0")[0]='\0';
|
||||||
else { char *p=put(out,"S"); i2str(p,(dbm+147)/6); }
|
else { char *p=put(out,"S"); i2str(p,(int)((uint16_t)(dbm+147)/6u)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t div_trunc_pow2(int32_t v, uint8_t shift)
|
||||||
|
{
|
||||||
|
if (v < 0)
|
||||||
|
return (int16_t)-((uint32_t)(-v) >> shift);
|
||||||
|
return (int16_t)((uint32_t)v >> shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t cycleIndex(uint8_t value, uint8_t count, int8_t dir)
|
||||||
|
{
|
||||||
|
if (dir > 0)
|
||||||
|
return ++value < count ? value : 0u;
|
||||||
|
return value > 0u ? (uint8_t)(value - 1u) : (uint8_t)(count - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void histSample(void){
|
static void histSample(void){
|
||||||
histEma += ((int16_t)curDbm*8 - histEma)/4;
|
histEma += div_trunc_pow2((int32_t)curDbm * 8 - histEma, 2u);
|
||||||
if(++histTick<HIST_DECIM) return;
|
if(++histTick<HIST_DECIM) return;
|
||||||
histTick=0;
|
histTick=0;
|
||||||
histBuf[histHead]=fillCount((int16_t)(histEma/8));
|
histBuf[histHead]=fillCount(div_trunc_pow2(histEma, 3u));
|
||||||
histHead=(uint8_t)((histHead+1)%HIST_LEN);
|
if(++histHead>=HIST_LEN) histHead=0;
|
||||||
}
|
}
|
||||||
static void rebase(void){
|
static void rebase(void){
|
||||||
curDbm=A->rssi_dbm();
|
curDbm=A->rssi_dbm();
|
||||||
@@ -171,7 +190,7 @@ static void rebase(void){
|
|||||||
histHead=0; histTick=0; histEma=(int16_t)(curDbm*8);
|
histHead=0; histTick=0; histEma=(int16_t)(curDbm*8);
|
||||||
}
|
}
|
||||||
static void attCycle(int8_t dir){
|
static void attCycle(int8_t dir){
|
||||||
attStep=(uint8_t)((attStep + (dir>0?1:ATT_COUNT-1))%ATT_COUNT);
|
attStep=cycleIndex(attStep,ATT_COUNT,dir);
|
||||||
applyAtt();
|
applyAtt();
|
||||||
A->delay_ms(ATT_SETTLE);
|
A->delay_ms(ATT_SETTLE);
|
||||||
rebase();
|
rebase();
|
||||||
@@ -198,7 +217,7 @@ static void drawHist(void){
|
|||||||
uint8_t lvl=histBuf[idx]; if(++idx>=HIST_LEN)idx=0;
|
uint8_t lvl=histBuf[idx]; if(++idx>=HIST_LEN)idx=0;
|
||||||
if(lvl>SEG_COUNT)lvl=SEG_COUNT;
|
if(lvl>SEG_COUNT)lvl=SEG_COUNT;
|
||||||
uint8_t x=GRAPH_X0+c;
|
uint8_t x=GRAPH_X0+c;
|
||||||
uint8_t y=(uint8_t)(floorY-(lvl*span)/SEG_COUNT);
|
uint8_t y=(uint8_t)(floorY-((uint32_t)lvl*span)/(uint32_t)SEG_COUNT);
|
||||||
for(uint8_t yy=y+1;yy<=floorY;yy++) if(((x+yy)&1)==0) A->draw_line(A->fb,x,yy,x,yy,true);
|
for(uint8_t yy=y+1;yy<=floorY;yy++) if(((x+yy)&1)==0) A->draw_line(A->fb,x,yy,x,yy,true);
|
||||||
if(c==0){ A->draw_line(A->fb,x,y,x,y,true); }
|
if(c==0){ A->draw_line(A->fb,x,y,x,y,true); }
|
||||||
else { uint8_t lo=(y<prevY)?y:prevY, hi=(y<prevY)?prevY:y; A->draw_line(A->fb,x,lo,x,hi,true); }
|
else { uint8_t lo=(y<prevY)?y:prevY, hi=(y<prevY)?prevY:y; A->draw_line(A->fb,x,lo,x,hi,true); }
|
||||||
@@ -240,7 +259,7 @@ static void draw(void){
|
|||||||
i2str(put(str,"PK "),peakDbm);
|
i2str(put(str,"PK "),peakDbm);
|
||||||
tag(str,4,2);
|
tag(str,4,2);
|
||||||
i2str(put(str,"MN "),minDbm);
|
i2str(put(str,"MN "),minDbm);
|
||||||
tag(str,(uint8_t)((LCD_WIDTH-slen(str)*4)/2),2);
|
tag(str,(uint8_t)(((uint32_t)LCD_WIDTH-(uint32_t)slen(str)*4u)/2u),2);
|
||||||
buildS(sMeter,curDbm);
|
buildS(sMeter,curDbm);
|
||||||
A->print_inverse(sMeter,(uint8_t)(126-slen(sMeter)*4),2,false,true,125);
|
A->print_inverse(sMeter,(uint8_t)(126-slen(sMeter)*4),2,false,true,125);
|
||||||
|
|
||||||
@@ -295,7 +314,7 @@ static void handleKeys(void){
|
|||||||
case APP_KEY_EXIT: running=false; break;
|
case APP_KEY_EXIT: running=false; break;
|
||||||
case APP_KEY_1: foxGraphMode^=1; break;
|
case APP_KEY_1: foxGraphMode^=1; break;
|
||||||
case APP_KEY_2:
|
case APP_KEY_2:
|
||||||
foxAudioMode=(uint8_t)((foxAudioMode+(dir>0?1:2))%3); setAudio();
|
foxAudioMode=cycleIndex(foxAudioMode,3u,dir); setAudio();
|
||||||
if(foxAudioMode==AUDIO_BEEP){ audioTick=RATE_SLOW; }
|
if(foxAudioMode==AUDIO_BEEP){ audioTick=RATE_SLOW; }
|
||||||
break;
|
break;
|
||||||
case APP_KEY_3: attCycle(dir); break;
|
case APP_KEY_3: attCycle(dir); break;
|
||||||
|
|||||||
@@ -14,17 +14,13 @@
|
|||||||
#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 SCOPE_SAMPLES 43u
|
|
||||||
#define SCOPE_FLOOR 200u
|
|
||||||
|
|
||||||
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];
|
||||||
static uint8_t selected, state;
|
static uint8_t selected, state;
|
||||||
static uint16_t cChannel;
|
static uint16_t cChannel;
|
||||||
static bool running, fArm, txDenied, channelLabelOn, showFrequency;
|
static bool running, fArm, txDenied, channelLabelOn, showFrequency;
|
||||||
static uint16_t scopeBuf[SCOPE_SAMPLES], scopeFloor;
|
static uint8_t batteryTicks;
|
||||||
static uint8_t scopeWrite, scopeReady, batteryTicks;
|
|
||||||
static bool scopeTx;
|
|
||||||
static char text[16];
|
static char text[16];
|
||||||
|
|
||||||
/* Resident status.c uses this exact 8-column inverted glyph at x=69. Keep
|
/* Resident status.c uses this exact 8-column inverted glyph at x=69. Keep
|
||||||
@@ -75,7 +71,6 @@ static void formatCode(char *s,const app_trivfo_info_t *v){
|
|||||||
} else return formatStep(s,v->step);
|
} else return formatStep(s,v->step);
|
||||||
*o='\0';
|
*o='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawMeter(const app_trivfo_info_t *v){
|
static void drawMeter(const app_trivfo_info_t *v){
|
||||||
int16_t dbm=v->rssi_dbm; if(dbm>-53)dbm=-53;
|
int16_t dbm=v->rssi_dbm; if(dbm>-53)dbm=-53;
|
||||||
uint8_t s=0,over=0;
|
uint8_t s=0,over=0;
|
||||||
@@ -98,37 +93,6 @@ static void drawMeter(const app_trivfo_info_t *v){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawAudioScope(void){
|
|
||||||
if(!scopeTx){
|
|
||||||
for(uint8_t i=0;i<SCOPE_SAMPLES;i++) scopeBuf[i]=SCOPE_FLOOR;
|
|
||||||
scopeFloor=SCOPE_FLOOR; scopeWrite=scopeReady=0; scopeTx=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(scopeReady>=7u) scopeBuf[scopeWrite]=A->bk_read(0x64u);
|
|
||||||
else scopeReady++;
|
|
||||||
if(scopeBuf[scopeWrite]==0u) scopeBuf[scopeWrite]=SCOPE_FLOOR;
|
|
||||||
scopeWrite=(uint8_t)((scopeWrite+1u)%SCOPE_SAMPLES);
|
|
||||||
|
|
||||||
uint16_t min=scopeBuf[0], max=scopeBuf[0];
|
|
||||||
for(uint8_t i=1;i<SCOPE_SAMPLES;i++){
|
|
||||||
if(scopeBuf[i]<min) min=scopeBuf[i];
|
|
||||||
if(scopeBuf[i]>max) max=scopeBuf[i];
|
|
||||||
}
|
|
||||||
if(scopeFloor>min) scopeFloor=(uint16_t)(scopeFloor-((scopeFloor-min)>>3)-1u);
|
|
||||||
else scopeFloor=(uint16_t)(scopeFloor+2u);
|
|
||||||
uint16_t range=max>scopeFloor?(uint16_t)(max-scopeFloor):0u;
|
|
||||||
|
|
||||||
for(uint8_t i=0;i<SCOPE_SAMPLES;i++){
|
|
||||||
uint8_t idx=(uint8_t)((scopeWrite+i)%SCOPE_SAMPLES), height=0;
|
|
||||||
if(range>=50u){
|
|
||||||
uint16_t value=scopeBuf[idx]>scopeFloor?(uint16_t)(scopeBuf[idx]-scopeFloor):0u;
|
|
||||||
height=(uint8_t)((uint32_t)value*7u/range);
|
|
||||||
}
|
|
||||||
uint8_t mask=height?(uint8_t)((0x7fu<<(7u-height))&0x7fu):0x40u;
|
|
||||||
A->fb[0][i*3u]=mask; A->fb[0][i*3u+1u]=mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -151,22 +115,18 @@ 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);
|
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);
|
A->print_tiny(power[p],24,techY,false,true);
|
||||||
if(v->flags&APP_TRIVFO_USER_POWER){
|
if(v->flags&APP_TRIVFO_USER_POWER){
|
||||||
A->fb[techLine][19]=0x3e; A->fb[techLine][20]=0x1c; A->fb[techLine][21]=0x08;
|
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);
|
if(v->offset_direction==1u) A->print_normal("+",41,0,techLine);
|
||||||
else if(v->offset_direction==2u) 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->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); }
|
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 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); }
|
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);
|
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';
|
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);
|
A->print_tiny(text,110,techY,false,true);
|
||||||
@@ -187,9 +147,9 @@ static void draw(void){
|
|||||||
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))
|
||||||
drawAudioScope();
|
A->audio_scope(0u,true);
|
||||||
else {
|
else {
|
||||||
scopeTx=false;
|
A->audio_scope(0u,false);
|
||||||
for(uint8_t i=0;i<VFO_COUNT;i++)
|
for(uint8_t i=0;i<VFO_COUNT;i++)
|
||||||
if(vi[i].flags&APP_TRIVFO_RECEIVING){ drawMeter(&vi[i]); break; }
|
if(vi[i].flags&APP_TRIVFO_RECEIVING){ drawMeter(&vi[i]); break; }
|
||||||
}
|
}
|
||||||
@@ -205,7 +165,7 @@ static void saveCfg(void){ uint8_t c[3]={CFG_MAGIC,(uint8_t)cChannel,(uint8_t)(c
|
|||||||
|
|
||||||
__attribute__((section(".text.entry"),used))
|
__attribute__((section(".text.entry"),used))
|
||||||
void app_main(const app_api_t *api){
|
void app_main(const app_api_t *api){
|
||||||
A=api; running=true; fArm=false; txDenied=false; channelLabelOn=true; showFrequency=false; selected=scopeWrite=scopeReady=batteryTicks=0; scopeTx=false; scopeFloor=SCOPE_FLOOR; loadCfg();
|
A=api; running=true; fArm=false; txDenied=false; channelLabelOn=true; showFrequency=false; selected=batteryTicks=0; loadCfg();
|
||||||
cChannel=A->trivfo_enter(cChannel); A->trivfo_select(0); A->backlight_on();
|
cChannel=A->trivfo_enter(cChannel); A->trivfo_select(0); A->backlight_on();
|
||||||
|
|
||||||
uint8_t held=APP_KEY_INVALID, blinkTicks=0; uint16_t heldMs=0; bool longDone=false, ptt=false;
|
uint8_t held=APP_KEY_INVALID, blinkTicks=0; uint16_t heldMs=0; bool longDone=false, ptt=false;
|
||||||
|
|||||||
+45
-49
@@ -843,15 +843,14 @@ void UI_DisplayAudioBar(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_FEAT_F4HWN_AUDIO_SCOPE
|
#if defined(ENABLE_FEAT_F4HWN_AUDIO_SCOPE) || defined(ENABLE_FEAT_F4HWN_OVERLAY_APPS)
|
||||||
|
|
||||||
#define SCOPE_SAMPLES 43 // number of columns (43 × 3px = 128px wide)
|
#define SCOPE_SAMPLES 43 // number of columns (43 × 3px = 128px wide)
|
||||||
#define SCOPE_NOISE_GATE 50u // minimum range below which the display shows baseline
|
#define SCOPE_NOISE_GATE 50u // minimum range below which the display shows baseline
|
||||||
#define SCOPE_FLOOR_RISE 2u // floor rise per frame (+100 units/s at 20ms/frame)
|
#define SCOPE_FLOOR_RISE 2u // floor rise per frame (+100 units/s at 20ms/frame)
|
||||||
#define SCOPE_FLOOR_DROP_SHR 3u // floor drop IIR shift: drop by (floor-min) >> N per frame (~160ms to halve)
|
#define SCOPE_FLOOR_DROP_SHR 3u // floor drop IIR shift: drop by (floor-min) >> N per frame (~160ms to halve)
|
||||||
#define SCOPE_VOLUME_MIN 200u // let's assume that the sound level in silence is 200
|
#define SCOPE_VOLUME_MIN 200u // let's assume that the sound level in silence is 200
|
||||||
|
|
||||||
void UI_DisplayAudioScope(void)
|
void UI_DisplayAudioScopeOverlay(const uint8_t line, const bool active)
|
||||||
{
|
{
|
||||||
static uint16_t g_scope_buf[SCOPE_SAMPLES];
|
static uint16_t g_scope_buf[SCOPE_SAMPLES];
|
||||||
static uint8_t g_scope_write = 0;
|
static uint8_t g_scope_write = 0;
|
||||||
@@ -865,22 +864,11 @@ void UI_DisplayAudioScope(void)
|
|||||||
|
|
||||||
static bool s_was_tx = false;
|
static bool s_was_tx = false;
|
||||||
|
|
||||||
if (gCurrentFunction != FUNCTION_TRANSMIT) {
|
if (!active) {
|
||||||
s_was_tx = false;
|
s_was_tx = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This prevents a sudden spike on the bar caused by release the PTT button
|
|
||||||
if (!GPIO_IsPttPressed()
|
|
||||||
#ifdef ENABLE_VOX
|
|
||||||
&& !gEeprom.VOX_SWITCH
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_FEAT_F4HWN
|
|
||||||
&& !gSetting_set_ptt_session
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!s_was_tx) {
|
if (!s_was_tx) {
|
||||||
// TX entry: full reset so every new transmission starts from a clean state
|
// TX entry: full reset so every new transmission starts from a clean state
|
||||||
for (uint8_t i = 0; i < SCOPE_SAMPLES; i++) g_scope_buf[i] = SCOPE_VOLUME_MIN;
|
for (uint8_t i = 0; i < SCOPE_SAMPLES; i++) g_scope_buf[i] = SCOPE_VOLUME_MIN;
|
||||||
@@ -903,32 +891,6 @@ void UI_DisplayAudioScope(void)
|
|||||||
|
|
||||||
g_scope_write = (g_scope_write + 1u) % SCOPE_SAMPLES;
|
g_scope_write = (g_scope_write + 1u) % SCOPE_SAMPLES;
|
||||||
|
|
||||||
// --------------------------------- Refresh display ---------------------------------
|
|
||||||
|
|
||||||
if (gLowBattery && !gLowBatteryConfirmed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (gScreenToDisplay != DISPLAY_MAIN
|
|
||||||
#ifdef ENABLE_DTMF_CALLING
|
|
||||||
|| gDTMF_CallState != DTMF_CALL_STATE_NONE
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef ENABLE_TX1750
|
|
||||||
if (gTx1750Active)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_FEAT_F4HWN
|
|
||||||
RxBlinkLed = 0;
|
|
||||||
RxBlinkLedCounter = 0;
|
|
||||||
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
|
|
||||||
const unsigned int line = isMainOnly() ? 5 : 3;
|
|
||||||
#else
|
|
||||||
const unsigned int line = 3;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t *p_line = gFrameBuffer[line];
|
uint8_t *p_line = gFrameBuffer[line];
|
||||||
memset(p_line, 0, LCD_WIDTH);
|
memset(p_line, 0, LCD_WIDTH);
|
||||||
|
|
||||||
@@ -968,9 +930,50 @@ void UI_DisplayAudioScope(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_FEAT_F4HWN_AUDIO_SCOPE
|
||||||
|
void UI_DisplayAudioScope(void)
|
||||||
|
{
|
||||||
|
const unsigned int line = isMainOnly() ? 5u : 3u;
|
||||||
|
|
||||||
|
/* Keep MAIN's original gating and side effects outside the shared renderer. */
|
||||||
|
if (gCurrentFunction != FUNCTION_TRANSMIT) {
|
||||||
|
UI_DisplayAudioScopeOverlay((uint8_t)line, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!GPIO_IsPttPressed()
|
||||||
|
#ifdef ENABLE_VOX
|
||||||
|
&& !gEeprom.VOX_SWITCH
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FEAT_F4HWN
|
||||||
|
&& !gSetting_set_ptt_session
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
if (gLowBattery && !gLowBatteryConfirmed)
|
||||||
|
return;
|
||||||
|
if (gScreenToDisplay != DISPLAY_MAIN
|
||||||
|
#ifdef ENABLE_DTMF_CALLING
|
||||||
|
|| gDTMF_CallState != DTMF_CALL_STATE_NONE
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
#ifdef ENABLE_TX1750
|
||||||
|
if (gTx1750Active)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_FEAT_F4HWN
|
||||||
|
RxBlinkLed = 0;
|
||||||
|
RxBlinkLedCounter = 0;
|
||||||
|
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
|
||||||
|
#endif
|
||||||
|
UI_DisplayAudioScopeOverlay((uint8_t)line, true);
|
||||||
ST7565_BlitLine(line);
|
ST7565_BlitLine(line);
|
||||||
}
|
}
|
||||||
#endif // ENABLE_FEAT_F4HWN_AUDIO_SCOPE
|
#endif
|
||||||
|
#endif // ENABLE_FEAT_F4HWN_AUDIO_SCOPE || ENABLE_FEAT_F4HWN_OVERLAY_APPS
|
||||||
|
|
||||||
void DisplayRSSIBar(const bool now)
|
void DisplayRSSIBar(const bool now)
|
||||||
{
|
{
|
||||||
@@ -2086,9 +2089,6 @@ void UI_DisplayMain(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUI_DisplaySmallest(String, 68 + shift, line == 0 ? 17 : 49, false, true);
|
GUI_DisplaySmallest(String, 68 + shift, line == 0 ? 17 : 49, false, true);
|
||||||
|
|
||||||
//sprintf(String, "%d.%02u", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100);
|
|
||||||
//GUI_DisplaySmallest(String, 91, line == 0 ? 2 : 34, false, true);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UI_PrintStringSmallNormal(s, LCD_WIDTH + 24, 0, line + 1);
|
UI_PrintStringSmallNormal(s, LCD_WIDTH + 24, 0, line + 1);
|
||||||
@@ -2123,8 +2123,6 @@ void UI_DisplayMain(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"};
|
const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"};
|
||||||
//sprintf(String, "%s", pwr_long[currentPower]);
|
|
||||||
//GUI_DisplaySmallest(String, 24, line == 0 ? 17 : 49, false, true);
|
|
||||||
GUI_DisplaySmallest(pwr_long[currentPower], 24, line == 0 ? 17 : 49, false, true);
|
GUI_DisplaySmallest(pwr_long[currentPower], 24, line == 0 ? 17 : 49, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2162,9 +2160,7 @@ void UI_DisplayMain(void)
|
|||||||
{
|
{
|
||||||
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
|
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
|
||||||
if(i == 3)
|
if(i == 3)
|
||||||
{
|
|
||||||
GUI_DisplaySmallest(dir_list[i], 43, line == 0 ? 17 : 49, false, true);
|
GUI_DisplaySmallest(dir_list[i], 43, line == 0 ? 17 : 49, false, true);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ extern center_line_t center_line;
|
|||||||
#ifdef ENABLE_AUDIO_BAR
|
#ifdef ENABLE_AUDIO_BAR
|
||||||
void UI_DisplayAudioBar(void);
|
void UI_DisplayAudioBar(void);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(ENABLE_FEAT_F4HWN_AUDIO_SCOPE) || defined(ENABLE_FEAT_F4HWN_OVERLAY_APPS)
|
||||||
|
void UI_DisplayAudioScopeOverlay(uint8_t line, bool active);
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_FEAT_F4HWN_AUDIO_SCOPE
|
#ifdef ENABLE_FEAT_F4HWN_AUDIO_SCOPE
|
||||||
void UI_DisplayAudioScope(void);
|
void UI_DisplayAudioScope(void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in new issue
Block a user