diff --git a/src/ansible_grid.c b/src/ansible_grid.c index 3e15c18..87546da 100644 --- a/src/ansible_grid.c +++ b/src/ansible_grid.c @@ -279,8 +279,8 @@ void refresh_preset(void) { monomeLedBuffer[followers[follower].oct + 3] = L1; if (followers[follower].mode_ct > 1) { - memset(monomeLedBuffer + 13, L0, followers[follower].mode_ct); - monomeLedBuffer[13 + followers[follower].active_mode] = L1; + memset(monomeLedBuffer + 12, L0, followers[follower].mode_ct); + monomeLedBuffer[12 + followers[follower].active_mode] = L1; } } else { @@ -1641,12 +1641,12 @@ static void preset_mode_handle_key(u8 x, u8 y, u8 z, u8* glyph) { follower_change_octave(&followers[follower], followers[follower].oct); } if (followers[follower].mode_ct > 1 - && x >= 13 - && x <= (13 + followers[follower].mode_ct)) { - follower_change_mode(&followers[follower], x - 13); + && x >= 12 + && x <= (12 + followers[follower].mode_ct)) { + follower_change_mode(&followers[follower], x - 12); } } - if (y >= 2 && y <= 5) { + if (y >= 2 && y <= 6) { if (x == 5) { follower = y - 2; } @@ -1661,7 +1661,7 @@ static void preset_mode_handle_key(u8 x, u8 y, u8 z, u8* glyph) { if (x > 7) { glyph[y] ^= 1<<(x-8); } - if (x == 5 && y >= 2 && y <= 5) { + if (x == 5 && y >= 2 && y <= 6) { if (mod_follower) { follower = y - 2; follower_select = true; diff --git a/src/ansible_ii_leader.c b/src/ansible_ii_leader.c index 681a361..13bf72f 100644 --- a/src/ansible_ii_leader.c +++ b/src/ansible_ii_leader.c @@ -328,9 +328,129 @@ static void ii_slew_txo(i2c_follower_t* follower, uint8_t track, uint16_t slew) } } +static void ii_mode_disting_ex(i2c_follower_t* follower, uint8_t track, uint8_t mode) { + if (mode > follower->mode_ct) return; + follower->active_mode = mode; +} + +static s16 calculate_note(s16 dac_value, s8 octave) { + s32 note = (dac_value * 240) / 16384; + note = note / 2 + (note & 1) + 36 + octave * 12; + return note; +} + +static void ii_tr_disting_ex(i2c_follower_t* follower, uint8_t track, uint8_t state) { + uint8_t d[4] = { 0 }; + s16 note = calculate_note(dac_get_value(track), follower->oct); + + switch (follower->active_mode) { + case 0: // SD Multisample / SD Triggers allocated voices + if (note < 0) note = 0; else if (note > 127) note = 127; + if (state) { + d[0] = 0x56; + d[1] = note; + i2c_leader_tx(follower->addr, d, 2); + d[0] = 0x55; + d[2] = 0x40; + d[3] = 0; + i2c_leader_tx(follower->addr, d, 4); + } else { + d[0] = 0x56; + d[1] = note; + i2c_leader_tx(follower->addr, d, 2); + } + break; + + case 1: // SD Multisample / SD Triggers fixed voices + if (state) { + d[0] = 0x52; + d[1] = track; + d[2] = 0x40; + d[3] = 0; + i2c_leader_tx(follower->addr, d, 4); + } else { + d[0] = 0x53; + d[1] = track; + i2c_leader_tx(follower->addr, d, 2); + } + break; + + case 2: // MIDI channel 1 + if (note < 0 || note > 127) return; + if (state) { + d[0] = 0x4F; + d[1] = 0x90; + d[2] = note; + d[3] = 80; + i2c_leader_tx(follower->addr, d, 4); + } else { + d[0] = 0x4F; + d[1] = 0x80; + d[2] = note; + d[3] = 0; + i2c_leader_tx(follower->addr, d, 4); + } + break; + case 3: // MIDI channels 1-4 + if (note < 0 || note > 127) return; + if (state) { + d[0] = 0x4F; + d[1] = 0x90 + track; + d[2] = note; + d[3] = 80; + i2c_leader_tx(follower->addr, d, 4); + } else { + d[0] = 0x4F; + d[1] = 0x80 + track; + d[2] = note; + d[3] = 0; + i2c_leader_tx(follower->addr, d, 4); + } + break; + default: return; + } +} + +static void ii_mute_disting_ex(i2c_follower_t* follower, uint8_t track, uint8_t mode) { + for (uint8_t i = 0; i < 4; i++) { + ii_tr_disting_ex(follower, i, 0); + } +} + +static void ii_cv_disting_ex(i2c_follower_t* follower, uint8_t track, uint16_t dac_value) { + uint8_t d[4] = { 0 }; + + s16 pitch = dac_value; + s16 note = calculate_note(pitch, follower->oct); + if (note < 0) note = 0; else if (note > 127) note = 127; + + s8 octave = follower->oct * 12; + if (octave > 0) + pitch += ET[octave]; + else + pitch -= ET[-octave]; + + d[2] = pitch >> 8; + d[3] = pitch; + + if (follower->active_mode == 0) { + if (note < 0 || note > 127) return; + d[0] = 0x54; + d[1] = note; + i2c_leader_tx(follower->addr, d, 4); + } else if (follower->active_mode == 1) { + d[0] = 0x51; + d[1] = track; + i2c_leader_tx(follower->addr, d, 4); + } +} + static void ii_u8_nop(i2c_follower_t* follower, uint8_t track, uint8_t state) { } +static void ii_s8_nop(i2c_follower_t* follower, uint8_t track, int8_t state) { +} + static void ii_u16_nop(i2c_follower_t* follower, uint8_t track, uint16_t dac_value) { } @@ -386,6 +506,23 @@ i2c_follower_t followers[I2C_FOLLOWER_COUNT] = { .mode_ct = 1, .active_mode = 1, // always gate/cv }, + { + .addr = DISTING_EX_1, + .active = false, + .track_en = 0xF, + .oct = 0, + + .init = ii_u8_nop, + .mode = ii_mode_disting_ex, + .tr = ii_tr_disting_ex, + .mute = ii_mute_disting_ex, + .cv = ii_cv_disting_ex, + .octave = ii_s8_nop, + .slew = ii_u16_nop, + + .mode_ct = 4, + .active_mode = 0, + }, }; void follower_change_mode(i2c_follower_t* follower, uint8_t param) { diff --git a/src/ansible_ii_leader.h b/src/ansible_ii_leader.h index 52cfef9..715af69 100644 --- a/src/ansible_ii_leader.h +++ b/src/ansible_ii_leader.h @@ -1,6 +1,6 @@ #pragma once -#define I2C_FOLLOWER_COUNT 3 +#define I2C_FOLLOWER_COUNT 4 struct i2c_follower_t;