blob: d812fccf980925d3dbb598c0edd947fa2713a941 [file] [log] [blame]
/*
* Copyright (c) 2021 Titouan Christophe
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "display_7seg.h"
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
const uint8_t DISPLAY_OFF[4] = { CHAR_OFF, CHAR_OFF, CHAR_OFF, CHAR_OFF };
const uint8_t TEXT_Err[4] = { CHAR_E, CHAR_r, CHAR_r, CHAR_OFF };
static bool initialized;
static const struct device *expander1 = DEVICE_DT_GET(DT_NODELABEL(expander1));
static const struct device *expander2 = DEVICE_DT_GET(DT_NODELABEL(expander2));
static const uint8_t digits[16] = {
CHAR_0,
CHAR_1,
CHAR_2,
CHAR_3,
CHAR_4,
CHAR_5,
CHAR_6,
CHAR_7,
CHAR_8,
CHAR_9,
CHAR_A,
CHAR_b,
CHAR_C,
CHAR_d,
CHAR_E,
CHAR_F,
};
static const int max_positive_for_base[17] = {
0,
1,
16,
81,
256,
625,
1296,
2401,
4096,
6561,
10000,
14641,
20736,
28561,
38416,
50625,
65536,
};
static const int max_negative_for_base[17] = {
-0,
-1,
-8,
-27,
-64,
-125,
-216,
-343,
-512,
-729,
-1000,
-1331,
-1728,
-2197,
-2744,
-3375,
-4096,
};
static int init_display(void)
{
int ret;
for (int i = 0; i < 14; i++) {
ret = gpio_pin_configure(expander1, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH);
if (ret) {
printk("Error in configure pin %d on expander1: %d", i, ret);
return ret;
}
ret = gpio_pin_configure(expander2, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH);
if (ret) {
printk("Error in configure pin %d on expander2: %d", i, ret);
return ret;
}
}
initialized = true;
return 0;
}
int display_chars(const uint8_t chars[4])
{
int r;
uint16_t port1, port2;
if (!initialized) {
r = init_display();
if (r) {
return r;
}
}
port1 = ((chars[3] & 0x7f) << 7) | (chars[2] & 0x7f);
port2 = ((chars[1] & 0x7f) << 7) | (chars[0] & 0x7f);
/* Common anode: invert the output (LOW = led on) */
r = gpio_port_set_masked(expander1, 0x3fff, port1 ^ 0x3fff);
if (r) {
return r;
}
return gpio_port_set_masked(expander2, 0x3fff, port2 ^ 0x3fff);
}
int display_number(int num, unsigned int base)
{
int d, i, neg = 0;
uint8_t representation[4] = { CHAR_E, CHAR_r, CHAR_r, CHAR_OFF };
/* Unsupported base */
if (base > 16) {
return -EINVAL;
}
/* Number too large to be displayed */
if (num <= max_negative_for_base[base] || num >= max_positive_for_base[base]) {
return -EINVAL;
}
if (num < 0) {
num = -num;
representation[0] = CHAR_DASH;
neg = 1;
}
for (i = 3; i >= neg; i--) {
if (num > 0 || i == 3) {
d = num % base;
representation[i] = digits[d];
num /= base;
} else {
representation[i] = CHAR_OFF;
}
}
return display_chars(representation);
}