📄 mod232commsprocessor.cpp
字号:
pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
if (MAX_MOD_MEMWORDS >= modMsg.address + modMsg.byteCount)
{
WORD memValueTemp;
deb.Format("Read Register from %d for %d .\n", modMsg.address, modMsg.byteCount);
OutputDebugString(deb);
RSDataMessage(deb);
for (i=0; i <modMsg.byteCount;i++)
{
// grab the memory now
memValueTemp = PLCMemory[requestMemArea][(seperationOffset + modMsg.address)+i];
*(WORD*)pDataPortion = SwapBytes( memValueTemp );
pDataPortion += 2;
}
}
else
{
// pack the exception code into the message
ASSERT(0); // this is supposed to be caught in TestMessage()
responseModMsg.buffer[1] |= 0x80;
responseModMsg.buffer[2] = 0x02; // exception code here (could also use 0x03)
deb.Format("Read register past %d error x%02X!\n", MAX_MOD_MEMWORDS, (BYTE)responseModMsg.buffer[2]);
OutputDebugString(deb);
RSDataMessage(deb);
}
break;
default :
// Writes acks are all built in copy constructor
// But the update is done here!
if (MAX_MOD_MEMWORDS >= modMsg.address + modMsg.byteCount)
{
// lock memory for writting
CMemWriteLock lk(PLCMemory.GetMutex());
pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
if (!lk.IsLocked())
//...Update
switch (modMsg.functionCode)
{
case MOD_WRITE_SINGLE_COIL :
{
CString deb;
deb.Format("Write single output %d.\n", modMsg.address);
OutputDebugString(deb);
RSDataMessage(deb);
}
//data gets copied in now
if (m_modifyThenRespond)
PLCMemory.SetAt(requestMemArea, seperationOffset +modMsg.address, (*(WORD*)modMsg.dataPtr?1:0));
// pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
*pDataPortion++ = (PLCMemory[requestMemArea][(seperationOffset +modMsg.address)+i] ? 0xFF : 0x00);
*pDataPortion++ = 0x00;
if (!m_modifyThenRespond)
PLCMemory.SetAt(requestMemArea, seperationOffset +modMsg.address, (*(WORD*)modMsg.dataPtr?1:0));
numRegs = 1; // repaint 1 item
break;
case MOD_WRITE_MULTIPLE_COILS :
// unpack into the SIMul memory on WORD of sim memory for every BIT in the data
//WORD numBytes;
numBytesInReq = modMsg.count/8;
if (modMsg.count%8) // if we overflow a byte
numBytesInReq++;
{
CString deb;
deb.Format("Write multiple outputs from %d for %d bits.\n", modMsg.address, modMsg.count);
OutputDebugString(deb);
RSDataMessage(deb);
}
numRegs = numBytesInReq; // repaint X bits
for (i=0;i<numBytesInReq;i++)
{
WORD bitOffset;
for (bitOffset=0;bitOffset<8;bitOffset++)
{
if ((i*8)+bitOffset <= modMsg.count)
{
if (*(BYTE*)modMsg.dataPtr & (0x01<<bitOffset))
PLCMemory.SetAt(requestMemArea, seperationOffset +modMsg.address+(i*8)+bitOffset, 1);
else
PLCMemory.SetAt(requestMemArea, seperationOffset +modMsg.address+(i*8)+bitOffset, 0);
}
}
modMsg.dataPtr++;
}
break;
case MOD_WRITE_HOLDING : //WRITE multiple holdings
case MOD_WRITE_EXTENDED:
//PLCMemory[requestMemArea][modMsg.address] = SwapBytes(*(WORD*)modMsg.dataPtr);
//break;
numRegs = modMsg.byteCount/2;
{
CString deb;
deb.Format("Write multiple registers from %d for %d registers.\n", modMsg.address, numRegs);
OutputDebugString(deb);
RSDataMessage(deb);
}
for (i=0;i<numRegs;i++)
{
PLCMemory.SetAt(requestMemArea, seperationOffset + modMsg.address + i, SwapBytes(*(WORD*)modMsg.dataPtr));
modMsg.dataPtr +=2; // inc pointer by 2 bytes
}
break;
case MOD_WRITE_SINGLEHOLDING : //WRITE single holding reg.
{
CString deb;
WORD memValueTemp;
deb.Format("Write single register %d.\n", modMsg.address);
OutputDebugString(deb);
RSDataMessage(deb);
numRegs = 1; //repaint 1 register
if (m_modifyThenRespond)
PLCMemory.SetAt(requestMemArea, seperationOffset + modMsg.address , SwapBytes(*(WORD*)modMsg.dataPtr));
memValueTemp = PLCMemory[requestMemArea][(seperationOffset +modMsg.address)];
*(WORD*)pDataPortion = SwapBytes( memValueTemp );
if (!m_modifyThenRespond)
PLCMemory.SetAt(requestMemArea, seperationOffset + modMsg.address , SwapBytes(*(WORD*)modMsg.dataPtr));
modMsg.dataPtr +=2; // inc pointer by 2 bytes
pDataPortion += 2;
}
break;
}
}
// we can only call on the GUI thread once we have un-locked
if (pGlobalDialog)
{
int cols = pGlobalDialog->GetListDisplayedWidth();
pGlobalDialog->RedrawListItems(modMsg.GetAddressArea(modMsg.functionCode),
(seperationOffset +modMsg.address)/(cols),
(seperationOffset +modMsg.address+(numRegs-1))/(cols)
); // repaint only the needed rows
}
break;
}
}
else
{ // error occurred
pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
}
if (0 == modMsg.stationID) // broadcast, don't respond at all.
return (TRUE);
// finnish building the response
responseModMsg.totalLen = (WORD)((LONG)pDataPortion-(LONG)responseModMsg.buffer);
responseModMsg.totalLen += MODBUS_CRC_LEN;
// 5. append the CRC
//OutputDebugString("Calculate CRC\n");
{
responseModMsg.BuildMessageEnd();
}
// 6. send it back
m_debuggerStep = 102;
#ifdef _COMMS_DEBUGGING
sprintf(debugStr, "Send %d bytes\n", responseModMsg.totalLen);
OutputDebugString(debugStr);
#endif
RSStateChanged(RSPORTCURRENTLY_WRITTING);
// Send it on the wire , but first kill any incomming messages as well so we don't overflow or anything
Purge();
if (!m_NoiseSimulator.ErrorsEnabled())
Send(responseModMsg.totalLen, (BYTE*)responseModMsg.buffer, debugStr);
else
{
m_NoiseSimulator.InjectErrors((CRS232Port*)this, (BYTE*)responseModMsg.buffer, responseModMsg.totalLen, debugStr);
RSDataMessage("Error simulation active\n");
}
m_debuggerStep = 103;
// inc our counter
pGlobalDialog->PacketsSentInc();
RSDataMessage(".\n");
/*if (TRUE)
{
BOOL linesSet;
linesSet = EscapeCommFunction(h232Port,
Sleep(300);
linesSet = EscapeCommFunction(h232Port,
} */
return (TRUE);
} // ProcessData
// ----------------------------- LoadRegistersIMP -----------------------------
// STATIC : implements the function to load register values from file
BOOL CMOD232CommsProcessor::LoadRegistersIMP()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;
if (!dat.Open("MODDATA.DAT", CFile::modeRead|CFile::shareDenyRead, &ex) )
{
// complain if an error happened
// no need to delete the exception object
TCHAR szError[1024];
ex.GetErrorMessage(szError, 1024);
OutputDebugString( "Couldn't open source file: ");
OutputDebugString( szError);
return FALSE;
}
// read it in
for (area=0;area < MAX_MOD_MEMTYPES;area++)
{
DWORD numRead,totalRead=0;
WORD dataWord;
DWORD maxIndex = PLCMemory[area].GetSize();
// lock the memory for reading
// CMemWriteLock lk(pGlobalDialog->m_pMemWriteSync);
CMemWriteLock lk(PLCMemory.GetMutex());
// loop thru all registers (WORD)
if (!lk.IsLocked())
{
for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
{
numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
PLCMemory.SetAt(area, wordIndex, dataWord);
totalRead +=numRead;
if (numRead != sizeof(WORD))
return FALSE;
}
// Read past the rest of the block
while (wordIndex < MAX_MOD_MEMWORDS)
{
numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
totalRead +=numRead;
if (numRead != sizeof(WORD))
return FALSE;
wordIndex++;
}
}
else
{
CString errorMsg;
//error
errorMsg.LoadString(IDS_SYNC_READING);
AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
return FALSE;
}
}
return(TRUE);
}
// ----------------------------- LoadRegisters -----------------------------
// load binary dump of the register values from file.
BOOL CMOD232CommsProcessor::LoadRegisters()
{
BOOL ret = LoadRegistersIMP();
if (ret)
RSDataMessage("Register values loaded OK\n");
return (ret);
} // LoadRegisters
// --------------------------------------- SaveRegisters ---------------------------
// save a binary dump of the values to file.
BOOL CMOD232CommsProcessor::SaveRegisters()
{
BOOL ret = SaveRegistersIMP();
if (ret)
RSDataMessage("Register values saved OK\n");
return (ret);
}
// --------------------------------------- SaveRegistersIMP ---------------------------
// STATIC : save all register values to a flat file.
BOOL CMOD232CommsProcessor::SaveRegistersIMP()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;
if (!dat.Open("MODDATA.DAT", CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate, &ex) )
{
// complain if an error happened
// no need to delete the ex object
TCHAR szError[1024];
ex.GetErrorMessage(szError, 1024);
OutputDebugString( "Couldn't open source file: ");
OutputDebugString( szError);
return FALSE;
}
// read it in
for (area=0;area < MAX_MOD_MEMTYPES;area++)
{
WORD wordData;
DWORD maxIndex = PLCMemory[area].GetSize();
// lock the memory for writting
CMemWriteLock lk(PLCMemory.GetMutex());
// loop thru all registers (WORD)
if (!lk.IsLocked())
{
for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
{
wordData = PLCMemory[area][wordIndex];
dat.Write((BYTE*)&wordData, sizeof(WORD));
}
// Fill the rest with NULLs
while (wordIndex < MAX_MOD_MEMWORDS)
{
wordData = 0;
dat.Write((BYTE*)&wordData, sizeof(WORD));
wordIndex++;
}
}
else
{
CString errorMsg;
errorMsg.LoadString(IDS_SYNC_WRITTING);
AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
// error
return FALSE;
}
}
return TRUE;
} // SaveRegistersIMP
// ------------------------------- ActivateStation ---------------------------
void CMOD232CommsProcessor::ActivateStationLED(LONG stationID)
{
if (stationID>0 && stationID<STATIONTICKBOXESMAX)
{
//start the counter for this station at the beginning
pGlobalDialog->m_microTicksCountDown[stationID] = pGlobalDialog->GetAnimationOnPeriod();
// it will count down untill it extinguishes
}
} // ActivateStation
// ------------------------------- StationIsEnabled ---------------------------
// Return TRUE if station is enabled
BOOL CMOD232CommsProcessor::StationIsEnabled(LONG stationID)
{
if (stationID>0 && stationID<STATIONTICKBOXESMAX)
{
return (pGlobalDialog->StationEnabled(stationID));//m_microTickState==1);
}
return TRUE;
} // StationIsEnabled
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -