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