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.