CRC16 help

For more advanced meter data users. Learn from others and ask questions about how to read meters, how to use the EKM Push Data, and how to display the meter data in useful ways.
Post Reply
aquarat
Posts: 7
Joined: Mon Sep 24, 2012 5:40 am

CRC16 help

Post by aquarat » Mon Sep 24, 2012 3:17 pm

Hi

I'm trying to get the CRC16 algorithm going in Java... but I must admit bitwise operations aren't my strong point. This is what I've done with the EKM-provided CRC16 C-code (an attempt to translate it to Java) :

Code: Select all

public void tryMe(byte[] responseFromDevice)
{
            byte[] c = new byte[2];
            c[0] = a[253];
            c[1] = a[254];
            
            log("EKM CRC : " + Integer.toHexString(ekmCheckCrc(responseFromDevice)) +
            " Device CRC : " + Integer.toHexString((int) (c[0])) + Integer.toHexString((int) (c[1])) );
}

    public int ekmCheckCrc(byte[] dat) {
        int crc = 0xffff;

        for (int i = 1; i < dat.length-3; i++) {
            crc = (crc >>> 8) ^ ekmCrcLut[(crc ^  dat[i]) & 0xff];
        }

       crc = (crc >>> 8) | (crc << 8);
       crc = crc & 0x7f7f;

        return crc;
    }
    
    static int[] ekmCrcLut = new int[]{
        0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
                       (EKM's LUT sits here, no point including the rest of it)
        0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    };
At present nothing this code generates matches the last 2 bytes in the 255-byte response from the Omnimeter.

Here's someone else's code, which uses the same LUT :

Code: Select all

    public class CRC16 {

        public void checksum(byte[] a) {

            int[] table = {
                0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
                 ...the same LUT as the one EKM uses goes here... no point including all of it...
                0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
            };

            byte[] bytes = a;
            int crc = 0x0000;
            for (byte b : bytes) {
                crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
            }

              System.out.println("CRC16 = " + Integer.toHexString(crc));

        }
    }
Example CRCs : This algorithm CRC : e6f and the device's CRC : 2e45

What am I doing wrong ? Thanks in advance :)

Jameson
Posts: 765
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: CRC16 help

Post by Jameson » Mon Sep 24, 2012 3:39 pm

I will also admit that I dont understand this too well myself. We use a plugin that solves this for the EKM Dash (we had a developer solve this for the EKM Push)

Perhaps someone here on the forum can comment on your code.

One thing to check is that the checksum is the last 2 bytes, and is calculated on the second byte, through the third from last byte.

Also are you aware of the challenges of calculating a CRC16 checksum on a 7 bit serial response?

Have you checked out everything in this thread?: http://forum.ekmmetering.com/viewtopic.php?f=4&t=5

If you still are stuck we can check with a developer.

Regards,
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371

aquarat
Posts: 7
Joined: Mon Sep 24, 2012 5:40 am

Re: CRC16 help

Post by aquarat » Tue Sep 25, 2012 1:44 am

Hey Jameson

I must admit I don't understand the issues associated with 7-bit serial, I'll try and research it a bit more today.

I've written an application which loads an array of meters from a config file and then communicates with them over VPNs attached to EKM iSerials at certain intervals... I'm hoping to install this in one of our properties tomorrow yay :) . My application inserts both the data received from the Omnimeter as well as the parsed data in the response into a mySQL table. The whole thing runs quite nicely on a Raspberry Pi Arm computer.

So far everything has been going very well, but every now and then I get an obviously corrupt packet. I still get these even after checking for the presence of various bytes, the year and attempting to parse all the various fields. The solution in my mind is to try and implement the CRC16 algorithm.

The current iSerial->Omnimeter run is about 8 meters, so it's strange that there's corrupt data in the first place.

The meter seems to sometimes return very short responses, like 47 bytes. My application just drops these packets.

Thanks for your time :) I'll respond again if I can't come right.

Jameson
Posts: 765
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: CRC16 help

Post by Jameson » Tue Sep 25, 2012 3:24 pm

Very interesting!! The Raspberry Pi is really perfect for this. We have one here and have tinkered with it a bit, but have not gotten it to read meters yet (I was trying through UART). I would be very interested in tracking your progress! Have you only read your meters through iSerials or have you also tried reading them through UART or USB? We would be happy to send you a USB converter to get you going if you need one.

For those reading this that are curious you can check out what Raspberry Pi is here: http://www.raspberrypi.org/
I must admit I don't understand the issues associated with 7-bit serial, I'll try and research it a bit more today.
As far as I understand CRC16 checksum usually assumes 8 bit communications (256 characters per byte). So when you communicate with 7 bit (128 character possibilities per byte) you have to take this into consideration. 7 bit communication only has roughly 16K possibilities with 2 bytes. Maybe someone here can explain this better than I, or I can ask for a more concise explanation from our developer who figured this out.
So far everything has been going very well, but every now and then I get an obviously corrupt packet. I still get these even after checking for the presence of various bytes, the year and attempting to parse all the various fields. The solution in my mind is to try and implement the CRC16 algorithm.
You are correct that verifying the data using the CRC16 will solve this issue. We also count bytes and discard any responses that are anything other than 255 bytes long. You should be able to get at least close to 100% good responses (uncorrupted data) with 8 meters connected to one iSerial.

Definitely keep us posted on your progress, if you need a hand with anything at all, please let us know.

Regards,
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371

aquarat
Posts: 7
Joined: Mon Sep 24, 2012 5:40 am

Re: CRC16 help

Post by aquarat » Thu Sep 27, 2012 6:31 am

Hey Jameson

I've finished installing one of your company's meters in one of our tenant's premises... I'll upload some photos at some point. Getting a cellphone signal was a mission, but it's all working now.

It's quite cool being able to see voltage differences between home and the first field meter (home is around 238 Volts, meter in the field is 221 V).

The layout of connectivity looks like this :

Code: Select all

                                       Client premises
|------------------------------------------------------------------------------------------| 
EKM OmniMeter ---(RS-485)---> iSerial ---(Ethernet)---> Mikrotik Router ---(VPN over 3G)---> Central VPN server ---(Ethernet)---> My meter reading system
I can currently access the freshly installed EKM meter from my current location, which is connected through another VPN over ADSL to my main VPN server... ahhh isn't the internet amazing ?

This is what the debugging output of my application looks like in the terminal (all this data also makes its way into the database, the db data is more complete than the terminal debugging output) :

Code: Select all

230 : Thu Sep 27 14:58:23 SAST 2012 : EKM CRC : 492e Device CRC : 2e57
231 : Thu Sep 27 14:58:23 SAST 2012 : Meter : 000000012727
232 : Thu Sep 27 14:58:23 SAST 2012 : Voltage 1 : 238.9
233 : Thu Sep 27 14:58:23 SAST 2012 : Voltage 2 : 0.0
234 : Thu Sep 27 14:58:23 SAST 2012 : Voltage 3 : 0.0
235 : Thu Sep 27 14:58:23 SAST 2012 : kWh Total : 296.0
236 : Thu Sep 27 14:58:23 SAST 2012 : kWh 1 : 155.2
237 : Thu Sep 27 14:58:23 SAST 2012 : kWh 2 : 140.8
238 : Thu Sep 27 14:58:23 SAST 2012 : kWh 3 : 0.0
239 : Thu Sep 27 14:58:23 SAST 2012 : Power 1 : 1266
240 : Thu Sep 27 14:58:23 SAST 2012 : Power 2 : 0
241 : Thu Sep 27 14:58:23 SAST 2012 : Power 3 : 0
242 : Thu Sep 27 14:58:23 SAST 2012 : Power Total : 1266
243 : Thu Sep 27 14:58:41 SAST 2012 : EKM CRC : 691b Device CRC : 1af
244 : Thu Sep 27 14:58:41 SAST 2012 : Meter : 000000012706
245 : Thu Sep 27 14:58:41 SAST 2012 : Voltage 1 : 226.2
246 : Thu Sep 27 14:58:41 SAST 2012 : Voltage 2 : 0.0
247 : Thu Sep 27 14:58:41 SAST 2012 : Voltage 3 : 0.0
248 : Thu Sep 27 14:58:41 SAST 2012 : kWh Total : 85.2
249 : Thu Sep 27 14:58:41 SAST 2012 : kWh 1 : 71.1
250 : Thu Sep 27 14:58:41 SAST 2012 : kWh 2 : 14.1
251 : Thu Sep 27 14:58:41 SAST 2012 : kWh 3 : 0.0
252 : Thu Sep 27 14:58:41 SAST 2012 : Power 1 : 3318
253 : Thu Sep 27 14:58:41 SAST 2012 : Power 2 : 0
254 : Thu Sep 27 14:58:41 SAST 2012 : Power 3 : 0
255 : Thu Sep 27 14:58:41 SAST 2012 : Power Total : 3318
This is running on a Pi but could easily run on any system, including x86 and Windows, without recompilation. There are still some minor issues in my application; I think I have the incorrect offset for the kwh2 data, as both of these meters are only connected to single phase. However the total kwh is my major point of interest and reliably matches what's displayed on the meter.

At the moment I'm using the InputStreamReader class in java, as opposed to the BufferedInputStreamReader... this might be causing the trouble with short responses, but certainly my application reliably reads more than 1 sample per minute, which is well in excess of my requirements (I just need to know how much power is being used on a monthly basis... but I love seeing all the other data and having more samples for better resolution... it's just cool).

Thanks for making such easy to use documentation available on your company's meter protocols, it's really been of great help :D .
Have you only read your meters through iSerials or have you also tried reading them through UART or USB? We would be happy to send you a USB converter to get you going if you need one.
I've only read data off the meters so far using the iSerials. I've experimented a great deal with RS232 and TTL UART comms before and so far I've had bad luck with USB-RS232 adapters... they seem to die after a random number of hours in Linux. Maybe the problem's been solved? The Raspberry Pi has a TTL UART that forms part of it's GPIO header, I regularly use this through a level shifter to talk to RS232 devices (APRS modem, Oregon Scientific weather station, etc.)... a similar solution may be possible for RS-485... but it doesn't really make sense for my scenario; I want my logging system to be separate from the meters for security purposes. If I were to log the data using Raspberry Pis at the site of the meter I'd still have to deal with getting that data to a central location, where I have control of it. That said, getting my programme to read data from the meters directly using a USB to RS-485 adapter would probably be extremely easy. I know from past experiences that the libraries used to read data from UARTs behave almost identically when compared with TCP sockets (from my code's perspective). I could just look for "/dev" or "COM" in the "meter0address" argument in my configuration file and then if I find one of those tokens assume that the meter is directly attached.

I must say, though, that I do like the iSerials... they're small and they're encased in metal, they look perfectly at home in a DB box.

Now that this is working I've asked our electrical contractors to install additional boxes for metering, which will hopefully be ready by next week.
Photos :
Image
Image
Image
Image
The photos are being hosted on my ADSL line... on a Raspberry Pi haha (I have many of them :P ).
In the image of the box without it's main cover you can see :
1) A Mikrotik router on the lower left with a USB 3G dongle attached and attached to that an antenna extender.
2) The iSerial is obscured by the box, but it sits just underneath the plus point.
3) Obviously the EKM Omnimeter is present in the top right and you can just barely make out it's CT in the top of the box on the left.
4) Another power meter is present... but it's quite dumb and was installed as the result of a misunderstanding.
Image
Above : A little less related; a Pi with a TTL->RS232 level shifter attached and that in turn attached to a USB-RS232 converter.

Jameson
Posts: 765
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: CRC16 help

Post by Jameson » Thu Sep 27, 2012 3:33 pm

Ooooh Yeah!! :ugeek:

I tip my hat to you, this is awesome.

Where to begin?: RasPi, cell connection, database.... Again very cool. If you ever get a hankering to try the USB converter we will send it right over.

The kWh2 data you mention is actually kWh TOU 2. The meters themselves keep track of Time-of-Use on up to 4 time periods. This is for customers who are charged more by their utilities for power they use during the day, then the power they use at night. You can custom set these TOU periods, seasons, and holidays using our EKM Dash software (or use the Dash to learn how to do it with "Hex Inspector"). In your case kWh T1 and kWh T2 should add together to equal Total kWh.

Were you able to sort out the CRC16 checksum? I see that you have it showing up different in the datastream.

My RasPi:
TTL UART (Im a beginner at this stuff): I connected an RS485 transceiver to the RasPi TTL UART. We were able to sniff the serial output of the RasPi on one of our RS485 converters (came through clean). I have not been able to get the serial settings on the RasPi to be the right ones to read one of our meters yet. The attached image (of our RasPi at EKM) shows the UART connection. The board it is connected to at the bottom, is a scrap board that I used to power the RS485 transceiver.

I could download the FTDI drivers to the RasPi and could see the USB converter was connected, but never got it to work.

Thanks again for sharing, it is really cool to see what is possible.

Best regards,
Attachments
IMG_0008.jpeg
Raspberry Pi to EKM Omnimeter RS485
IMG_0008.jpeg (97.23 KiB) Viewed 12707 times
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371

ianf
Posts: 7
Joined: Fri Jul 06, 2012 12:01 am

Re: CRC16 help

Post by ianf » Fri Jan 04, 2013 11:32 am

aquarat wrote: I'm trying to get the CRC16 algorithm going in Java... but I must admit bitwise operations aren't my strong point. This is what I've done with the EKM-provided CRC16 C-code (an attempt to translate it to Java) :

Code: Select all

    public int ekmCheckCrc(byte[] dat) {
        int crc = 0xffff;

        for (int i = 1; i < dat.length-3; i++) {
            crc = (crc >>> 8) ^ ekmCrcLut[(crc ^  dat[i]) & 0xff];
        }
I have a question regarding the bounds for the data that you use for calculating the CRC. I also spent a long time getting the CRCs to work. Are you sure that you're passing the entire response string to your ekmCheckCrc() function? Then, are you sure the function is consuming every character of interest in the string? I think you may want 'i <= dat.length-3', because what you have will stop at 'i == dat.length-4'. Also, don't forget about 'network byte order' which may be different from 'host byte order'.
When comparing the CRC, I do the following:

Code: Select all

got = ekm_read(connection, buffer, nbytes);
crc = ekmcrc(buffer + 1, got - (sizeof(crc) + 1));
return(crc == ntohs(*(u_int16_t *)&((char*)buffer)[got -sizeof(crc)]));
Note the use of the ntohs (network to host byte conversion of a short) macro on the data recieved off the network. Also, you should make sure that your receive buffer is flushed before you "open" the meter. There may be data waiting to be read if you explicitly read 255 bytes each time. The iSerial my itself corrupt the data. See below.

BTW, I think it's best to have the CRC function not make assumptions about the structure of the data it's consuming. IOW, pass the CRC function the entire string you want checked and handle how much of the original string you want checked in the calling function.

Then, over a VPN or any medium that exhibits a latency greater than the iSerial retransmit timer (~60ms), you may encounter another issue which EKM has had fixed. You will need to get an update firmware for your iSerial from Jameson. The iSerial has a fairly aggressive timeout in the function that packs UART data into the TCP packet which results in a flurry of tinygrams each containing a small portion of the data stream. If the iSerial does not receive an ACK before it transmits the next packet, it will retransmit un-ACKed data, but it will use the next TCP sequence to do so rather than using the original sequence, thereby inserting the retransmits into the data stream and corrupting it.

aquarat
Posts: 7
Joined: Mon Sep 24, 2012 5:40 am

Re: CRC16 help

Post by aquarat » Fri Jan 04, 2013 2:47 pm

Hi Ianf

I managed to get it working (with code that I've quoted below). I just roughly translated EKM's C code. I thought I had gotten the translation wrong, but in actual fact I was passing 1 byte too many to the method (which is what you suggested in your post).

Thanks for trying to help me. It's all working now.

I had been logging data from meters for at least two months and in addition to logging individual fields I also logged the entire response from the meter as a blob. As soon as I got this method going I wrote a programme to go through the database and check every sample, deleting those that didn't pass... it's great having clean data :D .

Code :

Code: Select all

    
"dat" is the response from the meter as a byte array (byte[255]).

public int ekmCheckCrc(byte[] dat) {
        int crc = 0xffff;//was 0xffff

        for (int i = 1; i < dat.length - 2; i++) {
            crc = (crc >> 8) ^ ekmCrcLut[(crc ^ dat[i]) & 0xff];
        }

        crc = (crc << 8) | (crc >> 8);
        crc = crc & 0x7f7f;

        return crc;
    }
    static int[] ekmCrcLut = new int[]{
        0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
        0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
        0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
        0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
        0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
        0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
        0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
        0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
        0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
        0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
        0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
        0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
        0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
        0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
        0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
        0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
        0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
        0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
        0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
        0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
        0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
        0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
        0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
        0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
        0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
        0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
        0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
        0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
        0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
        0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
        0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
        0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    };

cliff@hawkrdg.org
Posts: 3
Joined: Tue Mar 10, 2015 10:32 am

Re: CRC16 help

Post by cliff@hawkrdg.org » Tue Mar 10, 2015 1:00 pm

OK, so after a bit of head-banging, here is the javascript code to use this in a webapp. You can submit hex strings as str = String.fromCharCode(0x52, 0x31, 0x02, 0x30, 0x30, 0x31, 0x31, 0x03); - ReadLastKwh. I built a simple library of the calls I needed. This all works fine inside of a web app served off of a node.js server using angular.js and couchdb for data binding and storage.

//-- BY ALL THE GODS, FIX THIS FORMATTING SO IT LOOKS LIKE REAL JAVASCRIPT --

var crcHexString = "";

ekmCrcLut = [
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
];

convertStringToUint8Array = function( str ) {
var a8 = new Uint8Array( str.length ), data;

data = str.split("");
data.forEach( function(ch,cnt) {
a8[cnt] = ch.charCodeAt(0);
} );
return a8;
}

ekmCheckCrc = function( str ) {
var crc = 0xffff, data = main.convertStringToUint8Array( str );

console.log( 'calc crc16 for ' + data );
for (var i = 0; i < data.length; i++ ) {
crc = (crc >> 8) ^ main.ekmCrcLut[(crc ^ data) & 0xff];
}

crc = (crc << 8) | (crc >> 8); // reverse the bytes
crc &= 0x7f7f; // rip each byte to 7-bits

crcHexString.txtCRC16 = crc.toString(16); // text for page display
return crc
}

//-- BY ALL THE GODS, FIX THIS FORMATTING SO IT LOOKS LIKE REAL JAVASCRIPT --

Post Reply