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