// ************************************************************************************************* // @fn do_acceleration_measurement // @brief Get sensor data and store in sAccel struct // @param none // @return none // ************************************************************************************************* void do_acceleration_measurement(void) { // Get data from sensor as_get_data(sAccel.xyz); // Set display update flag display.flag.update_acceleration = 1; }
static void as_event(enum sys_message msg) { if ( (msg & SYS_MSG_RTC_MINUTE) == SYS_MSG_RTC_MINUTE) { if(sAccel.mode == ACCEL_MODE_ON) sAccel.timeout--; //if timeout is over disable the accelerometer if(sAccel.timeout<1) { //disable accelerometer to save power as_stop(); //update the mode to remember sAccel.mode = ACCEL_MODE_OFF; } } if ( (msg & SYS_MSG_AS_INT) == SYS_MSG_AS_INT) { //Check the vti register for status information as_status.all_flags=as_get_status(); //TODO For debugging only _printf(0, LCD_SEG_L1_1_0, "%1u", as_status.all_flags); buzzer_play(smb); //if we were in free fall or motion detection mode check for the event if(as_status.int_status.falldet || as_status.int_status.motiondet){ //if such an event is detected enable the symbol //display_symbol(0, LCD_ICON_ALARM , SEG_SET | BLINK_ON); //read the data as_get_data(sAccel.xyz); //display_data(0); /* update menu screen */ lcd_screen_activate(0); }//if we were in measurment mode do a measurement and put it in the virtual screen else { //display_symbol(0, LCD_ICON_ALARM , SEG_SET | BLINK_OFF); display_data(1); /* refresh to accelerometer screen only if in that modality */ if (submenu_state== VIEW_AXIS )lcd_screen_activate(1); } } /* The 1 Hz timer is used to refresh the menu screen */ if ( (msg & SYS_MSG_RTC_SECOND) == SYS_MSG_RTC_SECOND) { /*check the status register for debugging purposes */ _printf(0, LCD_SEG_L1_1_0, "%1u", as_read_register(ADDR_INT_STATUS)); /* update menu screen */ lcd_screen_activate(0); } }
// ************************************************************************************************* // @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 as_get_data(sAccel.xyz); }
// ************************************************************************************************* // @fn sx_acceleration // @brief Acceleration direct function. Button UP switches between X/Y/Z values. // @param uint8_t line LINE2 // @return none // ************************************************************************************************* void sx_acceleration(uint8_t line) { if (++sAccel.view_style > 2) sAccel.view_style = 0; // Reset current acceleration value sAccel.data = 0; // Get data from sensor as_get_data(sAccel.xyz); // Set display update flag sAccel.update_display = 1; }
// ************************************************************************************************* // @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 DRDY pin indicates new data (set in PORT2 ISR) if (request.flag.acceleration_measurement && ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN)) { // Clear flag request.flag.acceleration_measurement = 0; // Get data from sensor 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; // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; } }
// ************************************************************************************************* // @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*)"0430", SEG_ON); display_chars(LCD_SEG_L2_4_0, (u8*)"CC430", 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 #ifdef CONFIG_ALTITUDE 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(); #endif 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 as_start(); for (i=0; i<4; i++) { Timer0_A4_Delay(CONV_MS_TO_TICKS(250)); as_get_data(sAccel.xyz); str = itoa( sAccel.xyz[0], 3, 0); display_chars(LCD_SEG_L1_2_0, str, SEG_ON); str = itoa( sAccel.xyz[2], 3, 0); display_chars(LCD_SEG_L2_2_0, str, SEG_ON); } as_stop(); break; //pfs #ifndef ELIMINATE_BLUEROBIN 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; #endif } // 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; break; } } }