acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.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 }