After more than a year of inactivity, I have only recently checked the version number of the latest Microchip Graphic Library release and to my horror discovered that I was far behind. The major revision number had jumped (from 2 to 3) and this typically is not a good sign. Let me rephrase that. It is good to see that major work is being done on the library, it is bad for me, as I am so lazy, lots of changes mean a lot of work to fix something that “was working before”.
The relationship (if so we can call it) between me and the Graphics Lib developers is somewhat similar to a marriage of convenience. They need users, I need developers to maintain the library. But our best interests don’t always coincide, or at least their timing is not always perfectly synchronized with mine. A friend recently gave me a definition of marriage that in fact seems to describe the situation perfectly: “Marriage is solving together problems you did not have before”.
An example is the revision step from 1.x to 2.x of the lib that was driven by the launch of the PIC24DA series and the need to include a whole new set of custom features specific of that architecture. I could not care less.
The last revision step to 3.x though is different. This time it seems the developers have spent some real effort in improving the inner structure of the lib something that eventually benefits my project more directly. In particular I appreciated the separation of the display interface from the graphic controller detail (I/O vs. PMP 8 vs. PMP16 etc…). This used to be all mixed up in the graphics drivers with potentially messy results. I am pretty sure the problem must have popped up on the developers radar when attempting to extend the library to the dsPICs series (which is lacking a PMP port) and is now fully supported.
From an egoistic point of view though, the new libs also mark an increased attention to the PIC32 efficiency, as now the display drivers can use atomic I/O controls (reducing code size and increasing speed) in the low level macros or at least they are suggesting it as eventually it is up to us to define them properly in the hardware profile.
This is a segment of a new hardware profile (3.02 compatible) for the uMMB32 board I have been working on:
// display type #define GFX_USE_DISPLAY_CONTROLLER_HX8347D // interface #define USE_GFX_PMP #define USE_16BIT_PMP #define PMP_DATA_SETUP_TIME (30) #define PMP_DATA_WAIT_TIME (30) #define PMP_DATA_HOLD_TIME (30) #define DISP_ORIENTATION 90 // Definitions for reset pin #define DisplayResetConfig() TRISCCLR = _TRISC_TRISC1_MASK #define DisplayResetEnable() LATCCLR = _LATC_LATC1_MASK #define DisplayResetDisable() LATCSET = _LATC_LATC1_MASK // Definitions for RS pin #define DisplayCmdDataConfig() TRISBCLR = _TRISB_TRISB15_MASK #define DisplaySetCommand() LATBCLR = _LATB_LATB15_MASK #define DisplaySetData() LATBSET = _LATB_LATB15_MASK // Definitions for CS pin #define DisplayConfig() TRISFCLR = _TRISF_TRISF12_MASK #define DisplayEnable() LATFCLR = _LATF_LATF12_MASK #define DisplayDisable() LATFSET = _LATF_LATF12_MASK
Notice the nice parameterization of all PMP details and how the RS, CS, and RST lines of the display are now controlled by macros (DisplayConfig(), DisplayEnable()…) so to enable the use of the atomic I/O control registers (i.e. LATF-CLR)
Now for the part I don’t like:
- The display driver selection now requires an extremely verbose “GFX_USE_DISPLAY_CONTROLLER_HX8347D” which at 35 characters is exactly 30 characters too long for my taste.
- The I/O definition macros require us to specify 3 x times (three times, three time, three times) the port we are selecting, which is exactly two times too many:
LATFCLR = _LATF_LATF12_MASK
While the first one is just a personal preference and since it is used only once in each project it has virtually no chance of producing any damage (read bug), the second one is a symptom of something bigger. In fact you will soon discover that for each of the N I/O ports of each PIC 32 model, there are now 4 x 16 (one for each bit for each atomic control register) macros that define each bit listed in the corresponding .h file. It simply escapes me why we would need to distinguish the mask for bit 15 in port A SET register (0x8000), from the mask for bit 15 in port B SET register (0x8000), or any other register for that matter!? Bit 15 is bit 15 is bit 15, in every word!
So the declaration above would be:
LATFCLR = BIT12_MASK
Where is the harm? It’s a simple pilot’s rule: “Everything that has to be repeated more than once (by a human) is an opportunity for a mistake”. We humans are simply not good at repeating things consistently. Sooner or later we get distracted and skip one… An example, this is an actual simple typo that did cost me several hours to hunt down, when I converted the hardware profile from a demo project of the new graphics library to the uMMB32 I had to change the following line of code:
#define DisplayEnable() LATBCLR = _LATB_LATB9_MASK
From addressing bit 9 of PORTB, to addressing bit 12 of PORTF, I typed :
#define DisplayEnable() LATBCLR = _LATF_LATF12_MASK
Do you see any problem?