Project

General

Profile

Statistics
| Revision:

root / proj / src / rtc.c @ 259

History | View | Annotate | Download (4.67 KB)

1 234 up20180655
#include "rtc.h"
2
#include "rtc_macros.h"
3
4
#include <lcom/lcf.h>
5
6
#include "utils.h"
7
#include "errors.h"
8
9 259 up20180642
// RTC IRQ Line
10
11
#define KBC_IRQ   8  /* @brief KBC IRQ Line */
12
13
// RTC Ports
14
15
#define RTC_ADDR_REG        0x70
16
#define RTC_DATA_REG        0x71
17
18
// RTC Registers (Byte)
19
20
#define RTC_SEC             0
21
#define RTC_SEC_ALARM       1
22
#define RTC_MIN             2
23
#define RTC_MIN_ALARM       3
24
#define RTC_HOUR            4
25
#define RTC_HOUR_ALARM      5
26
#define RTC_WEEK_DAY        6
27
#define RTC_MONTH_DAY       7
28
#define RTC_MONTH           8
29
#define RTC_YEAR            9
30
#define RTC_REG_A           10
31
#define RTC_REG_B           11
32
#define RTC_REG_C           12
33
#define RTC_REG_D           13
34
35
// Register A
36
37
#define RS0     BIT(0)  /** @brief Rate selector */
38
#define RS1     BIT(1)  /** @brief Rate selector */
39
#define RS2     BIT(2)  /** @brief Rate selector */
40
#define RS3     BIT(3)  /** @brief Rate selector */
41
#define UIP     BIT(7)  /** @brief Update in progress */
42
43
// Register B
44
45
#define DSE             BIT(0)  /** @brief Enable Daylight Saving Time */
46
#define HOUR_FORM       BIT(1)  /** @brief Set to 1 for 24h format (0-23), 0 to 12h format (1-12) */
47
#define DM              BIT(2)  /** @brief Set to 1 if registers are in binary, 0 if in BCD */
48
#define SQWE            BIT(3)  /** @brief Enable square wave generation */
49
#define UIE             BIT(4)  /** @brief Enable Update interrupts */
50
#define AIE             BIT(5)  /** @brief Enable alarm interrupts */
51
#define PIE             BIT(6)  /** @brief Enable periodic interrupts */
52
#define SET             BIT(7)  /** @brief Set to 1 to inhibit updates of time/date registers */
53
54
// Register C
55
56
#define UF      BIT(4)  /** @brief Update Interrupt Pending */
57
#define AF      BIT(5)  /** @brief Alarm Interrupt Pending */
58
#define PF      BIT(6)  /** @brief Periodic Interrupt Pending */
59
#define IRQF    BIT(7)  /** @brief IRQ Line Active */
60
61
// Register D
62
63
#define VRT     BIT(7)  /** @brief Valid RAM/time - If set to 0 RTC reading aren't valid */
64
65 234 up20180655
int (subscribe_rtc_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
66
    if (interrupt_id == NULL) return NULL_PTR;
67
    *interrupt_id = interrupt_bit;
68
    if (sys_irqsetpolicy(KBC_IRQ, IRQ_REENABLE | IRQ_EXCLUSIVE, interrupt_id)) return SBCR_ERROR;
69
    return SUCCESS;
70
}
71
72
int (rtc_read_register)(uint32_t reg, uint8_t *data) {
73
    if (sys_outb(RTC_ADDR_REG, reg)) return WRITE_ERROR;
74
75
    if (util_sys_inb(RTC_DATA_REG, data)) return READ_ERROR;
76
77
    return SUCCESS;
78
}
79
80
int (rtc_write_register)(uint32_t reg, uint8_t data) {
81
    if (sys_outb(RTC_ADDR_REG, reg)) return WRITE_ERROR;
82
83
    if (sys_outb(RTC_DATA_REG, data)) return WRITE_ERROR;
84
85
    return SUCCESS;
86
}
87
88
int (rtc_check_update)(void) {
89
    uint8_t data;
90
    int r;
91
92
    if ((r = rtc_read_register(RTC_REG_A, &data))) return r;
93
94
    return (data & UIP) != 0;
95
}
96
97
int (rtc_set_updates)(int on) {
98
    uint8_t data;
99
    int r;
100
    if (on) {
101
        if ((r = rtc_read_register(RTC_REG_B, &data))) return r;
102
103
        data &= ~SET;
104
105
        if ((r = rtc_write_register(RTC_REG_B, data))) return r;
106
107
    } else {
108
        while (rtc_check_update());
109
110
        if ((r = rtc_read_register(RTC_REG_B, &data))) return r;
111
112
        data |= SET;
113
114
        if ((r = rtc_write_register(RTC_REG_B, data))) return r;
115
    }
116
    return SUCCESS;
117
}
118
119
int (rtc_read_time)(uint8_t *time) {
120
121
    int r;
122
    //if ((r = rtc_set_updates(false))) return r;
123
    while (rtc_check_update());
124
125
    uint8_t hour, min, sec;
126
127
    if ((r = rtc_read_register(RTC_SEC, &sec)))    return r;
128
    if ((r = rtc_read_register(RTC_MIN, &min)))    return r;
129
    if ((r = rtc_read_register(RTC_HOUR, &hour)))  return r;
130
131
    //if ((r = rtc_set_updates(true))) return r;
132
133
    time[0] = BCD_FIRST(sec)*10   + BCD_SECOND(sec);
134
    time[1] = BCD_FIRST(min)*10   + BCD_SECOND(min);
135
    time[2] = BCD_FIRST(hour)*10  + BCD_SECOND(hour);
136
137
    return SUCCESS;
138
}
139
140
int (rtc_read_date)(uint8_t *date) {
141
    int r;
142
    //if ((r = rtc_set_updates(false))) return r;
143
    while (rtc_check_update());
144
145
    uint8_t year, month, day, weekday;
146
147
    if ((r = rtc_read_register(RTC_WEEK_DAY,    &weekday)))     return r;
148
    if ((r = rtc_read_register(RTC_MONTH_DAY,   &day)))         return r;
149
    if ((r = rtc_read_register(RTC_MONTH,       &month)))       return r;
150
    if ((r = rtc_read_register(RTC_YEAR,        &year)))        return r;
151
152
    //if ((r = rtc_set_updates(true))) return r;
153
154
    date[0] = weekday;
155
    date[1] = BCD_FIRST(day)*10     + BCD_SECOND(day);
156
    date[2] = BCD_FIRST(month)*10   + BCD_SECOND(month);
157
    date[3] = BCD_FIRST(year)*10    + BCD_SECOND(year);
158
159
    return SUCCESS;
160
}