📄 homesensorenddevice.c
字号:
to time reading of sensors. In other states, ignore it */
switch (sDemoData.sSystem.eState)
{
case E_STATE_SYNCING:
/* Can now associate */
vStartAssociate();
break;
case E_STATE_RUNNING:
/* Process received data in beacon payload */
vProcessRxBeacon(psMlmeInd);
break;
default:
break;
}
break;
case MAC_MLME_IND_SYNC_LOSS:
/* Lost sync with coordinator so try to find coordinator again */
if (sDemoData.sSystem.eState != E_STATE_ASSOCIATING)
{
vStartScan();
}
else
{
sDemoData.sSystem.eState = E_STATE_ASSOC_TO_SCAN;
}
break;
default:
break;
}
}
/****************************************************************************
*
* NAME: bProcessKeyPress
*
* DESCRIPTION:
* Porcesses buttons, to turn on or off the remote switch or to detect a
* reset request.
*
* RETURNS:
* TRUE if reset combination detected.
*
****************************************************************************/
PRIVATE bool_t bProcessKeyPress(void)
{
uint8 u8KeysDown;
/* Check for key press. We don't bother with a debouce
algorithm as in all cases repeated presses have same effect
anyway. We also don't bother to check that the hardware
interrupt was caused by a key press */
u8KeysDown = u8ButtonReadRfd();
/* Keys control virtual switch value that is passed to the central
controller */
switch (u8KeysDown)
{
case E_KEY_0:
sDemoData.sControls.u8Switch = 0;
break;
case E_KEY_1:
sDemoData.sControls.u8Switch = 1;
break;
}
/* Return TRUE if both keys are pressed at once, to indicate that a
soft reset is required */
return (u8KeysDown == E_KEYS_0_AND_1);
}
/****************************************************************************
*
* NAME: vProcessRead
*
* DESCRIPTION:
* Gets the current readings from each sensor. If the light level causes the
* low light alarm to be triggered, an LED is illuminated.
*
* RETURNS:
* void
*
* NOTES:
* This is not an efficient way to read the sensors as much time is wasted
* waiting for the humidity and temperature sensor to complete. The sensor
* pulls a DIO line low when it is ready, and this could be used to generate
* an interrupt to indicate when data is ready to be read.
*
****************************************************************************/
PRIVATE void vProcessRead(void)
{
uint16 u16LightSensor;
uint16 u16Diff;
/* Read light level, adjust to range 0-6. This sensor automatically starts
a new conversion afterwards so there is no need for a 'start read' */
u16LightSensor = u16ALSreadChannelResult();
/* Adjust the high and low values if necessary, and obtain the
difference between them */
if (sDemoData.sLightSensor.u16Hi < u16LightSensor)
{
sDemoData.sLightSensor.u16Hi = u16LightSensor;
}
if (sDemoData.sLightSensor.u16Lo > u16LightSensor)
{
sDemoData.sLightSensor.u16Lo = u16LightSensor;
}
u16Diff = sDemoData.sLightSensor.u16Hi - sDemoData.sLightSensor.u16Lo;
/* Work out the current value as a value between 0 and 6 within the
range of values that have been seen previously */
if (u16Diff)
{
sDemoData.sSensors.u8AlsResult = (uint8)(((uint32)(u16LightSensor - sDemoData.sLightSensor.u16Lo) * 6) / (uint32)u16Diff);
}
else
{
sDemoData.sSensors.u8AlsResult = 0;
}
/* Set LED 1 based on light level */
if ((sDemoData.sSensors.u8AlsResult <= sDemoData.sControls.u8LightAlarmLevel)
&& (sDemoData.sControls.u8LightAlarmLevel < 7))
{
vLedControl(1, TRUE);
}
else
{
vLedControl(1, FALSE);
}
/* Read temperature, 0-52 are acceptable. Polls until result received */
vHTSstartReadTemp();
sDemoData.sSensors.u8TempResult = u8FindMin((uint8)u16HTSreadTempResult(), 52);
/* Read humidity, 0-104 are acceptable. Polls until result received */
vHTSstartReadHumidity();
sDemoData.sSensors.u8HtsResult = u8FindMin((uint8)u16HTSreadHumidityResult(), 104);
}
/****************************************************************************
*
* NAME: vProcessTxBlock
*
* DESCRIPTION:
* Creates an MCPS request to transmit a frame and passes it to the 802.15.4
* stack. The payload contains sensor information.
*
* RETURNS:
* void
*
****************************************************************************/
PRIVATE void vProcessTxBlock(void)
{
MAC_McpsReqRsp_s sMcpsReqRsp;
MAC_McpsSyncCfm_s sMcpsSyncCfm;
uint8 *pu8Payload;
/* Create frame transmission request */
sMcpsReqRsp.u8Type = MAC_MCPS_REQ_DATA;
sMcpsReqRsp.u8ParamLength = sizeof(MAC_McpsReqData_s);
/* Set handle so we can match confirmation to request */
sMcpsReqRsp.uParam.sReqData.u8Handle = sDemoData.sTransceiver.u8CurrentTxHandle;
/* Use short address for source */
sMcpsReqRsp.uParam.sReqData.sFrame.sSrcAddr.u8AddrMode = 2;
sMcpsReqRsp.uParam.sReqData.sFrame.sSrcAddr.u16PanId = DEMO_PAN_ID;
sMcpsReqRsp.uParam.sReqData.sFrame.sSrcAddr.uAddr.u16Short = sDemoData.sSystem.u16ShortAddr;
/* Use short address for destination */
sMcpsReqRsp.uParam.sReqData.sFrame.sDstAddr.u8AddrMode = 2;
sMcpsReqRsp.uParam.sReqData.sFrame.sDstAddr.u16PanId = DEMO_PAN_ID;
sMcpsReqRsp.uParam.sReqData.sFrame.sDstAddr.uAddr.u16Short = DEMO_COORD_ADDR;
/* Frame requires ack but not security, indirect transmit or GTS */
sMcpsReqRsp.uParam.sReqData.sFrame.u8TxOptions = MAC_TX_OPTION_ACK;
/* Payload is 8 bytes (room for expansion) and contains:
ID byte so coordinator knows this is sensor information
Previous beacon sequence number (for debug, can tell if beacon missed)
Virtual switch value
Sensor values: temp, humidity, light
*/
sMcpsReqRsp.uParam.sReqData.sFrame.u8SduLength = 8;
pu8Payload = sMcpsReqRsp.uParam.sReqData.sFrame.au8Sdu;
pu8Payload[0] = DEMO_ENDPOINT_IDENTIFIER;
pu8Payload[1] = sDemoData.sTransceiver.u8PrevRxBsn;
pu8Payload[2] = sDemoData.sControls.u8Switch;
pu8Payload[3] = sDemoData.sSensors.u8TempResult;
pu8Payload[4] = sDemoData.sSensors.u8HtsResult;
pu8Payload[5] = sDemoData.sSensors.u8AlsResult;
pu8Payload[6] = 0;
pu8Payload[7] = 0;
/* Request transmit */
vAppApiMcpsRequest(&sMcpsReqRsp, &sMcpsSyncCfm);
}
/****************************************************************************
*
* NAME: vProcessRxBeacon
*
* DESCRIPTION:
* Processes the beacon payload received from the coordinator. Checks that
* it is valid for the demo (8 bytes, with an identifier in the first byte)
* then stores data passed from coordinator (light level alarm, remote switch
* value). After processing reception, calls vProcessTxBlock to send a frame
* back.
*
* PARAMETERS: Name RW Usage
* psMlmeInd R Pointer to MLME event structure
*
* RETURNS:
* void
*
****************************************************************************/
PRIVATE void vProcessRxBeacon(MAC_MlmeDcfmInd_s *psMlmeInd)
{
uint8 *pu8Payload;
uint8 u8RxVal;
uint8 u8Bsn;
/* There has been a beacon notify, so get configuration from beacon
payload and re-synchronise timing */
if ((psMlmeInd->uParam.sIndBeacon.u8SDUlength != 8)
|| (psMlmeInd->uParam.sIndBeacon.u8SDU[0] != DEMO_BEACON_IDENTIFIER))
{
/* Not the payload we were looking for */
return;
}
pu8Payload = psMlmeInd->uParam.sIndBeacon.u8SDU;
/* Store beacon sequence number */
u8Bsn = psMlmeInd->uParam.sIndBeacon.u8BSN;
/* Read local 'relay' control and light low alarm level, as specified by
the user at the coordinator. Relay control is emulated by illuminating
an LED on the board */
u8RxVal = pu8Payload[1 + sDemoData.sSystem.u8ThisNode];
vLedControl(0, (bool_t)(u8RxVal & 0x01));
sDemoData.sControls.u8LightAlarmLevel = (u8RxVal >> 1) & 0x7;
if (((uint8)(u8Bsn - sDemoData.sTransceiver.u8PrevRxBsn)) > 7)
{
sDemoData.sTransceiver.u8PrevRxBsn = u8Bsn;
/* Respond to beacon by sending a frame and changing state to wait for
it to complete */
vProcessTxBlock();
sDemoData.sSystem.eState = E_STATE_TX_DATA;
}
}
/****************************************************************************
*
* NAME: u8FindMin
*
* DESCRIPTION:
* Returns the smallest of two values.
*
* PARAMETERS: Name RW Usage
* u8Val1 R First value to compare
* u8Val2 R Second value to compare
*
* RETURNS:
* uint8, lowest of two input values
*
****************************************************************************/
PRIVATE uint8 u8FindMin(uint8 u8Val1, uint8 u8Val2)
{
if (u8Val1 < u8Val2)
{
return u8Val1;
}
return u8Val2;
}
/****************************************************************************
*
* NAME: vDisplayError
*
* DESCRIPTION:
* Used to display fatal errors, by sending them to UART0 if this approach
* has been enabled at compile time.
*
* Sits in an endless loop afterwards.
*
* PARAMETERS: Name RW Usage
* pcErrorMessage R Message to display
* u32Data R Data to display
*
* RETURNS:
* void, never returns
*
****************************************************************************/
PRIVATE void vDisplayError(char *pcErrorMessage, uint32 u32Data)
{
#ifdef UART0_DEBUG
vDebug(pcErrorMessage);
vDisplayHex(u32Data, 8);
#endif
/* Fatal error has occurred, so loop indefinitely */
while (1);
}
/****************************************************************************
*
* NAME: vDebug
*
* DESCRIPTION:
* Sends a string to UART0 using the hardware API.
*
* PARAMETERS: Name RW Usage
* pcMessage R Null-terminated message to send
*
* RETURNS:
* void
*
****************************************************************************/
#ifdef UART0_DEBUG
PRIVATE void vDebug(char *pcMessage)
{
while (*pcMessage)
{
while ((u8AHI_UartReadLineStatus(0) & 0x20) == 0);
vAHI_UartWriteData(0, *pcMessage);
pcMessage++;
}
}
PRIVATE void vDisplayHex(uint32 u32Data, int iSize)
{
char acValue[9];
char *pcString = acValue;
uint8 u8Nybble;
int i, j;
j = 0;
for (i = (iSize << 2) - 4; i >= 0; i -= 4)
{
u8Nybble = (uint8)((u32Data >> i) & 0x0f);
u8Nybble += 0x30;
if (u8Nybble > 0x39)
u8Nybble += 7;
*pcString = u8Nybble;
pcString++;
}
*pcString = '\0';
vDebug(acValue);
}
#endif
/****************************************************************************/
/*** END OF FILE ***/
/****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -