1 /*
2 * FreeModbus Libary: user callback functions and buffer define in slave mode
3 * Copyright (C) 2013 Armink <[email protected]>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $
20 */
21 #include "user_mb_app.h"
22
23 /*------------------------Slave mode use these variables----------------------*/
24 //Slave mode:DiscreteInputs variables
25 USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
26 #if S_DISCRETE_INPUT_NDISCRETES%8
27 UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1];
28 #else
29 UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ;
30 #endif
31 //Slave mode:Coils variables
32 USHORT usSCoilStart = S_COIL_START;
33 #if S_COIL_NCOILS%8
34 UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ;
35 #else
36 UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ;
37 #endif
38 //Slave mode:InputRegister variables
39 USHORT usSRegInStart = S_REG_INPUT_START;
40 USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
41 //Slave mode:HoldingRegister variables
42 USHORT usSRegHoldStart = S_REG_HOLDING_START;
43 USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
44
45 /**
46 * Modbus slave input register callback function.
47 *
48 * @param pucRegBuffer input register buffer
49 * @param usAddress input register address
50 * @param usNRegs input register number
51 *
52 * @return result
53 */
eMBRegInputCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs)54 eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
55 {
56 eMBErrorCode eStatus = MB_ENOERR;
57 USHORT iRegIndex;
58 USHORT * pusRegInputBuf;
59 USHORT REG_INPUT_START;
60 USHORT REG_INPUT_NREGS;
61 USHORT usRegInStart;
62
63 pusRegInputBuf = usSRegInBuf;
64 REG_INPUT_START = S_REG_INPUT_START;
65 REG_INPUT_NREGS = S_REG_INPUT_NREGS;
66 usRegInStart = usSRegInStart;
67
68 /* it already plus one in modbus function method. */
69 usAddress--;
70
71 if ((usAddress >= REG_INPUT_START)
72 && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
73 {
74 iRegIndex = usAddress - usRegInStart;
75 while (usNRegs > 0)
76 {
77 *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
78 *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
79 iRegIndex++;
80 usNRegs--;
81 }
82 }
83 else
84 {
85 eStatus = MB_ENOREG;
86 }
87
88 return eStatus;
89 }
90
91 /**
92 * Modbus slave holding register callback function.
93 *
94 * @param pucRegBuffer holding register buffer
95 * @param usAddress holding register address
96 * @param usNRegs holding register number
97 * @param eMode read or write
98 *
99 * @return result
100 */
eMBRegHoldingCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs,eMBRegisterMode eMode)101 eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
102 USHORT usNRegs, eMBRegisterMode eMode)
103 {
104 eMBErrorCode eStatus = MB_ENOERR;
105 USHORT iRegIndex;
106 USHORT * pusRegHoldingBuf;
107 USHORT REG_HOLDING_START;
108 USHORT REG_HOLDING_NREGS;
109 USHORT usRegHoldStart;
110
111 pusRegHoldingBuf = usSRegHoldBuf;
112 REG_HOLDING_START = S_REG_HOLDING_START;
113 REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
114 usRegHoldStart = usSRegHoldStart;
115
116 /* it already plus one in modbus function method. */
117 usAddress--;
118
119 if ((usAddress >= REG_HOLDING_START)
120 && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
121 {
122 iRegIndex = usAddress - usRegHoldStart;
123 switch (eMode)
124 {
125 /* read current register values from the protocol stack. */
126 case MB_REG_READ:
127 while (usNRegs > 0)
128 {
129 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
130 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
131 iRegIndex++;
132 usNRegs--;
133 }
134 break;
135
136 /* write current register values with new values from the protocol stack. */
137 case MB_REG_WRITE:
138 while (usNRegs > 0)
139 {
140 pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
141 pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
142 iRegIndex++;
143 usNRegs--;
144 }
145 break;
146 }
147 }
148 else
149 {
150 eStatus = MB_ENOREG;
151 }
152 return eStatus;
153 }
154
155 /**
156 * Modbus slave coils callback function.
157 *
158 * @param pucRegBuffer coils buffer
159 * @param usAddress coils address
160 * @param usNCoils coils number
161 * @param eMode read or write
162 *
163 * @return result
164 */
eMBRegCoilsCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNCoils,eMBRegisterMode eMode)165 eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
166 USHORT usNCoils, eMBRegisterMode eMode)
167 {
168 eMBErrorCode eStatus = MB_ENOERR;
169 USHORT iRegIndex , iRegBitIndex , iNReg;
170 UCHAR * pucCoilBuf;
171 USHORT COIL_START;
172 USHORT COIL_NCOILS;
173 USHORT usCoilStart;
174 iNReg = usNCoils / 8 + 1;
175
176 pucCoilBuf = ucSCoilBuf;
177 COIL_START = S_COIL_START;
178 COIL_NCOILS = S_COIL_NCOILS;
179 usCoilStart = usSCoilStart;
180
181 /* it already plus one in modbus function method. */
182 usAddress--;
183
184 if( ( usAddress >= COIL_START ) &&
185 ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
186 {
187 iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
188 iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
189 switch ( eMode )
190 {
191 /* read current coil values from the protocol stack. */
192 case MB_REG_READ:
193 while (iNReg > 0)
194 {
195 *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
196 iRegBitIndex, 8);
197 iNReg--;
198 }
199 pucRegBuffer--;
200 /* last coils */
201 usNCoils = usNCoils % 8;
202 /* filling zero to high bit */
203 *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
204 *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
205 break;
206
207 /* write current coil values with new values from the protocol stack. */
208 case MB_REG_WRITE:
209 while (iNReg > 1)
210 {
211 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
212 *pucRegBuffer++);
213 iNReg--;
214 }
215 /* last coils */
216 usNCoils = usNCoils % 8;
217 /* xMBUtilSetBits has bug when ucNBits is zero */
218 if (usNCoils != 0)
219 {
220 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
221 *pucRegBuffer++);
222 }
223 break;
224 }
225 }
226 else
227 {
228 eStatus = MB_ENOREG;
229 }
230 return eStatus;
231 }
232
233 /**
234 * Modbus slave discrete callback function.
235 *
236 * @param pucRegBuffer discrete buffer
237 * @param usAddress discrete address
238 * @param usNDiscrete discrete number
239 *
240 * @return result
241 */
eMBRegDiscreteCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNDiscrete)242 eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
243 {
244 eMBErrorCode eStatus = MB_ENOERR;
245 USHORT iRegIndex , iRegBitIndex , iNReg;
246 UCHAR * pucDiscreteInputBuf;
247 USHORT DISCRETE_INPUT_START;
248 USHORT DISCRETE_INPUT_NDISCRETES;
249 USHORT usDiscreteInputStart;
250 iNReg = usNDiscrete / 8 + 1;
251
252 pucDiscreteInputBuf = ucSDiscInBuf;
253 DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
254 DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
255 usDiscreteInputStart = usSDiscInStart;
256
257 /* it already plus one in modbus function method. */
258 usAddress--;
259
260 if ((usAddress >= DISCRETE_INPUT_START)
261 && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
262 {
263 iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
264 iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
265
266 while (iNReg > 0)
267 {
268 *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
269 iRegBitIndex, 8);
270 iNReg--;
271 }
272 pucRegBuffer--;
273 /* last discrete */
274 usNDiscrete = usNDiscrete % 8;
275 /* filling zero to high bit */
276 *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
277 *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
278 }
279 else
280 {
281 eStatus = MB_ENOREG;
282 }
283
284 return eStatus;
285 }
286
287