#pragma once #include #include BEGIN_CS_NAMESPACE enum relativeCCmode { TWOS_COMPLEMENT, BINARY_OFFSET, SIGN_MAGNITUDE, NEXT_ADDRESS = 4, REAPER_RELATIVE_1 = TWOS_COMPLEMENT, REAPER_RELATIVE_2 = BINARY_OFFSET, REAPER_RELATIVE_3 = SIGN_MAGNITUDE, TRACKTION_RELATIVE = TWOS_COMPLEMENT, MACKIE_CONTROL_RELATIVE = SIGN_MAGNITUDE, KORG_KONTROL_INC_DEC_1 = NEXT_ADDRESS, }; class RelativeCCSender { public: static uint8_t toTwosComplement7bit(int8_t value) { return value & 0x7F; } static uint8_t toBinaryOffset7bit(int8_t value) { return value + 64; } static uint8_t toSignedMagnitude7bit(int8_t value) { uint8_t mask = value >> 7; uint8_t abs = (value + mask) ^ mask; uint8_t sign = mask & 0b01000000; return (abs & 0b00111111) | sign; } static uint8_t mapRelativeCC(int8_t value) { switch (mode) { case TWOS_COMPLEMENT: return toTwosComplement7bit(value); case BINARY_OFFSET: return toBinaryOffset7bit(value); case SIGN_MAGNITUDE: return toSignedMagnitude7bit(value); case NEXT_ADDRESS: return value < 0 ? -value : value; default: return 0; } } static void send(long delta, MIDIAddress address) { if (delta < 0 && mode == NEXT_ADDRESS) address = address + 1; while (delta != 0) { long thisDelta = constrain(delta, -15, 15); uint8_t msgVal = mapRelativeCC(thisDelta); Control_Surface.sendControlChange(address, msgVal); delta -= thisDelta; } } static void setMode(relativeCCmode mode) { RelativeCCSender::mode = mode; } private: static relativeCCmode mode; }; END_CS_NAMESPACE