#include <Wire.h>
#include <LedControl.h>
LedControl lc = LedControl(11, 13, 10, 1); // DIN, CLK, CS
#define N 8
float height[N][N];
float velX[N][N];
float velY[N][N];
int16_t ax, ay;
void setup() {
Wire.begin();
lc.shutdown(0, false);
lc.setIntensity(0, 7);
lc.clearDisplay(0);
Wire.beginTransmission(0x68);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
// calm pool
for (int x = 0; x < N; x++)
for (int y = 0; y < N; y++) {
height[x][y] = 3.5;
velX[x][y] = 0;
velY[x][y] = 0;
}
}
void loop() {
Wire.beginTransmission(0x68);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(0x68, 4, true);
ax = (Wire.read() << 8) | Wire.read();
ay = (Wire.read() << 8) | Wire.read();
// Normalize acceleration
float gx = -ax / 16384.0 * 0.4;
float gy = -ay / 16384.0 * 0.4;
for (int x = 0; x < N; x++) {
for (int y = 0; y < N; y++) {
velX[x][y] += gx;
velY[x][y] += gy;
// Damping
velX[x][y] *= 0.95;
velY[x][y] *= 0.95;
}
}
float newHeight[N][N];
for (int x = 0; x < N; x++)
for (int y = 0; y < N; y++)
newHeight[x][y] = 0;
for (int x = 0; x < N; x++) {
for (int y = 0; y < N; y++) {
int nx = x + (int)(velX[x][y] + 0.5);
int ny = y + (int)(velY[x][y] + 0.5);
// Keep in bounds
nx = constrain(nx, 0, N-1);
ny = constrain(ny, 0, N-1);
float flowAmount = height[x][y] * 0.7;
newHeight[nx][ny] += flowAmount;
newHeight[x][y] += height[x][y] * 0.3;
}
}
for (int x = 0; x < N; x++) {
for (int y = 0; y < N; y++) {
float sum = newHeight[x][y];
int count = 1;
if (x > 0) { sum += newHeight[x-1][y]; count++; }
if (x < N-1) { sum += newHeight[x+1][y]; count++; }
if (y > 0) { sum += newHeight[x][y-1]; count++; }
if (y < N-1) { sum += newHeight[x][y+1]; count++; }
height[x][y] = sum / count;
height[x][y] = constrain(height[x][y], 0.5, 7.5);
}
}
lc.clearDisplay(0);
for (int col = 0; col < N; col++) {
for (int row = 0; row < N; row++) {
int h = (int)height[col][row];
if ((7 - row) < h) {
lc.setLed(0, row, col, true);
}
}
}
delay(40);
}