Project

General

Profile

Statistics
| Revision:

root / proj / src / rtc.c @ 270

History | View | Annotate | Download (4.65 KB)

1
#include <lcom/lcf.h>
2

    
3
#include "rtc.h"
4

    
5
#include "utils.h"
6
#include "errors.h"
7

    
8
// 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
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
}