Compare commits

...

9 Commits

Author SHA1 Message Date
d501292f32 Add double opening 2026-01-20 15:44:33 +01:00
1974376134 Use double buffer 2026-01-20 10:41:27 +01:00
8c0f98b7a7 Add easy mode without shuffling 2026-01-20 10:33:32 +01:00
92a2d39e49 Reduce sampling rate 2026-01-19 21:40:37 +01:00
69f1cba2f8 Add potiNano Code 2026-01-19 21:38:04 +01:00
e2bf85c91e Switch easy timings 2026-01-19 21:02:24 +01:00
d3f10ea70b Optimize master behavior for reset 2026-01-19 20:59:07 +01:00
c2b5331bbd Simplify reset logic 2026-01-19 20:41:52 +01:00
462485dfa6 Remove unused variable 2026-01-19 18:37:31 +01:00
8 changed files with 124 additions and 53 deletions

View File

@@ -43,9 +43,13 @@ unsigned long lockTimer = 0;
bool unlocked = false; bool unlocked = false;
void openLock(uint8_t indexOn) { void openLock(uint8_t indexOn) {
digitalWrite(schubladen[indexOn].schlossPin, HIGH);
delay(400);
digitalWrite(schubladen[indexOn].schlossPin, LOW);
delay(400);
digitalWrite(schubladen[indexOn].schlossPin, HIGH);
unlocked = true; unlocked = true;
lockTimer = millis(); lockTimer = millis();
digitalWrite(schubladen[indexOn].schlossPin, HIGH);
} }
void onI2CReceive(int len) { void onI2CReceive(int len) {

View File

@@ -71,6 +71,7 @@ ISR(PCINT1_vect)
lastState = state; lastState = state;
} }
uint8_t inputPattern = 0; uint8_t inputPattern = 0;
uint8_t secretPattern = 0b10101010;
void handleEncoderMovement() void handleEncoderMovement()
{ {
long diff = encoderPostion - lastClickPosition; long diff = encoderPostion - lastClickPosition;
@@ -88,7 +89,8 @@ void handleEncoderMovement()
selectedIndex = (selectedIndex + 7) % 8; selectedIndex = (selectedIndex + 7) % 8;
inputPattern = ((inputPattern << 1) | 0) & 0xFF; inputPattern = ((inputPattern << 1) | 0) & 0xFF;
} }
resetPuzzles(inputPattern == 0b10101010); bool reset = inputPattern == secretPattern;
resetPuzzles(reset);
setDrawerLight(selectedIndex); setDrawerLight(selectedIndex);
lastClickPosition = encoderPostion; lastClickPosition = encoderPostion;
} }
@@ -144,7 +146,11 @@ void resetPuzzles(bool easy)
digitalWrite(puzzleResetPins[i], HIGH); digitalWrite(puzzleResetPins[i], HIGH);
puzzlesSolved[i] = false; puzzlesSolved[i] = false;
} }
delay(30 * (easy * 10)); //delay 30 or 300ms if (easy)
delay(400);
else
delay(90);
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
{ {
digitalWrite(puzzleResetPins[i], LOW); digitalWrite(puzzleResetPins[i], LOW);

View File

@@ -127,6 +127,7 @@ NormalizedRGB updateLeft()
uint32_t sum = inputR + inputG + inputB; uint32_t sum = inputR + inputG + inputB;
NormalizedRGB leftRGB; NormalizedRGB leftRGB;
strip.begin();
if (sum > 0) if (sum > 0)
{ {
leftRGB.r = (uint32_t)inputR * MAX_SUM / sum; leftRGB.r = (uint32_t)inputR * MAX_SUM / sum;
@@ -138,6 +139,7 @@ NormalizedRGB updateLeft()
{ {
strip.setPixelColor(2, strip.Color(0, 0, 0, 0)); strip.setPixelColor(2, strip.Color(0, 0, 0, 0));
} }
strip.show();
return leftRGB; return leftRGB;
} }
@@ -149,7 +151,7 @@ NormalizedRGB updateMiddle()
uint32_t sum = inputR + inputG + inputB; uint32_t sum = inputR + inputG + inputB;
NormalizedRGB middleRGB; NormalizedRGB middleRGB;
strip.begin();
if (sum > 0) if (sum > 0)
{ {
middleRGB.r = (uint32_t)inputR * MAX_SUM / sum; middleRGB.r = (uint32_t)inputR * MAX_SUM / sum;
@@ -161,6 +163,7 @@ NormalizedRGB updateMiddle()
{ {
strip.setPixelColor(1, strip.Color(0, 0, 0, 0)); strip.setPixelColor(1, strip.Color(0, 0, 0, 0));
} }
strip.show();
return middleRGB; return middleRGB;
} }
@@ -172,7 +175,7 @@ NormalizedRGB updateRight()
uint32_t sum = inputR + inputG + inputB; uint32_t sum = inputR + inputG + inputB;
NormalizedRGB rightRGB; NormalizedRGB rightRGB;
strip.begin();
if (sum > 0) if (sum > 0)
{ {
rightRGB.r = (uint32_t)inputR * MAX_SUM / sum; rightRGB.r = (uint32_t)inputR * MAX_SUM / sum;
@@ -184,7 +187,7 @@ NormalizedRGB updateRight()
{ {
strip.setPixelColor(0, strip.Color(0, 0, 0, 0)); strip.setPixelColor(0, strip.Color(0, 0, 0, 0));
} }
strip.show();
return rightRGB; return rightRGB;
} }
@@ -218,40 +221,30 @@ void generateTargetGameBoard(bool easy)
slavePotiValues[i] = 0; slavePotiValues[i] = 0;
} }
digitalWrite(COMPLETED_PIN, LOW); digitalWrite(COMPLETED_PIN, LOW);
strip.begin();
strip.clear();
GameBoard board; GameBoard board;
if (easy) if (easy)
{ {
// left
board.left = generateRandomNormalizedRGB(pot3, 2, 3); board.left = generateRandomNormalizedRGB(pot3, 2, 3);
finishedLeft = false;
strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left
// middle
board.middle = generateRandomNormalizedRGB(pot4, 3, 4); board.middle = generateRandomNormalizedRGB(pot4, 3, 4);
finishedMiddle = false;
strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // middle
// right
board.right = generateRandomNormalizedRGB(pot5, 4, 5); board.right = generateRandomNormalizedRGB(pot5, 4, 5);
finishedRight = false;
strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // left
} }
else else
{ {
// left
board.left = generateRandomNormalizedRGB(pot3, 0, 3); board.left = generateRandomNormalizedRGB(pot3, 0, 3);
board.middle = generateRandomNormalizedRGB(pot4, 0, 4);
board.right = generateRandomNormalizedRGB(pot5, 1, 5);
}
strip.begin();
strip.clear();
finishedLeft = false; finishedLeft = false;
strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left
// middle
board.middle = generateRandomNormalizedRGB(pot4, 0, 4);
finishedMiddle = false; finishedMiddle = false;
strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // middle strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // middle
// right
board.right = generateRandomNormalizedRGB(pot5, 1, 5);
finishedRight = false; finishedRight = false;
strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // left strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // right
//------------------
}
finishedBoard = board; finishedBoard = board;
strip.show(); strip.show();
} }
@@ -334,7 +327,6 @@ void loop()
generateTargetGameBoard(millis() - resetTimer > 150); generateTargetGameBoard(millis() - resetTimer > 150);
} }
strip.begin();
readExternalPotiValues(); readExternalPotiValues();
if (!finishedLeft) if (!finishedLeft)
@@ -371,5 +363,4 @@ void loop()
{ {
digitalWrite(COMPLETED_PIN, HIGH); digitalWrite(COMPLETED_PIN, HIGH);
} }
strip.show();
} }

View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@@ -0,0 +1,14 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino

View File

@@ -0,0 +1,39 @@
#include <Arduino.h>
#include <Wire.h>
#define I2C_SLAVE_ADDRESS 0x08
volatile uint16_t bufferA[6];
volatile uint16_t bufferB[6];
// Pointer to the buffer currently exposed to ISR
volatile uint16_t* activeBuffer = bufferA;
void onI2CRequest() {
// Safe: ISR only reads active buffer
Wire.write((uint8_t*)activeBuffer, 6 * sizeof(uint16_t));
}
void setup() {
Wire.begin(I2C_SLAVE_ADDRESS);
Wire.onRequest(onI2CRequest);
analogReference(DEFAULT);
}
void loop() {
// Choose the inactive buffer
volatile uint16_t* writeBuffer =
(activeBuffer == bufferA) ? bufferB : bufferA;
writeBuffer[0] = analogRead(A0);
writeBuffer[1] = analogRead(A1);
writeBuffer[2] = analogRead(A2);
writeBuffer[3] = analogRead(A3);
writeBuffer[4] = analogRead(A6);
writeBuffer[5] = analogRead(A7);
// Atomic pointer swap
noInterrupts();
activeBuffer = writeBuffer;
interrupts();
}

View File

@@ -97,16 +97,21 @@ bool readButton(uint8_t i) {
// ------------------ Neues Spiel ------------------ // ------------------ Neues Spiel ------------------
void generateNewGame() { void generateNewGame(bool easy) {
for (uint8_t i = 0; i < 6; i++) solutionOrder[i] = i; for (uint8_t i = 0; i < 6; i++)
solutionOrder[i] = i;
for (int i = 5; i > 0; i--) { if (!easy)
{
for (int i = 5; i > 0; i--)
{
int j = random(i + 1); int j = random(i + 1);
uint8_t t = solutionOrder[i]; uint8_t t = solutionOrder[i];
solutionOrder[i] = solutionOrder[j]; solutionOrder[i] = solutionOrder[j];
solutionOrder[j] = t; solutionOrder[j] = t;
} }
}
for (uint8_t i = 0; i < 6; i++) for (uint8_t i = 0; i < 6; i++)
expectedOrder[i] = solutionOrder[5 - i]; expectedOrder[i] = solutionOrder[5 - i];
@@ -137,12 +142,16 @@ void generateNewGame() {
uint8_t idx[18]; uint8_t idx[18];
for (uint8_t i = 0; i < 18; i++) idx[i] = i; for (uint8_t i = 0; i < 18; i++) idx[i] = i;
for (int i = 17; i > 0; i--) { if (!easy)
{
for (int i = 17; i > 0; i--)
{
int j = random(i + 1); int j = random(i + 1);
uint8_t t = idx[i]; uint8_t t = idx[i];
idx[i] = idx[j]; idx[i] = idx[j];
idx[j] = t; idx[j] = t;
} }
}
for (uint8_t i = 0; i < 6; i++) for (uint8_t i = 0; i < 6; i++)
buttonAssignment[idx[i]] = solutionOrder[i]; buttonAssignment[idx[i]] = solutionOrder[i];
@@ -244,7 +253,7 @@ void setup() {
if (powerOnState) if (powerOnState)
{ {
generateNewGame(); generateNewGame(false);
} }
} }
@@ -271,7 +280,7 @@ void loop() {
// Detecting turn-on // Detecting turn-on
if (!powerOnState && digitalRead(PIN_POWER_ON) == HIGH) if (!powerOnState && digitalRead(PIN_POWER_ON) == HIGH)
{ {
generateNewGame(); generateNewGame(false);
powerOnState = true; powerOnState = true;
} }
if (!powerOnState) if (!powerOnState)
@@ -279,14 +288,18 @@ void loop() {
// We are turned-off and stop anything after here // We are turned-off and stop anything after here
return; return;
} }
unsigned long now = millis();
bool trigger = digitalRead(PIN_TRIGGER_SHUFFLE); if (digitalRead(PIN_TRIGGER_SHUFFLE) == HIGH)
if (trigger && !lastTriggerState) { {
generateNewGame(); unsigned long resetTimer = millis();
while (digitalRead(PIN_TRIGGER_SHUFFLE) == HIGH)
{
delay(10);
}
generateNewGame(millis() - resetTimer > 150);
} }
lastTriggerState = trigger;
unsigned long now = millis();
for (uint8_t i = 0; i < 18; i++) { for (uint8_t i = 0; i < 18; i++) {
bool pressed = readButton(i); bool pressed = readButton(i);

View File

@@ -121,7 +121,6 @@ void setup() {
} }
bool reset = false;
void loop() { void loop() {
//Detecting turn-off //Detecting turn-off
if (powerOnState && digitalRead(POWER_PIN) == LOW) { if (powerOnState && digitalRead(POWER_PIN) == LOW) {