summaryrefslogtreecommitdiffstats
path: root/chars/chars.c
blob: de72a1085ac970eca2c1c146b6d6a9e6ecdb6842 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "../libleds.h"
#include "chars.h"

#include "space.xbm"
#include "0.xbm"
#include "1.xbm"
#include "2.xbm"
#include "3.xbm"
#include "4.xbm"
#include "5.xbm"
#include "6.xbm"
#include "7.xbm"
#include "8.xbm"
#include "9.xbm"

static unsigned char *get_char_bits(char c) {
	switch (c) {
		case ' ':
			return cspace_bits;
		case '0':
			return c0_bits;
		case '1':
			return c1_bits;
		case '2':
			return c2_bits;
		case '3':
			return c3_bits;
		case '4':
			return c4_bits;
		case '5':
			return c5_bits;
		case '6':
			return c6_bits;
		case '7':
			return c7_bits;
		case '8':
			return c8_bits;
		case '9':
			return c9_bits;
		default:
			return NULL;
	}
}

static char is_active(unsigned char const *bits, unsigned int const i)
{
	/*
	 * The first led is in the top left corner.
	 * After that it goes down the column, then up the next and so on.
	 *
	 * This means all columns with an even index count down.
	 * Those with an odd index count up.
	 *
	 *
	 * With a height of 8 the led numbers would look like this:
	 *
	 * 00  0F  10  1F  20  ...
	 * 01  0E  11  1E  21  ...
	 * 02  0D  12  1D  ...
	 * 03  0C  13  1C  ...
	 * 04  0B  14  1B  ...
	 * 05  0A  15  1A  ...
	 * 06  09  16  19  ...
	 * 07  08  17  18  ...
	 */

	unsigned int const bytes_per_row = ceil(char_width / 8.0);
	unsigned int col = i / char_height;
	unsigned int row = i % char_height;
	if (col % 2)
		row = char_height - 1 - row;
	
	// calculate byte to access
	unsigned int byte = row * bytes_per_row;
	byte += col / 8;

	unsigned char data = bits[byte];
	unsigned char mask = 1<<(col % 8);
	return data & mask;
}

static char leds_write_char(const struct led_color color, char c, struct led_color *buf)
{
	unsigned char *bits = get_char_bits(c);
	if (bits == NULL)
		return 0;

	for (unsigned int i = 0; i < char_length; i++) {
		if (is_active(bits, i))
			buf[i] = color;
		else
			buf[i] = (struct led_color){0, 0, 0};
	}

	return 1;
}

struct led_color *leds_text(struct led_color const color, const char *text)
{
	unsigned int const len = strlen(text);
	struct led_color *buf = calloc(
		sizeof(struct led_color), len * char_length
	);

	for (unsigned int i = 0; i < len; i++) {
		if (!leds_write_char(color, text[i], buf + i*char_length)) {
			// Invalid char
			free(buf);
			return NULL;
		}
	}

	return buf;
}