use strict; use warnings; use feature 'say'; use Digest::CRC; sub Left_Pad { my $value = shift; if (length($value) % 2) {$value = '0'.$value;} return $value; } sub Bitwise_Reverse { my $value = shift; $value = Left_Pad($value); my $offset = length($value); my $reversed; while ($offset > 0) { $offset -= 2; my $string = substr($value,$offset,2); $reversed .= $string; } return $reversed; } sub CRC_DNP_ASCII { my $value = shift; my $ctx = Digest::CRC->new(width=>16, init=>0x0, xorout=>0xffff, refin=>1, refout=>1, poly=>0x3d65, cont=>0); $ctx->add($value); my $digest = $ctx->hexdigest; my $crc = Bitwise_Reverse($digest); return $crc; } sub CRC_DNP_HEX { my $value = shift; my $ctx = Digest::CRC->new(width=>16, init=>0x0, xorout=>0xffff, refin=>1, refout=>1, poly=>0x3d65, cont=>0); my $offset = 0; while ($offset < length($value)) { my $string = substr($value,$offset,2); $ctx->add(chr(hex($string))); $offset += 2; } my $digest = $ctx->hexdigest; my $crc = Bitwise_Reverse($digest); return $crc; } my @data_list = ('056405F201000000','56405F201000000'); foreach my $data (@data_list) { say "Calculating CRC-DNP checksum for '$data':"; my $ascii = CRC_DNP_ASCII($data); say " ASCII input: $ascii"; my $hex = CRC_DNP_HEX($data); say " Hex input: $hex\n"; }