Interrupts

Z-Uno uses hardware interrupts of Z-Wave chip as well as software generated interrupts provide users simple experience. Currently Z-Uno supports the following interrupts:
  • INT0 (pin 17)
  • INT1 (pin 18)
  • ZEROX (pin 3)
  • GPT (General Purpose Timer)
  • 1 milliseconds software timer
Z-Uno v2 is able to handle some of hardware interrupts of Z-Wave chip in user code. There is a list of supported interrupt types:
  • ZUNO_IRQVEC_GPIO_ODD and ZUNO_IRQVEC_GPIO_EVEN
  • External interrupts of odd/even pins. See below about external interrupt handlers.
  • ZUNO_IRQVEC_I2C0 and ZUNO_IRQVEC_I2C1
  • I2C peripheral receive interrupts.
  • ZUNO_IRQVEC_TIMER0 and ZUNO_IRQVEC_TIMER1
  • 16Bit timers peripheral interrupts.
  • ZUNO_IRQVEC_WTIMER0
  • 32Bit timer peripheral interrupts.
  • ZUNO_IRQVEC_CSEN
  • Capacitive sensor peripheral interrupt.
  • ZUNO_IRQVEC_USART<n>_RX
  • USART peripheral receive interrupts.
  • ZUNO_IRQVEC_LEUART0_RX
  • Low energy UART peripheral receive interrupt.
External interrupts.
You can use any pin of Z-Uno as the source of external interrupt. Some of pins are not compatible to each other. Below is a list of pins, in a brackets are the pins which you unable to attach together: 0, (1/5), (2/15), (3/21), (4/22), (6/23), (7/17), 8, (9/20/25), (10/19), 11, 12, 13, 14, 16, (18/24).
The builtin interrupt controller supports up to 16 external interrupts. You are able to attach/detach handlers for external interrupts dinamically using attachInterrupt() and detachInterrupt() fuctions. Peripheral interrupts.
You can bind your handlers dinamically for this type of interrupts using zunoAttachSysHandler() fuction. Use this syntax to bind your ISRHandlerFunction to interrupt type ZUNO_IRQVEC_: zunoAttachSysHandler(ZUNO_HANDLER_IRQ, ZUNO_IRQVEC_..., (void*) &ISRHandlerFunction);
 Peripheral interrupt example1. Bind user-defined handler to USART0 RX interrupt.

    uint32_t num_bytes_received = 0;
    void UARTRxInt(uint32_t p){
        // p parameter is incoming symbol
        // Code just counts received bytes
        num_bytes_received++;
    }
    void setup(){
        Serial.begin(115200);
        // It's not evident, but Serial is binded to USART2 peripheral
        // Bind function
        zunoAttachSysHandler(ZUNO_HANDLER_IRQ, ZUNO_IRQVEC_USART2_RX, (void*) &UARTRxInt);
    }
    
    void loop(){
        if(num_bytes_received){
            Serial.print("RECEIVED:");
            Serial.print(num_bytes_received);
        }
        delay(1000);
    }
		
	
 Peripheral interrupt example2. GPT interrupt example.
    

volatile unsigned long count_gpt = 0;
void gpt_handler() {
    count_gpt++;
}
void setup() {
    Serial.begin(115200);
    // setup handler dynamically
    // GPT is maped to 32bit timer known as WTIMER
    zunoAttachSysHandler(ZUNO_HANDLER_IRQ, ZUNO_IRQVEC_WTIMER0, (void*) &gpt_handler);
    // setup GPT timer
    zunoGPTInit(ZUNO_GPT_SCALE1024|ZUNO_GPT_CYCLIC);	// divider and cyclic mode
    zunoGPTSet(10); // In 1024 tick units
    zunoGPTEnable(1); // start a timer    
}

void loop() {
    Serial0.print("Current GPT value:");
    Serial0.println(count_gpt);
    
    delay(1000);
}
            
        
Interrupt handler functions should be defined in user sketch and «announced» using the corresponding ZUNO_SETUP_ISR_*(my_handler_func) macro, where my_handler_func is the name of the handler function. The code in the user interrupt handler function should be as fast as possible and should not contain ANY function calls except few listed below. Also don't use local variables — use global variables instead!
Function allowed in interrupt handlerLimitations
digitalRead(pin)pin: a constant or variable of type s_pin
digitalWrite(pin, value)pin: a constant or variable of type s_pin
digitalToggle(pin)pin: a constant or variable of type s_pin
pinMode(pin, mode)pin: a constant or variable of type s_pin
zunoExtIntMode(int_num, mode)constant int_num and mode
zunoGPTEnable(mode)mode: a constant
zunoGPTSet(value)-
zunoFastPWMEnable(mode)mode: a constant
zunoFastPWMSet(a, b)-
millis()(starting from 2.1.5)
The code in the user interrupt handler function should be as fast as possible. ZUno uses the deferred interrupt method. Interrupts are stored in a list of special events, and then processed by an exclusive thread with high priority. If you configure the peripheral device to create interrupts too often, this will cause your Z-Uno to hang. Therefore, it is not recommended to setup cyclic timers with intervals of less than 50 microseconds. Old-fashioned static style definitions is available for Z-Uno v2 too. See section below. ZUNO_SETUP_ISR_*(my_handler_func) * the name of the interrupt (see table below) my_handler_func the name of the user defined interrupt handler

Interrupt nameDescriptionMacro
INT0 rise/fall/changeRise, fall or change of voltage on INT0 pin (pin 17)ZUNO_SETUP_ISR_INT0(my_handler_func)
INT1 rise/fall/changeRise, fall or change of voltage on INT1 pin (pin 18)ZUNO_SETUP_ISR_INT1(my_handler_func)
ZEROX rise/fall/changeRise, fall or change of voltage on ZEROX pin (pin 3)ZUNO_SETUP_ISR_ZEROX(my_handler_func)
GPTGeneral purpose timer reached zeroZUNO_SETUP_ISR_GPTIMER(my_handler_func)
1 millisecond tickExecuted every 1 millisecondZUNO_SETUP_ISR_1MSTIMER(my_handler_func)
 Static ISR definition. GPT interrupt handler example.

volatile unsigned long count_gpt = 0;
// special static macro-binding
ZUNO_SETUP_ISR_GPTIMER(gpt_handler);
void gpt_handler() {
    count_gpt++;
}
void setup() {
    Serial.begin(115200);
    // setup GPT timer
    zunoGPTInit(ZUNO_GPT_SCALE1024|ZUNO_GPT_CYCLIC);	// divider and cyclic mode
    zunoGPTSet(10); // In 1024 tick units
    zunoGPTEnable(1); // start a timer    
}
void loop() {
    Serial0.print("Current GPT value:");
    Serial0.println(count_gpt);
    delay(1000);
}