#include #include #include #include "config.h" #include "shalomorph.h" #include "shalom.h" #include "salam.h" #include "salamorph.h" #include "together.h" #include "talis.h" #include "metta.h" #define DEBUG false #define BUTTON1PIN ((gpio_num_t)35) #define BUTTON2PIN ((gpio_num_t)0) #define INTRO_START_MILLIS 4000 #define INTRO_END_MILLIS 6000 // should be > INTRO_START_MILLIS #define PING_START_MILLIS 8000 // should be > INTRO_END_MILLIS #define OUTRO_DURATION_MILLIS 2000 #define POST_OUTRO_MILLIS 1000 unsigned long outro_start = 0; #define SEND_INTERVAL 3000 unsigned long next_send = 0; String my_mac; bool is_salam; uint8_t peer_mac_addr[6]; esp_now_peer_info_t peerInfo; bool nearby = false; #define NUM_FRAMES 23 enum frameType { FRAME_ME, FRAME_ME2US, FRAME_US, FRAME_US2U, FRAME_U }; frameType frames[NUM_FRAMES] = { FRAME_ME, FRAME_ME2US, FRAME_US, FRAME_US2U, FRAME_U, FRAME_U, FRAME_U, FRAME_US2U, FRAME_US, FRAME_US, FRAME_US2U, FRAME_U, FRAME_U, FRAME_U, FRAME_US2U, FRAME_US, FRAME_ME2US, FRAME_ME, FRAME_ME, FRAME_ME, FRAME_ME, FRAME_ME, FRAME_ME }; const unsigned short *frame2image(frameType frame, bool is_salam) { switch (frame) { case FRAME_ME: return is_salam ? salam : shalom; case FRAME_ME2US: return is_salam ? salamorph : shalomorph; case FRAME_US: return together; case FRAME_US2U: return is_salam ? shalomorph : salamorph; case FRAME_U: return is_salam ? shalom : salam; } } int current_frame = 0; unsigned long last_flip = 0; #define DURATION 100 TFT_eSPI tft = TFT_eSPI(); TFT_eSprite background = TFT_eSprite(&tft); TFT_eSprite talisSprite = TFT_eSprite(&tft); TFT_eSprite mettaSprite = TFT_eSprite(&tft); // lifted from MacAddress.c bool str2mac(char *buf, uint8_t *mac) { char cs[18]; char *token; char *next; //Unused but required int i; strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer. for (i = 0; i < 6; i++) { token = strtok((i == 0) ? cs : NULL, ":"); //Find first or next token if (!token) { //No more tokens found return false; } mac[i] = strtol(token, &next, 16); } return true; } void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { nearby = (status == ESP_NOW_SEND_SUCCESS); if (DEBUG) { Serial.println(nearby ? "Nearby" : "Not nearby"); } } void setup() { pinMode(BUTTON1PIN, INPUT_PULLUP); pinMode(BUTTON2PIN, INPUT_PULLUP); Serial.begin(115200); delay(1000); Serial.println("=== Talis-Metta ==="); // determine peer mac address my_mac = WiFi.macAddress(); Serial.println("My MAC:"); Serial.println(my_mac); if (my_mac.equals(SHALOM)) { if (DEBUG) { Serial.println("Shalom"); } is_salam = false; str2mac(SALAM, peer_mac_addr); } else { if (DEBUG) { Serial.println("Salam"); } is_salam = true; str2mac(SHALOM, peer_mac_addr); } outro_start = 0; WiFi.mode(WIFI_STA); esp_now_init(); memcpy(peerInfo.peer_addr, peer_mac_addr, 6); peerInfo.channel = 0; peerInfo.encrypt = false; esp_now_add_peer(&peerInfo); esp_now_register_send_cb(OnDataSent); tft.init(); tft.setRotation(3); // was 1 tft.setSwapBytes(true); tft.fillScreen(TFT_BLACK); background.createSprite(240, 135); background.setSwapBytes(true); talisSprite.createSprite(120, 135); talisSprite.setSwapBytes(true); talisSprite.pushImage(0, 0, 120, 135, talis); mettaSprite.createSprite(120, 135); mettaSprite.setSwapBytes(true); mettaSprite.pushImage(0, 0, 120, 135, metta); } void loop() { unsigned long nowmillis = millis(); if (digitalRead(BUTTON1PIN) == LOW) { outro_start = nowmillis; } if (nowmillis > next_send) { if (DEBUG) { Serial.println("Pinging..."); } esp_now_send(peerInfo.peer_addr, (const uint8_t *)"<3", 2); next_send = nowmillis + SEND_INTERVAL; } if ((nowmillis > PING_START_MILLIS) && nearby) { if ((nowmillis - last_flip) > DURATION || nowmillis < last_flip) { current_frame = (current_frame + 1) % NUM_FRAMES; last_flip = nowmillis; background.pushSprite(0, 0); } } else { current_frame = 0; } // FRAMEW_ME or morph if (nowmillis >= INTRO_START_MILLIS && (!outro_start || nowmillis < outro_start + OUTRO_DURATION_MILLIS)) { background.pushImage(0, 0, 240, 135, frame2image(frames[current_frame], is_salam)); } if (outro_start) { // Outro scroll overlay if (nowmillis - outro_start > OUTRO_DURATION_MILLIS + POST_OUTRO_MILLIS) { // outro over. shut down esp_sleep_enable_ext0_wakeup(BUTTON1PIN, LOW); esp_deep_sleep_start(); } else if (nowmillis - outro_start > OUTRO_DURATION_MILLIS) { talisSprite.pushToSprite(&background, 0, 0); mettaSprite.pushToSprite(&background, 120, 0); } else { // do outro long scrollPixels = 123 - (123 * (nowmillis - outro_start) / OUTRO_DURATION_MILLIS); talisSprite.pushToSprite(&background, -scrollPixels, 0); mettaSprite.pushToSprite(&background, 120 + scrollPixels, 0); } } else if (nowmillis < INTRO_START_MILLIS) { // Intro scroll overlay talisSprite.pushToSprite(&background, 0, 0); mettaSprite.pushToSprite(&background, 120, 0); } else if (nowmillis < INTRO_END_MILLIS) { long scrollPixels = 123 * (nowmillis - INTRO_START_MILLIS) / (INTRO_END_MILLIS - INTRO_START_MILLIS); talisSprite.pushToSprite(&background, -scrollPixels, 0); mettaSprite.pushToSprite(&background, 120 + scrollPixels, 0); } background.pushSprite(0, 0); }