|
5 | 5 | #include "HamClock.h" |
6 | 6 |
|
7 | 7 | // ADS-B airplane icon -- opens https://adsb.lol, sits just below the MOTD mailbox icon |
8 | | -#define ADSB_ICON_W 14 |
9 | | -#define ADSB_ICON_H 14 |
| 8 | +#define ADSB_ICON_W 20 |
| 9 | +#define ADSB_ICON_H 20 |
| 10 | +#define ADSB_ICON_BPR ((ADSB_ICON_W + 7)/8) // bytes per bitmap row |
10 | 11 | #define ADSB_ICON_GAP 6 // gap below MOTD icon |
| 12 | +#define ADSB_ICON_C GRAY |
11 | 13 | SBox adsb_btn_b; |
12 | 14 |
|
| 15 | +// top-down airliner silhouette, one bit per pixel. zero bits are transparent. |
| 16 | +// rows are packed left-to-right, least-significant bit first, like santa.cpp. |
| 17 | +static const uint8_t adsb_plane[ADSB_ICON_BPR*ADSB_ICON_H] PROGMEM = { |
| 18 | + 0x00, 0x06, 0x00, |
| 19 | + 0x00, 0x06, 0x00, |
| 20 | + 0x00, 0x06, 0x00, |
| 21 | + 0x00, 0x06, 0x00, |
| 22 | + 0x00, 0x06, 0x00, |
| 23 | + 0x00, 0x06, 0x00, |
| 24 | + 0x00, 0x06, 0x00, |
| 25 | + 0x80, 0x1f, 0x00, |
| 26 | + 0xc0, 0x3f, 0x00, |
| 27 | + 0xf0, 0xff, 0x00, |
| 28 | + 0xf8, 0xff, 0x01, |
| 29 | + 0x1e, 0x86, 0x07, |
| 30 | + 0x03, 0x06, 0x0c, |
| 31 | + 0x00, 0x06, 0x00, |
| 32 | + 0x00, 0x06, 0x00, |
| 33 | + 0x00, 0x06, 0x00, |
| 34 | + 0x00, 0x06, 0x00, |
| 35 | + 0x00, 0x0f, 0x00, |
| 36 | + 0xe0, 0x7f, 0x00, |
| 37 | + 0x00, 0x0f, 0x00, |
| 38 | +}; |
| 39 | + |
13 | 40 | // format flags |
14 | 41 | uint8_t de_time_fmt; // one of DETIME_* |
15 | 42 | uint8_t desrss, dxsrss; // show actual de/dx sun rise/set else time to |
@@ -89,31 +116,24 @@ static void drawUTCButton() |
89 | 116 | */ |
90 | 117 | void drawADSBIcon() |
91 | 118 | { |
92 | | - adsb_btn_b.x = motd_btn_b.x; |
| 119 | + // center the wider airplane below the mailbox while retaining one clickable bounding box. |
| 120 | + adsb_btn_b.x = motd_btn_b.x - (ADSB_ICON_W - motd_btn_b.w)/2; |
93 | 121 | adsb_btn_b.y = motd_btn_b.y + motd_btn_b.h + ADSB_ICON_GAP; |
94 | 122 | adsb_btn_b.w = ADSB_ICON_W; |
95 | 123 | adsb_btn_b.h = ADSB_ICON_H; |
96 | 124 |
|
| 125 | + // erase the old icon, then paint only set bitmap pixels; zero bits remain background. |
97 | 126 | tft.fillRect (adsb_btn_b.x, adsb_btn_b.y, adsb_btn_b.w, adsb_btn_b.h, RA8875_BLACK); |
98 | | - |
99 | | - // airplane silhouette: fuselage nose-to-tail, wide wings ~1/3 back from the nose, a smaller |
100 | | - // tail stabilizer near the back -- the classic top-down airplane pictogram, not a paper dart. |
101 | | - // no icon font available, so this is built from basic line primitives, same approach |
102 | | - // drawMOTDIcon() uses for its envelope shape. |
103 | | - const uint16_t x = adsb_btn_b.x + 1; |
104 | | - const uint16_t y = adsb_btn_b.y + 1; |
105 | | - const uint16_t w = 12; |
106 | | - const uint16_t h = 12; |
107 | | - const uint16_t col = GRAY; |
108 | | - |
109 | | - uint16_t nose_x = x + w, tail_x = x, mid_y = y + h/2; |
110 | | - tft.drawLine (tail_x, mid_y, nose_x, mid_y, col); // fuselage |
111 | | - tft.drawLine (nose_x, mid_y, nose_x-3, mid_y-1, col); // nose taper |
112 | | - tft.drawLine (nose_x, mid_y, nose_x-3, mid_y+1, col); |
113 | | - uint16_t wing_x = x + (w*5)/8; |
114 | | - tft.drawLine (wing_x, y, wing_x, y+h-1, col); // main wings |
115 | | - uint16_t tail_wing_x = x + w/6; |
116 | | - tft.drawLine (tail_wing_x, mid_y-2, tail_wing_x, mid_y+2, col); // tail stabilizer |
| 127 | + for (uint16_t row = 0; row < ADSB_ICON_H; row++) { |
| 128 | + for (uint16_t byte_col = 0; byte_col < ADSB_ICON_BPR; byte_col++) { |
| 129 | + uint8_t bits = pgm_read_byte (&adsb_plane[row*ADSB_ICON_BPR + byte_col]); |
| 130 | + for (uint16_t bit = 0; bit < 8; bit++) { |
| 131 | + uint16_t col = 8*byte_col + bit; |
| 132 | + if (col < ADSB_ICON_W && (bits & (1U << bit))) |
| 133 | + tft.drawPixel (adsb_btn_b.x + col, adsb_btn_b.y + row, ADSB_ICON_C); |
| 134 | + } |
| 135 | + } |
| 136 | + } |
117 | 137 | } |
118 | 138 |
|
119 | 139 | /* function given to TimeLib's setSyncProvider() to resync its time base occasionally. |
|
0 commit comments