📄 udldcfg.c
字号:
}
if (!found) {
/* advance to next message */
lpMsg = (LPUDMSG) FindNextItem (&message_scanner);
}
}
/** check whether a compatible existing message was found,
even if we couldn't fold **/
if ((!folding) && (lpAppendMsg != (LPUDMSG) NULL)) {
/* indicate message found, get its pointer */
found = TRUE;
lpFoundMsg = lpAppendMsg;
}
/* if match found, put new data into message */
if (found) {
/* get pointer to message, indicate not changed */
lpMsg = lpFoundMsg;
changed = FALSE;
/* check whether folding this write into an existing message */
if (folding) {
/* substitute new data for the selected item */
/* find start of block of data */
myOff = (WORD) (found_index * 2); /* assume 2 bytes per "cell" */
pByte = lpMsg->mmOutData + myOff;
/* copy new data to holding area */
length = (WORD) (count * numBytes);
_fmemcpy (pByte, &pOutData[0], (size_t) length);
/* indicate message has changed */
changed = TRUE;
} else {
/* extend existing message */
if (lpMsg->mmEndAddr+1 == myAddr) {
/* extend final block in message */
/* find end of final block of data */
found_index = myAddr - lpMsg->mmStartAddr;
myOff = (WORD) (found_index * 2); /* assume 2 bytes per "cell" */
pByte = lpMsg->mmOutData + myOff;
/* copy new data to holding area */
length = (WORD) (count * numBytes);
_fmemcpy (pByte, &pOutData[0], (size_t) length);
/* update counts and extend final block */
lpMsg->mmCount += count;
lpMsg->mmEndAddr = endAddr;
} else {
/* insert block at beginning of message */
/* make room before existing data */
length = (WORD) ((lpMsg->mmEndAddr+1 - lpMsg->mmStartAddr) * 2);
pByte = lpMsg->mmOutData;
_fmemmove (pByte+2, pByte, length);
/* copy new data to holding area */
length = (WORD) (count * numBytes);
_fmemcpy (pByte, &pOutData[0], (size_t) length);
/* update counts and extend initial block */
lpMsg->mmCount += count;
lpMsg->mmStartAddr = myAddr;
}
/* indicate message has changed */
changed = TRUE;
}
/******************************************************************\
Modify the existing write message to include the new data value
\******************************************************************/
/* rebuild existing write message with changes */
plcAddr = lpTopic->statTopic;
msgSize = BldWrite (plcAddr, // 2/28/2000 Modify by Chen jun
&lpData, lpMsg->mmOutData,
plcDataType, DDEType,
lpMsg->mmStartAddr, lpMsg->mmCount);
if (msgSize != 0) {
/* copy modified message to message structure */
lpMsg->mmDue = TRUE;
lpMsg->mmSize = msgSize;
_fmemcpy (lpMsg->mmData, lpData, (size_t) msgSize);
/* indicate if message has changed */
lpMsg->mmChanged = changed;
/* initialize flag */
new_symbol = FALSE;
/* get pointer to first symbol entry associated with the write */
lpSymOld = (SYMPTR) GetExtArrayMemberPtr (&lpTopic->statSymTab,
(lpMsg->mmFirstSym - SYM_OFFSET));
/* compare to this symbol */
if (LogicalAddrCmp (lpSymEnt, lpSymOld) < 0) {
/* set new first symbol for message */
lpMsg->mmFirstSym = SymHandle;
new_symbol = TRUE;
}
/* get pointer to last symbol entry associated with the write */
lpSymOld = (SYMPTR) GetExtArrayMemberPtr (&lpTopic->statSymTab,
(lpMsg->mmLastSym - SYM_OFFSET));
/* compare to this symbol */
if (LogicalAddrCmp (lpSymOld, lpSymEnt) < 0) {
/* set new last symbol for message */
lpMsg->mmLastSym = SymHandle;
new_symbol = TRUE;
}
if (new_symbol) {
/* bump the lock count for the indicated symbol */
lpSymEnt->msLockCt++;
}
}
} else {
/******************************************************************\
Create a new write message for the new data value
\******************************************************************/
/* build new message */
plcAddr = lpTopic->statTopic;
msgSize = BldWrite (plcAddr, // 2/28/2000 Modify by Chen jun
&lpData, (BYTE FAR *) pOutData,
plcDataType, DDEType,
myAddr, count);
/* allocate new message structure */
assert(msgSize != 0);
allocSize = MAX_MSG_SIZE + sizeof(UDMSG);
lpMsg = (LPUDMSG) wwHeap_AllocPtr(hHeap,
GMEM_MOVEABLE | GMEM_ZEROINIT,
(DWORD) allocSize);
if (lpMsg != (LPUDMSG) NULL) {
/* copy new data to holding area */
length = (WORD) (count * numBytes);
_fmemcpy (lpMsg->mmOutData, &pOutData[0], (size_t) length);
/* copy new message to message structure */
lpMsg->mmSize = msgSize;
_fmemcpy(lpMsg->mmData, lpData, (size_t) msgSize);
/* set pointers to station, symbol, etc. */
lpMsg->mmTopic = lpTopic;
lpMsg->mmTopicId = lpTopic->statTopic;
lpMsg->mmIdLogDev = lpTopic->statIdLogDev;
lpMsg->mmFirstSym = SymHandle;
lpMsg->mmLastSym = SymHandle;
lpMsg->mmActiveCt = 1;
lpMsg->mmDue = TRUE; /* Write immediately */
lpMsg->mmRead = FALSE;
lpMsg->mmScanTimer = 0;
lpMsg->mmScanReload = 0;
/**************************************************************\
Initialize the protocol dependent message fields here.
\**************************************************************/
lpMsg->mmMsgInBinary= bBldSendMsgInBinary;
lpMsg->mmMsgType = msgType;
lpMsg->mmStartAddr = myAddr;
lpMsg->mmEndAddr = endAddr;
lpMsg->mmCount = count;
lpMsg->mmMbType = DDEType;
lpMsg->mmDiscrete = discrete;
/*
* Chain the newly allocated message into the write
* message list on the topic.
*/
AppendItemAtTail (&lpTopic->statWriteMsgList, (LPCHAINLINK) lpMsg);
/* bump the lock count for the indicated symbol */
lpSymEnt->msLockCt++;
} else {
#ifdef DEBUG_CALL_TRAFFIC
if (Verbose)
debug ("UdprotPrepareWriteMsg - can't alloc for message");
#endif
return FALSE; /* Couldn't allocate memory */
}
}
/* set message due flag */
lpMsg->mmDue = TRUE;
/* indicate success */
return ok;
} /* UdprotPrepareWriteMsg */
/***********************************************************************/
/** add polling of indicated point to queue of messages for station
returns TRUE if successful **/
BOOL
WINAPI
UdprotAddPoll (LPSTAT lpTopic,
SYMPTR lpSymEnt)
{
unsigned long SymHandle;
SYMPTR lpSymTab, lpSymOld;
LPSTR lpData;
LPUDMSG lpMsg;
LPUDMSG lpFoundMsg, lpBestFitMsg;
WORD newStart, newEnd;
BOOL ok, discrete;
BOOL folding, found, first, msg_ready;
WORD count, count_limit, numBytes, msgSize, allocSize;
WORD myAddr, endAddr;
BYTE plcDataType, subType;
BYTE msgType;
BYTE DDEType;
int found_index;
int bfDelta, delta;
WORD bfStart, bfEnd;
WORD bfCount, size;
WORD blockSize, extSize, message_limit;
CHAINSCANNER message_scanner;
#ifdef DEBUG_CALL_TRAFFIC
if (Verbose)
debug ("UdprotAddPoll( %Fp, %Fp )", lpTopic, lpSymEnt);
#endif
/* initialize return value */
ok = TRUE;
/* indicate error if pointers are NULL */
assert(lpTopic);
/* get handle for symbol table entry */
assert(lpSymEnt);
SymHandle = lpSymEnt->msIndex + SYM_OFFSET;
/* set type of data message, data from symbol table entry */
plcDataType = (BYTE) lpSymEnt->msPlcDataType;
DDEType = (BYTE) lpSymEnt->msDdeType;
subType = (BYTE) lpSymEnt->msSubType;
myAddr = lpSymEnt->msAddr1;
count = lpSymEnt->msCount;
endAddr = (WORD) (myAddr + count - 1);
numBytes = (WORD) lpSymEnt->msNumBytes;
discrete = FALSE;
msgType = (BYTE) plcDataType; /* device-specific */
/* check length of requested data, if necessary */
switch (subType)
{
case PLCS_STRC:
case PLCS_STRP:
case PLCS_STRB:
case PLCS_STR_:
/* ensure string is no longer than what we can receive in one message */
count_limit = LimitStringLength (myAddr, count, numBytes, TRUE);
if (count > count_limit)
{
/* too long, truncate string to manageable length */
count = count_limit;
endAddr = (WORD) (myAddr + count - 1);
}
break;
} /* switch */
/* get lengths needed to read and extend a message for this point */
GetBldMsgReadBlockSizes (&blockSize, &extSize,
msgType, plcDataType, myAddr, count);
/* get max length for message */
message_limit = UD_MAX_MESSAGE_SIZE;
/* get pointer to symbol table for station */
lpSymTab = (SYMPTR) lpTopic->statSymTab.first_member;
if (lpSymTab == (SYMPTR) NULL) {
/* no symbol table, so do nothing */
return FALSE;
}
/*********************************************************************\
There are two main ways read traffic may be reduced:
1. Folded reads.
When multiple data points access the same device memory range,
an existing message can be used to read data for all those
points. This is accomplished by setting the message pointer
in the symbol table entry to point to the indicated message
and incrementing the active count accordingly. In this case,
it is not necessary to regenerate the read message.
2. Optimized reads.
Instead of generating a new read message for each point
extend a compatible existing message, if any. This is
accomplished by extending the memory range requested by an
existing message with the range for the new point and then
regenerating the message. For really, REALLY optimized reads,
it might be faster to request a single response for a range
of memory that includes gaps -- i.e. areas that you don't
need to read -- rather than handle two or more messages for
the discontinuous ranges of memory. For example, if you need
data from words 1, 3, and 5, it COULD be faster to have one
message return values for words 1-5 and ignore the values for
words 2 and 4. This could be nice if a later request came in
for data from word 2 or 4 -- then you could just fold in the
read for the new data point.
Note: Optimized reads may or may not be possible, depending on
the communication protocol for the device. How to make
the extension depends on such things as addressing modes
and the partitioning of device memory. Also, it is
important to make sure that (a) the extended message is not
too long for the device protocol, and (b) the RESPONSE to
the extended message will not be too long for the protocol.
The example code below is for a simulated device that permits
reading and writing up to 22 consecutive memory locations of the
same data type. So a point is included if it is of the same
plcDataType and falls within the address range mmStartAddr..mmEndAddr.
And the message can be extended if it is of the same plcDataType and
the point is just before or after the range mmStartAddr..mmEndAddr.
\*********************************************************************/
/* get pointer to first message in read list */
lpMsg = (LPUDMSG) FindFirstItem (&lpTopic->statReadMsgList, SCAN_FROM_HEAD,
NULL, NULL, &message_scanner);
/* initialize search variables */
found = FALSE;
folding = FALSE;
found_index = 0;
lpFoundMsg = (LPUDMSG) NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -