Skip to content

Commit c06438f

Browse files
author
katspaugh
committed
initial
0 parents  commit c06438f

File tree

14 files changed

+1342
-0
lines changed

14 files changed

+1342
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Arduino software for synthesizer modules

arduino-chords/arduino-chords.ino

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#include <Wire.h>
2+
#include "tables.h"
3+
4+
static const int CLOCK_PIN = 2;
5+
static const int VOCT_PIN = A0;
6+
static const int HOLD_PIN = 11;
7+
static const int LED = 13;
8+
9+
// Analog pins for the potentiometers
10+
const int pot1 = A1; // scale
11+
const int pot2 = A2; // octave
12+
const int pot3 = A3; // key
13+
14+
const byte DAC_address = 0x60;
15+
// 2^12 = 4096 total DAC counts.
16+
// 4096/5 = 819.2 DAC counts per volt on a 5V supply
17+
// 819.2/12 = dac counts per semitone = 68.26
18+
// times 100 for some extra calculation precision = 6826
19+
//static const uint32_t DAC_CAL = 8889;
20+
static const uint32_t DAC_CAL = 6826;
21+
22+
int scale = 0; // scale
23+
int octaveOffset = 0; // octave
24+
int semitoneOffset = 0; // key transposition
25+
int total_arp_beats = 3;
26+
int arp_beat = 0;
27+
int chord_notes[] = { 0, 0, 0, 0, 0 };
28+
bool hold = false;
29+
bool last_hold = false;
30+
bool send_tick = false;
31+
32+
int CV0;
33+
int CV1;
34+
int CV2;
35+
int CV3;
36+
37+
/**
38+
* Quantize a V/oct input into a chord
39+
*/
40+
void setChord(int note) {
41+
int octaveSize;
42+
int notesToShift;
43+
44+
switch (scale) {
45+
case 0:
46+
octaveSize = 12;
47+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
48+
chord_notes[0] = mapChromatic(note, 0);
49+
chord_notes[1] = mapChromatic(note, 4);
50+
chord_notes[2] = mapChromatic(note, 7);
51+
for (int i = 0; i < 3; i++) {
52+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, chromaTable, sizeof(chromaTable));
53+
}
54+
break;
55+
case 1:
56+
octaveSize = 7;
57+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
58+
chord_notes[0] = mapMaj(note, 0);
59+
chord_notes[1] = mapMaj(note, 3);
60+
chord_notes[2] = mapMaj(note, 5);
61+
for (int i = 0; i < 3; i++) {
62+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, majTable, sizeof(majTable));
63+
}
64+
break;
65+
case 2:
66+
octaveSize = 7;
67+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
68+
chord_notes[0] = mapMin(note, 0);
69+
chord_notes[1] = mapMin(note, 3);
70+
chord_notes[2] = mapMin(note, 5);
71+
for (int i = 0; i < 3; i++) {
72+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, minTable, sizeof(minTable));
73+
}
74+
break;
75+
case 3:
76+
octaveSize = 6;
77+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
78+
chord_notes[0] = mapPenta(note, 0);
79+
chord_notes[1] = mapPenta(note, 3);
80+
chord_notes[2] = mapPenta(note, 5);
81+
for (int i = 0; i < 3; i++) {
82+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, pentaTable, sizeof(pentaTable));
83+
}
84+
break;
85+
case 4:
86+
octaveSize = 7;
87+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
88+
chord_notes[0] = mapDorian(note, 0);
89+
chord_notes[1] = mapDorian(note, 3);
90+
chord_notes[2] = mapDorian(note, 5);
91+
for (int i = 0; i < 3; i++) {
92+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, dorianTable, sizeof(dorianTable));
93+
}
94+
break;
95+
case 5:
96+
octaveSize = 4;
97+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
98+
chord_notes[0] = mapMaj3rd(note, 0);
99+
chord_notes[1] = mapMaj3rd(note, 1);
100+
chord_notes[2] = mapMaj3rd(note, 2);
101+
for (int i = 0; i < 3; i++) {
102+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, maj3rdTable, sizeof(maj3rdTable));
103+
}
104+
break;
105+
case 6:
106+
octaveSize = 4;
107+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
108+
chord_notes[0] = mapMin3rd(note, 0);
109+
chord_notes[1] = mapMin3rd(note, 1);
110+
chord_notes[2] = mapMin3rd(note, 2);
111+
for (int i = 0; i < 3; i++) {
112+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, min3rdTable, sizeof(min3rdTable));
113+
}
114+
break;
115+
case 7:
116+
octaveSize = 4;
117+
notesToShift = (octaveOffset * octaveSize) + semitoneOffset;
118+
chord_notes[0] = mapWh(note, 0);
119+
chord_notes[1] = mapWh(note, 3);
120+
chord_notes[2] = mapWh(note, 5);
121+
for (int i = 0; i < 3; i++) {
122+
chord_notes[i] = shiftNotes(chord_notes[i], notesToShift, whTable, sizeof(whTable));
123+
}
124+
break;
125+
}
126+
127+
if (total_arp_beats == 4) {
128+
chord_notes[3] = chord_notes[1];
129+
} else if (total_arp_beats == 5) {
130+
int swap = chord_notes[2];
131+
chord_notes[2] = chord_notes[0];
132+
chord_notes[3] = swap;
133+
chord_notes[4] = chord_notes[1];
134+
}
135+
}
136+
137+
void playNote(int quantizedNote) {
138+
setDAC(quantizedNote);
139+
}
140+
141+
void onClock() {
142+
send_tick = true;
143+
}
144+
145+
void readInputs() {
146+
if (hold) CV0 = analogRead(VOCT_PIN);
147+
CV1 = analogRead(pot1);
148+
CV2 = analogRead(pot2);
149+
CV3 = analogRead(pot3);
150+
151+
scale = map(CV1, 0, 1023, 0, 7);
152+
//octaveOffset = map(CV2, 0, 1023, 0, 3);
153+
semitoneOffset = map(CV2, 0, 1023, 0, 12);
154+
total_arp_beats = map(CV3, 0, 1023, 1, 5);
155+
}
156+
157+
void setDAC(uint8_t key) {
158+
uint32_t DC_Value = 400ul + ((key * DAC_CAL) / 100ul);
159+
160+
Wire.beginTransmission(DAC_address);
161+
Wire.write(byte((DC_Value & 0x0f00) >> 8));
162+
Wire.write(byte(DC_Value & 0xff));
163+
Wire.endTransmission();
164+
}
165+
166+
void setup() {
167+
pinMode(CLOCK_PIN, INPUT);
168+
pinMode(HOLD_PIN, INPUT);
169+
pinMode(LED, OUTPUT);
170+
171+
attachInterrupt(digitalPinToInterrupt(CLOCK_PIN), onClock, RISING);
172+
173+
//Serial.begin(9600);
174+
Wire.begin();
175+
}
176+
177+
void loop() {
178+
if (!send_tick) return;
179+
180+
send_tick = false;
181+
182+
hold = digitalRead(HOLD_PIN) == HIGH;
183+
184+
readInputs();
185+
setChord(CV0);
186+
187+
if (hold != last_hold) {
188+
last_hold = hold;
189+
190+
if (hold) {
191+
// Serial.print(" Scale ");
192+
// Serial.println(scale);
193+
// Serial.print(chord_notes[0]);
194+
// Serial.print(" - ");
195+
// Serial.print(chord_notes[1]);
196+
// Serial.print(" - ");
197+
// Serial.print(chord_notes[2]);
198+
// Serial.println(" ");
199+
200+
digitalWrite(LED, HIGH);
201+
} else {
202+
digitalWrite(LED, LOW);
203+
}
204+
}
205+
206+
playNote(chord_notes[arp_beat]);
207+
208+
arp_beat = (arp_beat + 1) % total_arp_beats;
209+
}

arduino-chords/scales.ino

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*Quantizer
2+
3+
Creative Commons License
4+
5+
Quantizer by Pantala Labs is licensed under a
6+
Creative Commons Attribution 4.0 International License.
7+
Based on a work at https://www.muffwiggler.com/forum/viewtopic.php?t=50137&highlight=
8+
9+
Gibran Curtiss Salomão. MAY/2017 - CC-BY
10+
11+
Original work:
12+
Author : SATINDAS
13+
Code: https://www.muffwiggler.com/forum/viewtopic.php?t=50137&highlight=
14+
*/
15+
int octaveSelect(int input) {
16+
int value = map(input, 0, 1023, -4, 4);
17+
return (value);
18+
}
19+
20+
int semitoneSelect(int input, int semitonesPerOctave) {
21+
int value = map(input, 0, 1023, -(semitonesPerOctave - 1) , semitonesPerOctave - 1);
22+
return (value);
23+
}
24+
25+
int noteSelect(int note, int table[], int tableSize) {
26+
int noteIndex;
27+
for (int i = 0; i < tableSize; i++) {
28+
if (note == table[i]) {
29+
noteIndex = i;
30+
break;
31+
}
32+
}
33+
if (noteIndex > tableSize) {
34+
noteIndex = tableSize;
35+
}
36+
if (noteIndex < 0) {
37+
noteIndex = 0;
38+
}
39+
return(noteIndex);
40+
}
41+
42+
int shiftNotes(int note, int shifts, int table[], int tableSize) {
43+
int noteIndex;
44+
for (int i = 0; i < tableSize; i++) {
45+
if (note == table[i]) {
46+
noteIndex = i + shifts;
47+
break;
48+
}
49+
}
50+
if (noteIndex > tableSize) {
51+
noteIndex = tableSize;
52+
}
53+
if (noteIndex < 0) {
54+
noteIndex = 0;
55+
}
56+
return (table[noteIndex]);
57+
}
58+
59+
60+
int mapMaj(int input, int offset) {
61+
int value = (input / 36) + offset;
62+
return (majTable[value]);
63+
}
64+
65+
int mapMin(int input, int offset) {
66+
int value = (input / 36) + offset;
67+
return (minTable[value]);
68+
}
69+
70+
int mapPenta(int input, int offset) {
71+
int value = (input / 42) + offset;
72+
return (pentaTable[value]);
73+
}
74+
75+
int mapDorian(int input, int offset) {
76+
int value = (input / 36) + offset;
77+
return (dorianTable[value]);
78+
}
79+
80+
int mapMaj3rd(int input, int offset) {
81+
int value = (input / 61) + offset;
82+
return (maj3rdTable[value]);
83+
}
84+
85+
int mapMin3rd(int input, int offset) {
86+
int value = (input / 59) + offset;
87+
return (min3rdTable[value]);
88+
}
89+
90+
int mapWh(int input, int offset) {
91+
int value = (input / 42) + offset;
92+
return (whTable[value]);
93+
}
94+
95+
int mapChromatic(int input, int offset) {
96+
int value = (input / 21) + offset;
97+
return (chromaTable[value]);
98+
}
99+

0 commit comments

Comments
 (0)