/*! Initiate a light sensor cycle. Then send the instantaneous and average * light sense values to the host. * * \param tHostMsg* pMsg is unused * */ static void ReadLightSensorHandler(void) { /* start cycle and wait for it to finish */ LightSenseCycle(); /* send message to the host */ tMessage OutgoingMsg; SetupMessageAndAllocateBuffer(&OutgoingMsg, ReadLightSensorResponse, NO_MSG_OPTIONS); /* instantaneous value */ unsigned int lv = ReadLightSense(); OutgoingMsg.pBuffer[0] = lv & 0xFF; OutgoingMsg.pBuffer[1] = (lv >> 8 ) & 0xFF; /* average value */ lv = ReadLightSenseAverage(); OutgoingMsg.pBuffer[2] = lv & 0xFF; OutgoingMsg.pBuffer[3] = (lv >> 8 ) & 0xFF; OutgoingMsg.Length = 4; RouteMsg(&OutgoingMsg); }
static void ChangeModeHandler(unsigned char Option) { unsigned char Mode = Option & MODE_MASK; tMessage Msg; SetupMessageAndAllocateBuffer(&Msg, ModeChangeIndMsg, (CurrentIdleScreen() << 4) | Mode); Msg.pBuffer[0] = eScUpdateComplete; Msg.Length = 1; RouteMsg(&Msg); PrintStringAndHexByte("- ChgModInd:", Msg.Options); if (Option & MSG_OPT_CHGMOD_IND) return; // ask for current idle page only if (Mode == MUSIC_MODE) SendMessage(&Msg, UpdConnParamMsg, ShortInterval); if (Mode != IDLE_MODE) { PageType = PAGE_TYPE_IDLE; if (ModeTimerId == UNASSIGNED) ModeTimerId = AllocateOneSecondTimer(); SetupOneSecondTimer(ModeTimerId, ModeTimeout[Mode], NO_REPEAT, DISPLAY_QINDEX, ModeTimeoutMsg, Mode); StartOneSecondTimer(ModeTimerId); if (Option & MSG_OPT_UPD_INTERNAL) SendMessage(&Msg, UpdateDisplayMsg, Option); } else { StopOneSecondTimer(ModeTimerId); IdleUpdateHandler(); } CurrentMode = Mode; }
static void ModeTimeoutHandler() { /* send a message to the host indicating that a timeout occurred */ PrintString2("- ModChgTout", CR); tMessage Msg; SetupMessageAndAllocateBuffer(&Msg, ModeChangeIndMsg, CurrentMode); Msg.pBuffer[0] = eScModeTimeout; Msg.Length = 1; RouteMsg(&Msg); ChangeModeHandler(IDLE_MODE); }
/*! Read the voltage of the battery. This provides power good, battery charging, * battery voltage, and battery voltage average. * * \param tHostMsg* pMsg is unused * */ static void ReadBatteryVoltageHandler(void) { tMessage Msg; SetupMessageAndAllocateBuffer(&Msg, VBatRespMsg, MSG_OPT_NONE); Msg.Length = 6; Msg.pBuffer[0] = ClipOn(); Msg.pBuffer[1] = Charging(); Msg.pBuffer[2] = BatteryPercentage(); unsigned int bv = Read(BATTERY); Msg.pBuffer[4] = bv & 0xFF; Msg.pBuffer[5] = (bv >> 8) & 0xFF; RouteMsg(&Msg); }
static void HandleMusicPlayStateChange(unsigned char State) { // music icon fits into one message PrintStringAndDecimal("- HdlMusicPlyChg:", State); tMessage Msg; SetupMessageAndAllocateBuffer(&Msg, WriteBufferMsg, MUSIC_MODE | MSG_OPT_WRTBUF_MULTILINE | ICON_MUSIC_WIDTH << 3); Msg.pBuffer[0] = MUSIC_STATE_START_ROW; Msg.Length = ICON_MUSIC_WIDTH * ICON_MUSIC_HEIGHT + 1; PrintStringAndTwoDecimals("- start:", Msg.pBuffer[0], "L:", Msg.Length); unsigned char i = 1; for (; i < Msg.Length; ++i) Msg.pBuffer[i] = pIconMusicState[1 - State][i - 1]; RouteMsg(&Msg); SendMessage(&Msg, UpdateDisplayMsg, MUSIC_MODE); }
/* send a vibration to the wearer */ void GenerateLinkAlarm(void) { tMessage Msg; SetupMessageAndAllocateBuffer(&Msg,SetVibrateMode,NO_MSG_OPTIONS); tSetVibrateModePayload* pMsgData; pMsgData = (tSetVibrateModePayload*) Msg.pBuffer; pMsgData->Enable = 1; pMsgData->OnDurationLsb = 0x00; pMsgData->OnDurationMsb = 0x01; pMsgData->OffDurationLsb = 0x00; pMsgData->OffDurationMsb = 0x01; pMsgData->NumberOfCycles = 5; RouteMsg(&Msg); }
/*! Read configuration of a specified button. This is used to read the * configuration of a button that needs to be restored at a later time * by the application. * * \param tHostMsg* pMsg - A message with a tButtonActionPayload payload */ static void ReadButtonConfigHandler(tMessage* pMsg) { /* map incoming message payload to button information */ tButtonActionPayload* pButtonActionPayload = (tButtonActionPayload*)pMsg->pBuffer; tMessage OutgoingMsg; SetupMessageAndAllocateBuffer(&OutgoingMsg, ReadButtonConfigResponse, NO_MSG_OPTIONS); ReadButtonConfiguration(pButtonActionPayload->DisplayMode, pButtonActionPayload->ButtonIndex, pButtonActionPayload->ButtonPressType, OutgoingMsg.pBuffer); OutgoingMsg.Length = 5; RouteMsg(&OutgoingMsg); }
static void ShowCall(tString *pString, unsigned char Type) { static tString CallerId[15] = ""; static tTimerId NotifyTimerId = UNASSIGNED; tMessage Msg; if (Type == SHOW_NOTIF_CALLER_ID) strcpy(CallerId, pString); if (Type == SHOW_NOTIF_CALLER_NAME && *CallerId) { PrintString3("- Caller:", pString, CR); SetupMessageAndAllocateBuffer(&Msg, SetVibrateMode, MSG_OPT_NONE); *(tSetVibrateModePayload *)Msg.pBuffer = RingTone; RouteMsg(&Msg); PageType = PAGE_TYPE_INFO; CurrentPage[PageType] = CallPage; DrawCallScreen(CallerId, pString); // set a 5s timer for switching back to idle screen if (NotifyTimerId == UNASSIGNED) NotifyTimerId = AllocateOneSecondTimer(); SetupOneSecondTimer(NotifyTimerId, 10, NO_REPEAT, DISPLAY_QINDEX, CallerNameMsg, SHOW_NOTIF_END); StartOneSecondTimer(NotifyTimerId); } else if (Type == SHOW_NOTIF_END || Type == SHOW_NOTIF_REJECT_CALL) { PrintString2("- Call Notif End", CR); *CallerId = NULL; StopOneSecondTimer(NotifyTimerId); PageType = PAGE_TYPE_IDLE; SendMessage(&Msg, UpdateDisplayMsg, CurrentMode | MSG_OPT_UPD_INTERNAL | (CurrentMode == IDLE_MODE ? MSG_OPT_NEWUI : 0)); if (Type == SHOW_NOTIF_REJECT_CALL) SendMessage(&Msg, HfpMsg, MSG_OPT_HFP_HANGUP); } }
static void NvalOperationHandler(tMessage* pMsg) { if (pMsg->pBuffer == NULL) // Property { HandleProperty(pMsg->Options); } else { tNvalOperationPayload* pNvPayload = (tNvalOperationPayload*)pMsg->pBuffer; /* create the outgoing message */ tMessage Msg; SetupMessageAndAllocateBuffer(&Msg, PropRespMsg, MSG_OPT_NONE); /* add identifier to outgoing message */ tWordByteUnion Identifier; Identifier.word = pNvPayload->NvalIdentifier; Msg.pBuffer[0] = Identifier.Bytes.byte0; Msg.pBuffer[1] = Identifier.Bytes.byte1; Msg.Length = 2; PrintStringAndTwoHexBytes("- Nval Id:Val 0x", Identifier.word, pNvPayload->DataStartByte); unsigned char Property = PropertyBit(pNvPayload->NvalIdentifier); if (pMsg->Options == NVAL_READ_OPERATION) { if (Property) Msg.pBuffer[2] = GetProperty(Property); Msg.Length += pNvPayload->Size; } else if (Property) // write operation { SetProperty(Property, pNvPayload->DataStartByte ? Property : 0); UpdateClock(); } RouteMsg(&Msg); } }
/*! Read the voltage of the battery. This provides power good, battery charging, * battery voltage, and battery voltage average. * * \param tHostMsg* pMsg is unused * */ static void ReadBatteryVoltageHandler(void) { tMessage OutgoingMsg; SetupMessageAndAllocateBuffer(&OutgoingMsg, ReadBatteryVoltageResponse, NO_MSG_OPTIONS); /* if the battery is not present then these values are meaningless */ OutgoingMsg.pBuffer[0] = QueryPowerGood(); OutgoingMsg.pBuffer[1] = QueryBatteryCharging(); unsigned int bv = ReadBatterySense(); OutgoingMsg.pBuffer[2] = bv & 0xFF; OutgoingMsg.pBuffer[3] = (bv >> 8 ) & 0xFF; bv = ReadBatterySenseAverage(); OutgoingMsg.pBuffer[4] = bv & 0xFF; OutgoingMsg.pBuffer[5] = (bv >> 8 ) & 0xFF; OutgoingMsg.Length = 6; RouteMsg(&OutgoingMsg); }
/*! 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; } }
static void NvalOperationHandler(tMessage* pMsg) { /* overlay */ tNvalOperationPayload* pNvPayload = (tNvalOperationPayload*)pMsg->pBuffer; /* create the outgoing message */ tMessage OutgoingMsg; SetupMessageAndAllocateBuffer(&OutgoingMsg, NvalOperationResponseMsg, NV_FAILURE); /* add identifier to outgoing message */ tWordByteUnion Identifier; Identifier.word = pNvPayload->NvalIdentifier; OutgoingMsg.pBuffer[0] = Identifier.Bytes.byte0; OutgoingMsg.pBuffer[1] = Identifier.Bytes.byte1; OutgoingMsg.Length = 2; /* option byte in return message is status */ switch (pMsg->Options) { case NVAL_INIT_OPERATION: /* may allow access to a specific range of nval ids that * the phone can initialize and use */ break; case NVAL_READ_OPERATION: /* read the value and update the length */ OutgoingMsg.Options = OsalNvRead(pNvPayload->NvalIdentifier, NV_ZERO_OFFSET, pNvPayload->Size, &OutgoingMsg.pBuffer[2]); OutgoingMsg.Length += pNvPayload->Size; break; case NVAL_WRITE_OPERATION: /* check that the size matches (otherwise NV_FAILURE is sent) */ if ( OsalNvItemLength(pNvPayload->NvalIdentifier) == pNvPayload->Size ) { OutgoingMsg.Options = OsalNvWrite(pNvPayload->NvalIdentifier, NV_ZERO_OFFSET, pNvPayload->Size, (void*)(&pNvPayload->DataStartByte)); } /* update the copy in ram */ NvUpdater(pNvPayload->NvalIdentifier); break; default: break; } RouteMsg(&OutgoingMsg); }
/*! Handle the messages routed to the background task */ static void BackgroundMessageHandler(tMessage* pMsg) { tMessage OutgoingMsg; switch(pMsg->Type) { case SetCallbackTimerMsg: SetCallbackTimerHandler(pMsg); break; case GetDeviceType: SetupMessageAndAllocateBuffer(&OutgoingMsg, GetDeviceTypeResponse, NO_MSG_OPTIONS); OutgoingMsg.pBuffer[0] = BOARD_TYPE; OutgoingMsg.Length = 1; RouteMsg(&OutgoingMsg); break; case AdvanceWatchHandsMsg: AdvanceWatchHandsHandler(pMsg); break; case SetVibrateMode: SetVibrateModeHandler(pMsg); break; case SetRealTimeClock: halRtcSet((tRtcHostMsgPayload*)pMsg->pBuffer); #ifdef DIGITAL SetupMessage(&OutgoingMsg,IdleUpdate,NO_MSG_OPTIONS); RouteMsg(&OutgoingMsg); #endif break; case GetRealTimeClock: SetupMessageAndAllocateBuffer(&OutgoingMsg, GetRealTimeClockResponse, NO_MSG_OPTIONS); halRtcGet((tRtcHostMsgPayload*)OutgoingMsg.pBuffer); OutgoingMsg.Length = sizeof(tRtcHostMsgPayload); RouteMsg(&OutgoingMsg); break; case EnableButtonMsg: EnableButtonMsgHandler(pMsg); break; case DisableButtonMsg: DisableButtonMsgHandler(pMsg); break; case ReadButtonConfigMsg: ReadButtonConfigHandler(pMsg); break; case BatteryChargeControl: #ifdef DIGITAL /* update the screen if there has been a change in charging status */ if ( BatteryChargingControl() ) { SetupMessage(&OutgoingMsg, IdleUpdate, NO_MSG_OPTIONS); RouteMsg(&OutgoingMsg); } #endif BatterySenseCycle(); LowBatteryMonitor(); #ifdef TASK_DEBUG UTL_FreeRtosTaskStackCheck(); #endif #if 0 LightSenseCycle(); #endif break; case LedChange: LedChangeHandler(pMsg); break; case BatteryConfigMsg: SetBatteryLevels(pMsg->pBuffer); break; case ReadBatteryVoltageMsg: ReadBatteryVoltageHandler(); break; case ReadLightSensorMsg: ReadLightSensorHandler(); break; case SoftwareResetMsg: SoftwareResetHandler(pMsg); break; case NvalOperationMsg: NvalOperationHandler(pMsg); break; case GeneralPurposeWatchMsg: /* insert handler here */ break; case ButtonStateMsg: ButtonStateHandler(); break; /* * Accelerometer Messages */ case AccelerometerEnableMsg: AccelerometerEnable(); break; case AccelerometerDisableMsg: AccelerometerDisable(); break; case AccelerometerSendDataMsg: AccelerometerSendDataHandler(); break; case AccelerometerAccessMsg: AccelerometerAccessHandler(pMsg); break; case AccelerometerSetupMsg: AccelerometerSetupHandler(pMsg); break; /* * */ case RateTestMsg: SetupMessageAndAllocateBuffer(&OutgoingMsg,DiagnosticLoopback,NO_MSG_OPTIONS); /* don't care what data is */ OutgoingMsg.Length = 10; RouteMsg(&OutgoingMsg); break; /* * */ default: PrintStringAndHex("<<Unhandled Message>> in Background Task: Type 0x", pMsg->Type); break; } }
/*! Function to implement the BackgroundTask loop * * \param pvParameters not used * */ static void BackgroundTask(void *pvParameters) { if ( QueueHandles[BACKGROUND_QINDEX] == 0 ) { PrintString("Background Queue not created!\r\n"); } PrintString(SPP_DEVICE_NAME); PrintString2("\r\nSoftware Version ",VERSION_STRING); PrintString("\r\n\r\n"); InitializeRstNmiConfiguration(); /* * check on the battery */ ConfigureBatteryPins(); BatteryChargingControl(); BatterySenseCycle(); /* * now set up a timer that will cause the battery to be checked at * a regular frequency. */ BatteryMonitorTimerId = AllocateOneSecondTimer(); InitializeBatteryMonitorInterval(); SetupOneSecondTimer(BatteryMonitorTimerId, nvBatteryMonitorIntervalInSeconds, REPEAT_FOREVER, BACKGROUND_QINDEX, BatteryChargeControl, NO_MSG_OPTIONS); StartOneSecondTimer(BatteryMonitorTimerId); /* * Setup a timer to use with the LED for the LCD. */ LedTimerId = AllocateOneSecondTimer(); SetupOneSecondTimer(LedTimerId, ONE_SECOND*3, NO_REPEAT, BACKGROUND_QINDEX, LedChange, LED_OFF_OPTION); // Allocate a timer for wake-up iOS background BLE app CallbackTimerId = AllocateOneSecondTimer(); /****************************************************************************/ #ifdef RAM_TEST RamTestTimerId = AllocateOneSecondTimer(); SetupOneSecondTimer(RamTestTimerId, ONE_SECOND*20, NO_REPEAT, DISPLAY_QINDEX, RamTestMsg, NO_MSG_OPTIONS); StartOneSecondTimer(RamTestTimerId); #endif /****************************************************************************/ InitializeAccelerometer(); #ifdef ACCELEROMETER_DEBUG SetupMessageAndAllocateBuffer(&BackgroundMsg, AccelerometerSetupMsg, ACCELEROMETER_SETUP_INTERRUPT_CONTROL_OPTION); BackgroundMsg.pBuffer[0] = INTERRUPT_CONTROL_ENABLE_INTERRUPT; BackgroundMsg.Length = 1; RouteMsg(&BackgroundMsg); /* don't call AccelerometerEnable() directly use a message*/ SetupMessage(&BackgroundMsg,AccelerometerEnableMsg,NO_MSG_OPTIONS); RouteMsg(&BackgroundMsg); #endif /****************************************************************************/ #ifdef RATE_TEST StartCrystalTimer(CRYSTAL_TIMER_ID3,RateTestCallback,RATE_TEST_INTERVAL_MS); #endif /****************************************************************************/ for(;;) { if( pdTRUE == xQueueReceive(QueueHandles[BACKGROUND_QINDEX], &BackgroundMsg, portMAX_DELAY ) ) { PrintMessageType(&BackgroundMsg); BackgroundMessageHandler(&BackgroundMsg); SendToFreeQueue(&BackgroundMsg); CheckStackUsage(xBkgTaskHandle,"Background Task"); CheckQueueUsage(QueueHandles[BACKGROUND_QINDEX]); } } }