-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmadge-ician.ino
More file actions
86 lines (67 loc) · 2.88 KB
/
Copy pathmadge-ician.ino
File metadata and controls
86 lines (67 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <Arduino.h>
#include <Adafruit_TinyUSB.h>
#include <MIDI.h>
#include "config.h"
Adafruit_USBD_MIDI usb_midi;
MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI);
unsigned long lastTriggerTime[10];
bool padActive[10];
int peakValue[10] = {0,0,0,0,0,0,0,0,0,0};
void setup() {
loadAllConfigs();
// S3 Analog Pins: Adjust these if your PCB uses non-sequential pins
for (int i = 0; i < 10; i++) {
pinMode(i + 1, INPUT);
}
TinyUSBDevice.setManufacturerDescriptor(MANUF_NAME);
TinyUSBDevice.setProductDescriptor(DEVICE_NAME);
// Link the SysEx handler defined in your storage/config file
MIDI.setHandleSystemExclusive(handleSysEx);
// Web Console Fetch Request
MIDI.setHandleNoteOn([](byte channel, byte note, byte velocity) {
if (note == CC_FETCH) sendFullStateToWeb();
});
MIDI.begin(MIDI_CHANNEL_OMNI);
// Set initial LED state
neopixelWrite(RGB_PIN, global.idleR, global.idleG, global.idleB);
}
void loop() {
MIDI.read();
unsigned long now = millis();
for (int i = 0; i < 10; i++) {
if (!inputs[i].enabled) {
if (padActive[i]) {
MIDI.sendNoteOff(inputs[i].note, 0, global.midiChannel);
padActive[i] = false;
}
continue;
}
int val = analogRead(i + 1);
// 1. Check for a new hit
if (val > inputs[i].threshold && !padActive[i] && (now - lastTriggerTime[i] > inputs[i].maskTime)) {
padActive[i] = true;
lastTriggerTime[i] = now;
peakValue[i] = val; // Start tracking the peak
}
// 2. While "scanning", keep track of the highest value found
if (padActive[i] && (now - lastTriggerTime[i] <= inputs[i].scanTime)) {
if (val > peakValue[i]) peakValue[i] = val;
}
// 3. Scan time is over: Send the Note On with the calculated velocity
if (padActive[i] && (now - lastTriggerTime[i] > inputs[i].scanTime) && peakValue[i] > 0) {
// Map the analog peak to 1-127 MIDI range
// We map from [threshold] to [1023] so that the lightest touch is 1
int velocity = map(peakValue[i], inputs[i].threshold, 1023, 1, 127);
velocity = constrain(velocity, 1, 127);
MIDI.sendNoteOn(inputs[i].note, velocity, global.midiChannel);
neopixelWrite(RGB_PIN, inputs[i].r, inputs[i].g, inputs[i].b);
peakValue[i] = 0; // Reset peak so we don't trigger again until next hit
}
// 4. Release logic: Turn off LED and Note after a set duration
if (padActive[i] && (now - lastTriggerTime[i] > (inputs[i].scanTime + 100))) {
MIDI.sendNoteOff(inputs[i].note, 0, global.midiChannel);
neopixelWrite(RGB_PIN, global.idleR, global.idleG, global.idleB);
padActive[i] = false;
}
}
}