517e0cf574e2bb4a8538bdba1e6759b66dca0d53
[cortex-from-scratch] / drivers / tm1637.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  * Basic driver for the TM1637. The TM1637 is 8 segment
9  * ledclock peripheral. Communication is similar to I2C,
10  * but not completely. There is no address selecting.
11  *
12  * Alternative I2C protocol : (W)rite or (R)ead
13  * | Start | ADDRESS | W | ACK/NACK | DATA | ACK/NACK | (d+a*n) | St
14  * | Start | ADDRESS | R | ACK/NACK | DATA | ACK/NACK | (d+a*n) | St
15  *
16  * */
17
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21
22 #include <sys/mmap.h>
23 #include <sys/robsys.h>
24
25 #include <lib/regfunc.h>
26 #include <lib/string.h>
27 #include <lib/stdio.h>
28
29 #include <drivers/tm1637.h>
30
31 #define TIMEOUT 1000
32
33 #define DATASET 0x40
34 #define CONTROL 0x80
35 #define SETADDR 0xC0
36
37 #define DISPLAY_ON      0x8F
38 #define DISPLAY_OFF     0x11
39
40 /* STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their
41 GPIOs must be configured as open-drain. So, you have to add two additional resistors to
42 pull-up I2C lines. Something between 4K and 10K is a proven value.
43 */
44
45 void tm1637_init() {
46
47  /* Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings
48  Configure the clock control registers CCR
49  Configure the rise time register TRIS
50  Program the I2C_CR1 register to enable the peripheral
51
52  ENABLE GPIOB6 and B7*/
53
54  regw_u32(RCC_APB1ENR, 0x1, 21, SETBIT);
55  regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT);
56  // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ?
57  
58  regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE);
59
60  regw_u32(I2C_CR2, 0x2, 0, OWRITE); //2 MHz 
61  regw_u8(I2C_TRISE, 0x3, 0, OWRITE); // MAX = 1000ns, TPCLK1 = 500ns (+1)
62  regw_u32(I2C_CCR, 0x000A, 0, OWRITE); // standard modeļ¼Œ output 100 kHz (100hz* / perip)
63  
64  regw_u32(I2C_CR1, 0x1, 0, OWRITE); // enable
65
66 }
67
68 static void start_condition() {
69
70         regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
71
72 }
73
74 static void stop_condition() {
75
76         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
77 }
78
79 int ack_recv() {
80
81         int cnt = 0;
82         while(!(*I2C_SR1 & 0x1)) {
83                 cnt++;
84                 if (cnt > TIMEOUT)
85                         return 0;
86         }
87
88         return 1;
89
90 }
91
92 int delay() {
93
94         int a = 0;
95         for (int i = 0; i < TIMEOUT; i++)
96                 a++;
97 }
98
99 void tm1637_start() {
100
101 //      regw_u32(I2C_CR1, 0x1, 8, SETBIT);
102 //      uint32_t read_status = *I2C_SR1;
103
104 //      regw_u32(I2C_DR, DATASET, 0, OWRITE); 
105         // conform DATA
106 //      read_status = *I2C_SR1;
107 //      read_status = *I2C_SR2;
108
109         uint32_t statusr;
110
111         start_condition();
112         //uint32_t statusr = *I2C_SR1; // clear start_signal
113         regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD
114         if(!ack_recv())
115                 cputs("TIMEOUT!");
116         //statusr = *I2C_SR1;
117         //statusr = *I2C_SR2;
118         stop_condition();
119
120         //delay();
121
122         start_condition();
123         //statusr = *I2C_SR1; // clear start_signal
124         regw_u32(I2C_DR, 0xC1, 0, OWRITE);
125         if(!ack_recv())
126                 cputs("TIMEOUT2!");
127         //statusr = *I2C_SR1;
128         //statusr = *I2C_SR2;
129         regw_u32(I2C_DR, 0x7D, 0, OWRITE);
130         if(!ack_recv())
131                 cputs("TIMEOUT3!");
132         stop_condition();
133
134         delay();
135
136         start_condition();
137         statusr = *I2C_SR1;
138         regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE);
139         if(!ack_recv())
140                 cputs("TIMEOUT4!");
141         stop_condition();
142
143
144         /* regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
145         uint32_t read_status = *I2C_SR1; 
146         regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD
147         read_status = *I2C_SR1;
148         read_status = *I2C_SR2;
149         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
150         read_status = *I2C_SR1;
151
152         regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
153         read_status = *I2C_SR1;
154         regw_u32(I2C_DR, 0xC1, 0, OWRITE); // segment address
155         read_status = *I2C_SR1;
156         read_status = *I2C_SR2;
157         regw_u32(I2C_DR, 0x7D, 0, OWRITE); // write a six
158
159         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
160         read_status = *I2C_SR1;
161
162         regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
163         read_status = *I2C_SR1;
164
165         regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE);
166         read_status = *I2C_SR1;
167         regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop */
168
169 }
170
171 void tm1637_stop() {
172
173         //regw_u32(I2C_CR1, 0x0, 9, SETBIT);
174 }
175
176
177