Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes to wiichuck support and upstream compilation checks. #1

Merged
merged 10 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions M4_Eyes/HeatSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void HeatSensor::setup()

// default settings
status = amg.begin();
if (!status) {
if(!status) {
Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
while (1);
}
Expand Down Expand Up @@ -77,7 +77,7 @@ void HeatSensor::find_focus()
for (int i = 1; i <= AMG88xx_PIXEL_ARRAY_SIZE; i++) {
int val = min(5, round(max(0, pixels[i-1] - 20) / 2));
Serial.print(charPixels[val]);
if (i % 8 == 0)
if(i % 8 == 0)
Serial.println();
}
Serial.println();
Expand Down
111 changes: 73 additions & 38 deletions M4_Eyes/M4_Eyes.ino
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ int iPupilFactor = 42;
uint32_t boopSum = 0,
boopSumFiltered = 0;
bool booped = false;
bool eyelidsClosed = false;
bool eyelidsWide = false;
int fixate = 7;
uint8_t lightSensorFailCount = 0;

Expand Down Expand Up @@ -135,34 +137,52 @@ uint32_t availableRAM(void) {

// USER CALLABLE FUNCTIONS

// set the booped flag
void eyesWide(bool t) {
booped = t;
// Start a blink.
void eyesBlink() {
Serial.println("eyesBlink()");
timeToNextBlink = 0;
}

// start a blink
void eyesBlink() {
timeToNextBlink = 0;
// Force the booped flag to be set true.
void eyesBoop() {
Serial.println("eyesBoop()");
boopSum = 99999;
}

// Close eyelids.
void eyesClose() {
Serial.println("eyesClose()");
eyelidsClosed = true;
}

// force the eyes to a position on the screen
// Return the eyes to normal random movement.
void eyesNormal() {
// Serial.println("eyesNormal()");
moveEyesRandomly = true;
}

// Open eyelids wide.
void eyesWide() {
Serial.println("eyesWide()");
eyelidsWide = true;
}

// Force the eyes to a position on the screen.
void eyesToCorner(float x, float y, bool immediate) {
// Serial.println("eyesToCorner(" + String(x) + ", " + String(-y) + ", " + (immediate ? "TRUE" : "FALSE") + ")");
moveEyesRandomly = false;
eyeTargetX = x;
eyeTargetY = y;
if (immediate)
if(immediate)
eyeMoveDuration = 0;
}

// return the eyes to normal random movement
void eyesNormal() {
moveEyesRandomly = true;
}


// SETUP FUNCTION - CALLED ONCE AT PROGRAM START ---------------------------

void setup() {
Serial.println("SETUP BEGINS");

if(!arcada.arcadaBegin()) fatal("Arcada init fail!", 100);
#if defined(USE_TINYUSB)
if(!arcada.filesysBeginMSD()) fatal("No filesystem found!", 250);
Expand Down Expand Up @@ -214,10 +234,10 @@ void setup() {
#endif

yield();
if (showSplashScreen) {
if (arcada.drawBMP((char *)"/splash.bmp", 0, 0, (eye[0].display)) == IMAGE_SUCCESS) {
if(showSplashScreen) {
if(arcada.drawBMP((char *)"/splash.bmp", 0, 0, (eye[0].display)) == IMAGE_SUCCESS) {
Serial.println("Splashing");
if (NUM_EYES > 1) { // other eye
if(NUM_EYES > 1) { // other eye
yield();
arcada.drawBMP((char *)"/splash.bmp", 0, 0, (eye[1].display));
}
Expand Down Expand Up @@ -448,10 +468,11 @@ void setup() {
}

lastLightReadTime = micros() + 2000000; // Delay initial light reading

Serial.println("END OF SETUP");
}



// LOOP FUNCTION - CALLED REPEATEDLY UNTIL POWER-OFF -----------------------

/*
Expand Down Expand Up @@ -502,29 +523,29 @@ void loop() {
// Eye movement
int32_t dt = t - eyeMoveStartTime; // uS elapsed since last eye event
if(eyeInMotion) { // Currently moving?
if(dt >= eyeMoveDuration) { // Time up? Destination reached.
eyeInMotion = false; // Stop moving
if (moveEyesRandomly) {
eyeMoveDuration = random(10000, 3000000); // 0.01-3 sec stop
eyeMoveStartTime = t; // Save initial time of stop
if(dt >= eyeMoveDuration) { // Time up? Destination reached.
eyeInMotion = false; // Stop moving
if(moveEyesRandomly) {
eyeMoveDuration = random(10000, 3000000); // 0.01-3 sec stop
eyeMoveStartTime = t; // Save initial time of stop
}
eyeX = eyeOldX = eyeNewX; // Save position
eyeY = eyeOldY = eyeNewY;
} else { // Move time's not yet fully elapsed -- interpolate position
float e = (float)dt / float(eyeMoveDuration); // 0.0 to 1.0 during move
e = 3 * e * e - 2 * e * e * e; // Easing function: 3*e^2-2*e^3 0.0 to 1.0
eyeX = eyeOldX + (eyeNewX - eyeOldX) * e; // Interp X
eyeY = eyeOldY + (eyeNewY - eyeOldY) * e; // and Y
eyeX = eyeOldX + (eyeNewX - eyeOldX) * e; // Interp X
eyeY = eyeOldY + (eyeNewY - eyeOldY) * e; // and Y
}
} else { // Eye stopped
} else { // Eye stopped
eyeX = eyeOldX;
eyeY = eyeOldY;
if(dt > eyeMoveDuration) { // Time up? Begin new move.
if(dt > eyeMoveDuration) { // Time up? Begin new move.
// r is the radius in X and Y that the eye can go, from (0,0) in the center.
float r = (float)mapDiameter - (float)DISPLAY_SIZE * M_PI_2; // radius of motion
r *= 0.6; // calibration constant

if (moveEyesRandomly) {
if(moveEyesRandomly) {
eyeNewX = random(-r, r);
float h = sqrt(r * r - x * x);
eyeNewY = random(-h, h);
Expand All @@ -537,9 +558,9 @@ void loop() {
eyeNewY += mapRadius;

// Set the duration for this move, and start it going.
eyeMoveDuration = random(83000, 166000); // ~1/12 - ~1/6 sec
eyeMoveStartTime = t; // Save initial time of move
eyeInMotion = true; // Start move on next frame
eyeMoveDuration = random(83000, 166000); // ~1/12 - ~1/6 sec
eyeMoveStartTime = t; // Save initial time of move
eyeInMotion = true; // Start move on next frame
}
}

Expand Down Expand Up @@ -581,24 +602,31 @@ void loop() {
iy = (int)map2screen(mapRadius - eye[eyeNum].eyeY) + (DISPLAY_SIZE/2); // on screen
iy += irisRadius * trackFactor;
if(eyeNum & 1) ix = DISPLAY_SIZE - 1 - ix; // Flip for right eye
if(iy > upperOpen[ix]) {
if(eyelidsWide) {
uq = 1.0;
} else if(iy < upperClosed[ix]) {
uq = 0.0;
} else {
uq = (float)(iy - upperClosed[ix]) / (float)(upperOpen[ix] - upperClosed[ix]);
}
if(booped) {
lq = 1.0;
} else if(booped) {
uq = 0.9;
lq = 0.7;
} else {
if(iy > upperOpen[ix]) {
uq = 1.0;
} else if(iy < upperClosed[ix]) {
uq = 0.0;
} else {
uq = (float)(iy - upperClosed[ix]) / (float)(upperOpen[ix] - upperClosed[ix]);
}
lq = 1.0 - uq;
}
} else {
// If no tracking, eye is FULLY OPEN when not blinking
uq = 1.0;
lq = 1.0;
}
if(eyelidsClosed) {
uq = 0.0;
lq = 0.0;
}
// Dampen eyelid movements slightly
// SAVE upper & lower lid factors per eye,
// they need to stay consistent across frame
Expand Down Expand Up @@ -629,13 +657,14 @@ void loop() {
// of both screens is about 1/2 this.
frames++;
if(((t - lastFrameRateReportTime) >= 1000000) && t) { // Once per sec.
Serial.println((frames * 1000) / (t / 1000));
Serial.printf("Frame rate: %d\n", (frames * 1000) / (t / 1000));
lastFrameRateReportTime = t;
}

// Once per frame (of eye #0), reset boopSum...
if((eyeNum == 0) && (boopPin >= 0)) {
boopSumFiltered = ((boopSumFiltered * 3) + boopSum) / 4;
// Serial.printf("boopSum: %d, boopSumFiltered: %d, boopThreshold: %d, booped: %s\n", boopSum, boopSumFiltered, boopThreshold, (booped ? "true" : "false"));
if(boopSumFiltered > boopThreshold) {
if(!booped) {
Serial.println("BOOP!");
Expand All @@ -647,6 +676,12 @@ void loop() {
boopSum = 0;
}

// Once per frame (of eye #1), reset eyelid states...
if(eyeNum == 1) {
eyelidsClosed = false;
eyelidsWide = false;
}

float mins = (float)millis() / 60000.0;
if(eye[eyeNum].iris.iSpin) {
// Spin works in fixed amount per frame (eyes may lose sync, but "wagon wheel" tricks work)
Expand Down
41 changes: 41 additions & 0 deletions M4_Eyes/eyes/eagle/config.eye
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"boopThreshold" : 17500, // lower is more sensitive
"eyeRadius" : 125, // radius, in pixels
"irisRadius" : 120, // radius, in pixels
"slitPupilRadius" : 0, // height, in pixels; 0 is round pupil

"irisTexture" : "eagle/iris.bmp",
// "scleraTexture" : "eagle/sclera.bmp",
"scleraColor" : [ 64, 24, 22 ],
"pupilColor" : [ 0, 0, 0 ],
"backColor" : [ 140, 40, 20 ], // covers the outermost/backmost part of the eye where the sclera texture map (or color) doesn’t reach
"eyelidIndex" : "0x00", // 8-bit value; from table learn.adafruit.com/assets/61921

// independent irisTexture, scleraTexture, irisColor, scleraColor,
// pupilColor, backColor, irisAngle, scleraAngle, irisSpin, scleraSpin,
// irisMirror, scleraMirror, and rotate can be specified
"left" : {
},
"right" : {
},

"upperEyelid" : "eagle/upper.bmp",
"lowerEyelid" : "eagle/lower.bmp",
"tracking" : true,
"squint" : 0.5, // offsets eyelid center point vertically

"lightSensor" : 102, // light sensor pin; 102 is MONSTER M4SK, 21 is HalloWing M4
"pupilMin" : 0.05, // smallest pupil size as a fraction of iris size; from 0.0 to 1.0
"pupilMax" : 0.3, // largest pupil size as a fraction of iris size; from 0.0 to 1.0

"voice" : false,
"pitch" : 1.0,
"gain" : 1.0, // microphone gain (sensitivity)
// "waveform" : "sine" // "square", "sine", "tri" and "saw" are supported
// "modulate" : 30 // waveform modulation, in Hz

"wiichuck" : {
"min" : 28,
"max" : 229
}
}
Binary file added M4_Eyes/eyes/eagle/eyelid.psd
Binary file not shown.
Binary file added M4_Eyes/eyes/eagle/iris.bmp
Binary file not shown.
Binary file added M4_Eyes/eyes/eagle/iris.psd
Binary file not shown.
Binary file added M4_Eyes/eyes/eagle/lower.bmp
Binary file not shown.
Binary file added M4_Eyes/eyes/eagle/sclera.bmp
Binary file not shown.
Binary file added M4_Eyes/eyes/eagle/upper.bmp
Binary file not shown.
17 changes: 9 additions & 8 deletions M4_Eyes/file.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//34567890123456789012345678901234567890123456789012345678901234567890123456

#define ARDUINOJSON_ENABLE_COMMENTS 1
#include <ArduinoJson.h> // JSON config file functions
#define ARDUINOJSON_ENABLE_COMMENTS 1 // ARDUINOJSON_ENABLE_COMMENTS must be set to 1 before including the library.
// The same value of ARDUINOJSON_ENABLE_COMMENTS must be set in each compilation unit.
#include <ArduinoJson.h> // JSON config file functions
#include "globals.h"

extern Adafruit_Arcada arcada;
Expand Down Expand Up @@ -89,7 +90,7 @@ void loadConfig(char *filename) {
DeserializationError error = deserializeJson(doc, file);
yield();
if(error) {
Serial.println("Config file error, using default settings");
Serial.println("Config file error, using default settings.");
Serial.println(error.c_str());
} else {
uint8_t e;
Expand Down Expand Up @@ -286,7 +287,7 @@ void loadConfig(char *filename) {
file.close();
user_setup(doc);
} else {
Serial.println("Can't open config file, using default settings");
Serial.println("Can't open config file, using default settings.");
}

// INITIALIZE DEFAULT VALUES if config file missing or in error ----------
Expand Down Expand Up @@ -330,7 +331,7 @@ ImageReturnCode loadEyelid(char *filename,
Adafruit_ImageReader *reader;

reader = arcada.getImageReader();
if (!reader) {
if(!reader) {
return IMAGE_ERR_FILE_NOT_FOUND;
}

Expand All @@ -340,7 +341,7 @@ ImageReturnCode loadEyelid(char *filename,
// This is the "booster seat" described in m4eyes.ino
if(reader->bmpDimensions(filename, &w, &h) == IMAGE_SUCCESS) {
tempBytes = ((w + 7) / 8) * h; // Bitmap size in bytes
if (maxRam > tempBytes) {
if(maxRam > tempBytes) {
if((tempPtr = (uint8_t *)malloc(maxRam - tempBytes)) != NULL) {
// Make SOME tempPtr reference, or optimizer removes the alloc!
tempPtr[0] = 0;
Expand Down Expand Up @@ -416,14 +417,14 @@ ImageReturnCode loadTexture(char *filename, uint16_t **data,
Adafruit_ImageReader *reader;

reader = arcada.getImageReader();
if (!reader) {
if(!reader) {
return IMAGE_ERR_FILE_NOT_FOUND;
}

// This is the "booster seat" described in m4eyes.ino
if(reader->bmpDimensions(filename, &w, &h) == IMAGE_SUCCESS) {
tempBytes = w * h * 2; // Image size in bytes (converted to 16bpp)
if (maxRam > tempBytes) {
if(maxRam > tempBytes) {
if((tempPtr = (uint8_t *)malloc(maxRam - tempBytes)) != NULL) {
// Make SOME tempPtr reference, or optimizer removes the alloc!
tempPtr[0] = 0;
Expand Down
12 changes: 8 additions & 4 deletions M4_Eyes/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,17 @@ extern float screen2map(int in);
extern float map2screen(int in);

// Functions in user.cpp
#include <ArduinoJson.h> // JSON config file functions
#define ARDUINOJSON_ENABLE_COMMENTS 1 // ARDUINOJSON_ENABLE_COMMENTS must be set to 1 before including the library.
// The same value of ARDUINOJSON_ENABLE_COMMENTS must be set in each compilation unit.
#include <ArduinoJson.h> // JSON config file functions
extern void user_setup(void);
extern void user_setup(StaticJsonDocument<2048> &doc);
extern void user_loop(void);

// user callable functions
extern void eyesWide(bool);
// User callable functions in M4_Eyes.ino
extern void eyesBlink();
extern void eyesToCorner(float x, float y, bool immediate);
extern void eyesBoop();
extern void eyesClose();
extern void eyesNormal();
extern void eyesWide();
extern void eyesToCorner(float x, float y, bool immediate);
4 changes: 3 additions & 1 deletion M4_Eyes/user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ void user_setup(void) {

// Called once after the processing of the configuration file. This allows
// user configuration to also be done based on the config file.
#include <ArduinoJson.h> // JSON config file functions
#define ARDUINOJSON_ENABLE_COMMENTS 1 // ARDUINOJSON_ENABLE_COMMENTS must be set to 1 before including the library.
// The same value of ARDUINOJSON_ENABLE_COMMENTS must be set in each compilation unit.
#include <ArduinoJson.h> // JSON config file functions
void user_setup(StaticJsonDocument<2048> &doc) {
}

Expand Down
4 changes: 3 additions & 1 deletion M4_Eyes/user_fizzgig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ void user_setup(void) {

// Called once after the processing of the configuration file. This allows
// user configuration to also be done based on the config file.
#include <ArduinoJson.h> // JSON config file functions
#define ARDUINOJSON_ENABLE_COMMENTS 1 // ARDUINOJSON_ENABLE_COMMENTS must be set to 1 before including the library.
// The same value of ARDUINOJSON_ENABLE_COMMENTS must be set in each compilation unit.
#include <ArduinoJson.h> // JSON config file functions
void user_setup(StaticJsonDocument<2048> &doc) {
}

Expand Down
Loading