]> git.basschouten.com Git - openhab-addons.git/blob
29049ad5c755e725f0571fd78e60f0473d06f571
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.dsmr.internal.device.p1telegram;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16
17 /**
18  * CRC16 implementation.
19  *
20  * This class supports 2 ways of using.
21  * The first is to give a complete byte array and get the CRC16 {@link #calculate(byte[], int)}
22  * The second variant the instance stores the actual CRC16 value giving the possibility to add bytes in subsequent
23  * calls to {@link #processByte(byte)}
24  *
25  * @author M. Volaart - Initial contribution
26  */
27 @NonNullByDefault
28 public class CRC16 {
29
30     public enum Polynom {
31         CRC16_IBM(0xA001), // standard CRC-16 x16+x15+x2+1 (CRC-16-IBM)
32         CRC16_IBM_REVERSE(0xC002), // standard reverse x16+x14+x+1 (CRC-16-IBM)
33         CRC16_CCIT(0x8408), // CCITT/SDLC/HDLC X16+X12+X5+1 (CRC-16-CCITT)
34         // The initial CRC value is usually 0xFFFF and the result is complemented.
35         CRC16_CCIT_REVERSE(0x8810), // CCITT reverse X16+X11+X4+1 (CRC-16-CCITT)
36         CRC16_LRCC(0x8000); // LRCC-16 X16+1
37
38         /**
39          * the polynom to use
40          */
41         public final int polynom;
42
43         /**
44          * Constructs a new Polynom using the required polynom value
45          *
46          * @param polynom
47          */
48         private Polynom(int polynom) {
49             this.polynom = polynom;
50         }
51     }
52
53     /**
54      * The cached CRC16 table based on the requested CRC16 variant
55      */
56     private short[] crcTable;
57
58     /**
59      * The current crcValue
60      */
61     private int crcValue;
62
63     /**
64      * Constructs a new CRC16 object using the requested polynom
65      *
66      * @param polynom the CRC16 polynom to use
67      */
68     public CRC16(Polynom polynom) {
69         crcTable = genCrc16Table(polynom);
70     }
71
72     /**
73      * Calculate a CRC16 based on the specified data and the initial CRCvalue
74      *
75      * @param data byes to calculate the CRC16 for
76      * @param initialCrcValue initial CRC value
77      * @return the CRC16 value
78      */
79     public int calculate(byte[] data, int initialCrcValue) {
80         int crc = initialCrcValue;
81         for (int p = 0; p < data.length; p++) {
82             crc = (crc >> 8) ^ (crcTable[(crc & 0xFF) ^ (data[p] & 0xFF)] & 0xFFFF);
83         }
84         return crc;
85     }
86
87     /**
88      * Initializes the CRC16 code to 0.
89      */
90     public void initialize() {
91         initialize(0);
92     }
93
94     /**
95      * Initializes the CRC16 code to the given initial value.
96      *
97      * @param initialCrcValue the initial value to set.
98      */
99     public void initialize(int initialCrcValue) {
100         crcValue = initialCrcValue;
101     }
102
103     /**
104      * Processed a single byte and updates the internal CRC16 value
105      *
106      * @param b the byte to process
107      */
108     public void processByte(byte b) {
109         crcValue = (crcValue >> 8) ^ (crcTable[(crcValue & 0xFF) ^ (b & 0xFF)] & 0xFFFF);
110     }
111
112     /**
113      * Returns the current CRC16 code
114      *
115      * @return integer containing the current CRC16 code.
116      */
117     public int getCurrentCRCCode() {
118         return crcValue;
119     }
120
121     /**
122      * Generates the CRC16 table
123      *
124      * @param polynom the polynonm to use
125      *
126      * @return the generated CRC16 table
127      */
128     private short[] genCrc16Table(Polynom polynom) {
129         short[] table = new short[256];
130         for (int x = 0; x < 256; x++) {
131             int w = x;
132             for (int i = 0; i < 8; i++) {
133                 if ((w & 1) != 0) {
134                     w = (w >> 1) ^ polynom.polynom;
135                 } else {
136                     w = w >> 1;
137                 }
138             }
139             table[x] = (short) w;
140         }
141         return table;
142     }
143 }