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