The midiexiter source is developed and created with AVRStudio 4. The 
software grew and evolved with the board. The original design had an 
LCD display, eight buttons and two analog potentiometers for input. 
The display proved too large and slow and was removed. The double 
7-segment display and five LEDs are more compact and work much faster. 
The buttons were reduced to three. The two potentiometers were 
replaced by a rotary encoder. 
All these changes are reflected in the software as features weer only 
removed if the replacement was working. Call it software evolution.
It is mainly visible in the port assignment.

Software description

The software is split over three files:
- midiexiter.asm
  The main loop, interrupt service routines and ISR macro's.
- midiexiter_def.asm
  The definitions and EEPROM contents. 
- midiexiter_lib.asm
  The subroutines of the main loop.

After initialisation the main loop is run continuously. Temporary 
variables are temp and temp2, which are also used for argument and
return value passing. The main loop
tasks are:
- Polling the receiver ring buffer status and copy its contents to the 
  transmit buffer. This feature is not useful as it is not a real MIDI
  merge. Only single byte messages are guaranteed to be copied 
  correctly.
- Poll the Message Interrupt flag driven by Timer1 and extension. If 
  the flag is set, the next message is set. Which message is to be 
  send depends on the sintabptr and the sinus table. The other wave
  shapes depend on sintabptr and the flags controlled by GETSINVALUE.
- Poll the Main Loop Interrupt flag driven by Timer0. This part of the 
  main loop reads the keyboard, updates the display. The EEPROM 
  save is started from here on pressing the P button. The edit select
  is handled in subroutines.
  
A lot of the lower interrupt handling is done in the interrupt service 
routines. The ISR routines have their own temporary variable isrtemp.
The routines are:
- External Interrupt 0 and 1.
  These take input from the rotary encoder. EXT_INT0 is increment and
  EXT_INT1 is decrement the current parameter. The parameter is 
  specified in editstat and the direction in the Increment flag.
  Both ISRs share the common macro PARAM_EDIT for the actual work.
- Timer 1 Overflow.
  This timer generates the main loop interrupt flag and controls the 
  keyboard read display refresh. The interval is constant and 
  currently 0.2 second.
- Timer 0 Overflow.
  This timer controls the MIDI message rate. Timing varies from about
  1 ms (minimum interval between 3 byte MIDI messages) and up. Two
  variables influence the timer; msgrate and dutycycle. Both have a 
  small offset to make the interval between the lowest values smaller.
  The dutycycle variable is applied in two ways, depending on wave 
  shape. For the square wave and sinusA, it increases the timer period
  during the upper half of the wave while decreasing it during the 
  lower half. And vice versa. This behaviour is controlled by the Wave 
  Polarity flag. For the triangle wave and sinusB, the timer period is 
  increased during the rising or ascending phase of the wave shape and
  decreased during the falling or descending phase. And vice versa 
  of course. This behaviour is controlled by the Wave Slope flag.
- UART character received.
  This routines gets the character and places it in the receive ring 
  buffer using the UR_A2RX macro.
- UART data transmit register empty.
  On receiving this interrupt, the transmit ring buffer status is
  checked. If not zero a character is retrieved from the transmit 
  buffer using the UD_G4TX macro. If txrbstat indicated an empty 
  buffer, the interrupt is switched off.
  
The subroutines are all directly or indirectly called from the
main loop. Called from the main loop unless indicated otherwise.
- DELAY5US
- DELAY5MS
  These two delay routines are copied from andreas-s@web.de.
- READBUTTON
  Scan the buttons and place it in scanbut. It contains some half
  baked debounce. Here is room for improvment.
- BUSYLED
  Toggles the busy LED. 
- HD12_CLEAR
  Clears both 7-segment displays. As these are addressed as nibbles,
  it is worth making a subroutine. Called by EDIT_DISPLAY.
- HD1_WR
  Calls HD_GETCHAR with the BCD nibble in temp as index. The 
  resulting two nibble width patterns are written into the display 
  registers. Also called by EDIT_DISPLAY.
- HD2_WR
  This routine is almost equal to HD1_WR, but two different routines 
  save one argument and a lot of unclear code. Also called by 
  EDIT_DISPLAY.
- HD3_WR
  This routine writes the low nibble of temp to the LED display 
  register. Also called by SAVEEEPROM.
- HD_WRPULSE
  Clocks the data into the latch of the selected display. Called by 
  HD_12CLEAR, HD1_WR, HD2_WR and HD3_WR.
- HD_GETCHAR
  Retrieves character patterns from the HD_CHAR table in RAM. Called 
  by HD1_WR and HD2_WR.
- EDIT_SELECT
  Scans scanbut for the '<' and '>' keys and modifies editstat. The
  main part is for keeping within legal bounds. Unlike the variable
  editing this routine can jump to the opposite end.
- EDIT_DISPLAY
  Displays the parameter specified by editstat on the display 
  complete with LED pattern.
- ADD2TXRB
  As the name indicates this routine adds characters to the transmit
  buffer TXRBBUF in RAM. Retrieval is done in the UART_DRE ISR. More 
  detailed info on this and the next routine is in the source code.
- GET4RXRB
  This routine retrieves characters from the receive ring buffer 
  RXRBBUF in RAM. See the source for more detailed info. The name 
  needs some ear bending; '4' almost sounds as 'from'.
- GETSINVALUE
  Retrieves the next value for the sinus wave shapes from the 
  SINUSTABLE in RAM and set the polarity and slope flags for all wave 
  shapes. Called by GETVALUE.
- MKMIDIPARAM
  This routine converts the full 8 bit values from the SINUSTABLE to
  a positive and negative half at proper MIDI size (7 bit) using the
  Wave Polarity flag. Called by GETVALUE.
- CALCDUTCY
  Calculates the duty cycle part of the message rate timer. The 
  dutycycle range of 0x00-0x1F is multiplied by four and depending
  on the wavemode (using the Mave Modulation bit/flag) and current
  Wave Polarity or Wave Slope flag setting invert it and write it
  to tim0dutcy (used by TIM0_OVR). Called by GETVALUE.
- TRIACALC
  Triangle wave calculation based on the sintblptr and using
  the Wave Polarity and Wave Slope flags. This method saves another
  variable as counter and guarantees phase sync of the different wave 
  shapes.This routine contains its own MKMIDIPARAM functionality. 
  Called by GETVALUE.
- WRITEEEPROM
  Low level routine for writing to EEPROM. Uses temp for the data 
  value and temp2 for the address. Called by SAVEEEPROM.
- SAVEEEVALUE
  High level routine for writing a parameter to EEPROM. Determines
  the current parameter and calls WRITEEEPROM. Flashes the LEDs as
  write indication.
- SENDMESSAGE
  Adds MIDI message bytes to the transmit buffer and enables the 
  transmit interrupt.
- GETVALUE
  Determines the speed (single or four speed), and calculates the
  parameter to be send. Called by SENDMESSAGE.
