void do_counter_measurement(void) { extern u16 convert_acceleration_value_to_mgrav(u8 value); u8 i; u16 accel_data, sum1; // Get data from sensor bmp_as_get_data(sCounter.xyz); for ( i = 0, sum1 = 0; i < 3; i ++ ) { accel_data = convert_acceleration_value_to_mgrav(sCounter.xyz[i]); // Filter acceleration #if 0 accel_data = (u16)((accel_data * 0.2) + (sCounter.data[i] * 0.8)); #endif accel_data = (u16)((accel_data * 0.1) + (sCounter.data[i] * 0.9)); sum1 += accel_data; // Store average acceleration sCounter.data[i] = accel_data; } if ( sCounter.sum == 0 ) { sCounter.low = sum1; sCounter.high = sum1; } else { switch ( sCounter.rise_state) { // init state case 0: if ( sum1 > sCounter.sum ) { sCounter.rise_state = 1; sCounter.low = sCounter.sum; } else { sCounter.rise_state = 2; sCounter.high = sCounter.sum; } break; case 1: if ( sum1 < sCounter.sum ) { // change direction sCounter.high = sCounter.sum; sCounter.rise_state = 2; } break; case 2: if ( sum1 > sCounter.sum ) { sCounter.low = sCounter.sum; sCounter.rise_state = 1; do_count(); } break; } } sCounter.sum = sum1; // Set display update flag // display.flag.update_counter = 1; }
// ************************************************************************************************* // @fn sx_acceleration // @brief Acceleration direct function. Button UP switches between X/Y/Z values. // @param u8 line LINE2 // @return none // ************************************************************************************************* void sx_acceleration(u8 line) { if (++sAccel.view_style > 2) sAccel.view_style = 0; // Reset current acceleration value sAccel.data = 0; // Get data from sensor if (bmp_used) { bmp_as_get_data(sAccel.xyz); } }
// ************************************************************************************************* // @fn test_mode // @brief Manual test mode. Activated by holding buttons STAR and UP simultaneously. // Cancelled by any other button press. // @param none // @return none // ************************************************************************************************* void test_mode(void) { u8 test_step, start_next_test; u8 *str; u8 i; // Disable timer - no need for a clock tick Timer0_Stop(); // Disable LCD charge pump while in standby mode // This reduces current consumption by ca. 5µA to ca. 10µA LCDBVCTL = 0; // Show welcome screen display_chars(LCD_SEG_L1_3_0, (u8 *) "TONY", SEG_ON); display_chars(LCD_SEG_L2_4_0, (u8 *) "MAGLA", SEG_ON); display_symbol(LCD_SEG_L1_COL, SEG_ON); display_symbol(LCD_ICON_HEART, SEG_ON); display_symbol(LCD_ICON_STOPWATCH, SEG_ON); display_symbol(LCD_ICON_RECORD, SEG_ON); display_symbol(LCD_ICON_ALARM, SEG_ON); display_symbol(LCD_ICON_BEEPER1, SEG_ON); display_symbol(LCD_ICON_BEEPER2, SEG_ON); display_symbol(LCD_ICON_BEEPER3, SEG_ON); display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); display_symbol(LCD_SYMB_AM, SEG_ON); // Hold watchdog WDTCTL = WDTPW + WDTHOLD; // Wait for button press _BIS_SR(LPM3_bits + GIE); __no_operation(); // Clear display display_all_off(); #ifdef USE_LCD_CHARGE_PUMP // Charge pump voltage generated internally, internal bias (V2-V4) generation // This ensures that the contrast and LCD control is constant for the whole battery lifetime LCDBVCTL = LCDCPEN | VLCD_2_72; #endif // Renenable timer Timer0_Start(); // Debounce button press Timer0_A4_Delay(CONV_MS_TO_TICKS(100)); while (1) { // Check button event if (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED) { // Start with test #0 test_step = 0; start_next_test = 1; while (1) { if (start_next_test) { // Clean up previous test display display_all_off(); start_next_test = 0; switch (test_step) { case 0: // All LCD segments on display_all_on(); // Wait until buttons are off while (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED) ; break; case 1: // Altitude measurement display_altitude(LINE1, DISPLAY_LINE_UPDATE_FULL); for (i = 0; i < 2; i++) { while ((PS_INT_IN & PS_INT_PIN) == 0) ; do_altitude_measurement(FILTER_OFF); display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL); } stop_altitude_measurement(); break; case 2: // Temperature measurement display_temperature(LINE1, DISPLAY_LINE_UPDATE_FULL); for (i = 0; i < 4; i++) { Timer0_A4_Delay(CONV_MS_TO_TICKS(250)); temperature_measurement(FILTER_OFF); display_temperature(LINE1, DISPLAY_LINE_UPDATE_PARTIAL); } break; case 3: // Acceleration measurement if (bmp_used) { bmp_as_start(); } else { cma_as_start(); } for (i = 0; i < 4; i++) { Timer0_A4_Delay(CONV_MS_TO_TICKS(250)); if (bmp_used) { bmp_as_get_data(sAccel.xyz); } else { cma_as_get_data(sAccel.xyz); } str = int_to_array(sAccel.xyz[0], 3, 0); display_chars(LCD_SEG_L1_2_0, str, SEG_ON); str = int_to_array(sAccel.xyz[2], 3, 0); display_chars(LCD_SEG_L2_2_0, str, SEG_ON); } if (bmp_used) { bmp_as_stop(); } else { cma_as_stop(); } break; case 4: // BlueRobin test button.flag.up = 1; sx_bluerobin(LINE1); Timer0_A4_Delay(CONV_MS_TO_TICKS(100)); get_bluerobin_data(); display_heartrate(LINE1, DISPLAY_LINE_UPDATE_FULL); stop_bluerobin(); break; } // Debounce button Timer0_A4_Delay(CONV_MS_TO_TICKS(200)); } // Check button event if (BUTTON_STAR_IS_PRESSED) { test_step = 1; start_next_test = 1; } else if (BUTTON_NUM_IS_PRESSED) { test_step = 2; start_next_test = 1; } else if (BUTTON_UP_IS_PRESSED) { test_step = 3; start_next_test = 1; } else if (BUTTON_DOWN_IS_PRESSED) { test_step = 4; start_next_test = 1; } else if (BUTTON_BACKLIGHT_IS_PRESSED) { // Wait until button has been released (avoid restart) while (BUTTON_BACKLIGHT_IS_PRESSED) ; // Disable LCD and LCD charge pump LCDBCTL0 &= ~BIT0; LCDBVCTL = 0; // Debounce button press Timer0_A4_Delay(CONV_MS_TO_TICKS(500)); // Disable timer - no need for a clock tick Timer0_Stop(); // Hold watchdog WDTCTL = WDTPW + WDTHOLD; // Sleep until button is pressed (ca. 4µA current consumption) _BIS_SR(LPM4_bits + GIE); __no_operation(); // Force watchdog reset for a clean restart WDTCTL = 1; } #ifdef USE_WATCHDOG // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; #endif // To LPM3 _BIS_SR(LPM3_bits + GIE); __no_operation(); } } else { // Debounce button Timer0_A4_Delay(CONV_MS_TO_TICKS(100)); button.all_flags = 0; // Turn off backlight P2OUT &= ~BUTTON_BACKLIGHT_PIN; P2DIR &= ~BUTTON_BACKLIGHT_PIN; break; } } }
// ************************************************************************************************* // @fn simpliciti_get_ed_data_callback // @brief Callback function to read end device data from acceleration sensor (if available) // and trigger sending. Can be also be used to transmit other data at // different packet rates. // Please observe the applicable duty limit in the chosen ISM band. // @param none // @return none // ************************************************************************************************* void simpliciti_get_ed_data_callback(void) { static u8 packet_counter = 0; if (sRFsmpl.mode == SIMPLICITI_ACCELERATION) { // Wait for next sample Timer0_A4_Delay(CONV_MS_TO_TICKS(5)); // Read from sensor if EOC pin indicates new data (set in PORT2 ISR) if (request.flag.acceleration_measurement) { // Clear flag request.flag.acceleration_measurement = 0; // Get data from sensor if (bmp_used) { bmp_as_get_data(sAccel.xyz); } else { cma_as_get_data(sAccel.xyz); } // Transmit only every 3rd data set (= 33 packets / second) if (packet_counter++ > 1) { // Reset counter packet_counter = 0; // Store XYZ data in SimpliciTI variable simpliciti_data[1] = sAccel.xyz[0]; simpliciti_data[2] = sAccel.xyz[1]; simpliciti_data[3] = sAccel.xyz[2]; // Trigger packet sending simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA; } } } else // transmit only button events { // New button event is stored in data if ((packet_counter == 0) && (simpliciti_data[0] & 0xF0) != 0) { packet_counter = 5; } // Send packet several times if (packet_counter > 0) { // Clear button event when sending last packet if (--packet_counter == 0) { simpliciti_data[0] &= ~0xF0; } else { // Trigger packet sending in regular intervals Timer0_A4_Delay(CONV_MS_TO_TICKS(30)); simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA; } } else { // Wait in LPM3 for next button press _BIS_SR(LPM3_bits + GIE); __no_operation(); } } // Update clock every 1/1 second if (display.flag.update_time) { display_time(LINE1, DISPLAY_LINE_UPDATE_PARTIAL); display.flag.update_time = 0; #ifdef USE_WATCHDOG // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; #endif } }