├── Programming
└── Pins.png
├── README.md
└── NMCode
└── NMCode
/Programming/Pins.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thisisnoiseinc/NMCode/HEAD/Programming/Pins.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NMCode
2 | The Brains That Make Noise Machine (NMSVE) Tick.
3 |
4 | ## Prerequisites
5 | * https://github.com/espressif/arduino-esp32
6 |
7 | ## Programming
8 |
9 | **USB to TTL Converter**
10 |
11 | You'll need a USB to TTL Converter to connect Noise Machine (NMSVE) to your PC.
12 |
13 | See below for reference:
14 |
15 | https://a.co/d/i3A57Qw
16 |
17 | **Pin Diagram**
18 |
19 | 
20 |
21 | Top to Bottom (in picture above):
22 |
23 | BOOT
24 |
25 | EN
26 |
27 | GND
28 |
29 | 3V3
30 |
31 | RX
32 |
33 | TX
34 |
35 | To enter BOOT Mode for programming pull "BOOT" to "GND" on startup.
36 |
37 | **Arduino**
38 |
39 | Use "Firebeetle-ESP32" as the board when uploading.
40 |
41 | ## Notes
42 | Originally based off neilbags code:
43 | * https://github.com/neilbags/arduino-esp32-BLE-MIDI
44 |
--------------------------------------------------------------------------------
/NMCode/NMCode:
--------------------------------------------------------------------------------
1 | /*
2 | NMCode by this.is.NOISE inc.
3 |
4 | https://github.com/thisisnoiseinc/NMCode
5 |
6 | Built upon:
7 |
8 | "BLE_MIDI Example by neilbags
9 | https://github.com/neilbags/arduino-esp32-BLE-MIDI
10 |
11 | Based on BLE_notify example by Evandro Copercini."
12 | */
13 |
14 | #include
15 |
16 | #include
17 |
18 | #include
19 |
20 | #include
21 |
22 | #include "esp_bt_main.h"
23 |
24 | #include "esp_bt_device.h"
25 |
26 | #define SERVICE_UUID "03b80e5a-ede8-4b33-a751-6ce34ec4c700"
27 |
28 | #define CHARACTERISTIC_UUID "7772e5db-3868-4112-a1a9-f2669d106bf3"
29 |
30 |
31 | int potPin = 36; // Slider
32 | int rotPin = 39; // Rotary Knob
33 | bool rotMoving = true;
34 | int midiCState = 0; // General current state
35 | int led_Blue = 14; // BLE LED
36 | int led_Green = 4; // CHANNEL LED
37 | const int button = 12;
38 | int potCstate = 0; // Slider current state
39 | int rotCState = 0; // Rotary Knob current state
40 | int outputValue = 0;
41 | int ButtonNote = 0;
42 | int Channel_SelectON = 0;
43 | int Channel_SelectOFF = 0;
44 | int Channel_SelectCC = 0;
45 | int Buttonselect[button] = { // Buttons put in order of reference board.
46 | 16,
47 | 17,
48 | 18,
49 | 21,
50 | 19,
51 | 25,
52 | 22,
53 | 23,
54 | 27,
55 | 26,
56 | 35,
57 | 34
58 | };
59 | int buttonCstate[button] = {0}; // Button current state
60 | int buttonPState[button] = {0}; // Button previous state
61 | int OffNote[button] = {0};
62 | int debounceDelay = 5;
63 | int lastDebounceTime[button] = {0};
64 | int i = 0;
65 | const int numReadings = 15;
66 | int readings[numReadings]; // the readings from the analog input
67 | int readIndex = 0; // the index of the current reading
68 | int total = 0; // the running total
69 | int average1 = 0; // average current state
70 | int lastaverage1 = 0; // average previous state
71 |
72 | BLECharacteristic *pCharacteristic;
73 |
74 | bool deviceConnected = false;
75 |
76 | uint8_t midiPacket[] = {
77 |
78 | 0x80, // header
79 |
80 | 0x80, // timestamp, not implemented
81 |
82 | 0x00, // status
83 |
84 | 0x3c, // 0x3c == 60 == middle c
85 |
86 | 0x00 // velocity
87 |
88 | };
89 |
90 | class MyServerCallbacks: public BLEServerCallbacks {
91 |
92 | void onConnect(BLEServer* pServer) {
93 |
94 | deviceConnected = true;
95 |
96 | };
97 |
98 |
99 |
100 | void onDisconnect(BLEServer* pServer) {
101 |
102 | deviceConnected = false;
103 |
104 | }
105 |
106 | };
107 |
108 | bool initBluetooth() {
109 |
110 | if (!btStart()) {
111 |
112 | Serial.println("Failed to initialize controller");
113 | return false;
114 |
115 | }
116 |
117 | if (esp_bluedroid_init() != ESP_OK) {
118 |
119 | Serial.println("Failed to initialize bluedroid");
120 | return false;
121 |
122 | }
123 |
124 | if (esp_bluedroid_enable() != ESP_OK) {
125 |
126 | Serial.println("Failed to enable bluedroid");
127 | return false;
128 |
129 | }
130 | }
131 |
132 | void setup() {
133 |
134 | Serial.begin(115200);
135 |
136 | initBluetooth();
137 | const uint8_t* point = esp_bt_dev_get_address();
138 |
139 | char str[6];
140 |
141 | sprintf(str, "NMSVE %02X %02X %02X", (int)point[3], (int)point[4], (int)point[5]);
142 | Serial.print(str);
143 |
144 | BLEDevice::init(str);
145 |
146 | BLEServer *pServer = BLEDevice::createServer();
147 |
148 | pServer->setCallbacks(new MyServerCallbacks());
149 |
150 | BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
151 |
152 | pCharacteristic = pService->createCharacteristic(
153 |
154 | BLEUUID(CHARACTERISTIC_UUID),
155 |
156 | BLECharacteristic::PROPERTY_READ |
157 |
158 | BLECharacteristic::PROPERTY_WRITE |
159 |
160 | BLECharacteristic::PROPERTY_NOTIFY |
161 |
162 | BLECharacteristic::PROPERTY_WRITE_NR
163 |
164 | );
165 |
166 | pCharacteristic->addDescriptor(new BLE2902());
167 |
168 | pService->start();
169 |
170 | BLEAdvertising *pAdvertising = pServer->getAdvertising();
171 |
172 | pAdvertising->addServiceUUID(pService->getUUID());
173 |
174 | pAdvertising->start();
175 |
176 | for (int i = 0; i < button; i++) {
177 |
178 | pinMode (Buttonselect[i], INPUT);
179 | pinMode (led_Blue, OUTPUT);
180 | pinMode (led_Green, OUTPUT);
181 |
182 | }
183 |
184 | for (int thisReading = 0; thisReading < numReadings; thisReading++) {
185 |
186 | readings[thisReading] = 0;
187 |
188 | }
189 |
190 | while (Channel_SelectON == 0) {
191 |
192 | digitalWrite(led_Green, HIGH);
193 |
194 | for (int i = 0; i < button; i++) {
195 |
196 | buttonCstate[i] = digitalRead(Buttonselect[i]);
197 |
198 | if (buttonCstate[i] == HIGH) {
199 |
200 | Channel_SelectON = (i + 144);
201 | Channel_SelectOFF = (i + 128);
202 | Channel_SelectCC = (i + 176);
203 |
204 | }
205 | }
206 | }
207 |
208 | digitalWrite(led_Green, LOW);
209 |
210 | }
211 |
212 | void loop(){
213 |
214 | if (deviceConnected == false) {
215 |
216 | digitalWrite(led_Blue, HIGH);
217 | delay(1000);
218 | digitalWrite(led_Blue, LOW);
219 | delay(1000);
220 |
221 | }
222 |
223 | else {
224 |
225 | digitalWrite(led_Blue, HIGH);
226 | BUTTONS();
227 | ROTARY();
228 |
229 | }
230 | }
231 |
232 | void BUTTONS() {
233 |
234 | for (int i = 0; i < button; i++) {
235 |
236 | buttonCstate[i] = digitalRead(Buttonselect[i]);
237 | potCstate = analogRead(potPin);
238 | outputValue = map(potCstate, 0, 4095, 3, 9);
239 | ButtonNote = (outputValue * 12 + i);
240 |
241 | if (outputValue == 3 || outputValue == 5 || outputValue == 7 || outputValue == 9) {
242 |
243 | digitalWrite(led_Green, HIGH);
244 |
245 | }
246 |
247 | else {
248 |
249 | digitalWrite(led_Green, LOW);
250 |
251 | }
252 |
253 | if ((millis() - lastDebounceTime[i]) > debounceDelay) {
254 |
255 | if (buttonPState[i] != buttonCstate[i]) {
256 |
257 | lastDebounceTime[i] = millis();
258 |
259 | if (buttonCstate[i] == HIGH) {
260 |
261 | midiPacket[2] = Channel_SelectON;
262 | Serial.println(Channel_SelectON);
263 | midiPacket[3] = ButtonNote;
264 | Serial.println(midiPacket[3]);
265 | midiPacket[4] = 100;
266 | pCharacteristic->setValue(midiPacket, 5);
267 | pCharacteristic->notify();
268 | OffNote[i] = ButtonNote;
269 |
270 | }
271 |
272 | else {
273 |
274 | midiPacket[2] = Channel_SelectOFF;
275 | Serial.println(Channel_SelectOFF);
276 | midiPacket[3] = OffNote[i];
277 | midiPacket[4] = 0;
278 | pCharacteristic->setValue(midiPacket, 5);
279 | pCharacteristic->notify();
280 |
281 | }
282 |
283 | buttonPState[i] = buttonCstate[i];
284 |
285 | }
286 | }
287 | }
288 | }
289 |
290 | void potaverage1() {
291 |
292 | for (int p = 0; p < 15; p++) {
293 |
294 | rotCState = analogRead(rotPin);
295 | midiCState = map(rotCState, 0, 4095, 0, 127);
296 |
297 | total = total - readings[readIndex];
298 | readings[readIndex] = midiCState;
299 | total = total + readings[readIndex];
300 | readIndex = readIndex + 1;
301 |
302 | if (readIndex >= numReadings) {
303 |
304 | readIndex = 0;
305 |
306 | }
307 |
308 | average1 = total / numReadings;
309 | delay(1);
310 |
311 | }
312 | }
313 |
314 | void ROTARY(){
315 |
316 | potaverage1();
317 |
318 | if (average1 != lastaverage1) {
319 |
320 | rotMoving = true;
321 |
322 | }
323 |
324 | else {
325 |
326 | rotMoving = false;
327 |
328 | }
329 |
330 | if (rotMoving == true) {
331 |
332 | midiPacket[2] = Channel_SelectCC;
333 | Serial.println(Channel_SelectCC);
334 |
335 | midiPacket[3] = 0x01;
336 | Serial.println(0x01);
337 |
338 | midiPacket[4] = average1;
339 | Serial.println(average1);
340 |
341 | pCharacteristic->setValue(midiPacket, 5);
342 |
343 | pCharacteristic->notify();
344 |
345 | lastaverage1 = average1;
346 |
347 | }
348 | }
349 |
--------------------------------------------------------------------------------