1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/7/25 - ROBIN KRENS
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.
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
23 #include <sys/robsys.h>
25 #include <lib/regfunc.h>
26 #include <lib/string.h>
27 #include <lib/stdio.h>
29 #include <drivers/tm1637.h>
50 /* STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their
51 GPIOs must be configured as open-drain. So, you have to add two additional resistors to
52 pull-up I2C lines. Something between 4K and 10K is a proven value.
59 /* Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings
60 Configure the clock control registers CCR
61 Configure the rise time register TRIS
62 Program the I2C_CR1 register to enable the peripheral
64 ENABLE GPIOB6 and B7*/
66 regw_u32(RCC_APB1ENR, 0x1, 21, SETBIT);
67 regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT);
68 // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ?
70 regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE);
72 regw_u32(I2C_CR2, 0x2, 0, OWRITE); //2 MHz
73 regw_u8(I2C_TRISE, 0x3, 0, OWRITE); // MAX = 1000ns, TPCLK1 = 500ns (+1)
74 regw_u32(I2C_CCR, 0x000A, 0, OWRITE); // standard mode, output 100 kHz (100hz* / perip)
76 regw_u32(I2C_CR1, 0x1, 0, OWRITE); // enable
82 regw_u32(RCC_APB1RSTR, 0x1, 21, SETBIT);
84 regw_u32(RCC_APB1RSTR, 0x00000000, 0, OWRITE); // clr
85 //regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT);
86 // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ?
88 regw_u32(RCC_APB1ENR, 0x1, 21, SETBIT);
89 //regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE);
91 regw_u32(I2C_CR2, 0x2, 0, OWRITE); //2 MHz
92 regw_u8(I2C_TRISE, 0x3, 0, OWRITE); // MAX = 1000ns, TPCLK1 = 500ns (+1)
93 regw_u32(I2C_CCR, 0x000A, 0, OWRITE); // standard mode, output 100 kHz (100hz* / perip)
95 regw_u32(I2C_CR1, 0x1, 0, OWRITE); // enable
100 static void start_condition() {
102 regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
106 static void stop_condition() {
108 regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop
111 static int buf_empty() {
113 while(!(*I2C_SR1 & 0x80)) {
125 while(!(*I2C_SR1 & 0x2)) {
130 uint32_t a = *I2C_SR2;
138 while(!(*I2C_SR1 & 0x8)) {
143 //uint32_t a = *I2C_SR2;
150 while(*I2C_SR2 & 0x2) {
162 for (int i = 0; i < TIMEOUT; i++)
169 for (int i = 0; i < (TIMEOUT * 150 ); i++)
173 void set_display(bool on, uint8_t degree) {
177 regw_u32(I2C_DR, 0xF1, 0, OWRITE);
179 cputs("Can't switch on display!");
183 regw_u32(I2C_CR1, 0x1, 15, SETBIT);
188 void set_segment(int offset, char value, bool dot) {
190 // int (ack_recv*)(void) = &ack_recv;
193 // ack_recv = &ack_recv;
196 cputs("Offset incorrect");
202 int start_pos_cmd = 0x03 | (offset & 0x01) << 7 | (offset & 0x2) << 5 ;
205 regw_u32(I2C_DR, 0x20, 0, OWRITE);
207 cputs("Error: initiating write for start segment \n");
212 cputs("Error: timeout");
215 regw_u32(I2C_DR, start_pos_cmd, 0, OWRITE);
217 cputs("Error: Can't set start segment \n");
220 regw_u32(I2C_CR1, 0x1, 15, SETBIT);
225 regw_u32(I2C_DR, value, 0, OWRITE); // use ack10 if higher
227 cputs("Error: can't set location\n");
231 regw_u32(I2C_CR1, 0x1, 15, SETBIT);
233 // cputs("Error: timeout");
241 void tm1637_start() {
243 unsigned char display_number[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
246 char love[4] = { 0x1C, 0xFC, 0x7C, 0x9E };
248 for (int i = 0; i < 4; i++) {
249 set_segment(i, love[i], NODOT);
252 set_display(true, 0);