diff --git a/App/apps/aprsrx/aprsrx_app.c b/App/apps/aprsrx/aprsrx_app.c index 419f9e22..e95a644b 100644 --- a/App/apps/aprsrx/aprsrx_app.c +++ b/App/apps/aprsrx/aprsrx_app.c @@ -167,6 +167,8 @@ void *memcpy(void *d, const void *s, size_t n) { } /* ---- formatting ---- */ +/* Share the string-copy loop across the display formatters. */ +__attribute__((noinline)) static char *put(char *o,const char *s){ while(*s)*o++=*s++; return o; } /* Formatting by repeated subtraction: no division. Values printed stay below 100000. */ static uint8_t sub(uint32_t *v,uint32_t d){ uint8_t q=0; while(*v>=d){ *v-=d; q++; } return q; } @@ -175,7 +177,7 @@ static char *puti(char *o,int32_t v){ uint32_t u; if(v<0){*o++='-';u=(uint32_t)(-v);} else u=(uint32_t)v; bool lead=false; - for(uint8_t i=0;i<5;i++){ + for(unsigned i=0;i<5u;i++){ uint8_t c=sub(&u,P10[i]); if(c||lead||i==4u){ *o++=(char)('0'+c); lead=true; } } @@ -398,6 +400,7 @@ static char *putCall(char *o,const uint8_t *a){ } /* The tiny font covers 0x20-0x7F: anything else shows as '.'. */ +__attribute__((noinline)) static char safe(uint8_t ch){ return (ch<0x20u||ch>0x7Eu)?'.':(char)ch; } /* One row str..end of the frame, wrapped every ROW_CHARS + g.cw (neither font @@ -409,8 +412,8 @@ static char *emit(char *end){ const app_api_t *A=g.A; char *p=str; while(pw)?p+w:end; + unsigned w=ROW_CHARS+g.cw; /* 18 or 32; compare lengths before forming p + w */ + char *q=((unsigned)(end-p)>w)?p+w:end; char c=*q; *q='\0'; uint8_t r=g.vrow, ln=(uint8_t)(r-(g.top>>3)); /* top = 0 when compact */ if(g.cw && r){ if(r<5u) A->print_tiny(p,0,(uint8_t)(r*6u+2u),false,true); } @@ -432,10 +435,11 @@ static char *brk(char *o){ /* Info bytes f[i..end) after the text already at str..o, on as many rows as * they take. */ static void textRows(char *o,const uint8_t *f,uint16_t i,uint16_t end){ + const uint8_t *p=f+i, *last=f+end; do{ - for(; o='0'&&c<='9') return (uint8_t)(c-'0'); - if(c>='A'&&c<='J') return (uint8_t)(c-'A'); - if(c>='P'&&c<='Y') return (uint8_t)(c-'P'); - return 0; /* K, L, Z: position ambiguity */ + /* Fold P-Y onto A-J, then A-J onto 0-9; reject all other values. */ + unsigned v=c; + if(v>='P') v-='P'-'A'; + if(v>='A') v-='A'-'0'; + v-='0'; + return v<10u?(uint8_t)v:0; /* K, L, Z: position ambiguity */ } static bool micBit(uint8_t c){ return c>='P' || (c>='A'&&c<='K'); } static bool micType(uint8_t t){ return t=='`'||t=='\''||t==0x1Cu||t==0x1Du; } @@ -497,7 +503,7 @@ static void drawMicE(const uint8_t *f,uint16_t i,uint16_t end,const char *s){ /* comment: trailing CR/LF, the device markers (Yaesu/other: '`' or '\'' + * text + 2 chars; Kenwood: '>' or ']' + text [+ '=' or '^']) and a leading * "xxx}" altitude (base 91, metres + 10000) */ - uint16_t j=(uint16_t)(i+9u); + unsigned j=i+9u; /* the caller guarantees j <= end */ while(end>j && (f[end-1]=='\r'||f[end-1]=='\n')) end--; if(ji+1u){ for(uint16_t k=(uint16_t)(i+1u);ki+1u){ + /* A timestamp always occupies the seven bytes after the data type. */ + for(unsigned k=0;k<7u;k++) *o++=safe(f[i+1u+k]); + *o++=' '; + } *o++=safe(q[8]); *o++=safe(q[18]); *o++=' '; textRows(o,f,(uint16_t)(p+19u),end); return true; diff --git a/App/apps/aprsrx/test/aprs_symbols_20_mockup.png b/App/apps/aprsrx/test/aprs_symbols_20_mockup.png new file mode 100644 index 00000000..a27fc857 Binary files /dev/null and b/App/apps/aprsrx/test/aprs_symbols_20_mockup.png differ