コード例 #1
0
ファイル: main.c プロジェクト: Alucard3571/MetaWatch-WDS11x
void main(void)
{
  /* Turn off the watchdog timer */
  WDTCTL = WDTPW + WDTHOLD;

  /* clear reason for reset */
  SYSRSTIV = 0;
  
  /* disable DMA during read-modify-write cycles */
  DMACTL4 = DMARMWDIS;
  
  unsigned char MspVersion = GetMsp430HardwareRevision();
    
  InitializeCalibrationData();
  
  ConfigureHardware();

  OsalNvInit(0);
  
  InitializeDebugFlags();      
  InitializeButtons();
  InitializeVibration();
  InitializeOneSecondTimers();
  
  InitializeBufferPool();    

  InitializeSppTask();
  
  InitializeRealTimeClock();       

  InitializeBackgroundTask();   

  InitializeDisplayTask();   

  InitializeAdc();
  
#if 0
  /* timeout is 16 seconds */
  hal_SetWatchdogTimeout(16); 
#endif

#ifdef CHECK_FOR_PMM15
  /* make sure error pmm15 does not exist */
  while ( PMM15Check() );
#endif
  
  /* Errata PMM17 - automatic prolongation mechanism 
   * SVSLOW is disabled
   */
  *(unsigned int*)(0x0110) = 0x9602;
  *(unsigned int*)(0x0112) |= 0x0800;
  
  PrintString("Starting Task Scheduler\r\n");
  vTaskStartScheduler();

  /* if vTaskStartScheduler exits an error occured. */
  PrintString("Program Error\r\n");
  ForceWatchdogReset();
  
}
コード例 #2
0
ファイル: DebugUart.c プロジェクト: fcengel/MetaWatch-Gen2
void WhoAmI(void)
{
  PrintS(BR_DEVICE_NAME);
  PrintF("Msp430 Rev:%c HwVer:%d", GetMsp430HardwareRevision(), HardwareVersion());
  PrintF("BoardConfig: %d", GetBoardConfiguration());
  PrintF("Calibration: %d", ValidCalibration());
  PrintF("Errata: %d", Errata());
}
コード例 #3
0
ファイル: LcdBuffer.c プロジェクト: lwalkera/MetaWatch-Gen2
void DrawWatchStatusScreen(void)
{
  FillMyBuffer(0, LCD_ROW_NUM, 0);
  CopyColumnsIntoMyBuffer(RadioOn() ? pRadioOnIcon : pRadioOffIcon,
                          3,
                          STATUS_ICON_SIZE_IN_ROWS,
                          LEFT_STATUS_ICON_COLUMN,
                          STATUS_ICON_SIZE_IN_COLUMNS);
  // Connection status
  CopyColumnsIntoMyBuffer(Connected(CONN_TYPE_MAIN) ? pConnectedIcon : pDisconnectedIcon,
                          3,
                          STATUS_ICON_SIZE_IN_ROWS,
                          CENTER_STATUS_ICON_COLUMN,
                          STATUS_ICON_SIZE_IN_COLUMNS);

  gRow = 31;
  gColumn = 5;
  gBitColumnMask = BIT4;
  SetFont(MetaWatch5);

  if (PairedDeviceType() == DEVICE_TYPE_BLE)
  {
    if (Connected(CONN_TYPE_HFP) && Connected(CONN_TYPE_MAP)) DrawString("DUO", DRAW_OPT_BITWISE_OR);
    else DrawString("BLE", DRAW_OPT_BITWISE_OR);
  }
  else if (PairedDeviceType() == DEVICE_TYPE_SPP) DrawString("BR", DRAW_OPT_BITWISE_OR);

  DrawBatteryOnIdleScreen(6, 9, MetaWatch7);

  // Add Wavy line
  gRow += 12;
  CopyRowsIntoMyBuffer(pWavyLine, gRow, NUMBER_OF_ROWS_IN_WAVY_LINE);
  CopyColumnsIntoMyBuffer(pIconWatch, 54, 21, 0, 2); //54, 21, 2, 2);

  /* add the firmware version */
  gColumn = 2;
  gRow = 56;
  gBitColumnMask = BIT2;
  DrawString("SW: ", DRAW_OPT_BITWISE_OR);
  DrawString((char *)VERSION, DRAW_OPT_BITWISE_OR);
  DrawString(" (", DRAW_OPT_BITWISE_OR);
  DrawChar(BUILD[0], DRAW_OPT_BITWISE_OR);
  DrawChar(BUILD[1], DRAW_OPT_BITWISE_OR);
  DrawChar(BUILD[2], DRAW_OPT_BITWISE_OR);
  DrawChar(')', DRAW_OPT_BITWISE_OR);
  
  gColumn = 2;
  gRow = 65;
  gBitColumnMask = BIT2;
  DrawString("HW: REV ", DRAW_OPT_BITWISE_OR);
  DrawChar(GetMsp430HardwareRevision(), DRAW_OPT_BITWISE_OR);

  DrawLocalAddress(1, 80);
  
  SendMyBufferToLcd(STARTING_ROW, LCD_ROW_NUM);
}
コード例 #4
0
ファイル: TestMode.c プロジェクト: ChrisSewell/MetaWatch-Gen2
/* this function probably belongs somewhere else */
void WhoAmI(void)
{
  extern const char BUILD[];
  extern const char VERSION[];
  PrintString3("Version: ", VERSION,CR);
  PrintString3("Build: ", BUILD,CR);
  
  tVersion Version = GetWrapperVersion();
  PrintString3("Wrapper: ", Version.pSwVer,CR);
  
  PrintString2(SPP_DEVICE_NAME,CR);
  PrintString("Msp430 Version ");
  PrintCharacter(GetMsp430HardwareRevision());
  PrintString(CR);
  
  PrintStringAndDecimal("HwVersion: ", HardwareVersion());
}
コード例 #5
0
ファイル: LcdDisplay.c プロジェクト: DragonWar/MetaWatch-Gen2
/*! Handle the messages routed to the display queue */
static void DisplayQueueMessageHandler(tMessage *pMsg)
{
  tMessage Msg;

  switch (pMsg->Type)
  {
  case ShowCallMsg:
    HandleCallNotification(pMsg->Options, pMsg->pBuffer, pMsg->Length);
    break;

  case WriteBufferMsg:
    WriteBufferHandler(pMsg);
    break;

  case SetWidgetListMsg:
    SetWidgetList(pMsg);
    break;
  
  case UpdateDisplayMsg:
  
    if ((!(pMsg->Options & MSG_OPT_UPD_INTERNAL) &&
        (pMsg->Options & MODE_MASK) == NOTIF_MODE) &&
        GetProperty(PROP_AUTO_BACKLIGHT))
      SendMessage(AutoBacklightMsg, MSG_OPT_NONE);

    UpdateDisplayHandler(pMsg);
    break;

  case DrawMsg:
    DrawMsgHandler(pMsg);
    break;
    
  case UpdateClockMsg:
    UpdateClock();
    break;
    
  case DrawClockWidgetMsg:
    DrawClockWidget(pMsg->Options);
    break;

  case BluetoothStateChangeMsg:
    BluetoothStateChangeHandler(pMsg);
    break;

  case IdleUpdateMsg:
    IdleUpdateHandler();
    break;

  case ButtonStateMsg:
    ButtonStateHandler();
    break;

  case StopTimerMsg:
    StopTimer((eTimerId)pMsg->Options);
    break;

  case MonitorBatteryMsg:
    MonitorBattery();
    break;

  case MusicIconMsg:
      MusicIcon(pMsg->Options);
      break;

  case MusicStateMsg:
    HandleMusicStateChange(pMsg->Options);
    break;
    
  case ChangeModeMsg:
    ChangeMode(pMsg->Options);
    break;
  
  case ControlFullScreenMsg:
    SetProperty(PROP_PHONE_DRAW_TOP, pMsg->Options || *pMsg->pBuffer ? PROP_PHONE_DRAW_TOP : 0);
    break;

  case ModifyTimeMsg:
    ModifyTimeHandler(pMsg);
    break;

  case MenuModeMsg:
    MenuModeHandler(pMsg->Options);
    break;

  case MenuButtonMsg:
    MenuButtonHandler(pMsg->Options);
    break;

  case EnableButtonMsg:
    EnableButtonMsgHandler(pMsg);
    break;

  case DevTypeMsg:

    Msg.Length = 1;
    Msg.Type = DevTypeRespMsg;
    Msg.Options = BOARD_TYPE; //default G2

    if (CreateMessage(&Msg))
    {
      Msg.pBuffer[0] = BOARD_TYPE; // backward compatible

      if (GetMsp430HardwareRevision() < 'F')
      {
        Msg.Options = DIGITAL_WATCH_TYPE_G1;
        Msg.pBuffer[0] = DIGITAL_WATCH_TYPE_G1; // backward compatible
      }

      Msg.Options |= DEV_TYPE_EN_ACK; // support ACK
      RouteMsg(&Msg);
    }

    PrintF("- DevTypeResp:%u", Msg.Options);

    // set ACK and HFP/MAP bits
//    SendMessage(ConnTypeMsg, pMsg->Options);
    break;

  case VerInfoMsg:

    Msg.Length = BUILD_LENGTH + 4 + 3;
    Msg.Type = VerInfoRespMsg;
    Msg.Options = MSG_OPT_NONE;

    if (CreateMessage(&Msg))
    {
      GetBuildNumber(Msg.pBuffer);

      *(Msg.pBuffer + BUILD_LENGTH) = VERSION[0] - ZERO;
      *(Msg.pBuffer + BUILD_LENGTH + 1) = VERSION[2] - ZERO;
      *(Msg.pBuffer + BUILD_LENGTH + 2) = VERSION[4] - ZERO;
      *(Msg.pBuffer + BUILD_LENGTH + 3) = GetMsp430HardwareRevision();
      *(Msg.pBuffer + BUILD_LENGTH + 4) = BootVersion[0] - ZERO;
      *(Msg.pBuffer + BUILD_LENGTH + 5) = BootVersion[2] - ZERO;
      *(Msg.pBuffer + BUILD_LENGTH + 6) = BootVersion[4] - ZERO;

      RouteMsg(&Msg);
    }
    PrintE("-Ver(%u):", Msg.Length); PrintQ(Msg.pBuffer, Msg.Length);
    break;

  case LogMsg:
    SendStateLog();
    break;
    
  case VibrateMsg:
    SetVibrateModeHandler(pMsg);
    break;

  case SetRtcMsg:
    if (SetRtc((Rtc_t *)pMsg->pBuffer)) UpdateClock();
    break;
    
  case CountdownMsg:
    if (pMsg->Options == CDT_ENTER)
    {
      PageType = PAGE_TYPE_INFO;
      CurrentPage[PageType] = CountdownPage;
    }
    CountdownHandler(pMsg->Options);
    break;

  case ServiceMenuMsg:
    ServiceMenuHandler();
    break;

  case FieldTestMsg:
    HandleFieldTestMode(pMsg->Options);
    break;

  case DisableButtonMsg:
    DisableButtonMsgHandler(pMsg);
    break;

  case ReadButtonConfigMsg:
    ReadButtonConfigHandler(pMsg);
    break;

  case SetBacklightMsg:
    SetBacklight(pMsg->Options);
    // testing
//    pMsg->Type = AccelMsg;
//    pMsg->Options = 1; //enable
//    HandleAccelerometer(pMsg);
    break;

  case AutoBacklightMsg:
    if (LightSenseCycle() < DARK_LEVEL) SetBacklight(LED_ON);
    break;

  case BatteryConfigMsg:
    SetBatteryLevels(pMsg->pBuffer);
    break;

  case ReadBatteryVoltageMsg:
    ReadBatteryVoltageHandler();
    break;

  case ResetMsg:
    SoftwareReset(RESET_BUTTON_PRESS, pMsg->Options);
    break;

  case NvalOperationMsg:
    NvalOperationHandler(pMsg);
    break;

  case SecInvertMsg:
    HandleSecInvert(pMsg->Options);
    break;

  case LoadTemplateMsg:
    LoadTemplateHandler(pMsg);
    break;

  case LinkAlarmMsg:
    SendMessage(VibrateMsg, VIBRA_PATTERN_LNKALM);
    break;

  case ModeTimeoutMsg:
    ModeTimeoutHandler();
    break;

  case WatchStatusMsg:
    PageType = PAGE_TYPE_INFO;
    CurrentPage[PageType] = StatusPage;
    DrawWatchStatusScreen(TRUE);
    break;

  case TermModeMsg:
    TermModeHandler();
    break;
    
  case LowBatteryWarningMsg:
    break;
    
  case LowBatteryBtOffMsg:
    UpdateClock();
    break;

#if __IAR_SYSTEMS_ICC__
  case EraseTemplateMsg:
//    EraseTemplateHandler(pMsg);
    break;
    
  case WriteToTemplateMsg:
//    WriteToTemplateHandler(pMsg);
    break;
#endif

  case AccelMsg:
    HandleAccelerometer(pMsg);
    break;

  case ReadLightSensorMsg:
    ReadLightSensorHandler();
    break;

  case WatchDrawnScreenTimeout:
    IdleUpdateHandler();
    break;

  case RateTestMsg:
    /* don't care what data is */
    Msg.Length = 10;
    Msg.Type = DiagnosticLoopback;
    Msg.Options = MSG_OPT_NONE;
    if (CreateMessage(&Msg)) RouteMsg(&Msg);
    break;
    
  default:
    PrintF("# Disp Msg:x%02X", pMsg->Type);
    break;
  }
}
コード例 #6
0
ファイル: LcdDisplay.c プロジェクト: Tangkw/MetaWatch-Gen2
/*! Handle the messages routed to the display queue */
static void DisplayQueueMessageHandler(tMessage* pMsg)
{
  tMessage Msg;
  unsigned char i = 0;

  switch (pMsg->Type)
  {
  case WriteBufferMsg:
    WriteBufferHandler(pMsg);
    break;

  case SetWidgetListMsg:
    SetWidgetList(pMsg);
    break;
  
  case UpdateDisplayMsg:
    UpdateDisplayHandler(pMsg);
    break;
    
  case UpdateClockMsg:
    UpdateClock();
    break;
    
  case DrawClockWidgetMsg:
    DrawClockWidget(pMsg->Options);
    break;

  case MonitorBatteryMsg:
    MonitorBattery();
    break;

  case BluetoothStateChangeMsg:
    BluetoothStateChangeHandler(pMsg);
    break;

  case IdleUpdateMsg:
    IdleUpdateHandler();
    break;

  case ButtonStateMsg:
    ButtonStateHandler();
    break;

  case CallerIdMsg:
//    PrintStringAndDecimal("LcdDisp:CallerId Len:", pMsg->Length);
    pMsg->pBuffer[pMsg->Length] = NULL;
    ShowCall((char *)pMsg->pBuffer, pMsg->Options);
    break;
    
  case CallerNameMsg:
    if (pMsg->Length)
    {
      pMsg->pBuffer[pMsg->Length] = NULL;
      ShowCall((char *)pMsg->pBuffer, SHOW_NOTIF_CALLER_NAME);
    }
    else ShowCall("", pMsg->Options);
    break;

  case MusicPlayStateMsg:
    HandleMusicPlayStateChange(pMsg->Options);
    break;
    
  case ChangeModeMsg:
    ChangeModeHandler(pMsg->Options);
    break;
  
  case ConfigureIdleBufferSize:
    SetProperty(PROP_PHONE_DRAW_TOP, *pMsg->pBuffer ? PROP_PHONE_DRAW_TOP : 0);
    break;

  case ModifyTimeMsg:
    ModifyTimeHandler(pMsg);
    break;

  case MenuModeMsg:
    MenuModeHandler(pMsg->Options);
    break;

  case MenuButtonMsg:
    MenuButtonHandler(pMsg->Options);
    break;

  case EnableButtonMsg:
    EnableButtonMsgHandler(pMsg);
    break;

  case DevTypeMsg:
    SetupMessageAndAllocateBuffer(&Msg, DevTypeRespMsg, MSG_OPT_NONE);
    Msg.Options = BOARD_TYPE; //default G2
    Msg.pBuffer[0] = BOARD_TYPE; // backward compatible

#ifdef WATCH
    if (GetMsp430HardwareRevision() < 'F')
    {
      Msg.Options = DIGITAL_WATCH_TYPE_G1;
      Msg.pBuffer[0] = DIGITAL_WATCH_TYPE_G1; // backward compatible
    }
#endif

    Msg.Length = 1;
    RouteMsg(&Msg);
    PrintStringAndDecimal("- DevTypeResp:", Msg.pBuffer[0]);
    break;

  case VerInfoMsg:
    SetupMessageAndAllocateBuffer(&Msg, VerInfoRespMsg, MSG_OPT_NONE);

    /* exclude middle '.' */
    strncpy((char *)Msg.pBuffer, BUILD, 3);
    strncpy((char *)Msg.pBuffer + 3, BUILD + 4, 3);
    Msg.Length += strlen(BUILD) - 1;
      
    *(Msg.pBuffer + Msg.Length++) = (unsigned char)atoi(VERSION);
    
    while (VERSION[i++] != '.');
    *(Msg.pBuffer + Msg.Length++) = atoi(VERSION + i);
    *(Msg.pBuffer + Msg.Length++) = NULL;
    
    RouteMsg(&Msg);
    
    PrintString("-Ver:"); for (i = 6; i < Msg.Length; ++i) PrintHex(Msg.pBuffer[i]);
    break;
    
  case SetVibrateMode:
    SetVibrateModeHandler(pMsg);
    break;

  case SetRtcMsg:
    halRtcSet((tRtcHostMsgPayload*)pMsg->pBuffer);

#ifdef DIGITAL
    UpdateClock();
#endif
    break;

  case GetRtcMsg:
    SetupMessageAndAllocateBuffer(&Msg, RtcRespMsg, MSG_OPT_NONE);
    halRtcGet((tRtcHostMsgPayload*)Msg.pBuffer);
    Msg.Length = sizeof(tRtcHostMsgPayload);
    RouteMsg(&Msg);
    break;

  case ServiceMenuMsg:
    ServiceMenuHandler();
    break;
    
  case DisableButtonMsg:
    DisableButtonMsgHandler(pMsg);
    break;

  case ReadButtonConfigMsg:
    ReadButtonConfigHandler(pMsg);
    break;

  case LedChange:
    LedChangeHandler(pMsg);
    break;

  case BatteryConfigMsg:
    SetBatteryLevels(pMsg->pBuffer);
    break;

  case ReadBatteryVoltageMsg:
    ReadBatteryVoltageHandler();
    break;

  case ResetMsg:
    SoftwareResetHandler(pMsg);
    break;

  case NvalOperationMsg:
    NvalOperationHandler(pMsg);
    break;

  case SecInvertMsg:
    HandleSecInvert(pMsg->Options);
    break;

  case LoadTemplateMsg:
    LoadTemplateHandler(pMsg);
    break;

  case LinkAlarmMsg:
    if (!GetProperty(PROP_DISABLE_LINK_ALARM))
    {
      SetupMessageAndAllocateBuffer(&Msg, SetVibrateMode, MSG_OPT_NONE);
      tSetVibrateModePayload* pMsgData;
      pMsgData = (tSetVibrateModePayload *)Msg.pBuffer;
      
      pMsgData->Enable = 1;
      pMsgData->OnDurationLsb = 0xC8;
      pMsgData->OnDurationMsb = 0x00;
      pMsgData->OffDurationLsb = 0xF4;
      pMsgData->OffDurationMsb = 0x01;
      pMsgData->NumberOfCycles = 1; //3
      
      RouteMsg(&Msg);
    }
    break;

  case ModeTimeoutMsg:
    ModeTimeoutHandler();
    break;

  case WatchStatusMsg:
    PageType = PAGE_TYPE_INFO;
    CurrentPage[PageType] = StatusPage;
    DrawWatchStatusScreen();
    break;

//  case ListPairedDevicesMsg:
//    ListPairedDevicesHandler();
//    break;

  case WatchDrawnScreenTimeout:
    IdleUpdateHandler();
    break;

  case TermModeMsg:
    TermModeHandler();
    break;
    
  case LowBatteryWarningMsg:
    break;
    
  case LowBatteryBtOffMsg:
    UpdateClock();
    break;

#if __IAR_SYSTEMS_ICC__
  case EraseTemplateMsg:
    EraseTemplateHandler(pMsg);
    break;
    
  case WriteToTemplateMsg:
    WriteToTemplateHandler(pMsg);
    break;
#endif

  case EnableAccelerometerMsg:
  case DisableAccelerometerMsg:
  case AccelerometerSendDataMsg:
  case AccelerometerAccessMsg:
  case AccelerometerSetupMsg:

    HandleAccelerometer(pMsg);
    break;

  case ReadLightSensorMsg:
    ReadLightSensorHandler();
    break;

  case RateTestMsg:
    SetupMessageAndAllocateBuffer(&Msg, DiagnosticLoopback, MSG_OPT_NONE);
    /* don't care what data is */
    Msg.Length = 10;
    RouteMsg(&Msg);
    break;
    
  case RamTestMsg:
    RamTestHandler(pMsg);
    break;
    
  default:
    PrintStringAndHexByte("# Disp Msg: 0x", pMsg->Type);
    break;
  }
}
コード例 #7
0
unsigned char Errata(void)
{
    unsigned char Revision = GetMsp430HardwareRevision();
    return (Revision < 'F' || Revision == 'G');
}
コード例 #8
0
/*! Handle the messages routed to the display queue */
static void DisplayQueueMessageHandler(tMessage* pMsg)
{
  tMessage Msg;
  unsigned char i = 0;

  switch (pMsg->Type)
  {
  case WriteBufferMsg:
    WriteBufferHandler(pMsg);
    break;

  case SetWidgetListMsg:
    SetWidgetList(pMsg);
    break;
  
  case UpdateDisplayMsg:
    if ((!(pMsg->Options & MSG_OPT_UPD_INTERNAL) &&
          (pMsg->Options & MODE_MASK) == NOTIF_MODE) &&
        GetProperty(PROP_AUTO_BACKLIGHT))
      SendMessage(&Msg, AutoBacklightMsg, MSG_OPT_NONE);

    UpdateDisplayHandler(pMsg);
    break;
    
  case UpdateClockMsg:
    UpdateClock();
    break;
    
  case DrawClockWidgetMsg:
    DrawClockWidget(pMsg->Options);
    break;

  case MonitorBatteryMsg:
    MonitorBattery();
    break;

  case BluetoothStateChangeMsg:
    BluetoothStateChangeHandler(pMsg);
    break;

  case IdleUpdateMsg:
    IdleUpdateHandler();
    break;

  case ButtonStateMsg:
    ButtonStateHandler();
    break;

  case CallerIdMsg:
    pMsg->pBuffer[pMsg->Length] = NUL;
    ShowCall((char *)pMsg->pBuffer, pMsg->Options);
    break;
    
  case CallerNameMsg:
    if (pMsg->Length)
    {
      pMsg->pBuffer[pMsg->Length] = NUL;
      ShowCall((char *)pMsg->pBuffer, SHOW_NOTIF_CALLER_NAME);

      if (GetProperty(PROP_AUTO_BACKLIGHT)) SendMessage(&Msg, AutoBacklightMsg, MSG_OPT_NONE);
    }
    else ShowCall("", pMsg->Options);
    break;

  case MusicPlayStateMsg:
    HandleMusicPlayStateChange(pMsg->Options);
    break;
    
  case ChangeModeMsg:
    ChangeModeHandler(pMsg->Options);
    break;
  
  case ControlFullScreenMsg:
    SetProperty(PROP_PHONE_DRAW_TOP, pMsg->Options || *pMsg->pBuffer ? PROP_PHONE_DRAW_TOP : 0);
    break;

  case ModifyTimeMsg:
    ModifyTimeHandler(pMsg);
    break;

  case MenuModeMsg:
    MenuModeHandler(pMsg->Options);
    break;

  case MenuButtonMsg:
    MenuButtonHandler(pMsg->Options);
    break;

  case EnableButtonMsg:
    EnableButtonMsgHandler(pMsg);
    break;

  case DevTypeMsg:

    SetupMessageWithBuffer(&Msg, DevTypeRespMsg, BOARD_TYPE); //default G2
    if (Msg.pBuffer != NULL)
    {
      Msg.pBuffer[0] = BOARD_TYPE; // backward compatible
      Msg.Length = 1;

      if (GetMsp430HardwareRevision() < 'F')
      {
        Msg.Options = DIGITAL_WATCH_TYPE_G1;
        Msg.pBuffer[0] = DIGITAL_WATCH_TYPE_G1; // backward compatible
      }

      Msg.Options |= pMsg->Options & 0x80; // support ACK
      RouteMsg(&Msg);
    }

    PrintF("- DevTypeResp:%d", Msg.Options);

    // set ACK bit
    SendMessage(&Msg, ConnTypeMsg, pMsg->Options);
    break;

  case VerInfoMsg:
    SetupMessageWithBuffer(&Msg, VerInfoRespMsg, MSG_OPT_NONE);
    if (Msg.pBuffer != NULL)
    {
      /* exclude middle '.' */
      strncpy((char *)Msg.pBuffer, BUILD, 3);
      strncpy((char *)Msg.pBuffer + 3, BUILD + 4, 3);
      Msg.Length += strlen(BUILD) - 1;
        
      *(Msg.pBuffer + Msg.Length++) = (unsigned char)atoi(VERSION);
      
      while (VERSION[i++] != '.');
      *(Msg.pBuffer + Msg.Length++) = atoi(VERSION + i);
      *(Msg.pBuffer + Msg.Length++) = NULL;
      
      RouteMsg(&Msg);
    }
    PrintS("-Ver:"); for (i = 6; i < Msg.Length; ++i) PrintH(Msg.pBuffer[i]);
    break;
    
  case SetVibrateMode:
    SetVibrateModeHandler(pMsg);
    break;

  case SetRtcMsg:
    SetRtc((Rtc_t *)pMsg->pBuffer);

#if COUNTDOWN_TIMER
    if (CurrentPage[PageType] == CountdownPage && CountdownMode() == COUNTING)
      SendMessage(&Msg, CountDownMsg, MSG_OPT_CNTDWN_TIME);
#endif
    UpdateClock();
    break;
    
#if COUNTDOWN_TIMER
  case CountDownMsg:
    if (pMsg->Options == MSG_OPT_NONE)
    {
      PageType = PAGE_TYPE_INFO;
      CurrentPage[PageType] = CountdownPage;
    }
    DrawCountdownScreen(pMsg->Options);
    break;

  case SetCountdownDoneMsg:
    // for testing
//    Rtc_t Done;
//    Done.Month = 5;
//    Done.Day = 1;
//    Done.Hour = 0;
//    Done.Minute = 0;
//    SetDoneTime(&Done);

    // Valid only DoneTime is different
    if (SetDoneTime((Rtc_t *)pMsg->pBuffer)) SendMessage(&Msg, CountDownMsg, MSG_OPT_NONE);
    break;
#endif

  case ServiceMenuMsg:
    ServiceMenuHandler();
    break;
    
  case DisableButtonMsg:
    DisableButtonMsgHandler(pMsg);
    break;

  case ReadButtonConfigMsg:
    ReadButtonConfigHandler(pMsg);
    break;

  case SetBacklightMsg:
    SetBacklight(pMsg->Options);
    // testing
//    pMsg->Type = AccelMsg;
//    pMsg->Options = 1; //enable
//    HandleAccelerometer(pMsg);
    break;

  case AutoBacklightMsg:
    if (LightSenseCycle() < DARK_LEVEL) SetBacklight(LED_ON_OPTION);
    break;

  case BatteryConfigMsg:
    SetBatteryLevels(pMsg->pBuffer);
    break;

  case ReadBatteryVoltageMsg:
    ReadBatteryVoltageHandler();
    break;

  case ResetMsg:
    SoftwareResetHandler(pMsg);
    break;

  case NvalOperationMsg:
    NvalOperationHandler(pMsg);
    break;

  case SecInvertMsg:
    HandleSecInvert(pMsg->Options);
    break;

  case LoadTemplateMsg:
    LoadTemplateHandler(pMsg);
    break;

  case LinkAlarmMsg:
    if (LinkAlarmEnable)
    {
      SetupMessageWithBuffer(&Msg, SetVibrateMode, MSG_OPT_NONE);
      if (Msg.pBuffer != NULL)
      {
        *(tSetVibrateModePayload *)Msg.pBuffer = LnkAlmTone;
        RouteMsg(&Msg);
      }
    }
    break;

  case ModeTimeoutMsg:
    ModeTimeoutHandler();
    break;

  case WatchStatusMsg:
    PageType = PAGE_TYPE_INFO;
    CurrentPage[PageType] = StatusPage;
    DrawWatchStatusScreen();
    break;

//  case ListPairedDevicesMsg:
//    ListPairedDevicesHandler();
//    break;

  case WatchDrawnScreenTimeout:
    IdleUpdateHandler();
    break;

  case TermModeMsg:
    TermModeHandler();
    break;
    
  case LowBatteryWarningMsg:
    break;
    
  case LowBatteryBtOffMsg:
    UpdateClock();
    break;

#if __IAR_SYSTEMS_ICC__
  case EraseTemplateMsg:
    EraseTemplateHandler(pMsg);
    break;
    
  case WriteToTemplateMsg:
    WriteToTemplateHandler(pMsg);
    break;
#endif

  case AccelMsg:
    HandleAccelerometer(pMsg);
    break;

  case ReadLightSensorMsg:
    ReadLightSensorHandler();
    break;

  case RateTestMsg:
    SetupMessageWithBuffer(&Msg, DiagnosticLoopback, MSG_OPT_NONE);
    if (Msg.pBuffer != NULL)
    {
      /* don't care what data is */
      Msg.Length = 10;
      RouteMsg(&Msg);
    }
    break;
    
  default:
    PrintF("# Disp Msg: 0x%02x", pMsg->Type);
    break;
  }
}