// ************************************************************************************************* // @fn Timer0_A4_Delay // @brief Wait for some microseconds // @param ticks (1 tick = 1/32768 sec) // @return none // ************************************************************************************************* void Timer0_A4_Delay(u16 ticks) { u16 value = 0; // Exit immediately if Timer0 not running - otherwise we'll get stuck here if ((TA0CTL & (BIT4 | BIT5)) == 0) return; // Disable timer interrupt TA0CCTL4 &= ~CCIE; // Clear delay_over flag sys.flag.delay_over = 0; // Add delay to current timer value // To make sure this value is correctly read while (value != TA0R) value = TA0R; value += ticks; // Update CCR TA0CCR4 = value; // Reset IRQ flag TA0CCTL4 &= ~CCIFG; // Enable timer interrupt TA0CCTL4 |= CCIE; // Wait for timer IRQ while (1) { // Delay in LPM to_lpm(); // will also set GIE again #ifdef USE_WATCHDOG // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; #endif // Redraw stopwatch display if (is_stopwatch()) display_stopwatch(LINE2, DISPLAY_LINE_UPDATE_PARTIAL); // Check stop condition // disable interrupt to prevent flag's change caused by interrupt methods __disable_interrupt(); if (sys.flag.delay_over) break; } __enable_interrupt(); }
// ************************************************************************************************* // @fn Timer0_A4_Delay // @brief Wait for some microseconds // @param ticks (1 tick = 1/32768 sec) // @return none // ************************************************************************************************* void Timer0_A4_Delay(u16 ticks) { u16 value; // Exit immediately if Timer0 not running - otherwise we'll get stuck here if ((TA0CTL & (BIT4 | BIT5)) == 0) return; // Disable timer interrupt TA0CCTL4 &= ~CCIE; // Clear delay_over flag sys.flag.delay_over = 0; // Add delay to current timer value value = TA0R + ticks; // Update CCR TA0CCR4 = value; // Reset IRQ flag TA0CCTL4 &= ~CCIFG; // Enable timer interrupt TA0CCTL4 |= CCIE; // Wait for timer IRQ while (1) { // Delay in LPM to_lpm(); #ifdef USE_WATCHDOG // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; #endif // Redraw stopwatch display if (is_stopwatch()) display_stopwatch(LINE2, DISPLAY_LINE_UPDATE_PARTIAL); // Redraw countdown display if (is_countdown_active()) display_countdown(LINE1, DISPLAY_LINE_UPDATE_PARTIAL); // Redraw countup display if (is_countup_active()) display_countup(LINE2, DISPLAY_LINE_UPDATE_PARTIAL); // Check stop condition if (sys.flag.delay_over) break; } }
__interrupt void PORT2_ISR(void) { // Clear flags u8 int_flag, int_enable; u8 buzzer = 0; u8 simpliciti_button_event = 0; static u8 simpliciti_button_repeat = 0; // Remember interrupt enable bits int_enable = BUTTONS_IE; if ((!button.flag.star_long) && (!button.flag.num_long)) { // Clear button flags button.all_flags = 0; // Store valid button interrupt flag int_flag = BUTTONS_IFG & int_enable; // --------------------------------------------------- // While SimpliciTI stack is active, buttons behave differently: // - Store button events in SimpliciTI packet data // - Exit SimpliciTI when button DOWN was pressed if (is_rf()) { // Erase previous button press after a number of resends (increase number if link // quality is low) // This will create a series of packets containing the same button press // Necessary because we have no acknowledge // Filtering (edge detection) will be done by receiver software if (simpliciti_button_repeat++ > 6) { simpliciti_data[0] &= ~0xF0; simpliciti_button_repeat = 0; } if ((int_flag & BUTTON_STAR_PIN) == BUTTON_STAR_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_STAR; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_NUM_PIN) == BUTTON_NUM_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_NUM; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_UP_PIN) == BUTTON_UP_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_UP; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_DOWN_PIN) == BUTTON_DOWN_PIN) { simpliciti_flag |= SIMPLICITI_TRIGGER_STOP; } // Trigger packet sending inside SimpliciTI stack if (simpliciti_button_event) simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA; } else // Normal operation { // Debounce buttons if ((int_flag & ALL_BUTTONS) != 0) { // Disable PORT2 IRQ __disable_interrupt(); BUTTONS_IE = 0x00; __enable_interrupt(); // Debounce delay 1 Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_IN)); // Reset inactivity detection sTime.last_activity = sTime.system_time; } // --------------------------------------------------- // STAR button IRQ if (IRQ_TRIGGERED(int_flag, BUTTON_STAR_PIN)) { // Filter bouncing noise if (BUTTON_STAR_IS_PRESSED) { button.flag.star = 1; button.flag.star_not_long = 0; // Generate button click buzzer = 1; } else if ((BUTTONS_IES & BUTTON_STAR_PIN) == BUTTON_STAR_PIN) { button.flag.star = 1; button.flag.star_not_long = 0; BUTTONS_IES &= ~BUTTON_STAR_PIN; } } // --------------------------------------------------- // NUM button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_NUM_PIN)) { // Filter bouncing noise if (BUTTON_NUM_IS_PRESSED) { button.flag.num = 1; button.flag.num_not_long = 0; // Generate button click buzzer = 1; } else if ((BUTTONS_IES & BUTTON_NUM_PIN) == BUTTON_NUM_PIN) { button.flag.num = 1; button.flag.num_not_long = 0; BUTTONS_IES &= ~BUTTON_NUM_PIN; } } // --------------------------------------------------- // UP button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_UP_PIN)) { // Filter bouncing noise if (BUTTON_UP_IS_PRESSED) { button.flag.up = 1; // Generate button click buzzer = 1; } } // --------------------------------------------------- // DOWN button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_DOWN_PIN)) { // Filter bouncing noise if (BUTTON_DOWN_IS_PRESSED) { button.flag.down = 1; // Generate button click buzzer = 1; // Faster reaction for stopwatch stop button press if (is_stopwatch() && !sys.flag.lock_buttons) { stop_stopwatch(); button.flag.down = 0; } } } // --------------------------------------------------- // B/L button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_BACKLIGHT_PIN)) { // Filter bouncing noise if (BUTTON_BACKLIGHT_IS_PRESSED) { sButton.backlight_status = 1; sButton.backlight_timeout = 0; P2OUT |= BUTTON_BACKLIGHT_PIN; P2DIR |= BUTTON_BACKLIGHT_PIN; } } } // Trying to lock/unlock buttons? if (button.flag.num && button.flag.down) { // No buzzer output buzzer = 0; button.all_flags = 0; } // Generate button click when button was activated if (buzzer) { // Any button event stops active alarm if (sAlarm.state == ALARM_ON) { stop_alarm(); button.all_flags = 0; } else if (!sys.flag.up_down_repeat_enabled) { start_buzzer(1, CONV_MS_TO_TICKS(20), CONV_MS_TO_TICKS(150)); } // Debounce delay 2 Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); } // --------------------------------------------------- // Acceleration sensor IRQ if (IRQ_TRIGGERED(int_flag, AS_INT_PIN)) { // Get data from sensor request.flag.acceleration_measurement = 1; } // --------------------------------------------------- // Pressure sensor IRQ if (IRQ_TRIGGERED(int_flag, PS_INT_PIN)) { // Get data from sensor request.flag.altitude_measurement = 1; } // --------------------------------------------------- // Safe long button event detection if (button.flag.star || button.flag.num) { // Additional debounce delay to enable safe high detection - 50ms Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_LEFT)); // Check if this button event is short enough if (BUTTON_STAR_IS_PRESSED) { // Change interrupt edge to detect button release BUTTONS_IES |= BUTTON_STAR_PIN; button.flag.star = 0; // This flag is used to detect if the user released the button before the // time for a long button press (3s) button.flag.star_not_long = 1; } if (BUTTON_NUM_IS_PRESSED) { // Change interrupt edge to detect button release BUTTONS_IES |= BUTTON_NUM_PIN; button.flag.num = 0; // This flag is used to detect if the user released the button before the // time for a long button press (3s) button.flag.num_not_long = 1; } } } // Reenable PORT2 IRQ __disable_interrupt(); BUTTONS_IFG = 0x00; BUTTONS_IE = int_enable; __enable_interrupt(); // Exit from LPM3/LPM4 on RETI __bic_SR_register_on_exit(LPM4_bits); }
__interrupt void PORT2_ISR(void) { u8 int_flag, int_enable; u8 buzzer = 0; u8 simpliciti_button_event = 0; static u8 simpliciti_button_repeat = 0; // Clear button flags button.all_flags = 0; // Remember interrupt enable bits int_enable = BUTTONS_IE; // Store valid button interrupt flag int_flag = BUTTONS_IFG & int_enable; // --------------------------------------------------- // While SimpliciTI stack is active, buttons behave differently: // - Store M1/M2/S1 button events in SimpliciTI packet data // - Exit SimpliciTI when S2 was pressed if (is_rf()) { // Erase previous button press after a number of resends (increase number if link quality is low) // This will create a series of packets containing the same button press // Necessary because we have no acknowledge // Filtering (edge detection) will be done by receiver software if (simpliciti_button_repeat++ > 6) { simpliciti_data[0] &= ~0xF0; simpliciti_button_repeat = 0; } if ((int_flag & BUTTON_M1_PIN) == BUTTON_M1_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_M1; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_M2_PIN) == BUTTON_M2_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_M2; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_S1_PIN) == BUTTON_S1_PIN) { simpliciti_data[0] |= SIMPLICITI_BUTTON_S1; simpliciti_button_event = 1; } else if ((int_flag & BUTTON_S2_PIN) == BUTTON_S2_PIN) { simpliciti_flag |= SIMPLICITI_TRIGGER_STOP; } // Trigger packet sending inside SimpliciTI stack if (simpliciti_button_event) simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA; } else // Normal operation { // Debounce buttons if ((int_flag & ALL_BUTTONS) != 0) { // Disable PORT2 IRQ __disable_interrupt(); BUTTONS_IE = 0x00; __enable_interrupt(); // Debounce delay 1 Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_IN)); // Reset inactivity detection sTime.last_activity = sTime.system_time; // Reset M button high detection sTime.previous_m_button_event = sTime.system_time; } // --------------------------------------------------- // M1 button IRQ if (IRQ_TRIGGERED(int_flag, BUTTON_M1_PIN)) { // Filter bouncing noise if (BUTTON_M1_IS_PRESSED) { button.flag.m1 = 1; sys.flag.mask_m1_button = 0; // Generate button click buzzer = 1; } } // --------------------------------------------------- // M2 button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_M2_PIN)) { // Filter bouncing noise if (BUTTON_M2_IS_PRESSED) { button.flag.m2 = 1; sys.flag.mask_m2_button = 0; // Generate button click buzzer = 1; } } // --------------------------------------------------- // S1 button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_S1_PIN)) { // Filter bouncing noise if (BUTTON_S1_IS_PRESSED) { button.flag.s1 = 1; // Generate button click buzzer = 1; } } // --------------------------------------------------- // S2 button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_S2_PIN)) { // Filter bouncing noise if (BUTTON_S2_IS_PRESSED) { button.flag.s2 = 1; // Generate button click buzzer = 1; // Faster reaction for stopwatch stop button press if (is_stopwatch()) { stop_stopwatch(); button.flag.s2 = 0; } } } // --------------------------------------------------- // B/L button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_BL_PIN)) { // Filter bouncing noise if (BUTTON_BL_IS_PRESSED) { button.flag.bl = 1; } } } // Generate button click when button was activated if (buzzer) { // Any button event stops active alarm if (sAlarm.state == ALARM_ON) { stop_alarm(); button.all_flags = 0; } else if (!sys.flag.s_button_repeat_enabled) { start_buzzer(1, CONV_MS_TO_TICKS(20), CONV_MS_TO_TICKS(150)); } // Debounce delay 2 Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); } // --------------------------------------------------- // Acceleration sensor IRQ if (IRQ_TRIGGERED(int_flag, AS_INT_PIN)) { // Get data from sensor request.flag.acceleration_measurement = 1; } // --------------------------------------------------- // Pressure sensor IRQ if (IRQ_TRIGGERED(int_flag, PS_INT_PIN)) { // Get data from sensor request.flag.altitude_measurement = 1; } // --------------------------------------------------- // Enable safe long button event detection if(button.flag.m1 || button.flag.m2) { // Additional debounce delay to enable safe high detection Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_M)); // Check if this button event is short enough if (BUTTON_M1_IS_PRESSED) button.flag.m1 = 0; if (BUTTON_M2_IS_PRESSED) button.flag.m2 = 0; } // Reenable PORT2 IRQ __disable_interrupt(); BUTTONS_IFG = 0x00; BUTTONS_IE = int_enable; __enable_interrupt(); // Exit from LPM3/LPM4 on RETI __bic_SR_register_on_exit(LPM4_bits); }
__interrupt void PORT2_ISR(void) { // Clear flags unsigned char int_flag, int_enable; unsigned char buzzer = 0; // Remember interrupt enable bits int_enable = BUTTONS_IE; if ((!button.flag.star_long) && (!button.flag.num_long)) { // Clear button flags button.all_flags = 0; // Store valid button interrupt flag int_flag = BUTTONS_IFG & int_enable; { // Debounce buttons if ((int_flag & ALL_BUTTONS) != 0) { // Disable PORT2 IRQ __disable_interrupt(); BUTTONS_IE = 0x00; __enable_interrupt(); // Debounce delay 1 Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_IN)); } // --------------------------------------------------- // STAR button IRQ if (IRQ_TRIGGERED(int_flag, BUTTON_STAR_PIN)) { // Filter bouncing noise if (BUTTON_STAR_IS_PRESSED) { button.flag.star = 1; button.flag.star_not_long = 0; // Generate button click buzzer = 1; } else if ((BUTTONS_IES & BUTTON_STAR_PIN) == BUTTON_STAR_PIN) { button.flag.star = 1; button.flag.star_not_long = 0; BUTTONS_IES &= ~BUTTON_STAR_PIN; } } // --------------------------------------------------- // NUM button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_NUM_PIN)) { // Filter bouncing noise if (BUTTON_NUM_IS_PRESSED) { button.flag.num = 1; button.flag.num_not_long = 0; // Generate button click buzzer = 1; } else if ((BUTTONS_IES & BUTTON_NUM_PIN) == BUTTON_NUM_PIN) { button.flag.num = 1; button.flag.num_not_long = 0; BUTTONS_IES &= ~BUTTON_NUM_PIN; } } // --------------------------------------------------- // UP button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_UP_PIN)) { // Filter bouncing noise if (BUTTON_UP_IS_PRESSED) { button.flag.up = 1; // Generate button click buzzer = 1; } } // --------------------------------------------------- // DOWN button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_DOWN_PIN)) { // Filter bouncing noise if (BUTTON_DOWN_IS_PRESSED) { button.flag.down = 1; // Generate button click buzzer = 1; // Faster reaction for stopwatch stop button press if (is_stopwatch() && !sys.flag.lock_buttons) { stop_stopwatch(); button.flag.down = 0; } } } // --------------------------------------------------- // B/L button IRQ else if (IRQ_TRIGGERED(int_flag, BUTTON_BACKLIGHT_PIN)) { // Filter bouncing noise if (BUTTON_BACKLIGHT_IS_PRESSED) { sButton.backlight_status = 1; sButton.backlight_timeout = 0; P2OUT |= BUTTON_BACKLIGHT_PIN; P2DIR |= BUTTON_BACKLIGHT_PIN; } } } // Trying to lock/unlock buttons? if (button.flag.num && button.flag.down) { // No buzzer output buzzer = 0; button.all_flags = 0; } // --------------------------------------------------- // Acceleration sensor IRQ if (IRQ_TRIGGERED(int_flag, AS_INT_PIN)) { // Get data from sensor request.flag.acceleration_measurement = 1; } // --------------------------------------------------- // Safe long button event detection if (button.flag.star || button.flag.num) { // Additional debounce delay to enable safe high detection - 50ms Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_LEFT)); // Check if this button event is short enough if (BUTTON_STAR_IS_PRESSED) { // Change interrupt edge to detect button release BUTTONS_IES |= BUTTON_STAR_PIN; button.flag.star = 0; // This flag is used to detect if the user released the button before the // time for a long button press (3s) button.flag.star_not_long = 1; } if (BUTTON_NUM_IS_PRESSED) { // Change interrupt edge to detect button release BUTTONS_IES |= BUTTON_NUM_PIN; button.flag.num = 0; // This flag is used to detect if the user released the button before the // time for a long button press (3s) button.flag.num_not_long = 1; } } } // Reenable PORT2 IRQ __disable_interrupt(); BUTTONS_IFG = 0x00; BUTTONS_IE = int_enable; __enable_interrupt(); // Exit from LPM3/LPM4 on RETI __bic_SR_register_on_exit(LPM4_bits); }