#include <drivers/tm1637.h>
-#define TIMEOUT 1000
+#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
}
+ 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
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;
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);
+ }
/* SYSTEM INFO AND DEBUG */
#define MCU_ID MEM_ADDR(0xE000ED00)
-#define FLASH_MEM MEM_ADDR(0x1FFFF000)
+#define FLASH_MEM MEM_ADDR(0x1FFFF000)
+
+/* POWER CONTROL REGISTERS */
+#define PWR_CR MEM_ADDR(0x40007000)
/* SYSTEM CONTROL BLOCK REGISTER */
#define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
/* SYSTICK REGISTER */
#define STK_CTRL MEM_ADDR(0xE000E010)
#define STK_RELOAD MEM_ADDR(0xE000E014)
+#define STK_CALIB MEM_ADDR(0xE000E01C)
-/* CLOCK REGISTER */
+/* RESET AND CLOCK REGISTER */
#define RCC_CR MEM_ADDR(0x40021000)
#define RCC_CFGR MEM_ADDR(0x40021004)
+#define RCC_BDCR MEM_ADDR(0x40021020)
/* 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)
#define GPIOPA_AFSEL MEM_ADDR(0x40004420)
#define GPIOA_CRH MEM_ADDR(0x40010804) // for USART1
+#define GPIOA_ODR MEM_ADDR(0x4001080C)
#define GPIOB_CRL MEM_ADDR(0x40010C00) // low register (!) for I2C1
-#define GPIOC_CRL MEM_ADDR(0x40011000) // for led
-#define GPIOC_ODR MEM_ADDR(0x4001100C) //
+#define GPIOB_BSRR MEM_ADDR(0x40010C10)
+#define GPIOC_CRL MEM_ADDR(0x40011000) // led
+#define GPIOC_CRH MEM_ADDR(0x40011004)
+#define GPIOC_ODR MEM_ADDR(0x4001100C)
+
+#define GPIOD_CRL MEM_ADDR(0x40011400)
+#define GPIOD_ODR MEM_ADDR(0x4001140C)
#define AFIO_EVCR MEM_ADDR(0x40010000)
#define USART1_CR1 MEM_ADDR(0x4001380C)
#define USART1_CR2 MEM_ADDR(0x40013810)
#define USART1_CR3 MEM_ADDR(0x40013814)
+
+/* REAL TIME CLOCK REGISTERS */
+#define RTC_CRH MEM_ADDR(0x40002800) // interrupts
+#define RTC_CRL MEM_ADDR(0x40002804)
+#define RTC_PRLL MEM_ADDR(0x4000280C)
+#define RTC_CNTH MEM_ADDR(0x40002818)
+#define RTC_CNTL MEM_ADDR(0x4000281C)
+/* BACKUP (CALIBR) REGISTERS */
+#define BKP_RTCCR MEM_ADDR(0x40006C2C) // RTC Calibration
+
+#define TIM4_CR1 MEM_ADDR(0x40000800)
+#define TIM4_RCR MEM_ADDR(0x40000830)
+#define TIM4_ARR MEM_ADDR(0x4000082C)
+#define TIM4_EGR MEM_ADDR(0x40000814)
+#define TIM4_SR1 MEM_ADDR(0x40000810)
+#define TIM4_CCR1 MEM_ADDR(0x40000834)
+#define TIM4_CCR2 MEM_ADDR(0x40000838)
+#define TIM4_PSC MEM_ADDR(0x40000828)
+#define TIM4_SMCR MEM_ADDR(0x40000808)
+#define TIM4_CCER MEM_ADDR(0x40000820)
+//#define TIM1_BDTR MEM_ADDR(0x40000844)
+#define TIM4_CCMR1 MEM_ADDR(0x40000818)
+#define TIM4_DIER MEM_ADDR(0x4000080C)