This document serves two purposes:
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:
The advantages of a consistent naming convention are also obvious:
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.
The device files are the base for other include files and contain:
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!
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:
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 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.
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.
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 loopWhen 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.
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 : 7Sometimes 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.
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 : 0etc. (for all other existing pins and ports).
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_TRISIO0etc. (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.
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_directionThis allows nibbles to be used as a regular variables.
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 unchangedSeveral 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.
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_A0and 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 : 0With 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_C1The 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!
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:
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:
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.
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 |
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.
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:
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:
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_ANSB5As 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:
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_ANS1In 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.
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.
Some elementary differences have to be taken into acount with respect to reading and writing memory:
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:
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:
Serial libraries should follow these conventions.
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 |
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:
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 : 0Same for the RTSECSEL1 and RTSECSEL0 bits of PADCFG1:
var volatile bit*2 PADCFG1_RTSECSEL at PADCFG1 : 1For 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
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
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.
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.
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 OSCCALStrictly 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!
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 OSCCALin 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 = 0x80See 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!
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.
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!
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.
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:
| 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 |
This group is not supported by Jallib (yet) and therefore not further covered here.
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.
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.
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 |
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:
B10 -- 10 bits B12 -- 12 bits B.. -- other number of bits
B8 -- 8 bits B16 -- 16 bits B.. -- other number of bits
W256 -- 256 words W512 -- 512 words W1K -- 1024 words (1K words) W2K -- 2048 words (2K words) W... -- any other number of words
ADJUST_NEG -- negative adjustment ADJUST_POS -- positive adjustment ... -- other
ENABLED -- BOD enabled, SBOREN disabled RUNONLY -- BOD enabled in run, disabled in sleep CONTROL -- SBOREN controls BOR function DISABLED -- BOD and SBOREN disabledBROWNOUT is also used for Deep Sleep BrownOut (DSBOREN).
B8 -- 8 bits B16 -- 16 bits B.. -- other number of bits
pin_xy -- assigned to pin y of PORTx pin_.. -- any other Enabled -- ) see datasheet Disabled -- )
ENABLED -- Code memory read protection on DISABLED -- Code mewmory read protection off
ENABLED -- Data (EEPROM) memory read protection on DISABLED -- Data (EEPROM) memory read protection off
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.
INTOSC -- internal oscillator OSC -- oscillator determined by OSC fuse_def
P2G -- 1 : 2G (2 *<PHONE_NUMBER>) P... P2M -- 1 : 2M (2 * 1048576) P... P2K -- 1 : 2K (2 * 1024) P.. P2 -- 1 : 2
ENABLED -- boot block table read protected DISABLED -- boot block may be table read
pin_xy -- pin y of portx is used
B12 -- 12 bits B16 -- 16 bits B20 -- 20 bit DISABLED -- disabled
ENABLED -- Ethernet LED enabled DISABLED -- Ethernet LED disabled
pin_xy -- Clock input assigned to pin y of portx
pin_xy -- pin y of portx is used
INTOSC -- Internal oscillator OSC -- Clock selected by OSC setting
ENABLED -- enable DISABLED -- disabled
F4MHZ -- 4 MHz F8MHZ -- 8 MHz
LOW_POWER -- low power, low noise immunity HIGH_POWER -- high power high noise immunity
ENABLED -- LVP on DISABLED -- LVP off
EXTERNAL -- /MCLR pin enabled INTERNAL -- /MCLR pin is digital I/O
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/OThe 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:
P1 -- 1 : 1 P.. -- etc P12 -- 1 : 12
DISABLED -- 1x P1 -- 1x ENABLED -- 4x P4 -- 4x F500KHZ -- freq 500 KHz F16MHZ -- freq 16 MHz
pin_xy -- PWM4 assigned to pin_y of portx
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
PORTx -- PMP on PORTx and other ports
ENABLED -- Power up timer enabled DISABLED -- Power Up timer disabled
INTOSC -- Internal oscillator T1OSC -- Timer 1 oscillator
NOT_CONDUCATED AREA_COMPLETE
pin_xy -- SPI active on pin y of portx DISABLED -- SPI not assigned
pin_A6_A7 -- pin_A6 and pin_A7 are used pin_B2_B3 -- pin_B2 and pin_B3 are used
P1 -- no divide P2 -- divide by 2
F48MHZ -- from 96MHZ PLL / 2 OSC -- from Oscillator
DISABLED pin_A0 ... etc (other pins which could be assigned
V20 -- 2.0 Volt V27 -- 2.7 Volt V42 -- 4.2 Volt V45 -- 4.5 Volt ... etc (whatever voltages are applicable)
ENABLED -- synchronous DISABLED -- asynchronous
ENABLED -- Watchdog enabled DISABLED -- Watchdog disabled CONTROL -- Software controlled by SWDTEN bit RUNNING -- Enabled while running, disabled in sleep.
STANDARD LOW_POWER
P0_WPFP -- from page 0 to write protect page PWPFD_END -- from write protect page to end of memory
P0 -- Write protect flash page 0 P1 -- Write protect flash page 1 P.. -- etc P127 -- Write protect flash page 127
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)
ENABLED -- table/region is not write protected DISABLED -- table/region is write protectedNotes:
pragma target CP R0F00_0FFF
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 Disabledis 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:
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:
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!
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:
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 usedfor 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.
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)!
The compiler recognises another pragma for data memory: pragma shared.
For the compiler 'shared' means:
Specific variables used by the compiler must be allocated in shared memory. This is done by the device files:
For performance reasons some other variables are preferrably allocated in shared memory. The device files attempt to allocate the following variables in shared 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!
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.
(to be done)
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.
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!
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.jarand with Windows (64 bits):
C:\Program Files (x86)\Microchip\MPLABX\v4.01\mplab_ipe\lib\crownking.edc.jarAt 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.
The Python scripts require Python version 3.5 or later.
Notes:
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.
| 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.
Re-iterate these actions (the whole set or parts of it) until you are satisfied and everything is OK.
When everything looks OK:
Create a new directory MPLABX. You should realize that scripts may have to be revised with every new
version of MPLABX because:
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:
However most warnings can usually be ignored, like:
The following actions may be required:
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!
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!
PICs with analog input modules may have 'active' bits
in control registers like ANSEL, but no corresponding AN-pin.
(error in MPLABX)
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.


Contents
In CSS, pattern matching rules determine which style rules apply to elements in the document tree. These patterns, called selectors, may range from simple element names to rich contextual patterns. If all conditions in the pattern are true for a certain element, the selector matches the element.
The case-sensitivity of document language element names in selectors depends on the document language. For example, in HTML, element names are case-insensitive, but in XML they are case-sensitive.
The following table summarizes CSS 2.1 selector syntax:
| Pattern | Meaning | Described in section |
|---|---|---|
| * | Matches any element. | Universal selector |
| E | Matches any E element (i.e., an element of type E). | Type selectors |
| E F | Matches any F element that is a descendant of an E element. | Descendant selectors |
| E > F | Matches any F element that is a child of an element E. | Child selectors |
| E:first-child | Matches element E when E is the first child of its parent. | The :first-child pseudo-class |
| E:link E:visited | Matches element E if E is the source anchor of a hyperlink of which the target is not yet visited (:link) or already visited (:visited). | The link pseudo-classes |
| E:active E:hover E:focus | Matches E during certain user actions. | The dynamic pseudo-classes |
| E:lang(c) | Matches element of type E if it is in (human) language c (the document language specifies how language is determined). | The :lang() pseudo-class |
| E + F | Matches any F element immediately preceded by a sibling element E. | Adjacent selectors |
| E[foo] | Matches any E element with the "foo" attribute set (whatever the value). | Attribute selectors |
| E[foo="warning"] | Matches any E element whose "foo" attribute value is exactly equal to "warning". | Attribute selectors |
| E[foo~="warning"] | Matches any E element whose "foo" attribute value is a list of space-separated values, one of which is exactly equal to "warning". | Attribute selectors |
| E[lang|="en"] | Matches any E element whose "lang" attribute has a hyphen-separated list of values beginning (from the left) with "en". | Attribute selectors |
| DIV.warning | Language specific. (In HTML, the same as DIV[class~="warning"].) | Class selectors |
| E#myid | Matches any E element with ID equal to "myid". | ID selectors |
A simple selector is either a type selector or universal selector followed immediately by zero or more attribute selectors, ID selectors, or pseudo-classes, in any order. The simple selector matches if all of its components match.
Note: the terminology used here in CSS 2.1 is different from what is used in CSS3. For example, a "simple selector" refers to a smaller part of a selector in CSS3 than in CSS 2.1. See the CSS3 Selectors module [CSS3SEL].
A selector is a chain of one or more simple selectors separated by combinators. Combinators are: white space, ">", and "+". White space may appear between a combinator and the simple selectors around it.
The elements of the document tree that match a selector are called subjects of the selector. A selector consisting of a single simple selector matches any element satisfying its requirements. Prepending a simple selector and combinator to a chain imposes additional matching constraints, so the subjects of a selector are always a subset of the elements matching the last simple selector.
One pseudo-element may be appended to the last simple selector in a chain, in which case the style information applies to a subpart of each subject.
When several selectors share the same declarations, they may be grouped into a comma-separated list.
In this example, we condense three rules with identical declarations into one. Thus,
h1 { font-family: sans-serif } h2 { font-family: sans-serif } h3 { font-family: sans-serif }
is equivalent to:
h1, h2, h3 { font-family: sans-serif }
CSS offers other "shorthand" mechanisms as well, including multiple declarations and shorthand properties.
The universal selector, written "*", matches the name of any element type. It matches any single element in the document tree.
If the universal selector is not the only component of a simple selector, the "*" may be omitted. For example:
*[lang=fr]
and [lang=fr]
are equivalent.
*.warning
and .warning
are equivalent.
*#myid
and #myid
are equivalent.
A type selector matches the name of a document language element type. A type selector matches every instance of the element type in the document tree.
The following rule matches all H1 elements in the document tree:
h1 { font-family: sans-serif }
At times, authors may want selectors to match an element that is
the descendant of another element in the document tree (e.g., "Match
those EM elements that are contained by an H1 element"). Descendant
selectors express such a relationship in a pattern.  A descendant
selector of the form "A B
" matches when an element
B
is an arbitrary descendant of some ancestor element A
.
For example, consider the following rules:
h1 { color: red } em { color: red }
Although the intention of these rules is to add emphasis to text by changing its color, the effect will be lost in a case such as:

This headline is very important

We address this case by supplementing the previous rules with a rule that sets the text color to blue whenever an EM occurs anywhere within an H1:
h1 { color: red } em { color: red } h1 em { color: blue }
The third rule will match the EM in the following fragment:

This headline is very important

The following selector:
div * p
matches a P element that is a grandchild or later descendant of a DIV element. Note the white space on either side of the "*" is not part of the universal selector; the white space is a combinator indicating that the DIV must be the ancestor of some element, and that that element must be an ancestor of the P.
The selector in the following rule, which combines descendant and attribute selectors, matches any element that (1) has the "href" attribute set and (2) is inside a P that is itself inside a DIV:
div p *[href]
A child selector matches when an element is the child of some element. A child selector is made up of two or more selectors separated by ">".
The following rule sets the style of all P elements that are children of BODY:
body > P { line-height: 1.3 }
The following example combines descendant selectors and child selectors:
div ol>li p
It matches a P element that is a descendant of an LI; the LI element must be the child of an OL element; the OL element must be a descendant of a DIV. Notice that the optional white space around the ">" combinator has been left out.
For information on selecting the first child of an element, please see the section on the :first-child pseudo-class below.
Adjacent sibling selectors have the following syntax: E1 + E2, where E2 is the subject of the selector. The selector matches if E1 and E2 share the same parent in the document tree and E1 immediately precedes E2, ignoring non-element nodes (such as text nodes and comments).
Thus, the following rule states that when a P element immediately follows a MATH element, it should not be indented:
math + p { text-indent: 0 }
The next example reduces the vertical space separating an H1 and an H2 that immediately follows it:
h1 + h2 { margin-top: -5mm }
The following rule is similar to the one in the previous example, except that it adds a class selector. Thus, special formatting only occurs when H1 has class="opener":
h1.opener + h2 { margin-top: -5mm }
CSS 2.1 allows authors to specify rules that match elements which have certain attributes defined in the source document.
Attribute selectors may match in four ways:
[att]
[att=val]
[att~=val]
att
attribute whose
value is a white space-separated list of words, one of which is exactly
"val". If "val" contains white space, it will never represent anything
(since the words are separated by spaces).
If "val" is the empty string, it will never represent anything either.
[att|=val]
att
attribute, its
value either being exactly "val" or beginning with "val" immediately
followed by "-" (U+002D). This is primarily intended to allow language subcode
matches (e.g., the hreflang
attribute on the
a
element in HTML) as described in BCP 47
([BCP47]) or its successor. For lang
(or
xml:lang
) language subcode matching, please see the :lang
pseudo-class.
Attribute values must be identifiers or strings. The case-sensitivity of attribute names and values in selectors depends on the document language.
For example, the following attribute selector matches all H1 elements that specify the "title" attribute, whatever its value:
h1[title] { color: blue; }
In the following example, the selector matches all SPAN elements whose "class" attribute has exactly the value "example":
span[class=example] { color: blue; }
Multiple attribute selectors can be used to refer to several attributes of an element, or even several times to the same attribute.
Here, the selector matches all SPAN elements whose "hello" attribute has exactly the value "Cleveland" and whose "goodbye" attribute has exactly the value "Columbus":
span[hello="Cleveland"][goodbye="Columbus"] { color: blue; }
The following selectors illustrate the differences between "=" and "~=". The first selector will match, for example, the value "copyright copyleft copyeditor" for the "rel" attribute. The second selector will only match when the "href" attribute has the value "http://www.w3.org/".
a[rel~="copyright"] a[href="http://www.w3.org/"]
The following rule hides all elements for which the value of the "lang" attribute is "fr" (i.e., the language is French).
*[lang=fr] { display : none }
The following rule will match for values of the "lang" attribute that begin with "en", including "en", "en-US", and "en-cockney":
*[lang|="en"] { color : red }
Similarly, the following aural style sheet rules allow a script to be read aloud in different voices for each role:
DIALOGUE[character=romeo] { voice-family: "Laurence Olivier", charles, male } DIALOGUE[character=juliet] { voice-family: "Vivien Leigh", victoria, female }
Matching takes place on attribute values in the document tree. Default attribute values may be defined in a DTD or elsewhere, but cannot always be selected by attribute selectors. Style sheets should be designed so that they work even if the default values are not included in the document tree.
More precisely, a UA may, but is not required to, read an "external subset" of the DTD but is required to look for default attribute values in the document's "internal subset." (See [XML10] for definitions of these subsets.) Depending on the UA, a default attribute value defined in the external subset of the DTD might or might not appear in the document tree.
A UA that recognizes an XML namespace [XMLNAMESPACES] may, but is not required to, use its knowledge of that namespace to treat default attribute values as if they were present in the document. (E.g., an XHTML UA is not required to use its built-in knowledge of the XHTML DTD.)
Note that, typically, implementations choose to ignore external subsets.
For example, consider an element EXAMPLE with an attribute "notation" that has a default value of "decimal". The DTD fragment might be
<!ATTLIST EXAMPLE notation (decimal,octal) "decimal">
If the style sheet contains the rules
EXAMPLE[notation=decimal] { /*... default property settings ...*/ } EXAMPLE[notation=octal] { /*... other settings...*/ }
the first rule might not match elements whose "notation" attribute is set by default, i.e., not set explicitly. To catch all cases, the attribute selector for the default value must be dropped:
EXAMPLE { /*... default property settings ...*/ } EXAMPLE[notation=octal] { /*... other settings...*/ }
Here, because the selector EXAMPLE[notation=octal]
is
more specific than the type
selector alone, the style declarations in the second rule will override
those in the first for elements that have a "notation" attribute value
of "octal". Care has to be taken that all property declarations that
are to apply only to the default case are overridden in the non-default
cases' style rules.
Working with HTML, authors may use the period (.
)
notation as an alternative to the ~=
notation when
representing the class
attribute. Thus, for HTML,
div.value
and div[class~=value]
have the
same meaning. The attribute value must immediately follow the
"period" (.
). UAs may apply selectors using the
period (.) notation in XML documents if the UA has namespace specific
knowledge that allows it to determine which attribute is the
"class" attribute for the respective namespace. One such
example of namespace specific knowledge is the prose in the
specification for a particular namespace (e.g., SVG 1.1 [SVG11]
describes the SVG
"class" attribute and how a UA should interpret it, and
similarly MathML 3.0 [MATH30] describes the MathML
"class" attribute.)
For example, we can assign style information to all elements with class~="pastoral" as follows:
*.pastoral { color: green } /* all elements with class~=pastoral */or just
.pastoral { color: green } /* all elements with class~=pastoral */
The following assigns style only to H1 elements with class~="pastoral":
H1.pastoral { color: green } /* H1 elements with class~=pastoral */
Given these rules, the first H1 instance below would not have green text, while the second would:

Not green

Very green

To match a subset of "class" values, each value must be preceded by a ".".
For example, the following rule matches any P element whose "class" attribute has been assigned a list of space-separated values that includes "pastoral" and "marine":
p.marine.pastoral { color: green }
This rule matches when class="pastoral blue aqua marine" but does not match for class="pastoral blue".
Note. CSS gives so much power to the "class" attribute, that authors could conceivably design their own "document language" based on elements with almost no associated presentation (such as DIV and SPAN in HTML) and assigning style information through the "class" attribute. Authors should avoid this practice since the structural elements of a document language often have recognized and accepted meanings and author-defined classes may not.
Note: If an element has multiple class attributes, their values must be concatenated with spaces between the values before searching for the class. As of this time the working group is not aware of any manner in which this situation can be reached, however, so this behavior is explicitly non-normative in this specification.
Document languages may contain attributes that are declared to be of type ID. What makes attributes of type ID special is that no two such attributes can have the same value; whatever the document language, an ID attribute can be used to uniquely identify its element. In HTML all ID attributes are named "id"; XML applications may name ID attributes differently, but the same restriction applies.
The ID attribute of a document language allows authors to assign an identifier to one element instance in the document tree. CSS ID selectors match an element instance based on its identifier. A CSS ID selector contains a "#" immediately followed by the ID value, which must be an identifier.
Note that CSS does not specify how a UA knows the ID attribute of an element. The UA may, e.g., read a document's DTD, have the information hard-coded or ask the user.
The following ID selector matches the H1 element whose ID attribute has the value "chapter1":
h1#chapter1 { text-align: center }
In the following example, the style rule matches the element that has the ID value "z98y". The rule will thus match for the P element:
 <TITLE>Match P</TITLE>
Wide text

In the next example, however, the style rule will only match an H1 element that has an ID value of "z98y". The rule will not match the P element in this example:
 <TITLE>Match H1 only</TITLE>
Wide text

ID selectors have a higher specificity than attribute selectors. For example, in HTML, the selector #p123 is more specific than [id=p123] in terms of the cascade.
Note. In XML 1.0 [XML10], the information about which
attribute contains an element's IDs is contained in a DTD. When
parsing XML, UAs do not always read the DTD, and thus may not know
what the ID of an element is. If a style sheet designer knows or
suspects that this will be the case, he should use normal attribute
selectors instead: [name=p371]
instead of
#p371
. However, the cascading order of normal attribute
selectors is different from ID selectors. It may be necessary to add
an "!important" priority to the declarations: [name=p371]
{color: red ! important}
.
If an element has multiple ID attributes, all of them must be treated as IDs for that element for the purposes of the ID selector. Such a situation could be reached using mixtures of xml:id [XMLID], DOM3 Core [DOM-LEVEL-3-CORE], XML DTDs [XML10] and namespace-specific knowledge.
In CSS 2.1, style is normally attached to an element based on its position in the document tree. This simple model is sufficient for many cases, but some common publishing scenarios may not be possible due to the structure of the document tree. For instance, in HTML 4 (see [HTML4]), no element refers to the first line of a paragraph, and therefore no simple CSS selector may refer to it.
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
Neither pseudo-elements nor pseudo-classes appear in the document source or document tree.
Pseudo-classes are allowed anywhere in selectors while pseudo-elements may only be appended after the last simple selector of the selector.
Pseudo-element and pseudo-class names are case-insensitive.
Some pseudo-classes are mutually exclusive, while others can be applied simultaneously to the same element. In case of conflicting rules, the normal cascading order determines the outcome.
The :first-child pseudo-class matches an element that is the first child element of some other element.
In the following example, the selector matches any P element that is the first child of a DIV element. The rule suppresses indentation for the first paragraph of a DIV:
div > p:first-child { text-indent: 0 }This selector would match the P inside the DIV of the following fragment:

 The last P before the note.

 The first P inside the note.
but would not match the second P in the following fragment:

 The last P before the note.

Note

 The first P inside the note.

The following rule sets the font weight to 'bold' for any EM element that is some descendant of a P element that is a first child:
p:first-child em { font-weight : bold }
Note that since anonymous boxes are not part of the document tree, they are not counted when calculating the first child.
For example, the EM in:

abc defaultis the first child of the P.
The following two selectors are equivalent:
* > a:first-child /* A is first child of any element */ a:first-child /* Same */
User agents commonly display unvisited links differently from previously visited ones. CSS provides the pseudo-classes ':link' and ':visited' to distinguish them:
UAs may return a visited link to the (unvisited) ':link' state at some point.
The two states are mutually exclusive.
The document language determines which elements are hyperlink source anchors. For example, in HTML4, the link pseudo-classes apply to A elements with an "href" attribute. Thus, the following two CSS 2.1 declarations have similar effect:
a:link { color: red } :link { color: red }
If the following link:
external linkhas been visited, this rule:
a.external:visited { color: blue }will cause it to be blue.
Note. It is possible for style sheet authors to abuse the :link and :visited pseudo-classes to determine which sites a user has visited without the user's consent.
UAs may therefore treat all links as unvisited links, or implement other measures to preserve the user's privacy while rendering visited and unvisited links differently. See [P3P] for more information about handling privacy.
Interactive user agents sometimes change the rendering in response to user actions. CSS provides three pseudo-classes for common cases:
An element may match several pseudo-classes at the same time.
CSS does not define which elements may be in the above states, or how the states are entered and left. Scripting may change whether elements react to user events or not, and different devices and UAs may have different ways of pointing to, or activating elements.
CSS 2.1 does not define if the parent of an element that is ':active' or ':hover' is also in that state.
User agents are not required to reflow a currently displayed document due to pseudo-class transitions. For instance, a style sheet may specify that the 'font-size' of an :active link should be larger than that of an inactive link, but since this may cause letters to change position when the reader selects the link, a UA may ignore the corresponding style rule.
a:link { color: red } /* unvisited links */ a:visited { color: blue } /* visited links */ a:hover { color: yellow } /* user hovers */ a:active { color: lime } /* active links */
Note that the A:hover must be placed after the A:link and A:visited rules, since otherwise the cascading rules will hide the 'color' property of the A:hover rule. Similarly, because A:active is placed after A:hover, the active color (lime) will apply when the user both activates and hovers over the A element.
An example of combining dynamic pseudo-classes:
a:focus { background: yellow } a:focus:hover { background: white }
The last selector matches A elements that are in pseudo-class :focus and in pseudo-class :hover.
For information about the presentation of focus outlines, please consult the section on dynamic focus outlines.
Note. In CSS1, the ':active' pseudo-class was mutually exclusive with ':link' and ':visited'. That is no longer the case. An element can be both ':visited' and ':active' (or ':link' and ':active') and the normal cascading rules determine which style declarations apply.
Note. Also note that in CSS1, the ':active' pseudo-class only applied to links.
If the document language specifies how the human language of an element is determined, it is possible to write selectors in CSS that match an element based on its language. For example, in HTML [HTML4], the language is determined by a combination of the "lang" attribute, the META element, and possibly by information from the protocol (such as HTTP headers). XML uses an attribute called xml:lang, and there may be other document language-specific methods for determining the language.
The pseudo-class ':lang(C)' matches if the element is in language C. Whether there is a match is based solely on the identifier C being either equal to, or a hyphen-separated substring of, the element's language value, in the same way as if performed by the '|=' operator. The matching of C against the element's language value is performed case-insensitively for characters within the ASCII range. The identifier C does not have to be a valid language name.
C must not be empty.
Note: It is recommended that documents and protocols indicate language using codes from BCP 47 [BCP47] or its successor, and by means of "xml:lang" attributes in the case of XML-based documents [XML10]. See "FAQ: Two-letter or three-letter language codes."
The following rules set the quotation marks for an HTML document that is either in Canadian French or German:
html:lang(fr-ca) { quotes: '« ' ' »' } html:lang(de) { quotes: '»' '«' '\2039' '\203A' } :lang(fr) > Q { quotes: '« ' ' »' } :lang(de) > Q { quotes: '»' '«' '\2039' '\203A' }
The second pair of rules actually set the 'quotes' property on Q elements according to the language of its parent. This is done because the choice of quote marks is typically based on the language of the element around the quote, not the quote itself: like this piece of French “à l'improviste” in the middle of an English text uses the English quotation marks.
Note the difference between [lang|=xx] and :lang(xx). In this HTML example, only the BODY matches [lang|=fr] (because it has a LANG attribute) but both the BODY and the P match :lang(fr) (because both are in French).

Je suis Français.

Pseudo-elements behave just like real elements in CSS with the exceptions described below and elsewhere.
Note that the sections below do not define the exact rendering of ':first-line' and ':first-letter' in all cases. A future level of CSS may define them more precisely.
The :first-line pseudo-element applies special styles to the contents of the first formatted line of a paragraph. For instance:
p:first-line { text-transform: uppercase }
The above rule means "change the letters of the first line of every paragraph to uppercase". However, the selector "P:first-line" does not match any real HTML element. It does match a pseudo-element that conforming user agents will insert at the beginning of every paragraph.
Note that the length of the first line depends on a number of factors, including the width of the page, the font size, etc. Thus, an ordinary HTML paragraph such as:

This is a somewhat long HTML paragraph that will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.

the lines of which happen to be broken as follows:
THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.
might be "rewritten" by user agents to include the fictional tag sequence for :first-line. This fictional tag sequence helps to show how properties are inherited.

 This is a somewhat long HTML paragraph that
 will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.

If a pseudo-element breaks up a real element, the desired effect can often be described by a fictional tag sequence that closes and then re-opens the element. Thus, if we mark up the previous paragraph with a SPAN element:

 This is a somewhat long HTML paragraph that will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.

the user agent could simulate start and end tags for SPAN when inserting the fictional tag sequence for :first-line.

 This is a somewhat long HTML paragraph that will
 be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.

The :first-line pseudo-element can only be attached to a block container element.
The "first formatted line" of an
element may occur inside a
block-level descendant in the same flow (i.e., a block-level
descendant that is not positioned and not a float). E.g., the first
line of the DIV in

This
line...

is the first line of the P (assuming
that both P and DIV are block-level).
The first line of a table-cell or inline-block cannot be the first
formatted line of an ancestor element. Thus, in

Hello
Goodbye

etcetera

the first formatted line of the DIV is not
the line "Hello".
Note that the first line of the P in this fragment:

First...
does not contain any letters
(assuming the default style for BR in HTML 4). The word "First" is
not on the first formatted line.
A UA should act as if the fictional start tags of the first-line pseudo-elements were nested just inside the innermost enclosing block-level element. (Since CSS1 and CSS2 were silent on this case, authors should not rely on this behavior.) Here is an example. The fictional tag sequence for

First paragraph

Second paragraph

is

First paragraph

Second paragraph

The :first-line pseudo-element is similar to an inline-level element, but with certain restrictions. The following properties apply to a :first-line pseudo-element: font properties, color property, background properties, 'word-spacing', 'letter-spacing', 'text-decoration', 'text-transform', and 'line-height'. UAs may apply other properties as well.
The :first-letter pseudo-element must select the first letter of the first line of a block, if it is not preceded by any other content (such as images or inline tables) on its line. The :first-letter pseudo-element may be used for "initial caps" and "drop caps", which are common typographical effects. This type of initial letter is similar to an inline-level element if its 'float' property is 'none', otherwise it is similar to a floated element.
These are the properties that apply to :first-letter pseudo-elements: font properties, 'text-decoration', 'text-transform', 'letter-spacing', 'word-spacing' (when appropriate), 'line-height', 'float', 'vertical-align' (only if 'float' is 'none'), margin properties, padding properties, border properties, color property, background properties. UAs may apply other properties as well. To allow UAs to render a typographically correct drop cap or initial cap, the UA may choose a line-height, width and height based on the shape of the letter, unlike for normal elements. CSS3 is expected to have specific properties that apply to first-letter.
This example shows a possible rendering of an initial cap. Note that the 'line-height' that is inherited by the first-letter pseudo-element is 1.1, but the UA in this example has computed the height of the first letter differently, so that it does not cause any unnecessary space between the first two lines. Also note that the fictional start tag of the first letter is inside the SPAN, and thus the font weight of the first letter is normal, not bold as the SPAN:
p { line-height: 1.1 } p:first-letter { font-size: 3em; font-weight: normal } span { font-weight: bold } ...
Het hemelsche gerecht heeft zich ten lange lesten
 Erbarremt over my en mijn benaeuwde vesten
 En arme burgery, en op mijn volcx gebed
 En dagelix geschrey de bange stad ontzet.
The following CSS 2.1 will make a drop cap initial letter span about two lines:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">   <TITLE>Drop cap initial letter</TITLE>
The first few words of an article in The Economist.

This example might be formatted as follows:
The fictional tag sequence is:

 T
he first  few words of an article in the Economist.

Note that the :first-letter pseudo-element tags abut the content (i.e., the initial character), while the :first-line pseudo-element start tag is inserted right after the start tag of the block element.
In order to achieve traditional drop caps formatting, user agents may approximate font sizes, for example to align baselines. Also, the glyph outline may be taken into account when formatting.
Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe), "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included, as in:
The ':first-letter' also applies if the first letter is in fact a digit, e.g., the "6" in "67 million dollars is a lot of money."
The :first-letter pseudo-element applies to block container elements.
The :first-letter pseudo-element can be used with all such elements that contain text, or that have a descendant in the same flow that contains text. A UA should act as if the fictional start tag of the first-letter pseudo-element is just before the first text of the element, even if that first text is in a descendant.
Here is an example. The fictional tag sequence for this HTML fragment:

The first text.
is:

T</...></...>he first text.
The first letter of a table-cell or inline-block cannot be the
first letter of an ancestor element. Thus, in

Hello
Goodbye

etcetera

the first letter of the DIV is not the
letter "H". In fact, the DIV does not have a first letter.
The first letter must occur on the first formatted line. For example, in
this fragment:

First...
the first line
does not contain any letters and ':first-letter' does not match anything
(assuming the default style for BR in HTML 4). In particular, it
does not match the "F" of "First."
If an element is a list item ('display: list-item'), the ':first-letter' applies to the first letter in the principal box after the marker. UAs may ignore ':first-letter' on list items with 'list-style-position: inside'. If an element has ':before' or ':after' content, the ':first-letter applies to the first letter of the element including that content.
E.g., after the rule 'p:before {content: "Note: "}', the selector 'p:first-letter' matches the "N" of "Note".
Some languages may have specific rules about how to treat certain letter combinations. In Dutch, for example, if the letter combination "ij" appears at the beginning of a word, both letters should be considered within the :first-letter pseudo-element.
If the letters that would form the first-letter are not in the same
element, such as "'T" in
'T...
, the UA may
create a first-letter pseudo-element from one of the elements, both
elements, or simply not create a pseudo-element.
Similarly, if the first letter(s) of the block are not at the start of the line (for example due to bidirectional reordering), then the UA need not create the pseudo-element(s).
The following example illustrates how overlapping pseudo-elements may interact. The first letter of each P element will be green with a font size of '24pt'. The rest of the first formatted line will be 'blue' while the rest of the paragraph will be 'red'.
p { color: red; font-size: 12pt } p:first-letter { color: green; font-size: 200% } p:first-line { color: blue }
Some text that ends up on two lines

Assuming that a line break will occur before the word "ends", the fictional tag sequence for this fragment might be:

 S
ome text that
 ends up on two lines

Note that the :first-letter element is inside the :first-line element. Properties set on :first-line are inherited by :first-letter, but are overridden if the same property is set on :first-letter.
The ':before' and ':after' pseudo-elements can be used to insert generated content before or after an element's content. They are explained in the section on generated text.
h1:before {content: counter(chapno, upper-roman) ". "}
When the :first-letter and :first-line pseudo-elements are applied to an element having content generated using :before and :after, they apply to the first letter or line of the element including the generated content.
p.special:before {content: "Special! "} p.special:first-letter {color: #ffd800}
This will render the "S" of "Special!" in gold.


Please enable JavaScript ...
The markdown file must be located on the same server and within the same directory or subdirectory as this html file.
1 / 1


Regional score (change manually)
Minimum to defeat current winner: ...
Checkpoints past: ...
Checkpoints left: ...
Cycle end: ...


--- title: "Values" ---
WE BREATHES THESE CORE VALUES EVERY SINGLE MINUTE.
We work with companies who are looking to grow, go big and influence people's lives for real. Taking a powerful product and making it work for the user is what we do.
CONTACT FOOBITS


Open login form
×
Login
×
Error!
{{ loginErrorText }}
E-mail:
Enter a valid email.
Password:
You must enter a password.
Don't have an account yet?
Sign up


Heart
Unauthorized User
You are no longer authorized to access Pulse Wearables services. If you believe that this is a mistake, feel free to email us. Thank you.
You are no longer authorized to access Pulse Wearables services. If you believe that this is a mistake, feel free to email us. Thank you.


A new take on Progressive Web Apps
Feature Showcase
Combining URI Paths with HTML blocks as views we've got a one of a kind Single Page Router implementation. The idea is to avoid writing multiple html pages with repeating boilerplate.
With the timed atomic updates the app assets are always fresh, edits in files are detected and they are updated on the go. You can still tinker the service worker for whole app upgrades (SkyRoutes 1.2).
The app can be hot-reloaded based on focus change, saves your extra key presses. We've got css-only, silent and full reload as possible options.
We can force our app to only run with an active internet connection and also detect network changes. The opposite is already key feature of PWAs!
We can force our users to install the PWA / add it to HomeScreen, It helps if you want to provide a native app experience.
Inspired by Flutter, errors in your code are displayed on the app screen!
The framework is written from scratch in vanilla JavaScript and it's OpenSource.
Despite being more than a router, all the implementations are straight-forward and designed for helping with fast prototyping to production. With the beginner friendly starter-kit and single Object based declaration an app can be built in no time.
Documentation
| Key | Value | Description |
|---|---|---|
| assets | Array of Valid paths as String | This is used for specifing files to be cached by the PWA, you can edit this string anytime |
| hot_reload | css/silent/full/false | refresh css / refresh html and css / reload app / disabled based on focus change |
| force_install | true/false | Force user to add app to HomeScreen |
| force_network | true/false | App dependent on active internet connection |
| route_error | hold/free | Client grabs navigation upon incorrect route (path) / usual server fetching |
| update_interval | -1/0/int in minutes | atomic updates disabled / atomic updates every reload / atomic updates after duration (in minutes) |
Changelog
2.1 : Rewrite and optimizations
2.0 : Relaunch (B)
1.5 : Dynamic router (Indexed DB)
1.3 : Static router (Legacy)
1.2 : SW integrated (B)
1.0 : Hash based router (uiJS)
About