acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Clock.ino (11651B)

      1 /*
      2    Arduino Watch Lite Version
      3    You may find full version at: https://github.com/moononournation/ArduinoWatch
      4 */
      5 
      6 /*******************************************************************************
      7  * Start of Arduino_GFX setting
      8  * 
      9  * Arduino_GFX try to find the settings depends on selected board in Arduino IDE
     10  * Or you can define the display dev kit not in the board list
     11  * Defalult pin list for non display dev kit:
     12  * Arduino Nano, Micro and more: CS:  9, DC:  8, RST:  7, BL:  6, SCK: 13, MOSI: 11, MISO: 12
     13  * ESP32 various dev board     : CS:  5, DC: 27, RST: 33, BL: 22, SCK: 18, MOSI: 23, MISO: nil
     14  * ESP32-C3 various dev board  : CS:  7, DC:  2, RST:  1, BL:  3, SCK:  4, MOSI:  6, MISO: nil
     15  * ESP32-S2 various dev board  : CS: 34, DC: 38, RST: 33, BL: 21, SCK: 36, MOSI: 35, MISO: nil
     16  * ESP32-S3 various dev board  : CS: 40, DC: 41, RST: 42, BL: 48, SCK: 36, MOSI: 35, MISO: nil
     17  * ESP8266 various dev board   : CS: 15, DC:  4, RST:  2, BL:  5, SCK: 14, MOSI: 13, MISO: 12
     18  * Raspberry Pi Pico dev board : CS: 17, DC: 27, RST: 26, BL: 28, SCK: 18, MOSI: 19, MISO: 16
     19  * RTL8720 BW16 old patch core : CS: 18, DC: 17, RST:  2, BL: 23, SCK: 19, MOSI: 21, MISO: 20
     20  * RTL8720_BW16 Official core  : CS:  9, DC:  8, RST:  6, BL:  3, SCK: 10, MOSI: 12, MISO: 11
     21  * RTL8722 dev board           : CS: 18, DC: 17, RST: 22, BL: 23, SCK: 13, MOSI: 11, MISO: 12
     22  * RTL8722_mini dev board      : CS: 12, DC: 14, RST: 15, BL: 13, SCK: 11, MOSI:  9, MISO: 10
     23  * Seeeduino XIAO dev board    : CS:  3, DC:  2, RST:  1, BL:  0, SCK:  8, MOSI: 10, MISO:  9
     24  * Teensy 4.1 dev board        : CS: 39, DC: 41, RST: 40, BL: 22, SCK: 13, MOSI: 11, MISO: 12
     25  ******************************************************************************/
     26 #include <Arduino_GFX_Library.h>
     27 
     28 #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
     29 
     30 /* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
     31 #if defined(DISPLAY_DEV_KIT)
     32 Arduino_GFX *gfx = create_default_Arduino_GFX();
     33 #else /* !defined(DISPLAY_DEV_KIT) */
     34 
     35 /* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
     36 Arduino_DataBus *bus = create_default_Arduino_DataBus();
     37 
     38 /* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
     39 Arduino_GFX *gfx = new Arduino_ILI9341(bus, DF_GFX_RST, 0 /* rotation */, false /* IPS */);
     40 
     41 #endif /* !defined(DISPLAY_DEV_KIT) */
     42 /*******************************************************************************
     43  * End of Arduino_GFX setting
     44  ******************************************************************************/
     45 
     46 #define BACKGROUND BLACK
     47 #define MARK_COLOR WHITE
     48 #define SUBMARK_COLOR DARKGREY // LIGHTGREY
     49 #define HOUR_COLOR WHITE
     50 #define MINUTE_COLOR BLUE // LIGHTGREY
     51 #define SECOND_COLOR RED
     52 
     53 #define SIXTIETH 0.016666667
     54 #define TWELFTH 0.08333333
     55 #define SIXTIETH_RADIAN 0.10471976
     56 #define TWELFTH_RADIAN 0.52359878
     57 #define RIGHT_ANGLE_RADIAN 1.5707963
     58 
     59 static uint8_t conv2d(const char *p)
     60 {
     61     uint8_t v = 0;
     62     return (10 * (*p - '0')) + (*++p - '0');
     63 }
     64 
     65 static int16_t w, h, center;
     66 static int16_t hHandLen, mHandLen, sHandLen, markLen;
     67 static float sdeg, mdeg, hdeg;
     68 static int16_t osx = 0, osy = 0, omx = 0, omy = 0, ohx = 0, ohy = 0; // Saved H, M, S x & y coords
     69 static int16_t nsx, nsy, nmx, nmy, nhx, nhy;                         // H, M, S x & y coords
     70 static int16_t xMin, yMin, xMax, yMax;                               // redraw range
     71 static int16_t hh, mm, ss;
     72 static unsigned long targetTime; // next action time
     73 
     74 static int16_t *cached_points;
     75 static uint16_t cached_points_idx = 0;
     76 static int16_t *last_cached_point;
     77 
     78 void setup(void)
     79 {
     80     gfx->begin();
     81     gfx->fillScreen(BACKGROUND);
     82 
     83 #ifdef GFX_BL
     84     pinMode(GFX_BL, OUTPUT);
     85     digitalWrite(GFX_BL, HIGH);
     86 #endif
     87 
     88     // init LCD constant
     89     w = gfx->width();
     90     h = gfx->height();
     91     if (w < h)
     92     {
     93         center = w / 2;
     94     }
     95     else
     96     {
     97         center = h / 2;
     98     }
     99     hHandLen = center * 3 / 8;
    100     mHandLen = center * 2 / 3;
    101     sHandLen = center * 5 / 6;
    102     markLen = sHandLen / 6;
    103     cached_points = (int16_t *)malloc((hHandLen + 1 + mHandLen + 1 + sHandLen + 1) * 2 * 2);
    104 
    105     // Draw 60 clock marks
    106     draw_round_clock_mark(
    107     // draw_square_clock_mark(
    108         center - markLen, center,
    109         center - (markLen * 2 / 3), center,
    110         center - (markLen / 2), center);
    111 
    112     hh = conv2d(__TIME__);
    113     mm = conv2d(__TIME__ + 3);
    114     ss = conv2d(__TIME__ + 6);
    115 
    116     targetTime = ((millis() / 1000) + 1) * 1000;
    117 }
    118 
    119 void loop()
    120 {
    121     unsigned long cur_millis = millis();
    122     if (cur_millis >= targetTime)
    123     {
    124         targetTime += 1000;
    125         ss++; // Advance second
    126         if (ss == 60)
    127         {
    128             ss = 0;
    129             mm++; // Advance minute
    130             if (mm > 59)
    131             {
    132                 mm = 0;
    133                 hh++; // Advance hour
    134                 if (hh > 23)
    135                 {
    136                     hh = 0;
    137                 }
    138             }
    139         }
    140     }
    141 
    142     // Pre-compute hand degrees, x & y coords for a fast screen update
    143     sdeg = SIXTIETH_RADIAN * ((0.001 * (cur_millis % 1000)) + ss); // 0-59 (includes millis)
    144     nsx = cos(sdeg - RIGHT_ANGLE_RADIAN) * sHandLen + center;
    145     nsy = sin(sdeg - RIGHT_ANGLE_RADIAN) * sHandLen + center;
    146     if ((nsx != osx) || (nsy != osy))
    147     {
    148         mdeg = (SIXTIETH * sdeg) + (SIXTIETH_RADIAN * mm); // 0-59 (includes seconds)
    149         hdeg = (TWELFTH * mdeg) + (TWELFTH_RADIAN * hh);   // 0-11 (includes minutes)
    150         mdeg -= RIGHT_ANGLE_RADIAN;
    151         hdeg -= RIGHT_ANGLE_RADIAN;
    152         nmx = cos(mdeg) * mHandLen + center;
    153         nmy = sin(mdeg) * mHandLen + center;
    154         nhx = cos(hdeg) * hHandLen + center;
    155         nhy = sin(hdeg) * hHandLen + center;
    156 
    157         // redraw hands
    158         redraw_hands_cached_draw_and_erase();
    159 
    160         ohx = nhx;
    161         ohy = nhy;
    162         omx = nmx;
    163         omy = nmy;
    164         osx = nsx;
    165         osy = nsy;
    166 
    167         delay(1);
    168     }
    169 }
    170 
    171 void draw_round_clock_mark(int16_t innerR1, int16_t outerR1, int16_t innerR2, int16_t outerR2, int16_t innerR3, int16_t outerR3)
    172 {
    173   float x, y;
    174   int16_t x0, x1, y0, y1, innerR, outerR;
    175   uint16_t c;
    176 
    177   for (uint8_t i = 0; i < 60; i++)
    178   {
    179     if ((i % 15) == 0)
    180     {
    181       innerR = innerR1;
    182       outerR = outerR1;
    183       c = MARK_COLOR;
    184     }
    185     else if ((i % 5) == 0)
    186     {
    187       innerR = innerR2;
    188       outerR = outerR2;
    189       c = MARK_COLOR;
    190     }
    191     else
    192     {
    193       innerR = innerR3;
    194       outerR = outerR3;
    195       c = SUBMARK_COLOR;
    196     }
    197 
    198     mdeg = (SIXTIETH_RADIAN * i) - RIGHT_ANGLE_RADIAN;
    199     x = cos(mdeg);
    200     y = sin(mdeg);
    201     x0 = x * outerR + center;
    202     y0 = y * outerR + center;
    203     x1 = x * innerR + center;
    204     y1 = y * innerR + center;
    205 
    206     gfx->drawLine(x0, y0, x1, y1, c);
    207   }
    208 }
    209 
    210 void draw_square_clock_mark(int16_t innerR1, int16_t outerR1, int16_t innerR2, int16_t outerR2, int16_t innerR3, int16_t outerR3)
    211 {
    212     float x, y;
    213     int16_t x0, x1, y0, y1, innerR, outerR;
    214     uint16_t c;
    215 
    216     for (uint8_t i = 0; i < 60; i++)
    217     {
    218         if ((i % 15) == 0)
    219         {
    220             innerR = innerR1;
    221             outerR = outerR1;
    222             c = MARK_COLOR;
    223         }
    224         else if ((i % 5) == 0)
    225         {
    226             innerR = innerR2;
    227             outerR = outerR2;
    228             c = MARK_COLOR;
    229         }
    230         else
    231         {
    232             innerR = innerR3;
    233             outerR = outerR3;
    234             c = SUBMARK_COLOR;
    235         }
    236 
    237         if ((i >= 53) || (i < 8))
    238         {
    239             x = tan(SIXTIETH_RADIAN * i);
    240             x0 = center + (x * outerR);
    241             y0 = center + (1 - outerR);
    242             x1 = center + (x * innerR);
    243             y1 = center + (1 - innerR);
    244         }
    245         else if (i < 23)
    246         {
    247             y = tan((SIXTIETH_RADIAN * i) - RIGHT_ANGLE_RADIAN);
    248             x0 = center + (outerR);
    249             y0 = center + (y * outerR);
    250             x1 = center + (innerR);
    251             y1 = center + (y * innerR);
    252         }
    253         else if (i < 38)
    254         {
    255             x = tan(SIXTIETH_RADIAN * i);
    256             x0 = center - (x * outerR);
    257             y0 = center + (outerR);
    258             x1 = center - (x * innerR);
    259             y1 = center + (innerR);
    260         }
    261         else if (i < 53)
    262         {
    263             y = tan((SIXTIETH_RADIAN * i) - RIGHT_ANGLE_RADIAN);
    264             x0 = center + (1 - outerR);
    265             y0 = center - (y * outerR);
    266             x1 = center + (1 - innerR);
    267             y1 = center - (y * innerR);
    268         }
    269         gfx->drawLine(x0, y0, x1, y1, c);
    270     }
    271 }
    272 
    273 void redraw_hands_cached_draw_and_erase()
    274 {
    275     gfx->startWrite();
    276     draw_and_erase_cached_line(center, center, nsx, nsy, SECOND_COLOR, cached_points, sHandLen + 1, false, false);
    277     draw_and_erase_cached_line(center, center, nhx, nhy, HOUR_COLOR, cached_points + ((sHandLen + 1) * 2), hHandLen + 1, true, false);
    278     draw_and_erase_cached_line(center, center, nmx, nmy, MINUTE_COLOR, cached_points + ((sHandLen + 1 + hHandLen + 1) * 2), mHandLen + 1, true, true);
    279     gfx->endWrite();
    280 }
    281 
    282 void draw_and_erase_cached_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t color, int16_t *cache, int16_t cache_len, bool cross_check_second, bool cross_check_hour)
    283 {
    284 #if defined(ESP8266)
    285     yield();
    286 #endif
    287     bool steep = _diff(y1, y0) > _diff(x1, x0);
    288     if (steep)
    289     {
    290         _swap_int16_t(x0, y0);
    291         _swap_int16_t(x1, y1);
    292     }
    293 
    294     int16_t dx, dy;
    295     dx = _diff(x1, x0);
    296     dy = _diff(y1, y0);
    297 
    298     int16_t err = dx / 2;
    299     int8_t xstep = (x0 < x1) ? 1 : -1;
    300     int8_t ystep = (y0 < y1) ? 1 : -1;
    301     x1 += xstep;
    302     int16_t x, y, ox, oy;
    303     for (uint16_t i = 0; i <= dx; i++)
    304     {
    305         if (steep)
    306         {
    307             x = y0;
    308             y = x0;
    309         }
    310         else
    311         {
    312             x = x0;
    313             y = y0;
    314         }
    315         ox = *(cache + (i * 2));
    316         oy = *(cache + (i * 2) + 1);
    317         if ((x == ox) && (y == oy))
    318         {
    319             if (cross_check_second || cross_check_hour)
    320             {
    321                 write_cache_pixel(x, y, color, cross_check_second, cross_check_hour);
    322             }
    323         }
    324         else
    325         {
    326             write_cache_pixel(x, y, color, cross_check_second, cross_check_hour);
    327             if ((ox > 0) || (oy > 0))
    328             {
    329                 write_cache_pixel(ox, oy, BACKGROUND, cross_check_second, cross_check_hour);
    330             }
    331             *(cache + (i * 2)) = x;
    332             *(cache + (i * 2) + 1) = y;
    333         }
    334         if (err < dy)
    335         {
    336             y0 += ystep;
    337             err += dx;
    338         }
    339         err -= dy;
    340         x0 += xstep;
    341     }
    342     for (uint16_t i = dx + 1; i < cache_len; i++)
    343     {
    344         ox = *(cache + (i * 2));
    345         oy = *(cache + (i * 2) + 1);
    346         if ((ox > 0) || (oy > 0))
    347         {
    348             write_cache_pixel(ox, oy, BACKGROUND, cross_check_second, cross_check_hour);
    349         }
    350         *(cache + (i * 2)) = 0;
    351         *(cache + (i * 2) + 1) = 0;
    352     }
    353 }
    354 
    355 void write_cache_pixel(int16_t x, int16_t y, int16_t color, bool cross_check_second, bool cross_check_hour)
    356 {
    357     int16_t *cache = cached_points;
    358     if (cross_check_second)
    359     {
    360         for (uint16_t i = 0; i <= sHandLen; i++)
    361         {
    362             if ((x == *(cache++)) && (y == *(cache)))
    363             {
    364                 return;
    365             }
    366             cache++;
    367         }
    368     }
    369     if (cross_check_hour)
    370     {
    371         cache = cached_points + ((sHandLen + 1) * 2);
    372         for (uint16_t i = 0; i <= hHandLen; i++)
    373         {
    374             if ((x == *(cache++)) && (y == *(cache)))
    375             {
    376                 return;
    377             }
    378             cache++;
    379         }
    380     }
    381     gfx->writePixel(x, y, color);
    382 }