+#include <Wire.h>
+#include <Adafruit_MPR121.h>
+#include "ICM_20948.h"
+#include "Goldelox_Serial_4DLib.h"
+#include "Goldelox_Const4D.h"
+#define DisplaySerial Serial1
+
+//keypad stuff
+#ifndef _BV
+#define _BV(bit) (1 << (bit))
+#endif
+uint16_t lasttouched = 0;
+uint16_t currtouched = 0;
+Adafruit_MPR121 cap = Adafruit_MPR121();
+void dump_regs(); //helper function from keypad example
+
+#define SDA_PIN 21
+#define SCL_PIN 22
+#define AD0_VAL 1
+
+//imu stuff
+ICM_20948_I2C myICM;
+ICM_20948_I2C *point;
+void printScaledAGMT(ICM_20948_I2C *sensor);
+void printFormattedFloat(float val, uint8_t leading, uint8_t decimals);
+
+//lcd stuff
+Goldelox_Serial_4DLib Display(&DisplaySerial);
+#define resetLine 20
+#define LCDTx 4
+#define LCDRx 5
+
+String passcode = "0045";
+String tiltcode = "UpDownRight";
+String attempt = "";
+bool passcodeCheck = false;
+bool tiltcodeCheck = false;
+bool partone = false;
+bool parttwo = false;
+bool unlocked = false;
+void checkPasscode();
+void drawArrow();
+int count = 0;
+String tiltAttempt = "";
void setup() {
+ // keypad setup
+ delay(1000);
+ Serial.begin(115200);
+ while (!Serial);
+ Serial.println("MPR121 Autoconfiguration Test. (MPR121-AutoConfig.ino)");
+
+ Serial.println("startup `Wire`");
+ Wire.begin(SDA_PIN, SCL_PIN);
+ Wire.setClock(400000);// added
+ Serial.println("startup `Wire` done.");
+ delay(100);
+
+ Serial.println("cap.begin..");
+ if (!cap.begin(0x5A, &Wire)) {
+ Serial.println("MPR121 not found, check wiring?");
+ while (1);
+ }
+ Serial.println("MPR121 found!");
+
+ delay(100);
+
+ Serial.println("Initial CDC/CDT values:");
+ dump_regs();
+
+ cap.setAutoconfig(true);
+
+ Serial.println("After autoconfig CDC/CDT values:");
+ dump_regs();
+
+ //imu + LCD
+ bool initialized = false;
+ while(!initialized) {
+ myICM.begin(Wire, AD0_VAL);
+ Serial.print(F("Initialization of the sensor returned: "));
+ Serial.println(myICM.statusString());
+ if (myICM.status != ICM_20948_Stat_Ok) {
+ Serial.println("Trying again...");
+ delay(500);
+ }
+ else {
+ initialized = true;
+ }
+ }
+
+ //lcd setup
+ pinMode(resetLine, OUTPUT);
+ digitalWrite(resetLine, 0);
+ delay(100);
+ digitalWrite(resetLine, 1);
+ delay(5000);
+
+ DisplaySerial.begin(9600, SERIAL_8N1, LCDRx, LCDTx);
+ Display.TimeLimit4D = 5000;
+ Display.gfx_Cls();
+
+ point = &myICM;
+
+ Display.txt_FGcolour(RED);
+ Display.println("Locked");
}
void loop() {
+ // put your main code here, to run repeatedly:
+ if(!partone) {
+ checkPasscode();
+ if(passcodeCheck ==true) {
+ Display.println("Locked 1/2");
+ delay(500);
+ }
+ }
+ if(!parttwo) {
+ if(passcodeCheck == true) {
+ checkTilt();
+ if(tiltcodeCheck == true) {
+ //unlocked = true;
+ Display.gfx_Cls();
+ Display.txt_FGcolour(GREEN);
+ Display.println("Unlocked!");
+ Serial.println("Fully Unlocked");
+ delay(1000);
+ }
+ }
+ }
+}
+//function definitions
+void checkPasscode() {
+ currtouched = cap.touched();
+
+ for (uint8_t i=0; i<12; i++) {
+ bool justPressed = (currtouched & _BV(i)) && !(lasttouched & _BV(i));
+ bool justReleased = !(currtouched & _BV(i)) && (lasttouched & _BV(i));
+
+ // process only on release so it fires once per touch
+ if (justReleased) {
+ if (i == 11) {
+ if (attempt.length() > 0) {
+ attempt.remove(attempt.length() - 1);
+ }
+ }
+ else if (i == 10) {
+ if (attempt == passcode) {
+ passcodeCheck = true;
+ Display.gfx_Cls();
+ Display.txt_FGcolour(YELLOW);
+ Display.println("Correct");
+ Serial.println("Correct Passcode");
+ partone = true;
+ return;
+ } else {
+ Serial.println("Wrong Passcode");
+ Display.println("Wrong Passcode");
+ }
+ }
+ else {
+ attempt += String(i);
+ }
+ Serial.println(attempt);
+ Display.gfx_Cls();
+ Display.println(attempt);
+ }
+ }
+ lasttouched = currtouched;
+}
+void checkTilt() {
+ String lastTilt = "";
+ if (point->dataReady()) {
+ point->getAGMT();
+ } else {
+ return; // no new data
+ }
+
+ String currentTilt = "";
+
+ // Detect tilt direction
+ if(point->accX() < -500) {
+ currentTilt = "Left";
+ }
+ else if(point->accX() > 500) {
+ currentTilt = "Right";
+ }
+ else if(point->accY() < -500) {
+ currentTilt = "Down";
+ }
+ else if(point->accY() > 500) {
+ currentTilt = "Up";
+ }
+ delay(500);
+
+ // Only do something if tilt changed and is valid
+ if (currentTilt.length() > 0 && currentTilt != lastTilt) {
+ tiltAttempt += currentTilt;
+ count++;
+ lastTilt = currentTilt;
+
+ Serial.println("Tilt sequence so far: " + tiltAttempt);
+ Display.gfx_Cls();
+ Display.println(tiltAttempt);
+ drawArrow(currentTilt);
+ delay(100);
+
+ }
+
+ // Reset lastTilt when neutral (so repeats are possible again)
+ if (currentTilt == "") {
+ lastTilt = "";
+ }
+
+ // Check if we have 3 tilts
+ if (count == 3) {
+ if (tiltAttempt == tiltcode) {
+ tiltcodeCheck = true;
+ Serial.println("Correct tiltcode");
+ Display.gfx_Cls();
+ Display.println("Correct tiltcode");
+ parttwo = true;
+ } else {
+ Serial.println("Incorrect tiltcode");
+ Display.gfx_Cls();
+ Display.println("Incorrect tiltcode");
+ // Reset for next try
+ tiltAttempt = "";
+ count = 0;
+ lastTilt = "";
+ }
+ }
+}
+void drawArrow(String dir) {
+ if(dir == "Up") {
+ Display.gfx_Triangle(64, 34, 54, 54, 74, 54, WHITE);
+ Display.gfx_Rectangle(59, 54, 69, 84, WHITE);
+ }
+ else if(dir == "Down") {
+ Display.gfx_Triangle(64, 94, 54, 74, 74, 74, WHITE);
+ Display.gfx_Rectangle(59, 44, 69, 74, WHITE);
+ }
+ else if(dir == "Left") {
+ Display.gfx_Triangle(34, 64, 54, 54, 54, 74, WHITE);
+ Display.gfx_Rectangle(54, 59, 84, 69, WHITE);
+ }
+ else if(dir == "Right") {
+ Display.gfx_Triangle(94, 64, 74, 54, 74, 74, WHITE);
+ Display.gfx_Rectangle(44, 59, 74, 69, WHITE);
+ }
+ else {}
+}
+void dump_regs() { //example helper function
+ Serial.println("========================================");
+ Serial.println("CHAN 00 01 02 03 04 05 06 07 08 09 10 11");
+ Serial.println(" -- -- -- -- -- -- -- -- -- -- -- --");
+ // CDC
+ Serial.print("CDC: ");
+ for (int chan=0; chan<12; chan++) {
+ uint8_t reg = cap.readRegister8(0x5F+chan);
+ if (reg < 10) Serial.print(" ");
+ Serial.print(reg);
+ Serial.print(" ");
+ }
+ Serial.println();
+ // CDT
+ Serial.print("CDT: ");
+ for (int chan=0; chan<6; chan++) {
+ uint8_t reg = cap.readRegister8(0x6C+chan);
+ uint8_t cdtx = reg & 0b111;
+ uint8_t cdty = (reg >> 4) & 0b111;
+ if (cdtx < 10) Serial.print(" ");
+ Serial.print(cdtx);
+ Serial.print(" ");
+ if (cdty < 10) Serial.print(" ");
+ Serial.print(cdty);
+ Serial.print(" ");
+ }
+ Serial.println();
+ Serial.println("========================================");
}