1 /*
2 * Copyright (c) 2021 Titouan Christophe
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "display_7seg.h"
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/sys/printk.h>
12
13 const uint8_t DISPLAY_OFF[4] = { CHAR_OFF, CHAR_OFF, CHAR_OFF, CHAR_OFF };
14 const uint8_t TEXT_Err[4] = { CHAR_E, CHAR_r, CHAR_r, CHAR_OFF };
15
16 static bool initialized;
17 static const struct device *const expander1 =
18 DEVICE_DT_GET(DT_NODELABEL(expander1_x_nucleo_53l0a1));
19 static const struct device *const expander2 =
20 DEVICE_DT_GET(DT_NODELABEL(expander2_x_nucleo_53l0a1));
21 static const uint8_t digits[16] = {
22 CHAR_0,
23 CHAR_1,
24 CHAR_2,
25 CHAR_3,
26 CHAR_4,
27 CHAR_5,
28 CHAR_6,
29 CHAR_7,
30 CHAR_8,
31 CHAR_9,
32 CHAR_A,
33 CHAR_b,
34 CHAR_C,
35 CHAR_d,
36 CHAR_E,
37 CHAR_F,
38 };
39
40 static const int max_positive_for_base[17] = {
41 0,
42 1,
43 16,
44 81,
45 256,
46 625,
47 1296,
48 2401,
49 4096,
50 6561,
51 10000,
52 14641,
53 20736,
54 28561,
55 38416,
56 50625,
57 65536,
58 };
59
60 static const int max_negative_for_base[17] = {
61 -0,
62 -1,
63 -8,
64 -27,
65 -64,
66 -125,
67 -216,
68 -343,
69 -512,
70 -729,
71 -1000,
72 -1331,
73 -1728,
74 -2197,
75 -2744,
76 -3375,
77 -4096,
78 };
79
init_display(void)80 static int init_display(void)
81 {
82 int ret;
83
84 for (int i = 0; i < 14; i++) {
85 ret = gpio_pin_configure(expander1, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH);
86 if (ret) {
87 printk("Error in configure pin %d on expander1: %d", i, ret);
88 return ret;
89 }
90 ret = gpio_pin_configure(expander2, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH);
91 if (ret) {
92 printk("Error in configure pin %d on expander2: %d", i, ret);
93 return ret;
94 }
95 }
96
97 initialized = true;
98 return 0;
99 }
100
101
display_chars(const uint8_t chars[4])102 int display_chars(const uint8_t chars[4])
103 {
104 int r;
105 uint16_t port1, port2;
106
107 if (!initialized) {
108 r = init_display();
109 if (r) {
110 return r;
111 }
112 }
113
114 port1 = ((chars[3] & 0x7f) << 7) | (chars[2] & 0x7f);
115 port2 = ((chars[1] & 0x7f) << 7) | (chars[0] & 0x7f);
116
117 /* Common anode: invert the output (LOW = led on) */
118 r = gpio_port_set_masked(expander1, 0x3fff, port1 ^ 0x3fff);
119 if (r) {
120 return r;
121 }
122 return gpio_port_set_masked(expander2, 0x3fff, port2 ^ 0x3fff);
123 }
124
display_number(int num,unsigned int base)125 int display_number(int num, unsigned int base)
126 {
127 int d, i, neg = 0;
128 uint8_t representation[4] = { CHAR_E, CHAR_r, CHAR_r, CHAR_OFF };
129
130 /* Unsupported base */
131 if (base > 16) {
132 return -EINVAL;
133 }
134
135 /* Number too large to be displayed */
136 if (num <= max_negative_for_base[base] || num >= max_positive_for_base[base]) {
137 return -EINVAL;
138 }
139
140 if (num < 0) {
141 num = -num;
142 representation[0] = CHAR_DASH;
143 neg = 1;
144 }
145
146 for (i = 3; i >= neg; i--) {
147 if (num > 0 || i == 3) {
148 d = num % base;
149 representation[i] = digits[d];
150 num /= base;
151 } else {
152 representation[i] = CHAR_OFF;
153 }
154 }
155 return display_chars(representation);
156 }
157