凌云物联网实验室ISKBoard(IoT Starter Kits Board)开发板项目源码
guowenxue
2023-04-03 32806da6f5647ac637fa7d48aa9c221b091ab35e
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/*
 * sht20.c
 *
 *  Created on: Jan 19, 2023
 *      Author: Wenxue
 */
 
#include <stdio.h>
#include <string.h>
#include "isl1208.h"
 
/*+--------------------------------------+
 *|      RTC Chipset ISL1208 Register    |
 *+--------------------------------------+*/
/* rtc section */
#define ISL1208_REG_SC            0x00
#define ISL1208_REG_MN            0x01
#define ISL1208_REG_HR            0x02
#define ISL1208_REG_HR_MIL     (1<<7)   /* 24h/12h mode */
#define ISL1208_REG_HR_PM      (1<<5)   /* PM/AM bit in 12h mode */
#define ISL1208_REG_DT            0x03
#define ISL1208_REG_MO            0x04
#define ISL1208_REG_YR            0x05
#define ISL1208_REG_DW            0x06
#define ISL1208_RTC_SECTION_LEN    7 /* RTC Section register */
#define REGS_RTC_SR_LEN            8 /* RTC Section and status register  */
 
/* control/status section */
#define ISL1208_REG_SR            0x07
#define ISL1208_REG_SR_ARST    (1<<7)   /* auto reset */
#define ISL1208_REG_SR_XTOSCB  (1<<6)   /* crystal oscillator */
#define ISL1208_REG_SR_WRTC    (1<<4)   /* write rtc */
#define ISL1208_REG_SR_EVT     (1<<3)   /* event */
#define ISL1208_REG_SR_ALM     (1<<2)   /* alarm */
#define ISL1208_REG_SR_BAT     (1<<1)   /* battery */
#define ISL1208_REG_SR_RTCF    (1<<0)   /* rtc fail */
#define ISL1208_REG_INT            0x08
#define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
#define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
#define ISL1219_REG_EV            0x09
#define ISL1219_REG_EV_EVEN    (1<<4)   /* event detection enable */
#define ISL1219_REG_EV_EVIENB  (1<<7)   /* event in pull-up disable */
#define ISL1208_REG_ATR            0x0a
#define ISL1208_REG_DTR            0x0b
 
/* alarm section */
#define ISL1208_REG_SCA            0x0c
#define ISL1208_REG_MNA            0x0d
#define ISL1208_REG_HRA            0x0e
#define ISL1208_REG_DTA            0x0f
#define ISL1208_REG_MOA            0x10
#define ISL1208_REG_DWA            0x11
#define ISL1208_ALARM_SECTION_LEN 6
 
/* user section */
#define ISL1208_REG_USR1        0x12
#define ISL1208_REG_USR2        0x13
#define ISL1208_USR_SECTION_LEN    2
 
#define ISL1208_REGS_MAX        0x13
 
const char *weekday[7]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat." };
 
#define CONFIG_RTC_DEBUG
 
#ifdef  CONFIG_RTC_DEBUG
#define rtc_print(format,args...) printf(format, ##args)
#else
#define rtc_print(format,args...) do{} while(0)
#endif
 
#ifdef CONFIG_RTC_DEBUG
__attribute__((unused)) static void dump_buf(const char *prompt, uint8_t *buf, uint32_t size)
{
    int      i;
    
    if(!buf)
        return ;
    
    if(prompt)
        printf("%s\r\n", prompt);
    
    for(i=0; i<size; i++)
        printf("%02x ", buf[i]);
    
    printf("\r\n");
}
#endif
    
 
/*
 *+----------------------------------+
 *|     ISL1208 Low level API        |
 *+----------------------------------+
 */
 
static int isl1208_i2c_read_regs(uint8_t regaddr, uint8_t *regs, uint8_t len)
{
    uint8_t        i;
    int            rv = 0;
    uint8_t        byte;
    uint8_t        ack;
    
    if( !regs || len<=0 )
    {
        rtc_print("ISL1208: Invalid input arguments\r\n");
        return -PARM_ERROR;
    }
 
    I2C_StartCondition(ISL1208_I2CBUS);
    
    if( NO_ERROR != (rv=I2C_SendAddress(ISL1208_I2CBUS, I2C_WR)) )
    {
        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
        rv = -rv;
        goto OUT;
    }
    
    if( NO_ERROR != (rv=I2C_WriteByte(ISL1208_I2CBUS, regaddr) ) )
    {
        rtc_print("ISL1208: Set register[0x%02x] failure: rv=0x%02x\r\n", regaddr, rv);
        rv = -rv;
        goto OUT;
    }
    
    I2C_StartCondition(ISL1208_I2CBUS);
    
    if( NO_ERROR != (rv=I2C_SendAddress( ISL1208_I2CBUS, I2C_RD ) ) )
    {
        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
        rv = -rv;
        goto OUT;
    }
    
    for (i=0; i<len; i++)
    {
         if( i == (len-1) )
             ack = ACK_NONE;
         else
             ack = ACK; 
         
         rv = I2C_ReadByte(ISL1208_I2CBUS, &byte, ack, I2C_CLK_STRETCH_TIMEOUT);
         if( NO_ERROR != rv )
         {
             rtc_print("ISL1208: Read register data failure: rv=0x%02x\r\n", rv);    
             rv = -rv;
             goto OUT;
         }
         
         regs[i] = byte;
    }
 
OUT:
    I2C_StopCondition(ISL1208_I2CBUS);
    return rv;
}
 
static int isl1208_i2c_write_regs(uint8_t regaddr, uint8_t *regs, uint8_t len)
{
    uint8_t        i;
    int            rv = 0;
 
    I2C_StartCondition(ISL1208_I2CBUS);
    
    if( NO_ERROR != (rv=I2C_SendAddress(ISL1208_I2CBUS, I2C_WR ) ) )
    {
        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
        rv = -rv;
        goto OUT;
    }
    
    if( NO_ERROR != (rv=I2C_WriteByte(ISL1208_I2CBUS, regaddr) ) )
    {
        rtc_print("ISL1208: Set register[0x%02x] failure: rv=0x%02x\r\n", regaddr, rv);
        rv = -rv;
        goto OUT;
    }
 
    for (i=0; i<len; i++)
    {
        rv = I2C_WriteByte(ISL1208_I2CBUS, regs[i]);
        if( NO_ERROR != rv )
        {
            rtc_print("ISL1208: Write register data failure: rv=0x%02x\r\n", rv);
            rv = -rv;
            goto OUT;
        }
    }        
 
    rv = 0;
    
OUT:
    I2C_StopCondition(ISL1208_I2CBUS);
    return rv;
}
 
 
#define bcd2bin(x)    (((x) & 0x0f) + ((x) >> 4) * 10)
#define bin2bcd(x)    ((((x) / 10) << 4) + (x) % 10)
 
int set_rtc_time(rtc_time_t tm)
{
    int                     rv;
    uint8_t                 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
    uint8_t                 sr;
 
    regs[ISL1208_REG_SC] = bin2bcd(tm.tm_sec);
    regs[ISL1208_REG_MN] = bin2bcd(tm.tm_min);
    regs[ISL1208_REG_HR] = bin2bcd(tm.tm_hour) | ISL1208_REG_HR_MIL;
    
    regs[ISL1208_REG_DT] = bin2bcd(tm.tm_mday);
    regs[ISL1208_REG_MO] = bin2bcd(tm.tm_mon);
    regs[ISL1208_REG_YR] = bin2bcd(tm.tm_year - 2000);
    //regs[ISL1208_REG_DW] = bin2bcd(tm.tm_wday & 7);
    
    if( i2c_init(ISL1208_I2CBUS, ISL1208_CHIPADDR) )
    {
        rtc_print("ISL1208: Initial I2C bus failure!\r\n");
        return -2;
    }
 
    rv = isl1208_i2c_read_regs(ISL1208_REG_SR, &sr, 1);
    if( rv < 0 )
    {
        rtc_print("ISL1208: read Status Register failure, rv=%d!\r\n", rv);
        rv = -3;
        goto OUT;
    }
    sr |= ISL1208_REG_SR_WRTC;
    rv = isl1208_i2c_write_regs(ISL1208_REG_SR, &sr, 1);
    if( rv < 0 )
    {
        rtc_print("ISL1208: Set Status Register WRTC failure, rv=%d!\r\n", rv);
        rv = -4;
        goto OUT;
    }    
 
    rv=isl1208_i2c_write_regs(ISL1208_REG_SC, regs, ISL1208_RTC_SECTION_LEN);
    if(rv < 0 )
    {
        rtc_print("ISL1208: Set RTC section registeres failure, rv=%d!\r\n", rv);
        rv = -5;
        goto OUT;
    }    
    
    sr &= (~ISL1208_REG_SR_WRTC);
    rv = isl1208_i2c_write_regs(ISL1208_REG_SR, &sr, 1);
    if( rv < 0 )
    {
        rtc_print("ISL1208: Clear Status Register WRTC failure, rv=%d!\r\n", rv);
        rv = -6;
        goto OUT;
    }        
    
OUT:
    i2c_term(ISL1208_I2CBUS);
    return rv;
}
 
int get_rtc_time(rtc_time_t *tm)
{
    int                                    rv = 0;
    uint8_t                             regs[REGS_RTC_SR_LEN] = { 0, };
    
    if( !tm )
    {
        rtc_print("ISL1208: Invalid input arugments!\r\n");
        return -1;
    }
    
    if( i2c_init(ISL1208_I2CBUS, ISL1208_CHIPADDR) )
    {
        rtc_print("ISL1208: Initial I2C bus failure!\r\n");
        return -2;
    }
 
    rv = isl1208_i2c_read_regs(ISL1208_REG_SC, regs, REGS_RTC_SR_LEN);
    if (rv < 0)
    {
        rtc_print("ISL1208: read RTC_SECTION and SR registeres failure, rv=%d!\r\n", rv);
        rv = -3;
        goto OUT;
    }
    
    if( regs[ISL1208_REG_SR] & ISL1208_REG_SR_RTCF )
    {
        rtc_print("ISL1208: Initialize RTC time after power failure!\r\n");
        rv = -4;
        goto OUT;
    }
 
    tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]);
    tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]);
    
    {
        const uint8_t _hr = regs[ISL1208_REG_HR];
            
        if (_hr & ISL1208_REG_HR_MIL)  /* 24H */
        {
            tm->tm_hour = bcd2bin(_hr & 0x3f);
        }
        else  /* 12H */
        {
            tm->tm_hour = bcd2bin(_hr & 0x1f);
            if (_hr & ISL1208_REG_HR_PM)
                tm->tm_hour += 12;
        }
    }
        
    tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]);
    tm->tm_mon  = bcd2bin(regs[ISL1208_REG_MO]); 
    tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 2000;
    tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]);
    
OUT:
    i2c_term(ISL1208_I2CBUS);
    return rv;
}
 
void print_rtc_time(void)
{
    rtc_time_t tm;
 
    if( get_rtc_time(&tm) < 0 )
        return ;
 
    printf("%04d-%02d-%02d %02d:%02d:%02d %s\r\n", tm.tm_year, tm.tm_mon, tm.tm_mday,
        tm.tm_hour, tm.tm_min, tm.tm_sec, weekday[tm.tm_wday]);
}