EZ430 Chronos 自带程序源码:rfsimpliciti 示范程序
rfsimpliciti.c
// ************************************************************************************************* // // Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // ************************************************************************************************* // SimpliciTI functions. // ************************************************************************************************* // ************************************************************************************************* // Include section // system #include "project.h" // driver #include "display.h" #include "vti_as.h" #include "ports.h" #include "timer.h" #include "radio.h" // logic #include "acceleration.h" #include "rfsimpliciti.h" #include "bluerobin.h" #include "simpliciti.h" #include "clock.h" #include "date.h" #include "alarm.h" #include "temperature.h" #include "vti_ps.h" #include "altitude.h" // ************************************************************************************************* // Prototypes section void simpliciti_get_data_callback(void); void start_simpliciti_tx_only(simpliciti_mode_t mode); void start_simpliciti_sync(void); // ************************************************************************************************* // Defines section // Each packet index requires 2 bytes, so we can have 9 packet indizes in 18 bytes usable payload #define BM_SYNC_BURST_PACKETS_IN_DATA (9u) // ************************************************************************************************* // Global Variable section struct RFsmpl sRFsmpl; // flag contains status information, trigger to send data and trigger to exit SimpliciTI unsigned char simpliciti_flag; // 4 data bytes to send unsigned char simpliciti_data[SIMPLICITI_MAX_PAYLOAD_LENGTH]; // 4 byte device address overrides SimpliciTI end device address set in "smpl_config.dat" unsigned char simpliciti_ed_address[4]; // Length of data unsigned char simpliciti_payload_length; // 1 = send one or more reply packets, 0 = no need to reply //unsigned char simpliciti_reply; unsigned char simpliciti_reply_count; // 1 = send packets sequentially from burst_start to burst_end, 2 = send packets addressed by their index u8 burst_mode; // Start and end index of packets to send out u16 burst_start, burst_end; // Array containing requested packets u16 burst_packet[BM_SYNC_BURST_PACKETS_IN_DATA]; // Current packet index u8 burst_packet_index; // ************************************************************************************************* // Extern section extern void (*fptr_lcd_function_line1)(u8 line, u8 update); // ************************************************************************************************* // @fn reset_rf // @brief Reset SimpliciTI data. // @param none // @return none // ************************************************************************************************* void reset_rf(void) { // No connection sRFsmpl.mode = SIMPLICITI_OFF; // Standard packets are 4 bytes long simpliciti_payload_length = 4; } // ************************************************************************************************* // @fn sx_rf // @brief Start SimpliciTI. Button DOWN connects/disconnects to access point. // @param u8 line LINE2 // @return none // ************************************************************************************************* void sx_rf(u8 line) { // Exit if battery voltage is too low for radio operation if (sys.flag.low_battery) return; // Exit if BlueRobin stack is active if (is_bluerobin()) return; // Start SimpliciTI in tx only mode start_simpliciti_tx_only(SIMPLICITI_ACCELERATION); } // ************************************************************************************************* // @fn sx_ppt // @brief Start SimpliciTI. Button DOWN connects/disconnects to access point. // @param u8 line LINE2 // @return none // ************************************************************************************************* void sx_ppt(u8 line) { // Exit if battery voltage is too low for radio operation if (sys.flag.low_battery) return; // Exit if BlueRobin stack is active if (is_bluerobin()) return; // Start SimpliciTI in tx only mode start_simpliciti_tx_only(SIMPLICITI_BUTTONS); } // ************************************************************************************************* // @fn sx_sync // @brief Start SimpliciTI. Button DOWN connects/disconnects to access point. // @param u8 line LINE2 // @return none // ************************************************************************************************* void sx_sync(u8 line) { // Exit if battery voltage is too low for radio operation if (sys.flag.low_battery) return; // Exit if BlueRobin stack is active if (is_bluerobin()) return; // Start SimpliciTI in sync mode start_simpliciti_sync(); } // ************************************************************************************************* // @fn start_simpliciti_tx_only // @brief Start SimpliciTI (tx only). // @param simpliciti_state_t SIMPLICITI_ACCELERATION, SIMPLICITI_BUTTONS // @return none // ************************************************************************************************* void start_simpliciti_tx_only(simpliciti_mode_t mode) { // Display time in line 1 clear_line(LINE1); fptr_lcd_function_line1(LINE1, DISPLAY_LINE_CLEAR); display_time(LINE1, DISPLAY_LINE_UPDATE_FULL); // Preset simpliciti_data with mode (key or mouse click) and clear other data bytes if (mode == SIMPLICITI_ACCELERATION) { simpliciti_data[0] = SIMPLICITI_MOUSE_EVENTS; } else { simpliciti_data[0] = SIMPLICITI_KEY_EVENTS; } simpliciti_data[1] = 0; simpliciti_data[2] = 0; simpliciti_data[3] = 0; // Turn on beeper icon to show activity display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON); display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON); display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_ON); // Debounce button event Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); // Prepare radio for RF communication open_radio(); // Set SimpliciTI mode sRFsmpl.mode = mode; // Set SimpliciTI timeout to save battery power sRFsmpl.timeout = SIMPLICITI_TIMEOUT; // Start SimpliciTI stack. Try to link to access point. // Exit with timeout or by a button DOWN press. if (simpliciti_link()) { if (mode == SIMPLICITI_ACCELERATION) { // Start acceleration sensor as_start(); } // Enter TX only routine. This will transfer button events and/or acceleration data to access point. simpliciti_main_tx_only(); } // Set SimpliciTI state to OFF sRFsmpl.mode = SIMPLICITI_OFF; // Stop acceleration sensor as_stop(); // Powerdown radio close_radio(); // Clear last button events Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); BUTTONS_IFG = 0x00; button.all_flags = 0; // Clear icons display_symbol(LCD_ICON_BEEPER1, SEG_OFF_BLINK_OFF); display_symbol(LCD_ICON_BEEPER2, SEG_OFF_BLINK_OFF); display_symbol(LCD_ICON_BEEPER3, SEG_OFF_BLINK_OFF); // Clean up line 1 clear_line(LINE1); display_time(LINE1, DISPLAY_LINE_CLEAR); // Force full display update display.flag.full_update = 1; } // ************************************************************************************************* // @fn display_rf // @brief SimpliciTI display routine. // @param u8 line LINE2 // u8 update DISPLAY_LINE_UPDATE_FULL // @return none // ************************************************************************************************* void display_rf(u8 line, u8 update) { if (update == DISPLAY_LINE_UPDATE_FULL) { display_chars(LCD_SEG_L2_5_0, (u8 *)" ACC", SEG_ON); } } // ************************************************************************************************* // @fn display_ppt // @brief SimpliciTI display routine. // @param u8 line LINE2 // u8 update DISPLAY_LINE_UPDATE_FULL // @return none // ************************************************************************************************* void display_ppt(u8 line, u8 update) { if (update == DISPLAY_LINE_UPDATE_FULL) { display_chars(LCD_SEG_L2_5_0, (u8 *)" PPT", SEG_ON); } } // ************************************************************************************************* // @fn display_sync // @brief SimpliciTI display routine. // @param u8 line LINE2 // u8 update DISPLAY_LINE_UPDATE_FULL // @return none // ************************************************************************************************* void display_sync(u8 line, u8 update) { if (update == DISPLAY_LINE_UPDATE_FULL) { display_chars(LCD_SEG_L2_5_0, (u8 *)" SYNC", SEG_ON); } } // ************************************************************************************************* // @fn is_rf // @brief Returns TRUE if SimpliciTI receiver is connected. // @param none // @return u8 // ************************************************************************************************* u8 is_rf(void) { return (sRFsmpl.mode != SIMPLICITI_OFF); } // ************************************************************************************************* // @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 start_simpliciti_sync // @brief Start SimpliciTI (sync mode). // @param none // @return none // ************************************************************************************************* void start_simpliciti_sync(void) { // Clear LINE1 clear_line(LINE1); fptr_lcd_function_line1(LINE1, DISPLAY_LINE_CLEAR); // Stop acceleration sensor as_stop(); // Get updated altitude start_altitude_measurement(); stop_altitude_measurement(); // Get updated temperature temperature_measurement(FILTER_OFF); // Turn on beeper icon to show activity display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON); display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON); display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_ON); // Debounce button event Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); // Prepare radio for RF communication open_radio(); // Set SimpliciTI mode sRFsmpl.mode = SIMPLICITI_SYNC; // Set SimpliciTI timeout to save battery power sRFsmpl.timeout = SIMPLICITI_TIMEOUT; // Start SimpliciTI stack. Try to link to access point. // Exit with timeout or by a button DOWN press. if (simpliciti_link()) { // Enter sync routine. This will send ready-to-receive packets at regular intervals to the access point. // The access point replies with a command (NOP if no other command is set) simpliciti_main_sync(); } // Set SimpliciTI state to OFF sRFsmpl.mode = SIMPLICITI_OFF; // Powerdown radio close_radio(); // Clear last button events Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT)); BUTTONS_IFG = 0x00; button.all_flags = 0; // Clear icons display_symbol(LCD_ICON_BEEPER1, SEG_OFF_BLINK_OFF); display_symbol(LCD_ICON_BEEPER2, SEG_OFF_BLINK_OFF); display_symbol(LCD_ICON_BEEPER3, SEG_OFF_BLINK_OFF); // Force full display update display.flag.full_update = 1; } // ************************************************************************************************* // @fn simpliciti_sync_decode_ap_cmd_callback // @brief For SYNC mode only: Decode command from access point and trigger actions. // @param none // @return none // ************************************************************************************************* void simpliciti_sync_decode_ap_cmd_callback(void) { u8 i; s16 t1, offset; // Default behaviour is to send no reply packets simpliciti_reply_count = 0; switch (simpliciti_data[0]) { case SYNC_AP_CMD_NOP: break; case SYNC_AP_CMD_GET_STATUS: // Send watch parameters simpliciti_data[0] = SYNC_ED_TYPE_STATUS; // Send single reply packet simpliciti_reply_count = 1; break; case SYNC_AP_CMD_SET_WATCH: // Set watch parameters sys.flag.use_metric_units = (simpliciti_data[1] >> 7) & 0x01; sTime.hour = simpliciti_data[1] & 0x7F; sTime.minute = simpliciti_data[2]; sTime.second = simpliciti_data[3]; sDate.year = (simpliciti_data[4]<<8) + simpliciti_data[5]; sDate.month = simpliciti_data[6]; sDate.day = simpliciti_data[7]; sAlarm.hour = simpliciti_data[8]; sAlarm.minute = simpliciti_data[9]; // Set temperature and temperature offset t1 = (s16)((simpliciti_data[10]<<8) + simpliciti_data[11]); offset = t1 - (sTemp.degrees - sTemp.offset); sTemp.offset = offset; sTemp.degrees = t1; // Set altitude sAlt.altitude = (s16)((simpliciti_data[12]<<8) + simpliciti_data[13]); update_pressure_table(sAlt.altitude, sAlt.pressure, sAlt.temperature); break; case SYNC_AP_CMD_GET_MEMORY_BLOCKS_MODE_1: // Send sequential packets out in a burst simpliciti_data[0] = SYNC_ED_TYPE_MEMORY; // Get burst start and end packet burst_start = (simpliciti_data[1]<<8)+simpliciti_data[2]; burst_end = (simpliciti_data[3]<<8)+simpliciti_data[4]; // Set burst mode burst_mode = 1; // Number of packets to send simpliciti_reply_count = burst_end - burst_start; break; case SYNC_AP_CMD_GET_MEMORY_BLOCKS_MODE_2: // Send specified packets out in a burst simpliciti_data[0] = SYNC_ED_TYPE_MEMORY; // Store the requested packets for (i=0; i<BM_SYNC_BURST_PACKETS_IN_DATA; i++) { burst_packet[i] = (simpliciti_data[i*2+1]<<8)+simpliciti_data[i*2+2]; } // Set burst mode burst_mode = 2; // Number of packets to send simpliciti_reply_count = BM_SYNC_BURST_PACKETS_IN_DATA; break; case SYNC_AP_CMD_ERASE_MEMORY: // Erase data logger memory break; case SYNC_AP_CMD_EXIT: // Exit sync mode simpliciti_flag |= SIMPLICITI_TRIGGER_STOP; break; } } // ************************************************************************************************* // @fn simpliciti_sync_get_data_callback // @brief For SYNC mode only: Access point has requested data. Copy this data into the TX buffer now. // @param u16 index Index used for memory requests // @return none // ************************************************************************************************* void simpliciti_sync_get_data_callback(unsigned int index) { u8 i; // simpliciti_data[0] contains data type and needs to be returned to AP switch (simpliciti_data[0]) { case SYNC_ED_TYPE_STATUS: // Assemble status packet simpliciti_data[1] = (sys.flag.use_metric_units << 7) | (sTime.hour & 0x7F); simpliciti_data[2] = sTime.minute; simpliciti_data[3] = sTime.second; simpliciti_data[4] = sDate.year >> 8; simpliciti_data[5] = sDate.year & 0xFF; simpliciti_data[6] = sDate.month; simpliciti_data[7] = sDate.day; simpliciti_data[8] = sAlarm.hour; simpliciti_data[9] = sAlarm.minute; simpliciti_data[10] = sTemp.degrees >> 8; simpliciti_data[11] = sTemp.degrees & 0xFF; simpliciti_data[12] = sAlt.altitude >> 8; simpliciti_data[13] = sAlt.altitude & 0xFF; break; case SYNC_ED_TYPE_MEMORY: if (burst_mode == 1) { // Set burst packet address simpliciti_data[1] = ((burst_start + index) >> 8) & 0xFF; simpliciti_data[2] = (burst_start + index) & 0xFF; // Assemble payload for (i=3; i<BM_SYNC_DATA_LENGTH; i++) simpliciti_data[i] = index; } else if (burst_mode == 2) { // Set burst packet address simpliciti_data[1] = (burst_packet[index] >> 8) & 0xFF; simpliciti_data[2] = burst_packet[index] & 0xFF; // Assemble payload for (i=3; i<BM_SYNC_DATA_LENGTH; i++) simpliciti_data[i] = index; } break; } }
rfsimpliciti.h
// ************************************************************************************************* // // Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // ************************************************************************************************* #ifndef RFSIMPLICITI_H_ #define RFSIMPLICITI_H_ // ************************************************************************************************* // Include section // ************************************************************************************************* // Prototypes section extern void reset_rf(void); extern void sx_rf(u8 line); extern void sx_ppt(u8 line); extern void sx_sync(u8 line); extern void display_rf(u8 line, u8 update); extern void display_ppt(u8 line, u8 update); extern void display_sync(u8 line, u8 update); extern void send_smpl_data(u16 data); extern u8 is_rf(void); // ************************************************************************************************* // Defines section // SimpliciTI connection states typedef enum { SIMPLICITI_OFF = 0, // Not connected SIMPLICITI_ACCELERATION, // Transmitting acceleration data and button events SIMPLICITI_BUTTONS, // Transmitting button events SIMPLICITI_SYNC // Syncing } simpliciti_mode_t; // Stop SimpliciTI transmission after 60 minutes to save power #define SIMPLICITI_TIMEOUT (60*60u) // Button flags for SimpliciTI data #define SIMPLICITI_BUTTON_STAR (0x10) #define SIMPLICITI_BUTTON_NUM (0x20) #define SIMPLICITI_BUTTON_UP (0x30) // SimpliciTI mode flag #define SIMPLICITI_MOUSE_EVENTS (0x01) #define SIMPLICITI_KEY_EVENTS (0x02) // ************************************************************************************************* // Global Variable section struct RFsmpl { // SIMPLICITI_OFF, SIMPLICITI_ACCELERATION, SIMPLICITI_BUTTONS simpliciti_mode_t mode; // Timeout until SimpliciTI transmission is automatically stopped u16 timeout; }; extern struct RFsmpl sRFsmpl; extern unsigned char simpliciti_flag; // ************************************************************************************************* // Extern section #endif /*RFSIMPLICITI_H_*/