Skip to content

Commit c671673

Browse files
authored
Merge pull request #236 from openhamclock/issue-121
Update YO3GND's PR 124 Thanks YO3GND!
2 parents 62a0662 + 37aca78 commit c671673

19 files changed

Lines changed: 183 additions & 24 deletions

ESPHamClock/ArduinoLib/Arduino.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// max cpu usage, throttle with -t
1818
#define DEF_CPU_USAGE 0.8F
1919
static float max_cpu_usage = DEF_CPU_USAGE;
20+
// even at 100% throttle, don't busy-spin the host when loop() has nothing to do
21+
#define DEF_MIN_IDLE_LOOP_US 1000
2022

2123
char **our_argv; // our argv for restarting
2224
std::string our_dir; // our storage directory, including trailing /
@@ -737,11 +739,21 @@ int main (int ac, char *av[])
737739
// this loop by itself would run 100% CPU so offer a means to be a better citizen and throttle back
738740
printf ("Starting Arduino loop()\n");
739741

742+
#define TVUSEC(tv0,tv1) (((tv1).tv_sec-(tv0).tv_sec)*1000000 + ((tv1).tv_usec-(tv0).tv_usec))
743+
740744
if (max_cpu_usage == 1) {
741745

742-
// pure loop
743-
for (;;)
746+
// pure loop, but still yield briefly when loop() returns faster than our minimum idle cadence.
747+
for (;;) {
748+
struct timeval tv0;
749+
gettimeofday (&tv0, NULL);
744750
loop();
751+
struct timeval tv1;
752+
gettimeofday (&tv1, NULL);
753+
int loop_us = TVUSEC(tv0, tv1);
754+
if (loop_us < DEF_MIN_IDLE_LOOP_US)
755+
usleep (DEF_MIN_IDLE_LOOP_US - loop_us);
756+
}
745757

746758
} else {
747759

@@ -751,8 +763,6 @@ int main (int ac, char *av[])
751763
const int sleep_dt = 10; // sleep adjustment, usecs
752764
const int max_sleep = 50000; // max sleep each loop, usecs
753765

754-
#define TVUSEC(tv0,tv1) (((tv1).tv_sec-(tv0).tv_sec)*1000000 + ((tv1).tv_usec-(tv0).tv_usec))
755-
756766
for (;;) {
757767

758768
// get time and usage before calling loop()

ESPHamClock/ESPHamClock.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ void newDX (LatLong &ll, const char grid[MAID_CHARLEN], const char *ovprefix)
10421042

10431043
// enable great path unless very close to DE
10441044
dxpath_time = ERAD_M * dx_ll.GSD(de_ll) > DEDX_MINPATH ? millis() : 0;
1045+
scheduleMapRedraw();
10451046

10461047
// just call initEarthMap??
10471048
drawDXInfo ();

ESPHamClock/HamClock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,9 @@ extern void drawMapCoord (uint16_t x, uint16_t y);
15011501
extern void drawSun (void);
15021502
extern void drawMoon (void);
15031503
extern void drawDXInfo (void);
1504+
extern void scheduleMapRedraw (void);
1505+
extern void mm_redraw(void);
1506+
extern bool mm_up (void);
15041507
extern void ll2s (const LatLong &ll, SCoord &s, uint8_t edge);
15051508
extern void ll2s (float lat, float lng, SCoord &s, uint8_t edge);
15061509
extern void ll2sRaw (const LatLong &ll, SCoord &s, uint8_t edge);

ESPHamClock/adif.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static bool showing_set_adif; // set when not checking
8585
static bool newfile_pending; // set when find new file while scrolled away
8686
static FileSignature fsig; // used to decide whether to read file again
8787
static int n_adif_bad; // n bad spots found, global to maintain context
88+
static uint32_t adif_generation; // increment whenever adif_spots is reloaded
8889

8990

9091
/* save sort and file name
@@ -391,6 +392,7 @@ void loadADIFFile (GenReader &gr, int &n_good, int &n_bad)
391392

392393
// note new source type ready
393394
showing_set_adif = gr.isClient();
395+
adif_generation++;
394396

395397
// final message
396398
mapMsg (1000, "Loaded ADIF file");
@@ -412,7 +414,10 @@ void updateADIF (const SBox &box, bool refresh)
412414
}
413415

414416
// check for changed file
417+
uint32_t prev_generation = adif_generation;
415418
freshenADIFFile();
419+
if (adif_generation != prev_generation && findPaneForChoice(PLOT_CH_ADIF) != PANE_NONE)
420+
scheduleMapRedraw();
416421

417422
// update symbol and hold
418423
adif_ss.drawNewSpotsSymbol (newfile_pending, false);

ESPHamClock/dxcluster.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,11 +1009,14 @@ bool updateDXCluster (const SBox &box, bool fresh)
10091009

10101010
if (dxc_ss.atNewest()) {
10111011
// rebuild displayed spots list when master list changes or oldest spot ages out
1012-
if (dxc_spots_changed || (n_dxspots > 0 && dxc_spots[0].spotted < myNow() - MAXKEEP_DT)) {
1012+
bool map_spots_changed = dxc_spots_changed;
1013+
if (map_spots_changed || (n_dxspots > 0 && dxc_spots[0].spotted < myNow() - MAXKEEP_DT)) {
10131014
rebuildDXWatchList();
10141015
dxc_spots_changed = false;
10151016
dxc_ss.drawNewSpotsSymbol (false, false); // insure off
10161017
scrolledaway_tm = 0;
1018+
if (findPaneForChoice(PLOT_CH_DXCLUSTER) != PANE_NONE)
1019+
scheduleMapRedraw();
10171020
}
10181021
ROTHOLD_CLR(PLOT_CH_DXCLUSTER); // resume rotation
10191022
} else {

ESPHamClock/dxpeds.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static DXPCredit *credits; // malloced list of each credit
5757
static int n_credits; // n credits
5858
static ADIFWList *adif_worked; // malloced list of ADIF worked band+mode
5959
static int n_adif_worked; // n adif_worked[]
60+
static bool dxpeds_spots_changed; // set when dxcluster spot state changes map markers
6061

6162

6263
// NV_DXPEDS bits
@@ -822,9 +823,15 @@ bool updateDXPeds (const SBox &box, bool fresh)
822823
}
823824
}
824825

825-
if (checkActiveDXPeds() || fresh)
826+
bool markers_changed = checkActiveDXPeds() || fresh;
827+
if (markers_changed)
826828
drawDXPedsPane (box);
827829

830+
if ((markers_changed || dxpeds_spots_changed) && findPaneForChoice(PLOT_CH_DXPEDS) != PANE_NONE) {
831+
scheduleMapRedraw();
832+
dxpeds_spots_changed = false;
833+
}
834+
828835
} else {
829836

830837
plotMessage (box, DXPEDS_COLOR, "DXPeds error");
@@ -995,8 +1002,10 @@ bool getClosestDXPed (LatLong &ll, DXPedEntry *&dxp)
9951002
*/
9961003
void tellDXPedsSpotChanged (void)
9971004
{
998-
if (findPaneForChoice (PLOT_CH_DXPEDS) != PANE_NONE && dxp_ss.atNewest())
1005+
if (findPaneForChoice (PLOT_CH_DXPEDS) != PANE_NONE && dxp_ss.atNewest()) {
1006+
dxpeds_spots_changed = true;
9991007
scheduleNewPlot (PLOT_CH_DXPEDS);
1008+
}
10001009
}
10011010

10021011

ESPHamClock/earthmap.cpp

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,59 @@ uint8_t show_lp; // display long path, else short
3838

3939
#define GRAYLINE_COS (-0.208F) // cos(90 + grayline angle), we use 12 degs
4040
#define GRAYLINE_POW (0.75F) // cos power exponent, sqrt is too severe, 1 is too gradual
41-
static SCoord moremap_s; // drawMoreEarth() scanning location
41+
static SCoord moremap_s; // drawMoreEarth() scanning location
42+
static bool moremap_active; // whether a map sweep is currently in progress
43+
static uint32_t moremap_generation; // incremented whenever a new sweep is explicitly scheduled
44+
static uint32_t next_redraw_ms; // next periodic redraw deadline once a sweep completes
45+
static bool mm_p; // mouse moved during a map sweep; redraw again when done
46+
static uint32_t mm_ms; // throttle mouse-driven city hover redraws
47+
static bool mp_a; // map popup menu currently running
48+
static bool mv_a; // map view menu currently running
49+
#define EARTH_REDRAW_INTERVAL_MS 30000U // redraw slow-changing map overlays at a conservative cadence
4250

4351
// cached grid colors
4452
uint16_t EARTH_GRIDC, EARTH_GRIDC00; // main and highlighted
4553

4654
// flag to defer drawing over map until opportune time:
4755
bool mapmenu_pending;
4856

57+
static void updateCircumstances();
58+
59+
/* request a fresh visual sweep of the current map without reloading its source data.
60+
* used to clear old overlays and redraw moving symbols on demand.
61+
*/
62+
void scheduleMapRedraw (void)
63+
{
64+
moremap_s.x = 0;
65+
moremap_s.y = map_b.y;
66+
moremap_active = true;
67+
next_redraw_ms = 0;
68+
moremap_generation++;
69+
}
70+
71+
72+
73+
void mm_redraw (void)
74+
{
75+
uint32_t now_ms = millis();
76+
77+
// City hover is cursor-driven. Do not restart an active progressive map sweep;
78+
// remember that another sweep is needed and start it as soon as the current one finishes.
79+
if (now_ms - mm_ms < 33U || moremap_active) {
80+
mm_p = true;
81+
return;
82+
}
83+
84+
mm_p = false;
85+
scheduleMapRedraw();
86+
mm_ms = now_ms;
87+
}
88+
89+
bool mm_up (void)
90+
{
91+
return (mp_a || mv_a);
92+
}
93+
4994
// grid spacing, degrees
5095
#define LL_LAT_GRID 15
5196
#define LL_LNG_GRID 15
@@ -447,7 +492,10 @@ static void drawMapPopup(void)
447492

448493
// go
449494
MenuInfo menu = {menu_b, ok_b, UF_CLOCKSOK, M_CANCELOK, 1, n_menu, mitems};
450-
if (runMenu (menu)) {
495+
mp_a = true;
496+
bool ok = runMenu (menu);
497+
mp_a = false;
498+
if (ok) {
451499
// init copy for changes
452500
PanZoom new_pz = pan_zoom;
453501

@@ -929,9 +977,11 @@ static void drawMapMenu()
929977
// run menu
930978
SBox ok_b;
931979
MenuInfo menu = {menu_b, ok_b, UF_CLOCKSOK, M_CANCELOK, 1, MI_N, mitems};
932-
bool menu_ok = runMenu (menu);
980+
mv_a = true;
981+
bool ok = runMenu (menu);
982+
mv_a = false;
933983

934-
if (menu_ok) {
984+
if (ok) {
935985

936986

937987
// build new map_rotset
@@ -1118,18 +1168,43 @@ void initEarthMap()
11181168
updateZoneSCoords(ZONE_CQ);
11191169
updateZoneSCoords(ZONE_ITU);
11201170

1121-
// init scan line in map_b
1122-
moremap_s.x = 0; // avoid updateCircumstances() first call to drawMoreEarth()
1123-
moremap_s.y = map_b.y;
1124-
11251171
// now main loop can resume with drawMoreEarth()
1172+
scheduleMapRedraw();
11261173
}
11271174

11281175
/* display another earth map row at mmoremap_s.
11291176
*/
11301177
void drawMoreEarth()
11311178
{
1179+
if (!moremap_active) {
1180+
uint32_t now_ms = millis();
1181+
bool mm_due = mm_p && now_ms - mm_ms >= 33U;
1182+
bool map_due = (int32_t)(now_ms - next_redraw_ms) >= 0;
1183+
1184+
// Only consume deferred overlays while the map is stable. If a redraw is
1185+
// due now, leave them pending so the fresh map does not immediately paint
1186+
// over them before the end-of-sweep handlers run.
1187+
if (!mm_due && !map_due) {
1188+
if (mapmenu_pending) {
1189+
drawMapMenu();
1190+
mapmenu_pending = false;
1191+
}
1192+
if (map_popup.pending) {
1193+
drawMapPopup();
1194+
map_popup.pending = false;
1195+
}
1196+
return;
1197+
}
11321198

1199+
if (mm_due) {
1200+
mm_p = false;
1201+
mm_ms = now_ms;
1202+
}
1203+
updateCircumstances();
1204+
scheduleMapRedraw();
1205+
}
1206+
1207+
uint32_t sweep_generation = moremap_generation;
11331208
uint16_t last_x = map_b.x + EARTH_W - 1;
11341209

11351210
// draw next row
@@ -1167,9 +1242,19 @@ void drawMoreEarth()
11671242
// rotate?
11681243
checkBGMap();
11691244

1170-
// prep for next
1171-
updateCircumstances();
1172-
moremap_s.y = map_b.y;
1245+
// a menu action or map refresh may have already restarted the sweep.
1246+
if (moremap_generation != sweep_generation)
1247+
return;
1248+
1249+
// otherwise stop here and wait until the next periodic or explicit redraw request.
1250+
moremap_active = false;
1251+
1252+
if (mm_p) {
1253+
mm_p = false;
1254+
mm_ms = millis();
1255+
scheduleMapRedraw();
1256+
}
1257+
next_redraw_ms = millis() + EARTH_REDRAW_INTERVAL_MS;
11731258

11741259
// #define TIME_MAP_DRAW // RBF
11751260
#if defined(TIME_MAP_DRAW)

ESPHamClock/hamclock-fb0-800x480

7.76 MB
Binary file not shown.

ESPHamClock/hamclock-web-800x480

7.73 MB
Binary file not shown.

ESPHamClock/infobox.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,12 @@ static bool drawIB_City (LatLong &ll, SCoord &ms, const SBox &info_b, uint16_t &
157157
ll = city_ll;
158158
ms = city_ms;
159159
names_w = max_cl * 6; // * font width
160+
uint16_t names_x = map_b.x + (map_b.w-names_w)/2;
160161
// dot
161162
tft.fillCircle (city_ms.x, city_ms.y, CDOT_R, RA8875_RED);
162-
// name, assuming background is already erased
163+
// name background
164+
tft.fillRect (names_x, names_y, names_w, 14, RA8875_BLACK);
165+
// name
163166
uint16_t c_w = getTextWidth (city);
164167
tft.setCursor (map_b.x + (map_b.w-c_w)/2, names_y + 3);
165168
tft.print(city);

0 commit comments

Comments
 (0)