void main(void)
{
InitializeSystem();
while(1)
{
USBTasks();
ProcessIO();
}
}
■ EXAMPLE 1.
main() routine.
// USB Tasks
routines in ProcessIO() and USBTasks(), which handles
USB housekeeping routines such as disconnecting and
reconnecting to the PC. The USB code is not interrupt
driven. ProcessIO() must execute promptly, otherwise the
USB interface will fail. I'll come back to this point later.
Interrupts Provide the Heartbeat
The heart of the mistralXG code is the interrupt
routine (interrupt.c) which handles three types of events:
a timer running every 1 ms; and receive and transmit
interrupts from the EUSART, generated by the incoming
and outgoing MIDI streams.
The timer interrupt manages a number of things:
• A display refresh timer that updates the display every
100 ms.
• A display timeout timer that returns the display to the
Home Screen after a few seconds.
• The Running Status injection timer that ensures a MIDI
command/status byte is sent at least every 250 ms.
• Switch debouncing to prevent spurious input from the
pushbuttons.
MIDI data to and from mistralXG are handled by the
interrupt routine and placed in buffers for transmission to
the PC and synth.
Keeping Everything Going — user.c
There are three main routines in user.c. UserInit() handles
initialization of the various user routines and is responsible for
configuring the various peripherals. Next in line is ProcessIO(),
discussed later, and finally there is ServiceRequests(),
responsible for the user data flowing over the USB.
ProcessIO() — the scheduler
If interrupts form mistralXG's heart, ProcessIO() is the
brain. This routine keeps everything in sync and on track. A
pseudo-code skeleton of its function is shown in Example 2.
If you look at the source code, you'll see that there is
a lot of additional fine detail to make sure that everything
works as it needs to, but the pseudo-code captures the
essence of the routine's function, and I'll take you through
this step-by-step:
• It first checks whether a MIDI byte has been received
by the EUSART. If so, processNextByte() (mxg_musm.c)
void ProcessIO(void)
{
if(MIDI data received) processNextByte();
if(buttons changed)
handle the button press;
if(data to write to EEPROM and it's
not busy) write data to EEPROM;
if(display timeout occurred)
switch to Home Screen;
if(display refresh timer complete)
refreshDisplay();
if(WritesToLCDPending and LCD not busy)
nextChar();
// User Application USB tasks
if(USB not connected)
disable MIDI to USB;
else { // USB is active
ServiceRequests();
}
}//end ProcessIO
void ServiceRequests(void)
{
if(incoming MIDI data ready)
send it to the PC via USB;
if(USB-MIDI data packet ready)
send it to the synth/MIDIOUT;
}//end ServiceRequests
■ EXAMPLE 2. The ProcessIO() and
ServiceRequests() user routines.
handles it by building it into a USB-MIDI packet. A
complete MIDI command message of one to three
bytes is combined into a single packet, with up to
16 packets being sent in a single USB transfer.
• Changes to the two pushbuttons are checked for and
handled in mxg_iface.c.
• If the user has changed an option, its setting is saved
in the MCU's EEPROM (mxg_eeprom.c). Writes to the
EEPROM take several milliseconds so they are scheduled and processed when the hardware is available.
• If the display timeout timer has expired, the display is
switched back to the Home Screen (mxg_iface.c).
• If the display refresh timer has expired, a display refresh
is scheduled (mxg_iface.c).
• Some display updates can take well over 1 ms, so these
are scheduled to occur when the hardware is available
(mxg_iface.c).
If the USB port is connected, ServiceRequests() is then
called to handle the application's USB transfers, doing so
in two stages:
• It first checks whether any incoming MIDI data has been
assembled into packets for the PC and, if so, sends them.
• It then checks for received USB-MIDI packets and, if so,
transfers extracted MIDI data to the transmit buffer
where the interrupt routine picks them up and sends
them out to the synth.
Timing is Critical
I've used the word scheduled several times in the
March 2009 43