You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
768 lines
22 KiB
768 lines
22 KiB
// ************************************************************************************************* |
|
// |
|
// 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. |
|
// |
|
// ************************************************************************************************* |
|
// Initialization and control of application. |
|
// ************************************************************************************************* |
|
|
|
// ************************************************************************************************* |
|
// Include section |
|
|
|
// system |
|
#include "project.h" |
|
#include <string.h> |
|
|
|
// driver |
|
#include "clock.h" |
|
#include "display.h" |
|
#include "vti_as.h" |
|
#include "vti_ps.h" |
|
#include "radio.h" |
|
#include "buzzer.h" |
|
#include "ports.h" |
|
#include "timer.h" |
|
#include "pmm.h" |
|
#include "rf1a.h" |
|
|
|
// logic |
|
#include "menu.h" |
|
#include "date.h" |
|
#include "alarm.h" |
|
#include "stopwatch.h" |
|
#include "battery.h" |
|
#include "temperature.h" |
|
#include "altitude.h" |
|
#include "battery.h" |
|
#include "acceleration.h" |
|
//pfs |
|
#ifndef ELIMINATE_BLUEROBIN |
|
#include "bluerobin.h" |
|
#endif |
|
#include "rfsimpliciti.h" |
|
#include "simpliciti.h" |
|
#ifdef CONFIG_TEST |
|
#include "test.h" |
|
#endif |
|
#ifdef CONFIG_EGGTIMER |
|
#include "eggtimer.h" |
|
#endif |
|
#ifdef CONFIG_PHASE_CLOCK |
|
#include "phase_clock.h" |
|
#endif |
|
|
|
#include "mrfi.h" |
|
#include "nwk_types.h" |
|
|
|
|
|
// ************************************************************************************************* |
|
// Prototypes section |
|
void init_application(void); |
|
void init_global_variables(void); |
|
void wakeup_event(void); |
|
void process_requests(void); |
|
void display_update(void); |
|
void idle_loop(void); |
|
void configure_ports(void); |
|
void read_calibration_values(void); |
|
|
|
|
|
// ************************************************************************************************* |
|
// Defines section |
|
|
|
// Number of calibration data bytes in INFOA memory |
|
#define CALIBRATION_DATA_LENGTH (13u) |
|
|
|
|
|
// ************************************************************************************************* |
|
// Global Variable section |
|
|
|
// Variable holding system internal flags |
|
volatile s_system_flags sys; |
|
|
|
// Variable holding flags set by logic modules |
|
volatile s_request_flags request; |
|
|
|
// Variable holding message flags |
|
volatile s_message_flags message; |
|
|
|
// Global radio frequency offset taken from calibration memory |
|
// Compensates crystal deviation from 26MHz nominal value |
|
u8 rf_frequoffset; |
|
|
|
// Function pointers for LINE1 and LINE2 display function |
|
void (*fptr_lcd_function_line1)(u8 line, u8 update); |
|
void (*fptr_lcd_function_line2)(u8 line, u8 update); |
|
|
|
// ************************************************************************************************* |
|
// Extern section |
|
|
|
extern void start_simpliciti_sync(void); |
|
|
|
extern u16 ps_read_register(u8 address, u8 mode); |
|
extern u8 ps_write_register(u8 address, u8 data); |
|
|
|
// rf hardware address |
|
static const addr_t sMyROMAddress = {THIS_DEVICE_ADDRESS}; |
|
|
|
// ************************************************************************************************* |
|
// @fn main |
|
// @brief Main routine |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
int main(void) |
|
{ |
|
// Init MCU |
|
init_application(); |
|
|
|
// Assign initial value to global variables |
|
init_global_variables(); |
|
|
|
#ifdef CONFIG_TEST |
|
// Branch to welcome screen |
|
test_mode(); |
|
#else |
|
display_all_off(); |
|
#endif |
|
|
|
// Main control loop: wait in low power mode until some event needs to be processed |
|
while(1) |
|
{ |
|
// When idle go to LPM3 |
|
idle_loop(); |
|
|
|
// Process wake-up events |
|
if (button.all_flags || sys.all_flags) wakeup_event(); |
|
|
|
// Process actions requested by logic modules |
|
if (request.all_flags) process_requests(); |
|
|
|
// Before going to LPM3, update display |
|
if (display.all_flags) display_update(); |
|
} |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn init_application |
|
// @brief Initialize the microcontroller. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void init_application(void) |
|
{ |
|
volatile unsigned char *ptr; |
|
|
|
// --------------------------------------------------------------------- |
|
// Enable watchdog |
|
|
|
// Watchdog triggers after 16 seconds when not cleared |
|
#ifdef USE_WATCHDOG |
|
WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK; |
|
#else |
|
WDTCTL = WDTPW + WDTHOLD; |
|
#endif |
|
|
|
// --------------------------------------------------------------------- |
|
// Configure PMM |
|
SetVCore(3); |
|
|
|
// Set global high power request enable |
|
PMMCTL0_H = 0xA5; |
|
PMMCTL0_L |= PMMHPMRE; |
|
PMMCTL0_H = 0x00; |
|
|
|
// --------------------------------------------------------------------- |
|
// Enable 32kHz ACLK |
|
P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1 |
|
UCSCTL6 &= ~XT1OFF; // XT1 On, Highest drive strength |
|
UCSCTL6 |= XCAP_3; // Internal load cap |
|
|
|
UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference |
|
UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; |
|
|
|
// --------------------------------------------------------------------- |
|
// Configure CPU clock for 12MHz |
|
_BIS_SR(SCG0); // Disable the FLL control loop |
|
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx |
|
UCSCTL1 = DCORSEL_5; // Select suitable range |
|
UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier |
|
_BIC_SR(SCG0); // Enable the FLL control loop |
|
|
|
// Worst-case settling time for the DCO when the DCO range bits have been |
|
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx |
|
// UG for optimization. |
|
// 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle |
|
__delay_cycles(250000); |
|
|
|
// Loop until XT1 & DCO stabilizes, use do-while to insure that |
|
// body is executed at least once |
|
do |
|
{ |
|
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); |
|
SFRIFG1 &= ~OFIFG; // Clear fault flags |
|
} while ((SFRIFG1 & OFIFG)); |
|
|
|
|
|
// --------------------------------------------------------------------- |
|
// Configure port mapping |
|
|
|
// Disable all interrupts |
|
__disable_interrupt(); |
|
// Get write-access to port mapping registers: |
|
PMAPPWD = 0x02D52; |
|
// Allow reconfiguration during runtime: |
|
PMAPCTL = PMAPRECFG; |
|
|
|
// P2.7 = TA0CCR1A or TA1CCR0A output (buzzer output) |
|
ptr = &P2MAP0; |
|
*(ptr+7) = PM_TA1CCR0A; |
|
P2OUT &= ~BIT7; |
|
P2DIR |= BIT7; |
|
|
|
// P1.5 = SPI MISO input |
|
ptr = &P1MAP0; |
|
*(ptr+5) = PM_UCA0SOMI; |
|
// P1.6 = SPI MOSI output |
|
*(ptr+6) = PM_UCA0SIMO; |
|
// P1.7 = SPI CLK output |
|
*(ptr+7) = PM_UCA0CLK; |
|
|
|
// Disable write-access to port mapping registers: |
|
PMAPPWD = 0; |
|
// Re-enable all interrupts |
|
__enable_interrupt(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Configure ports |
|
|
|
// --------------------------------------------------------------------- |
|
// Reset radio core |
|
radio_reset(); |
|
radio_powerdown(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Init acceleration sensor |
|
as_init(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Init LCD |
|
lcd_init(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Init buttons |
|
init_buttons(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Configure Timer0 for use by the clock and delay functions |
|
Timer0_Init(); |
|
|
|
// --------------------------------------------------------------------- |
|
// Init pressure sensor |
|
ps_init(); |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn init_global_variables |
|
// @brief Initialize global variables. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void init_global_variables(void) |
|
{ |
|
// -------------------------------------------- |
|
// Apply default settings |
|
|
|
// set menu pointers to default menu items |
|
ptrMenu_L1 = &menu_L1_Time; |
|
// ptrMenu_L1 = &menu_L1_Alarm; |
|
// ptrMenu_L1 = &menu_L1_Heartrate; |
|
// ptrMenu_L1 = &menu_L1_Speed; |
|
// ptrMenu_L1 = &menu_L1_Temperature; |
|
// ptrMenu_L1 = &menu_L1_Altitude; |
|
// ptrMenu_L1 = &menu_L1_Acceleration; |
|
ptrMenu_L2 = &menu_L2_Date; |
|
// ptrMenu_L2 = &menu_L2_Stopwatch; |
|
// ptrMenu_L2 = &menu_L2_Rf; |
|
// ptrMenu_L2 = &menu_L2_Ppt; |
|
// ptrMenu_L2 = &menu_L2_Sync; |
|
// ptrMenu_L2 = &menu_L2_Distance; |
|
// ptrMenu_L2 = &menu_L2_Calories; |
|
// ptrMenu_L2 = &menu_L2_Battery; |
|
// ptrMenu_L2 = &menu_L2_Phase; |
|
|
|
// Assign LINE1 and LINE2 display functions |
|
fptr_lcd_function_line1 = ptrMenu_L1->display_function; |
|
fptr_lcd_function_line2 = ptrMenu_L2->display_function; |
|
|
|
// Init system flags |
|
button.all_flags = 0; |
|
sys.all_flags = 0; |
|
request.all_flags = 0; |
|
display.all_flags = 0; |
|
message.all_flags = 0; |
|
|
|
// Force full display update when starting up |
|
display.flag.full_update = 1; |
|
|
|
#ifndef ISM_US |
|
// Use metric units when displaying values |
|
sys.flag.use_metric_units = 1; |
|
#else |
|
#ifdef CONFIG_METRIC_ONLY |
|
sys.flag.use_metric_units = 1; |
|
#endif |
|
#endif |
|
|
|
// Read calibration values from info memory |
|
read_calibration_values(); |
|
|
|
// Set system time to default value |
|
reset_clock(); |
|
|
|
// Set date to default value |
|
reset_date(); |
|
|
|
// Set alarm time to default value |
|
reset_alarm(); |
|
|
|
// Set buzzer to default value |
|
reset_buzzer(); |
|
|
|
// Reset stopwatch |
|
reset_stopwatch(); |
|
|
|
// Reset altitude measurement |
|
#ifdef CONFIG_ALTITUDE |
|
reset_altitude_measurement(); |
|
#endif |
|
|
|
// Reset acceleration measurement |
|
reset_acceleration(); |
|
|
|
// Reset BlueRobin stack |
|
//pfs |
|
#ifndef ELIMINATE_BLUEROBIN |
|
reset_bluerobin(); |
|
#endif |
|
|
|
#ifdef CONFIG_EGGTIMER |
|
//Set Eggtimer to a 5 minute default |
|
memcpy(seggtimer.defaultTime, "00010000", sizeof(seggtimer.time)); |
|
reset_eggtimer(); |
|
#endif |
|
|
|
#ifdef CONFIG_PROUT |
|
reset_prout(); |
|
#endif |
|
|
|
#ifdef CONFIG_VARIO |
|
reset_vario(); |
|
#endif |
|
|
|
#ifdef CONFIG_PHASE_CLOCK |
|
// default program |
|
sPhase.program = 0; |
|
#endif |
|
|
|
// Reset SimpliciTI stack |
|
reset_rf(); |
|
|
|
// Reset temperature measurement |
|
reset_temp_measurement(); |
|
|
|
// Reset battery measurement |
|
reset_batt_measurement(); |
|
battery_measurement(); |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn wakeup_event |
|
// @brief Process external / internal wakeup events. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void wakeup_event(void) |
|
{ |
|
// Enable idle timeout |
|
sys.flag.idle_timeout_enabled = 1; |
|
|
|
// If buttons are locked, only display "buttons are locked" message |
|
if (button.all_flags && sys.flag.lock_buttons) |
|
{ |
|
// Show "buttons are locked" message synchronously with next second tick |
|
if (!(BUTTON_NUM_IS_PRESSED && BUTTON_DOWN_IS_PRESSED)) |
|
{ |
|
message.flag.prepare = 1; |
|
message.flag.type_locked = 1; |
|
} |
|
|
|
// Clear buttons |
|
button.all_flags = 0; |
|
} |
|
// Process long button press event (while button is held) |
|
else if (button.flag.star_long) |
|
{ |
|
// Clear button event |
|
button.flag.star_long = 0; |
|
|
|
// Call sub menu function |
|
ptrMenu_L1->mx_function(LINE1); |
|
|
|
// Set display update flag |
|
display.flag.full_update = 1; |
|
} |
|
else if (button.flag.num_long) |
|
{ |
|
// Clear button event |
|
button.flag.num_long = 0; |
|
|
|
// Call sub menu function |
|
ptrMenu_L2->mx_function(LINE2); |
|
|
|
// Set display update flag |
|
display.flag.full_update = 1; |
|
} |
|
// Process single button press event (after button was released) |
|
else if (button.all_flags) |
|
{ |
|
// M1 button event --------------------------------------------------------------------- |
|
// (Short) Advance to next menu item |
|
if(button.flag.star) |
|
{ |
|
// Clean up display before activating next menu item |
|
fptr_lcd_function_line1(LINE1, DISPLAY_LINE_CLEAR); |
|
|
|
// Go to next menu entry |
|
ptrMenu_L1 = ptrMenu_L1->next; |
|
|
|
// Assign new display function |
|
fptr_lcd_function_line1 = ptrMenu_L1->display_function; |
|
|
|
// Set Line1 display update flag |
|
display.flag.line1_full_update = 1; |
|
|
|
// Clear button flag |
|
button.flag.star = 0; |
|
} |
|
// NUM button event --------------------------------------------------------------------- |
|
// (Short) Advance to next menu item |
|
else if(button.flag.num) |
|
{ |
|
// Clean up display before activating next menu item |
|
fptr_lcd_function_line2(LINE2, DISPLAY_LINE_CLEAR); |
|
|
|
// Go to next menu entry |
|
ptrMenu_L2 = ptrMenu_L2->next; |
|
|
|
// Assign new display function |
|
fptr_lcd_function_line2 = ptrMenu_L2->display_function; |
|
|
|
// Set Line2 display update flag |
|
display.flag.line2_full_update = 1; |
|
|
|
// Clear button flag |
|
button.flag.num = 0; |
|
} |
|
// UP button event --------------------------------------------------------------------- |
|
// Activate user function for Line1 menu item |
|
else if(button.flag.up) |
|
{ |
|
// Call direct function |
|
ptrMenu_L1->sx_function(LINE1); |
|
|
|
// Set Line1 display update flag |
|
display.flag.line1_full_update = 1; |
|
|
|
// Clear button flag |
|
button.flag.up = 0; |
|
} |
|
// DOWN button event --------------------------------------------------------------------- |
|
// Activate user function for Line2 menu item |
|
else if(button.flag.down) |
|
{ |
|
// Call direct function |
|
ptrMenu_L2->sx_function(LINE2); |
|
|
|
// Set Line1 display update flag |
|
display.flag.line2_full_update = 1; |
|
|
|
// Clear button flag |
|
button.flag.down = 0; |
|
} |
|
} |
|
|
|
// Process internal events |
|
if (sys.all_flags) |
|
{ |
|
// Idle timeout --------------------------------------------------------------------- |
|
if (sys.flag.idle_timeout) |
|
{ |
|
// Clear timeout flag |
|
sys.flag.idle_timeout = 0; |
|
|
|
// Clear display |
|
clear_display(); |
|
|
|
// Set display update flags |
|
display.flag.full_update = 1; |
|
} |
|
} |
|
|
|
// Disable idle timeout |
|
sys.flag.idle_timeout_enabled = 0; |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn process_requests |
|
// @brief Process requested actions outside ISR context. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void process_requests(void) |
|
{ |
|
// Do temperature measurement |
|
if (request.flag.temperature_measurement) temperature_measurement(FILTER_ON); |
|
|
|
// Do pressure measurement |
|
#ifdef CONFIG_ALTITUDE |
|
if (request.flag.altitude_measurement) do_altitude_measurement(FILTER_ON); |
|
#endif |
|
|
|
// Do acceleration measurement |
|
if (request.flag.acceleration_measurement) do_acceleration_measurement(); |
|
|
|
// Do voltage measurement |
|
if (request.flag.voltage_measurement) battery_measurement(); |
|
|
|
// Generate alarm (two signals every second) |
|
if (request.flag.buzzer) start_buzzer(2, BUZZER_ON_TICKS, BUZZER_OFF_TICKS); |
|
|
|
// Reset request flag |
|
request.all_flags = 0; |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn display_update |
|
// @brief Process display flags and call LCD update routines. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void display_update(void) |
|
{ |
|
u8 line; |
|
u8 string[8]; |
|
|
|
// --------------------------------------------------------------------- |
|
// Call Line1 display function |
|
if (display.flag.full_update || display.flag.line1_full_update) |
|
{ |
|
clear_line(LINE1); |
|
fptr_lcd_function_line1(LINE1, DISPLAY_LINE_UPDATE_FULL); |
|
} |
|
else if (ptrMenu_L1->display_update()) |
|
{ |
|
// Update line1 only when new data is available |
|
fptr_lcd_function_line1(LINE1, DISPLAY_LINE_UPDATE_PARTIAL); |
|
} |
|
|
|
|
|
// --------------------------------------------------------------------- |
|
// If message text should be displayed on Line2, skip normal update |
|
if (message.flag.show) |
|
{ |
|
line = LINE2; |
|
|
|
// Select message to display |
|
if (message.flag.type_locked) memcpy(string, " LO?T", 6); |
|
else if (message.flag.type_unlocked) memcpy(string, " OPEN", 6); |
|
else if (message.flag.type_lobatt) memcpy(string, "LOBATT", 6); |
|
else if (message.flag.type_no_beep_on) memcpy(string, " SILNC", 6); |
|
else if (message.flag.type_no_beep_off) memcpy(string, " BEEP", 6); |
|
else if (message.flag.type_alarm_on) |
|
{ |
|
memcpy(string, " ON", 4); |
|
line = LINE1; |
|
} |
|
else if (message.flag.type_alarm_off) |
|
{ |
|
memcpy(string, " OFF", 4); |
|
line = LINE1; |
|
} |
|
|
|
|
|
// Clear previous content |
|
clear_line(line); |
|
fptr_lcd_function_line2(line, DISPLAY_LINE_CLEAR); |
|
|
|
if (line == LINE2) display_chars(LCD_SEG_L2_5_0, string, SEG_ON); |
|
else display_chars(LCD_SEG_L1_3_0, string, SEG_ON); |
|
|
|
// Next second tick erases message and repaints original screen content |
|
message.all_flags = 0; |
|
message.flag.erase = 1; |
|
} |
|
// --------------------------------------------------------------------- |
|
// Call Line2 display function |
|
else if (display.flag.full_update || display.flag.line2_full_update) |
|
{ |
|
clear_line(LINE2); |
|
fptr_lcd_function_line2(LINE2, DISPLAY_LINE_UPDATE_FULL); |
|
} |
|
else if (ptrMenu_L2->display_update() && !message.all_flags) |
|
{ |
|
// Update line2 only when new data is available |
|
fptr_lcd_function_line2(LINE2, DISPLAY_LINE_UPDATE_PARTIAL); |
|
} |
|
|
|
// --------------------------------------------------------------------- |
|
// Restore blinking icons (blinking memory is cleared when calling set_value) |
|
if (display.flag.full_update) |
|
{ |
|
//pfs |
|
#ifndef ELIMINATE_BLUEROBIN |
|
if (is_bluerobin() == BLUEROBIN_CONNECTED) |
|
{ |
|
// Turn on beeper icon to show activity |
|
display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_OFF); |
|
display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_OFF); |
|
display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_OFF); |
|
} |
|
#endif |
|
} |
|
|
|
// Clear display flag |
|
display.all_flags = 0; |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn to_lpm |
|
// @brief Go to LPM0/3. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void to_lpm(void) |
|
{ |
|
// Go to LPM3 |
|
_BIS_SR(LPM3_bits + GIE); |
|
__no_operation(); |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn idle_loop |
|
// @brief Go to LPM. Service watchdog timer when waking up. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void idle_loop(void) |
|
{ |
|
// To low power mode |
|
to_lpm(); |
|
|
|
#ifdef USE_WATCHDOG |
|
// Service watchdog |
|
WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; |
|
#endif |
|
} |
|
|
|
|
|
// ************************************************************************************************* |
|
// @fn read_calibration_values |
|
// @brief Read calibration values for temperature measurement, voltage measurement |
|
// and radio from INFO memory. |
|
// @param none |
|
// @return none |
|
// ************************************************************************************************* |
|
void read_calibration_values(void) |
|
{ |
|
u8 cal_data[CALIBRATION_DATA_LENGTH]; // Temporary storage for constants |
|
u8 i; |
|
u8 * flash_mem; // Memory pointer |
|
|
|
// Read calibration data from Info D memory |
|
flash_mem = (u8 *)0x1800; |
|
for (i=0; i<CALIBRATION_DATA_LENGTH; i++) |
|
{ |
|
cal_data[i] = *flash_mem++; |
|
} |
|
|
|
if (cal_data[0] == 0xFF) |
|
{ |
|
// If no values are available (i.e. INFO D memory has been erased by user), assign experimentally derived values |
|
rf_frequoffset = 4; |
|
sTemp.offset = -250; |
|
sBatt.offset = -10; |
|
simpliciti_ed_address[0] = sMyROMAddress.addr[0]; |
|
simpliciti_ed_address[1] = sMyROMAddress.addr[1]; |
|
simpliciti_ed_address[2] = sMyROMAddress.addr[2]; |
|
simpliciti_ed_address[3] = sMyROMAddress.addr[3]; |
|
#ifdef CONFIG_ALTITUDE |
|
sAlt.altitude_offset = 0; |
|
#endif |
|
} |
|
else |
|
{ |
|
// Assign calibration data to global variables |
|
rf_frequoffset = cal_data[1]; |
|
// Range check for calibrated FREQEST value (-20 .. + 20 is ok, else use default value) |
|
if ((rf_frequoffset > 20) && (rf_frequoffset < (256-20))) |
|
{ |
|
rf_frequoffset = 0; |
|
} |
|
sTemp.offset = (s16)((cal_data[2] << 8) + cal_data[3]); |
|
sBatt.offset = (s16)((cal_data[4] << 8) + cal_data[5]); |
|
simpliciti_ed_address[0] = cal_data[6]; |
|
simpliciti_ed_address[1] = cal_data[7]; |
|
simpliciti_ed_address[2] = cal_data[8]; |
|
simpliciti_ed_address[3] = cal_data[9]; |
|
// S/W version byte set during calibration? |
|
#ifdef CONFIG_ALTITUDE |
|
if (cal_data[12] != 0xFF) |
|
{ |
|
sAlt.altitude_offset = (s16)((cal_data[10] << 8) + cal_data[11]);; |
|
} |
|
else |
|
{ |
|
sAlt.altitude_offset = 0; |
|
} |
|
#endif |
|
} |
|
} |
|
|
|
|
|
|