diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index e241a23..af83803 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER_WORKS 1) set(CMAKE_CXX_COMPILER_WORKS 1) -project("untitled" C CXX) +project("firmware" C CXX) include(CMakeListsPrivate.txt) diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp index d26b288..586db1e 100644 --- a/firmware/src/main.cpp +++ b/firmware/src/main.cpp @@ -1,6 +1,7 @@ #include #include #include +//#include #define u8 uint8_t #define u16 uint16_t @@ -8,6 +9,8 @@ #define u64 uint64_t #define timeMillis() std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() #define min(a, b) ((a) < (b) ? (a) : (b)) +#define let auto +#define val const auto u64 start_time = 0; @@ -18,7 +21,7 @@ typedef struct note { // 61 Notes from C2 to C7 -const int NUM_NOTES = 61; +val NUM_NOTES = 61; const Note notes[] = { {"C2", 36}, {"C#2", 37}, {"D2", 38}, {"D#2", 39}, {"E2", 40}, {"F2", 41}, {"F#2", 42}, {"G2", 43}, {"G#2", 44}, {"A2", 45}, {"A#2", 46}, {"B2", 47}, {"C3", 48}, {"C#3", 49}, {"D3", 50}, {"D#3", 51}, {"E3", 52}, {"F3", 53}, {"F#3", 54}, {"G3", 55}, {"G#3", 56}, {"A3", 57}, {"A#3", 58}, {"B3", 59}, @@ -28,35 +31,49 @@ const Note notes[] = { {"C7", 96} }; -// 4 Multiplexers: GPIO pins for each analog multiplexer that handles 16 sensors -// Notes are connected in order: Mux #1 (0-15), Mux #2 (16-31), Mux #3 (32-47), Mux #4 (48-61) -const int NUM_MUX = 5; -const int PINS_PER_MUX = 12; -const int mux_in[] = {34, 34, 35, 34, 34}; // Analog signal input +// LED pins +val PIN_LED = 8; +let led_state = true; + +// 5 Multiplexers: GPIO pins for each analog multiplexer that handles 12 sensors (1 octave) +// Notes are connected in order: Mux #1 (0-11), Mux #2 (12-23), Mux #3 (24-35), Mux #4 (36-47), Mux #5 (48-59) +val NUM_MUX = 5; +val PINS_PER_MUX = 12; +//const adc1_channel_t mux_in[] = {ADC1_CHANNEL_0, ADC1_CHANNEL_1, ADC1_CHANNEL_2, ADC1_CHANNEL_3, ADC1_CHANNEL_4}; +const int mux_in[] = {A0, A1, A2, A3, A4}; + // Select pins for every multiplexer, each multiplexer has 4 select pins, all sel0 are connected to 14, etc. -const int NUM_MUX_SEL = 4; -const int mux_sel[4] = {14, 27, 16, 17}; +val NUM_MUX_SEL = 4; +const int mux_sel[] = {40, 38, 36, 34}; + +// Multisampling: Take multiple samples for each sensor and average them +val MULTISAMPLING = 1; int lasts[NUM_NOTES]; // variable to store the value coming from the sensor u64 last_hit_times[NUM_NOTES]; -int max_sensor = 4096; -int max_threshold = 2000; -int active_threshold = 100; // Minimum value to be considered as a hit +val max_sensor = 4096; +val max_threshold = 2000; +val active_threshold = 100; // Minimum value to be considered as a hit void setup() { + // Turn on LED + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, led_state); + // Initialize pin and serial for (int pin: mux_in) pinMode(pin, INPUT); - for (int pin: mux_sel) pinMode(pin, OUTPUT); +// adc1_config_width(ADC_WIDTH_MAX); +// for (val pin : mux_in) { +//// adcAttachPin(pin); +// adc1_config_channel_atten(pin, ADC_ATTEN_DB_11); +// } + for (val pin: mux_sel) pinMode(pin, OUTPUT); Serial.begin(9600); - Serial.printf("Initialized\r\n"); + Serial.println("Initialized"); - // Testing pin - pinMode(2, OUTPUT); - analogWrite(2, 255); - - start_time = timeMillis(); +// start_time = timeMillis(); } /** @@ -79,7 +96,7 @@ void on_sensor_update(int id, u64 time, int last, int current) // The last value is a local maximum, // and we read it as the hit strength of our note. Send midi command to the host. // /hit - Serial.printf("/hit %d %d\r\n", notes[id].midi, + printf("/hit %d %d\r\n", notes[id].midi, min((last - active_threshold) * 127 / (max_threshold - active_threshold), 127)); // Update last hit time @@ -87,39 +104,66 @@ void on_sensor_update(int id, u64 time, int last, int current) } } +/** + * Read sensor value with multisampling + * + * @param pin Sensor pin + * @return Sensor value + */ +int read_sensor(int pin) +{ + let sum = 0; + for (let i = 0; i < MULTISAMPLING; i++) { + sum += analogRead(pin); + } + return (int) round(((float) sum) / ((float) MULTISAMPLING)); +} + void loop() { - u64 time = timeMillis(); - u64 elapsed = time - start_time; +// u64 time = timeMillis(); +// u64 elapsed = time - start_time; + + // Toggle LED + led_state = !led_state; + digitalWrite(PIN_LED, led_state); + +// // Loop through each multiplexer input + for (val mux : mux_in) + { + val v = read_sensor(mux); + printf("%d ", v); + } + Serial.println(); // Serial.printf("%" PRIu64 "=============\r\n", elapsed); // Loop through each multiplexer state - for (int i = 0; i < PINS_PER_MUX; i++) - { - // Set select pins - for (int j = 0; j < NUM_MUX_SEL; j++) - { - // i >> j is the jth bit of i - digitalWrite(mux_sel[j], (i >> j) & 1); - } - - // Read four input pins from the multiplexer - for (int j = 0; j < NUM_MUX; j++) - { - int note_id = j * PINS_PER_MUX + i; - if (note_id >= NUM_NOTES) break; - - // Read the analog input - int v = analogRead(mux_in[j]); - if (v != lasts[note_id]) - { - // Serial prints are really slow, so don't use them in debug mode - Serial.printf("%s %d\r\n", notes[note_id].name, v); - on_sensor_update(note_id, time, lasts[note_id], v); - } - lasts[note_id] = v; - } - } +// for (int i = 0; i < PINS_PER_MUX; i++) +// { +// // Set select pins +// for (int j = 0; j < NUM_MUX_SEL; j++) +// { +// // i >> j is the jth bit of i +// digitalWrite(mux_sel[j], (i >> j) & 1); +// } +// +// // Read four input pins from the multiplexer +// for (int j = 0; j < NUM_MUX; j++) +// { +// int note_id = j * PINS_PER_MUX + i; +// if (note_id >= NUM_NOTES) break; +// +// // Read the analog input +// int v = read_sensor(mux_in[j]); +// if (v != lasts[note_id]) +// { +// // Serial prints are really slow, so don't use them in debug mode +// Serial.printf("%s %d\r\n", notes[note_id].name, v); +// on_sensor_update(note_id, time, lasts[note_id], v); +// } +// lasts[note_id] = v; +// } +// } // Serial.printf("Loop %" PRIu64 "\r\n", elapsed); } \ No newline at end of file diff --git a/models/Exports/frame_1.stl b/models/Exports/frame_1.stl new file mode 100644 index 0000000..e25ccf5 Binary files /dev/null and b/models/Exports/frame_1.stl differ diff --git a/models/Exports/frame_2.stl b/models/Exports/frame_2.stl new file mode 100644 index 0000000..4c4448e Binary files /dev/null and b/models/Exports/frame_2.stl differ diff --git a/models/Exports/gap.stl b/models/Exports/gap.stl new file mode 100644 index 0000000..03a54a1 Binary files /dev/null and b/models/Exports/gap.stl differ diff --git a/models/v4-filled.FCStd b/models/v4-filled.FCStd index b637dda..6a2d0d7 100644 Binary files a/models/v4-filled.FCStd and b/models/v4-filled.FCStd differ diff --git a/models/v4-frame.FCStd b/models/v4-frame.FCStd new file mode 100644 index 0000000..1c841be Binary files /dev/null and b/models/v4-frame.FCStd differ diff --git a/src/main.rs b/src/main.rs index 8053442..9ab3c24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ fn start() -> Result<()> { let midi_out = MidiOutput::new("MIDI Output")?; let mut conn_out = midi_out.create_virtual("Virtual MIDI Output").unwrap(); - let serial_port = serialport::new("/dev/cu.usbserial-142140", 9600) + let serial_port = serialport::new("/dev/cu.usbmodem14101", 9600) .timeout(std::time::Duration::from_millis(10)) .open()?; let mut reader = BufReader::new(serial_port);