📄 lightswitch.c
字号:
/****************************************************************************
*
* MODULE: lightswitch.c
*
* COMPONENT: $RCSfile: LightSwitch.c,v $
*
* VERSION: $Name: JN-AN-1002-1v4 $
*
* REVISION: $Revision: 1.1 $
*
* DATED: $Date: 2006/08/15 13:22:38 $
*
* STATUS: $State: Exp $
*
* AUTHOR: Ian Morris
*
* DESCRIPTION:
* Performs the function of a simple switch in a light bulb switching system.
* To be run on an Endpoint demonstration board, uses switch SW2 as the light
* switch. After a power on reset the light switch scans for a network to
* join. Once it has found the coordinator it joins the network and then
* enters sleep mode until SW2 is pressed. At this point is wakes up and
* transmits a data frame to the coordinator indicating that the light bulb
* should be toggled. Sleep mode is entered again once the data frame
* transmission is complete.
*
* CHANGE HISTORY:
*
* $Log: LightSwitch.c,v $ * Revision 1.1 2006/08/15 13:22:38 imorr * Initial version *
*
*
* LAST MODIFIED BY: $Author: imorr $
* $Modtime: $
*
*
****************************************************************************
*
* (c) Copyright 2000 JENNIC Ltd
*
****************************************************************************/
/****************************************************************************/
/*** Include files ***/
/****************************************************************************/
#include <jendefs.h>
#include <AppHardwareApi.h>
#include <AppQueueApi.h>
#include <mac_sap.h>
#include <mac_pib.h>
#include <string.h>
/****************************************************************************/
/*** Macro Definitions ***/
/****************************************************************************/
/* Defines the channels to scan. Each bit represents one channel. All channels
in the channels (11-26) in the 2.4GHz band are scanned. */
#define SCAN_CHANNELS 0x07FFF800UL
/* Light switch control */
#define LIGHT_SWITCH_INPUT_MASK 0x00000800UL
/* Network parameters */
#define PAN_ID 0x0401U
#define COORD_ADDR 0x0502U
/* NV RAM addresses used to store data through sleep cycles */
#define NVRAM_ADR_DEVICE_SHORT_ADR 20
#define NVRAM_ADR_NETWORK_CHAN 21
#define NVRAM_ADR_DEVICE_STATE 22
/* Light switch device data */
#define LIGHT_SWITCH_NODE_ADDR_BASE 0x1000U
/****************************************************************************/
/*** Type Definitions ***/
/****************************************************************************/
/* State machine states */
typedef enum
{
E_STATE_OFF,
E_STATE_SCANNING,
E_STATE_ASSOCIATING,
E_STATE_RUNNING,
} teState;
/* All application data with scope within the entire file is kept here,
including all stored node data */
typedef struct
{
struct
{
teState eState;
uint8 u8Channel;
uint16 u16ShortAddr;
} sSystem;
} tsDeviceData;
/****************************************************************************/
/*** Local Function Prototypes ***/
/****************************************************************************/
PRIVATE void vInitSystem(void);
PRIVATE void vInitEndpoint(void);
PRIVATE void vStartScan(void);
PRIVATE void vStartAssociate(void);
PRIVATE void vProcessEventQueues(void);
PRIVATE void vProcessIncomingMlme(MAC_MlmeDcfmInd_s *psMlmeInd);
PRIVATE void vProcessIncomingData(MAC_McpsDcfmInd_s *psMcpsInd);
PRIVATE void vProcessIncomingHwEvent(AppQApiHwInd_s *psAHI_Ind);
PRIVATE void vHandleActiveScanResponse(MAC_MlmeDcfmInd_s *psMlmeInd);
PRIVATE void vHandleAssociateResponse(MAC_MlmeDcfmInd_s *psMlmeInd);
PRIVATE void vTxDataFrame(void);
PRIVATE void vProcessLightSwitch(void);
PRIVATE void vLightSwitchSleep(void);
PRIVATE void vRestore(void);
PRIVATE void vPrintString(char *pcMessage);
PRIVATE void vInitUart(void);
/****************************************************************************/
/*** Exported Variables ***/
/****************************************************************************/
/****************************************************************************/
/*** Local Variables ***/
/****************************************************************************/
/* Handles from the MAC */
PRIVATE void *s_pvMac;
PRIVATE MAC_Pib_s *s_psMacPib;
PRIVATE tsDeviceData sDeviceData;
/****************************************************************************/
/*** Exported Functions ***/
/****************************************************************************/
/****************************************************************************/
/*** Local Functions ***/
/****************************************************************************/
/****************************************************************************
*
* NAME: AppColdStart
*
* DESCRIPTION:
* Runs application.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* Entry point for a power on reset or wake from sleep mode.
****************************************************************************/
PUBLIC void AppColdStart(void)
{
/* General initialisation: reset hardware */
vInitSystem();
if (u8AHI_PowerStatus() & 0x01) /* If this is a wake from sleep mode */
{
vPrintString("wkup\r\n");
/* Must have occured due to the light switch being pressed so
restore network and device parameters before processing light
switch */
vRestore();
vProcessLightSwitch();
}
else /* else it must be a power on reset */
{
vPrintString("pwr on\r\n");
/* Initialise software elements */
vInitEndpoint();
/* Perform scan to find light bulb (coordinator) */
vStartScan();
}
while (1)
{
/* Run main loop. */
vProcessEventQueues();
}
}
/****************************************************************************
*
* NAME: AppWarmStart
*
* DESCRIPTION:
* Entry point for a wake from sleep mode with the memory contents held. We
* are not using this mode and so should never get here.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PUBLIC void AppWarmStart(void)
{
/* Should never get here but just in case... */
AppColdStart();
}
/****************************************************************************
*
* NAME: vInitSystem
*
* DESCRIPTION:
* Initialise the device hardware and stack interface.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vInitSystem(void)
{
/* Initialise stack and hardware interfaces. We aren't using callbacks
at all, just monitoring the upward queues in a loop */
u32AppQApiInit(NULL, NULL, NULL);
u32AHI_Init();
/* Set up the MAC handles. Must be called AFTER u32AppQApiInit() */
s_pvMac = pvAppApiGetMacHandle();
s_psMacPib = MAC_psPibGetHandle(s_pvMac);
vInitUart();
/* Set Pan ID in PIB (also sets match register in hardware) */
MAC_vPibSetPanId(s_pvMac, PAN_ID);
}
/****************************************************************************
*
* NAME: vInitEndpoint
*
* DESCRIPTION:
* Initialise light bulb specific parameters.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vInitEndpoint(void)
{
/* Set defaults for software */
sDeviceData.sSystem.eState = E_STATE_OFF;
sDeviceData.sSystem.u16ShortAddr = 0xffff;
/* Set light switch button IO line to inputs */
vAHI_DioSetDirection(LIGHT_SWITCH_INPUT_MASK, 0);
/* Enable wakeup on negative edge of switch input */
vAHI_DioWakeEdge(0, LIGHT_SWITCH_INPUT_MASK);
vAHI_DioWakeEnable(LIGHT_SWITCH_INPUT_MASK, 0);
}
/****************************************************************************
*
* NAME: vLightSwitchSleep
*
* DESCRIPTION:
* Put the light switch device into low power sleep mode. Before this is done
* the current state of the application and details of the network it is a
* part of are stored in NVRAM so that they are not lost when the main RAM is
* powered down.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vLightSwitchSleep(void)
{
vPrintString("sleep\r\n");
/* Store network parameters and device state before going to sleep */
vAHI_NvRamWrite(NVRAM_ADR_DEVICE_SHORT_ADR,sDeviceData.sSystem.u16ShortAddr);
vAHI_NvRamWrite(NVRAM_ADR_NETWORK_CHAN,sDeviceData.sSystem.u8Channel);
vAHI_NvRamWrite(NVRAM_ADR_DEVICE_STATE,sDeviceData.sSystem.eState);
/* Go to sleep without holding contents of RAM to acheive lowest power */
vAHI_MemoryHold(FALSE);
vAHI_PowerDown(FALSE);
}
/****************************************************************************
*
* NAME: vRestore
*
* DESCRIPTION:
* Restore application state and network parameter from NVRAM.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vRestore(void)
{
vPrintString("restore\r\n");
/* Restore device state and network parameters from NVRAM */
sDeviceData.sSystem.u16ShortAddr = (uint16)u32AHI_NvRamRead(NVRAM_ADR_DEVICE_SHORT_ADR);
sDeviceData.sSystem.u8Channel = (uint8)u32AHI_NvRamRead(NVRAM_ADR_NETWORK_CHAN);
sDeviceData.sSystem.eState = (uint16)u32AHI_NvRamRead(NVRAM_ADR_DEVICE_STATE);
}
/****************************************************************************
*
* NAME: vProcessLightSwitch
*
* DESCRIPTION:
* Process the light switch input. This routine gets called after a wakeup
* event has been generated by the light switch input being taken low. By the
* time we arrive at this point the application has been loaded from external
* FLASH. This means that in order to debounce the switch all we have to do is
* check that it is still low. If it is then we send a data frame to the light
* bulb indicating that it should be toggled, sleep mode is entered when we
* get a confirmation that this frame has been successfully transmitted.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vProcessLightSwitch(void)
{
uint32 u32DioStatus;
/* Read wake status of IO lines to clear bits and prevent multiple interrupts */
u32DioStatus = u32AHI_DioWakeStatus();
if ((u32AHI_DioReadInput() & LIGHT_SWITCH_INPUT_MASK) == 0)
{
/* If light switch input is still low after the time taken to load
the application from external serial FLASH then we can assume it
is not a result of switch bounce and toggle the light bulb by
sending a data frame to the coordinator */
vTxDataFrame();
}
else
{
/* Switch not low (could be a switch bounce) so just return to sleep */
vLightSwitchSleep();
}
}
/****************************************************************************
*
* NAME: vProcessEventQueues
*
* DESCRIPTION:
* Check each of the three event queues and process and items found.
*
* PARAMETERS: Name RW Usage
* None.
*
* RETURNS:
* None.
*
* NOTES:
* None.
****************************************************************************/
PRIVATE void vProcessEventQueues(void)
{
MAC_MlmeDcfmInd_s *psMlmeInd;
MAC_McpsDcfmInd_s *psMcpsInd;
AppQApiHwInd_s *psAHI_Ind;
/* Check for anything on the MCPS upward queue */
do
{
psMcpsInd = psAppQApiReadMcpsInd();
if (psMcpsInd != NULL)
{
vProcessIncomingData(psMcpsInd);
vAppQApiReturnMcpsIndBuffer(psMcpsInd);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -