From: Robin Krens Date: Tue, 13 Aug 2019 16:49:37 +0000 (+0800) Subject: Merge branch 'tm1637' X-Git-Url: https://robinkrens.nl/gitweb/?p=cortex-from-scratch;a=commitdiff_plain;h=8b8d6edcd57f69b40f430bc172e1c290a629a6a9;hp=7036ca076ae2da712914c04409872eab2aadfbdb Merge branch 'tm1637' --- diff --git a/drivers/tm1637.c b/drivers/tm1637.c index a2889fd..8c8ce5b 100644 --- a/drivers/tm1637.c +++ b/drivers/tm1637.c @@ -30,18 +30,30 @@ #define TIMEOUT 5000 -#define DATASET 0x40 -#define CONTROL 0x80 -#define SETADDR 0xC0 - -#define DISPLAY_ON 0x8F -#define DISPLAY_OFF 0x11 +#define DOT true +#define NODOT false + + +/* +0 = 0x00 +1 = 0x60 +2 = 0xDA +3 = 0xF2 +4 = 0x66 +5 = 0xB6 +6 = 0xBE +7 = 0xE0 +8 = 0xFF +9 = 0xF6 +*/ /* STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their GPIOs must be configured as open-drain. So, you have to add two additional resistors to pull-up I2C lines. Something between 4K and 10K is a proven value. */ +/* BIG ENDIAN! */ + void tm1637_init() { /* Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings @@ -65,6 +77,26 @@ void tm1637_init() { } +void tm1637_reset() { + + regw_u32(RCC_APB1RSTR, 0x1, 21, SETBIT); + + regw_u32(RCC_APB1RSTR, 0x00000000, 0, OWRITE); // clr + //regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT); + // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ? + + regw_u32(RCC_APB1ENR, 0x1, 21, SETBIT); + //regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE); + + regw_u32(I2C_CR2, 0x2, 0, OWRITE); //2 MHz + regw_u8(I2C_TRISE, 0x3, 0, OWRITE); // MAX = 1000ns, TPCLK1 = 500ns (+1) + regw_u32(I2C_CCR, 0x000A, 0, OWRITE); // standard mode, output 100 kHz (100hz* / perip) + + regw_u32(I2C_CR1, 0x1, 0, OWRITE); // enable + + +} + static void start_condition() { regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start @@ -76,22 +108,45 @@ static void stop_condition() { regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop } -int ack_recv() { +static int buf_empty() { + int cnt = 0; + while(!(*I2C_SR1 & 0x80)) { + cnt++; + if (cnt > TIMEOUT) { + return 0; + } + } + return 1; +} +/* Wait for an acknowledge from the peripheral */ +int ack_recv() { int cnt = 0; while(!(*I2C_SR1 & 0x2)) { cnt++; if (cnt > TIMEOUT) return 0; } + uint32_t a = *I2C_SR2; // need to read SR2 register! + return 1; +} + +/* Similar, but SR2 register is not read */ +int ack10_recv() { + int cnt = 0; + while(!(*I2C_SR1 & 0x8)) { + cnt++; + if (cnt > TIMEOUT) + return 0; + } return 1; } -int buf_empty() { +int idle() { int cnt = 0; - while(!(*I2C_SR1 & 0x80)) { + while(*I2C_SR2 & 0x2) { cnt++; if (cnt > TIMEOUT) return 0; @@ -107,82 +162,85 @@ int delay() { a++; } -void tm1637_start() { +void set_display(bool on, uint8_t degree) { + + start_condition(); + + regw_u32(I2C_DR, 0xF1, 0, OWRITE); + if(!ack_recv()) + cputs("Can't switch on display!"); + stop_condition(); + + // reset bus + regw_u32(I2C_CR1, 0x1, 15, SETBIT); -// regw_u32(I2C_CR1, 0x1, 8, SETBIT); -// uint32_t read_status = *I2C_SR1; +} + + +void set_segment(int offset, char value, bool dot) { + + int (*ack)() = ack_recv; /* Scary function pointer :D */ -// regw_u32(I2C_DR, DATASET, 0, OWRITE); - // conform DATA -// read_status = *I2C_SR1; -// read_status = *I2C_SR2; - uint32_t statusr; + if (offset > 3) { + cputs("Offset incorrect"); + } + + if (dot) { + value = value | 0x1; + } + int start_pos_cmd = 0x03 | (offset & 0x01) << 7 | (offset & 0x2) << 5 ; start_condition(); - //uint32_t statusr = *I2C_SR1; // clear start_signal - regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD + regw_u32(I2C_DR, 0x20, 0, OWRITE); if(!ack_recv()) - cputs("TIMEOUT!"); - //statusr = *I2C_SR1; - //statusr = *I2C_SR2; + cputs("Error: initiating write for start segment \n"); + stop_condition(); + + if(!idle()) + cputs("Error: timeout"); - //delay(); start_condition(); - //statusr = *I2C_SR1; // clear start_signal - regw_u32(I2C_DR, 0xC1, 0, OWRITE); - if(!ack_recv()) - cputs("TIMEOUT2!"); - //statusr = *I2C_SR1; - //statusr = *I2C_SR2; - regw_u32(I2C_DR, 0x7D, 0, OWRITE); - if(!buf_empty()) - cputs("TIMEOUT3!"); + regw_u32(I2C_DR, start_pos_cmd, 0, OWRITE); + if(!ack()) + cputs("Error: Can't set start segment \n"); + stop_condition(); + regw_u32(I2C_CR1, 0x1, 15, SETBIT); + + tm1637_reset(); -/* delay(); +// if (value & 0xF0) +// ack = &ack10_recv; start_condition(); - statusr = *I2C_SR1; - regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE); + regw_u32(I2C_DR, value, 0, OWRITE); // use ack10 if higher if(!ack_recv()) - cputs("TIMEOUT4!"); - stop_condition(); */ + cputs("Error: can't set location\n"); + stop_condition(); + regw_u32(I2C_CR1, 0x1, 15, SETBIT); - /* regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start - uint32_t read_status = *I2C_SR1; - regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD - read_status = *I2C_SR1; - read_status = *I2C_SR2; - regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop - read_status = *I2C_SR1; + tm1637_reset(); +} - regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start - read_status = *I2C_SR1; - regw_u32(I2C_DR, 0xC1, 0, OWRITE); // segment address - read_status = *I2C_SR1; - read_status = *I2C_SR2; - regw_u32(I2C_DR, 0x7D, 0, OWRITE); // write a six - regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop - read_status = *I2C_SR1; - regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start - read_status = *I2C_SR1; +void tm1637_start() { - regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE); - read_status = *I2C_SR1; - regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop */ +unsigned char display_number[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6}; -} -void tm1637_stop() { + char love[4] = { 0x1C, 0xFC, 0x7C, 0x9E }; + + for (int i = 0; i < 4; i++) { + set_segment(i, love[i], NODOT); + } - //regw_u32(I2C_CR1, 0x0, 9, SETBIT); -} + set_display(true, 0); +} diff --git a/include/sys/mmap.h b/include/sys/mmap.h index db6cf5c..9aae914 100644 --- a/include/sys/mmap.h +++ b/include/sys/mmap.h @@ -59,6 +59,7 @@ /* SYSTEM CONTROL REGISTER */ #define SYSCTRL_RCC MEM_ADDR(0x40021000) #define RCC_APB1ENR MEM_ADDR(0x4002101C) // register to enable I2C +#define RCC_APB1RSTR MEM_ADDR(0x40021010) // register to reset I2C #define RCC_APB2ENR MEM_ADDR(0x40021018) // register to enable USART1 #define SYSCTRL_RIS MEM_ADDR(0x400FE050) diff --git a/include/sys/robsys.h b/include/sys/robsys.h index 78aedef..9a19a47 100644 --- a/include/sys/robsys.h +++ b/include/sys/robsys.h @@ -8,7 +8,7 @@ * These values are used throughout the code to calculator desired baud * rates etc. */ -#define ENABLE_HSE +//#define ENABLE_HSE //efine CRYSTAL_MHZ 8 //efine CLKSPEED_MHZ 72 extern void clock_init(); diff --git a/main.c b/main.c index 51c2b10..8455b46 100644 --- a/main.c +++ b/main.c @@ -67,12 +67,12 @@ void main() // run(); led_init(); - eeprom_at24c_init(); - eeprom_test(); +// eeprom_at24c_init(); +// eeprom_test(); // rtc_init(); -// tm1637_init(); -// tm1637_start(); + tm1637_init(); + tm1637_start(); //uint32_t test = hextoreg("12345678");