diff --git a/libavr32 b/libavr32 index 086e5c9..5b05e94 160000 --- a/libavr32 +++ b/libavr32 @@ -1 +1 @@ -Subproject commit 086e5c9d39f25dc53686313da7baaca3d6a0df75 +Subproject commit 5b05e94c906689e02553bcbbf7847545f265faf4 diff --git a/src/ansible_grid.c b/src/ansible_grid.c index 0a7e689..35168e1 100644 --- a/src/ansible_grid.c +++ b/src/ansible_grid.c @@ -432,7 +432,7 @@ void grid_keytimer(void) { // reload factory default, don't immediately save it for (uint8_t i = 0; i < 4; i++) { for (uint8_t j = 0; j < 120; j ++) { - tuning_table[i][j] = ET[j] << 2; + tuning_table[i][j] = ET[j]; } } restore_grid_tuning(); @@ -948,7 +948,8 @@ static void kria_set_note(uint8_t trackNum) { trackNum, (int)cur_scale[noteInScale] + scale_adj[noteInScale] + - (int)((oct[trackNum]+octaveBump) * 12)); + (int)((oct[trackNum]+octaveBump) * 12), + 0); } void clock_kria_track( uint8_t trackNum ) { @@ -2826,6 +2827,15 @@ void handler_KriaKey(s32 data) { view_clock = false; break; case 1: + if (view_tuning) { + view_tuning = false; + view_config = false; + view_clock = false; + restore_grid_tuning(); + resume_kria(); + break; + } + grid_refresh = &refresh_clock; // print_dbg("\r\ntime: "); // print_dbg_ulong(time_fine); @@ -3695,7 +3705,7 @@ void mp_note_on(uint8_t n) { if(mp_clock_count < 1) { mp_clock_count++; note_now[0] = n; - set_cv_note(0, (int)cur_scale[7-n] + scale_adj[7-n]); + set_cv_note(0, (int)cur_scale[7-n] + scale_adj[7-n], 0); set_tr(TR1); } break; @@ -3704,7 +3714,7 @@ void mp_note_on(uint8_t n) { mp_clock_count++; w = get_note_slot(2); note_now[w] = n; - set_cv_note(w, (int)cur_scale[7-n] + scale_adj[7-n]); + set_cv_note(w, (int)cur_scale[7-n] + scale_adj[7-n], 0); set_tr(TR1 + w); } break; @@ -3713,7 +3723,7 @@ void mp_note_on(uint8_t n) { mp_clock_count++; w = get_note_slot(4); note_now[w] = n; - set_cv_note(w, (int)cur_scale[7-n] + scale_adj[7-n]); + set_cv_note(w, (int)cur_scale[7-n] + scale_adj[7-n], 0); set_tr(TR1 + w); } break; @@ -4529,7 +4539,7 @@ static void es_note_on(s8 x, s8 y, u8 from_pattern, u16 timer, u8 voices) { note_index = 0; else if (note_index > 119) note_index = 119; - set_cv_note(note, note_index); + set_cv_note(note, note_index, 0); dac_update_now(); set_tr(TR1 + note); diff --git a/src/ansible_ii_leader.c b/src/ansible_ii_leader.c index 94eb764..deac736 100644 --- a/src/ansible_ii_leader.c +++ b/src/ansible_ii_leader.c @@ -129,10 +129,10 @@ static void ii_mode_jf(i2c_follower_t* follower, uint8_t track, uint8_t mode) { static void ii_octave_jf(i2c_follower_t* follower, uint8_t track, int8_t octave) { int16_t shift; if (octave > 0) { - shift = ET[12*octave] << 2; + shift = ET[12*octave]; } else if (octave < 0) { - shift = -(ET[12*(-octave)] << 2); + shift = -(ET[12*(-octave)]); } else { shift = 0; @@ -225,10 +225,10 @@ static void ii_octave_txo(i2c_follower_t* follower, uint8_t track, int8_t octave } case 1: { // gate / cv if (octave > 0) { - shift = ET[12*octave] << 2; + shift = ET[12*octave]; } else if (octave < 0) { - shift = -(ET[12*(-octave)] << 2); + shift = -ET[12*(-octave)]; } else { shift = 0; @@ -284,7 +284,7 @@ static void ii_cv_txo(i2c_follower_t* follower, uint8_t track, uint16_t dac_valu switch (follower->active_mode) { case 0: { // enveloped oscillator - dac_value = (int)dac_value + (ET[12*(4+follower->oct)] << 2); + dac_value = (int)dac_value + (int)ET[12*(4+follower->oct)]; d[0] = 0x40; // TO_OSC d[1] = track; d[2] = dac_value >> 8; diff --git a/src/ansible_midi.c b/src/ansible_midi.c index 38488f3..9ebf3ae 100644 --- a/src/ansible_midi.c +++ b/src/ansible_midi.c @@ -14,6 +14,8 @@ #include "i2c.h" #include "gpio.h" #include "dac.h" +#include "music.h" +#include "util.h" #include "init_common.h" #include "conf_tc_irq.h" @@ -65,7 +67,7 @@ typedef enum { static void write_midi_standard(void); static void write_midi_arp(void); -static uint16_t pitch_cv(u8 num, s16 offset); +static void midi_pitch(uint8_t n, uint16_t note, int16_t bend); static uint16_t velocity_cv(u8 vel); static uint16_t cc_cv(u8 value); @@ -137,23 +139,6 @@ static void player_note_off(u8 ch, u8 num, u8 vel); //----------------------------- //----- globals -// step = 16384.0 / (10 octave * 12.0 semitones per octave) -// [int(n * step) for n in xrange(0,128)] -const u16 SEMI14[128] = { - 0, 136, 273, 409, 546, 682, 819, 955, 1092, 1228, 1365, 1501, 1638, - 1774, 1911, 2048, 2184, 2321, 2457, 2594, 2730, 2867, 3003, 3140, - 3276, 3413, 3549, 3686, 3822, 3959, 4096, 4232, 4369, 4505, 4642, - 4778, 4915, 5051, 5188, 5324, 5461, 5597, 5734, 5870, 6007, 6144, - 6280, 6417, 6553, 6690, 6826, 6963, 7099, 7236, 7372, 7509, 7645, - 7782, 7918, 8055, 8192, 8328, 8465, 8601, 8738, 8874, 9011, 9147, - 9284, 9420, 9557, 9693, 9830, 9966, 10103, 10240, 10376, 10513, 10649, - 10786, 10922, 11059, 11195, 11332, 11468, 11605, 11741, 11878, 12014, - 12151, 12288, 12424, 12561, 12697, 12834, 12970, 13107, 13243, 13380, - 13516, 13653, 13789, 13926, 14062, 14199, 14336, 14472, 14609, 14745, - 14882, 15018, 15155, 15291, 15428, 15564, 15701, 15837, 15974, 16110, - 16247, 16384, 16520, 16657, 16793, 16930, 17066, 17203, 17339 -}; - // step = 16384.0 / (10 octave * 12.0 semitones per octave) // semi_per_octave = step * 12 // bend_step = semi_per_octave / 512.0 @@ -227,6 +212,7 @@ static arp_player_t player[4]; // shared state static s16 pitch_offset[4]; +static s16 pitch_shift[4]; static midi_clock_t midi_clock; static key_state_t key_state; static clock_source sync_source; @@ -350,9 +336,8 @@ void handler_MidiFrontLong(s32 data) { //////////////////////////////////////////////////////////////////////////////// ///// common cv utilities - -inline static uint16_t pitch_cv(u8 num, s16 offset) { - return SEMI14[num] + offset; +inline static void midi_pitch(uint8_t n, uint16_t note, int16_t bend) { + set_cv_note(n, sclip((int)note + pitch_shift[n], 0, 120), bend); } inline static uint16_t velocity_cv(u8 vel) { @@ -473,6 +458,16 @@ static void set_voice_slew(voicing_mode v, s16 slew) { } } +static int ticks_to_semitones(int16_t shift) { + uint16_t mag = abs(shift); + for (int i = 0; i < 120; i++) { + if (mag <= ET[i]) { + return shift < 0 ? -i : i; + } + } + return 0; +} + static void set_voice_tune(voicing_mode v, s16 shift) { u8 i; @@ -480,18 +475,18 @@ static void set_voice_tune(voicing_mode v, s16 shift) { case eVoicePoly: case eVoiceMulti: for (i = 0; i < 4; i++) { - dac_set_off(i, shift); + pitch_shift[i] = ticks_to_semitones(shift); } break; case eVoiceMono: - dac_set_off(0, shift); // pitch - dac_set_off(1, 0); // velocity - dac_set_off(2, 0); // channel pressure - dac_set_off(3, 0); // mod + pitch_shift[0] = ticks_to_semitones(shift); // pitch + pitch_shift[1] = 0; // velocity + pitch_shift[2] = 0; // channel pressure + pitch_shift[3] = 0; // mod break; default: for (i = 0; i < 4; i++) { - dac_set_off(i, 0); + pitch_shift[i] = 0; } break; } @@ -691,8 +686,7 @@ static void poly_pitch_bend(u8 ch, u16 bend) { for (u8 i = 0; i < voice_state.count; i++) { if (voice_slot_active(&voice_state, i)) { - dac_set_value(i, pitch_cv(voice_slot_num(&voice_state, i), - pitch_offset[0])); + midi_pitch(i, voice_slot_num(&voice_state, i), pitch_offset[0]); } } dac_update_now(); @@ -737,7 +731,7 @@ static void mono_note_on(u8 ch, u8 num, u8 vel) { // keep track of held notes for legato and pitch bend notes_hold(¬es[0], num, vel); - dac_set_value(MONO_PITCH_CV, pitch_cv(num, pitch_offset[0])); + midi_pitch(MONO_PITCH_CV, num, pitch_offset[0]); dac_set_value_noslew(MONO_VELOCITY_CV, velocity_cv(vel)); dac_update_now(); set_tr(TR1); @@ -753,7 +747,7 @@ static void mono_note_off(u8 ch, u8 num, u8 vel) { notes_release(¬es[0], num); prior = notes_get(¬es[0], kNotePriorityLast); if (prior) { - dac_set_value(MONO_PITCH_CV, pitch_cv(prior->num, pitch_offset[0])); + midi_pitch(MONO_PITCH_CV, prior->num, pitch_offset[0]); dac_set_value(MONO_VELOCITY_CV, velocity_cv(prior->vel)); dac_update_now(); } @@ -780,7 +774,7 @@ static void mono_pitch_bend(u8 ch, u16 bend) { // re-set pitch to pick up changed offset const held_note_t *active = notes_get(&(notes[0]), kNotePriorityLast); if (active) { - dac_set_value(MONO_PITCH_CV, pitch_cv(active->num, pitch_offset[0])); + midi_pitch(MONO_PITCH_CV, active->num, pitch_offset[0]); dac_update_now(); } } @@ -921,7 +915,7 @@ static void multi_note_on(u8 ch, u8 num, u8 vel) { return; notes_hold(¬es[ch], num, vel); - dac_set_value(ch, pitch_cv(num, pitch_offset[ch])); + midi_pitch(ch, num, pitch_offset[ch]); dac_update_now(); multi_tr_set(ch); } @@ -937,7 +931,7 @@ static void multi_note_off(u8 ch, u8 num, u8 vel) { if (flags[ch].legato) { prior = notes_get(¬es[ch], kNotePriorityLast); if (prior) { - dac_set_value(ch, pitch_cv(prior->num, pitch_offset[ch])); + midi_pitch(ch, prior->num, pitch_offset[ch]); dac_update_now(); } else { @@ -971,7 +965,7 @@ static void multi_pitch_bend(u8 ch, u16 bend) { // re-set pitch to pick up changed offset const held_note_t *active = notes_get(&(notes[ch]), kNotePriorityLast); if (active) { - dac_set_value(ch, pitch_cv(active->num, pitch_offset[ch])); + midi_pitch(ch, active->num, pitch_offset[ch]); dac_update_now(); } } @@ -1462,10 +1456,10 @@ void ii_midi_arp(uint8_t *d, uint8_t l) { if (v == 0) { for (i = 0; i < 4; i++) - dac_set_off(i, s); + pitch_shift[i] = ticks_to_semitones(s); } else { - dac_set_off(v-1, s); + pitch_shift[v-1] = ticks_to_semitones(s); } break; @@ -1605,7 +1599,7 @@ void restore_midi_arp(void) { arp_player_set_offset(p, arp_state.p[i].offset); arp_player_set_fill(p, arp_state.p[i].fill); - dac_set_off(i, arp_state.p[i].shift); + pitch_shift[i] = ticks_to_semitones(arp_state.p[i].shift); dac_set_slew(i, arp_state.p[i].slew); } @@ -1797,7 +1791,7 @@ static void player_note_on(u8 ch, u8 num, u8 vel) { } */ - dac_set_value(ch, SEMI14[num]); + midi_pitch(ch, num, 0); multi_tr_set(ch); } diff --git a/src/main.c b/src/main.c index 7195bdf..785a92d 100644 --- a/src/main.c +++ b/src/main.c @@ -460,7 +460,7 @@ void flash_read(void) { void default_tuning(void) { for (uint8_t i = 0; i < 4; i++) { for (uint8_t j = 0; j < 120; j++) { - tuning_table[i][j] = ET[j] << 2; + tuning_table[i][j] = ET[j]; } } flashc_memcpy((void *)f.tuning_table, tuning_table, sizeof(tuning_table), true); @@ -476,7 +476,7 @@ void fit_tuning(int mode) { for (uint8_t i = 0; i < 4; i++) { uint16_t offset = tuning_table[i][0]; for (uint8_t j = 0; j < 120; j++) { - tuning_table[i][j] = (ET[j] << 2) + offset; + tuning_table[i][j] = ET[j] + offset; } } break; @@ -549,13 +549,13 @@ uint8_t get_tr(uint8_t n) { return gpio_get_pin_value(n); } -void set_cv_note(uint8_t n, uint16_t note) { - dac_set_value(n, tuning_table[n][note]); +void set_cv_note(uint8_t n, uint16_t note, int16_t bend) { + dac_set_value(n, (int16_t)tuning_table[n][note] + bend); for (uint8_t i = 0; i < I2C_FOLLOWER_COUNT; i++) { bool play_follower = followers[i].active && followers[i].track_en & (1 << n); if (play_follower) { - uint16_t cv_transposed = ET[note] << 2; + uint16_t cv_transposed = (int16_t)ET[note] + bend; followers[i].cv(&followers[i], n, cv_transposed); } } diff --git a/src/main.h b/src/main.h index e62dbe2..34793e5 100644 --- a/src/main.h +++ b/src/main.h @@ -95,7 +95,7 @@ void set_mode(ansible_mode_t m); void update_leds(uint8_t m); void set_tr(uint8_t n); void clr_tr(uint8_t n); -void set_cv_note(uint8_t n, uint16_t cv); +void set_cv_note(uint8_t n, uint16_t cv, int16_t bend); void set_cv_slew(uint8_t n, uint16_t s); void reset_outputs(void); void toggle_follower(uint8_t n);