@@ -59,6 +59,8 @@ int iPupilFactor = 42;
59
59
uint32_t boopSum = 0 ,
60
60
boopSumFiltered = 0 ;
61
61
bool booped = false ;
62
+ bool eyelidsClosed = false ;
63
+ bool eyelidsWide = false ;
62
64
int fixate = 7 ;
63
65
uint8_t lightSensorFailCount = 0 ;
64
66
@@ -135,34 +137,52 @@ uint32_t availableRAM(void) {
135
137
136
138
// USER CALLABLE FUNCTIONS
137
139
138
- // set the booped flag
139
- void eyesWide (bool t) {
140
- booped = t;
140
+ // Start a blink.
141
+ void eyesBlink () {
142
+ Serial.println (" eyesBlink()" );
143
+ timeToNextBlink = 0 ;
141
144
}
142
145
143
- // start a blink
144
- void eyesBlink () {
145
- timeToNextBlink = 0 ;
146
+ // Force the booped flag to be set true.
147
+ void eyesBoop () {
148
+ Serial.println (" eyesBoop()" );
149
+ boopSum = 99999 ;
150
+ }
151
+
152
+ // Close eyelids.
153
+ void eyesClose () {
154
+ Serial.println (" eyesClose()" );
155
+ eyelidsClosed = true ;
146
156
}
147
157
148
- // force the eyes to a position on the screen
158
+ // Return the eyes to normal random movement.
159
+ void eyesNormal () {
160
+ // Serial.println("eyesNormal()");
161
+ moveEyesRandomly = true ;
162
+ }
163
+
164
+ // Open eyelids wide.
165
+ void eyesWide () {
166
+ Serial.println (" eyesWide()" );
167
+ eyelidsWide = true ;
168
+ }
169
+
170
+ // Force the eyes to a position on the screen.
149
171
void eyesToCorner (float x, float y, bool immediate) {
172
+ // Serial.println("eyesToCorner(" + String(x) + ", " + String(-y) + ", " + (immediate ? "TRUE" : "FALSE") + ")");
150
173
moveEyesRandomly = false ;
151
174
eyeTargetX = x;
152
175
eyeTargetY = y;
153
- if (immediate)
176
+ if (immediate)
154
177
eyeMoveDuration = 0 ;
155
178
}
156
179
157
- // return the eyes to normal random movement
158
- void eyesNormal () {
159
- moveEyesRandomly = true ;
160
- }
161
-
162
180
163
181
// SETUP FUNCTION - CALLED ONCE AT PROGRAM START ---------------------------
164
182
165
183
void setup () {
184
+ Serial.println (" SETUP BEGINS" );
185
+
166
186
if (!arcada.arcadaBegin ()) fatal (" Arcada init fail!" , 100 );
167
187
#if defined(USE_TINYUSB)
168
188
if (!arcada.filesysBeginMSD ()) fatal (" No filesystem found!" , 250 );
@@ -214,10 +234,10 @@ void setup() {
214
234
#endif
215
235
216
236
yield ();
217
- if (showSplashScreen) {
218
- if (arcada.drawBMP ((char *)" /splash.bmp" , 0 , 0 , (eye[0 ].display )) == IMAGE_SUCCESS) {
237
+ if (showSplashScreen) {
238
+ if (arcada.drawBMP ((char *)" /splash.bmp" , 0 , 0 , (eye[0 ].display )) == IMAGE_SUCCESS) {
219
239
Serial.println (" Splashing" );
220
- if (NUM_EYES > 1 ) { // other eye
240
+ if (NUM_EYES > 1 ) { // other eye
221
241
yield ();
222
242
arcada.drawBMP ((char *)" /splash.bmp" , 0 , 0 , (eye[1 ].display ));
223
243
}
@@ -448,10 +468,11 @@ void setup() {
448
468
}
449
469
450
470
lastLightReadTime = micros () + 2000000 ; // Delay initial light reading
471
+
472
+ Serial.println (" END OF SETUP" );
451
473
}
452
474
453
475
454
-
455
476
// LOOP FUNCTION - CALLED REPEATEDLY UNTIL POWER-OFF -----------------------
456
477
457
478
/*
@@ -502,29 +523,29 @@ void loop() {
502
523
// Eye movement
503
524
int32_t dt = t - eyeMoveStartTime; // uS elapsed since last eye event
504
525
if (eyeInMotion) { // Currently moving?
505
- if (dt >= eyeMoveDuration) { // Time up? Destination reached.
506
- eyeInMotion = false ; // Stop moving
507
- if (moveEyesRandomly) {
508
- eyeMoveDuration = random (10000 , 3000000 ); // 0.01-3 sec stop
509
- eyeMoveStartTime = t; // Save initial time of stop
526
+ if (dt >= eyeMoveDuration) { // Time up? Destination reached.
527
+ eyeInMotion = false ; // Stop moving
528
+ if (moveEyesRandomly) {
529
+ eyeMoveDuration = random (10000 , 3000000 ); // 0.01-3 sec stop
530
+ eyeMoveStartTime = t; // Save initial time of stop
510
531
}
511
532
eyeX = eyeOldX = eyeNewX; // Save position
512
533
eyeY = eyeOldY = eyeNewY;
513
534
} else { // Move time's not yet fully elapsed -- interpolate position
514
535
float e = (float )dt / float (eyeMoveDuration); // 0.0 to 1.0 during move
515
536
e = 3 * e * e - 2 * e * e * e; // Easing function: 3*e^2-2*e^3 0.0 to 1.0
516
- eyeX = eyeOldX + (eyeNewX - eyeOldX) * e; // Interp X
517
- eyeY = eyeOldY + (eyeNewY - eyeOldY) * e; // and Y
537
+ eyeX = eyeOldX + (eyeNewX - eyeOldX) * e; // Interp X
538
+ eyeY = eyeOldY + (eyeNewY - eyeOldY) * e; // and Y
518
539
}
519
- } else { // Eye stopped
540
+ } else { // Eye stopped
520
541
eyeX = eyeOldX;
521
542
eyeY = eyeOldY;
522
- if (dt > eyeMoveDuration) { // Time up? Begin new move.
543
+ if (dt > eyeMoveDuration) { // Time up? Begin new move.
523
544
// r is the radius in X and Y that the eye can go, from (0,0) in the center.
524
545
float r = (float )mapDiameter - (float )DISPLAY_SIZE * M_PI_2; // radius of motion
525
546
r *= 0.6 ; // calibration constant
526
547
527
- if (moveEyesRandomly) {
548
+ if (moveEyesRandomly) {
528
549
eyeNewX = random (-r, r);
529
550
float h = sqrt (r * r - x * x);
530
551
eyeNewY = random (-h, h);
@@ -537,9 +558,9 @@ void loop() {
537
558
eyeNewY += mapRadius;
538
559
539
560
// Set the duration for this move, and start it going.
540
- eyeMoveDuration = random (83000 , 166000 ); // ~1/12 - ~1/6 sec
541
- eyeMoveStartTime = t; // Save initial time of move
542
- eyeInMotion = true ; // Start move on next frame
561
+ eyeMoveDuration = random (83000 , 166000 ); // ~1/12 - ~1/6 sec
562
+ eyeMoveStartTime = t; // Save initial time of move
563
+ eyeInMotion = true ; // Start move on next frame
543
564
}
544
565
}
545
566
@@ -581,24 +602,31 @@ void loop() {
581
602
iy = (int )map2screen (mapRadius - eye[eyeNum].eyeY ) + (DISPLAY_SIZE/2 ); // on screen
582
603
iy += irisRadius * trackFactor;
583
604
if (eyeNum & 1 ) ix = DISPLAY_SIZE - 1 - ix; // Flip for right eye
584
- if (iy > upperOpen[ix] ) {
605
+ if (eyelidsWide ) {
585
606
uq = 1.0 ;
586
- } else if (iy < upperClosed[ix]) {
587
- uq = 0.0 ;
588
- } else {
589
- uq = (float )(iy - upperClosed[ix]) / (float )(upperOpen[ix] - upperClosed[ix]);
590
- }
591
- if (booped) {
607
+ lq = 1.0 ;
608
+ } else if (booped) {
592
609
uq = 0.9 ;
593
610
lq = 0.7 ;
594
611
} else {
612
+ if (iy > upperOpen[ix]) {
613
+ uq = 1.0 ;
614
+ } else if (iy < upperClosed[ix]) {
615
+ uq = 0.0 ;
616
+ } else {
617
+ uq = (float )(iy - upperClosed[ix]) / (float )(upperOpen[ix] - upperClosed[ix]);
618
+ }
595
619
lq = 1.0 - uq;
596
620
}
597
621
} else {
598
622
// If no tracking, eye is FULLY OPEN when not blinking
599
623
uq = 1.0 ;
600
624
lq = 1.0 ;
601
625
}
626
+ if (eyelidsClosed) {
627
+ uq = 0.0 ;
628
+ lq = 0.0 ;
629
+ }
602
630
// Dampen eyelid movements slightly
603
631
// SAVE upper & lower lid factors per eye,
604
632
// they need to stay consistent across frame
@@ -629,13 +657,14 @@ void loop() {
629
657
// of both screens is about 1/2 this.
630
658
frames++;
631
659
if (((t - lastFrameRateReportTime) >= 1000000 ) && t) { // Once per sec.
632
- Serial.println ( (frames * 1000 ) / (t / 1000 ));
660
+ Serial.printf ( " Frame rate: %d \n " , (frames * 1000 ) / (t / 1000 ));
633
661
lastFrameRateReportTime = t;
634
662
}
635
663
636
664
// Once per frame (of eye #0), reset boopSum...
637
665
if ((eyeNum == 0 ) && (boopPin >= 0 )) {
638
666
boopSumFiltered = ((boopSumFiltered * 3 ) + boopSum) / 4 ;
667
+ // Serial.printf("boopSum: %d, boopSumFiltered: %d, boopThreshold: %d, booped: %s\n", boopSum, boopSumFiltered, boopThreshold, (booped ? "true" : "false"));
639
668
if (boopSumFiltered > boopThreshold) {
640
669
if (!booped) {
641
670
Serial.println (" BOOP!" );
@@ -647,6 +676,12 @@ void loop() {
647
676
boopSum = 0 ;
648
677
}
649
678
679
+ // Once per frame (of eye #1), reset eyelid states...
680
+ if (eyeNum == 1 ) {
681
+ eyelidsClosed = false ;
682
+ eyelidsWide = false ;
683
+ }
684
+
650
685
float mins = (float )millis () / 60000.0 ;
651
686
if (eye[eyeNum].iris .iSpin ) {
652
687
// Spin works in fixed amount per frame (eyes may lose sync, but "wagon wheel" tricks work)
0 commit comments