mirror of
https://github.com/jdillenburg/esphome.git
synced 2026-01-10 07:10:39 -07:00
matthiazzz - The current adxl345 component in ESPHome relies on multiple external Adafruit libraries (Adafruit Unified Sensor, Adafruit BusIO, Adafruit ADXL345). This causes unnecessary dependencies, compilation overhead, and sometimes incompatibilities when used with tca9548a multiplexers.
I modified the component to remove all Adafruit library dependencies and instead use a lightweight, self-contained ESPHome driver for ADXL345. After these changes, multiple ADXL345 sensors can be used in combination with a TCA9548A I²C multiplexer without conflicts.
This commit is contained in:
308
font_5x7_aa.h
Normal file
308
font_5x7_aa.h
Normal file
@@ -0,0 +1,308 @@
|
||||
// font_5x7_aa.h - 5x7 pixel anti-aliased font for LED Matrix
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// 5x7 font data - each character is 5 bytes (5 columns x 7 rows)
|
||||
// Bit 0 is top row, bit 6 is bottom row
|
||||
const uint8_t font_5x7[][5] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 32 space
|
||||
{0x00, 0x00, 0x5F, 0x00, 0x00}, // 33 !
|
||||
{0x00, 0x07, 0x00, 0x07, 0x00}, // 34 "
|
||||
{0x14, 0x7F, 0x14, 0x7F, 0x14}, // 35 #
|
||||
{0x24, 0x2A, 0x7F, 0x2A, 0x12}, // 36 $
|
||||
{0x23, 0x13, 0x08, 0x64, 0x62}, // 37 %
|
||||
{0x36, 0x49, 0x56, 0x20, 0x50}, // 38 &
|
||||
{0x00, 0x08, 0x07, 0x03, 0x00}, // 39 '
|
||||
{0x00, 0x1C, 0x22, 0x41, 0x00}, // 40 (
|
||||
{0x00, 0x41, 0x22, 0x1C, 0x00}, // 41 )
|
||||
{0x2A, 0x1C, 0x7F, 0x1C, 0x2A}, // 42 *
|
||||
{0x08, 0x08, 0x3E, 0x08, 0x08}, // 43 +
|
||||
{0x00, 0x80, 0x70, 0x30, 0x00}, // 44 ,
|
||||
{0x08, 0x08, 0x08, 0x08, 0x08}, // 45 -
|
||||
{0x00, 0x00, 0x60, 0x60, 0x00}, // 46 .
|
||||
{0x20, 0x10, 0x08, 0x04, 0x02}, // 47 /
|
||||
{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 48 0
|
||||
{0x00, 0x42, 0x7F, 0x40, 0x00}, // 49 1
|
||||
{0x72, 0x49, 0x49, 0x49, 0x46}, // 50 2
|
||||
{0x21, 0x41, 0x49, 0x4D, 0x33}, // 51 3
|
||||
{0x18, 0x14, 0x12, 0x7F, 0x10}, // 52 4
|
||||
{0x27, 0x45, 0x45, 0x45, 0x39}, // 53 5
|
||||
{0x3C, 0x4A, 0x49, 0x49, 0x31}, // 54 6
|
||||
{0x41, 0x21, 0x11, 0x09, 0x07}, // 55 7
|
||||
{0x36, 0x49, 0x49, 0x49, 0x36}, // 56 8
|
||||
{0x46, 0x49, 0x49, 0x29, 0x1E}, // 57 9
|
||||
{0x00, 0x00, 0x14, 0x00, 0x00}, // 58 :
|
||||
{0x00, 0x40, 0x34, 0x00, 0x00}, // 59 ;
|
||||
{0x00, 0x08, 0x14, 0x22, 0x41}, // 60 <
|
||||
{0x14, 0x14, 0x14, 0x14, 0x14}, // 61 =
|
||||
{0x00, 0x41, 0x22, 0x14, 0x08}, // 62 >
|
||||
{0x02, 0x01, 0x59, 0x09, 0x06}, // 63 ?
|
||||
{0x3E, 0x41, 0x5D, 0x59, 0x4E}, // 64 @
|
||||
{0x7C, 0x12, 0x11, 0x12, 0x7C}, // 65 A
|
||||
{0x7F, 0x49, 0x49, 0x49, 0x36}, // 66 B
|
||||
{0x3E, 0x41, 0x41, 0x41, 0x22}, // 67 C
|
||||
{0x7F, 0x41, 0x41, 0x41, 0x3E}, // 68 D
|
||||
{0x7F, 0x49, 0x49, 0x49, 0x41}, // 69 E
|
||||
{0x7F, 0x09, 0x09, 0x09, 0x01}, // 70 F
|
||||
{0x3E, 0x41, 0x41, 0x51, 0x73}, // 71 G
|
||||
{0x7F, 0x08, 0x08, 0x08, 0x7F}, // 72 H
|
||||
{0x00, 0x41, 0x7F, 0x41, 0x00}, // 73 I
|
||||
{0x20, 0x40, 0x41, 0x3F, 0x01}, // 74 J
|
||||
{0x7F, 0x08, 0x14, 0x22, 0x41}, // 75 K
|
||||
{0x7F, 0x40, 0x40, 0x40, 0x40}, // 76 L
|
||||
{0x7F, 0x02, 0x1C, 0x02, 0x7F}, // 77 M
|
||||
{0x7F, 0x04, 0x08, 0x10, 0x7F}, // 78 N
|
||||
{0x3E, 0x41, 0x41, 0x41, 0x3E}, // 79 O
|
||||
{0x7F, 0x09, 0x09, 0x09, 0x06}, // 80 P
|
||||
{0x3E, 0x41, 0x51, 0x21, 0x5E}, // 81 Q
|
||||
{0x7F, 0x09, 0x19, 0x29, 0x46}, // 82 R
|
||||
{0x26, 0x49, 0x49, 0x49, 0x32}, // 83 S
|
||||
{0x03, 0x01, 0x7F, 0x01, 0x03}, // 84 T
|
||||
{0x3F, 0x40, 0x40, 0x40, 0x3F}, // 85 U
|
||||
{0x1F, 0x20, 0x40, 0x20, 0x1F}, // 86 V
|
||||
{0x3F, 0x40, 0x38, 0x40, 0x3F}, // 87 W
|
||||
{0x63, 0x14, 0x08, 0x14, 0x63}, // 88 X
|
||||
{0x03, 0x04, 0x78, 0x04, 0x03}, // 89 Y
|
||||
{0x61, 0x59, 0x49, 0x4D, 0x43}, // 90 Z
|
||||
{0x00, 0x7F, 0x41, 0x41, 0x41}, // 91 [
|
||||
{0x02, 0x04, 0x08, 0x10, 0x20}, // 92 backslash
|
||||
{0x41, 0x41, 0x41, 0x7F, 0x00}, // 93 ]
|
||||
{0x04, 0x02, 0x01, 0x02, 0x04}, // 94 ^
|
||||
{0x40, 0x40, 0x40, 0x40, 0x40}, // 95 _
|
||||
{0x00, 0x03, 0x07, 0x08, 0x00}, // 96 `
|
||||
{0x20, 0x54, 0x54, 0x78, 0x40}, // 97 a
|
||||
{0x7F, 0x28, 0x44, 0x44, 0x38}, // 98 b
|
||||
{0x38, 0x44, 0x44, 0x44, 0x28}, // 99 c
|
||||
{0x38, 0x44, 0x44, 0x28, 0x7F}, // 100 d
|
||||
{0x38, 0x54, 0x54, 0x54, 0x18}, // 101 e
|
||||
{0x00, 0x08, 0x7E, 0x09, 0x02}, // 102 f
|
||||
{0x18, 0xA4, 0xA4, 0x9C, 0x78}, // 103 g
|
||||
{0x7F, 0x08, 0x04, 0x04, 0x78}, // 104 h
|
||||
{0x00, 0x44, 0x7D, 0x40, 0x00}, // 105 i
|
||||
{0x20, 0x40, 0x40, 0x3D, 0x00}, // 106 j
|
||||
{0x7F, 0x10, 0x28, 0x44, 0x00}, // 107 k
|
||||
{0x00, 0x41, 0x7F, 0x40, 0x00}, // 108 l
|
||||
{0x7C, 0x04, 0x78, 0x04, 0x78}, // 109 m
|
||||
{0x7C, 0x08, 0x04, 0x04, 0x78}, // 110 n
|
||||
{0x38, 0x44, 0x44, 0x44, 0x38}, // 111 o
|
||||
{0xFC, 0x18, 0x24, 0x24, 0x18}, // 112 p
|
||||
{0x18, 0x24, 0x24, 0x18, 0xFC}, // 113 q
|
||||
{0x7C, 0x08, 0x04, 0x04, 0x08}, // 114 r
|
||||
{0x48, 0x54, 0x54, 0x54, 0x24}, // 115 s
|
||||
{0x04, 0x04, 0x3F, 0x44, 0x24}, // 116 t
|
||||
{0x3C, 0x40, 0x40, 0x20, 0x7C}, // 117 u
|
||||
{0x1C, 0x20, 0x40, 0x20, 0x1C}, // 118 v
|
||||
{0x3C, 0x40, 0x30, 0x40, 0x3C}, // 119 w
|
||||
{0x44, 0x28, 0x10, 0x28, 0x44}, // 120 x
|
||||
{0x4C, 0x90, 0x90, 0x90, 0x7C}, // 121 y
|
||||
{0x44, 0x64, 0x54, 0x4C, 0x44}, // 122 z
|
||||
{0x00, 0x08, 0x36, 0x41, 0x00}, // 123 {
|
||||
{0x00, 0x00, 0x77, 0x00, 0x00}, // 124 |
|
||||
{0x00, 0x41, 0x36, 0x08, 0x00}, // 125 }
|
||||
{0x02, 0x01, 0x02, 0x04, 0x02}, // 126 ~
|
||||
};
|
||||
|
||||
// Helper function to draw a character at position
|
||||
void draw_char(light::AddressableLight &it, char c, int x_pos, int y_pos, Color color) {
|
||||
if (c < 32 || c > 126) return; // Character out of range
|
||||
|
||||
const uint8_t *char_data = font_5x7[c - 32];
|
||||
|
||||
for (int col = 0; col < 5; col++) {
|
||||
int x = x_pos + col;
|
||||
if (x < 0 || x >= 32) continue; // Skip if out of bounds
|
||||
|
||||
uint8_t column = char_data[col];
|
||||
for (int row = 0; row < 7; row++) {
|
||||
if (column & (1 << row)) {
|
||||
int y = y_pos + row;
|
||||
if (y < 0 || y >= 8) continue; // Skip if out of bounds
|
||||
|
||||
// Convert to LED index with serpentine mapping
|
||||
int flipped_y = 7 - y;
|
||||
int led_index;
|
||||
if (flipped_y % 2 == 0) {
|
||||
led_index = flipped_y * 32 + x;
|
||||
} else {
|
||||
led_index = flipped_y * 32 + (31 - x);
|
||||
}
|
||||
|
||||
if (led_index >= 0 && led_index < 256) {
|
||||
it[led_index] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to draw a string
|
||||
void draw_string(light::AddressableLight &it, const std::string &text, int x_pos, int y_pos, Color color) {
|
||||
int current_x = x_pos;
|
||||
|
||||
for (size_t i = 0; i < text.length(); i++) {
|
||||
draw_char(it, text[i], current_x, y_pos, color);
|
||||
current_x += 6; // 5 pixels for char + 1 pixel spacing
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate text width in pixels
|
||||
int get_text_width(const std::string &text) {
|
||||
return text.length() * 6 - 1; // 6 pixels per char minus 1 for last spacing
|
||||
}
|
||||
|
||||
|
||||
// Anti-aliased drawing with sub-pixel positioning
|
||||
void draw_char_aa(light::AddressableLight &it, char c, float x_pos, float y_pos, Color color, float brightness = 1.0) {
|
||||
if (c < 32 || c > 126) return;
|
||||
|
||||
const uint8_t *char_data = font_5x7[c - 32];
|
||||
|
||||
// Calculate fractional offsets
|
||||
int x_start = (int)floor(x_pos);
|
||||
int y_start = (int)floor(y_pos);
|
||||
float x_frac = x_pos - x_start;
|
||||
float y_frac = y_pos - y_start;
|
||||
|
||||
// Draw with 2x2 supersampling for anti-aliasing
|
||||
for (int col = 0; col < 5; col++) {
|
||||
uint8_t column = char_data[col];
|
||||
|
||||
for (int row = 0; row < 7; row++) {
|
||||
if (column & (1 << row)) {
|
||||
// Calculate anti-aliased pixel coverage for 4 affected pixels
|
||||
float coverage[2][2] = {
|
||||
{(1.0f - x_frac) * (1.0f - y_frac), x_frac * (1.0f - y_frac)},
|
||||
{(1.0f - x_frac) * y_frac, x_frac * y_frac}
|
||||
};
|
||||
|
||||
// Draw to up to 4 pixels with appropriate brightness
|
||||
for (int dy = 0; dy < 2; dy++) {
|
||||
for (int dx = 0; dx < 2; dx++) {
|
||||
int x = x_start + col + dx;
|
||||
int y = y_start + row + dy;
|
||||
|
||||
if (x >= 0 && x < 32 && y >= 0 && y < 8) {
|
||||
// Convert to LED index
|
||||
int flipped_y = 7 - y;
|
||||
int led_index;
|
||||
if (flipped_y % 2 == 0) {
|
||||
led_index = flipped_y * 32 + x;
|
||||
} else {
|
||||
led_index = flipped_y * 32 + (31 - x);
|
||||
}
|
||||
|
||||
if (led_index >= 0 && led_index < 256) {
|
||||
// Apply anti-aliased brightness
|
||||
float pixel_brightness = coverage[dy][dx] * brightness;
|
||||
|
||||
// Blend with existing pixel
|
||||
Color existing = it[led_index].get();
|
||||
Color new_color(
|
||||
existing.r + (color.r - existing.r) * pixel_brightness,
|
||||
existing.g + (color.g - existing.g) * pixel_brightness,
|
||||
existing.b + (color.b - existing.b) * pixel_brightness
|
||||
);
|
||||
it[led_index] = new_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for edge smoothing using 3x3 kernel
|
||||
void apply_edge_smoothing(light::AddressableLight &it, int x, int y, Color color, float strength) {
|
||||
// 3x3 Gaussian kernel for smoothing
|
||||
const float kernel[3][3] = {
|
||||
{0.075f, 0.124f, 0.075f},
|
||||
{0.124f, 0.204f, 0.124f},
|
||||
{0.075f, 0.124f, 0.075f}
|
||||
};
|
||||
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
int px = x + dx;
|
||||
int py = y + dy;
|
||||
|
||||
if (px >= 0 && px < 32 && py >= 0 && py < 8) {
|
||||
int flipped_y = 7 - py;
|
||||
int led_index;
|
||||
if (flipped_y % 2 == 0) {
|
||||
led_index = flipped_y * 32 + px;
|
||||
} else {
|
||||
led_index = flipped_y * 32 + (31 - px);
|
||||
}
|
||||
|
||||
if (led_index >= 0 && led_index < 256) {
|
||||
float weight = kernel[dy + 1][dx + 1] * strength;
|
||||
Color existing = it[led_index].get();
|
||||
Color new_color(
|
||||
existing.r + (color.r - existing.r) * weight,
|
||||
existing.g + (color.g - existing.g) * weight,
|
||||
existing.b + (color.b - existing.b) * weight
|
||||
);
|
||||
it[led_index] = new_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Improved string drawing with anti-aliasing
|
||||
void draw_string_aa(light::AddressableLight &it, const std::string &text, float x_pos, float y_pos, Color color) {
|
||||
float current_x = x_pos;
|
||||
|
||||
for (size_t i = 0; i < text.length(); i++) {
|
||||
draw_char_aa(it, text[i], current_x, y_pos, color);
|
||||
current_x += 6.0f; // Can use fractional spacing
|
||||
}
|
||||
}
|
||||
|
||||
// Alternative: Pre-rendered anti-aliased font (2-bit per pixel)
|
||||
// This would store 4 brightness levels per pixel for better quality
|
||||
struct AAGlyph {
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t data[35]; // 5x7 pixels, 2 bits each = 70 bits = ~9 bytes
|
||||
};
|
||||
|
||||
// Function to render with pre-computed anti-aliased glyphs
|
||||
void draw_aa_glyph(light::AddressableLight &it, const AAGlyph &glyph, int x, int y, Color color) {
|
||||
for (int row = 0; row < glyph.height; row++) {
|
||||
for (int col = 0; col < glyph.width; col++) {
|
||||
// Extract 2-bit brightness value (0, 85, 170, 255)
|
||||
int bit_index = (row * glyph.width + col) * 2;
|
||||
int byte_index = bit_index / 8;
|
||||
int bit_offset = bit_index % 8;
|
||||
|
||||
uint8_t brightness_bits = (glyph.data[byte_index] >> bit_offset) & 0x03;
|
||||
float brightness = brightness_bits / 3.0f;
|
||||
|
||||
if (brightness > 0) {
|
||||
int px = x + col;
|
||||
int py = y + row;
|
||||
|
||||
if (px >= 0 && px < 32 && py >= 0 && py < 8) {
|
||||
int flipped_y = 7 - py;
|
||||
int led_index;
|
||||
if (flipped_y % 2 == 0) {
|
||||
led_index = flipped_y * 32 + px;
|
||||
} else {
|
||||
led_index = flipped_y * 32 + (31 - px);
|
||||
}
|
||||
|
||||
if (led_index >= 0 && led_index < 256) {
|
||||
it[led_index] = Color(
|
||||
color.r * brightness,
|
||||
color.g * brightness,
|
||||
color.b * brightness
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user