From 69909851c217f0a18df8184f3848e4ee115a643d Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Sat, 21 Oct 2023 22:01:10 +0100 Subject: [PATCH] LCD: Introduce LCD display and animations Add support for the LCD and using it for displaying animations. Animations are automatically played if available for the ID of the detected tag. The code should support adding other kind of animations, for tags being removed or for other UI interactions for example. --- README.md | 4 ++-- include/LCD.h | 46 ++++++++++++++++++++++++++++++++++++ src/LCD.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 15 +++++++++++- 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 include/LCD.h create mode 100644 src/LCD.cpp diff --git a/README.md b/README.md index 2df5da7..2362bbd 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ se synchroniser avec le firmware et potentiellement le mettre à jour. - [ ] Contrôle des modules - [x] RFID (base) - [ ] RFID (avancé, écriture des tags) - - [ ] LCD (base) - - [ ] LCD (animations) + - [x] LCD (base) + - [x] LCD (animations) - [ ] LCD (UI) - [ ] Audio (sons de figurines) - [ ] Audio (sons d'UI) diff --git a/include/LCD.h b/include/LCD.h new file mode 100644 index 0000000..b3111a1 --- /dev/null +++ b/include/LCD.h @@ -0,0 +1,46 @@ +// +// Created by Teo-CD on 17/10/23. +// + +#ifndef JIN_BARBAPAPA_LCD_H +#define JIN_BARBAPAPA_LCD_H + +#include +#include +#include + +#include + +#include "Com.h" +#include "IDs.h" +#include "Pinout.h" + +class LCD { +public: + LCD() : sd(SD) {}; + void init(); + /*** + * Check if time has passed and we should display a new frame. + * @return True if a new frame was displayed. + */ + bool checkAndDisplay(); + void startNewAnim(int8_t ID); +private: + Adafruit_PCD8544 lcd{pin_LCD_DC, pin_LCD_CS, pin_LCD_RST}; + + SDClass &sd; + /* Directory where the current animation frames are stored. */ + File animDir; + + /*** + * Array storing the bitmap that will be passed to the LCD. + * The LCD is 84x48 so that should be 504 bytes, but the row length (84) + * is not byte aligned. Thus, the last byte is padded, giving 88x48 = 528. + */ + static uint8_t bitmap[528]; + uint32_t lastFrameTime = 0; + /* Delay between two frames, in milliseconds. Above 10 FPS is mushy, avoid. */ + static constexpr uint32_t frameTarget = 1000 / 7; +}; + +#endif //JIN_BARBAPAPA_LCD_H diff --git a/src/LCD.cpp b/src/LCD.cpp new file mode 100644 index 0000000..0b9e478 --- /dev/null +++ b/src/LCD.cpp @@ -0,0 +1,65 @@ +// +// Created by Teo-CD on 17/10/23. +// + +#include "LCD.h" + +uint8_t LCD::bitmap[528] = {}; + +void LCD::init() { + lcd.begin(60, 4); + lcd.clearDisplay(); + lastFrameTime = millis(); + /* Needed to keep the display clean at boot. */ + lcd.display(); + /* TODO: JIN splash welcome ? */ +} + +void LCD::startNewAnim(int8_t ID) { + char directoryPath[15]; + uint8_t rawID = getRawId(ID); + + if (!SD.mediaPresent()) { + Com::sendComment("SD Card not present, cannot play animation"); + return; + } + if (!isValidId(ID)) { + Com::sendComment("Unknown ID for animation : %d", rawID); + return; + } + + /* Interrupt previous running animation if there's one. */ + if (animDir) + animDir.close(); + + /* TODO: If adding remove animation, change path + check isIdGone */ + snprintf(directoryPath, 15, "%s/ANIM", + (isIdCharacter(ID) ? charDirs : promoDirs)[rawID]); + animDir = SD.open(directoryPath); + if (!animDir) { + Com::sendComment("Could not open directory %s for ID %d", directoryPath, rawID); + return; + } + checkAndDisplay(); +} + +bool LCD::checkAndDisplay() { + if (!animDir || millis() - lastFrameTime < frameTarget) + return false; + + File frame = animDir.openNextFile(); + if (!frame) { + /* There are no frames anymore, the animation is complete. */ + animDir.close(); + return false; + } + frame.read(bitmap, 528); + frame.close(); + + lcd.clearDisplay(); + lcd.drawBitmap(0, 0, bitmap, 84, 48, 1); + lcd.display(); + + lastFrameTime = millis(); + return true; +} diff --git a/src/main.cpp b/src/main.cpp index 14c990f..6615fef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "Pinout.h" #include "Com.h" +#include "LCD.h" #include "RFID.h" __attribute__((noreturn)) int main() { @@ -44,15 +45,27 @@ __attribute__((noreturn)) int main() { digitalWrite(pin_NFC1_RST, HIGH); rfid.init(); + if (!SD.begin(BUILTIN_SDCARD)) + Com::sendComment("Could not use the SD Card."); + + LCD lcd; + digitalWrite(pin_LCD_RST, HIGH); + lcd.init(); + /* Main loop */ while (true) { int8_t tagEvent; + /* Display first, in case the RFID communication delays it too much. */ + lcd.checkAndDisplay(); + tagEvent = rfid.checkTags(); if (tagEvent) { Com::sendFigUpdate(tagEvent); + lcd.startNewAnim(tagEvent); } - delay(100); + /* TODO: Drop delay, WFE+timer interrupt(s) ? */ + delay(25); } }