/** ASCII characters encoded for the 7 segments digit block
*@notestartswithspace
*/
staticconstuint8_tascii_7segments[]={
0x00,// 0b00000000 space
0x30,// 0b00110000 ! (I)
0x22,// 0b00100010 "
0x5c,// 0b01011100 # (o)
0x6d,// 0b01101101 $ (s)
0x52,// 0b01010010 % (/)
0x7d,// 0b01111101 & (6)
0x20,// 0b00100000 '
0x39,// 0b00111001 ( ([)
0x0f,// 0b00001111 )
0x70,// 0b01110000 *
0x46,// 0b01000110 +
0x10,// 0b00010000 ,
0x40,// 0b01000000 -
0x10,// 0b00010000 . (,)
0x52,// 0b01010010 /
0x3f,// 0b00111111 0
0x06,// 0b00000110 1
0x5b,// 0b01011011 2
0x4f,// 0b01001111 3
0x66,// 0b01100110 4
0x6d,// 0b01101101 5
0x7d,// 0b01111101 6
0x07,// 0b00000111 7
0x7f,// 0b01111111 8
0x6f,// 0b01101111 9
0x48,// 0b01001000 : (=)
0x48,// 0b01001000 ; (=)
0x58,// 0b01011000 <
0x48,// 0b01001000 =
0x4c,// 0b01001100 >
0x53,// 0b01010011 ?
0x7b,// 0b01111011 @
0x77,// 0b01110111 A
0x7f,// 0b01111111 B
0x39,// 0b00111001 C
0x5e,// 0b01011110 D
0x79,// 0b01111001 E
0x71,// 0b01110001 F
0x3d,// 0b00111101 G
0x76,// 0b01110110 H
0x30,// 0b00110000 I
0x1e,// 0b00011110 J
0x76,// 0b01110110 K
0x38,// 0b00111000 L
0x37,// 0b00110111 M
0x37,// 0b00110111 N
0x3f,// 0b00111111 O
0x73,// 0b01110011 P
0x6b,// 0b01101011 Q
0x33,// 0b00110011 R
0x6d,// 0b01101101 S
0x78,// 0b01111000 T
0x3e,// 0b00111110 U
0x3e,// 0b00111110 V (U)
0x3e,// 0b00111110 W (U)
0x76,// 0b01110110 X (H)
0x6e,// 0b01101110 Y
0x5b,// 0b01011011 Z
0x39,// 0b00111001 [
0x64,// 0b01100100 '\'
0x0f,// 0b00001111 /
0x23,// 0b00100011 ^
0x08,// 0b00001000 _
0x02,// 0b00000010 `
0x5f,// 0b01011111 a
0x7c,// 0b01111100 b
0x58,// 0b01011000 c
0x5e,// 0b01011110 d
0x7b,// 0b01111011 e
0x71,// 0b01110001 f
0x6f,// 0b01101111 g
0x74,// 0b01110100 h
0x10,// 0b00010000 i
0x0c,// 0b00001100 j
0x76,// 0b01110110 k
0x30,// 0b00110000 l
0x54,// 0b01010100 m
0x54,// 0b01010100 n
0x5c,// 0b01011100 o
0x73,// 0b01110011 p
0x67,// 0b01100111 q
0x50,// 0b01010000 r
0x6d,// 0b01101101 s
0x78,// 0b01111000 t
0x1c,// 0b00011100 u
0x1c,// 0b00011100 v (u)
0x1c,// 0b00011100 w (u)
0x76,// 0b01110110 x
0x6e,// 0b01101110 y
0x5b,// 0b01011011 z
0x39,// 0b00111001 { ([)
0x30,// 0b00110000 |
0x0f,// 0b00001111 } ([)
0x40,// 0b01000000 ~
};
voidled_tm1637_setup(void)
{
// configure GPIO for CLK and DIO signals
rcc_periph_clock_enable(RCC_GPIO(LED_TM1637_CLK_PORT));// enable clock for GPIO peripheral
gpio_set(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// idle high
gpio_set_mode(GPIO(LED_TM1637_CLK_PORT),GPIO_MODE_OUTPUT_10_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(LED_TM1637_CLK_PIN));// master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
rcc_periph_clock_enable(RCC_GPIO(LED_TM1637_DIO_PORT));// enable clock for GPIO peripheral
gpio_set(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN));// idle high
gpio_set_mode(GPIO(LED_TM1637_DIO_PORT),GPIO_MODE_OUTPUT_10_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(LED_TM1637_DIO_PIN));// master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
// first clock then data high also stands for stop condition
// setup timer to create signal timing (each tick is used for a single GPIO transition)
rcc_periph_clock_enable(RCC_TIM(LED_TM1637_TIMER));// enable clock for timer block
timer_reset(TIM(LED_TM1637_TIMER));// reset timer state
timer_set_mode(TIM(LED_TM1637_TIMER),TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);// set timer mode, use undivided timer clock, edge alignment (simple count), and count up
timer_set_prescaler(TIM(LED_TM1637_TIMER),0);// don't prescale to get most precise timing ( 1/(72E6/1/(2**16))=0.91 ms > 0.5 us )
timer_set_period(TIM(LED_TM1637_TIMER),500);// set the clock frequency (emprical value until the signal starts to look bad)
timer_clear_flag(TIM(LED_TM1637_TIMER),TIM_SR_UIF);// clear flag
timer_update_on_overflow(TIM(LED_TM1637_TIMER));// only use counter overflow as UEV source (use overflow as start time or timeout)
}
/** wait until clock tick (timer overflow) occurred
*/
staticinlinevoidled_tm1637_tick(void)
{
while(!timer_get_flag(TIM(LED_TM1637_TIMER),TIM_SR_UIF));// wait until counter overflow update event happens
timer_clear_flag(TIM(LED_TM1637_TIMER),TIM_SR_UIF);// clear event flag
timer_enable_counter(TIM(LED_TM1637_TIMER));// enable timer to generate timing
led_tm1637_tick();// wait to enforce minimum time since last write
// send start condition (DIO then CLK low)
gpio_clear(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN));// put DIO low
led_tm1637_tick();// wait for next tick
gpio_clear(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK low
// send data bytes (MSb first)
for(size_ti=0;i<length;i++){// send all bytes
uint8_tbyte=data[i];
for(uint8_tb=0;b<8;b++){// send all bits
if(byte&0x1){// send a 1
gpio_set(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN));// put DIO high
}else{
gpio_clear(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN));// put DIO low
}
byte>>=1;// shift data
led_tm1637_tick();// wait for next tick
gpio_set(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK high
led_tm1637_tick();// wait for next tick (no DIO transition when CLK is high)
gpio_clear(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK low
}
gpio_set_mode(GPIO(LED_TM1637_DIO_PORT),GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO(LED_TM1637_DIO_PIN));// switch DIO as input to read ACK
led_tm1637_tick();// wait for next tick (when the slave should ACK)
gpio_set(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK high
if(gpio_get(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN))){// no ACK received
to_return=false;// remember there was an error
break;// stop sending bytes
}
led_tm1637_tick();// wait for next tick
gpio_clear(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK low
gpio_set_mode(GPIO(LED_TM1637_DIO_PORT),GPIO_MODE_OUTPUT_2_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(LED_TM1637_DIO_PIN));// switch DIO back to output to send next byte
}
// send stop condition
gpio_set_mode(GPIO(LED_TM1637_DIO_PORT),GPIO_MODE_OUTPUT_2_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(LED_TM1637_DIO_PIN));// ensure DIO is output (in case no ACK as been received
led_tm1637_tick();// wait for next tick
gpio_set(GPIO(LED_TM1637_CLK_PORT),GPIO(LED_TM1637_CLK_PIN));// put CLK high
led_tm1637_tick();// wait for next tick
gpio_set(GPIO(LED_TM1637_DIO_PORT),GPIO(LED_TM1637_DIO_PIN));// put DIO high
timer_disable_counter(TIM(LED_TM1637_TIMER));// stop timer since it's not used anymore
returnto_return;
}
boolled_tm1637_on(void)
{
uint8_tdata[]={0x88+display_brightness};// command to turn display on (use set brightness)
if(display_on){// adjust brightness if display is on
returnled_tm1637_on();// adjust brightness
}else{
returntrue;// command succeeded
}
returnfalse;
}
boolled_tm1637_number(uint16_tnumber)
{
uint8_twrite_data[]={0x40};// command: write data, automatic address adding, normal
uint8_tdata[]={0xc0,ascii_7segments[((number/1000)%10)+'0'-''],ascii_7segments[((number/100)%10)+'0'-''],ascii_7segments[((number/10)%10)+'0'-''],ascii_7segments[((number/1)%10)+'0'-'']};// set address C0H and add data
uint8_twrite_data[]={0x40};// command: write data, automatic address adding, normal
uint8_tdata[]={0xc0,ascii_7segments[((hours/10)%10)+'0'-''],ascii_7segments[((hours/1)%10)+'0'-'']|0x80,ascii_7segments[((minutes/10)%10)+'0'-''],ascii_7segments[((minutes/1)%10)+'0'-'']};// set address C0H and add data
uint8_twrite_data[]={0x40};// command: write data, automatic address adding, normal
uint8_tdata[]={0xc0,ascii_7segments[(text[0]&0x7f)-'']|(text[0]&0x80),ascii_7segments[(text[1]&0x7f)-'']|(text[1]&0x80),ascii_7segments[(text[2]&0x7f)-'']|(text[2]&0x80),ascii_7segments[(text[3]&0x7f)-'']|(text[3]&0x80)};// set address C0H and add data