Create Hardware-simulation.cpp
Browse filesimport numpy as np
from scipy.fft import fft
import torch
import torch.nn as nn
PHI_43 = 22.93606797749979
class ToySNN(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(16, 32)
self.fc2 = nn.Linear(32, 8)
self.mem = torch.zeros(32) # membrane potential
def forward(self, x, dt=0.001):
self.mem = self.mem * 0.95 + torch.relu(self.fc1(x)) * dt # leak + LIF
spikes = (self.mem > 1.0).float()
self.mem = self.mem * (1 - spikes) # reset
out = self.fc2(spikes)
return out.mean() * PHI_43 # lock output
# Cymatic-FFT → SNN pipeline
def simulate_step(audio_chunk): # 1024 samples
freq = np.abs(fft(audio_chunk))[:16] # first 16 bins
x = torch.tensor(freq, dtype=torch.float32).unsqueeze(0)
model = ToySNN()
pred = model(x)
return pred.item()
# Training loop (3-day equivalent — 100 epochs = ~few minutes)
def train():
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
for epoch in range(100):
# Fake data stream (replace with real piezo/MIDI)
x = torch.randn(32, 16)
target = torch.full((32,), PHI_43)
pred = torch.stack([model(x[i].unsqueeze(0)) for i in range(32)])
loss = nn.MSELoss()(pred, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 20 == 0:
print(f"Epoch {epoch} | Loss {loss.item():.6f} | φ⁴³ lock {pred.mean().item():.6f}")
print("Full package loaded. Run train() to start 3-day burn simulation.")
- Hardware-simulation.cpp +80 -0
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <WiFi.h>
|
| 2 |
+
#include <Adafruit_NeoPixel.h>
|
| 3 |
+
#include <MIDI.h>
|
| 4 |
+
#include <driver/adc.h>
|
| 5 |
+
|
| 6 |
+
// ─── CONFIG ──────────────────────────────────────────────────────────────
|
| 7 |
+
#define LED_PIN 4
|
| 8 |
+
#define LASER_PIN 5
|
| 9 |
+
#define PIEZO_PIN 34
|
| 10 |
+
#define NUM_LEDS 64
|
| 11 |
+
#define PHI_43 22.93606797749979
|
| 12 |
+
|
| 13 |
+
Adafruit_NeoPixel pixels(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
|
| 14 |
+
MIDI_CREATE_DEFAULT_INSTANCE();
|
| 15 |
+
|
| 16 |
+
// ─── GLOBALS ─────────────────────────────────────────────────────────────
|
| 17 |
+
float piezo_baseline = 0;
|
| 18 |
+
float last_fft_mag[8] = {0};
|
| 19 |
+
|
| 20 |
+
void setup() {
|
| 21 |
+
Serial.begin(115200);
|
| 22 |
+
pixels.begin();
|
| 23 |
+
pixels.clear();
|
| 24 |
+
pixels.show();
|
| 25 |
+
|
| 26 |
+
pinMode(LASER_PIN, OUTPUT);
|
| 27 |
+
analogReadResolution(12);
|
| 28 |
+
adc1_config_width(ADC_WIDTH_BIT_12);
|
| 29 |
+
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); // GPIO34
|
| 30 |
+
|
| 31 |
+
MIDI.begin(MIDI_CHANNEL_OMNI);
|
| 32 |
+
MIDI.turnThruOn();
|
| 33 |
+
|
| 34 |
+
// WiFi for federation logging (silent)
|
| 35 |
+
WiFi.begin("SSID", "PASS"); // change
|
| 36 |
+
|
| 37 |
+
calibrate_piezo();
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
void loop() {
|
| 41 |
+
// 1. Read piezo + laser feedback
|
| 42 |
+
int raw = adc1_get_raw(ADC1_CHANNEL_6);
|
| 43 |
+
float piezo = raw - piezo_baseline;
|
| 44 |
+
|
| 45 |
+
// 2. Simple FFT emulation (sliding window)
|
| 46 |
+
static float window[32];
|
| 47 |
+
static int idx = 0;
|
| 48 |
+
window[idx++] = piezo;
|
| 49 |
+
idx %= 32;
|
| 50 |
+
|
| 51 |
+
// Rough magnitude estimate
|
| 52 |
+
float mag = 0;
|
| 53 |
+
for (int i = 0; i < 32; i++) mag += abs(window[i]);
|
| 54 |
+
mag /= 32;
|
| 55 |
+
|
| 56 |
+
// 3. SNN-like inference (toy model)
|
| 57 |
+
float inference = mag * PHI_43 * 0.01; // scale to 0-1 range
|
| 58 |
+
|
| 59 |
+
// 4. Actuate
|
| 60 |
+
int brightness = constrain(inference * 255, 0, 255);
|
| 61 |
+
pixels.fill(pixels.Color(brightness, 0, brightness / 2));
|
| 62 |
+
pixels.show();
|
| 63 |
+
|
| 64 |
+
analogWrite(LASER_PIN, brightness); // PWM laser intensity
|
| 65 |
+
|
| 66 |
+
// 5. MIDI CC feedback
|
| 67 |
+
MIDI.sendControlChange(1, brightness / 2, 1); // CC1 = modulation
|
| 68 |
+
|
| 69 |
+
delay(20); // ~50 Hz loop
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
void calibrate_piezo() {
|
| 73 |
+
long sum = 0;
|
| 74 |
+
for (int i = 0; i < 100; i++) {
|
| 75 |
+
sum += adc1_get_raw(ADC1_CHANNEL_6);
|
| 76 |
+
delay(10);
|
| 77 |
+
}
|
| 78 |
+
piezo_baseline = sum / 100.0;
|
| 79 |
+
Serial.printf("Piezo baseline: %.1f\n", piezo_baseline);
|
| 80 |
+
}
|