Advertisement
Guest User

PeteModbus

a guest
Nov 30th, 2015
989
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.07 KB | None | 0 0
  1. Rem "PeteModbus 0.4"
  2. ' Simplified implementation with no priority connections (no way to get sender IP) and all processing is immediately done in this task (may cause delays).
  3. ' Consider it a bad idea to attempt any kind of connection multiplexing in this environment.
  4. Include "MODBUS.INC"
  5. Print #.CONNLOG., "=== Start of the Program ==="
  6. Print #.CONNLOG., "T Initializing server sock " + Str$(.SERVER_SOCK_NUMBER.) + "."
  7. SockCreate .SERVER_SOCK_NUMBER.,0
  8. If E1% < 0
  9. *SERVER_SOCK_ERR
  10. .retrydelay. = Min(.retrydelay. + .RETRY_DELAY_INC.,.RETRY_DELAY_MAX.)
  11. Print #.CONNLOG., "E Server sock: " + Str$(E1%) + Chr$(44) + " " + Str$(E2%) + "; wait " + Str$(.retrydelay.) + " s."
  12. Pause Max(.retrydelay.*1000,1)
  13. End
  14. EndIf
  15. SockBind .SERVER_SOCK_NUMBER.,.PORT.
  16. Print #.CONNLOG., "T Server sock bound to port " + Str$(.PORT.) + "."
  17. If E1% < 0 Then *SERVER_SOCK_ERR
  18. .retrydelay. = 0
  19. *MAINLOOP
  20. Print #.CONNLOG.,"T Polling; server: " + Str$(.SERVER_SOCK_NUMBER.) + Chr$(44) + " comm: " + Str$(.COMM_SOCK_NUMBER.) + "."
  21. SockWait .SERVER_SOCK_NUMBER.,.COMM_SOCK_NUMBER.,.SERVER_WAIT_TIMEOUT.
  22. If E1% = -7 Then *LISTEN_TIMEOUT ' No new messages, close the socket.
  23. If E1% < 0 Then *SERVER_SOCK_ERR
  24. Print #.CONNLOG.,"T Opened comm sock."
  25. Print #.COMMLOG.,"M !!! New Modbus connection !!!"
  26. *INNERLOOP
  27. Print #.CONNLOG.,"T Polling comm sock " + Str$(.COMM_SOCK_NUMBER.) + " for MB-header."
  28. SockRecv .COMM_SOCK_NUMBER.,.HDRBUFF.,7,.RECEIVE_TIMEOUT.,.reclen.
  29. If E1% = -7
  30. *LISTEN_TIMEOUT
  31. Print #.CONNLOG.,"T Closing comm sock " + Str$(.COMM_SOCK_NUMBER.) + Chr$(44) + " wait time exceeded."
  32. SockClose .COMM_SOCK_NUMBER.
  33. GoTo *MAINLOOP
  34. EndIf
  35. If E1% < 0
  36. *COMM_SOCK_ERR
  37. Print #.CONNLOG., "E Comm sock " + Str$(.COMM_SOCK_NUMBER.) + Chr$(44) + " err: " + Str$(E1%) + Chr$(44) + Str$(E2%) + "."
  38. SockClose .COMM_SOCK_NUMBER.
  39. End
  40. EndIf
  41. Print #.COMMLOG., "M Reading header."
  42. .fn. = 0
  43. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  44. GetByte .HDRBUFF.,.recbyte1.,0
  45. GetByte .HDRBUFF.,.recbyte2.,1
  46. .tranid. = &H100*.recbyte1. + .recbyte2.
  47. GetByte .HDRBUFF.,.recbyte1.,2
  48. GetByte .HDRBUFF.,.recbyte2.,3
  49. .protid. = &H100*.recbyte1. + .recbyte2.
  50. GetByte .HDRBUFF.,.recbyte1.,4
  51. GetByte .HDRBUFF.,.recbyte2.,5
  52. .meslen. = &H100*.recbyte1. + .recbyte2.
  53. GetByte .HDRBUFF.,.recbyte1.,6
  54. .unitid. = .recbyte1. ' This must be done because socket commands and buffer READ (writes are OK) only operate on global variables.
  55. If .meslen. > .MAX_DATA. Then *ERRORCODE
  56. Print #.COMMLOG.,"M :" + Str$(.tranid.) + ":" + Str$(.protid.) + ":" + Str$(.meslen.) + ":" + Str$(.unitid.) + "."
  57. Print #.CONNLOG.,"T Polling comm sock " + Str$(.COMM_SOCK_NUMBER.) + " for MB-message."
  58. Print #.COMMLOG., "M Reading message body."
  59. SockRecv .COMM_SOCK_NUMBER.,.REQBUFF.,.meslen.-1,.RECEIVE_TIMEOUT.,.reclen.
  60. If E1% < 0 Then *COMM_SOCK_ERR
  61. Print #.COMMLOG., "M Read " + Str$(.reclen.) + " bytes."
  62. If (.reclen. + 1 < .meslen. And .ERR_ON_MESLEN.) Or (.protid. <> .PROTOCOL_ID. And .ERR_ON_PROTID.) Or (.unitid. <> .UNIT_ID. And .ERR_ON_UNITID.) Then *ERRORCODE
  63. Print #.COMMLOG.,"M Header ok."
  64. GetByte .REQBUFF.,.recbyte1.,0
  65. .fn. = .recbyte1.
  66. Print #.COMMLOG.,"M Fn-code is " + Str$(.fn.) + "."
  67. Switch .fn.
  68. Case .COM_READ_COILS.
  69. Print #.COMMLOG., "C Read multiple coils."
  70. GoTo *COM02
  71. Case .COM_READ_DISCRETE_INPUTS.
  72. Print #.COMMLOG., "C Read multiple input bits."
  73. *COM02
  74. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  75. If .meslen. < .MESLENOFFS. + 5 Then *ERRORCODE
  76. GoSub *GET2WORDS
  77. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  78. If .regnum. < 1 Or .regnum. > 2000 Then *ERRORCODE
  79. .hlp2. = .RESBUFFOFFS. + 2
  80. .errcode.=.ERR_NO_ERROR.
  81. .hlp1.=.regstart.
  82. .bytecount. = 0
  83. While .hlp1. + 8 <= .regstart.+.regnum.
  84. .mbaddr. = .hlp1.
  85. .bytelim. = 8
  86. GoSub *GET_MB_BYTE
  87. SetByte .RESBUFF.,.byteval.,.hlp2.
  88. .hlp1.=.hlp1. + 8.
  89. .hlp2.=.hlp2. + 1
  90. .bytecount. = .bytecount. + 1
  91. EndW
  92. .bytelim. = .regnum. Mod 8
  93. .mbaddr. = .hlp1.
  94. GoSub *GET_MB_BYTE
  95. SetByte .RESBUFF.,.byteval.,.hlp2. ' Last incomplete byte, wont cause harm even if mod is 0
  96. If .errcode. Then *ERRORCODE
  97. .bytecount. = .bytecount. + Min(.bytelim.,1)
  98. .meslen. = .bytecount. + 3
  99. SetByte .RESBUFF.,.bytecount.,.RESBUFFOFFS. + 1 ' Byte count
  100. GoSub *MKFNHEADER
  101. GoTo *SENDRES
  102. Case .COM_READ_HOLDING_REGISTERS.
  103. Print #.COMMLOG., "C Read multiple holding registers."
  104. GoTo *COM04
  105. Case .COM_READ_INPUT_REGISTERS.
  106. Print #.COMMLOG., "C Read multiple input registers."
  107. *COM04
  108. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  109. If .meslen. < .MESLENOFFS. + 5 Then *ERRORCODE
  110. GoSub *GET2WORDS
  111. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  112. If .regnum. < 0 Or .regnum. > 125 Then *ERRORCODE
  113. .errcode.= .ERR_NO_ERROR.
  114. .hlp2. = .RESBUFFOFFS. + 2
  115. .hlp1. = .regstart.
  116. .bytecount. = 0;
  117. While .hlp1. < .regstart.+.regnum.
  118. .mbaddr. = .hlp1.
  119. GoSub *GET_MB_WORD
  120. SetByte .RESBUFF.,.wordval./&H100,.hlp2.
  121. SetByte .RESBUFF.,.wordval.,.hlp2.+1.
  122. .hlp1.=.hlp1.+1
  123. .hlp2.=.hlp2.+2
  124. .bytecount. = .bytecount. + 2;
  125. EndW
  126. If .errcode. Then *ERRORCODE
  127. .meslen.= .bytecount. + 3
  128. SetByte .RESBUFF.,.bytecount.,.RESBUFFOFFS. + 1 ' Byte count
  129. GoSub *MKFNHEADER
  130. GoTo *SENDRES
  131. Case .COM_WRITE_SINGLE_COIL.
  132. Print #.COMMLOG., "C Set single coil."
  133. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  134. If .meslen. < .MESLENOFFS. + 5 Then *ERRORCODE
  135. GoSub *GET2WORDS
  136. If .outval. <> &HFF00 And .outval. <> &H0000 Then *ERRORCODE
  137. .bitaddr. = .outaddr.
  138. .bitval. = .outval.
  139. GoSub *SET_MB_BIT
  140. If .errcode. Then *ERRORCODE
  141. GoSub *MK2WORDHEADER
  142. GoTo *SENDRES
  143. Case .COM_WRITE_SINGLE_REGISTER.
  144. Print #.COMMLOG., "Com: Write single holding reg."
  145. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  146. If .meslen. < .MESLENOFFS. + 5 Then *ERRORCODE
  147. GoSub *GET2WORDS
  148. .errcode. = .ERR_NO_ERROR.
  149. .mbaddr. = .outaddr.
  150. .wordval. = .outval.
  151. GoSub *SET_MB_WORD
  152. If .errcode. Then *ERRORCODE
  153. GoSub *MK2WORDHEADER
  154. GoTo *SENDRES
  155. Case .COM_WRITE_MULTIPLE_COILS.
  156. Print #.COMMLOG., "C Set multiple coils."
  157. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  158. If .meslen. < .MESLENOFFS. + 6 Then *ERRORCODE
  159. GoSub *GET2WORDS
  160. GetByte .REQBUFF.,.bytecount.,.MESBUFFOFFS. + 5
  161. If .regnum. < 1 Or .regnum. > 2000 Then *ERRORCODE
  162. .hlp2. = .MESBUFFOFFS. + 6
  163. .errcode. = .ERR_NO_ERROR.
  164. .hlp1.=.regstart.
  165. .bitcount. = 0
  166. While .hlp1. + 8 <= .regstart. + .regnum.
  167. GetByte .REQBUFF.,.recbyte1.,.hlp2.
  168. .mbaddr. = .hlp1.
  169. .byteval. = .recbyte1.
  170. .bytelim. = 8
  171. GoSub *SET_MB_BYTE
  172. .hlp1.=.hlp1. + 8
  173. .hlp2.=.hlp2. + 1
  174. .bitcount. = .bitcount. + 8
  175. EndW
  176. GetByte .REQBUFF.,.recbyte1.,.hlp2.
  177. .mbaddr. = .hlp1.
  178. .byteval. = .recbyte1.
  179. .bytelim. = .regnum. Mod 8
  180. GoSub *SET_MB_BYTE
  181. If .errcode. Then *ERRORCODE
  182. .meslen.= .RESLENOFFS. + 5
  183. .1stword. = .regstart.
  184. .2ndword. = .bitcount. + .bytelim.
  185. GoSub *MK2WORDHEADER
  186. GoTo *SENDRES
  187. Case .COM_WRITE_MULTIPLE_REGISTERS.
  188. Print #.COMMLOG., "C Write multiple holding regs."
  189. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  190. If .meslen. < .MESLENOFFS. + 5 Then *ERRORCODE
  191. GoSub *GET2WORDS
  192. GetByte .REQBUFF.,.bytecount.,.MESBUFFOFFS. + 5
  193. If .regnum. < 0 Or .regnum. > 123 Then *ERRORCODE
  194. .hlp2.= .MESBUFFOFFS. + 6
  195. .hlp1.=.regstart. To .regstart.+.regnum.
  196. .errcode. = 0
  197. While .hlp1. < .regstart.+.regnum.
  198. GetByte .REQBUFF.,.recbyte1.,.hlp2.
  199. GetByte .REQBUFF.,.recbyte2.,.hlp2.+1.
  200. .mbaddr. = .hlp1.
  201. .wordval. = .recbyte1.*&H100 + .recbyte2.
  202. GoSub *SET_MB_WORD
  203. .hlp1. = .hlp1. + 1
  204. .hlp2. = .hlp2. + 2
  205. EndW
  206. If .errcode. Then *ERRORCODE
  207. .meslen.= .RESLENOFFS. + 5
  208. GoSub *MK2WORDHEADER
  209. GoTo *SENDRES
  210. Case .COM_REPORT_SLAVE_ID.
  211. Print #.COMMLOG., "C Report slave ID."
  212. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  213. If .meslen. < .MESLENOFFS. Then *ERRORCODE
  214. SetByte .RESBUFF.,.UNIT_ID., .RESBUFFOFFS. + 2
  215. SetByte .RESBUFF.,&HFF, .RESBUFFOFFS. + 3
  216. .resstr. = "PeteModbus by Kauppisen ropottivirma ltd."
  217. SetStr .RESBUFF.,.resstr.,.RESBUFFOFFS. + 4,len(.resstr.)
  218. .meslen.= .RESLENOFFS. + 4 + len(.resstr.)
  219. SetByte .RESBUFF.,.meslen.-3, .RESBUFFOFFS. + 1
  220. GoSub *MKFNHEADER
  221. GoTo *SENDRES
  222. Case .COM_READ_FILE_RECORD.
  223. Print #.COMMLOG., "C Read file."
  224. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  225. If .meslen. < .MESLENOFFS. + 9 Then *ERRORCODE
  226. GetByte .REQBUFF., .bytecount. , .MESBUFFOFFS. + 1
  227. If .bytecount. > &HF5 Then *ERRORCODE
  228. .hlp1. = .MESBUFFOFFS. + 2
  229. .hlp2. = .bytecount.
  230. .hlp3. = .RESBUFFOFFS. + 2
  231. While .hlp2. >= 7
  232. GetByte .REQBUFF., .reftype. , .hlp1.
  233. GetByte .REQBUFF.,.recbyte1., .hlp1.+1
  234. GetByte .REQBUFF.,.recbyte2., .hlp1.+2
  235. .filenum. = &H100*.recbyte1. + .recbyte2.
  236. GetByte .REQBUFF.,.recbyte1., .hlp1.+3
  237. GetByte .REQBUFF.,.recbyte2., .hlp1.+4
  238. .recordnum. = &H100*.recbyte1. + .recbyte2.
  239. GetByte .REQBUFF.,.recbyte1., .hlp1.+5
  240. GetByte .REQBUFF.,.recbyte2., .hlp1.+6
  241. .recordlen. = &H100*.recbyte1. + .recbyte2.
  242. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  243. If .filenum.<1 Or .filenum.>50 Or .recordnum.<0 Or (.recordnum.>200 And Not .recordnum.=&HFFFF) Or .recordlen.<0 Or (.recordlen.+.recordnum.>200 And Not .recordlen.=&HFFFF) Or .reftype.<>&H06
  244. GoTo *ERRORCODE
  245. EndIf
  246. If .recordlen. = &HFFFF And .recordnum. = &HFFFF
  247. .resstr. = V$[.filenum.]
  248. .recbyte1. = Len(.resstr.)
  249. Else
  250. .resstr. = Mid$(V$[.filenum.],.recordnum.,.recordlen.)
  251. .recbyte1. = Len(.resstr.)
  252. While .recbyte1. < .recordlen.
  253. .resstr. = .resstr. + Chr$(.FILLINCHAR.)
  254. .recbyte1. = .recbyte1. + 1
  255. EndW
  256. EndIf
  257. SetByte .RESBUFF., .recbyte1.*2 + 1, .hlp3.
  258. SetByte .RESBUFF., &H06 , .hlp3. + 1
  259. .recbyte2. = 1
  260. .hlp3. = .hlp3. + 2
  261. While .recbyte2. <= .recbyte1.
  262. .wordval. = Ord(Mid$(.resstr.,.recbyte2.,1))
  263. SetByte .RESBUFF., .wordval. / &H100 , .hlp3.
  264. SetByte .RESBUFF., .wordval. , .hlp3. +1
  265. .hlp3. = .hlp3. + 2
  266. .recbyte2. = .recbyte2. + 1
  267. EndW
  268. .hlp1. = .hlp1. + 7
  269. .hlp2. = .hlp2. - 7
  270. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  271. If .hlp3. > 253 Then *ERRORCODE
  272. EndW
  273. SetByte .RESBUFF., .hlp3. - .RESBUFFOFFS. - 2, .RESBUFFOFFS.+1
  274. .meslen. = .hlp3. - .RESBUFFOFFS. + 1
  275. GoSub *MKFNHEADER
  276. GoTo *SENDRES
  277. Case .COM_WRITE_FILE_RECORD.
  278. Print #.COMMLOG., "C Write file."
  279. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  280. If .meslen. < .MESLENOFFS. + 9 Then *ERRORCODE
  281. GetByte .REQBUFF., .bytecount., .MESBUFFOFFS. + 1
  282. .hlp1. = .MESBUFFOFFS. + 2
  283. .hlp2. = .bytecount.
  284. .hlp3. = .RESBUFFOFFS. + 2
  285. .bytecount. = 0
  286. While .hlp2. >= 7
  287. GetByte .REQBUFF., .reftype. , .hlp1.
  288. GetByte .REQBUFF., .recbyte1., .hlp1.+1
  289. GetByte .REQBUFF., .recbyte2., .hlp1.+2
  290. .filenum. = &H100*.recbyte1. + .recbyte2.
  291. GetByte .REQBUFF., .recbyte1., .hlp1.+3
  292. GetByte .REQBUFF., .recbyte2., .hlp1.+4
  293. .recordnum. = &H100*.recbyte1. + .recbyte2.
  294. GetByte .REQBUFF., .recbyte1., .hlp1.+5
  295. GetByte .REQBUFF., .recbyte2., .hlp1.+6
  296. .recordlen. = &H100*.recbyte1. + .recbyte2.
  297. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  298. If .filenum.<1 Or .filenum.>50 Or ((.recordnum.<0 Or .recordnum.>200 Or .recordnum.+.recordlen.>200) And (.recordnum. <> &HFFFF)) Or .reftype.<>&H06 Then *ERRORCODE
  299. SetByte .RESBUFF., .reftype. , .hlp3.
  300. SetByte .RESBUFF., .filenum. / &H100 , .hlp3.+1
  301. SetByte .RESBUFF., .filenum. , .hlp3.+2
  302. SetByte .RESBUFF., .recordnum. / &H100 , .hlp3.+3
  303. SetByte .RESBUFF., .recordnum. , .hlp3.+4
  304. SetByte .RESBUFF., .recordlen. / &H100 , .hlp3.+5
  305. SetByte .RESBUFF., .recordlen. , .hlp3.+6
  306. .hlp1. = .hlp1. + 7
  307. .hlp3. = .hlp3. + 7
  308. .bytecount. = .bytecount. + 7
  309. .resstr. = ""
  310. if .recordnum. <> &HFFFF
  311. .uhlp1. = 0
  312. .uhlp2. = Len(V$[.filenum.])
  313. While .uhlp1. < .uhlp2. And .uhlp1. < .recordnum.
  314. .resstr. = .resstr. + Mid$(V$[.filenum.],.uhlp1.,1)
  315. .uhlp1. = .uhlp1. + 1
  316. EndW
  317. While .uhlp1. < .recordnum.
  318. .resstr. = .resstr. + Chr$(.FILLINCHAR.)
  319. .uhlp1. = .uhlp1. + 1
  320. EndW
  321. EndIf
  322. .uhlp2. = 0
  323. While .uhlp2. < .recordlen.
  324. GetByte .REQBUFF., .recbyte1., .hlp1.
  325. GetByte .REQBUFF., .recbyte2., .hlp1.+1
  326. SetByte .RESBUFF., .recbyte1., .hlp3.
  327. SetByte .RESBUFF., .recbyte2., .hlp3.+1
  328. .resstr. = .resstr. + Chr$(.recbyte2.)
  329. .hlp1. = .hlp1. + 2
  330. .hlp3. = .hlp3. + 2
  331. .uhlp1. = .uhlp1. + 1
  332. .uhlp2. = .uhlp2. + 1
  333. .bytecount. = .bytecount. + 2
  334. EndW
  335. if .recordnum. <> &HFFFF
  336. .uhlp2. = Len(V$[.filenum.])
  337. While .uhlp1. < .uhlp2.
  338. .resstr. = .resstr. + Mid$(V$[.filenum.],.uhlp1.,1)
  339. .uhlp1. = .uhlp1. + 1
  340. EndW
  341. EndIf
  342. V$[.filenum.] = .resstr.
  343. .hlp2. = .hlp2. - 7 - .recordlen.*2
  344. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  345. If .hlp3. > 253 Then *ERRORCODE
  346. EndW
  347. SetByte .RESBUFF., .bytecount. , .RESBUFFOFFS.+1
  348. .meslen. = .hlp3. - .RESBUFFOFFS. + 1
  349. GoSub *MKFNHEADER
  350. GoTo *SENDRES
  351. Case .COM_MASK_WRITE_REGISTER.
  352. Print #.COMMLOG., "C Mask write multiple holding regs."
  353. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  354. If .meslen. < .MESLENOFFS. + 7 Then *ERRORCODE
  355. GoSub *GET3WORDS
  356. If .regnum. > 125 Or .regnum. < 0 Then *ERRORCODE
  357. .errcode. = .ERR_NO_ERROR.
  358. .mbaddr. = .regstart.
  359. GoSub *GET_MB_WORD
  360. If .errcode. Then *ERRORCODE
  361. .mbaddr. = .regstart.
  362. .wordval. = (.wordval. And .andmask.) Or (.ormask. And (Not .andmask.))
  363. GoSub *SET_MB_WORD
  364. If .errcode. Then *ERRORCODE
  365. GoSub *MK3WORDHEADER
  366. GoTo *SENDRES
  367. Case .COM_READ_WRITE_MULTIPLE_REGISTERS.
  368. Print #.COMMLOG., "C Read write multiple holding regs."
  369. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  370. If .meslen. < .MESLENOFFS. + 10 Then *ERRORCODE
  371. GoSub *GET4WORDS
  372. GetByte .REQBUFF.,.bytecount.,.MESBUFFOFFS.+ 8
  373. If .readlen. > 32 Or .writelen. > 32 Or .readlen. < 1 Or .writelen. < 1 Then *ERRORCODE
  374. .errcode. = .ERR_NO_ERROR.
  375. .hlp2.= .MESBUFFOFFS. + 10
  376. .hlp1.=.writestart.
  377. While .hlp1. < .writestart.+.writelen.
  378. GetByte .REQBUFF., .recbyte1. ,.hlp2.
  379. GetByte .REQBUFF., .recbyte2. ,.hlp2.+1
  380. .mbaddr. = .hlp1.
  381. .wordval. = .recbyte1.*&H100+.recbyte2.
  382. GoSub *SET_MB_WORD
  383. If .errcode. Then *ERRORCODE
  384. .hlp1. = .hlp1. + 1
  385. .hlp2. = .hlp2. + 2
  386. EndW
  387. .hlp2.= .RESBUFFOFFS. + 2
  388. .hlp1.=.readstart.
  389. .bytecount. = 0
  390. While .hlp1. < .readstart.+.readlen.
  391. .mbaddr. = .hlp1.
  392. GoSub *GET_MB_WORD
  393. If .errcode. Then *ERRORCODE
  394. SetByte .RESBUFF.,.wordval./&H100,.hlp2.
  395. SetByte .RESBUFF.,.wordval. And &HFF,.hlp2.+1
  396. .hlp1. = .hlp1. + 1
  397. .hlp2. = .hlp2. + 2
  398. .bytecount. = .bytecount. + 2
  399. EndW
  400. .meslen. = .bytecount. + 3
  401. SetByte .RESBUFF.,.bytecount., .RESBUFFOFFS. + 1
  402. GoSub *MKFNHEADER
  403. GoTo *SENDRES
  404. Case .COM_READ_FIFO_QUEUE.
  405. Print #.COMMLOG., "C Read fifo."
  406. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  407. If .meslen. < .MESLENOFFS. + 3 Then *ERRORCODE
  408. GoSub *GET1WORD
  409. .mbaddr. = .fifoptr.
  410. GoSub *GET_MB_WORD
  411. If .wordval. < 0 Or .wordval. > 31 Then *ERRORCODE
  412. .hlp3. = .wordval.
  413. .hlp2. = .RESBUFFOFFS. + 5
  414. .hlp1. = .fifoptr.+1
  415. .bytecount. = 0
  416. .errcode. = .ERR_NO_ERROR.
  417. While .hlp1. <= .fifoptr. + .hlp3.
  418. .mbaddr. = .hlp1.
  419. GoSub *GET_MB_WORD
  420. SetByte .RESBUFF., .wordval./&H100, .hlp2.
  421. SetByte .RESBUFF., .wordval., .hlp2.+1
  422. .hlp1. = .hlp1. + 1
  423. .hlp2. = .hlp2. + 2
  424. .bytecount. = .bytecount. + 2
  425. EndW
  426. .1stword. = .bytecount. + 2
  427. .2ndword. = .hlp3.
  428. .meslen. = .bytecount. + 6
  429. GoSub *MK2WORDHEADER
  430. GoTo *SENDRES
  431. Case .COM_READ_DEVICE_IDENTIFICATION.
  432. Case .COM_READ_DEVICE_IDENTIFICATION_ALT.
  433. Print #.COMMLOG., "C Read device identification."
  434. .errcode. = .ERR_ILLEGAL_DATA_VALUE.
  435. If .meslen. < .MESLENOFFS. + 4 Then *ERRORCODE
  436. GetByte .REQBUFF.,.meitype.,1
  437. GetByte .REQBUFF.,.deviceid.,2
  438. GetByte .REQBUFF.,.objectid.,3
  439. If .meitype. <> &H0E Or (.deviceid. <> 1 And .deviceid. <> 4) Then *ERRORCODE
  440. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  441. If .objectid. < 0 Or .objectid. > 2 Then *ERRORCODE
  442. SetByte .RESBUFF.,&H0E, .RESBUFFOFFS. + 1 ' MEI type
  443. SetByte .RESBUFF.,.deviceid., .RESBUFFOFFS. + 2 ' Device ID
  444. SetByte .RESBUFF.,&H81, .RESBUFFOFFS. + 3 ' Conformity level
  445. SetByte .RESBUFF.,&H00, .RESBUFFOFFS. + 4 ' More follows
  446. SetByte .RESBUFF.,&H00, .RESBUFFOFFS. + 5 ' Next obj
  447. .hlp1. = 7
  448. If .deviceid. = 1
  449. SetByte .RESBUFF.,3,.RESBUFFOFFS. + 6 ' Number of obj
  450. Else
  451. SetByte .RESBUFF.,1,.RESBUFFOFFS. + 6 ' Number of obj
  452. On .objectid. Goto *MEIPROD, *MEIPRODNUM
  453. EndIf
  454. SetByte .RESBUFF.,&H00,.RESBUFFOFFS. + .hlp1. ' Object ID
  455. .resstr. = "Kauppisen ropottivirma ltd."
  456. SetByte .RESBUFF.,Len(.resstr.),.RESBUFFOFFS. + 1 + .hlp1. ' Object Len
  457. SetStr .RESBUFF.,.resstr.,.RESBUFFOFFS. + 2 + .hlp1. ,Len(.resstr.) ' Object Val
  458. .hlp1. = .hlp1. + 2 + Len(.resstr.)
  459. If .deviceid. = 4 Then *MEIDONE
  460. *MEIPROD
  461. SetByte .RESBUFF.,&H01,.RESBUFFOFFS. + .hlp1. ' Object ID
  462. .resstr. = "PeteModbus"
  463. SetByte .RESBUFF.,Len(.resstr.),.RESBUFFOFFS. + 1 + .hlp1. ' Object Len
  464. SetStr .RESBUFF.,.resstr.,.RESBUFFOFFS. + 2 + .hlp1.,Len(.resstr.) ' Object Val
  465. .hlp1. = .hlp1. + 2 + Len(.resstr.)
  466. If .deviceid. = 4 Then *MEIDONE
  467. *MEIPRODNUM
  468. SetByte .RESBUFF.,&H02,.RESBUFFOFFS. + .hlp1. ' Object ID
  469. .resstr. = "1.0"
  470. SetByte .RESBUFF.,Len(.resstr.),.RESBUFFOFFS. + 1 + .hlp1. ' Object Len
  471. SetStr .RESBUFF.,.resstr.,.RESBUFFOFFS. + 2 + .hlp1.,Len(.resstr.) ' Object Val
  472. .hlp1. = .hlp1. + 2 + Len(.resstr.)
  473. *MEIDONE
  474. .meslen. = .RESBUFFOFFS. + .hlp1. - 6
  475. GoSub *MKFNHEADER
  476. GoTo *SENDRES
  477. Case ' Unsupported function code
  478. .errcode. = .ERR_ILLEGAL_FUNCTION.
  479. *ERRORCODE
  480. Print #.COMMLOG.,"E Fn " + Str$(.fn.) + " terminated with err " + Str$(.errcode.) + "."
  481. .fn. = .fn. + &H80
  482. .meslen. = .RESLENOFFS. + 2
  483. SetByte .RESBUFF., .errcode., 8
  484. GoSub *MKFNHEADER
  485. *SENDRES
  486. Print #.CONNLOG.,"T Sending MB-response with sock " + Str$(.COMM_SOCK_NUMBER.) + "."
  487. SockSend .COMM_SOCK_NUMBER.,.RESBUFF.,.meslen. + 6,.SEND_TIMEOUT.,.reclen.
  488. If .meslen. +6 < .reclen. Or E1% < 0 Then *LISTEN_TIMEOUT
  489. Print #.COMMLOG.,"M Reply sent."
  490. EndS
  491. GoTo *INNERLOOP
  492. *MK4WORDHEADER
  493. SetByte .RESBUFF.,.4thword.,15
  494. SetByte .RESBUFF.,.4thword./&H100,14
  495. *MK3WORDHEADER
  496. SetByte .RESBUFF.,.3rdword.,13
  497. SetByte .RESBUFF.,.3rdword./&H100,12
  498. *MK2WORDHEADER
  499. SetByte .RESBUFF.,.2ndword.,11
  500. SetByte .RESBUFF.,.2ndword./&H100,10
  501. *MK1WORDHEADER
  502. SetByte .RESBUFF.,.1stword.,9
  503. SetByte .RESBUFF.,.1stword./&H100,8
  504. *MKFNHEADER
  505. SetByte .RESBUFF.,.fn.,7
  506. *MKHEADER
  507. SetByte .RESBUFF.,.unitid.,6
  508. SetByte .RESBUFF.,.meslen.,5
  509. SetByte .RESBUFF.,.meslen./&H100,4
  510. SetByte .RESBUFF.,.protid.,3
  511. SetByte .RESBUFF.,.protid./&H100,2
  512. SetByte .RESBUFF.,.tranid.,1
  513. SetByte .RESBUFF.,.tranid./&H100,0
  514. Print #.COMMLOG., "M Reply header:" + Str$(.tranid.) + ":" + Str$(.protid.) + ":" + Str$(.meslen.) + ";" + Str$(.unitid.) + "."
  515. Return
  516. *GET4WORDS
  517. GetByte .REQBUFF.,.recbyte2.,8
  518. GetByte .REQBUFF.,.recbyte1.,7
  519. .4thword. = &H100*.recbyte1. + .recbyte2.
  520. *GET3WORDS
  521. GetByte .REQBUFF.,.recbyte2.,6
  522. GetByte .REQBUFF.,.recbyte1.,5
  523. .3rdword. = &H100*.recbyte1. + .recbyte2.
  524. *GET2WORDS
  525. GetByte .REQBUFF.,.recbyte2.,4
  526. GetByte .REQBUFF.,.recbyte1.,3
  527. .2ndword. = &H100*.recbyte1. + .recbyte2.
  528. *GET1WORD
  529. GetByte .REQBUFF.,.recbyte2.,2
  530. GetByte .REQBUFF.,.recbyte1.,1
  531. .1stword. = &H100*.recbyte1. + .recbyte2.
  532. Return
  533. *GET_MB_WORD ' In: .mbaddr., Out: .wordval.
  534. .trueaddr. = .mbaddr. + .MB_ADDR_OFFS.
  535. If .trueaddr. >= .COILBANK_ST. And .trueaddr. <= .COILBANK_MAX.
  536. .trueaddr. = .trueaddr. - .COILBANK.
  537. .wordval. = 0
  538. For .uhlp1.=0 To 15
  539. .wordval. = .wordval. + O[.trueaddr. + .uhlp1.]*(2^.uhlp1.)
  540. Next
  541. ElseIf .trueaddr. >= .INBANK_ST. And .trueaddr. <= .INBANK_MAX.
  542. .trueaddr. = .trueaddr. - .INBANK.
  543. .wordval. = 0
  544. For .uhlp1.=0 To 15
  545. .wordval. = .wordval. + I[.trueaddr. + .uhlp1.]*(2^.uhlp1.)
  546. Next
  547. ElseIf .trueaddr. >= .MEMBANK_ST. And .trueaddr. <= .MEMBANK_MAX.
  548. .trueaddr. = .trueaddr. - .MEMBANK.
  549. .wordval. = V%[.trueaddr.] And &HFFFF
  550. ElseIf .trueaddr. >= .MEMRBANK_ST. And .trueaddr. <= .MEMRBANK_MAX.
  551. .trueaddr. = .trueaddr. - .MEMRBANK.
  552. .real.=V![(.trueaddr.+1)/2]
  553. If (.trueaddr. Mod 2) = .NUXI. 'Odd
  554. GoSub *GETLOWREAL
  555. Else 'Even
  556. GoSub *GETHIGHREAL
  557. EndIf
  558. .wordval. = .realint.
  559. ElseIf .trueaddr. >= .MEMLBANK_ST. And .trueaddr. <= .MEMLBANK_MAX.
  560. .trueaddr. = .trueaddr. - .MEMLBANK.
  561. If (.trueaddr. Mod 2) = .NUXI. 'Odd
  562. .wordval. = V%[(.trueaddr.+1)/2] And &HFFFF
  563. Else 'Even
  564. .wordval. = V%[(.trueaddr.+1)/2] / &H10000
  565. EndIf
  566. Else ' Out of bounds
  567. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  568. Print #.DATALOG., "E WORD " + Str$(.mbaddr.) + " addr out of bounds."
  569. EndIf
  570. Print #.DATALOG., "A Got WORD " + Str$(.mbaddr.) + ": " + Str$(.wordval.) + "."
  571. Return
  572. *SET_MB_WORD ' In: .mbaddr., .wordval.
  573. .trueaddr. = .mbaddr. + .MB_ADDR_OFFS.
  574. If .trueaddr. >= .COILBANK_ST. And .trueaddr. <= .COILBANK_MAX.
  575. .trueaddr. = .trueaddr. - .COILBANK.
  576. For .uhlp1.=.trueaddr. To .trueaddr. + 15
  577. If .wordval. And 2^.uhlp1.
  578. Set O[.uhlp1.]
  579. Else
  580. Reset O[.uhlp1.]
  581. EndIf
  582. Next
  583. ElseIf .trueaddr. >= .MEMBANK_ST. And .trueaddr. <= .MEMBANK_MAX.
  584. .trueaddr. = .trueaddr. - .MEMBANK.
  585. V%[.trueaddr.] = .wordval.
  586. ElseIf .trueaddr. >= .MEMRBANK_ST. And .trueaddr. <= .MEMRBANK_MAX.
  587. .trueaddr. = .trueaddr. - .MEMRBANK.
  588. .real. = V![(.trueaddr.+1)/2]
  589. .realint. = .wordval.
  590. If (.trueaddr. Mod 2) = .NUXI. 'Odd
  591. GoSub *SETLOWREAL
  592. Else 'Even
  593. GoSub *SETHIGHREAL
  594. EndIf
  595. V![(.trueaddr.+1)/2] = .real.
  596. ElseIf .trueaddr. >= .MEMLBANK_ST. And .trueaddr. <= .MEMLBANK_MAX.
  597. .trueaddr. = .trueaddr. - .MEMLBANK.
  598. If (.trueaddr. Mod 2) = .NUXI. 'Odd
  599. V%[(.trueaddr.+1)/2] = (V%[(.trueaddr.+1)/2] And &HFFFF0000) + .wordval.
  600. Else 'Even
  601. V%[(.trueaddr.+1)/2] = (V%[(.trueaddr.+1)/2] And &H0000FFFF) + .wordval.*&H10000
  602. EndIf
  603. Else ' Out of bounds
  604. Print #.DATALOG., "E WORD " + .mbaddr. + " addr out of bounds."
  605. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  606. EndIf
  607. Print #.DATALOG., "A Set WORD " + Str$(.mbaddr.) + "=" + Str$(.wordval.) + "."
  608. Return
  609. *GET_MB_BYTE ' In: .mbaddr., .bytelim., Out: .byteval.
  610. Print #.DATALOG., "A Getting BYTE " + Str$(.mbaddr.) + Chr$(44) + " " + Str$(.bytelim.) + " bits."
  611. .uhlp2. = 0
  612. .uhlp1. = 0
  613. While .uhlp1. < .bytelim.
  614. .bitaddr. = .uhlp1. + .mbaddr.
  615. GoSub *GET_MB_BIT
  616. .uhlp2. = .uhlp2. + 2^.uhlp1.*.bitval.
  617. .uhlp1. = .uhlp1. + 1
  618. EndW
  619. .byteval. = .uhlp2.
  620. Return
  621. *SET_MB_BYTE ' In: .mbaddr., .byteval., .bytelim.
  622. Print #.DATALOG., "A Setting BYTE " + Str$(.mbaddr.) + Chr$(44) + " " + Str$(.bytelim.) + " bits."
  623. .uhlp1. = 0
  624. While .uhlp1. < .bytelim.
  625. .bitaddr.= .mbaddr. + .uhlp1.
  626. .bitval.= .byteval. And 2^.uhlp1.
  627. GoSub *SET_MB_BIT
  628. .uhlp1.=.uhlp1.+1
  629. EndW
  630. Return
  631. *GET_MB_BIT ' In: .bitaddr., Out: .bitval.
  632. .bitaddr. = .bitaddr. + .MB_ADDR_OFFS.
  633. If .COILBANK_BST. >= 1 And .bitaddr. <= .COILBANK_BMAX.
  634. .bitaddr. = .bitaddr. - .COILBANK.
  635. .bitval. = O[.bitaddr.]
  636. ElseIf .INBANK_BST. >= 1 And .bitaddr. <= .INBANK_BMAX.
  637. .bitaddr. = .bitaddr. - .INBANK.
  638. .bitval. = I[.bitaddr.]
  639. ElseIf .bitaddr. >= .MEMBANK_BST. And .bitaddr. <= .MEMBANK_BMAX.
  640. .bitaddr. = .bitaddr. - .MEMBANK.
  641. .bitval. =(V%[(.bitaddr.-1) / 16 + 1] And (2^((.bitaddr.-1) Mod 16))) <> 0
  642. ElseIf .bitaddr. >= .MEMRBANK_BST. And .bitaddr. <= .MEMRBANK_BMAX.
  643. .bitaddr. = .bitaddr. - .MEMRBANK.
  644. .real.=V![(.bitaddr.-1) / 32 + 1]
  645. If (((.bitaddr.-1) / 16) Mod 2) = .NUXI. 'Odd
  646. GoSub *GETLOWREAL
  647. .bitval. =(.realint. And 2^((.bitaddr.-1) Mod 16)) <> 0
  648. Else 'Even
  649. GoSub *GETHIGHREAL
  650. .bitval. =(.realint. And 2^((.bitaddr.-1) Mod 16)) <> 0
  651. EndIf
  652. ElseIf .bitaddr. >= .MEMLBANK_BST. And .bitaddr. <= .MEMLBANK_BMAX.
  653. .bitaddr. = .bitaddr. - .MEMLBANK.
  654. If (((.bitaddr.-1) / 16) Mod 2) = .NUXI. 'Odd
  655. .bitval. =(V%[(.bitaddr.-1) / 32 + 1] And 2^((.bitaddr.-1) Mod 16)) <> 0
  656. Else 'Even
  657. .bitval. =(V%[(.bitaddr.-1) / 32 + 1] / &H10000 And 2^((.bitaddr.-1) Mod 16)) <> 0
  658. EndIf
  659. Else ' Out of bounds
  660. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  661. Print #.DATALOG., "BIT " + Str$(.bitaddr.) + " out of bounds."
  662. Return
  663. EndIf
  664. Print #.DATALOG., "A Got BIT " + Str$(.bitaddr.) + ": " + Str$(.bitval.) + "."
  665. Return
  666. *SET_MB_BIT ' In: .bitaddr., .bitval.
  667. If .bitval.
  668. .bitaddr. = .bitaddr. + .MB_ADDR_OFFS.
  669. If .bitaddr. >= .COILBANK_BST. And .bitaddr. <= .COILBANK_BMAX.
  670. .bitaddr. = .bitaddr. - .COILBANK.
  671. Set O[.bitaddr.]
  672. ElseIf .bitaddr. >= .MEMBANK_BST. And .bitaddr. <= .MEMBANK_BMAX.
  673. .bitaddr. = .bitaddr. - .MEMBANK.
  674. V%[(.bitaddr.-1) / 16 + 1] = V%[(.bitaddr.-1) / 16 + 1] Or 2^((.bitaddr.-1) Mod 16)
  675. ElseIf .bitaddr. >= .MEMRBANK_BST. And .bitaddr. <= .MEMRBANK_BMAX.
  676. .bitaddr. = .bitaddr. - .MEMRBANK.
  677. .real.=V![(.bitaddr.-1)/32 + 1]
  678. If (((.bitaddr.-1) / 16 + 1) Mod 2) = .NUXI. 'Odd
  679. GoSub *GETLOWREAL
  680. .realint. = .realint. Or 2^((.bitaddr.-1) Mod 16)
  681. GoSub *SETLOWREAL
  682. Else 'Even
  683. GoSub *GETHIGHREAL
  684. .realint. = .realint. Or 2^((.bitaddr.-1) Mod 16)
  685. GoSub *SETHIGHREAL
  686. EndIf
  687. V![(.bitaddr.-1)/32 + 1]=.real.
  688. ElseIf .bitaddr. >= .MEMLBANK_BST. And .bitaddr. <= .MEMLBANK_BMAX.
  689. .bitaddr. = .bitaddr. - .MEMLBANK.
  690. If (((.bitaddr.-1) / 16 + 1) Mod 2) = .NUXI. 'Odd
  691. V%[(.bitaddr.-1) / 32 + 1] = V%[(.bitaddr.-1) / 32 + 1] Or 2^((.bitaddr.-1) Mod 16)
  692. Else 'Even
  693. V%[(.bitaddr.-1) / 32 + 1] = V%[(.bitaddr.-1) / 32 + 1] Or 2^((.bitaddr.-1) Mod 16)*&H10000
  694. EndIf
  695. Else ' Out of bounds
  696. Print #.DATALOG., "E BIT out of bounds."
  697. .errcode.=.ERR_ILLEGAL_DATA_ADDRESS.
  698. Return
  699. EndIf
  700. Print #.DATALOG., "A Set BIT " + Str$(.bitaddr.) + "."
  701. Else
  702. .bitaddr. = .bitaddr. + .MB_ADDR_OFFS.
  703. If .COILBANK_BST. >= 1 And .bitaddr. <= .COILBANK_BMAX.
  704. .bitaddr. = .bitaddr. - .COILBANK.
  705. Reset O[.bitaddr.]
  706. ElseIf .bitaddr. >= .MEMBANK_BST. And .bitaddr. <= .MEMBANK_BMAX.
  707. .bitaddr. = .bitaddr. - .MEMBANK.
  708. V%[(.bitaddr.-1) / 16 + 1] = V%[(.bitaddr.-1) / 16 + 1] And (Not (2^((.bitaddr.-1) Mod 16)))
  709. ElseIf .bitaddr. >= .MEMRBANK_BST. And .bitaddr. <= .MEMRBANK_BMAX.
  710. .bitaddr. = .bitaddr. - .MEMRBANK.
  711. .real.=V![(.bitaddr.-1) / 32 + 1]
  712. If (((.bitaddr.-1) / 16 + 1) Mod 2) = .NUXI. 'Odd
  713. GoSub *GETLOWREAL
  714. .realint. = .realint. And Not (2^((.bitaddr.-1) Mod 16))
  715. GoSub *SETLOWREAL
  716. Else 'Even
  717. GoSub *GETHIGHREAL
  718. .realint. = .realint. And Not (2^((.bitaddr.-1) Mod 16))
  719. GoSub *SETHIGHREAL
  720. EndIf
  721. V![(.bitaddr.-1) / 32 + 1] = .real.
  722. ElseIf .bitaddr. >= .MEMLBANK_BST. And .bitaddr. <= .MEMLBANK_BMAX.
  723. .bitaddr. = .bitaddr. - .MEMLBANK.
  724. If (((.bitaddr.-1) / 16 + 1) Mod 2) = .NUXI. 'Odd
  725. V%[(.bitaddr.-1) / 32 + 1] = V%[(.bitaddr.-1) / 32 + 1] And (Not (2^((.bitaddr.-1) Mod 16)))
  726. Else 'Even
  727. V%[(.bitaddr.-1) / 32 + 1] = V%[(.bitaddr.-1) / 32 + 1] And (Not (2^((.bitaddr.-1) Mod 16)*&H10000))
  728. EndIf
  729. Else ' Out of bounds
  730. Print #.DATALOG., "E BIT out of bounds."
  731. .errcode. = .ERR_ILLEGAL_DATA_ADDRESS.
  732. Return
  733. EndIf
  734. Print #.DATALOG., "A Reset BIT " + Str$(.bitaddr.) + "."
  735. EndIf
  736. Return
  737. *GETLOWREAL
  738. SetReal .REALBUFF., .real., 0
  739. GetInt .REALBUFF., .realint., 0
  740. .realint. = .realint. And &H0000FFFF
  741. Return
  742. *GETHIGHREAL
  743. SetReal .REALBUFF., .real., 2
  744. GetInt .REALBUFF., .realint., 0
  745. .realint. = .realint. And &H0000FFFF
  746. Return
  747. *SETLOWREAL
  748. SetReal .REALBUFF.,.real., 0
  749. SetByte .REALBUFF., (.realint. And &H0000FFFF) / &H100 , 2
  750. SetByte .REALBUFF., (.realint. And &H000000FF) , 3
  751. GetReal .REALBUFF.,.real., 0
  752. Return
  753. *SETHIGHREAL
  754. SetReal .REALBUFF.,.real., 2
  755. SetInt .REALBUFF.,.realint., 0
  756. GetReal .REALBUFF.,.real., 2
  757. Return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement