The Organ Project Software

The music driver part of the Organ Software has been built to run on Arizona Microchip PIC microcontrollers, responding to instructions from a PC that reads MIDI files and then talks to the microcontrollers using a standard serial cable.

A circuit diagram (schematic) isn't available yet but I hope to get one drawn before long. The first prototype board is basic but functional. It uses a 16F871 microcontroller clocked at 10Mhz (chosen because it handily divides to provide an almost 57,600 baud clock rate for the serial communications). Whilst I was deciding what clock rate to use I wrote a simple PHP program that would calculate what baud rates could be got from particular clock speeds and you are welcome to make use of it - put your clock rate into the box below and press the button to see what baud rates you can get for the divisors available from the 16F871.

Clock in MHz:
Array(), 75 => Array(), 110 => Array(), 134 => Array(), 150 => Array(), 200 => Array(), 300 => Array(), 600 => Array(), 1200 => Array(), 1800 => Array(), 2400 => Array(), 4800 => Array(), 9600 => Array(), 19200 => Array(), 38400 => Array(), 57600 => Array(), 115200 => Array(), 230400 => Array() ); for($i = 0; $i <= 255; $i++){ foreach($recognisedrates as $desired => $dummy){ $hi = $fosc/(16*($i+1)); $lo = $fosc/(64*($i+1)); $hierr = abs(100*($desired-$hi)/$desired); $loerr = abs(100*($desired-$lo)/$desired); if(!isset($recognisedrates[$desired]['besthierror']) || $hierr < $recognisedrates[$desired]['besthierror']){ $recognisedrates[$desired]['besthierror'] = $hierr; $recognisedrates[$desired]['besthidivisor'] = $i; $recognisedrates[$desired]['besthibaud'] = $hi; } if(!isset($recognisedrates[$desired]['bestloerror']) || $loerr < $recognisedrates[$desired]['bestloerror']){ $recognisedrates[$desired]['bestloerror'] = $loerr; $recognisedrates[$desired]['bestlodivisor'] = $i; $recognisedrates[$desired]['bestlobaud'] = $lo; } } } print "Calculated baud rate showing best hi/lo divisor value for that rate and consequent error percentage.\n"; print "Probably usable rates (error less than 3%) are coloured green.\n"; print "\n"; foreach($recognisedrates as $desired => $numbers){ $bhd = $numbers['besthidivisor']; $bld = $numbers['bestlodivisor']; $bhe = (int)($numbers['besthierror'] + 0.5); $ble = (int)($numbers['bestloerror'] + 0.5); $hicol = $bhe < 3 ? "lightgreen" : "red"; $locol = $ble < 3 ? "lightgreen" : "red"; $bhb = (int)($numbers['besthibaud'] + 0.5); $blb = (int)($numbers['bestlobaud'] + 0.5); print ""; } print "
Baud rateHi divisor (error), actualLo divisor (error), actual
$desired$bhd ($bhe%) $bhb baud$bld ($ble%) $blb baud
\n"; } ?>

The baud rate chosen is nothing like the standard MIDI baud rate but that's not important. The controller board isn't intended to be driven from a standard MIDI output, it is driven from a PC serial port instead and there's no particular reason why it should speak standard MIDI at all. Perhaps one day that might be changed but for the moment I have my own protocol for talking to it.

There are various ways of reprogramming the flash memory of the PIC chip. it is, after all, intended for in-circuit programming. Any of the most obvious ways of doing that use up some of the I/O ports on the chip and I didn't particularly want to have any of those involved for two reasons. The first was that it would require extra wiring on the board (probably a bogus concern), but more importantly, since the PC would be talking to the controller anyhow, a better approach would be to use the PIC's ability to reprogram itself and control that from the PC as well. That still implies an initial programming phase using one of the other methods, but once the PIC is in place on the controller board it can be reprogrammed as necessary so long as the reprogramming doesn't need to overwrite the code that talks to the PC.

The current software for the PIC implements a serial protcol between the PC and the PIC allowing for the flash memory, the EEPROM the registers and the IO ports to be read and written by the PC. The code is designed to allow further instructions to be written to flash memory above the control program which resides at low memory locations. It doesn't use interrupts since it doesn't need to.

The controller program runs as a polling loop checking for characters to be read from the serial port and for the internal hardware clock timer to expire. If either of those events occurs they are handled in small subroutines. Both the polling loop and the hardware clock sub-task call a further subroutine unless a flag bit is set. Each of those subroutines is located in memory above the main program with the intention being that reprogramming would overwrite the current return instruction with a jump to a longer subroutine.

At present there is no code on the PIC to control any of the electromechanical drivers that are attached. That's done instead by the PC instructing the PIC to change values on its IO ports and thus indirectly setting the state of the actual IO lines to the electromechanical units. Code to do that will be added later, it's not at the top of the agenda at present.

The relatively badly documented software is available to anyone who cares to look at it. Both the code for the PC side (undergoing rapid evolution) and the PIC (tested and believed working) can be downloaded and are subject to the GPL (Gnu Public Licence) terms and conditions.

Development of the code was made possible by and enjoyable through the use of the GNU pic tools and the remarkable gpsim program for simulating PICs. Although gpsim doesn't have a profile for the 16F871 (at least not as I write this), the 16F877 is essentially a directly compatible part with more memory and registers so I used that profile for the simulation. All of the software was developed and tested on the simulator before being programmed into the PIC and it worked first time on the actual hardware, which is a credit to Scott Dattalo and the other contributors to the gpsim project.

The current state of the software is: