📄 coordinatora.c
字号:
}/**************************************************************************** * * NAME: vProcessCurrentTimeBlock * * DESCRIPTION: * Operates a simple state machine. Called 20 times per second, this performs * several tasks over a 1 second period, with the time split into 50ms blocks. * In one block it updates the display, in another it starts a reading from * the temperature, in another it reads the temperature, etc. * * PARAMETERS: Name RW Usage * u8TimeBlock R Current time block, 0-19 * * RETURNS: * void * * NOTES: * A value greater than 19 may be used for u8TimeBlock, to ensure that the * simple state machine remains idle. * ****************************************************************************/PRIVATE void vProcessCurrentTimeBlock(uint8 u8TimeBlock){ uint8 u8LocalSensor; /* Process current block scheduled activity */ switch (u8TimeBlock) { case BLOCK_UPDATE: /* Time to update the display */ vProcessUpdateBlock(); /* Also update the information passed back to the endpoints in the beacon payload */ vUpdateBeaconPayload(); break; case BLOCK_START_TEMP: /* Time to start read of the temperature sensor. We read sensors even if we don't use the data, as the coordinator is assumed to be a device that doesn't have to be particularly economical on power */ vHTSstartReadTemp(); break; case BLOCK_READ_TEMP: /* Time to read the temperature sensor */ u8LocalSensor = (uint8)u16HTSreadTempResult(); if (u8LocalSensor > 52) { u8LocalSensor = 52; } if (sDemoData.sNode.bLocalNode) { sDemoData.sNode.asNodeData[0].asNodeElementData[E_SENSOR_TEMP].u8NowValue = u8LocalSensor; sDemoData.sNode.asNodeData[0].u8FramesMissed = 0; } break; case BLOCK_START_HUMIDITY: /* Time to start a read of the humidity sensor */ vHTSstartReadHumidity(); break; case BLOCK_READ_HUMIDITY: /* Time to read the humidity sensor */ u8LocalSensor = (uint8)u16HTSreadHumidityResult(); if (u8LocalSensor > 104) { u8LocalSensor = 104; } if (sDemoData.sNode.bLocalNode) { sDemoData.sNode.asNodeData[0].asNodeElementData[E_SENSOR_HTS].u8NowValue = u8LocalSensor; } break; case BLOCK_READ_LIGHT: /* Time to read the light sensor. This sensor automatically starts a new conversion afterwards so there is no need for a 'start read' */ u8LocalSensor = (uint8)(u16ALSreadChannelResult() >> 9); if (u8LocalSensor > 6) { u8LocalSensor = 6; } if (sDemoData.sNode.bLocalNode) { sDemoData.sNode.asNodeData[0].asNodeElementData[E_SENSOR_ALS].u8NowValue = u8LocalSensor; } break; }}/**************************************************************************** * * NAME: bProcessKeys * * DESCRIPTION: * Gets the latest button presses and detects any change since the last time * the buttons were checked. If there is a change it is passed to the * individual handler for the screen currently being displayed (the buttons * are all 'soft' keys so their meaning changes from screen to screen). The * exception to this is a button combination that causes the software to * shutdown and stop the LCD. There is also a reset combination. * * PARAMETERS: Name RW Usage * pu8Keys RW Persistent value of buttons pressed * * RETURNS: * TRUE if reset combination is pressed * ****************************************************************************/PRIVATE bool_t bProcessKeys(uint8 *pu8Keys){ uint8 u8KeysDown; uint8 u8NewKeysDown; uint8 *fad; u8KeysDown = *pu8Keys; /* Process key press */ u8NewKeysDown = u8ButtonReadFfd(); if (u8NewKeysDown != 0) { if ((u8NewKeysDown | u8KeysDown) != u8KeysDown) { /* Logical OR values to enable multiple keys at once */ u8KeysDown |= u8NewKeysDown; /* Key presses depend on mode */ if(LCD_RT){ vProcessKeyPressSelet(u8KeysDown); char acString[5]; if(Foodau2==1){ vValToDec(acString, sfootData.food, " "); vLcdWriteText(acString, Foodau1, 40); } if(Foodau2==2){ vValToDec(acString, sfootData.number, " "); vLcdWriteText(acString, Foodau1, 110); } vLcdRefreshAll(); } else{ vLcdClear(); vLcdRefreshAll(); vLcdLine(6); vLcdWriteText("Select", 7, 0); vLcdWriteText("\\", 7, 47); vLcdWriteText("]", 7, 74); vLcdWriteText("send", 7, 103); vLcdRefreshAll(); LCD_RT=1; } } } else { u8KeysDown = 0; } /* Store value for use next time */ *pu8Keys = u8KeysDown; return (u8KeysDown == E_KEYS_0_AND_3);}/****************************************************************************/PRIVATE void vProcessKeyPressSelet(uint8 u8KeyMap){ switch (u8KeyMap) { case E_KEY_0: if(Foodau1<=4){ Foodau2++; if(Foodau2>=3){ FOOD[Foodau1*2]=sfootData.food; FOOD[Foodau1*2+1]=sfootData.number; vLcdWriteText("^NUMBER", Foodau1, 60); Foodau1++; Foodau2=1; sfootData.food=sfootData.number=0; if(Foodau1==4){break;} } if(Foodau2==1){ vLcdWriteText("@FOOD", Foodau1, 0); } if(Foodau2==2){ vLcdWriteText("^FOOD", Foodau1, 0); vLcdWriteText("@NUMBER", Foodau1, 60); } vLcdRefreshAll(); } break; case E_KEY_1: if(Foodau1<=4){ if(Foodau2==1){ vAdjustAlarm(&sfootData.food, 5, 1, TRUE); } if(Foodau2==2){ vAdjustAlarm(&sfootData.number, 20, 1, TRUE); } } break; case E_KEY_2: if(Foodau1<=4){ if(Foodau2==1){ vAdjustAlarm(&sfootData.food, 5, 1, 0); } if(Foodau2==2){ vAdjustAlarm(&sfootData.number, 20, 1, 0); } } break; case E_KEY_3: break; }}/**************************************************************************** * * NAME: u8UpdateTimeBlock * * DESCRIPTION: * Moves the state machine time block on by one time period. * * PARAMETERS: Name RW Usage * u8TimeBlock R Previous time block * * RETURNS: * uint8 Next time block * ****************************************************************************/PRIVATE uint8 u8UpdateTimeBlock(uint8 u8TimeBlock){ /* Update block state for next time, if in a state where regular updates should be performed */ if ((sDemoData.sSystem.eState != E_STATE_SET_CHANNEL) && (sDemoData.sSystem.eState != E_STATE_SETUP_SCREEN) && (sDemoData.sSystem.eState != E_STATE_SCANNING)) { u8TimeBlock++; if (u8TimeBlock >= MAX_BLOCKS) { u8TimeBlock = 0; } } return u8TimeBlock;}/**************************************************************************** * * NAME: vProcessInterrupts * * DESCRIPTION: * Loops around checking for upward events from the Application Queue API. * To save power, the CPU is set to doze at the start of the loop. If an event * is generated, the CPU is woken up and processes it, then the code here is * allowed to continue. * For each type of event, the queue is checked and, if there is something to * process, the appropriate handler is called. The buffer is then returned to * the Application Queue API. This continues until all events have been * processed. If the hardware event handler detects that a timeout has * happened, the loop is exited. * * RETURNS: * void when a timeout is detected * * NOTES: * There is a possibility of the system locking up if an interrupt is * generated and handled by the Application Queue API just before the request * to doze the CPU. Normally there won't be an issue as the wake-up timer will * generate an interrupt eventually, but it is theoretically possible that an * MLME or MCPS event just before the timer fires could create this situation * (has never been seen in practice). An easy solution is to use the second * wake-up timer as a watchdog. * ****************************************************************************/PRIVATE void vProcessInterrupts(void){ MAC_MlmeDcfmInd_s *psMlmeInd; MAC_McpsDcfmInd_s *psMcpsInd; AppQApiHwInd_s *psAHI_Ind; bool_t bDone; /* Wait for events */ bDone = FALSE; do { /* Doze CPU: it will wake when interrupt occurs, then process interrupts, then this code will be able to process queue */ vAHI_CpuDoze(); /* Check for anything on the MCPS upward queue */ do { psMcpsInd = psAppQApiReadMcpsInd(); if (psMcpsInd != NULL) { vProcessIncomingData(psMcpsInd); vAppQApiReturnMcpsIndBuffer(psMcpsInd); } } while (psMcpsInd != NULL); /* Check for anything on the MLME upward queue */ do { psMlmeInd = psAppQApiReadMlmeInd(); if (psMlmeInd != NULL) { vProcessIncomingMlme(psMlmeInd); vAppQApiReturnMlmeIndBuffer(psMlmeInd); } } while (psMlmeInd != NULL); /* Check for anything on the AHI upward queue */ do { psAHI_Ind = psAppQApiReadHwInd(); if (psAHI_Ind != NULL) { if (bProcessForTimeout(psAHI_Ind) == TRUE) { bDone = TRUE; } vAppQApiReturnHwIndBuffer(psAHI_Ind); } } while (psAHI_Ind != NULL); } while (bDone == FALSE);}/**************************************************************************** * * NAME: vProcessIncomingData * * DESCRIPTION: * Deals with any incoming MCPS data events. If the event is an indication * from a device with a short address matching a demo endpoint, the data in * the payload is stored for display the next time that the LCD is updated. * * PARAMETERS: Name RW Usage * psMcpsInd R Pointer to structure containing MCPS event * * RETURNS: * void * ****************************************************************************/PRIVATE void vProcessIncomingData(MAC_McpsDcfmInd_s *psMcpsInd){ MAC_RxFrameData_s *psFrame; MAC_Addr_s *psAddr; tsNodeData *psNodeData; uint16 u16NodeAddr; uint8 u8Node; uint8 u8Count; psFrame = &psMcpsInd->uParam.sIndData.sFrame; /* Check that MCPS frame is a valid sensor one */ if ((psMcpsInd->u8Type != MAC_MCPS_IND_DATA) || (psFrame->u8SduLength != 8) || (psFrame->au8Sdu[0] != DEMO_ENDPOINT_IDENTIFIER)) { return; } /* Use address to determine node */ psAddr = &psFrame->sSrcAddr; if (psAddr->u8AddrMode != 2) { return; } u16NodeAddr = psAddr->uAddr.u16Short; if ((u16NodeAddr < DEMO_ENDPOINT_ADDR_BASE) || (u16NodeAddr >= (DEMO_ENDPOINT_ADDR_BASE + DEMO_ENDPOINTS))) { return; } /* Store data for node */ u8Node = (uint8)(u16NodeAddr - DEMO_ENDPOINT_ADDR_BASE); psNodeData = &sDemoData.sNode.asNodeData[u8Node]; psNodeData->u8FramesMissed = 0; psNodeData->u8SwitchOn = psFrame->au8Sdu[2]; vLedControl(u8Node, psNodeData->u8SwitchOn); for (u8Count = 0; u8Count < DEMO_SENSOR_LIST_LEN; u8Count++) { psNodeData->asNodeElementData[u8Count].u8NowValue = psFrame->au8Sdu[u8Count + 3]; } psNodeData->u8Rssi = psFrame->u8LinkQuality;}/**************************************************************************** * * NAME: vProcessIncomingMlme * * DESCRIPTION: * Deals with any incoming MCPS events. If the event is an indication that * device wants to associate, goes through a process to determine a short * address for the device, either as 'next on the list' or the same address * that was proviously given if the device has associated before. Then sends * an association response via the stack. * * For debug purposes, also displays any Communication Status indications. * * PARAMETERS: Name RW Usage * psMlmeInd R Pointer to structure containing MLME event * * RETURNS: * void * ****************************************************************************/PRIVATE void vProcessIncomingMlme(MAC_MlmeDcfmInd_s *psMlmeInd){ MAC_MlmeReqRsp_s sMlmeReqRsp; MAC_MlmeSyncCfm_s sMlmeSyncCfm; uint16 u16ShortAddress; uint8 u8Node; uint8 u8AssocStatus; switch (psMlmeInd->u8Type) { case MAC_MLME_IND_ASSOCIATE: /* Only respond if in network or node modes. We aren't a coordinator until then */ if ((sDemoData.sSystem.eState == E_STATE_NETWORK) || (sDemoData.sSystem.eState == E_STATE_NODE) || (sDemoData.sSystem.eState == E_STATE_NODE_CONTROL)) { /* Default short address */ u16ShortAddress = 0xffff; /* Check node extended address matches and device wants short address (for the demo, we only use short address) */ if (psMlmeInd->uParam.sIndAssociate.u8Capability & 0x80) { /* Check if already associated (idiot proofing) */ u8Node = 0; while (u8Node < sDemoData.sNode.u8AssociatedNodes) { if ((psMlmeInd->uParam.sIndAssociate.sDeviceAddr.u32L == sDemoData.sNode.asAssocNodes[u8Node].sExtAddr.u32L) && (psMlmeInd->uParam.sIndAssociate.sDeviceAddr.u32H == sDemoData.sNode.asAssocNodes[u8Node].sExtAddr.u32H)) { /* Already in system: give it same short address */ u16ShortAddress = sDemoData.sNode.asAssocNodes[u8Node].u16ShortAddr; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -