From 4f36c0c93226163ec339670e547a12436a605c96 Mon Sep 17 00:00:00 2001 From: Rudis Muiznieks Date: Thu, 16 Jun 2022 23:25:49 -0500 Subject: [PATCH] started on menu display --- Makefile | 2 +- README.md | 6 + slangin.ino | 105 +++++++--- src/Font3x5.cpp | 440 ++++++++++++++++++++++++++++++++++++++++++ src/Font3x5.h | 31 +++ src/Font4x6.cpp | 504 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Font4x6.h | 31 +++ src/LICENSE | 29 +++ 8 files changed, 1123 insertions(+), 25 deletions(-) create mode 100644 src/Font3x5.cpp create mode 100644 src/Font3x5.h create mode 100644 src/Font4x6.cpp create mode 100644 src/Font4x6.h create mode 100644 src/LICENSE diff --git a/Makefile b/Makefile index aec8d73..6322c17 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ slangin.hex: build cp ./build/arduino.avr.leonardo/slangin.ino.hex ./slangin.hex build: - arduino-cli compile -b arduino:avr:leonardo -e ./slangin.ino + arduino-cli compile -b arduino:avr:leonardo -e . clean: rm -rf ./build ./slangin.hex diff --git a/README.md b/README.md index b98af8f..4a3f48c 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,9 @@ arduino-cli upload -b arduino:avr:leonardo -p /dev/ttyACM1 slangin.hex ``` Your port path (`-p` argument) may differ depending on your system. + +## Resources + +Font libraries used: +- [Font3x5](https://github.com/filmote/Font3x5) +- [Font4x6](https://github.com/filmote/Font4x6) diff --git a/slangin.ino b/slangin.ino index bdb305a..3be17ea 100644 --- a/slangin.ino +++ b/slangin.ino @@ -5,8 +5,10 @@ License: WTFPL */ #include +#include "src/Font4x6.h"; Arduboy2 arduboy; +Font4x6 font4x6 = Font4x6(); enum GameState { STATE_TITLE = 0, @@ -43,24 +45,22 @@ enum Drug { DRUG_LUDES }; -enum StatusType { - STATUS_NONE = 0, - STATUS_TURN, - STATUS_FIGHT -}; - enum DialogType { DIALOG_INFO = 0, DIALOG_YESNO, DIALOG_AMOUNT }; +/**************/ +/* game state */ +/**************/ bool screenInitialized; -StatusType showStatus; -GameState gameState; +GameState sGameState; int sCurrentDay; -char sTitle[21] = {0}; -char sMenuItems[8][9] = {0}; + +/****************/ +/* player state */ +/****************/ int pMoney; int pLoanAmount; int pSavingsAmount; @@ -70,8 +70,11 @@ int pCapacity; int pHealth; int pInventory[6] = {0}; +/***********************/ +/* game setup and loop */ +/***********************/ void setup() { - gameState = STATE_TITLE; + sGameState = STATE_TITLE; screenInitialized = false; arduboy.begin(); arduboy.setFrameRate(15); @@ -82,23 +85,77 @@ void loop() { return; if (!screenInitialized) { - switch (gameState) { + arduboy.clear(); + switch (sGameState) { case STATE_TITLE: - showStatus = STATUS_NONE; - strcpy(sTitle, " Slangin' v0.9"); - break; - default: - showStatus = STATUS_NONE; - strcpy(sTitle, "[UNIMPLEMENTED]"); + drawTitle(" Slangin' v0.9"); + //char menu[3][19] = {{"New Game"}}; + //draw1ColMenu(1, menu); + char menu[5][19] = {{"Coney Island"},{"Central Park"},{"Manhatten"},{"Ghetto"},{"Brooklyn"}}; + draw2ColMenu(true, 5, menu); break; } - drawScreen(); + arduboy.display(); } } -void drawScreen() { - arduboy.clear(); - arduboy.setCursor(6, 12); - arduboy.print(sTitle); - arduboy.display(); +/***********************/ +/* screen draw heplers */ +/***********************/ +void drawTitle(const char title[]) { + arduboy.setCursor(6, 8); + arduboy.print(title); +} + +void draw1ColMenu(const bool small, + const int itemCount, + const char items[][19]) { + int colWidth = 0; + for (int i = 0; i < itemCount; i++) { + if (strlen(items[i]) > colWidth) colWidth = strlen(items[i]); + } + const int charWidth = small ? 5 : 6; + const int charHeight = small ? 7 : 10; + int x = 64 - round(colWidth * (charWidth / 2.0)); + int y = 18 - round(itemCount * (charHeight / 2.0)); + for (int i = 0; i < itemCount; i++) { + arduboy.setCursor(x, i * charHeight + 22 + y); + arduboy.print(items[i]); + } +} + +void draw2ColMenu(const bool small, + const int itemCount, + const char items[][19]) { + const int col1Count = round(itemCount / 2.0); + const int col2Count = itemCount - col1Count; + int col1Width = 0; + int col2Width = 0; + for (int i = 0; i < col1Count; i++) { + const int newLen = strlen(items[i]); + if (newLen > col1Width) col1Width = newLen; + } + for (int i = 0; i < col2Count; i++) { + const int newLen = strlen(items[col1Count + i]); + if (newLen > col2Width) col2Width = newLen; + } + const int charWidth = small ? 5 : 6; + const int charHeight = small ? 7 : 10; + int x = 64 - round((col1Width + col2Width + 2) * (charWidth / 2.0)); + int y = 18 - round(col1Count * (charHeight / 2.0)); + for (int i = 0; i < itemCount; i++) { + const int cx = (i < col1Count) + ? x + : x + (col1Width + 2) * charWidth; + const int cy = (i < col1Count) + ? i * charHeight + 22 + y + : (i - col1Count) * charHeight + 22 + y; + if (small) { + font4x6.setCursor(cx, cy); + font4x6.print(items[i]); + } else { + arduboy.setCursor(cx, cy); + arduboy.print(items[i]); + } + } } diff --git a/src/Font3x5.cpp b/src/Font3x5.cpp new file mode 100644 index 0000000..5ee5ce4 --- /dev/null +++ b/src/Font3x5.cpp @@ -0,0 +1,440 @@ +#include +#include +#include +#include "Font3x5.h" + +#define USE_LOWER_CASE + +#define FONT3X5_WIDTH 3 +#define FONT3X5_HEIGHT 6 + +#define CHAR_EXCLAMATION 33 +#define CHAR_PERIOD 46 +#define CHAR_LETTER_A 65 +#define CHAR_LETTER_Z 90 +#define CHAR_LETTER_A_LOWER 97 +#define CHAR_LETTER_Z_LOWER 122 +#define CHAR_NUMBER_0 48 +#define CHAR_NUMBER_9 57 + +#ifdef USE_LOWER_CASE + #define FONT_EXCLAMATION_INDEX 62 + #define FONT_PERIOD_INDEX 63 + #define FONT_NUMBER_INDEX 52 +#else + #define FONT_EXCLAMATION_INDEX 36 + #define FONT_PERIOD_INDEX 37 + #define FONT_NUMBER_INDEX 26 +#endif + +const uint8_t PROGMEM font_images[] = { + 3, 8, + + // #65 Letter 'A'. + 0x1F, // ░░░▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #66 Letter 'B'. + 0x1F, // ░░░▓▓▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1B, // ░░░▓▓░▓▓ + + // #67 Letter 'C'. + 0x1F, // ░░░▓▓▓▓▓ + 0x11, // ░░░▓░░░▓ + 0x11, // ░░░▓░░░▓ + + // #68 Letter 'D'. + 0x1F, // ░░░▓▓▓▓▓ + 0x11, // ░░░▓░░░▓ + 0x0E, // ░░░░▓▓▓░ + + // #69 Letter 'E'. + 0x1F, // ░░░▓▓▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x11, // ░░░▓░░░▓ + + // #70 Letter 'F'. + 0x1F, // ░░░▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + 0x01, // ░░░░░░░▓ + + // #71 Letter 'G'. + 0x1F, // ░░░▓▓▓▓▓ + 0x11, // ░░░▓░░░▓ + 0x1D, // ░░░▓▓▓░▓ + + // #72 Letter 'H'. + 0x1F, // ░░░▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #73 Letter 'I'. + 0x00, // ░░░░░░░░ + 0x1F, // ░░░▓▓▓▓▓ + 0x00, // ░░░░░░░░ + + // #74 Letter 'J'. + 0x10, // ░░░▓░░░░ + 0x10, // ░░░▓░░░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #75 Letter 'K'. + 0x1F, // ░░░▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x1B, // ░░░▓▓░▓▓ + + // #76 Letter 'L'. + 0x1F, // ░░░▓▓▓▓▓ + 0x10, // ░░░▓░░░░ + 0x10, // ░░░▓░░░░ + + // #77 Letter 'M'. + 0x1F, // ░░░▓▓▓▓▓ + 0x06, // ░░░░░▓▓░ + 0x1F, // ░░░▓▓▓▓▓ + + // #78 Letter 'N'. + 0x1F, // ░░░▓▓▓▓▓ + 0x01, // ░░░░░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #79 Letter 'O'. + 0x1F, // ░░░▓▓▓▓▓ + 0x11, // ░░░▓░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #80 Letter 'P'. + 0x1F, // ░░░▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + 0x07, // ░░░░░▓▓▓ + + // #81 Letter 'Q'. + 0x1F, // ░░░▓▓▓▓▓ + 0x31, // ░░▓▓░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #82 Letter 'R'. + 0x1F, // ░░░▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + 0x1B, // ░░░▓▓░▓▓ + + // #83 Letter 'S'. + 0x17, // ░░░▓░▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1D, // ░░░▓▓▓░▓ + + // #84 Letter 'T'. + 0x01, // ░░░░░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + 0x01, // ░░░░░░░▓ + + // #85 Letter 'U'. + 0x1F, // ░░░▓▓▓▓▓ + 0x10, // ░░░▓░░░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #86 Letter 'V'. + 0x0F, // ░░░░▓▓▓▓ + 0x10, // ░░░▓░░░░ + 0x0F, // ░░░░▓▓▓▓ + + // #87 Letter 'W'. + 0x1F, // ░░░▓▓▓▓▓ + 0x0C, // ░░░░▓▓░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #88 Letter 'X'. + 0x1B, // ░░░▓▓░▓▓ + 0x04, // ░░░░░▓░░ + 0x1B, // ░░░▓▓░▓▓ + + // #89 Letter 'Y'. + 0x07, // ░░░░░▓▓▓ + 0x1C, // ░░░▓▓▓░░ + 0x07, // ░░░░░▓▓▓ + + // #90 Letter 'Z'. + 0x19, // ░░░▓▓░░▓ + 0x15, // ░░░▓░▓░▓ + 0x13, // ░░░▓░░▓▓ + + #ifdef USE_LOWER_CASE + + // #97 Letter 'a'. + 0x0C, // ░░░░▓▓░░ + 0x12, // ░░░▓░░▓░ + 0x1E, // ░░░▓▓▓▓░ + + // #98 Letter 'b'. + 0x1F, // ░░░▓▓▓▓▓ + 0x12, // ░░░▓░░▓░ + 0x0C, // ░░░░▓▓░░ + + // #99 Letter 'c'. + 0x1E, // ░░░▓▓▓▓░ + 0x12, // ░░░▓░░▓░ + 0x12, // ░░░▓░░▓░ + + // #100 Letter 'd'. + 0x0C, // ░░░░▓▓░░ + 0x12, // ░░░▓░░▓░ + 0x1F, // ░░░▓▓▓▓▓ + + // #101 Letter 'e'. + 0x0C, // ░░░░▓▓░░ + 0x1A, // ░░░▓▓░▓░ + 0x14, // ░░░▓░▓░░ + + // #102 Letter 'f'. + 0x04, // ░░░░░▓░░ + 0x1F, // ░░░▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + + // #103 Letter 'g'. + 0x2E, // ░░▓░▓▓▓░ + 0x2A, // ░░▓░▓░▓░ + 0x1E, // ░░░▓▓▓▓░ + + // #104 Letter 'h'. + 0x1F, // ░░░▓▓▓▓▓ + 0x02, // ░░░░░░▓░ + 0x1C, // ░░░▓▓▓░░ + + // #105 Letter 'i'. + 0x00, // ░░░░░░░░ + 0x1D, // ░░░▓▓▓░▓ + 0x00, // ░░░░░░░░ + + // #106 Letter 'j'. + 0x20, // ░░▓░░░░░ + 0x1D, // ░░░▓▓▓░▓ + 0x00, // ░░░░░░░░ + + // #107 Letter 'k'. + 0x1F, // ░░░▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x1A, // ░░░▓▓░▓░ + + // #108 Letter 'l'. + 0x01, // ░░░░░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + 0x00, // ░░░░░░░░ + + // #109 Letter 'm'. + 0x1E, // ░░░▓▓▓▓░ + 0x04, // ░░░░░▓░░ + 0x1E, // ░░░▓▓▓▓░ + + // #110 Letter 'n'. + 0x1E, // ░░░▓▓▓▓░ + 0x02, // ░░░░░░▓░ + 0x1E, // ░░░▓▓▓▓░ + + // #111 Letter 'o'. + 0x1E, // ░░░▓▓▓▓░ + 0x12, // ░░░▓░░▓░ + 0x1E, // ░░░▓▓▓▓░ + + // #112 Letter 'p'. + 0x3E, // ░░▓▓▓▓▓░ + 0x12, // ░░░▓░░▓░ + 0x0C, // ░░░░▓▓░░ + + // #113 Letter 'q'. + 0x0C, // ░░░░▓▓░░ + 0x12, // ░░░▓░░▓░ + 0x3E, // ░░▓▓▓▓▓░ + + // #114 Letter 'r'. + 0x1E, // ░░░▓▓▓▓░ + 0x02, // ░░░░░░▓░ + 0x06, // ░░░░░▓▓░ + + // #115 Letter 's'. + 0x14, // ░░░▓░▓░░ + 0x12, // ░░░▓░░▓░ + 0x0A, // ░░░░▓░▓░ + + // #116 Letter 't'. + 0x02, // ░░░░░░▓░ + 0x0F, // ░░░░▓▓▓▓ + 0x12, // ░░░▓░░▓░ + + // #117 Letter 'u'. + 0x1E, // ░░░▓▓▓▓░ + 0x10, // ░░░▓░░░░ + 0x1E, // ░░░▓▓▓▓░ + + // #118 Letter 'v'. + 0x0E, // ░░░░▓▓▓░ + 0x10, // ░░░▓░░░░ + 0x0E, // ░░░░▓▓▓░ + + // #119 Letter 'w'. + 0x1E, // ░░░▓▓▓▓░ + 0x08, // ░░░░▓░░░ + 0x1E, // ░░░▓▓▓▓░ + + // #120 Letter 'x'. + 0x1A, // ░░░▓▓░▓░ + 0x04, // ░░░░░▓░░ + 0x1A, // ░░░▓▓░▓░ + + // #121 Letter 'y'. + 0x2E, // ░░▓░▓▓▓░ + 0x28, // ░░▓░▓░░░ + 0x1E, // ░░░▓▓▓▓░ + + // #122 Letter 'z'. + 0x1A, // ░░░▓▓░▓░ + 0x12, // ░░░▓░░▓░ + 0x16, // ░░░▓░▓▓░ + + #endif + + // #48 Number '0'. + 0x1F, // ░░░▓▓▓▓▓ + 0x11, // ░░░▓░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #49 Number '1'. + 0x00, // ░░░░░░░░ + 0x1F, // ░░░▓▓▓▓▓ + 0x00, // ░░░░░░░░ + + // #50 Number '2'. + 0x1D, // ░░░▓▓▓░▓ + 0x15, // ░░░▓░▓░▓ + 0x17, // ░░░▓░▓▓▓ + + // #51 Number '3'. + 0x11, // ░░░▓░░░▓ + 0x15, // ░░░▓░▓░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #52 Number '4'. + 0x07, // ░░░░░▓▓▓ + 0x04, // ░░░░░▓░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #53 Number '5'. + 0x17, // ░░░▓░▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1D, // ░░░▓▓▓░▓ + + // #54 Number '6'. + 0x1F, // ░░░▓▓▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1D, // ░░░▓▓▓░▓ + + // #55 Number '7'. + 0x01, // ░░░░░░░▓ + 0x01, // ░░░░░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #56 Number '8'. + 0x1F, // ░░░▓▓▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #57 Number '9'. + 0x17, // ░░░▓░▓▓▓ + 0x15, // ░░░▓░▓░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #33 Symbol '!'. + 0x00, // ░░░░░░░░ + 0x17, // ░░░▓░▓▓▓ + 0x00, // ░░░░░░░░ + + // #46 Symbol '.'. + 0x00, // ░░░░░░░░ + 0x10, // ░░░▓░░░░ + 0x00 // ░░░░░░░░ + +}; + + +Font3x5::Font3x5(uint8_t lineSpacing) { + + _lineHeight = lineSpacing; + _letterSpacing = 1; + + _cursorX = _cursorY = _baseX = 0; + _textColor = 1; + +} + +size_t Font3x5::write(uint8_t c) { + + if (c == '\n') { _cursorX = _baseX; _cursorY += _lineHeight; } + else { + + printChar(c, _cursorX, _cursorY); + _cursorX += FONT3X5_WIDTH + _letterSpacing; + + } + + return 1; + +} + +void Font3x5::printChar(const char c, const int8_t x, int8_t y) { + + int8_t idx = -1; + + ++y; + + switch (c) { + + case CHAR_LETTER_A ... CHAR_LETTER_Z: + idx = c - CHAR_LETTER_A; + break; + +#ifdef USE_LOWER_CASE + case CHAR_LETTER_A_LOWER ... CHAR_LETTER_Z_LOWER: + idx = c - CHAR_LETTER_A_LOWER + 26; + break; +#endif + + case CHAR_NUMBER_0 ... CHAR_NUMBER_9: + idx = c - CHAR_NUMBER_0 + FONT_NUMBER_INDEX; + break; + + case CHAR_EXCLAMATION: + idx = FONT_EXCLAMATION_INDEX; + break; + + case CHAR_PERIOD: + idx = FONT_PERIOD_INDEX; + break; + + } + + if (idx > -1) { + + if (_textColor == WHITE) { + Sprites::drawSelfMasked(x, y, font_images, idx); + } + else { + Sprites::drawErase(x, y, font_images, idx); + } + + } + +} + +void Font3x5::setCursor(const int8_t x, const int8_t y) { + _cursorX = _baseX = x; + _cursorY = y; +} + +void Font3x5::setTextColor(const uint8_t color){ + _textColor = color; +} + +void Font3x5::setHeight(const uint8_t color){ + _lineHeight = color; +} diff --git a/src/Font3x5.h b/src/Font3x5.h new file mode 100644 index 0000000..e78c052 --- /dev/null +++ b/src/Font3x5.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +class Font3x5 : public Print { + + public: + + Font3x5(uint8_t lineSpacing = 8); + + virtual size_t write(uint8_t); // used by the Arduino Print class + void printChar(const char c, const int8_t x, int8_t y); + void setCursor(const int8_t x, const int8_t y); + + void setTextColor(const uint8_t color); + void setHeight(const uint8_t color); + + + private: + + int8_t _cursorX; // Default is 0. + int8_t _baseX; // needed for linebreak. + int8_t _cursorY; // Default is 0. + + int8_t _textColor; // BLACK == 0, everything else is WHITE. Default is WHITE. + + uint8_t _letterSpacing; // letterSpacing controls the distance between letters. Default is 1. + uint8_t _lineHeight; // lineHeight controls the height between lines breakend by \n. Default is 8. + +}; diff --git a/src/Font4x6.cpp b/src/Font4x6.cpp new file mode 100644 index 0000000..d133e9e --- /dev/null +++ b/src/Font4x6.cpp @@ -0,0 +1,504 @@ +#include +#include +#include +#include "Font4x6.h" + +#define USE_LOWER_CASE + +#define FONT4x6_WIDTH 4 +#define FONT4x6_HEIGHT 7 + +#define CHAR_EXCLAMATION 33 +#define CHAR_PERIOD 46 +#define CHAR_LETTER_A 65 +#define CHAR_LETTER_Z 90 +#define CHAR_LETTER_A_LOWER 97 +#define CHAR_LETTER_Z_LOWER 122 +#define CHAR_NUMBER_0 48 +#define CHAR_NUMBER_9 57 + +#ifdef USE_LOWER_CASE + #define FONT_EXCLAMATION_INDEX 62 + #define FONT_PERIOD_INDEX 63 + #define FONT_NUMBER_INDEX 52 +#else + #define FONT_EXCLAMATION_INDEX 36 + #define FONT_PERIOD_INDEX 37 + #define FONT_NUMBER_INDEX 26 +#endif + +const uint8_t PROGMEM font_images[] = { + 4, 8, + + // #65 Letter 'A'. + 0x3E, // ░░▓▓▓▓▓░ + 0x09, // ░░░░▓░░▓ + 0x09, // ░░░░▓░░▓ + 0x3E, // ░░▓▓▓▓▓░ + + // #66 Letter 'B'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x1A, // ░░░▓▓░▓░ + + // #67 Letter 'C'. + 0x1E, // ░░░▓▓▓▓░ + 0x21, // ░░▓░░░░▓ + 0x21, // ░░▓░░░░▓ + 0x12, // ░░░▓░░▓░ + + // #68 Letter 'D'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x21, // ░░▓░░░░▓ + 0x21, // ░░▓░░░░▓ + 0x1E, // ░░░▓▓▓▓░ + + // #69 Letter 'E'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x21, // ░░▓░░░░▓ + + // #70 Letter 'F'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x05, // ░░░░░▓░▓ + 0x05, // ░░░░░▓░▓ + 0x01, // ░░░░░░░▓ + + // #71 Letter 'G'. + 0x1E, // ░░░▓▓▓▓░ + 0x21, // ░░▓░░░░▓ + 0x29, // ░░▓░▓░░▓ + 0x3A, // ░░▓▓▓░▓░ + + // #72 Letter 'H'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x04, // ░░░░░▓░░ + 0x3F, // ░░▓▓▓▓▓▓ + + // #73 Letter 'I'. + 0x21, // ░░▓░░░░▓ + 0x3F, // ░░▓▓▓▓▓▓ + 0x21, // ░░▓░░░░▓ + 0x00, // ░░░░░░░░ + + // #74 Letter 'J'. + 0x10, // ░░░▓░░░░ + 0x21, // ░░▓░░░░▓ + 0x21, // ░░▓░░░░▓ + 0x1F, // ░░░▓▓▓▓▓ + + // #75 Letter 'K'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x0A, // ░░░░▓░▓░ + 0x31, // ░░▓▓░░░▓ + + // #76 Letter 'L'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x20, // ░░▓░░░░░ + 0x20, // ░░▓░░░░░ + 0x20, // ░░▓░░░░░ + + // #77 Letter 'M'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x02, // ░░░░░░▓░ + 0x02, // ░░░░░░▓░ + 0x3F, // ░░▓▓▓▓▓▓ + + // #78 Letter 'N'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x02, // ░░░░░░▓░ + 0x04, // ░░░░░▓░░ + 0x3F, // ░░▓▓▓▓▓▓ + + // #79 Letter 'O'. + 0x1E, // ░░░▓▓▓▓░ + 0x21, // ░░▓░░░░▓ + 0x21, // ░░▓░░░░▓ + 0x1E, // ░░░▓▓▓▓░ + + // #80 Letter 'P'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x09, // ░░░░▓░░▓ + 0x09, // ░░░░▓░░▓ + 0x06, // ░░░░░▓▓░ + + // #81 Letter 'Q'. + 0x1E, // ░░░▓▓▓▓░ + 0x21, // ░░▓░░░░▓ + 0x11, // ░░░▓░░░▓ + 0x2E, // ░░▓░▓▓▓░ + + // #82 Letter 'R'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x09, // ░░░░▓░░▓ + 0x09, // ░░░░▓░░▓ + 0x36, // ░░▓▓░▓▓░ + + // #83 Letter 'S'. + 0x22, // ░░▓░░░▓░ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x19, // ░░░▓▓░░▓ + + // #84 Letter 'T'. + 0x01, // ░░░░░░░▓ + 0x3F, // ░░▓▓▓▓▓▓ + 0x01, // ░░░░░░░▓ + 0x01, // ░░░░░░░▓ + + // #85 Letter 'U'. + 0x1F, // ░░░▓▓▓▓▓ + 0x20, // ░░▓░░░░░ + 0x20, // ░░▓░░░░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #86 Letter 'V'. + 0x0F, // ░░░░▓▓▓▓ + 0x10, // ░░░▓░░░░ + 0x20, // ░░▓░░░░░ + 0x1F, // ░░░▓▓▓▓▓ + + // #87 Letter 'W'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x10, // ░░░▓░░░░ + 0x10, // ░░░▓░░░░ + 0x3F, // ░░▓▓▓▓▓▓ + + // #88 Letter 'X'. + 0x3B, // ░░▓▓▓░▓▓ + 0x04, // ░░░░░▓░░ + 0x04, // ░░░░░▓░░ + 0x3B, // ░░▓▓▓░▓▓ + + // #89 Letter 'Y'. + 0x03, // ░░░░░░▓▓ + 0x04, // ░░░░░▓░░ + 0x38, // ░░▓▓▓░░░ + 0x07, // ░░░░░▓▓▓ + + // #90 Letter 'Z'. + 0x31, // ░░▓▓░░░▓ + 0x2D, // ░░▓░▓▓░▓ + 0x23, // ░░▓░░░▓▓ + 0x21, // ░░▓░░░░▓ + + #ifdef USE_LOWER_CASE + + // #97 Letter 'a'. + 0x10, // ░░░▓░░░░ + 0x2A, // ░░▓░▓░▓░ + 0x2A, // ░░▓░▓░▓░ + 0x3C, // ░░▓▓▓▓░░ + + // #98 Letter 'b'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x24, // ░░▓░░▓░░ + 0x24, // ░░▓░░▓░░ + 0x18, // ░░░▓▓░░░ + + // #99 Letter 'c'. + 0x1C, // ░░░▓▓▓░░ + 0x22, // ░░▓░░░▓░ + 0x22, // ░░▓░░░▓░ + 0x14, // ░░░▓░▓░░ + + // #100 Letter 'd'. + 0x18, // ░░░▓▓░░░ + 0x24, // ░░▓░░▓░░ + 0x24, // ░░▓░░▓░░ + 0x3F, // ░░▓▓▓▓▓▓ + + // #101 Letter 'e'. + 0x1C, // ░░░▓▓▓░░ + 0x2A, // ░░▓░▓░▓░ + 0x2A, // ░░▓░▓░▓░ + 0x2C, // ░░▓░▓▓░░ + + // #102 Letter 'f'. + 0x04, // ░░░░░▓░░ + 0x7E, // ░▓▓▓▓▓▓░ + 0x05, // ░░░░░▓░▓ + 0x01, // ░░░░░░░▓ + + // #103 Letter 'g'. + 0x4C, // ░▓░░▓▓░░ + 0x52, // ░▓░▓░░▓░ + 0x52, // ░▓░▓░░▓░ + 0x3E, // ░░▓▓▓▓▓░ + + // #104 Letter 'h'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x04, // ░░░░░▓░░ + 0x04, // ░░░░░▓░░ + 0x38, // ░░▓▓▓░░░ + + // #105 Letter 'i'. + 0x24, // ░░▓░░▓░░ + 0x3D, // ░░▓▓▓▓░▓ + 0x20, // ░░▓░░░░░ + 0x00, // ░░░░░░░░ + + // #106 Letter 'j'. + 0x40, // ░▓░░░░░░ + 0x40, // ░▓░░░░░░ + 0x44, // ░▓░░░▓░░ + 0x3D, // ░░▓▓▓▓░▓ + + // #107 Letter 'k'. + 0x3F, // ░░▓▓▓▓▓▓ + 0x08, // ░░░░▓░░░ + 0x14, // ░░░▓░▓░░ + 0x22, // ░░▓░░░▓░ + + // #108 Letter 'l'. + 0x21, // ░░▓░░░░▓ + 0x3F, // ░░▓▓▓▓▓▓ + 0x20, // ░░▓░░░░░ + 0x00, // ░░░░░░░░ + + // #109 Letter 'm'. + 0x3E, // ░░▓▓▓▓▓░ + 0x04, // ░░░░░▓░░ + 0x04, // ░░░░░▓░░ + 0x3E, // ░░▓▓▓▓▓░ + + // #110 Letter 'n'. + 0x3E, // ░░▓▓▓▓▓░ + 0x04, // ░░░░░▓░░ + 0x02, // ░░░░░░▓░ + 0x3C, // ░░▓▓▓▓░░ + + // #111 Letter 'o'. + 0x1C, // ░░░▓▓▓░░ + 0x22, // ░░▓░░░▓░ + 0x22, // ░░▓░░░▓░ + 0x1C, // ░░░▓▓▓░░ + + // #112 Letter 'p'. + 0x7E, // ░▓▓▓▓▓▓░ + 0x22, // ░░▓░░░▓░ + 0x22, // ░░▓░░░▓░ + 0x1C, // ░░░▓▓▓░░ + + // #113 Letter 'q'. + 0x1C, // ░░░▓▓▓░░ + 0x22, // ░░▓░░░▓░ + 0x22, // ░░▓░░░▓░ + 0x7E, // ░▓▓▓▓▓▓░ + + // #114 Letter 'r'. + 0x3E, // ░░▓▓▓▓▓░ + 0x04, // ░░░░░▓░░ + 0x02, // ░░░░░░▓░ + 0x04, // ░░░░░▓░░ + + // #115 Letter 's'. + 0x24, // ░░▓░░▓░░ + 0x2A, // ░░▓░▓░▓░ + 0x2A, // ░░▓░▓░▓░ + 0x12, // ░░░▓░░▓░ + + // #116 Letter 't'. + 0x02, // ░░░░░░▓░ + 0x1F, // ░░░▓▓▓▓▓ + 0x22, // ░░▓░░░▓░ + 0x20, // ░░▓░░░░░ + + // #117 Letter 'u'. + 0x1E, // ░░░▓▓▓▓░ + 0x20, // ░░▓░░░░░ + 0x20, // ░░▓░░░░░ + 0x1E, // ░░░▓▓▓▓░ + + // #118 Letter 'v'. + 0x0E, // ░░░░▓▓▓░ + 0x10, // ░░░▓░░░░ + 0x20, // ░░▓░░░░░ + 0x1E, // ░░░▓▓▓▓░ + + // #119 Letter 'w'. + 0x3E, // ░░▓▓▓▓▓░ + 0x10, // ░░░▓░░░░ + 0x10, // ░░░▓░░░░ + 0x3E, // ░░▓▓▓▓▓░ + + // #120 Letter 'x'. + 0x36, // ░░▓▓░▓▓░ + 0x08, // ░░░░▓░░░ + 0x08, // ░░░░▓░░░ + 0x36, // ░░▓▓░▓▓░ + + // #121 Letter 'y'. + 0x4E, // ░▓░░▓▓▓░ + 0x50, // ░▓░▓░░░░ + 0x50, // ░▓░▓░░░░ + 0x3E, // ░░▓▓▓▓▓░ + + // #122 Letter 'z'. + 0x32, // ░░▓▓░░▓░ + 0x2A, // ░░▓░▓░▓░ + 0x26, // ░░▓░░▓▓░ + 0x22, // ░░▓░░░▓░ + + #endif + + // #48 Number '0'. + 0x1E, // ░░░▓▓▓▓░ + 0x29, // ░░▓░▓░░▓ + 0x25, // ░░▓░░▓░▓ + 0x1E, // ░░░▓▓▓▓░ + + // #49 Number '1'. + 0x22, // ░░▓░░░▓░ + 0x3F, // ░░▓▓▓▓▓▓ + 0x20, // ░░▓░░░░░ + 0x00, // ░░░░░░░░ + + // #50 Number '2'. + 0x32, // ░░▓▓░░▓░ + 0x29, // ░░▓░▓░░▓ + 0x29, // ░░▓░▓░░▓ + 0x26, // ░░▓░░▓▓░ + + // #51 Number '3'. + 0x12, // ░░░▓░░▓░ + 0x21, // ░░▓░░░░▓ + 0x25, // ░░▓░░▓░▓ + 0x1A, // ░░░▓▓░▓░ + + // #52 Number '4'. + 0x0C, // ░░░░▓▓░░ + 0x0A, // ░░░░▓░▓░ + 0x3F, // ░░▓▓▓▓▓▓ + 0x08, // ░░░░▓░░░ + + // #53 Number '5'. + 0x17, // ░░░▓░▓▓▓ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x19, // ░░░▓▓░░▓ + + // #54 Number '6'. + 0x1E, // ░░░▓▓▓▓░ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x18, // ░░░▓▓░░░ + + // #55 Number '7'. + 0x01, // ░░░░░░░▓ + 0x39, // ░░▓▓▓░░▓ + 0x05, // ░░░░░▓░▓ + 0x03, // ░░░░░░▓▓ + + // #56 Number '8'. + 0x1A, // ░░░▓▓░▓░ + 0x25, // ░░▓░░▓░▓ + 0x25, // ░░▓░░▓░▓ + 0x1A, // ░░░▓▓░▓░ + + // #57 Number '9'. + 0x06, // ░░░░░▓▓░ + 0x29, // ░░▓░▓░░▓ + 0x29, // ░░▓░▓░░▓ + 0x1E, // ░░░▓▓▓▓░ + + // #33 Symbol '!'. + 0x00, // ░░░░░░░░ + 0x2F, // ░░▓░▓▓▓▓ + 0x00, // ░░░░░░░░ + 0x00, // ░░░░░░░░ + + // #46 Symbol '.'. + 0x00, // ░░░░░░░░ + 0x20, // ░░▓░░░░░ + 0x00, // ░░░░░░░░ + 0x00 // ░░░░░░░░ + +}; + + +Font4x6::Font4x6(uint8_t lineSpacing) { + + _lineHeight = lineSpacing; + _letterSpacing = 1; + + _cursorX = _cursorY = _baseX = 0; + _textColor = 1; + +} + +size_t Font4x6::write(uint8_t c) { + + if (c == '\n') { _cursorX = _baseX; _cursorY += _lineHeight; } + else { + + printChar(c, _cursorX, _cursorY); + _cursorX += FONT4x6_WIDTH + _letterSpacing; + + } + + return 1; + +} + +void Font4x6::printChar(const char c, const int8_t x, int8_t y) { + + int8_t idx = -1; + + ++y; + + switch (c) { + + case CHAR_LETTER_A ... CHAR_LETTER_Z: + idx = c - CHAR_LETTER_A; + break; + +#ifdef USE_LOWER_CASE + case CHAR_LETTER_A_LOWER ... CHAR_LETTER_Z_LOWER: + idx = c - CHAR_LETTER_A_LOWER + 26; + break; +#endif + + case CHAR_NUMBER_0 ... CHAR_NUMBER_9: + idx = c - CHAR_NUMBER_0 + FONT_NUMBER_INDEX; + break; + + case CHAR_EXCLAMATION: + idx = FONT_EXCLAMATION_INDEX; + break; + + case CHAR_PERIOD: + idx = FONT_PERIOD_INDEX; + break; + + } + + if (idx > -1) { + + if (_textColor == WHITE) { + Sprites::drawSelfMasked(x, y, font_images, idx); + } + else { + Sprites::drawErase(x, y, font_images, idx); + } + + } + +} + +void Font4x6::setCursor(const int8_t x, const int8_t y) { + _cursorX = _baseX = x; + _cursorY = y; +} + +void Font4x6::setTextColor(const uint8_t color){ + _textColor = color; +} + +void Font4x6::setHeight(const uint8_t color){ + _lineHeight = color; +} diff --git a/src/Font4x6.h b/src/Font4x6.h new file mode 100644 index 0000000..64627b4 --- /dev/null +++ b/src/Font4x6.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +class Font4x6 : public Print { + + public: + + Font4x6(uint8_t lineSpacing = 8); + + virtual size_t write(uint8_t); // used by the Arduino Print class + void printChar(const char c, const int8_t x, int8_t y); + void setCursor(const int8_t x, const int8_t y); + + void setTextColor(const uint8_t color); + void setHeight(const uint8_t color); + + + private: + + int8_t _cursorX; // Default is 0. + int8_t _baseX; // needed for linebreak. + int8_t _cursorY; // Default is 0. + + int8_t _textColor; // BLACK == 0, everything else is WHITE. Default is WHITE. + + uint8_t _letterSpacing; // letterSpacing controls the distance between letters. Default is 1. + uint8_t _lineHeight; // lineHeight controls the height between lines breakend by \n. Default is 8. + +}; diff --git a/src/LICENSE b/src/LICENSE new file mode 100644 index 0000000..b90a2eb --- /dev/null +++ b/src/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Filmote +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.