rtc.c
4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <os.h>
#include <bcp.h>
#include "bbint.h"
#define RTC_SLAVE_ADDR 0xd0
#define RTC_SCLK PI_GPIO_USER0_BIT
#define RTC_SIO PI_GPIO_USER1_BIT
#define RTC_MASK (RTC_SCLK|RTC_SIO|((RTC_SCLK|RTC_SIO) << PI_GPIO_ENABLE_SHIFT))
#define RTC_SCLK_HI (RTC_SCLK|(RTC_SCLK<<PI_GPIO_ENABLE_SHIFT))
#define RTC_SCLK_LO (0|(RTC_SCLK<<PI_GPIO_ENABLE_SHIFT))
#define RTC_SO(b) (b|(RTC_SIO<<PI_GPIO_ENABLE_SHIFT))
#define tobcd(x) ((((x)/10)<<4) | ((x)%10))
#define frbcd(x) (((x)>>4)*10 + ((x)&0xf))
static void
write_rtc(u32 x) {
IO_WRITE(PI_GPIO_REG, x);
__osBbDelay(2);
}
static void
send_start(u8 write) {
u32 i, j, mask = IO_READ(PI_GPIO_REG) & ~RTC_MASK;
u8 byte[2];
byte[0] = RTC_SLAVE_ADDR | (write == 0);
byte[1] = 0; /* address */
/* assume we are in idle state, clock and data hi */
/* clock hi, data lo */
write_rtc(mask | RTC_SCLK_HI | RTC_SO(0));
/* clock lo, hold data */
write_rtc(mask | RTC_SCLK_LO | RTC_SO(0));
for(j = 0; j < 1+write; j++) {
for(i = 0; i < 8; i++) {
u32 b = (byte[j] & (1<<(7-i))) ? RTC_SIO : 0;
/* clock lo, new data */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_LO);
/* clock hi */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_HI);
/* clock lo, hold data */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_LO);
}
/* acknowledge */
/* clock lo, new data */
write_rtc(mask | RTC_SCLK_LO);
/* clock hi */
write_rtc(mask | RTC_SCLK_HI);
}
write_rtc(mask | RTC_SCLK_LO);
}
static void
send_stop(void) {
u32 mask = IO_READ(PI_GPIO_REG) & ~RTC_MASK;
/* clock lo, data lo */
write_rtc(mask | RTC_SCLK_LO | RTC_SO(0));
/* clock hi, data lo */
write_rtc(mask | RTC_SCLK_HI | RTC_SO(0));
/* clock hi, data hi */
write_rtc(mask | RTC_SCLK_HI | RTC_SO(RTC_SIO));
}
static void
read_bytes(u8* bytes, u8 len) {
u32 ack, i, mask = IO_READ(PI_GPIO_REG) & ~RTC_MASK;
while(len-- > 0) {
u32 x = 0;
for(i = 0; i < 8; i++) {
/* clock low */
write_rtc(mask | RTC_SCLK_LO);
/* clock high */
write_rtc(mask | RTC_SCLK_HI);
x <<= 1;
x |= (IO_READ(PI_GPIO_REG) & RTC_SIO) ? 1 : 0;
}
*bytes++ = x;
/* acknowledge */
ack = (len == 0) ? RTC_SO(RTC_SIO) : RTC_SO(0);
/* clock lo, data lo */
write_rtc(mask | RTC_SCLK_LO | RTC_SO(0));
/* clock hi, ack or stop */
write_rtc(mask | RTC_SCLK_HI | ack);
}
send_stop();
}
static void
write_bytes(const u8* bytes, u8 len) {
u32 i, mask = IO_READ(PI_GPIO_REG) & ~RTC_MASK;
while(len-- > 0) {
u32 x = *bytes++;
for(i = 0; i < 8; i++) {
u32 b = (x&0x80) ? RTC_SIO : 0;
/* clock low */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_LO);
/* clock high */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_HI);
/* clock lo, hold data */
write_rtc(mask | RTC_SO(b) | RTC_SCLK_HI);
x <<= 1;
}
/* recv acknowledge */
/* clock lo */
write_rtc(mask | RTC_SCLK_LO);
/* clock hi, hold data */
write_rtc(mask | RTC_SCLK_HI);
x = (IO_READ(PI_GPIO_REG) & RTC_SIO) ? 1 : 0;
#ifdef _DEBUG
if (x && len) osSyncPrintf("premature stop?\n");
#endif
/* clock lo */
write_rtc(mask | RTC_SCLK_LO);
}
send_stop();
}
void
osBbRtcInit(void) {
u32 mask = IO_READ(PI_GPIO_REG) & ~RTC_MASK;
/* idle state is clock and data high */
write_rtc(mask | RTC_SCLK_HI | RTC_SO(RTC_SIO));
}
void
osBbRtcSet(u8 year, u8 month, u8 day, u8 dow, u8 hour, u8 min, u8 sec) {
u8 data[8];
data[7] = 0;
data[6] = tobcd(year); data[5] = tobcd(month); data[4] = tobcd(day);
data[3] = tobcd(dow); data[2] = tobcd(hour); data[1] = tobcd(min);
data[0] = tobcd(sec);
send_start(1);
//osSyncPrintf("w %02x %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
write_bytes(data, 8);
}
void
osBbRtcGet(u8* year, u8* month, u8* day, u8* dow, u8* hour, u8* min, u8* sec) {
u8 data[8];
send_start(1);
send_start(0);
read_bytes(data, 8);
//osSyncPrintf("r %02x %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
*year = frbcd(data[6]); *month = frbcd(data[5]); *day = frbcd(data[4]);
*dow = frbcd(data[3]); *hour = frbcd(data[2]); *min = frbcd(data[1]);
*sec = frbcd(data[0]);
}