Project

General

Profile

Statistics
| Revision:

root / proj / libs / rtc / src / rtc.c @ 340

History | View | Annotate | Download (4.65 KB)

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