acidportal

- 😈 Worlds smallest Evil Portal on a LilyGo T-QT
git clone git://git.acid.vegas/acidportal.git
Log | Files | Refs | Archive | README | LICENSE

Animated_Eyes_1.ino (5107B)

      1 // An adaption of the "UncannyEyes" sketch (see eye_functions tab)
      2 // for the TFT_eSPI library. As written the sketch is for driving
      3 // one (240x320 minimum) TFT display, showing 2 eyes. See example
      4 // Animated_Eyes_2 for a dual 128x128 TFT display configured sketch.
      5 
      6 // The size of the displayed eye is determined by the screen size and
      7 // resolution. The eye image is 128 pixels wide. In humans the palpebral
      8 // fissure (open eye) width is about 30mm so a low resolution, large
      9 // pixel size display works best to show a scale eye image. Note that
     10 // display manufacturers usually quote the diagonal measurement, so a
     11 // 128 x 128 1.7" display or 128 x 160 2" display is about right.
     12 
     13 // Configuration settings for the eye, eye style, display count,
     14 // chip selects and x offsets can be defined in the sketch "config.h" tab.
     15 
     16 // Performance (frames per second = fps) can be improved by using
     17 // DMA (for SPI displays only) on ESP32 and STM32 processors. Use
     18 // as high a SPI clock rate as is supported by the display. 27MHz
     19 // minimum, some displays can be operated at higher clock rates in
     20 // the range 40-80MHz.
     21 
     22 // Single defaultEye performance for different processors
     23 //                                  No DMA   With DMA
     24 // ESP8266 (160MHz CPU) 40MHz SPI   36 fps
     25 // ESP32 27MHz SPI                  53 fps     85 fps
     26 // ESP32 40MHz SPI                  67 fps    102 fps
     27 // ESP32 80MHz SPI                  82 fps    116 fps // Note: Few displays work reliably at 80MHz
     28 // STM32F401 55MHz SPI              44 fps     90 fps
     29 // STM32F446 55MHz SPI              83 fps    155 fps
     30 // STM32F767 55MHz SPI             136 fps    197 fps
     31 
     32 // DMA can be used with RP2040, STM32 and ESP32 processors when the interface
     33 // is SPI, uncomment the next line:
     34 //#define USE_DMA
     35 
     36 // Load TFT driver library
     37 #include <SPI.h>
     38 #include <TFT_eSPI.h>
     39 TFT_eSPI tft;           // A single instance is used for 1 or 2 displays
     40 
     41 // A pixel buffer is used during eye rendering
     42 #define BUFFER_SIZE 1024 // 128 to 1024 seems optimum
     43 
     44 #ifdef USE_DMA
     45   #define BUFFERS 2      // 2 toggle buffers with DMA
     46 #else
     47   #define BUFFERS 1      // 1 buffer for no DMA
     48 #endif
     49 
     50 uint16_t pbuffer[BUFFERS][BUFFER_SIZE]; // Pixel rendering buffer
     51 bool     dmaBuf   = 0;                  // DMA buffer selection
     52 
     53 // This struct is populated in config.h
     54 typedef struct {        // Struct is defined before including config.h --
     55   int8_t  select;       // pin numbers for each eye's screen select line
     56   int8_t  wink;         // and wink button (or -1 if none) specified there,
     57   uint8_t rotation;     // also display rotation and the x offset
     58   int16_t xposition;    // position of eye on the screen
     59 } eyeInfo_t;
     60 
     61 #include "config.h"     // ****** CONFIGURATION IS DONE IN HERE ******
     62 
     63 extern void user_setup(void); // Functions in the user*.cpp files
     64 extern void user_loop(void);
     65 
     66 #define SCREEN_X_START 0
     67 #define SCREEN_X_END   SCREEN_WIDTH   // Badly named, actually the "eye" width!
     68 #define SCREEN_Y_START 0
     69 #define SCREEN_Y_END   SCREEN_HEIGHT  // Actually "eye" height
     70 
     71 // A simple state machine is used to control eye blinks/winks:
     72 #define NOBLINK 0       // Not currently engaged in a blink
     73 #define ENBLINK 1       // Eyelid is currently closing
     74 #define DEBLINK 2       // Eyelid is currently opening
     75 typedef struct {
     76   uint8_t  state;       // NOBLINK/ENBLINK/DEBLINK
     77   uint32_t duration;    // Duration of blink state (micros)
     78   uint32_t startTime;   // Time (micros) of last state change
     79 } eyeBlink;
     80 
     81 struct {                // One-per-eye structure
     82   int16_t   tft_cs;     // Chip select pin for each display
     83   eyeBlink  blink;      // Current blink/wink state
     84   int16_t   xposition;  // x position of eye image
     85 } eye[NUM_EYES];
     86 
     87 uint32_t startTime;  // For FPS indicator
     88 
     89 // INITIALIZATION -- runs once at startup ----------------------------------
     90 void setup(void) {
     91   Serial.begin(115200);
     92   //while (!Serial);
     93   Serial.println("Starting");
     94 
     95 #if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
     96   // Enable backlight pin, initially off
     97   Serial.println("Backlight turned off");
     98   pinMode(DISPLAY_BACKLIGHT, OUTPUT);
     99   digitalWrite(DISPLAY_BACKLIGHT, LOW);
    100 #endif
    101 
    102   // User call for additional features
    103   user_setup();
    104 
    105   // Initialise the eye(s), this will set all chip selects low for the tft.init()
    106   initEyes();
    107 
    108   // Initialise TFT
    109   Serial.println("Initialising displays");
    110   tft.init();
    111 
    112 #ifdef USE_DMA
    113   tft.initDMA();
    114 #endif
    115 
    116   // Raise chip select(s) so that displays can be individually configured
    117   digitalWrite(eye[0].tft_cs, HIGH);
    118   if (NUM_EYES > 1) digitalWrite(eye[1].tft_cs, HIGH);
    119 
    120   for (uint8_t e = 0; e < NUM_EYES; e++) {
    121     digitalWrite(eye[e].tft_cs, LOW);
    122     tft.setRotation(eyeInfo[e].rotation);
    123     tft.fillScreen(TFT_BLACK);
    124     digitalWrite(eye[e].tft_cs, HIGH);
    125   }
    126 
    127 #if defined(DISPLAY_BACKLIGHT) && (DISPLAY_BACKLIGHT >= 0)
    128   Serial.println("Backlight now on!");
    129   analogWrite(DISPLAY_BACKLIGHT, BACKLIGHT_MAX);
    130 #endif
    131 
    132   startTime = millis(); // For frame-rate calculation
    133 }
    134 
    135 // MAIN LOOP -- runs continuously after setup() ----------------------------
    136 void loop() {
    137   updateEye();
    138 }