1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - af_rtc.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2014 Bobby Smiles *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21 
22 #include "af_rtc.h"
23 
24 #include "api/m64p_types.h"
25 #include "api/callbacks.h"
26 
27 #include <time.h>
28 
byte2bcd(int n)29 static uint8_t byte2bcd(int n)
30 {
31    n %= 100;
32    return ((n / 10) << 4) | (n % 10);
33 }
34 
af_rtc_get_time(struct af_rtc * rtc)35 const struct tm* af_rtc_get_time(struct af_rtc* rtc)
36 {
37  return rtc->get_time(rtc->user_data);
38 }
39 
af_rtc_status_command(struct af_rtc * rtc,uint8_t * cmd)40 void af_rtc_status_command(struct af_rtc *rtc, uint8_t *cmd)
41 {
42    /* AF-RTC status query */
43    cmd[3] = 0x00;
44    cmd[4] = 0x10;
45    cmd[5] = 0x00;
46 }
47 
af_rtc_read_command(struct af_rtc * rtc,uint8_t * cmd)48 void af_rtc_read_command(struct af_rtc *rtc, uint8_t *cmd)
49 {
50    const struct tm *rtc_time;
51 
52    /* read RTC block (cmd[3]: block number) */
53    switch (cmd[3])
54    {
55       case 0:
56          cmd[4] = 0x00;
57          cmd[5] = 0x02;
58          cmd[12] = 0x00;
59          break;
60       case 1:
61          DebugMessage(M64MSG_ERROR, "AF-RTC read command: cannot read block 1");
62          break;
63       case 2:
64          rtc_time = af_rtc_get_time(rtc);
65          cmd[4] = byte2bcd(rtc_time->tm_sec);
66          cmd[5] = byte2bcd(rtc_time->tm_min);
67          cmd[6] = 0x80 + byte2bcd(rtc_time->tm_hour);
68          cmd[7] = byte2bcd(rtc_time->tm_mday);
69          cmd[8] = byte2bcd(rtc_time->tm_wday);
70          cmd[9] = byte2bcd(rtc_time->tm_mon + 1);
71          cmd[10] = byte2bcd(rtc_time->tm_year);
72          cmd[11] = byte2bcd(rtc_time->tm_year / 100);
73          cmd[12] = 0x00;	/* status */
74          break;
75    }
76 }
77 
af_rtc_write_command(struct af_rtc * rtc,uint8_t * cmd)78 void af_rtc_write_command(struct af_rtc *rtc, uint8_t* cmd)
79 {
80    /* write RTC block */
81    DebugMessage(M64MSG_ERROR, "AF-RTC write command: not yet implemented");
82 }
83 
init_af_rtc(struct af_rtc * rtc,void * user_data,const struct tm * (* get_time)(void *))84 void init_af_rtc(struct af_rtc* rtc,
85       void* user_data,
86       const struct tm* (*get_time)(void*))
87 {
88    rtc->user_data = user_data;
89    rtc->get_time = get_time;
90 }
91