Skip to content

Commit 6d80530

Browse files
authored
Merge pull request #254 from wasatch-dev/planets
Add support for displaying the 7 classical planets in our solar syste…
2 parents eb0e8d5 + 0746f4d commit 6d80530

12 files changed

Lines changed: 585 additions & 208 deletions

File tree

ESPHamClock/ESPHamClock.cpp

Lines changed: 52 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,8 @@ static void checkTouch()
878878
// set showing sat in DX box
879879
dx_info_for_sat = true;
880880
drawSatPass();
881+
} else if (checkPlanetMapTouch (s)) {
882+
// handled entirely within checkPlanetMapTouch
881883
} else if (!overViewBtn(s, DX_R) && s2ll (s, ll)) {
882884
// tapped map: set flag to run popup after map finishes or set newDX here if special-tap
883885
if (names_on)
@@ -1715,6 +1717,7 @@ void drawAllSymbols()
17151717
drawADIFSpotsOnMap();
17161718
drawDXPedsOnMap();
17171719
drawHamsatOnMap();
1720+
drawPlanetsOnMap();
17181721
drawStormsOnMap();
17191722
drawLaunchesOnMap();
17201723
drawActiveNetsOnMap();
@@ -1886,10 +1889,7 @@ void drawDEFormatMenu()
18861889
// number of core menu items
18871890
#define N_DEFMT_CORE 8
18881891

1889-
// PLOT_CH_SATACT can't join PANE_0_CH_MASK -- that's a 32-bit bitmask constant and SATACT's
1890-
// ordinal (32) can never fit in one, by the same design as everywhere else PLOTBIT() is used.
1891-
// it's offered as one extra, separately-handled menu item instead.
1892-
MenuItem mitems[N_DEFMT_CORE+N_PANE_0_CH+1] = {
1892+
MenuItem mitems[N_DEFMT_CORE+N_PANE_0_CH] = {
18931893

18941894
// outer menu is whether to display the DE pane or use both DE+DX for a pane choice
18951895
{MENU_1OFN, !SHOWING_PANE_0(), 1, mi, "DE format:", NULL},
@@ -1904,40 +1904,28 @@ void drawDEFormatMenu()
19041904

19051905
{MENU_1OFN, SHOWING_PANE_0(), 1, mi, "Data Panes:", NULL},
19061906

1907-
// bottom submenu is list of possible pane choices, see next.
1908-
// N.B. don't include ones already in play in the top set
1909-
1907+
// bottom submenu is filled below from PANE_0_CH_MASK, including high-word choices.
19101908
};
19111909

1912-
// set and record PANE_0 choices from successive bits in PANE_0_CH_MASK
1913-
uint32_t pane_0_bits = PANE_0_CH_MASK;
1910+
// prepare each suitable Pane 0 choice in PlotChoice order
19141911
PlotChoice menu_ch[N_PANE_0_CH];
1915-
for (int i = 0; i < N_PANE_0_CH; i++) {
1916-
// find and zero out the next bit in mask of possible PANE_0 panes
1917-
int plot_n = 0;
1918-
for (uint32_t bits = pane_0_bits; bits >>= 1; plot_n++)
1912+
int n_menu_ch = 0;
1913+
for (int i = 0; i < PLOT_CH_N; i++) {
1914+
PlotChoice pc = (PlotChoice)i;
1915+
if (!PLOT_CH_IS_REAL(pc) || !(PANE_0_CH_MASK & PLOTBIT(pc)))
19191916
continue;
1920-
pane_0_bits &= ~(1<<plot_n);
1921-
menu_ch[i] = (PlotChoice)plot_n;
1922-
// prepare menu item
1923-
PlotPane pp = findPaneForChoice ((PlotChoice)plot_n);
1924-
bool available = plotChoiceIsAvailable((PlotChoice)plot_n) && (pp == PANE_NONE || pp == PANE_0);
1925-
MenuFieldType type = available ? MENU_AL1OFN : MENU_IGNORE;
1926-
mitems[N_DEFMT_CORE+i] = {type, !!(plot_rotset[PANE_0] & PLOTBIT(plot_n)), 3, Mi, plot_names[plot_n], 0};
1927-
}
1928-
if (pane_0_bits != 0)
1929-
fatalError ("drawDEFormatMenu() %d %d 0x%x\n", pane_0_bits, N_PANE_0_CH, PANE_0_CH_MASK);
1930-
1931-
// extra SATACT item -- can't be represented in plot_rotset (see comment above), so its
1932-
// "currently set" state is determined the same way paneHasChoice() checks a solo choice
1933-
const int SATACT_MI = N_DEFMT_CORE + N_PANE_0_CH;
1934-
{
1935-
PlotPane pp = findPaneForChoice (PLOT_CH_SATACT);
1936-
bool available = plotChoiceIsAvailable (PLOT_CH_SATACT) && (pp == PANE_NONE || pp == PANE_0);
1917+
1918+
menu_ch[n_menu_ch] = pc;
1919+
PlotPane pp = findPaneForChoice (pc);
1920+
bool available = plotChoiceIsAvailable(pc) && (pp == PANE_NONE || pp == PANE_0);
19371921
MenuFieldType type = available ? MENU_AL1OFN : MENU_IGNORE;
1938-
bool is_set = (plot_ch[PANE_0] == PLOT_CH_SATACT && plot_rotset[PANE_0] == 0);
1939-
mitems[SATACT_MI] = {type, is_set, 3, Mi, plot_names[PLOT_CH_SATACT], 0};
1922+
mitems[N_DEFMT_CORE+n_menu_ch] = {
1923+
type, !!(plot_rotset[PANE_0] & PLOTBIT(pc)), 3, Mi, plot_names[pc], 0
1924+
};
1925+
n_menu_ch++;
19401926
}
1927+
if (n_menu_ch != N_PANE_0_CH)
1928+
fatalError ("drawDEFormatMenu() found %d of %d Pane 0 choices", n_menu_ch, N_PANE_0_CH);
19411929

19421930
// create a box for the menu
19431931
SBox menu_b;
@@ -1948,73 +1936,56 @@ void drawDEFormatMenu()
19481936
// run menu
19491937
SBox ok_b;
19501938
MenuInfo menu = {menu_b, ok_b, UF_NOCLOCKS, M_CANCELOK, 1, NARRAY(mitems), mitems};
1951-
if (runMenu (menu)) {
1952-
1953-
// capture and save new state
1954-
1955-
if (mitems[0].set) {
1956-
1957-
// set desired detime format
1958-
1959-
int new_fmt = -1;
1960-
for (int i = 0; i < DETIME_N; i++) {
1961-
if (mitems[i+1].set) {
1962-
new_fmt = i;
1963-
break;
1964-
}
1965-
}
1966-
1967-
// paranoid
1968-
if (new_fmt < 0)
1969-
fatalError ("drawDEFormatMenu: No de fmt");
1970-
1971-
// set fmt and turn off PANE_0
1972-
de_time_fmt = (uint8_t)new_fmt;
1973-
NVWriteUInt8(NV_DE_TIMEFMT, de_time_fmt);
1974-
plot_ch[PANE_0] = PLOT_CH_NONE;
1975-
plot_rotset[PANE_0] = 0;
1939+
if (!runMenu (menu))
1940+
return;
19761941

1977-
} else {
1942+
if (mitems[0].set) {
19781943

1979-
// get new collection of plot choices
1980-
uint32_t new_rotset = 0;
1981-
for (int i = 0; i < N_PANE_0_CH; i++) {
1982-
if (mitems[N_DEFMT_CORE+i].set)
1983-
new_rotset |= PLOTBIT(menu_ch[i]);
1944+
// set desired DE time format and restore the normal DE/DX layout
1945+
int new_fmt = -1;
1946+
for (int i = 0; i < DETIME_N; i++) {
1947+
if (mitems[i+1].set) {
1948+
new_fmt = i;
1949+
break;
19841950
}
1951+
}
1952+
if (new_fmt < 0)
1953+
fatalError ("drawDEFormatMenu: No de fmt");
19851954

1986-
bool satact_set = mitems[SATACT_MI].set;
1987-
1988-
if (satact_set && new_rotset == 0) {
1955+
de_time_fmt = (uint8_t)new_fmt;
1956+
NVWriteUInt8 (NV_DE_TIMEFMT, de_time_fmt);
1957+
restoreNormPANE0();
19891958

1990-
// SATACT alone: solo, non-rotating choice -- can't be represented in plot_rotset
1991-
plot_ch[PANE_0] = PLOT_CH_SATACT;
1992-
plot_rotset[PANE_0] = 0;
1959+
} else {
19931960

1994-
} else if (new_rotset != 0) {
1961+
// collect low- and high-word choices into one in-memory rotation mask
1962+
PlotMask new_rotset = 0;
1963+
for (int i = 0; i < N_PANE_0_CH; i++) {
1964+
if (mitems[N_DEFMT_CORE+i].set)
1965+
new_rotset |= PLOTBIT(menu_ch[i]);
1966+
}
19951967

1996-
// one or more mask-based choices (SATACT, if also checked, can't join a
1997-
// multi-item rotation set the way these can, so it's dropped in that case)
1998-
plot_rotset[PANE_0] = new_rotset;
1968+
if (new_rotset == 0) {
1969+
restoreNormPANE0();
1970+
} else {
1971+
plot_rotset[PANE_0] = new_rotset;
19991972

2000-
// pick any one as current
1973+
// retain the current choice when still selected, otherwise choose the first set bit
1974+
if (!(plot_rotset[PANE_0] & PLOTBIT(plot_ch[PANE_0]))) {
20011975
for (int i = 0; i < PLOT_CH_N; i++) {
20021976
if (plot_rotset[PANE_0] & PLOTBIT(i)) {
2003-
plot_ch[PANE_0] = (PlotChoice) i;
1977+
plot_ch[PANE_0] = (PlotChoice)i;
20041978
break;
20051979
}
20061980
}
20071981
}
1982+
1983+
if (!setPlotChoice (PANE_0, plot_ch[PANE_0]))
1984+
fatalError ("drawDEFormatMenu: can not set Pane 0 choice %d", (int)plot_ch[PANE_0]);
20081985
}
20091986
}
20101987

2011-
// set PANE_0 choice, even if none
2012-
setPlotChoice (PANE_0, plot_ch[PANE_0]);
20131988
logPaneRotSet (PANE_0, plot_ch[PANE_0]);
2014-
2015-
// redraw if normal
2016-
if (!SHOWING_PANE_0())
2017-
restoreNormPANE0();
20181989
}
20191990

20201991
/* resume using nearestPrefix

ESPHamClock/HamClock.h

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ typedef enum {
386386

387387
// N.B. take care that names will fit in menu built by askPaneChoice()
388388
// N.B. names should not include blanks, but _ are changed to blanks for prettier printing
389-
#define PLOTNAMES \
389+
// Keep the original 32 choices at their historic ordinals. EEPROM value 32 remains NONE forever;
390+
// choices added after that sentinel are mapped into the new high rotation word by PLOTBIT().
391+
#define PLOTNAMES_LOW \
390392
X(PLOT_CH_BC, "VOACAP_DEDX") \
391393
X(PLOT_CH_DEWX, "DE_Wx") \
392394
X(PLOT_CH_DXCLUSTER, "DX_Cluster") \
@@ -418,18 +420,23 @@ typedef enum {
418420
X(PLOT_CH_ACTIVENETS, "Nets") \
419421
X(PLOT_CH_LAUNCHES, "Launches") \
420422
X(PLOT_CH_HFCOND, "HF_Bands") \
421-
X(PLOT_CH_VHFCOND, "VHF_Cond") \
423+
X(PLOT_CH_VHFCOND, "VHF_Cond")
424+
425+
#define PLOTNAMES_HIGH \
422426
X(PLOT_CH_SATACT, "Sat_Alerts")
423427

424-
#define X(a,b) a, // expands PLOTNAMES to each enum and comma
428+
#define PLOTNAMES PLOTNAMES_LOW PLOTNAMES_HIGH
429+
430+
#define X(a,b) a, // expand the original low-word choices
425431
typedef enum {
426-
PLOTNAMES
432+
PLOTNAMES_LOW
433+
PLOT_CH_NONE, // fixed EEPROM sentinel: value 32
434+
PLOTNAMES_HIGH // first high-word choice starts at value 33
427435
PLOT_CH_N
428436
} PlotChoice;
429437
#undef X
430438

431-
// reuse count also handy flag for not found
432-
#define PLOT_CH_NONE PLOT_CH_N
439+
static_assert (PLOT_CH_N - 1 <= 64, "PlotMask high word is full");
433440

434441
typedef enum {
435442
PANE_0, // DE/DX overlay
@@ -1597,6 +1604,15 @@ extern Satellite *lookupSatByName (const char *name, int *norad = NULL);
15971604

15981605
extern void drawSatGroupSchedule (void);
15991606
extern void drawSatCoVis (void);
1607+
1608+
/*********************************************************************************************
1609+
*
1610+
* planets.cpp
1611+
*
1612+
*/
1613+
1614+
extern void drawPlanetsOnMap (void);
1615+
extern bool checkPlanetMapTouch (const SCoord &s);
16001616
extern bool setSatFromTLE (const char *name, const char *t1, const char *t2);
16011617
extern bool initSat(void);
16021618
extern bool getSatNow (SatNow &satnow);
@@ -2231,16 +2247,22 @@ extern void plotServerFile (const char *filename, const char title[], const char
22312247

22322248
extern const SBox plot_b[PANE_N]; // box for each pane
22332249
extern PlotChoice plot_ch[PANE_N]; // current choice in each pane, or PLOT_CH_NONE for PANE_0
2234-
extern const char *plot_names[PLOT_CH_N]; // must be in same order as PlotChoice
2235-
extern uint32_t plot_rothold; // bitmask of PlotChoice in rotset but temporarily holding
2236-
extern uint32_t plot_rotset[PANE_N]; // bitmask of each pane's PlotChoice rotation choices
2237-
// N.B. plot_rotset[i] must always include plot_ch[i] unless NONE
2238-
2239-
// plot_rotset/plot_rothold are only 32 bits wide, but PLOT_CH_N may exceed 32 (e.g. PLOT_CH_SATACT).
2240-
// PLOTBIT() maps any PlotChoice >= 32 to 0 instead of performing an out-of-range shift, which both
2241-
// avoids undefined behavior and, as a deliberate side effect, guarantees such choices can never be
2242-
// captured in a rotation set -- i.e. they can never participate in pane auto rotation.
2243-
#define PLOTBIT(pc) ((uint32_t)(pc) < 32 ? (1u << (uint32_t)(pc)) : 0u)
2250+
extern const char *plot_names[PLOT_CH_N]; // indexed by PlotChoice; PLOT_CH_NONE entry is "NONE"
2251+
2252+
typedef uint64_t PlotMask;
2253+
extern PlotMask plot_rothold; // PlotChoice bits temporarily holding rotation
2254+
extern PlotMask plot_rotset[PANE_N]; // each pane's PlotChoice rotation choices
2255+
// N.B. plot_rotset[i] must include plot_ch[i] unless NONE
2256+
2257+
// EEPROM value 32 is permanently reserved for PLOT_CH_NONE. Choices below it keep their original
2258+
// low-word bit numbers; real choices above it are packed down by one so PLOT_CH_SATACT uses bit 32
2259+
// (high-word bit 0), the next new choice uses bit 33, and so on.
2260+
#define PLOT_CH_IS_REAL(pc) ((uint32_t)(pc) < (uint32_t)PLOT_CH_NONE || \
2261+
((uint32_t)(pc) > (uint32_t)PLOT_CH_NONE && \
2262+
(uint32_t)(pc) < (uint32_t)PLOT_CH_N))
2263+
#define PLOTBIT_INDEX(pc) ((uint32_t)(pc) < (uint32_t)PLOT_CH_NONE \
2264+
? (uint32_t)(pc) : (uint32_t)(pc)-1U)
2265+
#define PLOTBIT(pc) (PLOT_CH_IS_REAL(pc) ? (UINT64_C(1) << PLOTBIT_INDEX(pc)) : UINT64_C(0))
22442266

22452267
#define ROTHOLD_SET(pc) (plot_rothold |= PLOTBIT(pc))
22462268
#define ROTHOLD_CLR(pc) (plot_rothold &= ~PLOTBIT(pc))
@@ -2249,15 +2271,18 @@ extern uint32_t plot_rotset[PANE_N]; // bitmask of each pane's PlotChoice
22492271
#define SHOWING_PANE_0() (plot_ch[PANE_0] != PLOT_CH_NONE)
22502272
#define BOX_IS_PANE_0(b) ((b).w == PLOTBOX0_W && (b).h == PLOTBOX0_H)
22512273

2252-
// bit mask of plot choices suitable for PANE_0
2253-
#define PANE_0_CH_MASK ((1<<PLOT_CH_DXCLUSTER) | (1<<PLOT_CH_CONTESTS) | (1<<PLOT_CH_ADIF) \
2254-
| (1<<PLOT_CH_ONTA) | (1<<PLOT_CH_DXPEDS) | (1<<PLOT_CH_ACTIVENETS) | (1<<PLOT_CH_LAUNCHES))
2274+
// bit mask of plot choices suitable for PANE_0, including high-word choices
2275+
#define PANE_0_CH_MASK (PLOTBIT(PLOT_CH_DXCLUSTER) | PLOTBIT(PLOT_CH_CONTESTS) | \
2276+
PLOTBIT(PLOT_CH_ADIF) | PLOTBIT(PLOT_CH_ONTA) | \
2277+
PLOTBIT(PLOT_CH_DXPEDS) | PLOTBIT(PLOT_CH_ACTIVENETS) | \
2278+
PLOTBIT(PLOT_CH_LAUNCHES) | PLOTBIT(PLOT_CH_SATACT))
22552279

22562280
// compute number of bits set in PANE_0_CH_MASK at compile time :-)
22572281
// https://stackoverflow.com/questions/109023/count-the-number-of-set-bits-in-a-32-bit-integer
22582282
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
22592283
#define NBITS_SET(v) ((((((((v) - (((v) >> 1) & 0x55555555)) & 0x33333333) + ((((v) - (((v) >> 1) & 0x55555555)) >> 2) & 0x33333333)) + (((((v) - (((v) >> 1) & 0x55555555)) & 0x33333333) + ((((v) - (((v) >> 1) & 0x55555555)) >> 2) & 0x33333333)) >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24)
2260-
#define N_PANE_0_CH ((int)(NBITS_SET((uint32_t)PANE_0_CH_MASK)))
2284+
#define N_PANE_0_CH ((int)(NBITS_SET((uint32_t)PANE_0_CH_MASK) + \
2285+
NBITS_SET((uint32_t)(PANE_0_CH_MASK >> 32))))
22612286

22622287
#define PLOT_ROTWARN_DT 4 // show rotation about to occur, secs
22632288

@@ -2278,7 +2303,7 @@ extern void savePlotOps(void);
22782303
extern int tickmarks (float min, float max, int numdiv, float ticks[]);
22792304
extern bool isPaneRotating (PlotPane pp);
22802305
extern bool isSpecialPaneRotating (PlotPane pp);
2281-
extern bool enforceCDownAlone (const SBox &box, uint32_t rotset);
2306+
extern bool enforceCDownAlone (const SBox &box, PlotMask rotset);
22822307
extern bool overHoverPane (const SCoord &s);
22832308
extern void restoreNormPANE0(void);
22842309

@@ -2771,6 +2796,7 @@ extern bool useOSTime (void);
27712796
extern bool showNewDXDEWx(void);
27722797
extern int getPaneRotationPeriod (void);
27732798
extern bool showPIP(void);
2799+
extern bool showPlanets(void);
27742800
extern bool autoMap(void);
27752801
extern int getMapRotationPeriod(void);
27762802
extern GrayDpy_t getGrayDisplay(void);

ESPHamClock/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ OBJS = \
144144
ontheair.o \
145145
parsespot.o \
146146
passwd.o \
147+
planets.o \
147148
plot.o \
148149
plotmap.o \
149150
plotmgmnt.o \

ESPHamClock/hamsat.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,10 @@ static void drawHamsatVisAlerts (const SBox &box)
453453
char cd[8];
454454
formatCountdown (a.aos_at, now, cd, sizeof(cd));
455455
char line[24];
456-
snprintf (line, sizeof(line), "%-7.7s%-6.6s%s", a.callsign, a.satname, cd);
456+
if (box.w < PLOTBOX123_W)
457+
snprintf (line, sizeof(line), "%-6.6s%-5.5s%s", a.callsign, a.satname, cd);
458+
else
459+
snprintf (line, sizeof(line), "%-7.7s%-6.6s%s", a.callsign, a.satname, cd);
457460
tft.setTextColor (a.is_workable ? RA8875_YELLOW : RA8875_WHITE);
458461
tft.setCursor (x + badge_w, y);
459462
tft.print (line);
@@ -477,10 +480,16 @@ static void drawHamsatPane (const SBox &box)
477480
tft.setCursor (box.x + (box.w-pw)/2, box.y + PANETITLE_H);
478481
tft.print (title);
479482

480-
// subtitle: source + whether personalized
483+
// subtitle: source + whether personalized. maxStringW() truncates its argument in place,
484+
// so this must be writable storage, never a cast-away-const string literal. Pane 0 is also
485+
// narrower than the normal panes, so use a compact form there.
481486
selectFontStyle (LIGHT_FONT, FAST_FONT);
482-
const char *sub = hamsat_key[0] ? "https://hams.at (has key)" : "https://hams.at (no key)";
483-
uint16_t sw = maxStringW ((char*)sub, box.w-2);
487+
char sub[40];
488+
if (box.w < PLOTBOX123_W)
489+
snprintf (sub, sizeof(sub), "hams.at (%s)", hamsat_key[0] ? "key" : "no key");
490+
else
491+
snprintf (sub, sizeof(sub), "https://hams.at (%s)", hamsat_key[0] ? "has key" : "no key");
492+
uint16_t sw = maxStringW (sub, box.w-2);
484493
tft.setTextColor (hamsat_key[0] ? RA8875_WHITE : RGB565(180,140,60));
485494
tft.setCursor (box.x + (box.w-sw)/2, box.y + SUBTITLE_Y0);
486495
tft.print (sub);

ESPHamClock/nvramenum.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,18 @@ typedef enum {
370370
// 251
371371
NV_SATGROUP, // newline-separated satellite names for group schedule
372372

373+
// 252
374+
NV_SHOWPLANETS, // whether to show planets on the map
375+
376+
// 253 -- retain the experimental marker so already-patched EEPROM files remain compatible
377+
NV_PLOTSCHEMA, // reserved plot settings schema marker
378+
379+
// 254 -- appended so all prior EEPROM addresses remain unchanged
380+
NV_PANE0ROTSET_HI, // high 32 bits of pane 0 PlotChoice rotation mask
381+
NV_PANE1ROTSET_HI, // high 32 bits of pane 1 PlotChoice rotation mask
382+
NV_PANE2ROTSET_HI, // high 32 bits of pane 2 PlotChoice rotation mask
383+
NV_PANE3ROTSET_HI, // high 32 bits of pane 3 PlotChoice rotation mask
384+
373385
NV_N
374386

375387
} NV_Name;

ESPHamClock/nvramsize.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,18 @@ static const uint8_t nv_sizes[NV_N] = {
373373
// 251
374374
NV_SATGROUP_LEN, // NV_SATGROUP
375375

376+
// 252
377+
1, // NV_SHOWPLANETS
378+
379+
// 253 -- retained compatibility marker
380+
1, // NV_PLOTSCHEMA
381+
382+
// 254 -- high words are appended; no existing item moves
383+
4, // NV_PANE0ROTSET_HI
384+
4, // NV_PANE1ROTSET_HI
385+
4, // NV_PANE2ROTSET_HI
386+
4, // NV_PANE3ROTSET_HI
387+
376388
};
377389

378390
#endif // _NVRAMSIZE_H

0 commit comments

Comments
 (0)