I think you were being bit by some variant of the "precompiler rearranges your sketch" bug.
I got your last code to compile by adding a line defining SendMidiMsg(); see below.
I got there by looking at the .cpp that is actually compiled for the project, which you can get from rummaging around in the build folder, which you can identify by turning on verbose builds in Preferences. The precompiler phase moved the definition of SendMidiMsg above the definition of the union, which made the compiler unhappy. It seems better here with the patch.
-br
#include "arduino.h"
#define _C4 0x30
#define _Cs4 0x31
#define _D4 0x32
#define _Ds4 0x33
#define _E4 0x34
#define _F4 0x35
#define _Fs4 0x36
#define _G4 0x37
#define _Gs4 0x38
#define _A4 0x39
#define _As4 0x3A
#define _B4 0x3B
#define _C5 0x3C
#define NoteOn 0x7B
#define MaxVel 0xFF
typedef union {
struct {
uint8_t Command;
uint8_t Channel;
uint8_t Data1;
uint8_t Data2;
} Msg;
uint8_t Raw[4];
} MidiMsg;
void SendMidiMsg (MidiMsg* Message); // this is the magic line
void setup() {
Serial.begin(31250);
}
void SendMidiMsg (MidiMsg* Message){
Serial.write(Message->Raw, sizeof(*Message));
}
void SendNoteOn (uint8_t Note, uint8_t Velocity, uint8_t Channel){
MidiMsg Message;
Message.Msg.Command=NoteOn;
Message.Msg.Channel=Channel;
Message.Msg.Data1=Note;
Message.Msg.Data2=Velocity;
SendMidiMsg(&Message);
}
void SendScale (int ValveState){
uint8_t Vel=MaxVel;
uint8_t Ch=0x00;
switch (ValveState) {
case 0: SendNoteOn(_C4,Vel,Ch); break;
case 1: SendNoteOn(_D4,Vel,Ch); break;
case 2: SendNoteOn(_F4,Vel,Ch); break;
case 3: SendNoteOn(_E4,Vel,Ch); break;
case 4: SendNoteOn(_A4,Vel,Ch); break;
case 5: SendNoteOn(_B4,Vel,Ch); break;
case 6: SendNoteOn(_G4,Vel,Ch); break;
case 7: SendNoteOn(_C5,Vel,Ch); break;
}
}
void loop(){
SendScale(0);
}