For all you that are contemplating a common body of code running on many different PICs , I have a project where I have to deal with this on a constant basis. For a long time, we built hardware with a 20Mhz 8720. Later, the hardware changed to a 40Mhz 8723. The speed increase was necessary for some new functionality (the 12 bit A/D was handy too), but we really didn't want to support two code bases. Some customers had both models, which meant the same code had to run seamlessly on both. The boards (obviously) have nearly the same functionality, but upgrades dictated that some pin changes (at least on the PIC - not the board I/O) had to change as well.

We even had a few intermediate boards that were running with an 8723 at 20Mhz. These were built when the '8720 was becoming obsolete and before we had code that was modified to run at 40Mhz.

Our code can tell some of the things about the board it is on by reading the state of a couple of pins on startup (no we didn't plan it that way, it just works out).

The 20 Mhz units are running with a 20Mhz XTAL, and the 40Mhz units are running on a 10Mhz XTAL with the 4X PLL running.

We read the config bits to see if the PLL is enabled and set a "40Mhz" flag.
The config bits also tell us we are running on an 8723 or 8720.

Since the code is the same in all boards, the DEFINES are the same. In our code, the OSC is DEFINEd to 20.

Using information from the config bits, we made a table that set up things properly as far as timer reload values (to keep the timer interrupts at a constant rate), Baud rate values, PR2 (PWM registers, etc), A/D clock (/32 or /64). The A/D conversion routines also had to be changed to deal with the two extra bits on the '23.

Finally, we made a large number of GOSUB DELAYX , which replaced all the PAUSE STATEMENTS. For example: The PAUSE 100 would be replaced with
GOSUB DELAY100. DELAY100 called another routine that contained PAUSE X,
where 'X' was either 100 (for 20Mhz) or 200 (for 40Mhz).

It can be done.