diff --git a/amp.cpp b/amp.cpp new file mode 100644 index 0000000..f996fb9 --- /dev/null +++ b/amp.cpp @@ -0,0 +1,99 @@ + +#include "amp.h" +#include "mustang.h" + +int +AmpCC::cc69( int value ) { + return amp->control_common1( 0x01, 0x0c, value ); +} + +int +AmpCC::cc70( int value ) { + return amp->control_common1( 0x00, 0x0c, value ); +} + +int +AmpCC::cc71( int value ) { + return amp->control_common1( 0x04, 0x0c, value ); +} + +int +AmpCC::cc72( int value ) { + return amp->control_common1( 0x05, 0x0c, value ); +} + +int +AmpCC::cc73( int value ) { + return amp->control_common1( 0x06, 0x0c, value ); +} + +int +AmpCC::cc74( int value ) { + if ( value > 2 ) return 0; + return amp->control_common2( 0x13, 0x8f, value ); +} + +int +AmpCC::cc75( int value ) { + return amp->control_common1( 0x0a, 0x0d, value ); +} + +int +AmpCC::cc76( int value ) { + if ( value > 4 ) return 0; + return amp->control_common2( 0x0f, 0x90, value ); +} + +int +AmpCC::cc77( int value ) { + if ( value < 1 || value > 12 ) return 0; + return amp->control_common2( 0x11, 0x8e, value ); +} + + + +int +AmpCC1::cc78( int value ) { + return amp->control_common1( 0x07, 0x0c, value ); +} + +int +AmpCC1::cc79( int value ) { + return amp->control_common1( 0x02, 0x0c, value ); +} + + + +int +AmpCC2::cc78( int value ) { + return amp->control_common1( 0x02, 0x0c, value ); +} + +int +AmpCC2::cc79( int value ) { + return amp->control_common1( 0x03, 0x0c, value ); +} + + + +int +AmpCC3::cc78( int value ) { + return amp->control_common1( 0x07, 0x0c, value ); +} + +int +AmpCC3::cc79( int value ) { + return amp->control_common1( 0x03, 0x0c, value ); +} + + + +int +AmpCC4::cc78( int value ) { + return amp->control_common1( 0x07, 0x0c, value ); +} + +int +AmpCC4::cc79( int value ) { + return amp->control_common1( 0x03, 0x0c, value ); +} diff --git a/amp.h b/amp.h new file mode 100644 index 0000000..473113a --- /dev/null +++ b/amp.h @@ -0,0 +1,109 @@ +// -*-c++-*- + +#ifndef _AMPCC_H +#define _AMPCC_H + +class Mustang; + +// F57 Deluxe +// F57 Champ +// F65 Deluxe +// F65 Princeton +// F65 Twin +// +class AmpCC { + +protected: + + Mustang * amp; + +public: + + AmpCC( Mustang * theAmp ) : amp(theAmp) {} + + // Gain + int cc69( int value ); + // Ch. Volume + int cc70( int value ); + // Treble + int cc71( int value ); + // Mid + int cc72( int value ); + // Bass + int cc73( int value ); + // Sag + virtual int cc74( int value ); + // Bias + virtual int cc75( int value ); + // Noise Gate + int cc76( int value ); + // Cabinet + int cc77( int value ); + + // Dummy in base class + virtual int cc78( int value ) { return 0;} + virtual int cc79( int value ) { return 0;} +}; + + +// F59 Bassman +// British 70s +// +class AmpCC1 : public AmpCC { +public: + AmpCC1( Mustang * theAmp ) : AmpCC(theAmp) {} + // Presence + virtual int cc78( int value ); + // Blend + virtual int cc79( int value ); +}; + + +// Fender Supersonic +// +class AmpCC2 : public AmpCC { +public: + AmpCC2( Mustang * theAmp ) : AmpCC(theAmp) {} + // Gain2 + virtual int cc78( int value ); + // Master Volume + virtual int cc79( int value ); +}; + + +// British 60s +// +class AmpCC3 : public AmpCC { +public: + AmpCC3( Mustang * theAmp ) : AmpCC(theAmp) {} + // Cut + virtual int cc78( int value ); + // Master Volume + virtual int cc79( int value ); +}; + + +// British 80s +// American 90s +// Metal 2000 +// +class AmpCC4 : public AmpCC { +public: + AmpCC4( Mustang * theAmp ) : AmpCC(theAmp) {} + // Presence + virtual int cc78( int value ); + // Master Volume + virtual int cc79( int value ); +}; + + +// Studio Preamp +// +class AmpCC5 : public AmpCC { +public: + AmpCC5( Mustang * theAmp ) : AmpCC(theAmp) {} + virtual int cc78( int value ) { return 0;} + virtual int cc79( int value ) { return 0;} +}; + +#endif diff --git a/amp_defaults.h b/amp_defaults.h new file mode 100644 index 0000000..ee1e995 --- /dev/null +++ b/amp_defaults.h @@ -0,0 +1,88 @@ +// Default settings for Mustang III (original) amp models +// +// This header is auto-generated from decoded pcap capture. + +static unsigned char f57_deluxe[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x99, 0x80, 0x80, 0xbe, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f59_bassman[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xa2, 0x80, 0x80, 0x80, 0x7a, 0xa2, 0x91, 0x80, 0x80, 0x80, 0x80, 0x02, 0x02, 0x02, 0x00, + 0x00, 0x02, 0x02, 0x01, 0x00, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f57_champ[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xb3, 0x00, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0c, 0x0c, 0x0c, 0x00, + 0x00, 0x05, 0x0c, 0x01, 0x00, 0x01, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f65_deluxe[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x71, 0x00, 0xff, 0x91, 0xcf, 0x38, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x03, 0x03, 0x00, + 0x00, 0x03, 0x03, 0x01, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f65_princeton[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x55, 0x00, 0xff, 0x99, 0xcc, 0x4c, 0x80, 0x80, 0x80, 0x80, 0x80, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x01, 0x00, 0x01, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f65_twin[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x55, 0x80, 0x63, 0xb3, 0xbb, 0xaa, 0x80, 0x80, 0x80, 0x80, 0x80, 0x05, 0x05, 0x05, 0x00, + 0x00, 0x09, 0x05, 0x01, 0x00, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char f_supersonic[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xbb, 0x82, 0x55, 0x99, 0xa2, 0x99, 0x80, 0x80, 0x80, 0x80, 0x80, 0x06, 0x06, 0x06, 0x02, + 0x00, 0x0c, 0x06, 0x01, 0x00, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char brit_60[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xa2, 0x80, 0x63, 0x99, 0x80, 0xb0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x07, 0x07, 0x07, 0x00, + 0x00, 0x07, 0x07, 0x01, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char brit_70[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xff, 0x80, 0x7d, 0xaa, 0x5b, 0xc4, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x0b, 0x0b, 0x01, + 0x00, 0x08, 0x0b, 0x01, 0x00, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char brit_80[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xff, 0x80, 0x7d, 0xaa, 0x5b, 0xc4, 0x80, 0x80, 0x80, 0x80, 0x80, 0x09, 0x09, 0x09, 0x01, + 0x00, 0x06, 0x09, 0x01, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char us_90[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x8e, 0x80, 0x66, 0xa4, 0x19, 0xc7, 0x71, 0x80, 0x80, 0x80, 0x80, 0x0a, 0x0a, 0x0a, 0x03, + 0x00, 0x0a, 0x0a, 0x01, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char metal_2k[] = { + 0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xa4, 0x80, 0x55, 0x99, 0x4c, 0x91, 0x8e, 0x80, 0x80, 0x80, 0x80, 0x08, 0x08, 0x08, 0x02, + 0x00, 0x08, 0x08, 0x01, 0x00, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + diff --git a/doc/fender_mustang_protocol.txt b/doc/fender_mustang_protocol.txt index 2fdd454..aea8b60 100644 --- a/doc/fender_mustang_protocol.txt +++ b/doc/fender_mustang_protocol.txt @@ -631,7 +631,7 @@ Toggling effect on/off: 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -00 | 19| c3|DSP| st|slt| 00 | +00 | 19| c3|fam| st|slt| 00 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 16 | 00 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ @@ -640,7 +640,7 @@ Toggling effect on/off: 48 | 00 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -DSP - can be either 6, 7, 8 or 9; depends on effect familly +fam - (3 = stomp, 4 = mod, 5 = delay, 6 = reverb) st - status (on = 00, off = 01) slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 @@ -659,7 +659,7 @@ slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 48 | ? | ? | ? | ? | ? | 00 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -DSP - can be either 6, 7, 8 or 9; depends on effect familly +efx_family - (3 = stomp, 4 = mod, 5 = delay, 6 = reverb) fxm - effect model; independent for each effect slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 diff --git a/magic.h b/magic.h new file mode 100644 index 0000000..c922063 --- /dev/null +++ b/magic.h @@ -0,0 +1,38 @@ +// Magic values for direct conditioning of Mustang analog controls +// + +#ifndef _MAGIC_H +#define _MAGIC_H + +unsigned short magic_values[] = { + 0x0000, 0x013b, 0x02ef, 0x036a, 0x04a4, 0x0659, 0x06d4, 0x080e, 0x0a3d, 0x0b78, + 0x0bf2, 0x0d2d, 0x0da7, 0x0ee2, 0x0f5c, 0x1111, 0x124c, 0x12c6, 0x1400, 0x147b, + 0x1630, 0x176a, 0x17e5, 0x191f, 0x1999, 0x1ad4, 0x1b4e, 0x1c89, 0x1d03, 0x1e3e, + 0x1eb8, 0x1ff3, 0x206d, 0x21a8, 0x2222, 0x235d, 0x23d7, 0x2511, 0x258c, 0x26c6, + 0x2741, 0x287b, 0x28f6, 0x2a30, 0x2aaa, 0x2be5, 0x2c5f, 0x2d9a, 0x2e14, 0x2f4f, + 0x2fc9, 0x3104, 0x317e, 0x32b9, 0x3333, 0x346e, 0x34e8, 0x3622, 0x369d, 0x37d7, + 0x3852, 0x398c, 0x3a07, 0x3b41, 0x3bbb, 0x3cf6, 0x3d70, 0x3eab, 0x3f25, 0x4060, + 0x40da, 0x4215, 0x428f, 0x43ca, 0x4444, 0x457f, 0x45f9, 0x4733, 0x47ae, 0x48e8, + 0x4963, 0x4a9d, 0x4b18, 0x4c52, 0x4ccc, 0x4e07, 0x4e81, 0x4fbc, 0x5036, 0x5171, + 0x51eb, 0x5326, 0x53a0, 0x54db, 0x5555, 0x5690, 0x570a, 0x5844, 0x58bf, 0x59f9, + 0x5a74, 0x5bae, 0x5c29, 0x5d63, 0x5dde, 0x5f18, 0x5f92, 0x60cd, 0x6282, 0x62fc, + 0x6437, 0x64b1, 0x65ec, 0x6666, 0x67a1, 0x681b, 0x6955, 0x69d0, 0x6b0a, 0x6b85, + 0x6cbf, 0x6d3a, 0x6e74, 0x6eef, 0x7029, 0x70a3, 0x71de, 0x7258, 0x7393, 0x740d, + 0x7548, 0x75c2, 0x76fd, 0x7777, 0x78b2, 0x792c, 0x7a66, 0x7ae1, 0x7c1b, 0x7c96, + 0x7dd0, 0x7e4b, 0x7f85, 0x8000, 0x813a, 0x81b4, 0x82ef, 0x8369, 0x84a4, 0x851e, + 0x8659, 0x86d3, 0x880e, 0x8888, 0x89c3, 0x8a3d, 0x8bf2, 0x8d2c, 0x8da7, 0x8ee1, + 0x9096, 0x9111, 0x924b, 0x92c5, 0x947a, 0x962f, 0x97e4, 0x9b4e, 0x9d03, 0x9eb8, + 0xa06d, 0xa222, 0xa3d6, 0xa58b, 0xa740, 0xa8f5, 0xaaaa, 0xac5f, 0xafc9, 0xb17e, + 0xb333, 0xb4e7, 0xb851, 0xba06, 0xbbbb, 0xbd70, 0xbf25, 0xc0da, 0xc28f, 0xc444, + 0xc5f8, 0xc962, 0xcb17, 0xcccc, 0xce81, 0xd036, 0xd1eb, 0xd3a0, 0xd555, 0xd709, + 0xd8be, 0xda73, 0xdc28, 0xdddd, 0xdf92, 0xe147, 0xe2fc, 0xe4b1, 0xe666, 0xe81a, + 0xe9cf, 0xeb84, 0xf0a3, 0xf258, 0xf5c2, 0xf92b, 0xfae0, 0xfe4a, 0xffff +}; + +// Max index in array +unsigned magic_max = 218; + +// Scale MIDI CC value to array index +double magic_scale_factor = 1.711; + +#endif diff --git a/mustang.cpp b/mustang.cpp index 5f0d1c6..8758014 100644 --- a/mustang.cpp +++ b/mustang.cpp @@ -1,9 +1,14 @@ #include "mustang.h" #include +#include + +#include "magic.h" +#include "amp_defaults.h" Mustang::Mustang() { amp_hand = NULL; + curr_amp = NULL; // "apply efect" command memset(execute, 0x00, LENGTH); @@ -26,7 +31,7 @@ Mustang::~Mustang() this->stop_amp(); } -int Mustang::start_amp(char list[][32], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) +int Mustang::start_amp(void) { int ret, received; unsigned char array[LENGTH]; @@ -84,37 +89,44 @@ int Mustang::start_amp(char list[][32], char *name, struct amp_settings *amp_set memset(array, 0x00, LENGTH); array[0] = 0x1a; - array[1] = 0x03; + + // This seems model specific + // Perhaps for Mustang II? + // array[1] = 0x03; + + // Correct value for Mustang III + array[1] = 0xc1; + libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - if(list != NULL || name != NULL || amp_set != NULL || effects_set != NULL) + int i = 0, j = 0; + + memset(array, 0x00, LENGTH); + array[0] = 0xff; + array[1] = 0xc1; + + // Request parameter dump from amplifier + libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + + for(i = 0; received; i++) { - int i = 0, j = 0; - memset(array, 0x00, LENGTH); - array[0] = 0xff; - array[1] = 0xc1; - libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - - for(i = 0; received; i++) - { - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - memcpy(received_data[i], array, LENGTH); - } - - int max_to_receive; - i > 143 ? max_to_receive = 200 : max_to_receive = 48; - if(list != NULL) - for(i = 0, j = 0; i 143 ? max_to_receive = 200 : max_to_receive = 48; + + // List of preset names + for(i = 0, j = 0; i 0 ? 0 : 1; + array[FXSLOT] = curr_state[state_index][FXSLOT]; +#if 0 + for ( int i=0; i<15; i++ ) fprintf( stderr, "%02x ", array[i] ); + fprintf( stderr, "\n" ); +#endif + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + // flush reply data + for (int i=0; received; i++) { + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + } + + return ret; +} + +int Mustang::control_common1(int parm, int bucket, int value) +{ + static unsigned short previous = 0; + + int ret, received; + unsigned char array[LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x05; + array[1] = 0xc3; + array[2] = 0x02; + array[3] = curr_state[AMP_STATE][AMPLIFIER]; + // target parameter + array[5] = array[6] = parm; + // bucket + array[7] = bucket; + + // Scale and clamp to valid index range + int index = (int) ceil( (double)value * magic_scale_factor ); + if ( index > magic_max ) index = magic_max; + + unsigned short eff_value = magic_values[index]; + + // Try to prevent extra traffic if successive calls resolve to the same + // slot. + if (eff_value == previous) return 0; + previous = eff_value; + + array[9] = eff_value & 0xff; + array[10] = (eff_value >> 8) & 0xff; + + // Send command and flush reply + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + return ret; +} + + +int Mustang::control_common2(int parm, int bucket, int value) +{ + int ret, received; + unsigned char array[LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x05; + array[1] = 0xc3; + array[2] = 0x02; + array[3] = curr_state[AMP_STATE][AMPLIFIER]; + // target parameter + array[5] = array[6] = parm; + // bucket + array[7] = bucket; + // value + array[9] = value; + + // Send command and flush reply + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + return ret; +} + +int Mustang::setAmp( int ord ) { + int ret, received; + unsigned char scratch[LENGTH]; + + unsigned char *array; + + switch (ord) { + case 1: + array = f57_deluxe; + break; + case 2: + array = f59_bassman; + break; + case 3: + array = f57_champ; + break; + case 4: + array = f65_deluxe; + break; + case 5: + array = f65_princeton; + break; + case 6: + array = f65_twin; + break; + case 7: + array = f_supersonic; + break; + case 8: + array = brit_60; + break; + case 9: + array = brit_70; + break; + case 10: + array = brit_80; + break; + case 11: + array = us_90; + break; + case 12: + array = metal_2k; + break; + default: + fprintf( stderr, "W - Amp select %d not yet supported\n", ord ); + return 0; + } + + // Setup amp personality + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT); + + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT); + + // Copy to current setting store + memcpy(curr_state[AMP_STATE], array, LENGTH); + updateAmp(); + + // Setup USB gain + memset(scratch, 0x00, LENGTH); + scratch[0] = 0x1c; + scratch[1] = 0x03; + scratch[2] = 0x0d; + scratch[6] = 0x01; + scratch[7] = 0x01; + scratch[16] = 0x80; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, scratch, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT); + + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT); + + return ret; +} + +int Mustang::save_on_amp(char *name, int slot) +{ + int ret, received; + unsigned char array[LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x1c; + array[1] = 0x01; + array[2] = 0x03; + array[SAVE_SLOT] = slot; + array[6] = 0x01; + array[7] = 0x01; + + if(strlen(name) > 31) + name[31] = 0x00; + + for(unsigned int i = 16, j = 0; name[j] != 0x00; i++,j++) + array[i] = name[j]; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + load_memory_bank(slot); + + return ret; +} + +int Mustang::load_memory_bank( int slot ) +{ + int ret, received; + unsigned char array[LENGTH], data[7][LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x1c; + array[1] = 0x01; + array[2] = 0x01; + array[SAVE_SLOT] = slot; + array[6] = 0x01; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + + for(int i = 0; received; i++) { + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + if(i < 7) + memcpy(curr_state[i], array, LENGTH); + } + updateAmp(); + + return ret; +} + int Mustang::set_effect(struct fx_pedal_settings value) { int ret, received; // variables used when sending @@ -187,8 +464,7 @@ int Mustang::set_effect(struct fx_pedal_settings value) libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); - //DEBUG -// qDebug("set: DSP: %d, slot: %d, effect: %d, EMPTY", array[DSP], array[FXSLOT], array[EFFECT]); + if(value.effect_num == EMPTY) return ret; @@ -465,645 +741,16 @@ int Mustang::set_effect(struct fx_pedal_settings value) // send packet to the amp ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); - //DEBUG -// qDebug("set: DSP: %d, slot: %d, effect: %d", array[DSP], array[FXSLOT], array[EFFECT]); // save current settings memcpy(prev_array[array[DSP]-6], array, LENGTH); - - //DEBUG -// FILE *f; -// static char trynum=0; -// char mes[16]; -// sprintf(mes, "test%d.bin",trynum); -// f=fopen(mes,"w"); -// fwrite(array, sizeof(array), 1, f); -// //fwrite(execute, sizeof(execute), 1, f); -// fclose(f); -// trynum++; - - return ret; } -int Mustang::effect_toggle(int category, int state) -{ - int ret, received; - unsigned char array[LENGTH]; - - memset(array, 0x00, LENGTH); - array[0] = 0x19; - array[1] = 0xc3; - // Translate DSP to internal effect category - array[2] = prev_array[category][DSP] - 3; - array[3] = state; - array[FXSLOT] = prev_array[category][FXSLOT]; - - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - // flush reply data - for (int i=0; received; i++) { - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - } - - return ret; -} - - -int Mustang::set_amplifier(struct amp_settings value) -{ - int ret, received; - unsigned char array[LENGTH] = { - 0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xaa, 0xa2, 0x80, 0x63, 0x99, 0x80, 0xb0, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x07, 0x07, 0x07, 0x05, - 0x00, 0x07, 0x07, 0x01, 0x00, 0x01, 0x5e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - array[DSP] = 0x05; - array[GAIN] = value.gain; - array[VOLUME] = value.volume; - array[TREBLE] = value.treble; - array[MIDDLE] = value.middle; - array[BASS] = value.bass; - - if(value.cabinet > 0x0c) - array[CABINET] = 0x00; - else - array[CABINET] = value.cabinet; - - if(value.noise_gate > 0x05) - array[NOISE_GATE] = 0x00; - else - array[NOISE_GATE] = value.noise_gate; - - array[MASTER_VOL] = value.master_vol; - array[GAIN2] = value.gain2; - array[PRESENCE] = value.presence; - - if(value.noise_gate == 0x05) - { - if(value.threshold > 0x09) - array[THRESHOLD] = 0x00; - else - array[THRESHOLD] = value.threshold; - - array[DEPTH] = value.depth; - } - array[BIAS] = value.bias; - - if(value.sag > 0x02) - array[SAG] = 0x01; - else - array[SAG] = value.sag; - - array[BRIGHTNESS] = value.brightness?1:0; - - switch (value.amp_num) - { - case STUDIO_PREAMP: - array[AMPLIFIER] = 0xf1; - array[44] = array[45] = array[46] = 0x0d; - array[50] = 0x0d; - array[54] = 0xf6; - break; - - case FENDER_57_CHAMP: - array[AMPLIFIER] = 0x7c; - array[44] = array[45] = array[46] = 0x0c; - array[50] = 0x0c; - array[54] = 0x00; - break; - - case FENDER_57_DELUXE: - array[AMPLIFIER] = 0x67; - array[44] = array[45] = array[46] = 0x01; - array[50] = 0x01; - array[54] = 0x53; - break; - - case FENDER_57_TWIN: - array[AMPLIFIER] = 0xf6; - array[44] = array[45] = array[46] = 0x0e; - array[50] = 0x0e; - array[54] = 0xf9; - break; - - case FENDER_59_BASSMAN: - array[AMPLIFIER] = 0x64; - array[44] = array[45] = array[46] = 0x02; - array[50] = 0x02; - array[54] = 0x67; - break; - - case FENDER_65_PRINCETON: - array[AMPLIFIER] = 0x6a; - array[44] = array[45] = array[46] = 0x04; - array[50] = 0x04; - array[54] = 0x61; - break; - - case FENDER_65_DELUXE_REVERB: - array[AMPLIFIER] = 0x53; - array[40] = array[43] = 0x00; - array[44] = array[45] = array[46] = 0x03; - array[50] = 0x03; - array[54] = 0x6a; - break; - - case FENDER_65_TWIN_REVERB: - array[AMPLIFIER] = 0x75; - array[44] = array[45] = array[46] = 0x05; - array[50] = 0x05; - array[54] = 0x72; - break; - - case S60S_THRIFT: - array[AMPLIFIER] = 0xf9; - array[44] = array[45] = array[46] = 0x0f; - array[50] = 0x0f; - array[54] = 0xfc; - break; - - case BRITISH_WATTS: - array[AMPLIFIER] = 0xff; - array[44] = array[45] = array[46] = 0x11; - array[50] = 0x11; - array[54] = 0x00; - break; - - case BRITISH_60S: - array[AMPLIFIER] = 0x61; - array[44] = array[45] = array[46] = 0x07; - array[50] = 0x07; - array[54] = 0x5e; - break; - - case BRITISH_70S: - array[AMPLIFIER] = 0x79; - array[44] = array[45] = array[46] = 0x0b; - array[50] = 0x0b; - array[54] = 0x7c; - break; - - case BRITISH_80S: - array[AMPLIFIER] = 0x5e; - array[44] = array[45] = array[46] = 0x09; - array[50] = 0x09; - array[54] = 0x5d; - break; - case BRITISH_COLOUR: - array[AMPLIFIER] = 0xfc; - array[44] = array[45] = array[46] = 0x10; - array[50] = 0x10; - array[54] = 0xff; - break; - - case FENDER_SUPER_SONIC: - array[AMPLIFIER] = 0x72; - array[44] = array[45] = array[46] = 0x06; - array[50] = 0x06; - array[54] = 0x79; - break; - - case AMERICAN_90S: - array[AMPLIFIER] = 0x5d; - array[44] = array[45] = array[46] = 0x0a; - array[50] = 0x0a; - array[54] = 0x6d; - break; - - case METAL_2000: - array[AMPLIFIER] = 0x6d; - array[44] = array[45] = array[46] = 0x08; - array[50] = 0x08; - array[54] = 0x75; - break; - - - } - - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - - memset(array, 0x00, LENGTH); - array[0] = 0x1c; - array[1] = 0x03; - array[2] = 0x0d; - array[6] = 0x01; - array[7] = 0x01; - array[16] = value.usb_gain; - - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - - return ret; -} - -int Mustang::save_on_amp(char *name, int slot) -{ - int ret, received; - unsigned char array[LENGTH]; - - memset(array, 0x00, LENGTH); - array[0] = 0x1c; - array[1] = 0x01; - array[2] = 0x03; - array[SAVE_SLOT] = slot; - array[6] = 0x01; - array[7] = 0x01; - - if(strlen(name) > 31) - name[31] = 0x00; - - for(unsigned int i = 16, j = 0; name[j] != 0x00; i++,j++) - array[i] = name[j]; - - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - load_memory_bank(slot, NULL, NULL, NULL); - - return ret; -} - -int Mustang::load_memory_bank(int slot, char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) -{ - int ret, received; - unsigned char array[LENGTH], data[7][LENGTH]; - - memset(array, 0x00, LENGTH); - array[0] = 0x1c; - array[1] = 0x01; - array[2] = 0x01; - array[SAVE_SLOT] = slot; - array[6] = 0x01; - - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - - for(int i = 0; received; i++) { - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - if(i < 7) - memcpy(data[i], array, LENGTH); - } - - if(name != NULL || amp_set != NULL || effects_set != NULL) - decode_data(data, name, amp_set, effects_set); - - return ret; -} - -int Mustang::decode_data(unsigned char data[6][LENGTH], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) -{ - if(name != NULL) - { - // NAME - memset(name, 0x00, 32); - for(int i = 0, j = 16; data[0][j] != 0x00; i++, j++) - name[i] = data[0][j]; - } - - - if(amp_set != NULL) - { - // AMPLIFIER - switch(data[1][AMPLIFIER]) - { - case 0xf1: - amp_set->amp_num = STUDIO_PREAMP; - break; - - case 0x7c: - amp_set->amp_num = FENDER_57_CHAMP; - break; - - case 0x67: - amp_set->amp_num = FENDER_57_DELUXE; - break; - - case 0xf6: - amp_set->amp_num = FENDER_57_TWIN; - break; - - case 0x64: - amp_set->amp_num = FENDER_59_BASSMAN; - break; - - case 0x6a: - amp_set->amp_num = FENDER_65_PRINCETON; - break; - - case 0x53: - amp_set->amp_num = FENDER_65_DELUXE_REVERB; - break; - - case 0x75: - amp_set->amp_num = FENDER_65_TWIN_REVERB; - break; - - case 0xf9: - amp_set->amp_num = S60S_THRIFT; - break; - - case 0xff: - amp_set->amp_num = BRITISH_WATTS; - break; - - case 0x61: - amp_set->amp_num = BRITISH_60S; - break; - - case 0x79: - amp_set->amp_num = BRITISH_70S; - break; - - case 0x5e: - amp_set->amp_num = BRITISH_80S; - break; - - case 0xfc: - amp_set->amp_num = BRITISH_COLOUR; - break; - - case 0x72: - amp_set->amp_num = FENDER_SUPER_SONIC; - break; - - case 0x5d: - amp_set->amp_num = AMERICAN_90S; - break; - - case 0x6d: - amp_set->amp_num = METAL_2000; - break; - - default: - amp_set->amp_num = STUDIO_PREAMP; - break; - } - // STUDIO_PREAMP, - // FENDER_57_CHAMP, - // FENDER_57_DELUXE, - // FENDER_57_TWIN, - // FENDER_59_BASSMAN, - // FENDER_65_PRINCETON, - // FENDER_65_DELUXE_REVERB, - // FENDER_65_TWIN_REVERB, - // S60S_THRIFT, - // BRITISH_WATTS, - // BRITISH_60S, - // BRITISH_70S, - // BRITISH_80S, - // BRITISH_COLOUR, - // FENDER_SUPER_SONIC, - // AMERICAN_90S, - // METAL_2000 - - amp_set->gain = data[1][GAIN]; - amp_set->volume = data[1][VOLUME]; - amp_set->treble = data[1][TREBLE]; - amp_set->middle = data[1][MIDDLE]; - amp_set->bass = data[1][BASS]; - amp_set->cabinet = data[1][CABINET]; - amp_set->noise_gate = data[1][NOISE_GATE]; - amp_set->master_vol = data[1][MASTER_VOL]; - amp_set->gain2 = data[1][GAIN2]; - amp_set->presence = data[1][PRESENCE]; - amp_set->threshold = data[1][THRESHOLD]; - amp_set->depth = data[1][DEPTH]; - amp_set->bias = data[1][BIAS]; - amp_set->sag = data[1][SAG]; - amp_set->brightness = data[1][BRIGHTNESS]?true:false; - amp_set->usb_gain = data[6][16]; - } - - - if(effects_set != NULL) - { - // EFFECTS - for(int i = 2; i < 6; i++) - { - int j=0; - - prev_array[data[i][DSP]-6][0] = 0x1c; - prev_array[data[i][DSP]-6][1] = 0x03; - prev_array[data[i][DSP]-6][FXSLOT] = data[i][FXSLOT]; - prev_array[data[i][DSP]-6][DSP] = data[i][DSP]; - prev_array[data[i][DSP]-6][19] = data[i][19]; - prev_array[data[i][DSP]-6][20] = data[i][20]; - - switch(data[i][FXSLOT]) - { - case 0x00: - case 0x04: - j = 0; - break; - - case 0x01: - case 0x05: - j = 1; - break; - - case 0x02: - case 0x06: - j = 2; - break; - - case 0x03: - case 0x07: - j = 3; - break; - - default: - j=0; - break; - } - - effects_set[j].fx_slot = j; - effects_set[j].knob1 = data[i][KNOB1]; - effects_set[j].knob2 = data[i][KNOB2]; - effects_set[j].knob3 = data[i][KNOB3]; - effects_set[j].knob4 = data[i][KNOB4]; - effects_set[j].knob5 = data[i][KNOB5]; - effects_set[j].knob6 = data[i][KNOB6]; - if(data[i][FXSLOT] > 0x03) - effects_set[j].put_post_amp = true; - else - effects_set[j].put_post_amp = false; - - switch(data[i][EFFECT]) - { - case 0x00: - effects_set[j].effect_num = EMPTY; - break; - - case 0x3c: - effects_set[j].effect_num = OVERDRIVE; - break; - - case 0x49: - effects_set[j].effect_num = WAH; - break; - - case 0x4a: - effects_set[j].effect_num = TOUCH_WAH; - break; - - case 0x1a: - effects_set[j].effect_num = FUZZ; - break; - - case 0x1c: - effects_set[j].effect_num = FUZZ_TOUCH_WAH; - break; - - case 0x88: - effects_set[j].effect_num = SIMPLE_COMP; - break; - - case 0x07: - effects_set[j].effect_num = COMPRESSOR; - break; - - case 0x12: - effects_set[j].effect_num = SINE_CHORUS; - break; - - case 0x13: - effects_set[j].effect_num = TRIANGLE_CHORUS; - break; - - case 0x18: - effects_set[j].effect_num = SINE_FLANGER; - break; - - case 0x19: - effects_set[j].effect_num = TRIANGLE_FLANGER; - break; - - case 0x2d: - effects_set[j].effect_num = VIBRATONE; - break; - - case 0x40: - effects_set[j].effect_num = VINTAGE_TREMOLO; - break; - - case 0x41: - effects_set[j].effect_num = SINE_TREMOLO; - break; - - case 0x22: - effects_set[j].effect_num = RING_MODULATOR; - break; - - case 0x29: - effects_set[j].effect_num = STEP_FILTER; - break; - - case 0x4f: - effects_set[j].effect_num = PHASER; - break; - - case 0x1f: - effects_set[j].effect_num = PITCH_SHIFTER; - break; - - case 0x16: - effects_set[j].effect_num = MONO_DELAY; - break; - - case 0x43: - effects_set[j].effect_num = MONO_ECHO_FILTER; - break; - - case 0x48: - effects_set[j].effect_num = STEREO_ECHO_FILTER; - break; - - case 0x44: - effects_set[j].effect_num = MULTITAP_DELAY; - break; - - case 0x45: - effects_set[j].effect_num = PING_PONG_DELAY; - break; - - case 0x15: - effects_set[j].effect_num = DUCKING_DELAY; - break; - - case 0x46: - effects_set[j].effect_num = REVERSE_DELAY; - break; - - case 0x2b: - effects_set[j].effect_num = TAPE_DELAY; - break; - - case 0x2a: - effects_set[j].effect_num = STEREO_TAPE_DELAY; - break; - - case 0x24: - effects_set[j].effect_num = SMALL_HALL_REVERB; - break; - - case 0x3a: - effects_set[j].effect_num = LARGE_HALL_REVERB; - break; - - case 0x26: - effects_set[j].effect_num = SMALL_ROOM_REVERB; - break; - - case 0x3b: - effects_set[j].effect_num = LARGE_ROOM_REVERB; - break; - - case 0x4e: - effects_set[j].effect_num = SMALL_PLATE_REVERB; - break; - - case 0x4b: - effects_set[j].effect_num = LARGE_PLATE_REVERB; - break; - - case 0x4c: - effects_set[j].effect_num = AMBIENT_REVERB; - break; - - case 0x4d: - effects_set[j].effect_num = ARENA_REVERB; - break; - - case 0x21: - effects_set[j].effect_num = FENDER_63_SPRING_REVERB; - break; - - case 0x0b: - effects_set[j].effect_num = FENDER_65_SPRING_REVERB; - break; - - default: - effects_set[j].effect_num = EMPTY; - break; - } - } - } - - return 0; -} - int Mustang::save_effects(int slot, char name[24], int number_of_effects, struct fx_pedal_settings effects[2]) { int ret, received; @@ -1383,120 +1030,3 @@ int Mustang::save_effects(int slot, char name[24], int number_of_effects, struct return 0; } -int Mustang::update(char *filename) -{ - int ret, received; - unsigned char array[LENGTH], number = 0; - FILE *file; -// struct timespec sleep; -// sleep.tv_nsec = NANO_SEC_SLEEP; -// sleep.tv_sec = 0; - - if(amp_hand == NULL) - { - // initialize libusb - ret = libusb_init(NULL); - if (ret) - return ret; - - // get handle for the device - amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, OLD_USB_UPDATE_PID); - if(amp_hand == NULL) - { - amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, NEW_USB_UPDATE_PID); - if(amp_hand == NULL) - { - amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, MINI_USB_UPDATE_PID); - if(amp_hand == NULL) - { - amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, FLOOR_USB_UPDATE_PID); - if(amp_hand == NULL) - { - libusb_exit(NULL); - return -100; - } - } - } - } - - // detach kernel driver - ret = libusb_kernel_driver_active(amp_hand, 0); - if(ret) - { - ret = libusb_detach_kernel_driver(amp_hand, 0); - if(ret) - { - stop_amp(); - return ret; - } - } - - // claim the device - ret = libusb_claim_interface(amp_hand, 0); - if(ret) - { - stop_amp(); - return ret; - } - } - else - return -200; - - file = fopen(filename, "rb"); - // send date when firmware was created - fseek(file, 0x1a, SEEK_SET); - memset(array, 0x00, LENGTH); - array[0] = 0x02; - array[1] = 0x03; - array[2] = 0x01; - array[3] = 0x06; - int rc = fread(array+4, 1, 11, file); - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); -// nanosleep(&sleep, NULL); - usleep(10000); - - // send firmware - fseek(file, 0x110, SEEK_SET); - for(;;) - { - memset(array, 0x00, LENGTH); - array[0] = array[1] = 0x03; - array[2] = number; - number++; - array[3] = fread(array+4, 1, LENGTH-8, file); - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); -// nanosleep(&sleep, NULL); - usleep(10000); - if(feof(file)) // if reached end of the file - break; // exit loop - } - fclose(file); - - // send "finished" packet - memset(array, 0x00, LENGTH); - array[0] = 0x04; - array[1] = 0x03; - ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); - libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); - - // release claimed interface - ret = libusb_release_interface(amp_hand, 0); - if(ret) - return ret; - - // re-attach kernel driver - ret = libusb_attach_kernel_driver(amp_hand, 0); - if(ret) - return ret; - - // close opened interface - libusb_close(amp_hand); - amp_hand = NULL; - - // stop using libusb - libusb_exit(NULL); - - return 0; -} diff --git a/mustang.h b/mustang.h index 33a68b6..9362c30 100644 --- a/mustang.h +++ b/mustang.h @@ -1,8 +1,9 @@ +// -*-c++-*- #ifndef MUSTANG_H #define MUSTANG_H -#include +#include #include #include #include @@ -10,6 +11,7 @@ #include "effects_enum.h" #include "data_structs.h" //#include +#include "amp.h" // amp's VID and PID #define USB_VID 0x1ed8 @@ -69,30 +71,74 @@ #define SAVE_SLOT 4 #define FXKNOB 3 -// effect category (slot in 'prev_array'). Used to toggle state. -#define STOMP 0 -#define MOD 1 -#define DELAY 2 -#define REVERB 3 +// direct control fields +#define FAMILY 2 +#define ACTIVE_INVERT 3 + +// Index into current state structure +#define PRESET_NAME 0 +#define AMP_STATE 1 +#define STOMP_STATE 2 +#define MOD_STATE 3 +#define DELAY_STATE 4 +#define REVERB_STATE 5 +#define EXP_STATE 6 + +// DSP Category +#define AMP_DSP 5 +#define STOMP_DSP 6 +#define MOD_DSP 7 +#define DELAY_DSP 8 +#define REVERB_DSP 9 + +// DSP Family (used for direct parm set) - Effectively DSP - 3 +#define STOMP_FAM 3 +#define MOD_FAM 4 +#define DELAY_FAM 5 +#define REVERB_FAM 6 + +// Amp id values +#define F57_DELUXE_ID 0x67 +#define F59_BASSMAN_ID 0x64 +#define F57_CHAMP_ID 0x7c +#define F65_DELUXE_ID 0x53 +#define F65_PRINCETON_ID 0x6a +#define F65_TWIN_ID 0x75 +#define F_SUPERSONIC_ID 0x72 +#define BRIT_60S_ID 0x61 +#define BRIT_70S_ID 0x79 +#define BRIT_80S_ID 0x5e +#define US_90S_ID 0x5d +#define METAL_2K_ID 0x6d +#define STUDIO_PREAMP_ID 0xf1 + +#define F57_TWIN_ID 0xf6 +#define S60S_THRIFT_ID 0xf9 +#define BRIT_WATT_ID 0xff +#define BRIT_COLOR_ID 0xfc class Mustang { public: Mustang(); ~Mustang(); - int start_amp(char list[][32]=NULL, char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); // initialize communication + int start_amp(void); // initialize communication int stop_amp(void); // terminate communication int set_effect(struct fx_pedal_settings); - int set_amplifier(struct amp_settings); + int setAmp( int ord ); int save_on_amp(char *, int); - int load_memory_bank(int, char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); + int load_memory_bank(int); int save_effects(int , char *, int , struct fx_pedal_settings *); - int update(char *); // State: 1 = off, 0 = on int effect_toggle(int category, int state); -private: + int control_common1(int parm, int bucket, int value); + int control_common2(int parm, int bucket, int value); + + AmpCC * getAmp( void ) { return curr_amp;} + + private: libusb_device_handle *amp_hand; // handle for USB communication unsigned char execute[LENGTH]; // "apply" command sent after each instruction @@ -106,7 +152,22 @@ private: // unsigned char prev_array[4][LENGTH]; // array used to clear the effect - int decode_data(unsigned char [6][LENGTH], char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); + + // Current state of amp. + // + // 0 : Preset Name + // 1 : Amp + // 2 : Stomp + // 3 : Mod + // 4 : Delay + // 5 : Reverb + // 6 : Expression Pedal + // + unsigned char curr_state[7][LENGTH]; + + AmpCC * curr_amp; + + void updateAmp(void); }; #endif // MUSTANG_H diff --git a/mustang_midi.cpp b/mustang_midi.cpp index 088ecd5..a6d8af6 100644 --- a/mustang_midi.cpp +++ b/mustang_midi.cpp @@ -5,17 +5,12 @@ #include "mustang.h" -static Mustang amp; - -static amp_settings amp_parms; -static fx_pedal_settings pedal_parms; -static char name[32]; -static char names[100][32]; +static Mustang mustang; static int channel; void message_action( double deltatime, std::vector< unsigned char > *message, void *userData ) { -#if 1 +#if 0 unsigned int nBytes = message->size(); if ( nBytes > 0 ) { for ( unsigned int i=0; i *message, vo int msg_channel = (*message)[0] & 0x0f; if ( msg_channel != channel ) return; - int rc; int msg_type = (*message)[0] & 0xf0; + switch ( msg_type ) { + case 0xc0: { // Program change int bank = (int)(*message)[1]; - rc = amp.load_memory_bank( bank, name, &_parms, &pedal_parms ); + int rc = mustang.load_memory_bank( bank ); if ( rc ) { - std::cout << "Error: load_memory_bank " << bank << " failed. rc = " << rc << "\n"; + fprintf( stderr, "Error: PC#%d failed. RC = %d\n", bank, rc ); } } break; case 0xb0: { // Control change - if ( (*message)[1] >= 23 && (*message)[1] <= 26 ) { - int category = (*message)[1] - 23; - int value = (*message)[2]; + int rc; + int cc = (*message)[1]; + int value = (*message)[2]; + AmpCC *ampModel = mustang.getAmp(); + + // Effects on/off + if ( cc >= 23 && cc <= 26 ) { + // Translate 23..26 --> 2..5 (current state index) + int index = cc - 21; int state; - if ( value >= 0 && value <= 63 ) state = 1; - else if ( value > 63 && value <= 127 ) state = 0; - rc = amp.effect_toggle( category, state ); - if ( rc ) { - std::cout << "Error: effect_toggle " << category << " failed. rc = " << rc << "\n"; - } + if ( value >= 0 && value <= 63 ) state = 0; + else if ( value > 63 && value <= 127 ) state = 1; + rc = mustang.effect_toggle( index, state ); + } + // Set amp model + else if ( cc == 68 ) { + // fprintf( stderr, "DEBUG: %d\n", value ); + rc = mustang.setAmp( value ); + } + // Gain + else if ( cc == 69 ) { + rc = ampModel->cc69( value ); + } + // Channel volume + else if ( cc == 70 ) { + rc = ampModel->cc70( value ); + } + // Treble + else if ( cc == 71 ) { + rc = ampModel->cc71( value ); + } + // Mid + else if ( cc == 72 ) { + rc = ampModel->cc72( value ); + } + // Bass + else if ( cc == 73 ) { + rc = ampModel->cc73( value ); + } + // Sag + else if ( cc == 74 ) { + rc = ampModel->cc74( value ); + } + // Bias + else if ( cc == 75 ) { + rc = ampModel->cc75( value ); + } + // Noise Gate + else if ( cc == 76 ) { + rc = ampModel->cc76( value ); + } + // Cabinet + else if ( cc == 77 ) { + rc = ampModel->cc77( value ); + } + // Presence / Gain2 / Cut + else if ( cc == 78 ) { + rc = ampModel->cc78( value ); + } + // Blend / Master Volume + else if ( cc == 79 ) { + rc = ampModel->cc79( value ); + } + if ( rc ) { + fprintf( stderr, "Error: CC#%d failed. RC = %d\n", cc, rc ); } } break; @@ -84,7 +135,7 @@ int main( int argc, const char **argv ) { if ( endptr == argv[0] ) usage(); if ( channel < 0 || channel > 15 ) usage(); - int rc = amp.start_amp( names, name, &_parms, &pedal_parms ); + int rc = mustang.start_amp(); if (rc) { std::cout << "Fender USB initialization failed: " << rc << "\n"; return 8;