-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
217 lines (187 loc) · 8.94 KB
/
Copy pathindex.html
File metadata and controls
217 lines (187 loc) · 8.94 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="https://matsrobot.github.io/Favicon-192.png" sizes="192x192">
<title>RoboEyes: Dual GC9A01 SPI Animation System | MatsRobot</title>
<meta name="description" content="High-frame-rate robotic eye system using RP2040 and dual GC9A01 LCDs. Implements partial window refreshes, asynchronous state machines, and UART telemetry for real-time saccade masking.">
<link rel="canonical" href="https://github.com/MatsRobot/Robots-Blinking-Eyes-using-GC9A01-display" />
<style>
:root {
--gh-green: #238636;
--gh-green-hover: #2ea44f;
--gh-dark: #24292e;
--gh-blue: #0366d6;
--gh-border: #eaecef;
--gh-bg-gray: #f6f8fa;
--note-bg: #fffbdd;
--note-border: #d4a017;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
line-height: 1.6;
color: var(--gh-dark);
max-width: 950px;
margin: 0 auto;
padding: 2rem;
}
.hero-section {
display: flex;
gap: 2.5rem;
margin-bottom: 2rem;
align-items: center;
}
.hero-text { flex: 3; }
.image-sidebar {
flex: 2;
border: 1px solid var(--gh-border);
border-radius: 8px;
padding: 15px;
text-align: center;
background: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}
.image-sidebar img {
max-width: 100%;
height: auto;
border-radius: 4px;
}
.caption {
font-size: 0.85rem;
color: #586069;
margin-top: 10px;
display: block;
}
h1 { font-size: 1.8rem; margin-top: 0; }
h2 { color: var(--gh-blue); border-bottom: 1px solid var(--gh-border); padding-bottom: 0.3em; margin-top: 2rem; }
h3 { font-size: 1.1rem; margin-bottom: 0.5rem; }
.note {
background-color: var(--note-bg);
padding: 1.25rem;
border-left: 5px solid var(--note-border);
margin: 1.5rem 0;
border-radius: 4px;
}
.btn-download {
background-color: var(--gh-green);
color: white;
padding: 12px 28px;
text-decoration: none;
border-radius: 6px;
display: inline-flex;
align-items: center;
gap: 18px;
font-weight: 600;
transition: background 0.2s, transform 0.1s;
border: 1px solid rgba(27, 31, 35, 0.15);
box-shadow: 0 1px 0 rgba(27, 31, 35, 0.1);
}
.btn-download:hover { background-color: var(--gh-green-hover); }
.btn-text-container {
display: flex;
flex-direction: column;
line-height: 1.1;
}
.btn-main {
font-size: 1.35rem;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 4px;
}
.btn-sub-lines {
font-size: 0.75rem;
font-weight: 400;
opacity: 0.9;
}
.table-container { overflow-x: auto; margin: 1rem 0; }
.tech-table { width: 100%; border-collapse: collapse; min-width: 500px; }
.tech-table th, .tech-table td { padding: 12px; border: 1px solid var(--gh-border); }
.tech-table th { background-color: var(--gh-bg-gray); text-align: left; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 1.5rem; }
footer {
margin-top: 4rem;
padding: 2rem 0;
border-top: 1px solid var(--gh-border);
text-align: center;
color: #6a737d;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.hero-section, .grid { flex-direction: column; }
.hero-text { order: 2; }
.image-sidebar { order: 1; width: 100%; }
.btn-download { width: 100%; justify-content: center; box-sizing: border-box; }
}
</style>
</head>
<body>
<div class="hero-section">
<div class="hero-text">
<h1>👁️ RoboEyes: High-Frame-Rate GC9A01 System</h1>
<p>An optimized visual expression system for robots using dual 1.28-inch round LCDs and an RP2040 micro-architecture. This system utilizes <strong>partial window refreshes</strong> and <strong>asynchronous state machines</strong> to deliver 60FPS pupil tracking without the latency of procedural pixel rendering.</p>
<div class="note">
<strong>SPI Bus Optimization:</strong> By implementing a "Window Update" strategy, we bypass the need to re-transmit static background data, reducing SPI bus contention and maximizing the RP2040's effective throughput.
</div>
<a href="https://github.com/MatsRobot/Robots-Blinking-Eyes-using-GC9A01-display" class="btn-download">
<svg width="32" height="32" viewBox="0 0 24 24" fill="white">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
</svg>
<div class="btn-text-container">
<span class="btn-main">Get Source Code</span>
<div class="btn-sub-lines">
<span>Pico Firmware & Blinking Eye Assets</span>
</div>
</div>
</a>
</div>
<div class="image-sidebar">
<img src="https://raw.githubusercontent.com/MatsRobot/Robots-Blinking-Eyes-using-GC9A01-display/main/Blink3.gif" alt="RoboEyes Dual GC9A01 LCD Wiring and Animation View">
<span class="caption">Dual GC9A01 1.28" High-Speed Setup</span>
</div>
</div>
<h2>How It Works: The Logic Flow</h2>
<p>The firmware architecture focuses on low-latency memory management to maintain visual fluidity:</p>
<ul>
<li><strong>VRAM Mapping:</strong> RGB565 assets (iris, pupil, eyelid) are indexed into the display's internal DDRAM at initialization.</li>
<li><strong>Partial Frame Refreshes:</strong> The RP2040 calculates localized bounding boxes for movement, updating only modified pixel clusters.</li>
<li><strong>Asynchronous Timers:</strong> Blinking cycles are managed via non-blocking interrupts, preventing frame-drop during pupil tracking.</li>
<li><strong>UART Telemetry:</strong> High-speed serial RX enables real-time synchronization with external FaceTracker centroid data.</li>
</ul>
<h2>Technical Specifications</h2>
<div class="table-container">
<table class="tech-table">
<thead>
<tr><th>Component</th><th>Role & Specification</th></tr>
</thead>
<tbody>
<tr><td><strong>Microcontroller</strong></td><td>Raspberry Pi Pico (RP2040) @ 133MHz</td></tr>
<tr><td><strong>Display Driver</strong></td><td>2x GC9A01 Round LCD (240x240 px / 1.28")</td></tr>
<tr><td><strong>Interface</strong></td><td>Hardware SPI (Dual-CS Configuration)</td></tr>
<tr><td><strong>Color Depth</strong></td><td>RGB565 16-bit (Optimized Bit-Depth Assets)</td></tr>
<tr><td><strong>Input Protocol</strong></td><td>3.3V UART (Asynchronous Coordinate Stream)</td></tr>
</tbody>
</table>
</div>
<div class="grid">
<div>
<h3>Synchronized SPI Logic</h3>
<p>The system manages two independent round LCDs by multiplexing the MOSI line with discrete Chip Select (CS) logic, ensuring zero-latency synchronization between the left and right eye states.</p>
</div>
<div>
<h3>Active Saccade Masking</h3>
<p>Designed to replicate biological eye movements. By pairing with the ESP32-CAM FaceTracker, the system utilizes "Saccade Masking"—triggering blinks during rapid gaze shifts to hide artificial pupil "snapping."</p>
</div>
</div>
<h2>🗺️ Future Roadmap</h2>
<ul>
<li><strong>DMA Buffering:</strong> Implementing Direct Memory Access to offload SPI transmission from the RP2040 cores.</li>
<li><strong>Dynamic Pupillary Dilation:</strong> Logic for adjusting pupil diameter in response to ambient light sensors via ADC.</li>
<li><strong>PID Smoothing:</strong> Integration of PID control loops for fluid, human-like gaze transitions.</li>
</ul>
<footer>
<p>© 2026 MatsRobot - Part of the Open Source Robotics Initiative</p>
<p><small>Copyright (c) 2026 | Licensed under the <a href="https://github.com/MatsRobot/matsrobot.github.io/blob/main/LICENSE" style="color: #6a737d;">MIT License</a></small></p>
</footer>
</body>
</html>