Examples

  INTERRUPT {NOPRESERVE | NOCODE} {Rate} Instruction(s) ... RETURNINT {Cycles}

Function
INTERRUPT allows the insertion a code block to handle an interrupt in an SX/B program. The interrupt code block is terminated with RETURNINT.

Explanation
An interrupt handler allows the SX to perform "background" task, at regular intervals (using the internal RTCC rollover) or asynchronously (using the external RTCC input pin, or Port B inputs). The interrupt code must be located in Page 0 of your program, and before any other code -- this is a requirement of the SX microcontroller.

SX/B automatically saves internal program variables (__PARAMx) at the start of the ISR and restores them on exit of the ISR. This consumes ISR cycles (14 cycles on entry, 13 cycles on exit) and must be accounted for in time-critical ISR applications. If high-level instructions will not be used in the ISR, the NOPRESERVE option may be specified, eliminating the code that preserves and restores internal SX/B program variables. If the NOPRESERVE option is used, you must make sure that none of the __PARAMx variables are modified by the ISR (i.e., use high-level SX/B instructions). If the NOCODE option is specified then the interrupt routine must set FSR to zero to access variables in location $10 to $1F reliably.

When the interrupt Rate is specified, in calls per second, the SX/B compiler will automatically generate the proper !OPTION register and RETURNINT values in the initialization code. If a rate is specified that is not possible within specified FREQ setting, the Rate parameter will flag an "Invalid Parameter" error.

Periodic Interrupts
The SX chip can be set to cause an interrupt upon rollover of the Real Time Clock Counter (RTCC). By configuring an interrupt on RTCC rollover, the SX chip can perform an operation at a predefined time interval in a deterministic fashion. This can be configured by setting the STACKX or OPTIONX fuse (in the DEVICE directive, and required by SX/B) and writing to the RTI, RTS and RTE bits of the Option register (OPTION). The RTCC rollover interrupt is disabled by default.

To configure the RTCC rollover interrupt:

  1. Set the STACKX or OPTIONX fuse in the DEVICE directive.
  2. Write to the RTI, RTS and RTE bits of the OPTION register to enable RTCC interrupts. For RTI, a high bit (1) disables RTCC rollover interrupts and a low bit (0) enables RTCC rollover interrupts. For RTS, a high bit (1) selects incrementing RTCC on internal clock cycle and a low bit (0) increments RTCC on the RTCC pin transitions. For RTE, a high bit (1) selects incrementing on low-to-high transition and a low bit (0) increments on a high-to-low transition.

An interrupt handler that uses the RTCC rollover to create a periodic interrupt might look as follows:

' -------------------------------------------------------------------------
  INTERRUPT
' -------------------------------------------------------------------------

ISR_Start:
  INC tix                                       ' update tix counter
  IF tix = 200 THEN                             ' check for 1 second
    tix = 0
    INC secs
    IF secs = 60 THEN
      secs = 0
      INC mins
      IF mins = 60 THEN
        mins = 0
        INC hrs
        IF hrs = MaxHr THEN
          hrs = 0
        ENDIF
      ENDIF
    ENDIF
  ENDIF

ISR_Exit:
  RETURNINT 156  

This routine (ISR) maintains a real-time clock. The variable called tix is updated each time through the ISR and when it reaches 200 the seconds counter is updated. This indicates that the ISR is designed to run 200 times per second.

Even when using a 4 MHz oscillator, each instruction takes only 0.25 microseconds. By using the RTCC prescaler we can slow the RTCC timing to a more manageable value and simplify the code. For the timer above, the RTCC prescaler ratio is set to 1:128 via the OPTION register (and clearing OPTION.6 enables the ISR):

  OPTION = $86                                  ' prescaler = 1:128

Note that the Cycles count is set to 156 -- this means that the ISR will run after 156 cycles of the internal RTCC. The final math for the ISR timing works out like this:

4 MHz (FREQ) ÷ 128 (prescaler) ÷ 200 (ISR rate) = 156.25 (Cycles)


Option Register
The OPTION register is a run-time writable register used to configure the RTCC and the Watchdog Timer. The size of this register is affected by the OPTIONX device setting.

OPTION
7 6 5 4 3 2 1 0
RTW RTI RTS RTE PSA PS2 PS1 PS0

When OPTION Extend = 0, bits 7 and 6 are implemented.
When OPTION Extend = 1, bits 7 and 6 read as '1's.

RTW   If = 0, register $01 is W
If = 1, register $01 is RTCC

RTI   If = 0, RTCC roll-over interrupt is enabled
If = 1, RTCC roll-over interrupt is disabled

RTS   If = 0, RTCC increments on internal instruction cycle
If = 1, RTCC increments on transition of RTCC pin

RTE   If = 0, RTCC increments on low-to-high transition
If = 1, RTCC increments on high-to-low transition

PSA   If = 0, prescaler is assigned to RTCC, divide rate determined by PS2..PS0 bits
If = 1, prescaler is assigned to WDT, and divide rate on RTCC is 1:1

Prescaler Division Ratios
PS2, PS1, PS0 RTCC
Divide Rate
Watchdog Timer
Divide Rate
000 1:2 1:1
001 1:4 1:2
010 1:8 1:4
011 1:16 1:8
100 1:32 1:16
101 1:64 1:32
110 1:128 1:64
111 1:256 1:128


Using the Rate Parameter
With SX/B version 1.5 the programming of interrupts is simplified with the Rate parameter. When used, the Rate parameter designates the interrupt frequency in calls per second. For example, to automate the timer code shown above at a rate of 200 calls per second, the INTERRUPT code could be modified as follows:

' -------------------------------------------------------------------------
  INTERRUPT 200
' -------------------------------------------------------------------------

ISR_Start:
  INC tix                                       ' update tix counter
  IF tix = 200 THEN                             ' check for 1 second
    tix = 0
    INC secs
    IF secs = 60 THEN
      secs = 0
      INC mins
      IF mins = 60 THEN
        mins = 0
        INC hrs
        IF hrs = MaxHr THEN
          hrs = 0
        ENDIF
      ENDIF
    ENDIF
  ENDIF

ISR_Exit:
  RETURNINT  

By using this style the programmer does not need to set the OPTION register manually.


Asynchronous Interrupts
Every I/O pin in port B can be set to cause an interrupt upon logic level transitions (rising edge or falling edge). By configuring interrupts on input pins, the SX chip can respond to signal changes in a quick and deterministic fashion. In addition, an interrupt of this sort will wake up the SX chip from a SLEEP state. This can be configured by writing to the Edge Selection register (WKED_B) and the Wake-Up Enable register (WKEN_B) and detected by monitoring the Pending register (WKPND_B) in the interrupt routine. The I/O pins have interrupts disabled and are set to detect falling edge transitions by default.

As with edge selection, the Pending register bits will never be cleared by the SX alone; the running program is responsible for doing so. This means if a desired edge is detected, the interrupt will occur and the flag indicating this will remain set until the program clears it. Additional transitions on that pin will not cause interrupts until the associated bit in the Pending register is cleared.

To configure the I/O pins for wake-up (interrupt) edge detection:

  1. Set I/O pin edge detection with WKED_B as desired.
  2. Use WKEN_B to enable the individual pins for wake-up interrupts. A high bit (1) disables interrupts and a low bit (0) enables interrupts.
  3. Set I/O pin directions as necessary.
  4. Clear the Pending register to enable new interrupts.


Special Notes
Interrupts that are not precisely timed should be avoided -- or at the very least disabled -- when using time-sensitive instructions such as SERIN, SEROUT, PULSIN, PULSOUT, etc. If an interrupt with variable timing is triggered while a time-sensitive instruction is active the instruction is likely to fail, or return bad results. If, however, the interrupt code is constructed such that is always runs a given number of cycles, the EffectiveHz parameter of FREQ may be used to allow time-sensitive SX/B instructions to operate while the interrupt is enabled.


Related projects: Clock / Timer and Quadrature Encoder Input