1515 * along with the libmodbuspp Library; if not, see <http://www.gnu.org/licenses/>.
1616 */
1717#include < modbuspp/message.h>
18+ #include < modbus-ascii.h>
1819#include " asciilayer_p.h"
1920#include " config.h"
21+ #include " modbuspp/global.h"
2022
2123#ifndef _WIN32
2224#include < unistd.h>
2325#endif
2426
2527namespace Modbus {
26-
27- namespace ascii {
28-
29- // -------------------------------------------------------------------------
30- const uint8_t CrcHiTable[] = {
31- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 ,
32- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 ,
33- 0x00 , 0xC1 , 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 ,
34- 0x80 , 0x41 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 ,
35- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 ,
36- 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 , 0x80 , 0x41 ,
37- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 ,
38- 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 ,
39- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 ,
40- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 ,
41- 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 ,
42- 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 ,
43- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 ,
44- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 ,
45- 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 ,
46- 0x80 , 0x41 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 ,
47- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 ,
48- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 ,
49- 0x00 , 0xC1 , 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 ,
50- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 ,
51- 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 ,
52- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 ,
53- 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x00 , 0xC1 ,
54- 0x81 , 0x40 , 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 ,
55- 0x00 , 0xC1 , 0x81 , 0x40 , 0x01 , 0xC0 , 0x80 , 0x41 , 0x01 , 0xC0 ,
56- 0x80 , 0x41 , 0x00 , 0xC1 , 0x81 , 0x40
57- };
58-
59- // -------------------------------------------------------------------------
60- const uint8_t CrcLoTable[] = {
61- 0x00 , 0xC0 , 0xC1 , 0x01 , 0xC3 , 0x03 , 0x02 , 0xC2 , 0xC6 , 0x06 ,
62- 0x07 , 0xC7 , 0x05 , 0xC5 , 0xC4 , 0x04 , 0xCC , 0x0C , 0x0D , 0xCD ,
63- 0x0F , 0xCF , 0xCE , 0x0E , 0x0A , 0xCA , 0xCB , 0x0B , 0xC9 , 0x09 ,
64- 0x08 , 0xC8 , 0xD8 , 0x18 , 0x19 , 0xD9 , 0x1B , 0xDB , 0xDA , 0x1A ,
65- 0x1E , 0xDE , 0xDF , 0x1F , 0xDD , 0x1D , 0x1C , 0xDC , 0x14 , 0xD4 ,
66- 0xD5 , 0x15 , 0xD7 , 0x17 , 0x16 , 0xD6 , 0xD2 , 0x12 , 0x13 , 0xD3 ,
67- 0x11 , 0xD1 , 0xD0 , 0x10 , 0xF0 , 0x30 , 0x31 , 0xF1 , 0x33 , 0xF3 ,
68- 0xF2 , 0x32 , 0x36 , 0xF6 , 0xF7 , 0x37 , 0xF5 , 0x35 , 0x34 , 0xF4 ,
69- 0x3C , 0xFC , 0xFD , 0x3D , 0xFF , 0x3F , 0x3E , 0xFE , 0xFA , 0x3A ,
70- 0x3B , 0xFB , 0x39 , 0xF9 , 0xF8 , 0x38 , 0x28 , 0xE8 , 0xE9 , 0x29 ,
71- 0xEB , 0x2B , 0x2A , 0xEA , 0xEE , 0x2E , 0x2F , 0xEF , 0x2D , 0xED ,
72- 0xEC , 0x2C , 0xE4 , 0x24 , 0x25 , 0xE5 , 0x27 , 0xE7 , 0xE6 , 0x26 ,
73- 0x22 , 0xE2 , 0xE3 , 0x23 , 0xE1 , 0x21 , 0x20 , 0xE0 , 0xA0 , 0x60 ,
74- 0x61 , 0xA1 , 0x63 , 0xA3 , 0xA2 , 0x62 , 0x66 , 0xA6 , 0xA7 , 0x67 ,
75- 0xA5 , 0x65 , 0x64 , 0xA4 , 0x6C , 0xAC , 0xAD , 0x6D , 0xAF , 0x6F ,
76- 0x6E , 0xAE , 0xAA , 0x6A , 0x6B , 0xAB , 0x69 , 0xA9 , 0xA8 , 0x68 ,
77- 0x78 , 0xB8 , 0xB9 , 0x79 , 0xBB , 0x7B , 0x7A , 0xBA , 0xBE , 0x7E ,
78- 0x7F , 0xBF , 0x7D , 0xBD , 0xBC , 0x7C , 0xB4 , 0x74 , 0x75 , 0xB5 ,
79- 0x77 , 0xB7 , 0xB6 , 0x76 , 0x72 , 0xB2 , 0xB3 , 0x73 , 0xB1 , 0x71 ,
80- 0x70 , 0xB0 , 0x50 , 0x90 , 0x91 , 0x51 , 0x93 , 0x53 , 0x52 , 0x92 ,
81- 0x96 , 0x56 , 0x57 , 0x97 , 0x55 , 0x95 , 0x94 , 0x54 , 0x9C , 0x5C ,
82- 0x5D , 0x9D , 0x5F , 0x9F , 0x9E , 0x5E , 0x5A , 0x9A , 0x9B , 0x5B ,
83- 0x99 , 0x59 , 0x58 , 0x98 , 0x88 , 0x48 , 0x49 , 0x89 , 0x4B , 0x8B ,
84- 0x8A , 0x4A , 0x4E , 0x8E , 0x8F , 0x4F , 0x8D , 0x4D , 0x4C , 0x8C ,
85- 0x44 , 0x84 , 0x85 , 0x45 , 0x87 , 0x47 , 0x46 , 0x86 , 0x82 , 0x42 ,
86- 0x43 , 0x83 , 0x41 , 0x81 , 0x80 , 0x40
87- };
88- }
89-
9028 // ---------------------------------------------------------------------------
9129 //
9230 // AsciiLayer Class
@@ -209,17 +147,51 @@ namespace Modbus {
209147#endif
210148 }
211149
150+ static char nibble_to_hex_ascii (uint8_t nibble)
151+ {
152+ char c;
153+
154+ if (nibble < 10 ) {
155+ c = nibble + ' 0' ;
156+ } else {
157+ c = nibble - 10 + ' A' ;
158+ }
159+ return c;
160+ }
161+
212162 // ---------------------------------------------------------------------------
213163 bool AsciiLayer::prepareToSend (Message & msg) {
214-
215- if (msg.net () == Rtu && msg.size () >= 1 ) {
164+
165+ if (msg.net () == Ascii && msg.size () >= 1 ) {
216166 size_t aduSize = msg.aduSize ();
217167 uint8_t * adu = msg.adu ();
218168
219- uint16_t crc = crc16 (adu, aduSize);
220- adu[aduSize++] = crc >> 8 ;
221- adu[aduSize++] = crc & 0xFF ;
222- msg.setAduSize (aduSize);
169+ /* Skip colon */
170+ uint8_t lrc = lrc8 (adu + 1 , aduSize- 1 );
171+ adu[aduSize++] = lrc;
172+
173+ uint8_t ascii_adu[MODBUS_ASCII_MAX_ADU_LENGTH];
174+ memset (ascii_adu, 0 , MODBUS_ASCII_MAX_ADU_LENGTH);
175+ ssize_t i, j = 0 ;
176+
177+ for (i = 0 ; i < aduSize; i++) {
178+ if ((i == 0 && adu[i] == ' :' ) ||
179+ (i == aduSize - 2 && adu[i] == ' \r ' ) ||
180+ (i == aduSize - 1 && adu[i] == ' \n ' )) {
181+ ascii_adu[j++] = adu[i];
182+ } else {
183+ ascii_adu[j++] = nibble_to_hex_ascii (adu[i] >> 4 );
184+ ascii_adu[j++] = nibble_to_hex_ascii (adu[i] & 0x0f );
185+ }
186+ }
187+ ascii_adu[j++] = ' \r ' ;
188+ ascii_adu[j++] = ' \n ' ;
189+ ascii_adu[j] = ' \0 ' ;
190+
191+ msg.setAduSize (j);
192+
193+ std::memcpy (adu, ascii_adu, j);
194+
223195 return true ;
224196 }
225197 return false ;
@@ -228,7 +200,7 @@ namespace Modbus {
228200 // ---------------------------------------------------------------------------
229201 bool AsciiLayer::checkMessage (const Message & msg) {
230202
231- return crc16 (msg.adu (), msg.aduSize () - 2 ) == msg.crc ();
203+ return lrc8 (msg.adu (), msg.aduSize () - 2 ) == msg.lrc ();
232204 }
233205
234206 // ---------------------------------------------------------------------------
@@ -272,21 +244,15 @@ namespace Modbus {
272244
273245 // ---------------------------------------------------------------------------
274246 // static
275- uint16_t AsciiLayer::crc16 (const uint8_t * buf, uint16_t count) {
276- uint8_t crcHi = 0xFF ; /* high CRC byte initialized */
277- uint8_t crcLo = 0xFF ; /* low CRC byte initialized */
278- unsigned int i; /* will index into CRC lookup */
279-
280- /* pass through message buffer */
281- while (count--) {
282-
283- i = crcHi ^ *buf++; /* calculate the CRC */
284- crcHi = crcLo ^ ascii::CrcHiTable[i];
285- crcLo = ascii::CrcLoTable[i];
286- }
287-
288- return (crcHi << 8 | crcLo);
289- }
247+ uint8_t AsciiLayer::lrc8 (const uint8_t *buffer, uint16_t buffer_length)
248+ {
249+ uint8_t lrc = 0 ;
250+ while (buffer_length--) {
251+ lrc += *buffer++;
252+ }
253+ /* Return two's complementing of the result */
254+ return -lrc;
255+ }
290256
291257 // ---------------------------------------------------------------------------
292258 //
@@ -296,12 +262,13 @@ namespace Modbus {
296262
297263 // ---------------------------------------------------------------------------
298264 AsciiLayer::Private::Private (const std::string & port, const std::string & settings) :
299- NetLayer::Private (Rtu , port, settings, MODBUS_ASCII_MAX_ADU_LENGTH) {
265+ NetLayer::Private (Ascii , port, settings, MODBUS_ASCII_MAX_ADU_LENGTH) {
300266
301267 // RTU MUST BE 8-bits
302268 ctx = modbus_new_ascii (port.c_str (), AsciiLayer::baud (settings),
303269 AsciiLayer::parity (settings), 8 ,
304270 AsciiLayer::stop (settings));
271+
305272 if (! ctx) {
306273
307274 throw std::invalid_argument (
0 commit comments