f1105988031e9d560f77e9992e402b6b2afcaaa9
[cortex-from-scratch] / drivers / at24c.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/7/25 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  *
9  * */
10
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include <stdint.h>
14
15 #include <sys/mmap.h>
16 #include <sys/robsys.h>
17
18 #include <lib/regfunc.h>
19 #include <lib/string.h>
20 #include <lib/stdio.h>
21 #include <lib/tinyprintf.h>
22
23 #include <drivers/at24c.h>
24
25 #define TIMEOUT 5000
26
27 #define READ_CMD        0xA1
28 #define WRITE_CMD       0xA0
29 #define PAGE 64 /* Bytes that can be written continiously */
30 #define BUFFER 256 /* */
31
32 /* STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their
33 GPIOs must be configured as open-drain. So, you have to add two additional resistors to
34 pull-up I2C lines. Something between 4K and 10K is a proven value. 
35 */
36
37 char buf[BUFFER];
38
39 void * cap_handler() {
40
41         printf("a!");
42 }
43
44 void at24c_init() {
45
46  /* Program the peripheral input clock in I2C_CR2 Register
47   *  in order to generate correct timings. Configure the clock control registers CCR
48  Configure the rise time register TRIS  Program the I2C_CR1 register to enable the peripheral Enable GPIOB6 and B7*/
49
50  rsetbit(RCC_APB1ENR, 21);
51  rsetbit(RCC_APB2ENR, 3);
52  rwrite(GPIOB_CRL, 0xEE444444);
53  rsetbitsfrom(I2C_CR2, 0, 0x2); // 2 MHz 
54  rwrite(I2C_TRISE, 0x3); // MAX = 1000ns, TPCLK1 = 500ns (+1)
55  rwrite(I2C_CCR, 0x000A); // standard modeļ¼Œ output 100 kHz (100hz* / perip)
56  rsetbit(I2C_CR1, 10); // send ack if Master receives data
57  rsetbit(I2C_CR2, 10); // buffer interrupt
58  rsetbit(I2C_CR1, 0); // enable
59
60
61 }
62
63 static void start_condition() {
64         rsetbit(I2C_CR1, 8); //start
65 }
66
67 static void stop_condition() {
68         rsetbit(I2C_CR1, 9); //stop
69 }
70
71 static int ack_recv() {
72         int cnt = 0;
73         while(!(*I2C_SR1 & 0x2)) {
74                 cnt++;
75                 if (cnt > TIMEOUT)
76                         return 0;
77         }
78
79         int a = *I2C_SR2;
80         return 1;
81 }
82
83 static int buf_empty() {
84         int cnt = 0;
85         while(!(*I2C_SR1 & 0x80)) {
86                 cnt++;
87                 if (cnt > TIMEOUT)
88                         return 0;
89         }
90         return 1;
91 }
92
93 // TODO: interrupt base, so it doesn't block
94 static void data_recv() {
95         while(!(*I2C_SR1 & 0x40)) {
96         }
97 }
98
99 // TODO: polling
100 static int delay() {
101
102         int a = 0;
103         for (int i = 0; i < 0xFFFF; i++)
104                 a++;
105 }
106
107 int eeprom_write(uint16_t addr, char * data, size_t size) {
108         
109         if(size > PAGE) {
110                 printf("Maximum writable page size: %d\n", PAGE);
111                 return -1;
112         }
113
114         uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr }; 
115         
116         start_condition();
117         rwrite(I2C_DR, WRITE_CMD);
118         if(!ack_recv()) {
119                 printf("Can't reach device");
120                 return -1;
121         }
122
123         rwrite(I2C_DR, hi_lo[0]); // higher part of address
124         if(!buf_empty()) {
125                 printf("Can't address location");
126                 return -1;
127         }
128         rwrite(I2C_DR,hi_lo[1]); // lower part of address
129         if(!buf_empty()) {
130                 printf("Can't address location");
131                 return -1;
132         }
133
134         for (int i = 0; i < size; i++) {
135                 rwrite(I2C_DR, *data++);
136                 if(!buf_empty()) {
137                         printf("Write error");
138                         return -1;
139                 }       
140         }
141
142         stop_condition();
143         
144         return 0;
145 }
146 /* Random access read based on dummy write  */
147 int eeprom_read(uint16_t addr, int num) {
148
149         printf("ENTERING");     
150         uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr }; 
151         
152         start_condition();
153         
154         rwrite(I2C_DR, WRITE_CMD);
155         if(!ack_recv()) {
156                 printf("Can't reach device");
157                 return -1;
158         }
159
160         rwrite(I2C_DR, hi_lo[0]); // higher part of address
161         if(!buf_empty()) {
162                 printf("Can't address location");
163                 return -1;
164         }
165         rwrite(I2C_DR,hi_lo[1]); // lower part of address
166         if(!buf_empty()) {
167                 printf("Can't address location");
168                 return -1;
169         }
170
171         stop_condition();
172         
173         delay(); // NEEDED?
174
175         start_condition(); // restart condition
176         rwrite(I2C_DR, READ_CMD); // read? to address CMD
177         if(!ack_recv()) {
178                 printf("Can't initiate read");
179                 return -1;
180         }
181
182
183         rsetbit(I2C_CR1, 10); // send ack if Master receives data
184 //      data_recv();
185 //      char c = *I2C_DR;
186 //      printf("%d:%p\n", addr, c);
187         for (int i = 0; i < BUFFER ; i++ ) {
188                 data_recv();
189                 buf[i] = (char) *I2C_DR;
190         }
191
192         printf("%p, %p, %p, %p\n", *I2C_SR1, *I2C_SR2, *I2C_DR, *I2C_CR1);
193         printf("DATA: %s\n", buf);
194
195 }
196
197 void at24c_run() {
198
199 //      char * global_data = "abcdefghijklmnop";
200
201 //      eeprom_write(0x0080, global_data, strlen(global_data));
202         
203 //      delay();
204
205 //      for (int i = 0; i < 0xFFFF; i++) { 
206 //              eeprom_read(i);
207 //              delay();
208 //      }
209
210         //delay();
211
212         eeprom_read(0x0000);
213
214 //W     uint32_t statusr;
215 //W
216 //W     start_condition();
217 //W     rwrite(I2C_DR, WRITE_CMD); // write to address CMD
218 //W     if(!ack_recv())
219 //W             cputs("CAN'T REACH DEVICE");
220 //W
221 //W     rwrite(I2C_DR, 0x00);
222 //W     if(!buf_empty())
223 //W             cputs("FAIL");
224 //W     rwrite(I2C_DR, 0x03);
225 //W     if(!buf_empty()) 
226 //W             cputs("FAIL");
227 //W     //rwrite(I2C_DR, 0x61);
228 //W     //if(!buf_empty())
229 //W     //      cputs("FAIL");
230 //W
231 //W     //statusr = *I2C_SR1;
232 //W     //statusr = *I2C_SR2;
233 //W     stop_condition();
234
235 //      start_condition();
236 //      rwrite(I2C_DR, 0xA0); // dummy write
237 //      if(!ack_recv())
238 //              cputs("CAN'T REACH DEVICE");
239 //
240 //      rwrite(I2C_DR, 0x00);
241 //      if(!buf_empty())
242 //              cputs("FAIL");
243 //      rwrite(I2C_DR, 0x00);
244 //      if(!buf_empty()) 
245 //              cputs("FAIL");
246 //
247 //W     delay();
248 //W
249 //W     start_condition(); // restart condition
250 //W     rwrite(I2C_DR, 0xA1); // read? to address CMD
251 //W     if(!ack_recv())
252 //W             cputs("COULDN'T START READ CMD");
253 //W
254 //W
255 //W     data_recv();
256 //W             //cputs("NO RESPONSE");
257 //W
258 //W     char a = (char) *I2C_DR;
259 //W     printf("DATA %c\n", a); 
260 //W
261 //W     stop_condition();
262         //delay();
263
264         //start_condition();
265         //statusr = *I2C_SR1; // clear start_signal
266         //regw_u32(I2C_DR, 0xC1, 0, OWRITE);
267         //if(!ack_recv())
268         //      cputs("TIMEOUT2!");
269         //statusr = *I2C_SR1;
270         //statusr = *I2C_SR2;
271         //regw_u32(I2C_DR, 0x7D, 0, OWRITE);
272         //if(!buf_empty())
273         //      cputs("TIMEOUT3!");
274         //stop_condition();
275
276 /*      delay();
277
278         start_condition();
279         statusr = *I2C_SR1;
280         regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE);
281         if(!ack_recv())
282                 cputs("TIMEOUT4!");
283         stop_condition(); */
284
285
286         /* regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
287         uint32_t read_status = *I2C_SR1; 
288         regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD
289         read_status = *I2C_SR1;
290         read_status = *I2C_SR2;
291         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
292         read_status = *I2C_SR1;
293
294         regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
295         read_status = *I2C_SR1;
296         regw_u32(I2C_DR, 0xC1, 0, OWRITE); // segment address
297         read_status = *I2C_SR1;
298         read_status = *I2C_SR2;
299         regw_u32(I2C_DR, 0x7D, 0, OWRITE); // write a six
300
301         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
302         read_status = *I2C_SR1;
303
304         regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
305         read_status = *I2C_SR1;
306
307         regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE);
308         read_status = *I2C_SR1;
309         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop */
310
311 }
312
313