1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 *
4 *
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "aos/kernel.h"
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13
14 /* I2C settings for I2C library */
15 #ifndef DS1307_I2C
16 #define DS1307_I2C 1
17 //#define DS1307_I2C_PINSPACK TM_I2C_PinsPack_2
18 #endif
19
20 /* DS1307 I2C clock */
21 #ifndef DS1307_I2C_CLOCK
22 #define DS1307_I2C_CLOCK 100000
23 #endif
24
25 /* I2C slave address for DS1307 */
26 #define DS1307_I2C_ADDR 0xD0
27
28 /* Registers location */
29 #define DS1307_SECONDS 0x00
30 #define DS1307_MINUTES 0x01
31 #define DS1307_HOURS 0x02
32 #define DS1307_DAY 0x03
33 #define DS1307_DATE 0x04
34 #define DS1307_MONTH 0x05
35 #define DS1307_YEAR 0x06
36 #define DS1307_CONTROL 0x07
37
38 /* Bits in control register */
39 #define DS1307_CONTROL_OUT 7
40 #define DS1307_CONTROL_SQWE 4
41 #define DS1307_CONTROL_RS1 1
42 #define DS1307_CONTROL_RS0 0
43
44
45 /**
46 * @brief Result enumeration
47 */
48 typedef enum {
49 TM_DS1307_Result_Ok = 0x00, /*!< Everything OK */
50 TM_DS1307_Result_Error, /*!< An error occurred */
51 TM_DS1307_Result_DeviceNotConnected /*!< Device is not connected */
52 } TM_DS1307_Result_t;
53
54 /**
55 * @brief Structure for date/time
56 */
57 typedef struct {
58 uint8_t seconds; /*!< Seconds parameter, from 00 to 59 */
59 uint8_t minutes; /*!< Minutes parameter, from 00 to 59 */
60 uint8_t hours; /*!< Hours parameter, 24Hour mode, 00 to 23 */
61 uint8_t day; /*!< Day in a week, from 1 to 7 */
62 uint8_t date; /*!< Date in a month, 1 to 31 */
63 uint8_t month; /*!< Month in a year, 1 to 12 */
64 uint8_t year; /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */
65 } TM_DS1307_Time_t;
66
67 /**
68 * @brief Enumeration for SQW/OUT pin
69 */
70 typedef enum {
71 TM_DS1307_OutputFrequency_1Hz = 0x00, /*!< Set SQW/OUT pin to 1Hz output frequency */
72 TM_DS1307_OutputFrequency_4096Hz, /*!< Set SQW/OUT pin to 4096Hz output frequency */
73 TM_DS1307_OutputFrequency_8192Hz, /*!< Set SQW/OUT pin to 8192Hz output frequency */
74 TM_DS1307_OutputFrequency_32768Hz, /*!< Set SQW/OUT pin to 32768Hz output frequency */
75 TM_DS1307_OutputFrequency_High, /*!< Set SQW/OUT pin high. Because this pin is open-drain, you will need external pull up resistor */
76 TM_DS1307_OutputFrequency_Low /*!< Set SQW/OUT pin low */
77 } TM_DS1307_OutputFrequency_t;
78
79 /**
80 * @}
81 */
82
83
84 i2c_dev_t ds1307_i2c = {
85 .port = DS1307_I2C,
86 .config.address_width = 8,
87 .config.freq = DS1307_I2C_CLOCK,
88 .config.dev_addr = DS1307_I2C_ADDR,
89 };
90
TM_DS1307_Bcd2Bin(uint8_t bcd)91 uint8_t TM_DS1307_Bcd2Bin(uint8_t bcd) {
92 uint8_t dec = 10 * (bcd >> 4);
93 dec += bcd & 0x0F;
94 return dec;
95 }
96
TM_DS1307_Bin2Bcd(uint8_t bin)97 uint8_t TM_DS1307_Bin2Bcd(uint8_t bin) {
98 uint8_t low = 0;
99 uint8_t high = 0;
100
101 /* High nibble */
102 high = bin / 10;
103 /* Low nibble */
104 low = bin - (high * 10);
105
106 /* Return */
107 return high << 4 | low;
108 }
109
TM_DS1307_CheckMinMax(uint8_t val,uint8_t min,uint8_t max)110 uint8_t TM_DS1307_CheckMinMax(uint8_t val, uint8_t min, uint8_t max) {
111 if (val < min) {
112 return min;
113 } else if (val > max) {
114 return max;
115 }
116 return val;
117 }
118
119
drv_rtc_maxim_ds1307_irq_handle(void)120 static void drv_rtc_maxim_ds1307_irq_handle(void)
121 {
122 /* no handle so far */
123 }
124
drv_rtc_maxim_ds1307_open(void)125 static int drv_rtc_maxim_ds1307_open(void)
126 {
127 return 0;
128 /* no handle so far */
129 }
130
drv_rtc_maxim_ds1307_close(void)131 static int drv_rtc_maxim_ds1307_close(void)
132 {
133 /* no handle so far */
134 return 0;
135 }
136
137
drv_rtc_maxim_ds1307_ioctl(int cmd,unsigned long arg)138 static int drv_rtc_maxim_ds1307_ioctl(int cmd, unsigned long arg)
139 {
140 /* no handle so far */
141 return 0;
142 }
143
144
drv_rtc_maxim_ds1307_write(const void * buf,size_t len)145 static int drv_rtc_maxim_ds1307_write(const void *buf, size_t len)
146 {
147 int ret = 0;
148 size_t size;
149 uint8_t data[7];
150
151 const rtc_data_t *time = (rtc_data_t *)buf;
152
153 if (buf == NULL)
154 {
155 return -1;
156 }
157
158 size = sizeof(rtc_data_t);
159
160 if (len < size)
161 {
162 return -1;
163 }
164
165 /* Format data */
166 data[DS1307_SECONDS] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->seconds, 0, 59));
167 data[DS1307_MINUTES] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->minutes, 0, 59));
168 data[DS1307_HOURS] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->hours, 0, 23));
169 data[DS1307_DAY] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->day, 1, 7));
170 data[DS1307_DATE] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->date, 1, 31));
171 data[DS1307_MONTH] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->month, 1, 12));
172 data[DS1307_YEAR] = TM_DS1307_Bin2Bcd(TM_DS1307_CheckMinMax(time->year, 0, 99));
173
174 ret = sensor_i2c_write(&ds1307_i2c, DS1307_I2C_ADDR, data, 7, I2C_OP_RETRIES);
175
176 if (unlikely(ret))
177 {
178 return -1;
179 }
180
181 return (int)size;
182 }
183
184
drv_rtc_maxim_ds1307_read(void * buf,size_t len)185 static int drv_rtc_maxim_ds1307_read(void *buf, size_t len)
186 {
187 int ret = 0;
188 size_t size;
189 uint8_t data[7];
190
191 rtc_data_t *time = (rtc_data_t *)buf;
192
193 if (buf == NULL)
194 {
195 return -1;
196 }
197
198 size = sizeof(rtc_data_t);
199
200 if (len < size)
201 {
202 return -1;
203 }
204
205 ret = sensor_i2c_read(&ds1307_i2c, DS1307_SECONDS, data, 7, I2C_OP_RETRIES);
206
207 if (unlikely(ret))
208 {
209 return -1;
210 }
211
212 /* Fill data */
213 time->seconds = TM_DS1307_Bcd2Bin(data[DS1307_SECONDS]);
214 time->minutes = TM_DS1307_Bcd2Bin(data[DS1307_MINUTES]);
215 time->hours = TM_DS1307_Bcd2Bin(data[DS1307_HOURS]);
216 time->day = TM_DS1307_Bcd2Bin(data[DS1307_DAY]);
217 time->date = TM_DS1307_Bcd2Bin(data[DS1307_DATE]);
218 time->month = TM_DS1307_Bcd2Bin(data[DS1307_MONTH]);
219 time->year = TM_DS1307_Bcd2Bin(data[DS1307_YEAR]);
220
221 time->timestamp = aos_now_ms();
222
223 return (int)size;
224
225 }
226
227
drv_rtc_maxim_ds1307_init(void)228 int drv_rtc_maxim_ds1307_init(void)
229 {
230 int ret = 0;
231 sensor_obj_t sensor;
232 memset(&sensor, 0, sizeof(sensor));
233 /* fill the sensor obj parameters here */
234 sensor.io_port = I2C_PORT;
235 sensor.tag = TAG_DEV_RTC;
236 sensor.path = dev_rtc_path;
237 sensor.open = drv_rtc_maxim_ds1307_open;
238 sensor.close = drv_rtc_maxim_ds1307_close;
239 sensor.read = drv_rtc_maxim_ds1307_read;
240 sensor.write = drv_rtc_maxim_ds1307_write;
241 sensor.ioctl = drv_rtc_maxim_ds1307_ioctl;
242 sensor.irq_handle = drv_rtc_maxim_ds1307_irq_handle;
243
244 ret = sensor_create_obj(&sensor);
245 if(unlikely(ret)){
246 return -1;
247 }
248
249 ret = hal_i2c_init(&ds1307_i2c);
250 if(unlikely(ret)){
251 printf("i2c init failed!\n");
252 }
253
254 if(unlikely(ret)){
255 return -1;
256 }
257
258 //set odr is 100hz, and will update
259 if(unlikely(ret)){
260 return -1;
261 }
262
263 /* update the phy sensor info to sensor hal */
264 LOG("%s %s successfully \n", RTC_STR, __func__);
265 return 0;
266 }
267
268 SENSOR_DRV_ADD(drv_rtc_maxim_ds1307_init);
269
270
271