# Jallib Device Files Users Guide

Copyright © Rob Hamerling 2008..2017. All rights reserved.

## Table of contents

1. Introduction
2. The Overall Picture
   - Device files
   - Common include file Chipdef_Jallib
   - Function include files
3. User Information
   - Sample Program
   - Naming conventions for ports and pins
     - PORTx and pins, TRISx and pin directions
     - GPIO and TRISIO
     - Nibbles
     - Alias names
     - Non memory mapped registers (NMMR)
     - Input-only pins
   - Names for function modules and peripherals
     - CCP
     - ANSEL
     - ADC
     - Data EEPROM
     - [E]USART
     - MSSP (I2C,SPI)
     - Timers
     - RTCC
     - Shadow STATUS
     - Miscellaneous
   - About Port Shadowing
   - Calibration of Internal Oscillator
   - Provisions for USB
   - Peripheral Pin Selection
   - Naming convention for configuration bit fields (fuses)
   - Data Memory and Compiler Requirements
     - Data memory
     - Memory banks
     - Shared memory
     - INTOSC calibration
     - Data memory of PICs with USB module
     - Analog modules
   - Compatibility and Miscellaneous Remarks
4. Generating device files
   - The process
   - To do with new datasheets
   - To do with a new release of MPLABX

# 1. Introduction

This document serves two purposes:

- Inform the user how to use the JalV2 device files, probably being more important for library developers than for application developers.
- Provide information for maintenance and further development of the device files.

The Jallib device files are generated by means of a Python script pic2jal.py which converts the .pic files in the MPLABX file crownking.edc.jar to .jal device files.

The advantages of automated generation of device files are pretty obvious, such as:

- creation of device files for all PICmicros available in MPLABX
- automatic new device files for new chips
- consistent layout
- consistent naming convention
- no manual maintenance of device files
- no errors due to typos with manual editing

The advantages of a consistent naming convention are also obvious:

- Easy migration of a program from one target PICmicro to another.
- Same for libraries using this naming convention.

# 2. The Overall Picture

With the design of the device files I had in mind a structure as shown below.

                       +----------+   +------------------+
                       | device   |   |     general      |
                       |  file    |---|     include      |
                       | include  |   |chipdef_jallib.jal|
                       +----------+   +------------------+
                            |
             +--------------+--------------+-------------+-----------
             |              |              |             |
       +----------+   +----------+   +----------+   +----------+
       | function |   | function |   | function |   | function |
       | include  |   | include  |   | include  |   | include  |   etc
       | 'delay'  |   |  'jal'   |   |'adc.....'|   |'pwm....' |
       +----------+   +----------+   +----------+   +----------+

The device files are now part of the central JalV2 library repository Jallib at Github, which uses the same structure.

## Device Files

The device files are the base for other include files and contain:

- An include statement for the common include file 'chipdef_jallib'
- CPU type specification (12-, 14-, enhanced 14-, or 16-bits core).
- Program memory size specification.
- Data memory (EEPROM or FLASH) location and size specification.
- Configuration memory (fuses) and ID memory location and size specification.
- A set of default fuse settings.
- Declaration of symbolic names for configuration bits (fuses).
- Declaration of Special Function Register (SFR) address and mirror adresses, alias names and bit fields.
- Specification of General Purpose Register (GPR, RAM) location range and sharing.
- Declaration of procedures and functions for shadowing of I/O ports.
- Procedures to switch all pins to digital I/O.

Including a device file doesn't change anything to the PIC. For example pins which are input after power-on or reset remain input, etc. Required changes are the responsibility of the application program or function libraries.
For user convenience every device file contains a procedure to disable all analog modules of the PIC and to change all pins which are by default analog to digital I/O: enable_digital_io(). This procedure calls on its turn procedures to disable ADC modules, comparator modules and a procedure to set analog pins to digital, all when applicable to the specific PIC.

The device file contains a set of 'default' configuration bits, see Default Configuration Bits Setting for more information!

## Common Include File 'chipdef_jallib.jal'

The file 'chipdef_jallib.jal' which comes with these device files replaces the file 'chipdef.jal' which comes with the compiler distribution. It is included by every device file and contains:

- Constants required by the compiler.
- Commonly used constants by the device files and other libraries.

With the statement 'pragma target chip = .....' in every device file the compiler assigns a unique value to the constant 'target_chip'. The program may reference this variable with a symbolic name. This symbolic name consists of 'PIC_' followed by the type of the PIC, which makes it possible to use the same source file to generate a hex file for different types of PICs, as the following example shows:

       if (target_chip == PIC_16F88) then          -- (not for 16f87)

         ....                                      -- 16F88 unique code

       end if

This program is designed for a 16F88, but may be used for another PIC, like 16f87 (or any other). But for any other PIC than a 16F88 the block of statements between 'if' and 'end if' will be skipped by the compiler. Of course the 'if' may be followed by one or more 'elsif' blocks or an 'else' block to select specific code for other PICs.

The list of targets in chipdef_jallib.jal makes sure that every possible target name and the corresponding unique value of target_chip is known to the compiler.

Note: The original chipdef.jal file of the compiler package specifies a different value for 'target_chip' and only for a limited number of PICs. Therefore the Jallib version is included by the Jallib device files.

## Function Include Files

Function specific include files offer facilities to ease the use of PIC peripherals (such as USART, ADC), external devices (such as LCDs, sensors), or extensions to the Jal language such as for data formatting, mathematical functions, etc.
These function-oriented libraries should be included explicitly as required by the application program. This is not done by device files!

In most cases these function libraries require some statements to couple function specific registers and pins with the device. Read the comments in the library sources and the library documentation for instructions. Most libraries contain comments with user instructions in the header of include files and just ahead of the procedures and functions in these files.

# 3. User Information

We'll start with a very elementary sample program (blink-a-led) to show how device files make programming in JAL a piece of cake, followed by a description of other features of the device files which are aimed at writing device independent libraries.

## Sample program

The device files define static device (PICmicro) specific matter. This allows writing elementary programs, such as for a blinking led, which are almost device independent. Differences are mostly in the fuse settings (configuration words).

The device files are also the base for extensions, such as libraries for more complicated functions like displaying text on an LCD or handling analog devices.

Below a simple blink-a-led program (led on pin 1 of port A) for a PIC16F886 using a 20 MHz resonator. In addition to the device-specific information obtained from the include file '16f886.jal' some run-time information is needed, like the speed and type of the oscillator and some other 'environmental' variables. No extra function libraries are required.

    -- ------ blink-a-led on pin_A1 of a PIC16F886 --------

       include 16f886                        -- target is a PIC16F886
                                             -- Notes: - The extension .jal is
                                             --          added by the compiler!
                                             --        - No other includes needed.

       pragma target clock  20_000_000       -- oscillator frequency (in Hz)
                                             -- required for delays

       pragma target OSC    HS               -- high speed external oscillator
       pragma target WDT    Disabled         -- watchdog off
       pragma target MCLR   External         -- external chip reset
       pragma target LVP    Disabled         -- no low voltage programming

       enable_digital_io()                   -- set all pins to digital I/O

       alias  led           is pin_A1        -- declare alias for pin_A1
       alias  led_direction is pin_A1_direction   -- and for its direction

       led_direction = OUTPUT                -- make led-pin output
       forever loop                          -- endless loop
          led = ON                           -- light
          _usec_delay(250000)                -- spin 1/4 seconds
          led = OFF                          -- dark
          _usec_delay(250000)                -- spin 1/4 seconds
       end loop

When loaded in a 16F886 with 20 MHz resonator or crystal a led connected (with series resistor!) to pin 3 (pin_A1, RA1) should blink twice a second.

## Naming conventions for Ports and Pins

Unfortunately Microchip is not particularly consistent in its choice of names! The datasheets and the various informational files of MPLABX do not infrequently use different names for the same entity! Since the device files have been generated from the MPLABX information files, it is possible that some names may not be the same as in the datasheet. As a rule the device files use the names as used by the datasheets (but no rule is without exception!).

For all registers of the PIC a name is declared and where appropriate also the individual bits or groups of bits are declared.
Subfields of registers have the name of the register as prefix, like

       var volatile bit  INTCON_GIE  at INTCON : 7

Sometimes aliases are declared for easy migration or conversion of existing JalV2 libraries and programs to the Jallib environment.

To be able to develop libraries which can be used for different PICs, a consistent naming is required: normalization. The following sections describe the details.

### PORTx and pins, TRISx and pin directions

For all ports and port pins a device independent alias is declared and a similar direction declaration, as the following examples show:

       var  volatile  byte  PORTA            at  <addr>
       var  volatile  byte  TRISA            at  <addr>
       alias                PORTA_direction  is  TRISA
       var  volatile  bit   pin_A0           at  PORTA : 0
       alias                pin_A0_direction at  TRISA : 0

etc. (for all other existing pins and ports).

### GPIO and TRISIO (with the smaller chips)

Although the smaller PICs have no 'official' PORTA and TRISA registers, the device files contain the necessary aliases. So even with the smaller PICs you can use the names PORTA, pin_A0, pin_A0_direction, etc.

       var  volatile  byte  GPIO             at { <addr> }
       alias                PORTA            is GPIO

       var  volatile  byte  TRISIO           at { <addr> }
       alias                TRISA            is TRISIO
       alias                PORTA_direction  is TRISIO

       var  volatile  bit   GPIO_GP0         at GPIO : 0
       var  volatile  bit   pin_A0           at GPIO : 0

       var  volatile  bit   TRISIO_TRISIO0   at TRISIO : 0
       alias                pin_A0_direction is TRISIO_TRISIO0

etc. (for all other existing pins)

Pins which can be input-only may have no corresponding _direction variable, for example pin_E3_direction of the 18F4550 may not be declared.

In MPLABX some of the 12F-PICs have PORTB and TRISB registers, but the datasheets of these PICs may mention GPIO and TRISIO! The Jallib device files will contain replacements or aliases, and declare the only(!) port as PORTA and its pins as pin_A0 etc., the direction setting as PORTA_direction and the pins as pin_A0_direction, etc.

### Nibbles

Because the upper and lower 4 bits ('nibble') of a port are frequently used as a unit - for example as data lines for LCDs - these are declared as (pseudo) variables.

       PORTx_low               - bits 0..3    (low order bits)
       PORTx_high              - bits 4..7    (high order bits)
       PORTx_low_direction
       PORTx_high_direction

This allows nibbles to be used as a regular variables.
The value for both PORTx_low and PORTx_high is passed in the lower nibble (bits 3..0) of a constant or variable, both with reading from and writing to the nibble. For example:

        PORTA_high   = 0b0101            -- write only uper nibble
        var byte nib = PORTA_high        -- read from upper nibble

Nibbles can also be used to set pin directions by 4 at a time:

       PORTA_low_direction = ALL_OUTPUT  -- direction of upper nibble
                                         -- remains unchanged

Several function libraries in the Jallib collection use this facility.

Note: Nibbles are always declared even when the register doesn't have the nibble fully populated, or even not populated at all! For example: several PICs have only the upper 4 bits of PORTB, nevertheless the device files may declare PORTB_low.

### Alias names

When a pin is multiplexed (has a different function depending on control registers or configuration bit settings), aliases are declared to make the pin accessible by more functional names. For example: of the 16F88 pin_B6 is usable as analog input for the ADC module as channel 5 and therefore pin_B6 has been given an alias name pin_AN5. You can find the 'AN5' name with the pin layout pictures and tables in the datasheet.
Of course also for the pin_B6_direction an alias is declared and similarly called pin_AN5_direction!
Libraries - in this case the ADC libraries - should use the alias names in stead of the physical pin names. Reason for this is that another PIC may have pin_AN5 associated with a different physical pin, but by using the alias name the ADC library becomes independent of the physical pin configuration which makes the library to a large extent device independent.

If you want to use another name for a port, nibble or individual pin you can also specify an alias in your program. For example when you have a red led connected to pin 0 of PortA, you could specify:

       alias  led_red  is  pin_A0

and use 'led_red = ON' or 'led_red = OFF' assignments in your program.

Pin aliases in the device files are declared in this way and therefore also make use of the port shadowing provided by the device files. This way of aliasing - using the keyword 'alias' - is only available since JalV2 compiler version 2.4n.

You should avoid direct pin and I/O port manipulation, because it will be overruled by the automatic shadowing mechanism (see the chapter about About Port Shadowing). For example do not specify:

       var bit led_red at portA : 0

With this specification a 'led_red = on' will have the desired result, but it will not update the shadow register. Any next operation which uses the shadowing mechanism will override the previous direct control operation.

Some pin alias names as found in the datasheets are not acceptable for the JalV2 compiler, in which case a special name is used. For example PICs with USB support have a D+ and D- pin. These are declared (e.g. for the 18F45K50) as:

       alias  pin_D_POS     is  pin_C5
       alias  pin_D_NEG     is  pin_C4

Some function pins can be on one or another pin of a PIC, controlled by a register or a configuration bit setting. In these cases the name has to be suffixed to prevent duplicate names. For example the 16F737 can have the CCP2 bit on pin_B3 or pin_C1, controlled by a configuration bit (fuse_def CCP2MUX).

       alias  pin_CCP2_RB3  is  pin_B3
       alias  pin_CCP2_RC1  is  pin_C1

The program or library has to detect the actual use of the CCP2 pin.

Some high-end 18Fs have an even more complex multiplexing mode. With the 18F8310 for example the multiplexing depends also on the processor mode. One position of CCP2 is pin_C1, the alternate pin is pin_E7 (in Microcontroller mode) or pin_B3 (in Microprocessor, Extended Microcontroller and Microcontroller with Boot Block modes). This variant is not always available in the device files!

### Non-memory-mapped registers

In addition to or in stead of normal (memory mapped) Special Function Registers (SFRs) some PICs have Non Memory Mapped Registers (NMMRs). It requires a special action or the setting of a flag or a bit pattern in another register to read or write these registers. For example:

- The 12-bit core PICs like 10Fs, 12F5xx have no memory mapped TRISx registers. In stead these PICs have a TRIS instruction to set the direction of ports or pins. This would make it impossible to use statements like: 'PORTA_direction = ALL_OUTPUT'
- Some midrange PICs like 16f690, 16f887 have a register SSPMSK which has the same memory address as the SSPADD register. Which of both is accessed depends on the bit pattern in SSPCON_SSPM.
- Some PICs of the 18F series have several SFR pairs of which both registers have the same address. For example of the 18F65J50 ADCON0 and ANCON1 have both address FC2h. The WDTCON_ADSHR bit determines which of a pair is accessed.
- Some 18Fs, like the 18f44j11, have registers PMADDL/H with the same address as PMOUTL/H. Which of both is accessed depends on the mode of operation.

For all these situations the device files contain pseudo variables to make it possible to use the 'Non Memory Mapped Registers' as if these were normal 'Special Function Registers', for both read and write. For example:

- Even though a 16F509 has no addressable TRISA register, you can still specify: 'pin_A5_direction = output' to make pin_A5 (alias of pin_GP5) an output pin.
- For PICs of which SSPMSK has the same address as SSPADD: when accessing register SSPMSK the bits of SSPCON_SSPM will be temporary set automatically to 0b1001 and restored afterwards.
- For PICs of which ANCON1 has the same address as ADCON0: when register ANCON1 is accessed the WDTCON_ADSHR bit will be temporary set automatically and reset afterwards.
- In case of PICs like the 18f44j11 the PMOUTL/H registers are declared as normal SFRs, because either PMADDL/H or PMOUTL/H are used exclusively in different modes of operation.

### Input-only pins

The Jallib device files of the 18F-series and the extended midrange families have their pins declared as 'expansion' of the LATx registers, even when the pin is input-only and the corresponding bit in the LATx register would not be active. But when PORTx has just input-only pins the LATx register is not required and may not be present (in the MPLABX .pic file). And when LATx is absent the pins of PORTx cannot be declared as expansion of the LATx register! One such a situation is known and a solution is provided.

Several PICs of the 18F-series and the extended midrange families have their MCLR pin multiplexed with pin_A3, pin_A5 or pin_E3. This pin is useable as input-only pin when MCLR is set to 'internal' via a configuration bit setting. In these cases pin_A3, pin_A5 and pin_E3 are declared under the PORTA/E in stead of under the LATA/E register. When the MCLR pin is the only active pin of PORTE the LATE register is frequently not present!

Note: For an input-only pin the corresponding bit in the TRISx register may be inactive, or the TRISx register may even be absent. In that case the Jallib device files will not contain a declaration of the corresponding pin-direction.

## Names of functions modules

### Names for registers and subfields of CCP modules

There are CCP modules and Enhanced CCP modules. The first is also called 'legacy' CPP modules in this document and elsewhere. Most legacy CCP modules have registers names starting with CCP, most registers of enhanced CCP modules start with ECCP. The same is true for subfields of these registers. However there are many deviations from these rules and contradictions between MPLABX .pic files and the datasheets!

Enhanced CCP modules can be used as legacy CCP modules, in particular for PWM operations. For this purpose a number aliases are added to the device files which allow access of enhanced CCP registers and subfields with legacy names. An example of this is the pwm_hardware library.

The following aliases for enhanced CCP modules are declared:

field | alias | remarks
--- | --- | ---
ECCPxCON | CCPxCON | x in range 1..10
ECCPxCON_EDCxB | CCPxCON_DCxB | bits*2
ECCPxCON_ECCPxM | CCPxCON_CCPxM | bits*4
ECCPRx | CCPRx |
ECCPRxH | CCPRxH |
ECCPRxL | CCPRxL |

Extended midrange PICs (12/16F18/19xx) have only enhanced CCP modules which have 'legacy' names. Therefore no special naming is needed to use these as legacy CCP modules.

For PICs with both an CCP1CON and a ECCP1CON register (18f448,4480,458,4580,4585,4680,4682,4685) to allow the enhanced CCP module to be used as second legacy CCP module the following aliases are declared:

field | alias | remarks
--- | --- | ---
ECCP1CON | CCP2CON |
ECCP1CON_EDC1B | CCP2CON_DC2B |
ECCP1CON_ECCP1M | CCP2CON_CCP2M |
ECCPR1 | CCPR2 |
ECCPR1H | CCPR2H |
ECCPR1L | CCPR2L |

Corresponding pins when called ECCP1 have an alias CCP1.

Some PICs (16F91x,946, 18F2321,2480,2580,4321,4480,4580) have the CCPxCON 2-bits subfield DCxB defined as 2 separate bits CCPxX and CCPxY, other PICs (16F88x) have this field enumerated and defined as DCxB1 and DCxB0. For compatibility with most other PICs a 2 bits field CCPxCON_DCxB has been added in the device files for these cases.

### Names of ANSEL bits

For the control of the ADC channel the ADC library has to set the appropriate pin(s) to analog (input). There are generally 3 methods used by the different PICs:

- with the PCFG field of the ADCON1 register
- with the PCFG bits in ANCONx registers
- with bits of the ANSELx register(s)

The first two methods as covered by the ADC libraries, this section is about the third method with ANSEL register(s). There are a couple of issues with this method:

- Pins with analog capability are not evenly and sequentially distributed over the ports. Sometimes channel numbers are not present and the numbering in the PORT register is sometimes 'chaotic'.
- There is no direct relation between the number of the analog channel (pin_ANx, x in the range 0..28) and the bit in the ANSEL register with which the channel is controlled. And the ANSEL registers are not uniformly named (e.g. the first register can be ANSEL, ANSEL0, ANSELA, the second can be ANSELH, ANSEL1, ANSELB, etc.).

The first item is no problem when always referring to the logical pin name pin_ANx (an alias of the physical pin name). A solution for the second item has been found by declaring aliases for the channel selection bits in ANSEL registers (normalization of names). In stead of enumerating the bits of all ANSELx registers individually, a number of bit aliases 'JANSEL_ANSx' is declared, in which 'x' represents the ADC channel, which points to the appropriate AN-pin.
For example the declaration of the JANSEL bits of a 16F722 looks like:

       var volatile byte   ANSELA           at { 0x185 }
       var volatile bit*6  ANSELA_ANSA      at ANSELA : 0
       var volatile bit    ANSELA_ANSA0     at ANSELA : 0
       alias               JANSEL_ANS0      is ANSELA_ANSA0
       var volatile bit    ANSELA_ANSA1     at ANSELA : 1
       alias               JANSEL_ANS1      is ANSELA_ANSA1
       var volatile bit    ANSELA_ANSA2     at ANSELA : 2
       alias               JANSEL_ANS2      is ANSELA_ANSA2
       var volatile bit    ANSELA_ANSA3     at ANSELA : 3
       alias               JANSEL_ANS3      is ANSELA_ANSA3
       var volatile bit    ANSELA_ANSA4     at ANSELA : 4
       var volatile bit    ANSELA_ANSA5     at ANSELA : 5
       alias               JANSEL_ANS4      is ANSELA_ANSA5
       --
       var volatile byte   ANSELB           at { 0x186 }
       var volatile bit*6  ANSELB_ANSB      at ANSELB : 0
       var volatile bit    ANSELB_ANSB0     at ANSELB : 0
       alias               JANSEL_ANS12     is ANSELB_ANSB0
       var volatile bit    ANSELB_ANSB1     at ANSELB : 1
       alias               JANSEL_ANS10     is ANSELB_ANSB1
       var volatile bit    ANSELB_ANSB2     at ANSELB : 2
       alias               JANSEL_ANS8      is ANSELB_ANSB2
       var volatile bit    ANSELB_ANSB3     at ANSELB : 3
       alias               JANSEL_ANS9      is ANSELB_ANSB3
       var volatile bit    ANSELB_ANSB4     at ANSELB : 4
       alias               JANSEL_ANS11     is ANSELB_ANSB4
       var volatile bit    ANSELB_ANSB5     at ANSELB : 5
       alias               JANSEL_ANS13     is ANSELB_ANSB5

As you can see the JANSEL_ANSx numbering is not restricted to bits 0..7 of the first ANSEL register (or whatever its name is), it is also used for channel numbers higher than 7 controlled by another ANSEL register. Note further in the example above that:

- channels 0..3 are regularly sequenced on pin_A0..3
- channel 4 is on pin_A5 (pin_A4 is not an ADC pin)
- channels 5..7 are missing
- channels 8..13 are irregularly sequenced on pin_B0..5

Other PICs, like for example the 18F43K22, have 28 ADC channels spread over 5 ANSEL registers, also largely irregularly numbered. For example pin_AN5..7 are controlled by ANSELE. The declaration of JANSEL_ANS0..27 hides all these irregularities for the ADC library.

Another example, now for the 10F222:

       var volatile byte   ADCON0           at  { 0x7 }
                           ...
       var volatile bit*2  ADCON0_ANS       at ADCON0 : 6
                           ...
       var volatile bit    ADCON0_ANS0      at ADCON0 : 6
       alias               JANSEL_ANS0      is ADCON0_ANS0
       var volatile bit    ADCON0_ANS1      at ADCON0 : 7
       alias               JANSEL_ANS1      is ADCON0_ANS1

In this case the channel selection bits are in register ADCON0 (the 10Fs have no ANSEL register), but the ADC library doesn't need to know when it uses the JANSEL_ANSx alias.
Note: in reality the channel selection of the 10F220/222 is somewhat more complicated, but the ADC library takes care of that!.

### Names of other ADC registers and subfields

Names of registers and subfields of ADC modules have been normalized as follows:

When the ADCONx_VCFG subfield is a multi-bit field it is declared both as a multi-bit field ADCONx_VCFG and as enumerated bits (ADCONx_VCFG0 and ADCONx_VCFG1). Same for ADCONx_PVCFG and ADCONx_NVCFG.

While most PICs with more than 8 ADC channels have a 4-bits or 5-bits subfield ADCONx_CHS, some PICs have the channel selection bits scattered over more than 1 subfield. For example the 16F7x7s have a 3-bits CHS field plus a single CHS3 bit to be able to support ADC channel 8 and up. In this and similar cases a pseudo variable ADCONx_CHS has been declared which takes care of the scattering of channel selection bits. So an ADC library can always address the variable ADCONx_CHS as multibit 'binary' field, regardless if the bits are scattered over the register or not.

A similar situation exists for the ADCS bits of ADCONx of some PICs. For PICs which have their ADCS bits scattered over ADCON0 and ADCON1 a pseudo-variable ADCON0_ADCS is added which takes care of setting the proper bits. In this way an ADC library can always address the variable ADCONx_ADCS as single multibit field, regardless if the bits are scattered over registers or not and regardless if it is a bit*2 or a bit*3 variable.

The result of an Analog to Digital Conversion can be 8, 10 or 12 bits. When a PIC supports only 8-bits ADC the result is always a byte: ADRES. With higher resolutions 2 bytes are used: the high order bits are always in ADRESH, the low order bits can be in ADRESL.
Note: when both ADRESL and ADRES are present ADRES is a 16 bits variable.

### Names of EEPROM control registers

Some elementary differences have to be taken into acount with respect to reading and writing memory:

- The unit of information of data memory (EEPROM) is always a byte for all PICs, while for program memory it is a word: 12, 14 or 16 bits, depending on the PIC type.
- The 18Fs have always byte-level access for both data and program memory. The baseline and midrange have byte level access for data memory access, but program memory is on word level.

### Names of registers and subfields of [E]USART modules

PICs can have zero, one or two USART modules, of which zero, one or both can be 'extended' (EUSART) modules. Compared to a 'legacy' USART an 'extended' USART has a BAUDCON register and can use a 16 bits in stead of an 8-bits value for the baudrate divisor, allowing a more accurate baudrate setting, especially with high speeds.

The names of USART related registers and -subfields are not particular consistent in the MPLABX .pic files, so it is desired to normalize these. And it would be convenient if serial libraries supporting a single serial module could be used for the first USART of PICs with multiple USARTs. These are the primary reasons for the following naming convention in the Jallib device files:

- for PICs with 1 USART:
  - no module number in the names
- for PICS with 2 USARTs:
  - first USART: Names without module number
  - second USART: Names with suffix '2'

The registers will be declared in the device files with their native name as obtained from the MPLABX .pic files. When the native name doesn't follow our convention an alias will be added.

Application of these rules results in the following list of names:

only or first of 2 USARTs | second of 2 USARTs
--- | ---
BAUDCON | BAUDCON2
IPR1_RCIP | IPR3_RCIP2
IPR1_TXIP | IPR3_TXIP2
PIE1_RCIE | PIE3_RCIE2 or PIE4_PCIE2
PIE1_TXIE | PIE3_TXIE2 or PIE4_TXIE2
PIR1_RCIF | PIR3_RCIF2 or PIR4_RCIF2
PIR1_TXIF | PIR3_TXIF2 or PIR4_TXIF2
RCREG | RCREG2
RCSTA | RCSTA2
SPBRGL (byte) | SPBRGL2 (byte)
SPBRGH (byte) | SPBRGH2 (byte)
TXREG | TXREG2
TXSTA | TXSTA2

Notes:

- BAUDCON and SPBGRH registers are only available with extended USARTs.
- Some PICs have a BAUDCTL register in stead of BAUDCON. In that case the device files have an additional alias: BAUDCON, and the bit fields of BAUDCTL have a BAUDCON alias too.
- There is no standard (yet) for PICs with more than 2 USARTs.

Serial libraries should follow these conventions.

### Names of MSSP registers

Like multiple USARTs, PICs can have multiple MSSP modules (for SPI, I2C). For these modules a similar naming convention is used as for USART modules. For the only or first module names without a module number will be used, while for the second module the names will have a number '2'. In this case the module number follows immediately the 'SSP' of the name because there can be multiple OSCCON registers, which could cause confusion.

The registers will be declared in the device files with their native name as obtained from the MPLABX .pic files. when the native name doesn't follow our convention an alias will be added.

Application of these rules results in the following list of names:

Only or first of 2 MSSP | second of 2 MSSPs
--- | ---
IPR1_SSPIP | IPR2_SSP2IP or IPR3_SSP2IP
PIE1_SSPIE | PIE2_SSP2IE or PIE3_SSP2IE
PIR1_SSPIF | PIR2_SSP2IF or PIR3_SSP2IF
SSPADD | SSP2ADD
SSPBUF | SSP2BUF
SSPCON1 | SSP2CON1
SSPCON2 | SSP2CON2
SSPCON3 | SSP2CON3
SSPMSK | SSP2MSK
SSPSTAT | SSP2STAT

For the pins related to I2C and SPI the names have no suffix for the first or only module and a '2' suffix for the second module.

Only or first of 2 MSSP | second of 2 MSSPs
--- | ---
pin_SDA | pin_SDA2
pin_SDI | pin_SDI2
pin_SDO | pin_SDO2
pin_SCK | pin_SCK2
pin_SCL | pin_SCL2
pin_SDA_direction | pin_SDA2_direction
pin_SDI_direction | pin_SDI2_direction
pin_SDO_direction | pin_SDO2_direction
pin_SCK_direction | pin_SCK2_direction
pin_SCL_direction | pin_SCL2_direction

### Names of Timer fields

Some register subfields of timer control registers have inconsistent names in the MPLABX .pic files.

For these subfields the following naming convention has been chosen:

- The interrupt bits of Timer 0 are declared as TMR0IE and TMR0IF for all PICs, even though some datasheets use the names T0IE and T0IF.
- For 16-bits timers pseudo variables are declared for writing and reading the timer in the preferred sequence: first TMRxH then TMRxL.
- For TxSYNC in TxCON registers an alias NTxSYNC is defined and vice versa. Both aliases are added for any other TxCON_??SYNC bit.
- For CS in TxCON registers an alias TMR3CS is defined.
- For CKPS in TxCON registers an alias T3CKPS is defined.
- TxCON_TOUTPS is normalized to TxCON_TxOUTPS (x = timer number) for the 18Fs. Since the midrange PICs have only 1 timer with TOUTPS bit this name has been maintained for these PICs. Extended midrange PICs have T2CON, T4CON and T6CON and follow the same naming convention.
- A variable 'bit*4 PS' in T0CON is splitted in 'bit PSA' and 'bit*3 PS'
- Aliases are provided for Timer 0 related fields in OPTION_REG of baseline and midrange PICS to simulate the existence of a T0CON register - like there are T0CON, T1CON, T2CON, etc. registers with other PICs: T0CON_T0SE, T0CON_T0CS, T0CON_PSA and T0CON_T0PS.
- The extended midrange PICs have in OPTION_REG the bits TMR0CS1 and TMR0CS0 and a 2-bits prescaler TMR0PS. These have been given aliases bit*2 T0CON_T0CS and bit*2 T0CON_T0PS to be as much compatible as possible with the other midrange PICs.

### Names of RTCC registers

For consistency with the ALRMCFG register and since the RTCPTR1 - and RTCPTR0 bits of the RTCCFG register could be used as 2-bits binary field - an additional field is declared:

      var volatile  bit*2  RTCCFG_RTCPTR     at RTCCFG : 0

Same for the RTSECSEL1 and RTSECSEL0 bits of PADCFG1:

      var volatile  bit*2  PADCFG1_RTSECSEL  at PADCFG1 : 1

For consistency the 2-bits ALRMCFG_ALRMPRT field has been enumerated:

      var volatile  bit    ALRMCFG_ALRMPTR1  at ALRMCFG : 1
      var volatile  bit    ALRMCFG_ALRMPTR0  at ALRMCFG : 0

### Subfields of STATUS_SHAD

The shadow of the STATUS register (in the extended midrange PICs) has its bits named like in the STATUS register:

      STATUS_SHAD_Z
      STATUS_SHAD_DC
      STATUS_SHAD_C

### Miscellaneous remarks about names

- The name PORTA (and a similar name for other ports) is used consistently, while previously PORT_A was a popular naming convention especially for PORT_A_low, PORT_A_high, PORT_A_direction, etc.
- For individual pins the convention 'pin_Ax' is used.
- Numerous minor naming inconsistences in the MPLABX .pic files are 'corrected'.

When you hit compilation errors related to undefined names, scan the device file of the specified target PIC to search for the Jallib name of the registers and their subfields.

## About Port Shadowing

Port shadowing is a technique to prevent the Read-Modify-Write ('RMW') problem with I/O ports of PICmicro's. This is a problem related to the hardware design. Search the Internet for "PIC" and "read-modify-read" and you'll get many hits to more or less interesting articles! None of the explanations are repeated here. And you don't absolutely need to understand the problem, since by using the Jallib device files you won't face the problem when you follow some simple rules and avoid a few pitfalls.

With port shadowing for the baseline and midrange PICs (10F, 12F, 16F) a byte variable is used as representative of the port register, for output only. This byte is frequently called 'shadow-register'. When writing to a port or individual pin first the shadow register is updated and then the whole byte is written to the port.

The shadow registers are not declared as 'volatile', because the shadowing procedures would occupy significantly more program memory. The disadvantage of not declaring these as volatile is that the procedures for shadowing are not re-entrant (not interrupt-proof). This means that you should refrain from updating pins from both the mainline and an interrupt routine.

The 18F series and the newer extended midrange (XLP) PICs have a special register for this purpose (LATx), and the device files use these registers for output.

In all cases reading is done from the port register itself!

With the Jallib device files shadowing is automatic, as long as you use the following names:

       PORTx             -- all bits of port x
       PORTx_low         -- low order nibble of port x (bits 3..0)
       PORTx_high        -- high order nibble of port x (bits 7..4)
       pin_xy            -- single pin 'y' of port 'x'
       aliases of pin_xy

(in which 'x' is a port-letter and 'y' a bit number).

PORTx_low is read from or written to bits 3..0 of Portx, PORTx_high is read from or written to bits 7..4 of Portx.

At power on and reset all ports are in input mode. It is recommended to initialise ports or individual pins before switching these from input to output mode.

## Calibration of Internal Oscillator

Some low end PICs have an uncalibrated internal oscillator, but have been factory calibrated and contain the proper value for OSCCAL in the highest word of code memory. User programs can use it to calibrate the internal oscillator. See also INTOSC calibration

PIC programmers are supposed to preserve this high memory word. When it has (accidentally) been erased or overwritten the factory provided calibration value for OSCCAL is lost. Not only that, due to the way this value is supposed to be loaded this may lead to unpredictable behaviour of the PIC.

### Baseline

A number of baseline PICs (10F2xx, several 12F5xx and 16F5xx) have in their highest word of code memory a MOVLW instruction. This instruction is executed automatically after a reset of the PIC and thus the W register is loaded with the desired contents of OSCCAL at power-on or after MCLR reset. This may be ignored, but when your PIC application needs the frequency of the internal oscillator to be accurate the OSCCAL register should be loaded with the provided value. For this a MOVWF OSCCAL instruction is required as first instruction of the program, for example with:

       asm  bank  movwf  0x5            -- store contents of W in OSCCAL

Strictly speaking this needs not be the first instruction. It may be preceded by other instructions as long as these do not modify the W register!

The compiler does not have an option to insert this instruction, but the device files of these PICs do have the required instruction. This has been introduced with revision 3185.

The instructions (possibly including bank selection instructions) are located in the beginning of the device file to ensure that no other instructions destroy the contents of the W register, for example for the initialization of shadow registers. Of course the user program should not have any instructions before the include of the device file!

### Midrange

Some midrange PICs (12F629/675, 16F630/676) have in their highest word of code memory a RETLW instruction. This allows the following method to be used to load OSCCAL with the proper value.

       asm  page  call   <last-word-of-memory>
       asm  bank  movwf  0x90     -- store contents of W in OSCCAL

in which you have to specify for <last-word-of-memory> the address of the highest word in program memory. For example when your PIC has 1K words of program memory you should specify:

       asm  page  call   0x3FF

These instructions may be inserted anywhere in your program. It is not required to have these as very first instructions like with the baseline PICs.

This method is not without danger! When the high memory word is (accidentally) erased or overwritten most likely it will not contain a RETLW instruction. In that case the next instruction will be fetched, which is at address 0x0000 because of program counter wrap around. Thus the PIC will probably enter an endless reset loop. For this reason the device files of these PICs do not calibrate the internal oscillator. You could insert the asm instructions above in your program at your own risc!

When you are not sure about the contents of the high word of code memory or you want to play it safe, you can move a 'medium' value directly into OSCCAL, for example with:

       OSCCAL = 0x80

See the datasheet for acceptable values: frequently the low order bits must be zero.

By varying the value in OSCCAL and measuring the effect you can also fine tune the oscillator frequency for this specific PIC. Other PICs of the same type and revision may need another value!

## Provisions for USB

When the USB module of a PIC is activated, memory for data buffers is needed. For some PICs the address and size of data buffers is fixed, other PICs offer more freedom. The USB data buffers are specified in the Buffer Descriptor Table (BDT). This BDT is at a fixed location in RAM but not the same for all PICs. To help the USB library with finding the actual location of the BDT for a specific PIC a constant USB_BDT_ADDRESS is defined indicating the address of the Buffer Descriptor Table.

## Peripheral Pin Selection

A number of newer enhanced midranges PICs and several PICs in the 18F series have a feature called Peripheral Pin Selection (in short PPS). This allows the selection of specific pins for input and/or output of peripheral modules.

Pin selection for an input function is controlled by loading a pin number in a specific register.

Pin selection for an output function is controlled by loading a function number in a specific register.

When a peripheral pin is bidirectional both the input and the output must be mapped to the same pin!

### PPS groups

There are many similarities and some differences between PICs. Currently we distinguish 5 groups of PICs with PPS module (in the MPLABX called 'PPS flavors').

Groups 1 and 2 are very alike, the differences are in values for output function (described below).

Group 3 is a collection of some high-end PICs with PPS facility.

Groups 4 and 5 are very alike, but differ from groups 1 and 2 in the way the pins are mapped.

To facilitate the use of the PPS feature especially to build a library every device file declares a constant 'PPS_GROUP' with the appropriate group number. A symbolic name of the format 'PPS_x' is used, in which x is in the range 0 to 5. These symbolic names are defined in constants_jallib.jal.

### PPS_0

This group of PICs does not support Peripheral Pin Selection. Most PICs in this group, especially the 'classic' PICs have a fixed pin functionality. However several newer PICs have a limited way of pin mapping. This can be with a configuration bit setting, or with 'APFCON' (Alternate Pin Function CONtrol). These methods are PIC-specific. See the appropriate datasheet for instructions on how to use these types of pin mapping.

### PPS_1 and PPS_2

Pins supported by PPS have a 'RP' (Remappable Pin) alias. For example pin_B7 of the 18F26J50 has an alias pin_RP10.

Examples of pin mapping for these groups are:

- To map pin_RP10 to the transmit lead of ESUART2 the function number of TX2/DT2 (number 5 for an 18F26J50) to RPOR10_RPOR. Unfortunately not all function numbers are the same for all PICs. For example the TX2/DT2 function has number 6 with the 18F27J53. This issue is solved by the PPS library by defining of symbolic names to the function like in this case PPS_TX2.
- To map the receive lead of ESUART2 to a specific pin by putting the pin number in RPINR16_RX2DT2 (x of pin_RPx). The control registers for all functions are the same for all PICs and the PPS library contains symbolic names for remappable pins. Differences between PICs are only in the number of remappable pins.

Function numbers for PPS_GROUPs 1 and 2
Func. | Group 1 | Group 2 |
--- | --- | --- | ---
0 | NULL | NULL |
1 | C1OUT | C1OUT |
2 | C2OUT | C2OUT |
3 |  | C3OUT |
4 |  |  |
5 | TX2/CK2 |  |
6 | DT2 | TX2/CK2 |
7 |  | DT2 |
8 |  |  |
9 | SDO2 |  |
10 | SCK2 | SDO2 |
11 |  | SCK2 |
12 | SSDMA | SSDMA |
13 | ULPOUT | ULPOUT |
14 | CCP1/P1A | CCP1/P1A |
15 | P1B | P1B |
16 | P1C | P1C |
17 | P1D | P1D |
18 | CCP2/P2A | CCP2/P2A |
19 | P2B | P2B |
20 | P2C | P2C |
21 | P2D | P2D |
22 |  | CCP3/P3A |
23 |  | P3B |
24 |  | P3C |
25 |  | P3D |

### PPS_3

This group is not supported by Jallib (yet) and therefore not further covered here.

### PPS_4 and PPS_5

For PPS groups 4 and 5 the way pins and functions are controlled is similar to that of groups 1 and 2, but better structured. The datasheets describe pretty well how this works.

For these groups the device files contain symbolic names of the pins in the format PPS_Rxy (x is port letter, y is pin number). These names are valid for all PICs in these two groups and are defined in the library.

The function names for pins are in the same format as of groups 1 and 2: PPS_<function>. These names are PIC specific and defined in the device files.

## Naming convention for configuration bit fields (fuses)

### Pragma fuse_def

The MPLABX .pic files contain a keyword for every configuration bit or group of bits, and a description of the possible bit settings. Unfortunately not always the same keyword is used for essentially the same configuration bit or bit-field, and the keyword is sometimes different from the keyword in the datasheet, or is simply spelled wrongly! The descriptions have an even larger variation and are sometimes very long.

For use with Jal, in particular for the 'pragma fuse_def' declarations, a consistent keyword (in JalV2 called 'opt') and single-word symbolic values (in JalV2 called 'tag') are desired. The Jallib 'standard' is described below.

### Fuse_def keywords, synonyms and replaced words

For all pragma fuse_defs a keyword and a number of symbolic values are declared in the device files. This section deals with the keywords, the next section with symbolic values.

Every configuration word or byte is preceeded with a comment line indicating its address in memory.
The meaning of configuration bits can in most cases be found in the DataSheet of the specific chip, in the section 'Special Features of the CPU'. This info can also be found in the Programming Specifications of the chip. For convenience the MicroChip document numbers of the specific PIC are mentioned in the heading of its device file.

To minimize misunderstanding and confusion the description for every keyword as found in the MPLABX .pic file is appended as comment on the 'pragma fuse_def' line. The combination of memory address and description should unambiguously identify which configuration bits are controlled by the keyword, even though the name might be different from that in the datasheet.

Where convenient and intuitive enough the keywords found in the MPLABX .pic files are used. But synonyms are eliminated and some apparent misspellings are corrected. Sometimes an arbitrary keyword is chosen.

The list below shows examples of most deviations of keywords from MPLABX .pic files:

keyword | replaces synonym(s) and typo(s)
--- | ---
ABW | ADDRBW
BBSIZ | BBSIZ0
BROWNOUT | BODEN, BOREN, DSBOREN
BW | DATABW
CCP(x)MUX | CCP(x)MX
CPD | CPDF, CPSW
CPx | CP_x
DEBUG | BACKBUG, BKBUG
EBTRx | EBTR_x, EBRTx (typo)
ECCPMUX | ECCPMX
EXCLKMUX | EXCLKMX
FCMEN | FSCM
FLTAMUX | FLTAMX
OSC | FOSC, FOSC0
IOSCFS | IOFSCS (typo)
MCLR | MCLRE
MSSPMASK | MSSP7B_EN, MSSPMSK
P2BMUX | P2BMX
PMODE | PM
PMPMUX | PMPMX
PWM4MUX | PWM4MX
PWRTE | PUT, PWRT, PWRTEN, NPWRTE, NPWRTEN
RTCOSC | RTCSOSC
SDOMUX | SDOMX
SOSCSEL | SOSCEL
SSPMUX | SSPMX
STVR | STVREN
T1OSCMUX | T1OSCMX
T3CKMUX | T3CMX, T3CKMX
VOLTAGE | BODENV, BOR4V, BORV
WDT | WDTE, WDTEN
WRT | WRT_ENABLE, WRTE
WRTx | WRT_x

Notes:

1. Keywords for pin multiplexing end in 'MUX', like CPPxMUX.
2. Not all declared keywords in the MPLABX .pic files may be 'catched', there may be some inconveniently (long) keywords left.
3. When the compiler stalls over a fuse-def line a correction should be applied. If you encounter such an occasion please report it in the Jallib discussion group at Google Groups.

### fuse_def symbolic values

As mentioned above the MPLABX .pic files contain frequently long and descriptions with many variations of the same story. Only for the oscillator specification alone the MPLABX .pic files contains about 200 different descriptions! But often the description is a single word like DISABLED or ACTIVE. Multi-word descriptions have been reduced to a single word or at least a single string (multiple words coupled by underscore characters).

Like for the keywords also for the symbolic values many synonyms can be found in the MPLABX .pic files. These synonyms are eliminated to a large extent. For example 'ENABLE' is often used even when the datasheet or MPLABX .pic file specifies 'ON' or 'ACTIVE'.

Below a set of 'normalized' pragma fuse_def:

#### fuse_def ADSEL (ADC resolution)

       B10                -- 10 bits
       B12                -- 12 bits
       B..                -- other number of bits

#### fuse_def ABW (Address Bus Width)

       B8                 -- 8 bits
       B16                -- 16 bits
       B..                -- other number of bits

#### fuse_def BBSIZ (Boot Block Size)

       W256               -- 256 words
       W512               -- 512 words
       W1K                -- 1024 words (1K words)
       W2K                -- 2048 words (2K words)
       W...               -- any other number of words

#### fuse_def BG (Band Gap)

       ADJUST_NEG         -- negative adjustment
       ADJUST_POS         -- positive adjustment
       ...                -- other

#### fuse_def BROWNOUT (Brown Out detection)

       ENABLED            -- BOD enabled, SBOREN disabled
       RUNONLY            -- BOD enabled in run, disabled in sleep
       CONTROL            -- SBOREN controls BOR function
       DISABLED           -- BOD and SBOREN disabled

BROWNOUT is also used for Deep Sleep BrownOut (DSBOREN).

#### fuse_def BW (Bus Width)

       B8                 -- 8 bits
       B16                -- 16 bits
       B..                -- other number of bits

#### fuse_def CCPxMUX (multiplexing of pin of CCP module x)

       pin_xy             -- assigned to pin y of PORTx
       pin_..             -- any other
       Enabled            -- ) see datasheet
       Disabled           -- )

When the multiplexing is also dependend of the microprocessor mode (with some high end 18Fs) the pin for 'Microcontroller mode' is specified. Of course in other modes another alternate pin will actually be configured!

#### fuse_def CP (Code Protection)

       ENABLED            -- Code memory read protection on
       DISABLED           -- Code mewmory read protection off

#### fuse_def CPD (Data Code Protection)

       ENABLED            -- Data (EEPROM) memory read protection on
       DISABLED           -- Data (EEPROM) memory read protection off

#### fuse_def CPUDIV (CPU clock divisor)

Specifies the divisor value for the Primary Oscillator to obtain the desired CPU frequency.

       P1                 -- No divide *)
       P2                 -- CPU freq. is oscillator freq. divided by 2 *)
       P3                 -- CPU freq. is oscillator freq. divided by 3 *)
       P4                 -- CPU freq. is oscillator freq. divided by 4 *)

* The symbolic values P1, P2, P3 and P4 have a one-to-one relationship with the divisor value, but only when PLL is not enabled.
When the PIC has a PLL module and PLL is enabled the output of the PLL module (96 MHz) is used obtain the desired CPU frequency and the corresponding divisor values may be different! For example: when PLL is enabled with the 18f4550 P1 gives a divisor value 2, P2 divisor 3, P3 divisor 4, P4 divisor 6.
See the Oscillator chapter in the datasheet for actual values.

#### fuse_def DSWDTOSC (Watchdog oscillator selections)

       INTOSC             -- internal oscillator
       OSC                -- oscillator determined by OSC fuse_def

#### fuse_def DSWDTPS and WDTPS ([Deep Sleep] WatchDog Timer PostScaler)

       P2G                -- 1 : 2G  (2 * 1073741824)
       P...
       P2M                -- 1 : 2M  (2 * 1048576)
       P...
       P2K                -- 1 : 2K  (2 * 1024)
       P..
       P2                 -- 1 : 2

#### fuse_def EBTRB (bootblock write protection)

       ENABLED            -- boot block table read protected
       DISABLED           -- boot block may be table read

#### fuse_def ECCPxMUX (ECCP pin multiplexing)

       pin_xy             -- pin y of portx is used

#### fuse_def EMB (External memory bus width)

       B12                -- 12 bits
       B16                -- 16 bits
       B20                -- 20 bit
       DISABLED           -- disabled

#### fuse_def ETHLED (Ethernet LED)

       ENABLED            -- Ethernet LED enabled
       DISABLED           -- Ethernet LED disabled

#### fuse_def EXCLKMUX (TMR1/T5CLKI assignment)

       pin_xy             -- Clock input assigned to pin y of portx

#### fuse_def FLTAMUX (FLTA multiplexing)

       pin_xy             -- pin y of portx is used

#### fuse_def FOSC2 (default/reset system clock select)

       INTOSC             -- Internal oscillator
       OSC                -- Clock selected by OSC setting

#### fuse_def HFOFST (...)

       ENABLED            -- enable
       DISABLED           -- disabled

#### fuse_def IOSCFS (Internal Oscillator Frequency Select)

       F4MHZ              -- 4 MHz
       F8MHZ              -- 8 MHz

#### fuse_def LPT1OSC (Low Power Timer1 Oscillator)

       LOW_POWER          -- low power, low noise immunity
       HIGH_POWER         -- high power high noise immunity

#### fuse_def LVP (Low Voltage Programming)

       ENABLED            -- LVP on
       DISABLED           -- LVP off

#### fuse_def MCLR (reset)

       EXTERNAL           -- /MCLR pin enabled
       INTERNAL           -- /MCLR pin is digital I/O

#### fuse_def OSC (oscillator)

       LP                 -- Low Power crystal on OSC1,OSC2
       XT                 -- Crystal or Resonator on OSC1,OSC2
       HS                 -- High Speed Crystal or Resonator on OSC1,OSC2
       HS_PLL             -- HS with (hardware) PLL active
       EC_CLKOUT          -- External Clock (TTL) signal on OSC1, ClockOut on OSC2
       EC_NOCLKOUT        -- External Clock (TTL) signal on OSC1, OSC2 is I/O
       EC_CLKOUT_PLL      -- EC_CLKOUT with PLL active
       EC_NOCLKOUT_PLL    -- EC_NOCLKOUT with PLL active
       ECH_NOCLKOUT       -- external clock, high power mode
       ECL_NOCLKOUT       -- external clock, low power mode
       ECM_NOCLKOUT       -- external clock, medium power mode
       RC_CLKOUT          -- (external) Resistor/Capacitor oscillator on OSC1, ClockOut on OSC2
       RC_NOCLKOUT        -- (external) Resistor/Capacitor oscillator on OSC1, OSC2 is I/O
       INTOSC_CLKOUT      -- Internal oscillator, OSC1 is I/O, ClockOut on OSC2
       INTOSC_NOCLKOUT    -- Internal oscillator, OSC1 and OSC2 are I/O

The first or only part is the oscillator type, the [optional] second part indicates a related subfunction. For example it may indicate if the OSC2 pin is CLKOUT or I/O, or if PLL is active. Several other keywords are possible, for example:

- with USB
- with dual oscillator sources

The datasheet will specify the possibilities, browse the device file for the applicable keywords.

#### fuse_def PLLDIV (PLL prescaler)

       P1                 -- 1 : 1
       P..                -- etc
       P12                -- 1 : 12

#### fuse_def PLLEN (PLL enable)

       DISABLED           -- 1x
       P1                 -- 1x
       ENABLED            -- 4x
       P4                 -- 4x
       F500KHZ            -- freq 500 KHz
       F16MHZ             -- freq 16 MHz

#### fuse_def PWM4MUX (PWM4 multiplexing)

       pin_xy             -- PWM4 assigned to pin_y of portx

#### fuse_def PMODE (Extended memory bus)

       B12                 -- extended microcontroller 12-bit
       B16                 -- extended microcontroller 16-bit
       B20                 -- extended microcontroller 20-bit
       EXT                 -- extended microcontroller
       MICROCONTROLLER     -- microcontroller
       MICROPROCESSOR      -- microprocessor
       MICROPROCESSOR_BOOT -- microprocessor with boot block

#### fuse_def PMPMUX (PMP multiplexing)

       PORTx              -- PMP on PORTx and other ports

#### fuse_def PWRTE (Power-up Timer Enable)

       ENABLED            -- Power up timer enabled
       DISABLED           -- Power Up timer disabled

#### fuse_def RTCOSC (RTC reference clock selection)

       INTOSC             -- Internal oscillator
       T1OSC              -- Timer 1 oscillator

#### fuse_def SIGN (bulk erase)

       NOT_CONDUCATED
       AREA_COMPLETE

#### fuse_def SSPMUX (SPI I/O multiplexing)

       pin_xy             -- SPI active on pin y of portx
       DISABLED           -- SPI not assigned

#### fuse_def T1OSCMUX (Timer 1 multiplexing)

       pin_A6_A7          -- pin_A6 and pin_A7 are used
       pin_B2_B3          -- pin_B2 and pin_B3 are used

#### fuse_def USBDIV (USB clock selection)

       P1                 -- no divide
       P2                 -- divide by 2

#### fuse_def USBPLL (USB PLL source)

       F48MHZ             -- from 96MHZ PLL / 2
       OSC                -- from Oscillator

#### fuse_def VCAPEN (Voltage regulator capacitor pin)

       DISABLED
       pin_A0
       ...  etc (other pins which could be assigned

#### fuse_def VOLTAGE (Brown out voltage)

       V20                -- 2.0 Volt
       V27                -- 2.7 Volt
       V42                -- 4.2 Volt
       V45                -- 4.5 Volt
       ...  etc (whatever voltages are applicable)

#### fuse_def WAIT (Wait ...)

       ENABLED            -- synchronous
       DISABLED           -- asynchronous

#### fuse_def WDT (WatchDog Timer)

       ENABLED            -- Watchdog enabled
       DISABLED           -- Watchdog disabled
       CONTROL            -- Software controlled by SWDTEN bit
       RUNNING            -- Enabled while running, disabled in sleep.

#### fuse_def WDTCS (WatchDog Timer Clock Select)

       STANDARD
       LOW_POWER

#### fuse_def WPEND (Write protect area)

       P0_WPFP            -- from page 0 to write protect page
       PWPFD_END          -- from write protect page to end of memory

#### fuse_def WPFP (Write Protect Flash Page)

       P0                 -- Write protect flash page 0
       P1                 -- Write protect flash page 1
       P..                -- etc
       P127               -- Write protect flash page 127

#### fuse_def WRT (Program Memory Self-Write Protection)

       NO_PROTECTION      -- All program memory writable
       ALL_PROTECTED      -- Writing of program memory prohibited
       Rxxxx_yyyy         -- Protected memory range
                          -- (only specific ranges can be write protected)

#### fuse_def WRTx (Write Protection of Table/Region)

       ENABLED            -- table/region is not write protected
       DISABLED           -- table/region is write protected

Notes:

1. The list above in not exhaustive there may be others, depending on the features of the specific PICmicro. To conform to a compiler requirement names must start with a letter or an underscore and may not contain special characters and spaces. Multi-word descriptions as found in the MPLABX .pic files (other than those listed above) have been transformed to a keyword as follows:
   - special characters and spaces are translated to underscores
   - leading and trailing underscores are removed
   - multiple consecutive underscores are reduced to a single underscore
   - when the first character is a digit a letter is added as prefix, which can be 'R' for range, 'F' for frequency, 'B' for number of bits, or 'N' otherwise.
2. As an example of an address range specification for PICs with the possibility to protect certain code memory areas you may have to specify:

       pragma target CP R0F00_0FFF

3. The device file contains a specification for the fuses array. how many words or bytes and their corresponding memory addresses. Also a default fuse setting is specified, which may or may not be suitable for your application! Never trust defaults!

## Alternate ways to specify configuration bits

When you find the specification of multiple 'pragma target <fuse_def>' inconvenient or you want to specify the bits one-by-one by yourself, the compiler allows you to do so. For example for the PIC16F690 the following group of statements:

       pragma target OSC       HS
       pragma target WDT       Disabled
       pragma target PWRTE     Enabled
       pragma target MCLR      External
       pragma target CP        Disabled
       pragma target CPD       Disabled
       pragma target BROWNOUT  Enabled
       pragma target IESO      Disabled
       pragma target FCMEN     Disabled

is equivalent with:

       pragma target fuses   0b11_0011_1110_0010

PICs with 16-bits core (the 18F series) have such a large set and variety of configuration bits that explicit specification is probably the best way to make sure all configuration bits are set correctly for your program. As an example see the following list for a simple blink-a-led program with an 18F242.

       pragma  target fuses 0  0b0000_0000       -- (n/a)
       pragma  target fuses 1  0b0010_0010       -- not switchable, HS osc, no PLL
       pragma  target fuses 2  0b0000_0001       -- BOR disabled, PWTR disabled
       pragma  target fuses 3  0b0000_0000       -- watchdog disabled
       pragma  target fuses 4  0b0000_0000       -- (n/a)
       pragma  target fuses 5  0b0000_0001       -- CCP2 on RC1
       pragma  target fuses 6  0b1000_0001       -- no bg debug, no LVP, STVREN
       pragma  target fuses 7  0b0000_0000       -- (n/a)
       pragma  target fuses 8  0b0000_1111       -- no code protection
       pragma  target fuses 9  0b1100_0000       -- no data protection
       pragma  target fuses 10 0b0000_1111       -- no code write protection
       pragma  target fuses 11 0b1110_0000       -- no other write protection
       pragma  target fuses 12 0b0000_1111       -- no table read protection
       pragma  target fuses 13 0b0100_0000       -- no boot block write protect

(n/a) means not applicable to this specific PIC, but may be specified (as all zeroes).

Notes:

1. When a PIC has multiple configuration words or bytes the index value of the word or byte must be specified between 'fuses' and the value.

### Default Configuration Bits Settings

The device files contain both address and default settings of configuration bits. For the baseline and midrange this is in units of words of 12 or 14 bits, in most cases a single word, but with newer PICs usually multiple words. For the 18F series the configuration bits are in a (varying) number of bytes.

The specified defaults in the device files are those supposed to be found in the datasheets and in the MPLABX .pic files. Unfortunately these two sources do not always concur! The following defaults are specified in the device files:

- Baseline: 0xFFF
- Midrange and extended midrange: 0x3FFF
- 18F series derived from the MPLABX files

With a few exceptions, covered by devicespecific.json.

When your PIC programmer detects a verification error with the configuration bits, this is probably caused by a wrong default in the device file. Suspect especially the setting of 'reserved' or 'unused' bits!

## Data Memory and Compiler requirements

The compiler - at the moment of this writing version 2.4q6 - has a number of requirements for device specifications. The most important from a user perspective are the following:

### Data memory

The device files specify the amount of available data memory (RAM) for variables in bytes with pragma data.
The log of a compilation contains a line like:

     Data area: 250 of 368 used

for a specific PIC and program. The last number is the total amount of data memory available to a user program and libraries (and also the device files may 'consume' some data memory), the first number is the amount of bytes actually used.

### Data memory banks

The compiler supports for the baseline and classic midrange PICs a maximum of 4 data memory banks. PICs with more than 4 memory banks are supported, but with data memory limited to banks 0..3. Only few baseline or classic midrange PICs have more than 4 banks (example: 16f59)!

### Shared Memory

The compiler recognises another pragma for data memory: pragma shared.

For the compiler 'shared' means:

- For baseline and midrange PICs: the part of data memory which is accessible in all banks regardless the settings of the bank selection bits (STATUS_RPx, or similar bits in FSR). Note: Memory which is accessible in other bank(s) but not in all banks, is in this context not shared memory!
- For the enhanced midrange: Core registers (range 0x00-0x0B) and in most cases data memory in the range 0x70-0x7F.
- For the 18F PICs: memory in the access bank.

Specific variables used by the compiler must be allocated in shared memory. This is done by the device files:

_pic_isr_w
  A byte variable used for saving the W register with interrupts.
  This variable is only needed for baseline and midrange PICs (core 12 and 14).
  It is not required for PICs without interrupt support (like 10f20x), but since the compiler requires this valriable, the device files still declare it for these PICs. However unused variables are removed by the compiler!
_pic_accum
  A byte variable used for saving the W register with multi-byte additions and subtractions when the two involved variables are in different memory banks, and for sign extensions of signed variables (adding sbyte to sword, etc.).

For performance reasons some other variables are preferrably allocated in shared memory. The device files attempt to allocate the following variables in shared memory:

Shadowing bytes
  Bytes for port and other register shadowing (for PICs without LAT registers: baseline and classic midrange PICs).

When no (more) shared memory is available these variables are (not surprisingly!) allocated in unshared memory.

Note: When a port is not used the memory reserved for its shadow byte is not returned to the memory pool (is 'lost') with the current compiler (2.4q6). This is considered a minor disadvantage compared to the performance advantage and reduction of code memory usage.

With most PICs only part of data memory shared. Some baseline and midrange PICs have all data memory shared, some others have no shared memory at all. There is no problem with 'all shared memory', but with 'no shared memory' the memory for the compiler required variables is declared as 'shared' even though it is in fact unshared memory! In the latter case the locations with the same (7-bits) offset in other banks are reserved (excluded from 'pragma data'). However this is only partly a solution: it avoids problems with interrupt handlers (which use _pic_isr_w), but it does not completely avoid problems with calculations with multi-byte variables (word, dword, etc., which use _pic_accum) when the variables are in different banks.
Examples: 16F73 and 16F74. With these PICs it is not safe for programs to perform calculations with multi-byte variables!.

Although you can declare a variable with the 'shared' keyword, the compiler won't allocate the variable in shared memory! The only effect of shared is that no bank setting is done by the compiler, regardless whether the variable is really in shared memory or not! You need to explicitly assign it an address with 'at <address>', whereby <address> must be in the shared memory range. Remember that device files allocate some variables in shared memory! Do not specify an address which is already assigned to another variable. This may result in very difficult to debug behaviour! To help you with this every device file contains a comment with the range of free shared memory after include of the device file!
By declaring a variable with an absolute address you take over part of memory management by the compiler, which is of course at your own responsibility!

### INTOSC calibration

Baseline and some midrange PICs have in the last word of code memory an instruction for calibration of the internal oscillator. This is a reserved word and not counted in the amount of available code memory. See also Calibration of Internal Oscillator.

### Data memory for PICs with USB module

PICs with USB module will have data memory reserved for the USB module. Sometimes this memory can be used as regular data memory by a user program, but only when the USB module is inactive, and sometimes it can be shared between USB module and user program. So the amount of available data memory as specified in the device file can be smaller than the total amount of memory specified in the datasheet due to reservation by the USB module.

### Analog modules

(to be done)

## Compatibility and Miscellaneous Remarks

These device files are part of the central JalV2 repository 'Jallib' (https://github.com/jallib/jallib/). Other libraries of Jallib have been or are being converted to use the names in these device files. You are strongly recommended to use only this combination of include files. Using these device files in combination with other libraries may cause problems, especially with libraries for the old (pre JalV2) compiler.

- The naming convention of ports and subfields maybe different, you may have to convert the other libraries.
- Bank switching functions are not needed with JalV2 and do not appear in the device files. This may cause compile-time errors when using programs or libraries which still use these procedures. You must remove these bank switching functions from your programs and libraries!
- The device files are generated from the MPLABX .pic files. This may cause confusion or even conflicts because the register and bit names are not always identical to those in the datasheets! Apart from that, MPLABX is not errorfree, consequently include files generated from this source cannot expected to be errorfree either!
- The device files contain some information for specific function libraries to make life of function library builders easier. For example a constant 'ADC_GROUP' is declared and assigned a value. This value can be used by ADC libraries to handle groups of PICs similarly and groups of other PICs differently. This grouping is inspired by the Microchip MCC18 compiler.

Note: With Jallib version 0.7 a number of constants, formerly declared in each device file are moved to a file 'constants_jallib.jal'. This file is included by chipdef_jallib.jal (which is on its turn included by every device file). Don't worry about memory occupation: unused constants are removed by the compiler automatically and don't occupy memory!

# 4. Generating device files

## The process

The device files are a transformation of MPLABX .pic files, for example in the IPE environment with Linux and MPLABX v4.01 in a .jar archive:

    /opt/microchip/mplabx/v4.01/mplab.ipe/lib/crownking.edc.jar

and with Windows (64 bits):

    C:\Program Files (x86)\Microchip\MPLABX\v4.01\mplab_ipe\lib\crownking.edc.jar

At least these are the locations with MPLABX version 4.01, with other versions you may have to search for this file! The device files are generated from these files with the scripts below. Before running these scripts you may have to modify the MPLABX version number and the "home" or "base" locations, maybe also the location of the file crownking.edc.jar. These variables are specified somewhere after the header of the scripts.

mplabxtract.py
  A new directory (e.g. 'mplabx_4.01') will be created, and the .pic files will be in 3 subdirectories of directory mplabx_4.01/content/edc, resp. for the 12-, 14- and 16-bits cores There is a .pic file for every PIC.
  This script expects that the utility program UNZIP is installed.
pinmap_create.py
  Python script to create the file pinmap.py from .pic files. This script is preferrably executed from the jallib tools directory. It creates a file pinmapnew.py, which should replace the existing file pinmap.py, but only after checking (comparing new with old)!
extract_pininfos.py
  Python script to create among others the file pinmap_suffixes.json. The output of this script should be generated in or copied to the Jallib tools directory.
pic2jal.py
  Python script to generate the Jallib device files from the MPLABX .pic files with the help of several other files in the tools directory, in particular:
  - devicespecific.json
  - pinmap_suffixes.json
  - datasheet.list

The Python scripts require Python version 3.5 or later.

Notes:

1. The scripts expect MPLABX IPE and a local copy of Jallib installed. The scripts contain comments with instructions for possible changes to run them on a different system configuration. This concerns only a few variables at the top of a script file.
2. The 'test' commandline argument of the pic2jal script will put the device files in a 'test' subdirectory of the current directory. When 'prod' is specified the device files have Jallib as destination, replacing all current device files.

## To do with new datasheets

MPLABX contains .pic files of all current PICs, but generally also of some future PICs of which the datasheet may of may not be available. The pic2jal script does not generate device files when the datasheet number is unknown (i.c. specified as "-" in the file devicespecific.json). When a datasheet becomes available the following actions are needed to generate device files.

- Make a new entry or update an existing entry in the file 'datasheet.list' in the jallib tools directory for each new Datasheet or Programming Specifications.
- Make a new entry or update an existing entry in the file 'devicespecific.json' in the tools directory for each of the PICs described in the new datasheet. An entry contains the following elements:

  Keyword | Description | Format | Remarks
  --- | --- | --- | ---
  DATASHEET | Datasheet number excl. suffix (letter) | 5 or 8 digits | Mandatory, otherwise no device file will be produced
  PGMSPEC | Programming Specifications number excl. suffix (letter) | 5 or 8 digits | Optional, no default
  ADCGROUP | Analog-to-Digital group number | ADC_V... | Optional, default 0 (no ADC module present)
  ADCMAXRESOLUTION | Analog-to-Digital resolution (# bits) | 0, 8, 10, 12 | Optional, default 10 (8 when no ADRESH present!)
  FUSESDEFAULT | Default configuration bits contents | hexdecimal digits | Optional, the defaults are obtained from .pic files, with some exceptions. *)
  DATA | Range(s) of data memory (RAM) | 0x...-0x...[,0x...-0x...,etc] | Optional, may contain multiple ranges. Only required in special cases. **)
  SHARED | Range(s) of shared data memory (RAM) | 0x...-0x...[,0x...-0x...,etc] | Optional, single range. Does not include SFR and core register areas. Only required in special cases **)

  *) With most midrange PICs unimplemented fuse bits read as '1'. but there are exceptions like with 12F629, 12F675, 16F630, 16F676. This may not be specified correctly in the .pic files of MPLABX. In case of exceptions to the rules a specification of FUSESDEFAULT in devicespecific.json is required.
  **) DATA and SHARED are 'special' for some PICs. This is because the values in the .pic file do not translate straight forwardly to the requirements of the JalV2 compiler. This applies to 12F629, 12F675, 16F526, 16F630, 16F636, 16F72, 16F73, 16F74, 16F83, 16F84, 16F84A, 16F818, 16F819, 16F870, 16F871, 16F872 16F873, 16F873A, 16F874, 16F874A and possibly for some other PICs.
  See for more details of the specifications the related sections about memory in this document and the comments in the pic2jal script.

- Run the Python script 'createdswikis.py' to create up-to-date datasheet wikis.
- The Python script 'pic2jal.py' may have to be adapted for new PICs. For example: the assigment of pin_ANx (JANSEL) may have to be extended (in the procedure ansel2j).
- Run the Python script 'pic2jal.py' with the TEST option to generate a new set of device files. It is recommended to compare the results with the existing device files to be certain you didn't forget something or made errors with modifying scripts or support files. The program KDIFF3 is a good tool for this purpose.
- Run the Python script 'blink-a-led.py' with the TEST option to validate the new device files and to generate blink-a-led samples.

Re-iterate these actions (the whole set or parts of it) until you are satisfied and everything is OK.

When everything looks OK:

- Run the Python script 'pic2jal.py' with the 'PROD' option.
- GIT-add any new device files.
- GIT-commit these and other changed files in the tools and wiki directories.
- Update the Jallib files CHANGELOG and TORELEASE when relevant and GIT-commit these.
  Note: TORELEASE may contain only device files and blink samples when at least one PIC of a group of PICs described in the same datasheet has actually been tested with good results.
- Run the script blink-a-led.cmd with the PROD option.
- GIT-add new blink samples and GIT-commit these.
- Run the Python script PPS-check.py to generate a new table of PPS_GROUPS and replace this table in the file devicefiles.html.

## To do with a new release of MPLABX

Create a new directory MPLABX. and extract the .pic files from the MPLABX file crownking.edc.jar into this directory.

You should realize that scripts may have to be revised with every new version of MPLABX because:

- The location of the .pic fies may have changed.
- The .pic files may have fixed errors in a previous version.
- The .pic files may contain new errors.
- There will probably be new .pic files which have to be examined.

Run the Python script mplabxtract.py to obtain the .pic files from MPLABX.

Change the MPLABX version in the Python script pinmap_create.py and run it to generate a new 'pinmap.py'. This script may have to be adapted because of changes in MPLABX .pic files.

Run the Python script extract_pininfos.py to generate a new 'pinmap_pinsuffix.json' (and some other files not relevant for device files). This script may have to be adapted because of changes in MPLABX .pic files.

The script pic2jal.py contains several device specific adaptations to make the device files suitable for Jallib. Most of these are mentioned in chapter 3 of this document. A warning is generated when such an adaptation is probably needed to correct an error in MPLABX. When generating Jallib device files with a new version of MPLABX these adaptations may have to be revised. In any case the MPLABX version needs to be changed.

When there are new device files which are not yet in Jallib then before running the pic2jal script you may have to perform the actions described above in the section To do when new datasheets become available.

Now run the pic2jal script with the 'TEST' option, redirect the output to a file and check this file for messages, like:

- A Python error 'invalid key' may appear when you have updated the datasheet number in datasheet.list but not in devicespecific.json or vice versa, in particular with the renumbering from 5 to 8 digits (e.g 4xxxxY -> 4000xxxxY).

However most warnings can usually be ignored, like:

- 'No "pin_ANx" alias in pinmap for ....'
  PICs with analog input modules may have 'active' bits in control registers like ANSEL, but no corresponding AN-pin. (error in MPLABX)
- 'Duplicate name: in ' This is generally caused by multiple names for the same register or bitfield (like with GPIO, PORTx, TRISx, PIE1, PIR1, etc.) or because pinmap.py contains an alias name which is also listed in MPLABX.
- 'Duplicate keyword for fuse_def xxxxx (.....)'
  Frequently there is more than one bit combination to disable or enable a configurable function. The device files declare just one of these, other combinations are reported as duplicate.
- 'PinMap..Rxy is undefined' These warnings are caused by 'active' bits in TRIS registers without a corresponding pin, or a reference to an input-only pin.
- Other warnings, many of which are caused by 'glitches' in MPLABX.

The pic2jal script has on several places code to suppress 'known' duplicates. But this may vary with the release of MPLABX: next release may have removed the duplicates (usually attempts to be backward compatible), and this would mean that the pic2jal script contains superfluous code. On the other hand MPLABX may also contain more duplicates!

The following actions may be required:

- Add an entry for each new PIC in the file devicespecific.json with the appropriate parameter values. Normally the pic2jal script will correctly insert the pragma data and pragma shared in the device files, but check if these match with memory conventions of JalV2!
- Support for unrecognised fuse_def keywords to the pic2jal script. The fuse_def OSC init procedure may have to be updated for new 'cname's and exceptions handling for fusedef OSC may have to be extended.
- With new entries or changes of pinmap.py the 'extract_pininfo.py' must be run to obtain an up-to-date pinmap_pinsuffix.json.
- Maybe some corrections have to be applied to the pic2jal script when new PICs have exceptions not covered yet, for example JANSEL numbering in procedure ansel2j.
- Visually check the new device files for irregularities. Use a file compare program (e.g. kdiff3) to reveal differences between the new and current device files. When needed apply changes to the script and/or data files.

Regardless of all the above information and instructions: in my experience with every new version of MPLABX there will be unforseen actions needed to generate a correct set of device files!