git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/examples/megaduck/laptop_rtc/src/megaduck_rtc.c

      1 #include <gbdk/platform.h>
      2 #include <stdint.h>
      3 #include <stdbool.h>
      4 
      5 #include <duck/laptop_io.h>
      6 
      7 #include "megaduck_rtc.h"
      8 
      9 // These BCD conversions are for simplicity, in
     10 // actual programs for performance it may be
     11 // optimal to use the Game Boy / GBDK BCD features.
     12 static uint8_t bcd_to_u8(uint8_t i)
     13 {
     14     return (i & 0xFu) + ((i >> 4) * 10u);
     15 }
     16 
     17 static uint8_t u8_to_bcd(uint8_t i)
     18 {
     19     return (i % 10u) + ((i / 10u) << 4);
     20 }
     21 
     22 // Get RTC command reply (Peripheral -> Duck)
     23 //     All values are in BCD format
     24 //         Ex: Month = December = 12th month = 0x12 (NOT 0x0C)
     25 // [0]: Length of reply (always 4)
     26 // [1..8] RTC Data
     27 // [9]: checksum
     28 //
     29 // RTC Data:
     30 //    if (tm.tm_year > (2000 - 1900))
     31 //        [1] = int_to_bcd(tm.tm_year - (2000 - 1900));
     32 //    else
     33 //        [1] = int_to_bcd(tm.tm_year); // Years in BCD since 1900 (tm_year is already in since 1900 format)
     34 //    [2] = int_to_bcd(tm.tm_mon + 1);
     35 //    [3] = int_to_bcd(tm.tm_mday);
     36 //    [4] = int_to_bcd(tm.tm_wday); // DOW
     37 //
     38 //    [5] = int_to_bcd( (tm.tm_hour < 12) ? 0 : 1 ); // AMPM
     39 //    [6] = int_to_bcd(tm.tm_hour % 12);
     40 //    [7] = int_to_bcd(tm.tm_min);
     41 //    [8] = int_to_bcd(tm.tm_sec);
     42 
     43 
     44 // Send RTC data to the Laptop Hardware and handle the response
     45 //
     46 // Returns success or failure
     47 bool duck_io_set_rtc(duck_rtc_data_t * p_rtc) {
     48 
     49     uint8_t year_to_send;
     50     // Calculate as number of years since either 1900 or 2000
     51     // Strip year off, handle
     52     if (p_rtc->year < 2000u) year_to_send = p_rtc->year - 1900u;
     53     else                           year_to_send = p_rtc->year - 2000u;
     54 
     55     duck_io_tx_buf[0] = u8_to_bcd(year_to_send);
     56     duck_io_tx_buf[1] = u8_to_bcd(p_rtc->mon);
     57     duck_io_tx_buf[2] = u8_to_bcd(p_rtc->day);
     58     duck_io_tx_buf[3] = u8_to_bcd(p_rtc->weekday);
     59 
     60     duck_io_tx_buf[4] = p_rtc->ampm;
     61     duck_io_tx_buf[5] = p_rtc->hour;
     62     duck_io_tx_buf[6] = p_rtc->min;
     63     duck_io_tx_buf[7] = p_rtc->sec;
     64 
     65     duck_io_tx_buf_len = DUCK_IO_LEN_RTC_SET;
     66 
     67     if (duck_io_send_cmd_and_buffer(DUCK_IO_CMD_SET_RTC)) {
     68         return true;
     69     } else {
     70         return false;
     71     }
     72 }
     73 
     74 
     75 // Request RTC data and handle the response
     76 //
     77 // Returns success or failure (RTC struct data not updated if polling failed)
     78 // Raw RTC data is converted into BCD format
     79 bool duck_io_get_rtc(duck_rtc_data_t * p_rtc) {
     80 
     81     if (duck_io_send_cmd_and_receive_buffer(DUCK_IO_CMD_GET_RTC)) {
     82         if (duck_io_rx_buf_len == DUCK_IO_LEN_RTC_GET) {
     83 
     84             // Translate raw RTC data in BCD format to decimal
     85 
     86             // For Year the 1992 wraparound is optional, but it's how
     87             // the Super Junior SameDuck emulation does it in order
     88             // to remain compatible with the MegaDuck Laptop System ROM
     89             // which defaults to 1993 on startup (so BCD 93 for year)
     90             // and supports years as early as 1992 (BCD 92) within an
     91             // 8 bit bcd number (max being 99 years)
     92             p_rtc->year = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_YEAR]);
     93             if (p_rtc->year >= 92) p_rtc->year += 1900u;
     94             else                p_rtc->year += 2000u;
     95 
     96             p_rtc->mon     = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_MON]);
     97             p_rtc->day     = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_DAY]);
     98             p_rtc->mon     = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_MON]);
     99             p_rtc->weekday = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_WEEKDAY]);
    100 
    101             p_rtc->ampm    = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_AMPM]);
    102             p_rtc->hour    = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_HOUR]);
    103             p_rtc->min     = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_MIN]);
    104             p_rtc->sec     = bcd_to_u8(duck_io_rx_buf[DUCK_IO_RTC_SEC]);
    105             return true;
    106         }
    107     }
    108     return false;
    109 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.