# Designing implementation-inspecific PIC32MZ communication classes in C++

Alright everyone, that title may seem like a significant amount of technobabble, so let me explain what I'm trying to do.

I'm starting to break into the PIC32 family, specifically the PIC32MZ series, namely because I'm starting to want to do things that I want more horsepower for than an AVR can deliver. I've been reading a bunch of tutorial docs and source on the subject, but I figured I'd bring this question here.

What I'm trying to do is develop a set of classes for the communication interfaces in C++ such that they are unit-inspecific; that is, a generic class that is initialized with the number of the communication interface unit; essentially "one set of code for any number of interfaces". Let me give you an example.

We know from the datasheet that the PIC32MZ family has 6 4-wire SPI modules. This example, while it (presumably) works, it has a number of things that I consider undesirable for my uses:

• It's in C. I want to use classes to help with my data management, so preferably I'm looking for a C++ solution. Obviously, it'd take me all of ten minutes to rewrite this code, but see the next point.
• It's specific to SPI2. This means I'd need an individual class for each of the six SPI units, even if I only need one or two. What I'd like to develop is a unified class for SPI, such that I can call one class and declare the unit number (1 to 6) in the constructor and have it initialize the appropriate one. Basing off the above example, the constructor would look like so:

 SPI::SPI (uint baud, uint u_num) { // Some discrimination of what u_num is // Setup } 

Things I've considered, but thrown-out/decided against/unsure if feasible or how to do:

• If/else/switch statements in each method. This is the obviously easiest of all possible routes, but also the dumbest and the most sub-optimal. Every time the method calls, it would have to evaluate which unit to assign the parameters to which is wasted time.
• Function pointers from Microchip functions into arrays for calls. So, SPI1-6 functions such as configure, send byte, etc. would map into an array, when the class method calls it plugs the unit number (stored in a class variable) into the array and pumps the parameters in to the function referenced by the pointer table.
• Macros. Using the register macros provided by Microchip somehow to my advantage, although I have no idea (not afraid to say that one) how I would use that or to my advantage. Again, the gut feeling is it'd have to be some sort of pointer table.
• Raw addresses. I seem to remember that the datasheet gives the addresses for the registers in the memory space, although it's hard to draw a reference to them right now on demand. I believe they were virtual addresses - my main issue with this is that I don't have a clue how to leverage virtual memory from a high-level context (I've always understood that the OS and CPU manage virtual memory to physical address mapping, but how that translates up the totem pole I have no idea of), and so I wouldn't have any idea how to make the class work. Essentially, if I could figure it out (providing this was feasible), I could figure out the association (offset) between say, SPI1 registers and SPI2 registers and make the class methods auto-apply that offset depending on the unit class variable.

EDIT: Found the SPI register map along with virtual addresses, apparently starting at 0xBF821000, although it's of little comfort so far.

Thank you if any of you can help.

• Cheat and take a look at the chipKIT software: github.com/chipKIT32/chipKIT32-MAX It has all those classes in there for you already - SPI (look at the DSPI library), UART (look at the HardwareSerial classes), I2C (look at DTWI)... – Majenko Mar 14 '15 at 12:15
• A class template and a bit of template metaprogramming should be able to provide optimal code. – Pete Becker Mar 14 '15 at 12:41
• Take a look at ChibiOS. Basically, it boils down to either specializing each class with a SPI struct that point's to the right hardware address, or compare addresses: if (myNum == 1) myDriver = &spi1 else if (myNum == 2) ... – FRob Mar 16 '15 at 2:49