aboutsummaryrefslogtreecommitdiff
path: root/src/tm1637.c
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-03-19 11:24:39 +0100
committerlonkaars <loek@pipeframe.xyz>2022-03-19 11:24:39 +0100
commitb3344df3e3a3594f133c2c051df981d75e0112b8 (patch)
tree2c61bc9d4c67afa9b6d9794fdad041bc85260927 /src/tm1637.c
initial commit (i think my display is broken)
Diffstat (limited to 'src/tm1637.c')
-rw-r--r--src/tm1637.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/tm1637.c b/src/tm1637.c
new file mode 100644
index 0000000..4e6e68c
--- /dev/null
+++ b/src/tm1637.c
@@ -0,0 +1,110 @@
+#include "main.h"
+#include "tm1637.h"
+#include "stm32f091xc.h"
+
+void _tm1637_micro_delay() {
+ timer_delay(10);
+ // for(unsigned int x = 0; x < 10e4; x++);
+}
+
+/** @brief reset gpio mode registers for dio */
+void _tm1637_GPIOMODE_reset() {
+ GPIOA->MODER &= ~(0b11 << (PINOUT_DISP_DIO * 2));
+ GPIOA->PUPDR &= ~(0b11 << (PINOUT_DISP_DIO * 2));
+ GPIOA->OTYPER &= ~(0b1 << PINOUT_DISP_DIO);
+}
+
+/** @brief set dio to general-purpose output mode */
+void _tm1637_GPIOMODE_gp_output() {
+ _tm1637_GPIOMODE_reset();
+
+ GPIOA->MODER |= (0b01 << (PINOUT_DISP_DIO * 2));
+}
+
+/** @brief set dio to open drain input mode */
+void _tm1637_GPIOMODE_open_drain() {
+ _tm1637_GPIOMODE_reset();
+
+ GPIOA->MODER |= (0b10 << (PINOUT_DISP_DIO * 2));
+ GPIOA->OTYPER |= (0b1 << PINOUT_DISP_DIO);
+}
+
+/**
+ * @brief gpio write abstraction function
+ * @param pin pin to write
+ * @param state state to set `pin` to
+ */
+void _tm1637_pin_write(uint32_t pin, bool state) {
+ GPIOA->ODR ^= (((GPIOA->ODR & (1 << pin)) >> pin) ^ state) << pin;
+
+ if (pin == PINOUT_DISP_CLK) led_write(0, state);
+ if (pin == PINOUT_DISP_DIO) led_write(1, state);
+}
+
+void tm1637_begin() {
+ _tm1637_GPIOMODE_gp_output();
+
+ // general purpose output mode for clk
+ GPIOA->MODER &= ~(0b11 << (PINOUT_DISP_CLK * 2));
+ GPIOA->MODER |= (0b01 << (PINOUT_DISP_CLK * 2));
+
+ _tm1637_pin_write(PINOUT_DISP_CLK, 1);
+ _tm1637_pin_write(PINOUT_DISP_DIO, 1);
+
+ _tm1637_micro_delay();
+}
+
+void _tm1637_start() {
+ _tm1637_pin_write(PINOUT_DISP_DIO, 0);
+ _tm1637_micro_delay();
+}
+
+void _tm1637_stop() {
+ _tm1637_pin_write(PINOUT_DISP_CLK, 1);
+ _tm1637_pin_write(PINOUT_DISP_DIO, 1);
+ _tm1637_micro_delay();
+}
+
+bool _tm1637_ack() {
+ _tm1637_pin_write(PINOUT_DISP_CLK, 0);
+ _tm1637_pin_write(PINOUT_DISP_DIO, 0);
+ _tm1637_GPIOMODE_open_drain();
+ _tm1637_micro_delay();
+ _tm1637_pin_write(PINOUT_DISP_CLK, 1);
+ _tm1637_micro_delay();
+ _tm1637_pin_write(PINOUT_DISP_CLK, 0);
+ _tm1637_GPIOMODE_gp_output();
+ _tm1637_micro_delay();
+ return true;
+}
+
+/**
+ * @brief send data to TM1637
+ * @param command command to send
+ * @return response data as TM1637Response struct
+ */
+TM1637Sequence _tm1637_send(TM1637Sequence command) {
+ TM1637Sequence response = { .data = 0, .length = 0 };
+
+ _tm1637_start();
+
+ for (uint32_t byte = 0; byte < command.length; byte++) {
+ for (uint8_t bit = 0; bit < 8; bit++) {
+ uint8_t rev_bit = 7 - bit;
+ _tm1637_pin_write(PINOUT_DISP_CLK, 0);
+ _tm1637_pin_write(PINOUT_DISP_DIO, (command.data[byte] & (1 << rev_bit)) >> rev_bit);
+ _tm1637_micro_delay();
+ _tm1637_pin_write(PINOUT_DISP_CLK, 1);
+ _tm1637_micro_delay();
+ }
+ //TODO: confirm ack
+ /*bool ack =*/ _tm1637_ack();
+ }
+
+ _tm1637_micro_delay();
+
+ // stop condition
+ _tm1637_stop();
+
+ return response;
+}