Hi,
I managed to get USB MIDI to work for Axe FX II XL+ on a Raspberry pi. This as a quick write-up of the steps so far... might be interesting for custom controllers. The PI doesn't excel at anything, but it's "adequate" for a great many things... Me, I'm after physical buttons for tone controls...
"fxload" for USB firmware upload can be installed with sudo apt-get install fxload.
The hex file is here.
I haven't done a "regular" hotplug setup yet but ran it from the command line as
sudo fxload -v -t fx2lp -I axefx2load.hex -D /dev/bus/usb/001/011
where the number "11" changes with every replug cycle, get it with dmesg
[ 368.463374] usb 1-1.1.3: new high-speed USB device number 11 using dwc_otg
[ 368.594151] usb 1-1.1.3: New USB device found, idVendor=2466, idProduct=8003
[ 368.594168] usb 1-1.1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
If this step causes trouble, a temporary solution is to plug the USB cable first into a Windows machine with drivers, then unplug and connect to the RPI without power cycling. The MIDI interface should appear as /dev/snd/midiC1D0.
Then, I did a crude implementation of the sysex protocol. The program doesn't do anything useful, but I hope it helps as a simple starting point, below.
Note, you may need to edit the "model number" byte, see [1] link in the code.
Then compile with gcc main.c (might require some apt-get gcc or similar) and run with ./a.out. Everything going according to plan, you should see a single message"got firmware info".
I hope this is useful to somebody. Happy hacking
I managed to get USB MIDI to work for Axe FX II XL+ on a Raspberry pi. This as a quick write-up of the steps so far... might be interesting for custom controllers. The PI doesn't excel at anything, but it's "adequate" for a great many things... Me, I'm after physical buttons for tone controls...
"fxload" for USB firmware upload can be installed with sudo apt-get install fxload.
The hex file is here.
I haven't done a "regular" hotplug setup yet but ran it from the command line as
sudo fxload -v -t fx2lp -I axefx2load.hex -D /dev/bus/usb/001/011
where the number "11" changes with every replug cycle, get it with dmesg
[ 368.463374] usb 1-1.1.3: new high-speed USB device number 11 using dwc_otg
[ 368.594151] usb 1-1.1.3: New USB device found, idVendor=2466, idProduct=8003
[ 368.594168] usb 1-1.1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
If this step causes trouble, a temporary solution is to plug the USB cable first into a Windows machine with drivers, then unplug and connect to the RPI without power cycling. The MIDI interface should appear as /dev/snd/midiC1D0.
Then, I did a crude implementation of the sysex protocol. The program doesn't do anything useful, but I hope it helps as a simple starting point, below.
Note, you may need to edit the "model number" byte, see [1] link in the code.
Then compile with gcc main.c (might require some apt-get gcc or similar) and run with ./a.out. Everything going according to plan, you should see a single message"got firmware info".
I hope this is useful to somebody. Happy hacking
Code:
#include <stdio.h>
#include <assert.h>
// [1] https://wiki.fractalaudio.com/axefx2/index.php?title=MIDI_SysEx#MIDI_SysEx:_Axe-Fx_II
#define MODELNO (0x07) // [1] "MIDI SysEx: SysEx Model number per device"
#define MIDIDEV ("/dev/snd/midiC1D0")
void handleMsg(char* buf, int len){
if (len < 6) return;
if (buf[0] != 0xF0) return;
if (buf[1] != 0x00) return;
if (buf[2] != 0x01) return;
if (buf[3] != 0x74) return;
if (buf[4] != MODELNO) return;
switch (buf[5]){
case 0x08: fprintf(stdout, "got firmware info\n"); break;
case 0x10: fprintf(stdout, "got tempo beat\n"); break;
case 0x21: fprintf(stdout, "got front panel change\n"); break;
default:
for (int ix = 0; ix < len; ++ix){
fprintf(stdout, "%02x ", (int)(buf[ix]));
}
fprintf(stdout, "\n"); fflush(stdout);
}
}
typedef struct {
char buf[256];
int ptr;
} msg_t;
void msg_init(msg_t* self){
self->ptr = 0;
self->buf[self->ptr++] = 0xf0; // sysex start
self->buf[self->ptr++] = 0x00; // man ID byte 1
self->buf[self->ptr++] = 0x01; // man ID byte 2
self->buf[self->ptr++] = 0x74; // man ID byte 3
self->buf[self->ptr++] = MODELNO; // model specific. See above
}
void msg_add(msg_t* self, char val){
self->buf[self->ptr++] = val;
}
void msg_closeSendInit(msg_t* self, FILE* h){
char chksum = 0;
for (int ix = 0; ix < self->ptr; ++ix)
chksum ^= self->buf[ix];
self->buf[self->ptr++] = chksum & 0x7F;
self->buf[self->ptr++] = 0xF7;
int n = fwrite((void*)self->buf, 1, self->ptr, h); assert(n == self->ptr);
fflush(h);
msg_init(self);
}
int main(void){
FILE* hIn = fopen(MIDIDEV, "r"); assert(hIn);
FILE* hOut = fopen(MIDIDEV, "wb"); assert(hOut);
msg_t _m; msg_t* m = &_m;
msg_init(m);
msg_add(m, 0x08);
msg_closeSendInit(m, hOut);
int p;
char buf[256];
restartMidiLoop:
p = 0;
while (1){
char c;
int n = fread((void*)&c, 1, 1, hIn); assert(n == 1);
if (c == 0xF0)
p = 0;
buf[p++] = c;
if (p == sizeof(buf)) goto restartMidiLoop;
if (c == 0xF7){
handleMsg(buf, p);
goto restartMidiLoop;
}
}
}
Last edited: