diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 6e236a94..9afa1d69 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(esp32spi) +add_subdirectory(ltp305) add_subdirectory(st7789) add_subdirectory(msa301) add_subdirectory(rv3028) diff --git a/drivers/ltp305/CMakeLists.txt b/drivers/ltp305/CMakeLists.txt new file mode 100644 index 00000000..0424b754 --- /dev/null +++ b/drivers/ltp305/CMakeLists.txt @@ -0,0 +1 @@ +include(ltp305.cmake) diff --git a/drivers/ltp305/dotfont.hpp b/drivers/ltp305/dotfont.hpp new file mode 100644 index 00000000..ba525083 --- /dev/null +++ b/drivers/ltp305/dotfont.hpp @@ -0,0 +1,405 @@ +#pragma once + +#include +#include + +namespace pimoroni { + + static const uint8_t DOT_CHAR_WIDTH = 5; + + struct DotChar { + uint8_t data[DOT_CHAR_WIDTH]; + }; + + static const std::map dotfont = { + {32, {0x00, 0x00, 0x00, 0x00, 0x00}}, // (space) + {33, {0x00, 0x00, 0x5f, 0x00, 0x00}}, // ! + {34, {0x00, 0x07, 0x00, 0x07, 0x00}}, // " + {35, {0x14, 0x7f, 0x14, 0x7f, 0x14}}, // # + {36, {0x24, 0x2a, 0x7f, 0x2a, 0x12}}, // $ + {37, {0x23, 0x13, 0x08, 0x64, 0x62}}, // % + {38, {0x36, 0x49, 0x55, 0x22, 0x50}}, // & + {39, {0x00, 0x05, 0x03, 0x00, 0x00}}, // ' + {40, {0x00, 0x1c, 0x22, 0x41, 0x00}}, // ( + {41, {0x00, 0x41, 0x22, 0x1c, 0x00}}, // ) + {42, {0x08, 0x2a, 0x1c, 0x2a, 0x08}}, // * + {43, {0x08, 0x08, 0x3e, 0x08, 0x08}}, // + + {44, {0x00, 0x50, 0x30, 0x00, 0x00}}, // , + {45, {0x08, 0x08, 0x08, 0x08, 0x08}}, // - + {46, {0x00, 0x60, 0x60, 0x00, 0x00}}, // . + {47, {0x20, 0x10, 0x08, 0x04, 0x02}}, // / + {48, {0x3e, 0x51, 0x49, 0x45, 0x3e}}, // 0 + {49, {0x00, 0x42, 0x7f, 0x40, 0x00}}, // 1 + {50, {0x42, 0x61, 0x51, 0x49, 0x46}}, // 2 + {51, {0x21, 0x41, 0x45, 0x4b, 0x31}}, // 3 + {52, {0x18, 0x14, 0x12, 0x7f, 0x10}}, // 4 + {53, {0x27, 0x45, 0x45, 0x45, 0x39}}, // 5 + {54, {0x3c, 0x4a, 0x49, 0x49, 0x30}}, // 6 + {55, {0x01, 0x71, 0x09, 0x05, 0x03}}, // 7 + {56, {0x36, 0x49, 0x49, 0x49, 0x36}}, // 8 + {57, {0x06, 0x49, 0x49, 0x29, 0x1e}}, // 9 + {58, {0x00, 0x36, 0x36, 0x00, 0x00}}, // : + {59, {0x00, 0x56, 0x36, 0x00, 0x00}}, // ; + {60, {0x00, 0x08, 0x14, 0x22, 0x41}}, // < + {61, {0x14, 0x14, 0x14, 0x14, 0x14}}, // = + {62, {0x41, 0x22, 0x14, 0x08, 0x00}}, // > + {63, {0x02, 0x01, 0x51, 0x09, 0x06}}, // ? + {64, {0x32, 0x49, 0x79, 0x41, 0x3e}}, // @ + {65, {0x7e, 0x11, 0x11, 0x11, 0x7e}}, // A + {66, {0x7f, 0x49, 0x49, 0x49, 0x36}}, // B + {67, {0x3e, 0x41, 0x41, 0x41, 0x22}}, // C + {68, {0x7f, 0x41, 0x41, 0x22, 0x1c}}, // D + {69, {0x7f, 0x49, 0x49, 0x49, 0x41}}, // E + {70, {0x7f, 0x09, 0x09, 0x01, 0x01}}, // F + {71, {0x3e, 0x41, 0x41, 0x51, 0x32}}, // G + {72, {0x7f, 0x08, 0x08, 0x08, 0x7f}}, // H + {73, {0x00, 0x41, 0x7f, 0x41, 0x00}}, // I + {74, {0x20, 0x40, 0x41, 0x3f, 0x01}}, // J + {75, {0x7f, 0x08, 0x14, 0x22, 0x41}}, // K + {76, {0x7f, 0x40, 0x40, 0x40, 0x40}}, // L + {77, {0x7f, 0x02, 0x04, 0x02, 0x7f}}, // M + {78, {0x7f, 0x04, 0x08, 0x10, 0x7f}}, // N + {79, {0x3e, 0x41, 0x41, 0x41, 0x3e}}, // O + {80, {0x7f, 0x09, 0x09, 0x09, 0x06}}, // P + {81, {0x3e, 0x41, 0x51, 0x21, 0x5e}}, // Q + {82, {0x7f, 0x09, 0x19, 0x29, 0x46}}, // R + {83, {0x46, 0x49, 0x49, 0x49, 0x31}}, // S + {84, {0x01, 0x01, 0x7f, 0x01, 0x01}}, // T + {85, {0x3f, 0x40, 0x40, 0x40, 0x3f}}, // U + {86, {0x1f, 0x20, 0x40, 0x20, 0x1f}}, // V + {87, {0x7f, 0x20, 0x18, 0x20, 0x7f}}, // W + {88, {0x63, 0x14, 0x08, 0x14, 0x63}}, // X + {89, {0x03, 0x04, 0x78, 0x04, 0x03}}, // Y + {90, {0x61, 0x51, 0x49, 0x45, 0x43}}, // Z + {91, {0x00, 0x00, 0x7f, 0x41, 0x41}}, // [ + {92, {0x02, 0x04, 0x08, 0x10, 0x20}}, // "\" + {93, {0x41, 0x41, 0x7f, 0x00, 0x00}}, // ] + {94, {0x04, 0x02, 0x01, 0x02, 0x04}}, // ^ + {95, {0x40, 0x40, 0x40, 0x40, 0x40}}, // _ + {96, {0x00, 0x01, 0x02, 0x04, 0x00}}, // ` + {97, {0x20, 0x54, 0x54, 0x54, 0x78}}, // a + {98, {0x7f, 0x48, 0x44, 0x44, 0x38}}, // b + {99, {0x38, 0x44, 0x44, 0x44, 0x20}}, // c + {100, {0x38, 0x44, 0x44, 0x48, 0x7f}}, // d + {101, {0x38, 0x54, 0x54, 0x54, 0x18}}, // e + {102, {0x08, 0x7e, 0x09, 0x01, 0x02}}, // f + {103, {0x08, 0x14, 0x54, 0x54, 0x3c}}, // g + {104, {0x7f, 0x08, 0x04, 0x04, 0x78}}, // h + {105, {0x00, 0x44, 0x7d, 0x40, 0x00}}, // i + {106, {0x20, 0x40, 0x44, 0x3d, 0x00}}, // j + {107, {0x00, 0x7f, 0x10, 0x28, 0x44}}, // k + {108, {0x00, 0x41, 0x7f, 0x40, 0x00}}, // l + {109, {0x7c, 0x04, 0x18, 0x04, 0x78}}, // m + {110, {0x7c, 0x08, 0x04, 0x04, 0x78}}, // n + {111, {0x38, 0x44, 0x44, 0x44, 0x38}}, // o + {112, {0x7c, 0x14, 0x14, 0x14, 0x08}}, // p + {113, {0x08, 0x14, 0x14, 0x18, 0x7c}}, // q + {114, {0x7c, 0x08, 0x04, 0x04, 0x08}}, // r + {115, {0x48, 0x54, 0x54, 0x54, 0x20}}, // s + {116, {0x04, 0x3f, 0x44, 0x40, 0x20}}, // t + {117, {0x3c, 0x40, 0x40, 0x20, 0x7c}}, // u + {118, {0x1c, 0x20, 0x40, 0x20, 0x1c}}, // v + {119, {0x3c, 0x40, 0x30, 0x40, 0x3c}}, // w + {120, {0x44, 0x28, 0x10, 0x28, 0x44}}, // x + {121, {0x0c, 0x50, 0x50, 0x50, 0x3c}}, // y + {122, {0x44, 0x64, 0x54, 0x4c, 0x44}}, // z + {123, {0x00, 0x08, 0x36, 0x41, 0x00}}, // { + {124, {0x00, 0x00, 0x7f, 0x00, 0x00}}, // | + {125, {0x00, 0x41, 0x36, 0x08, 0x00}}, // } + {126, {0x08, 0x08, 0x2a, 0x1c, 0x08}}, // ~ + + {8221, {0x00, 0x07, 0x00, 0x07, 0x00}}, // ” + {8592, {0x08, 0x1C, 0x2A, 0x08, 0x08}}, // ← + {8593, {0x08, 0x04, 0x7E, 0x04, 0x08}}, // ↑ + {8594, {0x08, 0x08, 0x2A, 0x1C, 0x08}}, // → + {8595, {0x08, 0x10, 0x3F, 0x10, 0x08}}, // ↓ + {9472, {0x08, 0x08, 0x08, 0x08, 0x08}}, // ─ + {9474, {0x00, 0x00, 0x7F, 0x00, 0x00}}, // │ + {9484, {0x00, 0x00, 0x78, 0x08, 0x08}}, // ┌ + {9488, {0x08, 0x08, 0x78, 0x00, 0x00}}, // ┐ + {9492, {0x00, 0x00, 0x0F, 0x08, 0x08}}, // └ + {9496, {0x08, 0x08, 0x0F, 0x00, 0x00}}, // ┘ + {9500, {0x00, 0x00, 0x7F, 0x08, 0x08}}, // ├ + {9508, {0x08, 0x08, 0x7F, 0x00, 0x00}}, // ┤ + {9516, {0x08, 0x08, 0x78, 0x08, 0x08}}, // ┬ + {9524, {0x08, 0x08, 0x0F, 0x08, 0x08}}, // ┴ + {9532, {0x08, 0x08, 0x7F, 0x08, 0x08}}, // ┼ + {9632, {0x7F, 0x7F, 0x7F, 0x7F, 0x7F}}, // ■ + {9633, {0x7F, 0x41, 0x41, 0x41, 0x7F}}, // □ + {9650, {0x10, 0x1C, 0x1E, 0x1C, 0x10}}, // ▲ + {9651, {0x10, 0x1C, 0x12, 0x1C, 0x10}}, // △ + {9660, {0x04, 0x1C, 0x3C, 0x1C, 0x04}}, // ▼ + {9661, {0x04, 0x1C, 0x24, 0x1C, 0x04}}, // ▽ + {9670, {0x08, 0x1C, 0x3E, 0x1C, 0x08}}, // ◆ + {9675, {0x1C, 0x22, 0x22, 0x22, 0x1C}}, // ○ + {9679, {0x1C, 0x3E, 0x3E, 0x3E, 0x1C}}, // ● + {9733, {0x64, 0x3E, 0x1F, 0x3E, 0x64}}, // ★ + {12288, {0x00, 0x00, 0x00, 0x00, 0x00}}, // + {12289, {0x10, 0x20, 0x40, 0x00, 0x00}}, // 、 + {12290, {0x70, 0x50, 0x70, 0x00, 0x00}}, // 。 + {12300, {0x00, 0x0F, 0x01, 0x01, 0x01}}, // 「 + {12301, {0x40, 0x40, 0x40, 0x78, 0x00}}, // 」 + {12316, {0x02, 0x01, 0x02, 0x04, 0x02}}, // 〜 + {12353, {0x28, 0x58, 0x3C, 0x68, 0x00}}, // ぁ + {12354, {0x32, 0x7A, 0x2F, 0x1A, 0x72}}, // あ + {12355, {0x38, 0x40, 0x08, 0x30, 0x00}}, // ぃ + {12356, {0x3E, 0x40, 0x20, 0x00, 0x1C}}, // い + {12357, {0x10, 0x0C, 0x4C, 0x30, 0x00}}, // ぅ + {12358, {0x04, 0x05, 0x45, 0x25, 0x18}}, // う + {12359, {0x48, 0x2C, 0x5C, 0x48, 0x00}}, // ぇ + {12360, {0x44, 0x24, 0x35, 0x4D, 0x44}}, // え + {12361, {0x68, 0x7C, 0x10, 0x64, 0x00}}, // ぉ + {12362, {0x32, 0x7F, 0x0A, 0x48, 0x32}}, // お + {12363, {0x34, 0x0F, 0x44, 0x38, 0x06}}, // か + {12365, {0x22, 0x4A, 0x4F, 0x5A, 0x08}}, // き + {12367, {0x00, 0x18, 0x24, 0x43, 0x00}}, // く + {12369, {0x3E, 0x00, 0x44, 0x3F, 0x04}}, // け + {12371, {0x22, 0x52, 0x42, 0x42, 0x44}}, // こ + {12373, {0x24, 0x44, 0x47, 0x5C, 0x12}}, // さ + {12375, {0x3F, 0x40, 0x40, 0x20, 0x10}}, // し + {12377, {0x02, 0x0A, 0x56, 0x3F, 0x02}}, // す + {12379, {0x04, 0x3E, 0x44, 0x5F, 0x44}}, // せ + {12381, {0x08, 0x2D, 0x5B, 0x45, 0x44}}, // そ + {12383, {0x72, 0x0F, 0x22, 0x4A, 0x48}}, // た + {12385, {0x0A, 0x0E, 0x4B, 0x4A, 0x32}}, // ち + {12387, {0x08, 0x48, 0x48, 0x30, 0x00}}, // っ + {12388, {0x02, 0x02, 0x42, 0x22, 0x1C}}, // つ + {12390, {0x02, 0x32, 0x4A, 0x46, 0x42}}, // て + {12392, {0x30, 0x4B, 0x44, 0x44, 0x42}}, // と + {12394, {0x0A, 0x27, 0x52, 0x38, 0x26}}, // な + {12395, {0x3E, 0x00, 0x22, 0x42, 0x42}}, // に + {12396, {0x38, 0x6F, 0x1C, 0x67, 0x78}}, // ぬ + {12397, {0x12, 0x7F, 0x0A, 0x64, 0x78}}, // ね + {12398, {0x3C, 0x62, 0x1E, 0x44, 0x38}}, // の + {12399, {0x3E, 0x00, 0x32, 0x7F, 0x22}}, // は + {12402, {0x04, 0x3E, 0x40, 0x47, 0x3C}}, // ひ + {12405, {0x30, 0x05, 0x7A, 0x00, 0x38}}, // ふ + {12411, {0x3E, 0x00, 0x35, 0x7F, 0x25}}, // ほ + {12414, {0x2A, 0x5A, 0x7F, 0x2A, 0x4A}}, // ま + {12415, {0x71, 0x3F, 0x08, 0x7E, 0x08}}, // み + {12416, {0x1A, 0x3F, 0x42, 0x40, 0x26}}, // む + {12417, {0x38, 0x4E, 0x34, 0x1F, 0x78}}, // め + {12418, {0x14, 0x3F, 0x54, 0x40, 0x20}}, // も + {12419, {0x1C, 0x68, 0x0C, 0x30, 0x00}}, // ゃ + {12420, {0x04, 0x7F, 0x04, 0x2E, 0x18}}, // や + {12421, {0x18, 0x50, 0x3C, 0x18, 0x00}}, // ゅ + {12422, {0x1E, 0x44, 0x3F, 0x12, 0x0C}}, // ゆ + {12423, {0x60, 0x7C, 0x28, 0x40, 0x00}}, // ょ + {12424, {0x20, 0x50, 0x3F, 0x24, 0x44}}, // よ + {12425, {0x10, 0x0D, 0x49, 0x4A, 0x30}}, // ら + {12426, {0x0E, 0x00, 0x40, 0x21, 0x1E}}, // り + {12427, {0x20, 0x55, 0x65, 0x4B, 0x30}}, // る + {12428, {0x34, 0x7F, 0x04, 0x3E, 0x40}}, // れ + {12429, {0x10, 0x49, 0x4D, 0x4B, 0x30}}, // ろ + {12431, {0x24, 0x7F, 0x0A, 0x44, 0x38}}, // わ + {12434, {0x22, 0x5F, 0x4A, 0x56, 0x42}}, // を + {12435, {0x70, 0x0F, 0x30, 0x40, 0x20}}, // ん + {12443, {0x02, 0x04, 0x01, 0x02, 0x00}}, // ゛ + {12444, {0x07, 0x05, 0x07, 0x00, 0x00}}, // ゜ + {12449, {0x44, 0x44, 0x3C, 0x14, 0x0C}}, // ァ + {12450, {0x42, 0x42, 0x3A, 0x12, 0x0E}}, // ア + {12451, {0x20, 0x10, 0x78, 0x04, 0x00}}, // ィ + {12452, {0x10, 0x08, 0x04, 0x7E, 0x01}}, // イ + {12453, {0x18, 0x08, 0x4C, 0x48, 0x38}}, // ゥ + {12454, {0x0E, 0x42, 0x43, 0x22, 0x1E}}, // ウ + {12455, {0x48, 0x48, 0x78, 0x48, 0x48}}, // ェ + {12456, {0x42, 0x42, 0x7E, 0x42, 0x42}}, // エ + {12457, {0x48, 0x38, 0x08, 0x7C, 0x08}}, // ォ + {12458, {0x22, 0x12, 0x0A, 0x7F, 0x02}}, // オ + {12459, {0x42, 0x3F, 0x02, 0x02, 0x7E}}, // カ + {12461, {0x0A, 0x0A, 0x7F, 0x0A, 0x0A}}, // キ + {12463, {0x08, 0x06, 0x42, 0x22, 0x1E}}, // ク + {12465, {0x0F, 0x42, 0x42, 0x3E, 0x02}}, // ケ + {12467, {0x42, 0x42, 0x42, 0x42, 0x7E}}, // コ + {12469, {0x02, 0x4F, 0x42, 0x3F, 0x02}}, // サ + {12471, {0x4A, 0x4A, 0x40, 0x20, 0x1C}}, // シ + {12473, {0x42, 0x22, 0x12, 0x2A, 0x46}}, // ス + {12475, {0x02, 0x3F, 0x42, 0x42, 0x4E}}, // セ + {12477, {0x06, 0x48, 0x40, 0x30, 0x0E}}, // ソ + {12479, {0x08, 0x4E, 0x52, 0x32, 0x0E}}, // タ + {12481, {0x08, 0x4A, 0x4A, 0x3F, 0x09}}, // チ + {12483, {0x18, 0x40, 0x58, 0x40, 0x30}}, // ッ + {12484, {0x0E, 0x40, 0x4E, 0x20, 0x1E}}, // ツ + {12486, {0x04, 0x45, 0x45, 0x3D, 0x04}}, // テ + {12488, {0x00, 0x7F, 0x08, 0x10, 0x10}}, // ト + {12490, {0x44, 0x44, 0x44, 0x3F, 0x04}}, // ナ + {12491, {0x40, 0x42, 0x42, 0x42, 0x40}}, // ニ + {12492, {0x42, 0x4A, 0x2A, 0x12, 0x2E}}, // ヌ + {12493, {0x22, 0x12, 0x73, 0x0A, 0x16}}, // ネ + {12494, {0x40, 0x40, 0x20, 0x10, 0x0E}}, // ノ + {12495, {0x70, 0x0E, 0x00, 0x07, 0x78}}, // ハ + {12498, {0x3F, 0x44, 0x44, 0x44, 0x44}}, // ヒ + {12501, {0x02, 0x42, 0x42, 0x22, 0x1E}}, // フ + {12504, {0x08, 0x04, 0x02, 0x0C, 0x30}}, // ヘ + {12507, {0x32, 0x02, 0x7F, 0x02, 0x32}}, // ホ + {12510, {0x02, 0x12, 0x22, 0x52, 0x0E}}, // マ + {12511, {0x20, 0x2A, 0x2A, 0x2A, 0x40}}, // ミ + {12512, {0x30, 0x2C, 0x22, 0x28, 0x70}}, // ム + {12513, {0x40, 0x44, 0x28, 0x10, 0x2E}}, // メ + {12514, {0x0A, 0x0A, 0x3E, 0x4A, 0x4A}}, // モ + {12515, {0x08, 0x7C, 0x08, 0x28, 0x18}}, // ャ + {12516, {0x04, 0x7F, 0x04, 0x14, 0x0C}}, // ヤ + {12517, {0x48, 0x48, 0x48, 0x78, 0x40}}, // ュ + {12518, {0x42, 0x42, 0x42, 0x7E, 0x40}}, // ユ + {12519, {0x54, 0x54, 0x54, 0x7C, 0x00}}, // ョ + {12520, {0x4A, 0x4A, 0x4A, 0x4A, 0x7E}}, // ヨ + {12521, {0x04, 0x45, 0x45, 0x25, 0x1C}}, // ラ + {12522, {0x0E, 0x40, 0x40, 0x20, 0x1E}}, // リ + {12523, {0x7E, 0x00, 0x7E, 0x40, 0x38}}, // ル + {12524, {0x7E, 0x40, 0x40, 0x20, 0x10}}, // レ + {12525, {0x7E, 0x42, 0x42, 0x42, 0x7E}}, // ロ + {12527, {0x0E, 0x42, 0x42, 0x22, 0x1E}}, // ワ + {12530, {0x0A, 0x4A, 0x4A, 0x2A, 0x1E}}, // ヲ + {12531, {0x42, 0x42, 0x40, 0x20, 0x1C}}, // ン + {12539, {0x00, 0x00, 0x08, 0x00, 0x00}}, // ・ + {12540, {0x04, 0x08, 0x08, 0x08, 0x08}}, // ー + {65281, {0x00, 0x00, 0x5F, 0x00, 0x00}}, // ! + {65283, {0x14, 0x7F, 0x14, 0x7F, 0x14}}, // # + {65284, {0x24, 0x2A, 0x7F, 0x2A, 0x12}}, // $ + {65285, {0x23, 0x13, 0x08, 0x64, 0x62}}, // % + {65286, {0x36, 0x49, 0x56, 0x20, 0x50}}, // & + {65288, {0x00, 0x1C, 0x22, 0x41, 0x00}}, // ( + {65289, {0x00, 0x41, 0x22, 0x1C, 0x00}}, // ) + {65290, {0x2A, 0x1C, 0x3E, 0x1C, 0x2A}}, // * + {65291, {0x08, 0x08, 0x3E, 0x08, 0x08}}, // + + {65292, {0x00, 0x10, 0x30, 0x00, 0x00}}, // , + {65294, {0x00, 0x60, 0x60, 0x00, 0x00}}, // . + {65295, {0x20, 0x10, 0x08, 0x04, 0x02}}, // / + {65296, {0x3E, 0x51, 0x49, 0x45, 0x3E}}, // 0 + {65297, {0x42, 0x42, 0x7F, 0x40, 0x40}}, // 1 + {65298, {0x42, 0x61, 0x51, 0x49, 0x46}}, // 2 + {65299, {0x22, 0x41, 0x49, 0x49, 0x36}}, // 3 + {65300, {0x38, 0x24, 0x22, 0x7F, 0x20}}, // 4 + {65301, {0x2F, 0x45, 0x45, 0x45, 0x39}}, // 5 + {65302, {0x3C, 0x4A, 0x49, 0x49, 0x30}}, // 6 + {65303, {0x03, 0x01, 0x79, 0x05, 0x03}}, // 7 + {65304, {0x36, 0x49, 0x49, 0x49, 0x36}}, // 8 + {65305, {0x06, 0x49, 0x49, 0x49, 0x3E}}, // 9 + {65306, {0x00, 0x00, 0x12, 0x00, 0x00}}, // : + {65307, {0x00, 0x40, 0x32, 0x00, 0x00}}, // ; + {65308, {0x08, 0x14, 0x22, 0x41, 0x00}}, // < + {65309, {0x14, 0x14, 0x14, 0x14, 0x14}}, // = + {65310, {0x00, 0x41, 0x22, 0x14, 0x08}}, // > + {65311, {0x02, 0x01, 0x51, 0x09, 0x06}}, // ? + {65312, {0x1C, 0x22, 0x49, 0x55, 0x4E}}, // @ + {65313, {0x7C, 0x12, 0x11, 0x12, 0x7C}}, // A + {65314, {0x7F, 0x49, 0x49, 0x49, 0x36}}, // B + {65315, {0x3E, 0x41, 0x41, 0x41, 0x22}}, // C + {65316, {0x7F, 0x41, 0x41, 0x22, 0x1C}}, // D + {65317, {0x7F, 0x49, 0x49, 0x49, 0x41}}, // E + {65318, {0x7F, 0x09, 0x09, 0x09, 0x01}}, // F + {65319, {0x3E, 0x41, 0x49, 0x49, 0x79}}, // G + {65320, {0x7F, 0x08, 0x08, 0x08, 0x7F}}, // H + {65321, {0x00, 0x41, 0x7F, 0x41, 0x00}}, // I + {65322, {0x20, 0x40, 0x41, 0x3F, 0x01}}, // J + {65323, {0x7F, 0x08, 0x14, 0x22, 0x41}}, // K + {65324, {0x7F, 0x40, 0x40, 0x40, 0x40}}, // L + {65325, {0x7F, 0x02, 0x04, 0x02, 0x7F}}, // M + {65326, {0x7F, 0x02, 0x04, 0x08, 0x7F}}, // N + {65327, {0x3E, 0x41, 0x41, 0x41, 0x3E}}, // O + {65328, {0x7F, 0x09, 0x09, 0x09, 0x06}}, // P + {65329, {0x3E, 0x41, 0x51, 0x21, 0x5E}}, // Q + {65330, {0x7F, 0x09, 0x19, 0x29, 0x46}}, // R + {65331, {0x26, 0x49, 0x49, 0x49, 0x32}}, // S + {65332, {0x01, 0x01, 0x7F, 0x01, 0x01}}, // T + {65333, {0x3F, 0x40, 0x40, 0x40, 0x3F}}, // U + {65334, {0x07, 0x18, 0x60, 0x18, 0x07}}, // V + {65335, {0x7F, 0x20, 0x10, 0x20, 0x7F}}, // W + {65336, {0x63, 0x14, 0x08, 0x14, 0x63}}, // X + {65337, {0x03, 0x04, 0x78, 0x04, 0x03}}, // Y + {65338, {0x61, 0x51, 0x49, 0x45, 0x43}}, // Z + {65339, {0x00, 0x7F, 0x41, 0x41, 0x00}}, // [ + {65340, {0x02, 0x04, 0x08, 0x10, 0x20}}, // \ + {65341, {0x00, 0x41, 0x41, 0x7F, 0x00}}, // ] + {65342, {0x04, 0x02, 0x01, 0x02, 0x04}}, // ^ + {65343, {0x40, 0x40, 0x40, 0x40, 0x40}}, // _ + {65344, {0x00, 0x01, 0x02, 0x00, 0x00}}, // ` + {65345, {0x24, 0x54, 0x54, 0x54, 0x78}}, // a + {65346, {0x7F, 0x44, 0x44, 0x44, 0x38}}, // b + {65347, {0x38, 0x44, 0x44, 0x44, 0x44}}, // c + {65348, {0x38, 0x44, 0x44, 0x44, 0x7F}}, // d + {65349, {0x38, 0x54, 0x54, 0x54, 0x18}}, // e + {65350, {0x08, 0x08, 0x7E, 0x09, 0x09}}, // f + {65351, {0x0C, 0x52, 0x52, 0x52, 0x3E}}, // g + {65352, {0x7F, 0x08, 0x04, 0x04, 0x78}}, // h + {65353, {0x00, 0x44, 0x7D, 0x40, 0x00}}, // i + {65354, {0x20, 0x40, 0x40, 0x44, 0x3D}}, // j + {65355, {0x7F, 0x20, 0x10, 0x28, 0x44}}, // k + {65356, {0x00, 0x41, 0x7F, 0x40, 0x00}}, // l + {65357, {0x7C, 0x04, 0x7C, 0x04, 0x78}}, // m + {65358, {0x7C, 0x04, 0x04, 0x04, 0x78}}, // n + {65359, {0x38, 0x44, 0x44, 0x44, 0x38}}, // o + {65360, {0x7E, 0x12, 0x12, 0x12, 0x0C}}, // p + {65361, {0x0C, 0x12, 0x12, 0x12, 0x7E}}, // q + {65362, {0x7C, 0x08, 0x04, 0x04, 0x08}}, // r + {65363, {0x48, 0x54, 0x54, 0x54, 0x24}}, // s + {65364, {0x04, 0x04, 0x3F, 0x44, 0x44}}, // t + {65365, {0x3C, 0x40, 0x40, 0x40, 0x7C}}, // u + {65366, {0x1C, 0x20, 0x40, 0x20, 0x1C}}, // v + {65367, {0x3C, 0x40, 0x38, 0x40, 0x3C}}, // w + {65368, {0x44, 0x28, 0x10, 0x28, 0x44}}, // x + {65369, {0x0E, 0x50, 0x50, 0x50, 0x3E}}, // y + {65370, {0x44, 0x64, 0x54, 0x4C, 0x44}}, // z + {65371, {0x00, 0x08, 0x36, 0x41, 0x41}}, // { + {65372, {0x00, 0x00, 0x77, 0x00, 0x00}}, // | + {65373, {0x41, 0x41, 0x36, 0x08, 0x00}}, // } + {65374, {0x08, 0x04, 0x08, 0x10, 0x08}}, // ~ + {65383, {0x44, 0x44, 0x3C, 0x14, 0x0C}}, // ァ + {65384, {0x42, 0x42, 0x3A, 0x12, 0x0E}}, // ィ + {65385, {0x20, 0x10, 0x78, 0x04, 0x00}}, // ゥ + {65386, {0x10, 0x08, 0x04, 0x7E, 0x01}}, // ェ + {65387, {0x18, 0x08, 0x4C, 0x48, 0x38}}, // ォ + {65388, {0x0E, 0x42, 0x43, 0x22, 0x1E}}, // ャ + {65389, {0x48, 0x48, 0x78, 0x48, 0x48}}, // ュ + {65390, {0x42, 0x42, 0x7E, 0x42, 0x42}}, // ョ + {65391, {0x48, 0x38, 0x08, 0x7C, 0x08}}, // ッ + {65392, {0x22, 0x12, 0x0A, 0x7F, 0x02}}, // ー + {65393, {0x42, 0x3F, 0x02, 0x02, 0x7E}}, // ア + {65394, {0x0A, 0x0A, 0x7F, 0x0A, 0x0A}}, // イ + {65395, {0x08, 0x06, 0x42, 0x22, 0x1E}}, // ウ + {65396, {0x0F, 0x42, 0x42, 0x3E, 0x02}}, // エ + {65397, {0x42, 0x42, 0x42, 0x42, 0x7E}}, // オ + {65398, {0x02, 0x4F, 0x42, 0x3F, 0x02}}, // カ + {65399, {0x4A, 0x4A, 0x40, 0x20, 0x1C}}, // キ + {65400, {0x42, 0x22, 0x12, 0x2A, 0x46}}, // ク + {65401, {0x02, 0x3F, 0x42, 0x42, 0x4E}}, // ケ + {65402, {0x06, 0x48, 0x40, 0x30, 0x0E}}, // コ + {65403, {0x08, 0x4E, 0x52, 0x32, 0x0E}}, // サ + {65404, {0x08, 0x4A, 0x4A, 0x3F, 0x09}}, // シ + {65405, {0x18, 0x40, 0x58, 0x40, 0x30}}, // ス + {65406, {0x0E, 0x40, 0x4E, 0x20, 0x1E}}, // セ + {65407, {0x04, 0x45, 0x45, 0x3D, 0x04}}, // ソ + {65408, {0x00, 0x7F, 0x08, 0x10, 0x10}}, // タ + {65409, {0x44, 0x44, 0x44, 0x3F, 0x04}}, // チ + {65410, {0x40, 0x42, 0x42, 0x42, 0x40}}, // ツ + {65411, {0x42, 0x4A, 0x2A, 0x12, 0x2E}}, // テ + {65412, {0x22, 0x12, 0x73, 0x0A, 0x16}}, // ト + {65413, {0x40, 0x40, 0x20, 0x10, 0x0E}}, // ナ + {65414, {0x70, 0x0E, 0x00, 0x07, 0x78}}, // ニ + {65415, {0x3F, 0x44, 0x44, 0x44, 0x44}}, // ヌ + {65416, {0x02, 0x42, 0x42, 0x22, 0x1E}}, // ネ + {65417, {0x08, 0x04, 0x02, 0x0C, 0x30}}, // ノ + {65418, {0x32, 0x02, 0x7F, 0x02, 0x32}}, // ハ + {65419, {0x02, 0x12, 0x22, 0x52, 0x0E}}, // ヒ + {65420, {0x20, 0x2A, 0x2A, 0x2A, 0x40}}, // フ + {65421, {0x30, 0x2C, 0x22, 0x28, 0x70}}, // ヘ + {65422, {0x40, 0x44, 0x28, 0x10, 0x2E}}, // ホ + {65423, {0x0A, 0x0A, 0x3E, 0x4A, 0x4A}}, // マ + {65424, {0x08, 0x7C, 0x08, 0x28, 0x18}}, // ミ + {65425, {0x04, 0x7F, 0x04, 0x14, 0x0C}}, // ム + {65426, {0x48, 0x48, 0x48, 0x78, 0x40}}, // メ + {65427, {0x42, 0x42, 0x42, 0x7E, 0x40}}, // モ + {65428, {0x54, 0x54, 0x54, 0x7C, 0x00}}, // ヤ + {65429, {0x4A, 0x4A, 0x4A, 0x4A, 0x7E}}, // ユ + {65430, {0x04, 0x45, 0x45, 0x25, 0x1C}}, // ヨ + {65431, {0x0E, 0x40, 0x40, 0x20, 0x1E}}, // ラ + {65432, {0x7E, 0x00, 0x7E, 0x40, 0x38}}, // リ + {65433, {0x7E, 0x40, 0x40, 0x20, 0x10}}, // ル + {65434, {0x7E, 0x42, 0x42, 0x42, 0x7E}}, // レ + {65435, {0x0E, 0x42, 0x42, 0x22, 0x1E}}, // ロ + {65436, {0x0A, 0x4A, 0x4A, 0x2A, 0x1E}}, // ワ + {65437, {0x42, 0x42, 0x40, 0x20, 0x1C}}, // ン + {65438, {0x02, 0x04, 0x01, 0x02, 0x00}}, // ゙ + {65439, {0x07, 0x05, 0x07, 0x00, 0x00}}, // ゚ + }; +} \ No newline at end of file diff --git a/drivers/ltp305/ltp305.cmake b/drivers/ltp305/ltp305.cmake new file mode 100644 index 00000000..c8663029 --- /dev/null +++ b/drivers/ltp305/ltp305.cmake @@ -0,0 +1,10 @@ +set(DRIVER_NAME ltp305) +add_library(${DRIVER_NAME} INTERFACE) + +target_sources(${DRIVER_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp) + +target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_i2c) diff --git a/drivers/ltp305/ltp305.cpp b/drivers/ltp305/ltp305.cpp new file mode 100644 index 00000000..98c3be2e --- /dev/null +++ b/drivers/ltp305/ltp305.cpp @@ -0,0 +1,132 @@ +#include "ltp305.hpp" +#include +#include "dotfont.hpp" + +namespace pimoroni { + + bool LTP305::init() { + i2c_init(i2c, 400000); + + gpio_set_function(sda, GPIO_FUNC_I2C); gpio_pull_up(sda); + gpio_set_function(scl, GPIO_FUNC_I2C); gpio_pull_up(scl); + + set_brightness(DEFAULT_BRIGHTNESS); + clear(); + + return true; + } + + i2c_inst_t* LTP305::get_i2c() const { + return i2c; + } + + int LTP305::get_sda() const { + return sda; + } + + int LTP305::get_scl() const { + return scl; + } + + void LTP305::set_brightness(uint8_t brightness, bool update) { + brightness = std::min((uint8_t)MAX_BRIGHTNESS, brightness); + if(update) + i2c_reg_write_uint8(CMD_BRIGHTNESS, brightness); + } + + void LTP305::set_decimal(bool left, bool right) { + if(left) + buf_matrix_left[7 + BUFFER_CMD] |= 0b01000000; + else + buf_matrix_left[7 + BUFFER_CMD] &= 0b10111111; + + if(right) + buf_matrix_right[6 + BUFFER_CMD] |= 0b10000000; + else + buf_matrix_right[6 + BUFFER_CMD] &= 0b01111111; + } + + void LTP305::set_pixel(uint8_t x, uint8_t y, bool c) { + // Left Matrix + if(x < 5) { + if(c) + buf_matrix_left[x + BUFFER_CMD] |= (0b1 << y); + else + buf_matrix_left[x + BUFFER_CMD] &= ~(0b1 << y); + } + // Right Matrix + else { + x -= 5; + if(c) + buf_matrix_right[y + BUFFER_CMD] |= (0b1 << x); + else + buf_matrix_right[y + BUFFER_CMD] &= ~(0b1 << x); + } + } + + void LTP305::set_character(uint8_t x, uint16_t ch) { + std::map::const_iterator it = dotfont.find(ch); + + if(it != dotfont.end()) { + DotChar dchar = it->second; + for(uint8_t cx = 0; cx < DOT_CHAR_WIDTH; cx++) { + for(uint8_t cy = 0; cy < HEIGHT; cy++) { + uint8_t c = dchar.data[cx] & (0b1 << cy); + set_pixel(x + cx, cy, c); + } + } + } + } + + void LTP305::set_image(const uint8_t *image, uint16_t image_width, uint16_t image_height, + uint16_t offset_x, uint16_t offset_y, bool wrap, bool bg, uint8_t on_level, uint8_t padding) { + + for(uint8_t y = 0; y < HEIGHT; y++) { + for(uint8_t x = 0; x < WIDTH; x++) { + bool p = bg; + uint16_t i_x = x + offset_x; + uint16_t i_y = y + offset_y; + + if(x >= 5) + i_x += padding; + + if(wrap) { + while(i_x >= image_width) { + i_x -= image_width; + } + while(i_y >= image_height) { + i_y -= image_height; + } + } + + if((i_x < image_width) && (i_y < image_height)) { + p = (image[(i_y * image_width) + i_x] >= on_level); + } + + set_pixel(x, y, p); + } + } + } + + void LTP305::clear() { + for(uint8_t i = 0; i < BUFFER_LENGTH; i++) { + buf_matrix_left[i + 1] = 0x00; + buf_matrix_right[i + 1] = 0x00; + } + } + + void LTP305::show() { + i2c_write_blocking(i2c, address, buf_matrix_left, BUFFER_CMD + BUFFER_LENGTH, false); + i2c_write_blocking(i2c, address, buf_matrix_right, BUFFER_CMD + BUFFER_LENGTH, false); + + i2c_reg_write_uint8(CMD_MODE, MODE); + i2c_reg_write_uint8(CMD_OPTIONS, OPTS); + i2c_reg_write_uint8(CMD_BRIGHTNESS, brightness); + i2c_reg_write_uint8(CMD_UPDATE, 0x01); + } + + void LTP305::i2c_reg_write_uint8(uint8_t reg, uint8_t value) { + uint8_t buffer[2] = {reg, value}; + i2c_write_blocking(i2c, address, buffer, 2, false); + } +} \ No newline at end of file diff --git a/drivers/ltp305/ltp305.hpp b/drivers/ltp305/ltp305.hpp new file mode 100644 index 00000000..4762d547 --- /dev/null +++ b/drivers/ltp305/ltp305.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include "hardware/i2c.h" +#include "hardware/gpio.h" + +namespace pimoroni { + + class LTP305 { + //-------------------------------------------------- + // Constants + //-------------------------------------------------- + public: + static constexpr uint8_t WIDTH = 10; + static constexpr uint8_t HEIGHT = 7; + + static const uint8_t DEFAULT_I2C_ADDRESS = 0x61; + static const uint8_t I2C_ADDRESS_ALTERNATE1 = 0x62; + static const uint8_t I2C_ADDRESS_ALTERNATE2 = 0x63; + static const uint8_t DEFAULT_SDA_PIN = 20; + static const uint8_t DEFAULT_SCL_PIN = 21; + + static const uint8_t DEFAULT_BRIGHTNESS = 64; + static const uint8_t MAX_BRIGHTNESS = 127; + static const uint8_t DEFAULT_ON_LEVEL = 0x7f; + + private: + static const uint8_t MODE = 0b00011000; + static const uint8_t OPTS = 0b00001110; // 1110 = 35mA, 0000 = 40mA + + static const uint8_t CMD_BRIGHTNESS = 0x19; + static const uint8_t CMD_MODE = 0x00; + static const uint8_t CMD_UPDATE = 0x0C; + static const uint8_t CMD_OPTIONS = 0x0D; + + static const uint8_t CMD_MATRIX_L = 0x0E; + static const uint8_t CMD_MATRIX_R = 0x01; + + static const uint8_t BUFFER_LENGTH = 8; + static const uint8_t BUFFER_CMD = 1; + + + //-------------------------------------------------- + // Variables + //-------------------------------------------------- + private: + i2c_inst_t *i2c = i2c0; + + // interface pins with our standard defaults where appropriate + int8_t address = DEFAULT_I2C_ADDRESS; + int8_t sda = DEFAULT_SDA_PIN; + int8_t scl = DEFAULT_SCL_PIN; + + uint8_t brightness = DEFAULT_BRIGHTNESS; + + //Including CMD in buffer to make transmission easier later on + uint8_t buf_matrix_left[BUFFER_CMD + BUFFER_LENGTH] = { CMD_MATRIX_L, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t buf_matrix_right[BUFFER_CMD + BUFFER_LENGTH] = { CMD_MATRIX_R, 0, 0, 0, 0, 0, 0, 0, 0 }; + + /* How matrix buffers look with all leds illuminated + buf_matrix_left = { + // Row 7654321 + 0b01111111, // col 1, bottom = msb + 0b01111111, // col 2 + 0b01111111, // col 3 + 0b01111111, // col 4 + 0b01111111, // col 5 + 0b00000000, + 0b00000000, + 0b01000000 # bit 7 = decimal dot + }; + + buf_matrix_right = { + // Col 12345 + 0b00011111, // row 1 + 0b00011111, // row 2 + 0b00011111, // row 3 + 0b00011111, // row 4 + 0b00011111, // row 5 + 0b00011111, // row 6 + 0b10011111, // row 7 + bit 8 = decimal dot + 0b00000000 + };*/ + + + //-------------------------------------------------- + // Constructors/Destructor + //-------------------------------------------------- + public: + LTP305() {} + + LTP305(uint8_t address) : + address(address) {} + + LTP305(i2c_inst_t *i2c, uint8_t address, uint8_t sda, uint8_t scl) : + i2c(i2c), address(address), sda(sda), scl(scl) {} + + + //-------------------------------------------------- + // Methods + //-------------------------------------------------- + public: + bool init(); + + i2c_inst_t* get_i2c() const; + int get_sda() const; + int get_scl() const; + + void set_brightness(uint8_t brightness, bool update = false); + void set_decimal(bool left = false, bool right = false); + void set_pixel(uint8_t x, uint8_t y, bool c); + void set_character(uint8_t x, uint16_t ch); + void set_image(const uint8_t *image, uint16_t image_width, uint16_t image_height, + uint16_t offset_x, uint16_t offset_y, bool wrap = false, bool bg = false, uint8_t on_level = DEFAULT_ON_LEVEL, uint8_t padding = 0); + void clear(); + void show(); + + private: + void i2c_reg_write_uint8(uint8_t reg, uint8_t value); + }; + +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 908711e3..c74a1165 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(breakout_dotmatrix) add_subdirectory(breakout_roundlcd) add_subdirectory(breakout_rgbmatrix5x5) add_subdirectory(breakout_matrix11x7) diff --git a/examples/breakout_dotmatrix/CMakeLists.txt b/examples/breakout_dotmatrix/CMakeLists.txt new file mode 100644 index 00000000..4d842236 --- /dev/null +++ b/examples/breakout_dotmatrix/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(bargraph) +add_subdirectory(eyes) +add_subdirectory(image) +add_subdirectory(timer) \ No newline at end of file diff --git a/examples/breakout_dotmatrix/bargraph/CMakeLists.txt b/examples/breakout_dotmatrix/bargraph/CMakeLists.txt new file mode 100644 index 00000000..39aa1a81 --- /dev/null +++ b/examples/breakout_dotmatrix/bargraph/CMakeLists.txt @@ -0,0 +1,12 @@ +set(OUTPUT_NAME dotmatrix_bargraph) + +add_executable( + ${OUTPUT_NAME} + bargraph.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_dotmatrix) + +# create map/bin/hex file etc. +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/breakout_dotmatrix/bargraph/bargraph.cpp b/examples/breakout_dotmatrix/bargraph/bargraph.cpp new file mode 100644 index 00000000..a9c2783c --- /dev/null +++ b/examples/breakout_dotmatrix/bargraph/bargraph.cpp @@ -0,0 +1,57 @@ +#include + +#include "breakout_dotmatrix.hpp" +#include "time.h" + +using namespace pimoroni; + +BreakoutDotMatrix display; +static const uint8_t WIDTH = display.WIDTH; +static const uint8_t HEIGHT = display.HEIGHT; +static const uint8_t HALF_WIDTH = (WIDTH / 2); + +uint8_t values[HALF_WIDTH] = { 0, 0, 0, 0, 0 }; +uint8_t next_value = 0; + +int main() { + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + + display.init(); + + while(true) { + gpio_put(PICO_DEFAULT_LED_PIN, true); + + absolute_time_t at = get_absolute_time(); + uint64_t t = to_us_since_boot(at) / 1000000; + + // Add a new random value to our array, overriding the oldest value + values[next_value] = rand() % HEIGHT; + next_value = (next_value + 1) % HALF_WIDTH; + + // Animate a value from 0 to height + 1 + float value = (sinf(t * M_PI) + 1) / 2.0f; + value *= HEIGHT + 1; + value = floor(value); + + for(uint8_t y = 0; y < HEIGHT; y++) { + uint8_t y_inv = HEIGHT - 1 - y; + + for(uint8_t x = 0; x < HALF_WIDTH; x++) { + // Left + display.set_pixel(x, y_inv, value <= y_inv); + + // Right + display.set_pixel(x + HALF_WIDTH, y_inv, values[(x + next_value) % HALF_WIDTH] <= y_inv); + } + } + + display.show(); + + gpio_put(PICO_DEFAULT_LED_PIN, false); + + sleep_ms(1000 / HEIGHT); + } + + return 0; +} \ No newline at end of file diff --git a/examples/breakout_dotmatrix/eyes/CMakeLists.txt b/examples/breakout_dotmatrix/eyes/CMakeLists.txt new file mode 100644 index 00000000..d2a48b0c --- /dev/null +++ b/examples/breakout_dotmatrix/eyes/CMakeLists.txt @@ -0,0 +1,12 @@ +set(OUTPUT_NAME dotmatrix_eyes) + +add_executable( + ${OUTPUT_NAME} + eyes.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_dotmatrix) + +# create map/bin/hex file etc. +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/breakout_dotmatrix/eyes/eyes.cpp b/examples/breakout_dotmatrix/eyes/eyes.cpp new file mode 100644 index 00000000..f685ec75 --- /dev/null +++ b/examples/breakout_dotmatrix/eyes/eyes.cpp @@ -0,0 +1,59 @@ +#include + +#include "breakout_dotmatrix.hpp" +#include "time.h" + +using namespace pimoroni; + +BreakoutDotMatrix display; +bool led_toggle = false; + +void eye(uint8_t x, uint8_t y) { + display.set_pixel(x, y, true); + display.set_pixel(x, y + 1, true); + display.set_pixel(x + 1, y, true); + display.set_pixel(x + 1, y + 1, true); +} + +int main() { + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + + display.init(); + + while(true) { + absolute_time_t at = get_absolute_time(); + uint64_t t = to_us_since_boot(at) / 1000000; + + // Get eye x and y positions in the range 0.0 to 1.0 + // You can plug in your own 0.0 to 1.0 values here + uint64_t t_pi = t * M_PI; + float x = (sinf(t_pi / 2) + 1) / 2; + float y = (sinf(t_pi / 4) + 1) / 2; + + // Multiply them up to display coords and convert to int + x = floor(x * 3); + y = floor(y * 5); + + // Clear the display + display.clear(); + + // Blink occasionally + if(!(rand() % 20 == 2)) { + // Draw the eyes if not blinking + eye(x, y); + eye(x + 5, y); + } + + // Update the display at 10FPS + // This gives our crude blink code time to not look like a random flicker + display.show(); + + gpio_put(PICO_DEFAULT_LED_PIN, led_toggle); + led_toggle = !led_toggle; + + sleep_ms(100); + } + + return 0; +} \ No newline at end of file diff --git a/examples/breakout_dotmatrix/image/CMakeLists.txt b/examples/breakout_dotmatrix/image/CMakeLists.txt new file mode 100644 index 00000000..efaec03b --- /dev/null +++ b/examples/breakout_dotmatrix/image/CMakeLists.txt @@ -0,0 +1,12 @@ +set(OUTPUT_NAME dotmatrix_image) + +add_executable( + ${OUTPUT_NAME} + image.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_dotmatrix) + +# create map/bin/hex file etc. +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/breakout_dotmatrix/image/image.cpp b/examples/breakout_dotmatrix/image/image.cpp new file mode 100644 index 00000000..cc6ceecd --- /dev/null +++ b/examples/breakout_dotmatrix/image/image.cpp @@ -0,0 +1,47 @@ +#include + +#include "breakout_dotmatrix.hpp" + +using namespace pimoroni; + +BreakoutDotMatrix display; +bool led_toggle = false; + + // Left Image Padding Right Image Padding +uint8_t image[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 }; + +static const uint8_t IMAGE_HEIGHT = 7; +static const uint8_t IMAGE_PADDING = 3; // 3 columns of padding +static const uint8_t IMAGE_WIDTH = floor(sizeof(image) / IMAGE_HEIGHT); +static const uint8_t ON_LEVEL = 1; //The value above which an image's pixel will be considered as on + +uint8_t offset = 0; + + + +int main() { + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + + display.init(); + + while(true) { + display.set_image(image, IMAGE_WIDTH, IMAGE_HEIGHT, offset, 0, true, false, ON_LEVEL, IMAGE_PADDING); + display.show(); + + gpio_put(PICO_DEFAULT_LED_PIN, led_toggle); + led_toggle = !led_toggle; + + sleep_ms(500); + + offset = (offset + 1) % IMAGE_WIDTH; + } + + return 0; +} diff --git a/examples/breakout_dotmatrix/timer/CMakeLists.txt b/examples/breakout_dotmatrix/timer/CMakeLists.txt new file mode 100644 index 00000000..9cb663a1 --- /dev/null +++ b/examples/breakout_dotmatrix/timer/CMakeLists.txt @@ -0,0 +1,12 @@ +set(OUTPUT_NAME dotmatrix_timer) + +add_executable( + ${OUTPUT_NAME} + timer.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_dotmatrix) + +# create map/bin/hex file etc. +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/breakout_dotmatrix/timer/timer.cpp b/examples/breakout_dotmatrix/timer/timer.cpp new file mode 100644 index 00000000..ffd8976b --- /dev/null +++ b/examples/breakout_dotmatrix/timer/timer.cpp @@ -0,0 +1,46 @@ +#include +#include + +#include "breakout_dotmatrix.hpp" +#include "time.h" + +using namespace pimoroni; + +BreakoutDotMatrix display(BreakoutDotMatrix::DEFAULT_I2C_ADDRESS); +bool led_toggle = false; + +int main() { + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + + display.init(); + display.show(); + + while(true) { + absolute_time_t at = get_absolute_time(); + uint64_t t = to_us_since_boot(at) / 1000000; + + std::string second = std::to_string(t % 60); + + uint16_t left, right; + if(second.length() == 1) { + left = '0'; + right = second[0]; + } + else { + left = second[0]; + right = second[1]; + } + + display.set_character(0, left); + display.set_character(5, right); + display.show(); + + gpio_put(PICO_DEFAULT_LED_PIN, led_toggle); + led_toggle = !led_toggle; + + sleep_ms(1000 / 60); + } + + return 0; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 91ca9308..8bd92bf3 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(breakout_dotmatrix) add_subdirectory(breakout_roundlcd) add_subdirectory(breakout_rgbmatrix5x5) add_subdirectory(breakout_matrix11x7) diff --git a/libraries/breakout_dotmatrix/CMakeLists.txt b/libraries/breakout_dotmatrix/CMakeLists.txt new file mode 100644 index 00000000..fdb3c6f0 --- /dev/null +++ b/libraries/breakout_dotmatrix/CMakeLists.txt @@ -0,0 +1 @@ +include(breakout_dotmatrix.cmake) diff --git a/libraries/breakout_dotmatrix/breakout_dotmatrix.cmake b/libraries/breakout_dotmatrix/breakout_dotmatrix.cmake new file mode 100644 index 00000000..a5e297f8 --- /dev/null +++ b/libraries/breakout_dotmatrix/breakout_dotmatrix.cmake @@ -0,0 +1,11 @@ +set(LIB_NAME breakout_dotmatrix) +add_library(${LIB_NAME} INTERFACE) + +target_sources(${LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp +) + +target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib ltp305) diff --git a/libraries/breakout_dotmatrix/breakout_dotmatrix.cpp b/libraries/breakout_dotmatrix/breakout_dotmatrix.cpp new file mode 100644 index 00000000..eab51d0d --- /dev/null +++ b/libraries/breakout_dotmatrix/breakout_dotmatrix.cpp @@ -0,0 +1,5 @@ +#include "breakout_dotmatrix.hpp" + +namespace pimoroni { + +} diff --git a/libraries/breakout_dotmatrix/breakout_dotmatrix.hpp b/libraries/breakout_dotmatrix/breakout_dotmatrix.hpp new file mode 100644 index 00000000..0a6b59a0 --- /dev/null +++ b/libraries/breakout_dotmatrix/breakout_dotmatrix.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "../../drivers/ltp305/ltp305.hpp" + +namespace pimoroni { + + typedef LTP305 BreakoutDotMatrix; +} diff --git a/micropython/examples/breakout_dotmatrix/bargraph.py b/micropython/examples/breakout_dotmatrix/bargraph.py new file mode 100644 index 00000000..665e1a6f --- /dev/null +++ b/micropython/examples/breakout_dotmatrix/bargraph.py @@ -0,0 +1,36 @@ +import time +import math +import random + +from breakout_dotmatrix import BreakoutDotMatrix + +display = BreakoutDotMatrix() +width = display.WIDTH +height = display.HEIGHT + +values = [0, 0, 0, 0, 0] +start_time = time.time() + + +while True: + # Add a new random value to our list and prune the list to visible values + values.insert(0, random.randint(0, height)) + values = values[:width] + + # Animate a value from 0 to height + 1 + value = (math.sin((time.time() - start_time) * math.pi) + 1) / 2.0 + value *= height + 1 + value = math.floor(value) + + for y in range(height): + y = height - 1 - y + + for x in range(width // 2): + # Left + display.set_pixel(x, y, value <= y) + + # Right + display.set_pixel(x + (width // 2), y, values[x] <= y) + + display.show() + time.sleep(1.0 / height) diff --git a/micropython/examples/breakout_dotmatrix/eyes.py b/micropython/examples/breakout_dotmatrix/eyes.py new file mode 100644 index 00000000..7d0b0484 --- /dev/null +++ b/micropython/examples/breakout_dotmatrix/eyes.py @@ -0,0 +1,42 @@ +import math +import time +import random + +from breakout_dotmatrix import BreakoutDotMatrix + +display = BreakoutDotMatrix() +start_time = time.time() + + +def eye(x, y): + display.set_pixel(x, y, True) + display.set_pixel(x, y + 1, True) + display.set_pixel(x + 1, y, True) + display.set_pixel(x + 1, y + 1, True) + + +while True: + t = (time.time() - start_time) * math.pi + + # Get eye x and y positions in the range 0.0 to 1.0 + # You can plug in your own 0.0 to 1.0 values here + x = (math.sin(t / 2) + 1) / 2 + y = (math.sin(t / 4) + 1) / 2 + + # Multiply them up to display coords and convert to int + x = math.floor(x * 3) + y = math.floor(y * 5) + + # Clear the display + display.clear() + + # Blink occasionally + if not random.randint(0, 20) == 2: + # Draw the eyes if not blinking + eye(x, y) + eye(x + 5, y) + + # Update the display at 10FPS + # This gives our crude blink code time to not look like a random flicker + display.show() + time.sleep(1.0 / 10) diff --git a/micropython/examples/breakout_dotmatrix/image.py b/micropython/examples/breakout_dotmatrix/image.py new file mode 100644 index 00000000..f1af07ae --- /dev/null +++ b/micropython/examples/breakout_dotmatrix/image.py @@ -0,0 +1,28 @@ +import time +import math + +from breakout_dotmatrix import BreakoutDotMatrix + +display = BreakoutDotMatrix() + +# Left Image Padding Right Image Padding +image = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0] + +image_height = 7 +image_padding = 3 # 3 columns of padding +image_width = math.floor(len(image) / image_height) + +arr = bytearray(image) + +offset = 0 +while True: + display.set_image(arr, image_width, image_height, offset_x=offset, wr=True, on_level=1, padding=image_padding) + display.show() + time.sleep(0.5) + offset = (offset + 1) % image_width diff --git a/micropython/examples/breakout_dotmatrix/timer.py b/micropython/examples/breakout_dotmatrix/timer.py new file mode 100644 index 00000000..c32db6cf --- /dev/null +++ b/micropython/examples/breakout_dotmatrix/timer.py @@ -0,0 +1,24 @@ +import time + +from breakout_dotmatrix import BreakoutDotMatrix + +address = 0x61 +start_time = time.time() + +display = BreakoutDotMatrix(address=address) +display.clear() +display.show() + +while True: + second = str((time.time() - start_time) % 60) + if len(second) == 1: + left = '0' + right = second[0] + else: + left = second[0] + right = second[1] + + display.set_character(0, ord(left)) + display.set_character(5, ord(right)) + display.show() + time.sleep(1.0 / 60) diff --git a/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.c b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.c new file mode 100644 index 00000000..b22bbddc --- /dev/null +++ b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.c @@ -0,0 +1,60 @@ +#include "breakout_dotmatrix.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// BreakoutDotMatrix Class +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Methods *****/ +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutDotMatrix_set_brightness_obj, 2, BreakoutDotMatrix_set_brightness); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutDotMatrix_set_decimal_obj, 1, BreakoutDotMatrix_set_decimal); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutDotMatrix_set_pixel_obj, 4, BreakoutDotMatrix_set_pixel); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutDotMatrix_set_character_obj, 3, BreakoutDotMatrix_set_character); +MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutDotMatrix_set_image_obj, 4, BreakoutDotMatrix_set_image); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutDotMatrix_clear_obj, BreakoutDotMatrix_clear); +MP_DEFINE_CONST_FUN_OBJ_1(BreakoutDotMatrix_show_obj, BreakoutDotMatrix_show); + +/***** Binding of Methods *****/ +STATIC const mp_rom_map_elem_t BreakoutDotMatrix_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_set_brightness), MP_ROM_PTR(&BreakoutDotMatrix_set_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_decimal), MP_ROM_PTR(&BreakoutDotMatrix_set_decimal_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&BreakoutDotMatrix_set_pixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_character), MP_ROM_PTR(&BreakoutDotMatrix_set_character_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_image), MP_ROM_PTR(&BreakoutDotMatrix_set_image_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&BreakoutDotMatrix_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&BreakoutDotMatrix_show_obj) }, + { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(WIDTH) }, + { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(HEIGHT) }, +}; +STATIC MP_DEFINE_CONST_DICT(BreakoutDotMatrix_locals_dict, BreakoutDotMatrix_locals_dict_table); + +/***** Class Definition *****/ +const mp_obj_type_t breakout_dotmatrix_BreakoutDotMatrix_type = { + { &mp_type_type }, + .name = MP_QSTR_breakout_dotmatrix, + .print = BreakoutDotMatrix_print, + .make_new = BreakoutDotMatrix_make_new, + .locals_dict = (mp_obj_dict_t*)&BreakoutDotMatrix_locals_dict, +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// breakout_dotmatrix Module +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Globals Table *****/ +STATIC const mp_map_elem_t breakout_dotmatrix_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_dotmatrix) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BreakoutDotMatrix), (mp_obj_t)&breakout_dotmatrix_BreakoutDotMatrix_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_breakout_dotmatrix_globals, breakout_dotmatrix_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t breakout_dotmatrix_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_breakout_dotmatrix_globals, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +MP_REGISTER_MODULE(MP_QSTR_breakout_dotmatrix, breakout_dotmatrix_user_cmodule, MODULE_BREAKOUT_DOTMATRIX_ENABLED); +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.cpp b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.cpp new file mode 100644 index 00000000..201cb6bf --- /dev/null +++ b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.cpp @@ -0,0 +1,250 @@ +#include "../../../libraries/breakout_dotmatrix/breakout_dotmatrix.hpp" + +#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) + +// SDA/SCL on even/odd pins, I2C0/I2C1 on even/odd pairs of pins. +#define IS_VALID_SCL(i2c, pin) (((pin) & 1) == 1 && (((pin) & 2) >> 1) == (i2c)) +#define IS_VALID_SDA(i2c, pin) (((pin) & 1) == 0 && (((pin) & 2) >> 1) == (i2c)) + + +using namespace pimoroni; + +extern "C" { +#include "breakout_dotmatrix.h" + +/***** Variables Struct *****/ +typedef struct _breakout_dotmatrix_BreakoutDotMatrix_obj_t { + mp_obj_base_t base; + BreakoutDotMatrix *breakout; +} breakout_dotmatrix_BreakoutDotMatrix_obj_t; + +/***** Print *****/ +void BreakoutDotMatrix_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; //Unused input parameter + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + BreakoutDotMatrix* breakout = self->breakout; + mp_print_str(print, "BreakoutDotMatrix("); + + mp_print_str(print, "i2c = "); + mp_obj_print_helper(print, mp_obj_new_int((breakout->get_i2c() == i2c0) ? 0 : 1), PRINT_REPR); + + mp_print_str(print, ", sda = "); + mp_obj_print_helper(print, mp_obj_new_int(breakout->get_sda()), PRINT_REPR); + + mp_print_str(print, ", scl = "); + mp_obj_print_helper(print, mp_obj_new_int(breakout->get_scl()), PRINT_REPR); + + mp_print_str(print, ")"); +} + +/***** Constructor *****/ +mp_obj_t BreakoutDotMatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = nullptr; + + if(n_args == 0) { + mp_arg_check_num(n_args, n_kw, 0, 0, true); + self = m_new_obj(breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->base.type = &breakout_dotmatrix_BreakoutDotMatrix_type; + self->breakout = new BreakoutDotMatrix(); + } + else if(n_args == 1) { + enum { ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self = m_new_obj(breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->base.type = &breakout_dotmatrix_BreakoutDotMatrix_type; + + self->breakout = new BreakoutDotMatrix(args[ARG_address].u_int); + } + else { + enum { ARG_i2c, ARG_address, ARG_sda, ARG_scl }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get I2C bus. + int i2c_id = args[ARG_i2c].u_int; + if(i2c_id < 0 || i2c_id > 1) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%d) doesn't exist"), i2c_id); + } + + int sda = args[ARG_sda].u_int; + if (!IS_VALID_SDA(i2c_id, sda)) { + mp_raise_ValueError(MP_ERROR_TEXT("bad SDA pin")); + } + + int scl = args[ARG_scl].u_int; + if (!IS_VALID_SCL(i2c_id, scl)) { + mp_raise_ValueError(MP_ERROR_TEXT("bad SCL pin")); + } + + self = m_new_obj(breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->base.type = &breakout_dotmatrix_BreakoutDotMatrix_type; + + i2c_inst_t *i2c = (i2c_id == 0) ? i2c0 : i2c1; + self->breakout = new BreakoutDotMatrix(i2c, args[ARG_address].u_int, sda, scl); + } + + self->breakout->init(); + + return MP_OBJ_FROM_PTR(self); +} + +mp_obj_t BreakoutDotMatrix_set_brightness(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_brightness, ARG_update }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_brightness, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_update, MP_ARG_BOOL, {.u_bool = false } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + + float brightness = mp_obj_get_float(args[ARG_brightness].u_obj); + if(brightness < 0 || brightness > 1.0f) + mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0"); + else + self->breakout->set_brightness((uint8_t)(brightness * BreakoutDotMatrix::MAX_BRIGHTNESS), args[ARG_update].u_bool); + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_set_decimal(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_left, ARG_right }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_left, MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_right, MP_ARG_BOOL, { .u_bool = false } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->breakout->set_decimal(args[ARG_left].u_bool, args[ARG_right].u_bool); + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_x, ARG_y, ARG_on }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_col, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_row, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_on, MP_ARG_REQUIRED | MP_ARG_BOOL }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + + if(x < 0 || x >= BreakoutDotMatrix::WIDTH || y < 0 || y >= BreakoutDotMatrix::HEIGHT) + mp_raise_ValueError("x or y out of range."); + else + self->breakout->set_pixel(x, y, args[ARG_on].u_bool); + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_set_character(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_x, ARG_ch }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_col, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_char, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + + int x = args[ARG_x].u_int; + int ch = mp_obj_get_int(args[ARG_ch].u_obj); + self->breakout->set_character(x, ch); + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_set_image(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_image, ARG_width, ARG_height, ARG_offset_x, ARG_offset_y, ARG_wrap, ARG_bg, ARG_on_level, ARG_padding }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_offset_x, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_offset_y, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_wr, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_bg, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_on_level, MP_ARG_INT, {.u_int = BreakoutDotMatrix::DEFAULT_ON_LEVEL} }, + { MP_QSTR_padding, MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + + int width = args[ARG_width].u_int; + int height = args[ARG_height].u_int; + int offset_x = args[ARG_offset_x].u_int; + int offset_y = args[ARG_offset_y].u_int; + int on_level = args[ARG_on_level].u_int; + int padding = args[ARG_padding].u_int; + + if(width <= 0 || height <= 0) + mp_raise_ValueError("width or height less than or equal to zero."); + else if(offset_x < 0 || offset_y < 0) + mp_raise_ValueError("offset_x or offset_y less than zero."); + else if(on_level < 0 || offset_y > 255) + mp_raise_ValueError("on_level out of range. Expected 0 to 255"); + else if(padding < 0 || padding > 255) + mp_raise_ValueError("padding out of range. Expected 0 to 255"); + else { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_image].u_obj, &bufinfo, MP_BUFFER_READ); + + self->breakout->set_image((const uint8_t *)bufinfo.buf, width, height, + offset_x, offset_y, args[ARG_wrap].u_bool, + args[ARG_bg].u_bool, on_level, padding); + } + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_clear(mp_obj_t self_in) { + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->breakout->clear(); + + return mp_const_none; +} + +mp_obj_t BreakoutDotMatrix_show(mp_obj_t self_in) { + breakout_dotmatrix_BreakoutDotMatrix_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_dotmatrix_BreakoutDotMatrix_obj_t); + self->breakout->show(); + + return mp_const_none; +} +} \ No newline at end of file diff --git a/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.h b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.h new file mode 100644 index 00000000..a59f0639 --- /dev/null +++ b/micropython/modules/breakout_dotmatrix/breakout_dotmatrix.h @@ -0,0 +1,21 @@ +// Include MicroPython API. +#include "py/runtime.h" +#include "py/objstr.h" + +/***** Constants *****/ +static const int WIDTH = 10; +static const int HEIGHT = 7; + +/***** Extern of Class Definition *****/ +extern const mp_obj_type_t breakout_dotmatrix_BreakoutDotMatrix_type; + +/***** Extern of Class Methods *****/ +extern void BreakoutDotMatrix_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +extern mp_obj_t BreakoutDotMatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t BreakoutDotMatrix_set_brightness(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutDotMatrix_set_decimal(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutDotMatrix_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutDotMatrix_set_character(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutDotMatrix_set_image(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t BreakoutDotMatrix_show(mp_obj_t self_in); +extern mp_obj_t BreakoutDotMatrix_clear(mp_obj_t self_in); diff --git a/micropython/modules/breakout_dotmatrix/micropython.cmake b/micropython/modules/breakout_dotmatrix/micropython.cmake new file mode 100644 index 00000000..005dbfa2 --- /dev/null +++ b/micropython/modules/breakout_dotmatrix/micropython.cmake @@ -0,0 +1,20 @@ +set(MOD_NAME breakout_dotmatrix) +string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER) +add_library(usermod_${MOD_NAME} INTERFACE) + +target_sources(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/${MOD_NAME}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/ltp305/ltp305.cpp +) + +target_include_directories(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_compile_definitions(usermod_${MOD_NAME} INTERFACE + -DMODULE_${MOD_NAME_UPPER}_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file diff --git a/micropython/modules/breakout_dotmatrix/micropython.mk b/micropython/modules/breakout_dotmatrix/micropython.mk new file mode 100755 index 00000000..e58a3cc2 --- /dev/null +++ b/micropython/modules/breakout_dotmatrix/micropython.mk @@ -0,0 +1,13 @@ +set(MOD_NAME breakout_dotmatrix) +BREAKOUT_MOD_DIR := $(USERMOD_DIR) + +# Add our source files to the respective variables. +SRC_USERMOD += $(BREAKOUT_MOD_DIR)/${MOD_NAME}.c +SRC_USERMOD_CXX += $(BREAKOUT_MOD_DIR)/${MOD_NAME}.cpp + +# Add our module directory to the include path. +CFLAGS_USERMOD += -I$(BREAKOUT_MOD_DIR) +CXXFLAGS_USERMOD += -I$(BREAKOUT_MOD_DIR) + +# We use C++ features so have to link against the standard library. +LDFLAGS_USERMOD += -lstdc++ \ No newline at end of file diff --git a/micropython/modules/micropython.cmake b/micropython/modules/micropython.cmake index 220d6610..c98611ef 100644 --- a/micropython/modules/micropython.cmake +++ b/micropython/modules/micropython.cmake @@ -1,3 +1,4 @@ +include(${CMAKE_CURRENT_LIST_DIR}/breakout_dotmatrix/micropython.cmake) include(${CMAKE_CURRENT_LIST_DIR}/breakout_roundlcd/micropython.cmake) include(${CMAKE_CURRENT_LIST_DIR}/breakout_rgbmatrix5x5/micropython.cmake) include(${CMAKE_CURRENT_LIST_DIR}/breakout_matrix11x7/micropython.cmake)