⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modethcommsprocessor.cpp

📁 mod_RSsim
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      WORD startCol,endCol;         // col #
   
         endTable = MOSCADTABLENUMBER(endRegister); // MOSCAD specify register # on the wire for the formula
         endCol = MOSCADCOLNUMBER(endRegister);
         startTable = MOSCADTABLENUMBER(startRegister);
         startCol = MOSCADCOLNUMBER(startRegister);
         // test that this request does not bridge 2 columns.
         // , else we cannot job/request them together.
         if ((endTable != startTable) ||
             (endCol != startCol))
         {
            MBUSError = TRUE;
            MBUSerrorCode = MOD_EXCEPTION_ILLEGALADDR;   // 02
         }
      }
   }

   if (!MBUSError)
   {
      // if we want to disable all writes
      if ((m_disableWrites) &&
          ((modMsg.functionCode == MOD_WRITE_SINGLE_COIL) ||
           (modMsg.functionCode == MOD_WRITE_SINGLEHOLDING) ||
           (modMsg.functionCode == MOD_WRITE_MULTIPLE_COILS) ||
           (modMsg.functionCode == MOD_WRITE_HOLDING) ||
           (modMsg.functionCode == MOD_WRITE_EXTENDED) 
          )
         )
      {
      CString deb;
         MBUSError = TRUE;
         MBUSerrorCode = MOD_EXCEPTION_ILLEGALFUNC;   // 02
         deb.Format("Writting to registers or I/O is disabled!\n");
         OutputDebugString(deb);
         SockDataMessage(deb);
      }
   }
   // do a address+length range check too
   if (!MBUSError)
   {
      if (PLCMemory[requestMemArea].GetSize() < endRegister)
      {
         MBUSError = TRUE;
         MBUSerrorCode = (PLCMemory[requestMemArea].GetSize() < startRegister ?
                             MOD_EXCEPTION_ILLEGALADDR:MOD_EXCEPTION_ILLEGALVALUE);   // 02
      }
   }

   if (MBUSError)
   {
   CString msg;
      msg.Format("Modbus message in error x%02X\n", MBUSerrorCode);
      OutputDebugString(msg);
      SockDataMessage(msg);
   }

   //
   // Request message seems error free, process it.
   //
                        // 1st 3 bytes + any others up to data get 
                        // added in at this time 
   responseModMsg.BuildMessagePreamble(MBUSError,
                                       MBUSerrorCode); 

   // If a write is done then the copy constructor will have done all required for ack
   // else a read must now pack into dataPtr onwards! and calc len etc!

   // A read must now pack into dataPtr onwards! and calc len etc!
   //   writes must update our mem areas accordingly.
   if (!MBUSError)
   {
      // 4. fill in the data portion of telegram
      switch (modMsg.functionCode)
      {
      case MOD_READ_COILS     : // 01 READ
      case MOD_READ_DIGITALS  : // 02 READ
         pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
         if (MAX_MOD_MEMWORDS >= modMsg.address + modMsg.byteCount)
         {
         WORD memValueTemp;
         WORD bitOffset;

//#ifdef _COMMS_DEBUGGING
            deb.Format("Read In/output from %d for %d bits.\n", modMsg.address, modMsg.byteCount);
            OutputDebugString(deb);
            SockDataMessage(deb);
//#endif

            // pack SIM memory: one WORD of sim memory for every BIT in the data.
            // Ie the sim uses one word for each I/O bit in modbus.
            numBytesInReq = modMsg.byteCount/8;
            if (modMsg.byteCount%8)  // if we overflow the byte
               numBytesInReq++;
            for (i=0; i <numBytesInReq;i++)
            {
               // grab the memory now
               memValueTemp = 0;
               for (bitOffset=0;bitOffset<8;bitOffset++)
               {
                  if ((i*8)+bitOffset < modMsg.byteCount)
                     if (PLCMemory[requestMemArea][(modMsg.address)+(i*8)+bitOffset])
                        memValueTemp += (0x01<<bitOffset);
                     // else bit is off
               }
               *(BYTE*)pDataPortion =  (BYTE)memValueTemp;
               pDataPortion +=1;
            }

         }
         else
         {
            // pack the exception code into the message
            responseModMsg.buffer[1] |= 0x80;
            responseModMsg.buffer[2] = 0x02;    // exception code here (could also use 0x03)
         }
         break;

      case MOD_READ_REGISTERS : 
      case MOD_READ_HOLDING   :
      case MOD_READ_EXTENDED  :
         pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
         if (MAX_MOD_MEMWORDS >= modMsg.address + modMsg.byteCount)
         {
            WORD memValueTemp;

//#ifdef _COMMS_DEBUGGING
            deb.Format("Read Register from %d for %d .\n", modMsg.address, modMsg.byteCount);
            OutputDebugString(deb);
            SockDataMessage(deb);
//#endif
            for (i=0; i <modMsg.byteCount;i++)
            {
               // grab the memory now
               memValueTemp = PLCMemory[requestMemArea][(modMsg.address)+i];
               *(WORD*)pDataPortion =  SwapBytes( memValueTemp );
               pDataPortion += 2;
            }
         }
         else
         {
            // pack the exception code into the message
            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);
            SockDataMessage(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);
                        SockDataMessage(deb);
                     }
                     //data gets copied in now
                     if (m_modifyThenRespond)
                        PLCMemory.SetAt(requestMemArea, modMsg.address, (*(WORD*)modMsg.dataPtr?1:0));

                     pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
                     *pDataPortion++ = (PLCMemory[requestMemArea][(modMsg.address)+i] ? 0xFF : 0x00);
                     *pDataPortion++ = 0x00;
                     if (!m_modifyThenRespond)
                        PLCMemory.SetAt(requestMemArea, modMsg.address, (*(WORD*)modMsg.dataPtr?1:0));
                     
                     numRegs = 1;   // repaint 1 item

                     break;
                 case MOD_WRITE_MULTIPLE_COILS  :
                    // unpack into the SIM 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);
                        SockDataMessage(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, modMsg.address+(i*8)+bitOffset, 1);
                              else
                                 PLCMemory.SetAt(requestMemArea, 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);
                        SockDataMessage(deb);
                     }
                     for (i=0;i<numRegs;i++)
                     {
                        PLCMemory.SetAt(requestMemArea, 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;
                        deb.Format("Write single register %d.\n", modMsg.address);
                        OutputDebugString(deb);
                        SockDataMessage(deb);
                     }
                     numRegs = 1;   //repaint 1 register

                     PLCMemory.SetAt(requestMemArea, modMsg.address + i, SwapBytes(*(WORD*)modMsg.dataPtr));
                     modMsg.dataPtr +=2;   // inc pointer by 2 bytes
                     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), 
                                            modMsg.address/(cols), 
                                            (modMsg.address+(numRegs-1))/(cols)
                                           ); // repaint only the needed rows
          }
          break;
  
      } //end switch
   } 
   else
   { // error occurred
      pDataPortion = responseModMsg.dataPtr; // Get offset to fill in data
   }
   
   // THERE IS no CRC, so do not call BuildMessageEnd
   responseModMsg.totalLen = (WORD)((LONG)pDataPortion-(LONG)responseModMsg.buffer);

   // insert the frame info
   //responseModMsg
   memmove(&responseModMsg.buffer[ETH_PREAMBLE_LENGTH], responseModMsg.buffer, responseModMsg.totalLen);
   responseLen = ETH_PREAMBLE_LENGTH + responseModMsg.totalLen; //SwapBytes(*(WORD*)(responseModMsg.preambleLenPtr)) + 6; //hdr;
   memset(responseModMsg.buffer, 0 , ETH_PREAMBLE_LENGTH);
   WORD tn = responseModMsg.GetEthernetTransNum();
   *((WORD*)&responseModMsg.buffer[0]) = tn;
   *((WORD*)&responseModMsg.buffer[4]) = SwapBytes(responseModMsg.totalLen);
   
   // 6. send it back
   m_debuggerStep = 102;
   sprintf(debugStr, "Send %d bytes\n", responseLen);
   OutputDebugString(debugStr);
   //Send(openSocket, responseLen, responseBuffer, debugStr);

   SockStateChanged(SOCKETCURRENTLY_WRITTING);
   Send(openSocket, responseLen, responseModMsg.buffer, debugStr);
   m_debuggerStep = 103;
   // inc counter
   pGlobalDialog->PacketsSentInc();

   return (TRUE);
}

// ----------------------------- LoadRegisters -----------------------------
// load binary dump of the register values from file.
BOOL CMODEthCommsProcessor::LoadRegisters()
{
   BOOL ret = CMOD232CommsProcessor::LoadRegistersIMP();

   if (ret)
      SockDataMessage("Register values loaded OK\n");
   return (ret);
} // LoadRegisters

// ----------------------------- SaveRegisters -----------------------------
// Save binary dump of the register values from file.
BOOL CMODEthCommsProcessor::SaveRegisters()
{
   BOOL ret = CMOD232CommsProcessor::SaveRegistersIMP();

   if (ret)
      SockDataMessage("Register values Saved OK\n");
   return (ret);
} // SaveRegisters

// -------------------------- SetEmulationParameters ------------------------
void CMODEthCommsProcessor::SetEmulationParameters(BOOL moscadChecks, 
                                                BOOL modifyThenRespond, 
                                                BOOL disableWrites)
{
   m_MOSCADchecks = moscadChecks;
   m_modifyThenRespond = modifyThenRespond;
   m_disableWrites = disableWrites;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -