xref: /nrf52832-nimble/rt-thread/components/net/freemodbus/port/user_mb_app_m.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * FreeModbus Libary: user callback functions and buffer define in master 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_m.c,v 1.60 2013/11/23 11:49:05 Armink $
20  */
21 #include "user_mb_app.h"
22 
23 /*-----------------------Master mode use these variables----------------------*/
24 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
25 //Master mode:DiscreteInputs variables
26 USHORT   usMDiscInStart                             = M_DISCRETE_INPUT_START;
27 #if      M_DISCRETE_INPUT_NDISCRETES%8
28 UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
29 #else
30 UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
31 #endif
32 //Master mode:Coils variables
33 USHORT   usMCoilStart                               = M_COIL_START;
34 #if      M_COIL_NCOILS%8
35 UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
36 #else
37 UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
38 #endif
39 //Master mode:InputRegister variables
40 USHORT   usMRegInStart                              = M_REG_INPUT_START;
41 USHORT   usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
42 //Master mode:HoldingRegister variables
43 USHORT   usMRegHoldStart                            = M_REG_HOLDING_START;
44 USHORT   usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
45 
46 /**
47  * Modbus master input register callback function.
48  *
49  * @param pucRegBuffer input register buffer
50  * @param usAddress input register address
51  * @param usNRegs input register number
52  *
53  * @return result
54  */
eMBMasterRegInputCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs)55 eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
56 {
57     eMBErrorCode    eStatus = MB_ENOERR;
58     USHORT          iRegIndex;
59     USHORT *        pusRegInputBuf;
60     USHORT          REG_INPUT_START;
61     USHORT          REG_INPUT_NREGS;
62     USHORT          usRegInStart;
63 
64     pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1];
65     REG_INPUT_START = M_REG_INPUT_START;
66     REG_INPUT_NREGS = M_REG_INPUT_NREGS;
67     usRegInStart = usMRegInStart;
68 
69     /* it already plus one in modbus function method. */
70     usAddress--;
71 
72     if ((usAddress >= REG_INPUT_START)
73             && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
74     {
75         iRegIndex = usAddress - usRegInStart;
76         while (usNRegs > 0)
77         {
78             pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
79             pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
80             iRegIndex++;
81             usNRegs--;
82         }
83     }
84     else
85     {
86         eStatus = MB_ENOREG;
87     }
88 
89     return eStatus;
90 }
91 
92 /**
93  * Modbus master holding register callback function.
94  *
95  * @param pucRegBuffer holding register buffer
96  * @param usAddress holding register address
97  * @param usNRegs holding register number
98  * @param eMode read or write
99  *
100  * @return result
101  */
eMBMasterRegHoldingCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs,eMBRegisterMode eMode)102 eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
103         USHORT usNRegs, eMBRegisterMode eMode)
104 {
105     eMBErrorCode    eStatus = MB_ENOERR;
106     USHORT          iRegIndex;
107     USHORT *        pusRegHoldingBuf;
108     USHORT          REG_HOLDING_START;
109     USHORT          REG_HOLDING_NREGS;
110     USHORT          usRegHoldStart;
111 
112     pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
113     REG_HOLDING_START = M_REG_HOLDING_START;
114     REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
115     usRegHoldStart = usMRegHoldStart;
116     /* if mode is read, the master will write the received date to buffer. */
117     eMode = MB_REG_WRITE;
118 
119     /* it already plus one in modbus function method. */
120     usAddress--;
121 
122     if ((usAddress >= REG_HOLDING_START)
123             && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
124     {
125         iRegIndex = usAddress - usRegHoldStart;
126         switch (eMode)
127         {
128         /* read current register values from the protocol stack. */
129         case MB_REG_READ:
130             while (usNRegs > 0)
131             {
132                 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
133                 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
134                 iRegIndex++;
135                 usNRegs--;
136             }
137             break;
138         /* write current register values with new values from the protocol stack. */
139         case MB_REG_WRITE:
140             while (usNRegs > 0)
141             {
142                 pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
143                 pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
144                 iRegIndex++;
145                 usNRegs--;
146             }
147             break;
148         }
149     }
150     else
151     {
152         eStatus = MB_ENOREG;
153     }
154     return eStatus;
155 }
156 
157 /**
158  * Modbus master coils callback function.
159  *
160  * @param pucRegBuffer coils buffer
161  * @param usAddress coils address
162  * @param usNCoils coils number
163  * @param eMode read or write
164  *
165  * @return result
166  */
eMBMasterRegCoilsCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNCoils,eMBRegisterMode eMode)167 eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
168         USHORT usNCoils, eMBRegisterMode eMode)
169 {
170     eMBErrorCode    eStatus = MB_ENOERR;
171     USHORT          iRegIndex , iRegBitIndex , iNReg;
172     UCHAR *         pucCoilBuf;
173     USHORT          COIL_START;
174     USHORT          COIL_NCOILS;
175     USHORT          usCoilStart;
176     iNReg =  usNCoils / 8 + 1;
177 
178     pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1];
179     COIL_START = M_COIL_START;
180     COIL_NCOILS = M_COIL_NCOILS;
181     usCoilStart = usMCoilStart;
182 
183     /* if mode is read,the master will write the received date to buffer. */
184     eMode = MB_REG_WRITE;
185 
186     /* it already plus one in modbus function method. */
187     usAddress--;
188 
189     if ((usAddress >= COIL_START)
190             && (usAddress + usNCoils <= COIL_START + COIL_NCOILS))
191     {
192         iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
193         iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
194         switch (eMode)
195         {
196          /* read current coil values from the protocol stack. */
197         case MB_REG_READ:
198             while (iNReg > 0)
199             {
200                 *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
201                         iRegBitIndex, 8);
202                 iNReg--;
203             }
204             pucRegBuffer--;
205             /* last coils */
206             usNCoils = usNCoils % 8;
207             /* filling zero to high bit */
208             *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
209             *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
210             break;
211 
212         /* write current coil values with new values from the protocol stack. */
213         case MB_REG_WRITE:
214             while (iNReg > 1)
215             {
216                 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
217                         *pucRegBuffer++);
218                 iNReg--;
219             }
220             /* last coils */
221             usNCoils = usNCoils % 8;
222             /* xMBUtilSetBits has bug when ucNBits is zero */
223             if (usNCoils != 0)
224             {
225                 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
226                         *pucRegBuffer++);
227             }
228             break;
229         }
230     }
231     else
232     {
233         eStatus = MB_ENOREG;
234     }
235     return eStatus;
236 }
237 
238 /**
239  * Modbus master discrete callback function.
240  *
241  * @param pucRegBuffer discrete buffer
242  * @param usAddress discrete address
243  * @param usNDiscrete discrete number
244  *
245  * @return result
246  */
eMBMasterRegDiscreteCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNDiscrete)247 eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
248 {
249     eMBErrorCode    eStatus = MB_ENOERR;
250     USHORT          iRegIndex , iRegBitIndex , iNReg;
251     UCHAR *         pucDiscreteInputBuf;
252     USHORT          DISCRETE_INPUT_START;
253     USHORT          DISCRETE_INPUT_NDISCRETES;
254     USHORT          usDiscreteInputStart;
255     iNReg =  usNDiscrete / 8 + 1;
256 
257     pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1];
258     DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
259     DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
260     usDiscreteInputStart = usMDiscInStart;
261 
262     /* it already plus one in modbus function method. */
263     usAddress--;
264 
265     if ((usAddress >= DISCRETE_INPUT_START)
266             && (usAddress + usNDiscrete    <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
267     {
268         iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
269         iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
270 
271         /* write current discrete values with new values from the protocol stack. */
272         while (iNReg > 1)
273         {
274             xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8,
275                     *pucRegBuffer++);
276             iNReg--;
277         }
278         /* last discrete */
279         usNDiscrete = usNDiscrete % 8;
280         /* xMBUtilSetBits has bug when ucNBits is zero */
281         if (usNDiscrete != 0)
282         {
283             xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
284                     usNDiscrete, *pucRegBuffer++);
285         }
286     }
287     else
288     {
289         eStatus = MB_ENOREG;
290     }
291 
292     return eStatus;
293 }
294 #endif
295