// Copyright 2009 Brian Rzycki
// brzycki at gmail dot com
// Version 1.1
// This is released to the public domain.  Don't blame me if it breaks your hardware. :)

desc:Automation to MIDI RPN/NRPN

slider1:0<0,15,1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>MIDI Channel
slider2:0<0,2,1{RPN,NRPN}>Type
slider3:0<0,16383,1>Parameter
slider4:0<0,16383,1>Value

@init
val_curr = ceil(slider4);
cc_msg = 176; // 0xB0 or CC messages

@slider
// Bad floats!  You be good little ints like mommy MIDI taught you!
slider3 = ceil(slider3);
slider4 = ceil(slider4);

val_curr != slider4 ? (
    val_curr = slider4;
    run = 1;
);

@block
run ? (
    slider2 == 0 ? (
        // RPN mode
        cc_msb = 101;
        cc_lsb = 100;
    ) : (
        // NRPN mode
        cc_msb = 99;
        cc_lsb = 98;
    );

    num_msb = (slider3  / 128) | 0;
    num_lsb = (slider3  & 127) | 0;
    val_msb = (val_curr / 128) | 0;
    val_lsb = (val_curr & 127) | 0;

    midisend(offset, (cc_msg + slider1), (cc_msb) | (num_msb * 256)); // MSB Address
    midisend(offset, (cc_msg + slider1), (cc_lsb) | (num_lsb * 256)); // LSB Address
    midisend(offset, (cc_msg + slider1),      (6) | (val_msb * 256)); // MSB Data byte
    midisend(offset, (cc_msg + slider1),     (38) | (val_lsb * 256)); // LSB Data byte

    // The website http://www.philrees.co.uk/nrpnq.htm recommends all RPN/NRPN should
    // send the registered RPN (127,127) after sending a data change.  This prevents
    // a device from accidentally accepting a second change to the RPN/NRPN if CC
    // messages 6 or 38 are sent sometime in the future withouth a corresponding
    // address.
    midisend(offset, (cc_msg + slider1), 32613); // (101 | (127 * 256))
    midisend(offset, (cc_msg + slider1), 32612); // (100 | (127 * 256))

    run = 0;
);
