📄 exm.c
字号:
/* Copyright (c) 1999-2002 ITRAN Communications, Ltd. All rights reserved */
/*
This application is a simple example of using the modem for switching lamp. We have only two devices in
our network: "switch" and "lamp". The present application impements all functions for the switch. It has
one button and indicator. When the user presses the button the aplication sends command to the lamp via
the PLC network. The lamp receives the command and turns into desired state. Then the lamp sends the answer
about its state to the switch via the network. If the switch device does not receive the answer for some reason
it decides that the target had not received its command and repeats the reques again.
*/
#include "Portability.h"
#include "HalExm.h"
#include "WtIfcDef.h"
#include "DLHdi.h"
// ****************************************************************************************************
// sizes of the application buffers
#define Exm_RESP_SIZE 164
#define Exm_PKT_SIZE 164
// indices of the command payload
#define Exm_CMDIDX_ATTN 0
#define Exm_CMDIDX_ID 1
#define Exm_CMDIDX_LENLO 2
#define Exm_CMDIDX_LENHI 3
#define Exm_CMDIDX_PL 4
#define Exm_ANSW_PL_IDX_CMDID 0
#define Exm_ANSW_PL_IDX_RESULT 1
// packet header parameters
#define Exm_LEN_HEADER 4
#define Exm_LEN_PKT_FILEDS 8
// device address in the network
#define Exm_NETID 73
#define Exm_NODEID 19
#define Exm_TARGET1ID 3
// parameters of media access
#define Exm_REPEATS 3
#define Exm_RETRIES 3
#define Exm_RXTYPE 1
// ****************************************************************************************************
#define Exm_W2B( x ) (BYTE)x, (BYTE)(x >> 8) // converts one wort into list of two bytes
// reset command
BYTE Exm_Cmd_Reset[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_RST, 1, 0, 0 };
// start single device mode command
BYTE Exm_Cmd_StartSdm[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_SSD, 1, 0, 0 };
// set modulation command
BYTE Exm_Cmd_Modulation[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_CW, 1, 0, DLHdi_CODE_RATEMODE_DCSK4 };
// set repeats and retries command
BYTE Exm_Cmd_Repeats[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_SRC, 2, 0, Exm_REPEATS, Exm_RETRIES };
// set RX packet type command
BYTE Exm_Cmd_RxType[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_RPT, 1, 0, Exm_RXTYPE };
// set address command
BYTE Exm_Cmd_SetAddress[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_ADE, 4, 0, Exm_W2B(Exm_NETID), Exm_W2B(Exm_NODEID) };
BYTE Exm_Cmd_SendCfgPacket[] =
{
WtIfcDef_ATTN,
WtIfcDef_ePcCmd_SC,
16, 0,
0xF8, // configuration packet
0x3F, 0xC4, 0xDE, 0x3C,
0x6E, 0x28, 0x28, 0x64,
0x64, 0xB8, 0x4F, 0x51,
0x00, 0x00, 0x00
};
BYTE Exm_Cmd_ReadEEPROM[] =
{
WtIfcDef_ATTN,
WtIfcDef_ePcCmd_REP,
5, 0,
10, 0, 0, 0, // arbitrary address to read data from
20 // size of the data
};
BYTE Exm_Cmd_WriteEEPROM[] =
{
WtIfcDef_ATTN,
WtIfcDef_ePcCmd_REP,
9, 0,
14, 0, 0, 0, // arbitrary address to write data to
0x01, 0x0A, 0x0B, 0x04, 0x02 // some data
};
BYTE Exm_Cmd_GetDLLParam[] = { WtIfcDef_ATTN, WtIfcDef_ePcCmd_GCD, 1, 0, 0 };
// this packet will be sent to the target device when the application decides to turn the "lamp" on
BYTE Exm_LampOnPkt[] =
{
WtIfcDef_ATTN,
WtIfcDef_ePcCmd_PT,
Exm_LEN_PKT_FILEDS + 11,
0,
DLHdi_CodeCmdSpPrty_NORM,
DLHdi_CodeCmdSpServ_REP,
Exm_W2B(Exm_NETID),
Exm_W2B(Exm_NODEID),
Exm_W2B(Exm_TARGET1ID),
'L', 'a', 'm', 'p', '_', 'O', 'N', '_', '_', '_', 'R'
};
// this packet will be sent to the target device when the application decides to turn the "lamp" off
BYTE Exm_LampOffPkt[] =
{
WtIfcDef_ATTN,
WtIfcDef_ePcCmd_PT,
Exm_LEN_PKT_FILEDS + 11,
0,
DLHdi_CodeCmdSpPrty_NORM,
DLHdi_CodeCmdSpServ_REP,
Exm_W2B(Exm_NETID),
Exm_W2B(Exm_NODEID),
Exm_W2B(Exm_TARGET1ID),
'L', 'a', 'm', 'p', '_', 'O', 'F', 'F', '_', '_', 'R'
};
// keywords in the answer packets from the target device ("the lamp" )
char Exm_LampOnAnsw[] = "LampIsOn";
char Exm_LampOffAnsw[] = "LampIsOff";
// ****************************************************************************************************
// ****************************************************************************************************
// states of the application receiver
typedef
enum tagExm_eRecState_t
{
Exm_eRecState_Attn = 0, // the receiver waits for incoming data from the modem
Exm_eRecState_Command = 1, // it is receiving the answer ID
Exm_eRecState_Length_Low = 3, // it is receiving the low byte of the length
Exm_eRecState_Length_High = 4, // it is receiving the high byte of the length
Exm_eRecState_Payload = 5 // it is receiving the answer or packet payload
} Exm_eRecState_t;
// ****************************************************************************************************
// global variables of the application
typedef
struct tagExm_GLOBAL_T
{
Exm_eRecState_t eRecState; // the application receiver state
WORD wRecPLIdx; // current index of incoming answer or packet payload
WORD wRecLength; // incoming answer/packet length
BYTE byRecAnswID; // ID value of incomin answer
BYTE sRecAnswBuf[Exm_RESP_SIZE]; // buffer for storing the incoming answer
BOOL bRecAnsw; // flag for signaling that the receiver has new answer in its buffer
BOOL bResetDetected; // flag for signaling the modem reset
BYTE sPktBuf[Exm_PKT_SIZE]; // buffer for storing the incoming packet
BOOL bSwState; // the "switch" state
BOOL bRemoteLampState; // state of the target device "lamp" as it known to our application
BOOL bLampOffPktReceived; // the application has received "the lamp is off" feedback from the target device
BOOL bLampOnPktReceived; // the application has received "the lamp is on" feedback from the target device
} Exm_GLOBAL_T;
// ****************************************************************************************************
Exm_GLOBAL_T Exm;
// ****************************************************************************************************
// on sending data end callback
//
// Description: this function is called by HAL module when the transmission ends
//
// ****************************************************************************************************
void HalExm_CB_OnSendDataEnd( void )
{
}
// ****************************************************************************************************
// fill the answer buffer
//
// Description: this function fills the modem answer buffer with a byte and moves the current payload
// index
//
// Arguments: byData is one byte of answer payload
//
// ****************************************************************************************************
void s_FillAnswBuf( BYTE byData )
{
Exm.sRecAnswBuf[Exm.wRecPLIdx++] = byData; // put the byte into the answer buffer
// and increment the index
if( Exm.wRecPLIdx == Exm.wRecLength ) // check if the buffer is full
{
Exm.eRecState = Exm_eRecState_Attn; // reset the receiver state
Exm.bRecAnsw = TRUE; // set "we have got an answer" flag
if( Exm.byRecAnswID == WtIfcDef_eDLLCmd_Responce // if we have received the "reset" notification
&& Exm.sRecAnswBuf[Exm_ANSW_PL_IDX_CMDID] == WtIfcDef_ePcCmd_RST )
{
Exm.bResetDetected = TRUE; // set the reset flag
}
}
}
// ****************************************************************************************************
// fill the answer buffer
//
// Description: this function fills the packet buffer with a byte and moves the current payload
// index
//
// Arguments: byData is one byte of packet payload
//
// ****************************************************************************************************
#define Exm_INC_PKT_PL_START_IDX 15 // index of the data start in the packet payload
void s_FillPktBuf( BYTE byData )
{
static BOOL bLmpOnD, bLmpOffD; // variables for detecting the keyword in the packet
if( Exm.wRecPLIdx == 0 ) // if the byte is the first one in the packet payload
{
bLmpOnD = TRUE; // reset the variables
bLmpOffD = TRUE;
}
if( Exm.wRecPLIdx >= Exm_INC_PKT_PL_START_IDX ) // if the index has reached the keyword
{
// compare the data with "on" keyword
if( byData != Exm_LampOnAnsw[Exm.wRecPLIdx - Exm_INC_PKT_PL_START_IDX] ) { bLmpOnD = FALSE; }
// compare with off keyword
if( byData != Exm_LampOffAnsw[Exm.wRecPLIdx - Exm_INC_PKT_PL_START_IDX] ) { bLmpOffD = FALSE; }
}
Exm.sPktBuf[Exm.wRecPLIdx] = byData; // store the data in the packet buffer
if( ++Exm.wRecPLIdx == Exm.wRecLength ) // increment the payload index and chek for the packet end
{
Exm.eRecState = Exm_eRecState_Attn; // reset the receiver state
if( bLmpOnD ) { Exm.bLampOnPktReceived = TRUE; } // if the packet contains the "lamp is on" answer
if( bLmpOffD ) { Exm.bLampOffPktReceived = TRUE; } // if the packet contains the "lamp is off" answer
}
}
// ****************************************************************************************************
// error case hander
//
// Description: Just reset the receiver state
//
// ****************************************************************************************************
void s_OtherType( void )
{
if( ++Exm.wRecPLIdx == Exm.wRecLength ) { Exm.eRecState = Exm_eRecState_Attn; } // reset the receiver state
}
// ****************************************************************************************************
// "on data received" callback
//
// Description: This function is called when the USART receives one byte from the modem
//
// Arguments: byData is one byte from the USART
//
// ****************************************************************************************************
void HalExm_CB_OnDataReceived( BYTE byData )
{
switch( Exm.eRecState )
{
case Exm_eRecState_Attn:
if( byData == WtIfcDef_ATTN ) // if the first byte is ATTN
{
Exm.eRecState = Exm_eRecState_Command; // start the receiving, set "command" state
}
break;
case Exm_eRecState_Command:
Exm.byRecAnswID = byData; // save the ID
Exm.eRecState = Exm_eRecState_Length_Low; // set "length low" state
break;
case Exm_eRecState_Length_Low:
Exm.wRecLength = byData; // store the low byte of the length
Exm.eRecState = Exm_eRecState_Length_High; // set "length high" state
break;
case Exm_eRecState_Length_High:
Exm.wRecLength |= (((WORD)byData) << 8) ; // store the length high byte
Exm.eRecState = Exm_eRecState_Payload; // start receiving the payload
Exm.wRecPLIdx = 0; // reset the payload index
break;
case Exm_eRecState_Payload: // all othe bytes fill the payload buffer
if( Exm.wRecPLIdx < Exm.wRecLength ) // if the payload index is below the length
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -