I'm aware that java byte is a 8 bits signed variable and to get unsigned (byte) values I will have to do the masking with 0xff everywhere.
Java documentation also says that I can use int to generate unsigned bits by using the procedure previously mentioned.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
However, whether using the mask or not, it returns the same results.
I've trying changing short into int but no success.
Delphi Code
procedure TForm1.ReadHoldRegisters(var lst: TList<byte>; deviceaddr: byte;
RegisterAddress, RegisterLength: word);
begin
lst.Add(deviceaddr);
lst.Add(6);
lst.Add(RegisterAddress div 256);
lst.Add(RegisterAddress mod 256);
lst.Add(RegisterLength div 256);
lst.Add(RegisterLength mod 256);
Add_CRC16(lst);
end;
procedure TForm1.Add_CRC16(var Data: TList<byte>);
var
CRC16Lo, CRC16Hi, CL, CH, SaveHi, SaveLo: byte;
Flag: Integer;
b: byte;
begin
CRC16Lo := $FF;
CRC16Hi := $FF;
CL := $1;
CH := $A0;
for b in Data do
begin
CRC16Lo := CRC16Lo Xor b;
For Flag := 0 To 7 Do
Begin
SaveHi := CRC16Hi;
SaveLo := CRC16Lo;
CRC16Hi := CRC16Hi Div 2;
CRC16Lo := CRC16Lo Div 2;
If ((SaveHi And $1) = $1) Then
begin
CRC16Lo := CRC16Lo Or $80;
end;
If ((SaveLo And $1) = $1) Then
Begin
CRC16Hi := CRC16Hi Xor CH;
CRC16Lo := CRC16Lo Xor CL;
End;
End;
end;
Data.Add(CRC16Lo);
Data.Add(CRC16Hi);
end;
Java Code
public void ReadHoldRegisters(List<Short> lst, byte deviceaddr, char RegisterAddress, char RegisterLength)
{
lst.add((short) (deviceaddr & 0xff));
lst.add((short) ((byte) 6 & 0xff));
lst.add((short) ((RegisterAddress / 256 & 0xff)));
lst.add((RegisterAddress%256));
lst.add((RegisterLength/256));
lst.add(((RegisterLength%256)));
Add_CRC16(lst);
}
private void Add_CRC16(List<Short> Data)
{
//Cyclic Redundancy Check 16
short SaveLo, SaveHi;
int flag;
short CRC16Lo = ((short) 0xFF & 0xff);
short CRC16Hi = ((short) 0xFF & 0xff);
short CL = (short) 0x1 & 0xff;
short CH = (short) (0xA0) & 0xff;
short andop = ((short) 0x80 & 0xff);
short andop2 = (short) 0x1 & 0xff;
// inĂcio do for in
for (Short b : Data)
{
CRC16Lo ^= b & 0xff;
for(flag=0;flag<7;flag++)
{
SaveHi = (short) ((CRC16Hi) & 0xff);
SaveLo = (short) ((CRC16Lo) & 0xff);
CRC16Hi = (short) ((CRC16Hi/2) & 0xff);
CRC16Lo = (short) ((CRC16Lo/2) & 0xff);
if((SaveHi & andop2) == andop2 )
CRC16Lo |= andop & 0xff;
if(((SaveLo) & (andop2)) == (andop2))
{
CRC16Hi ^= CH & 0xff;
CRC16Lo ^= CL & 0xff;
}
}
}
Data.add((short) (CRC16Lo & 0xff));
Data.add((short) (CRC16Hi & 0xff));
}
The correct result to be displayed in this case is "01 06 00 01 00 0A 58 0D"
Any thoughts? Any help?
The most obvious difference is here:
for(flag=0;flag<7;flag++)
This loops runs one fewer times than the Delphi version. You mean:
for(flag=0;flag<8;flag++)
On top of that, the Java code was needlessly complex. It can be greatly simplified. This program gives the same output as the Delphi code:
import java.util.*;
public class test
{
public static void ReadHoldRegisters(List<Integer> lst, int deviceaddr, int RegisterAddress, int RegisterLength)
{
lst.add(deviceaddr & 0xff);
lst.add(6);
lst.add((RegisterAddress >> 8) & 0xff);
lst.add(RegisterAddress & 0xff);
lst.add((RegisterLength >> 8) & 0xff);
lst.add(RegisterLength & 0xff);
Add_CRC16(lst);
}
private static void Add_CRC16(List<Integer> Data)
{
int SaveLo, SaveHi;
int CRC16Lo = 0xFF;
int CRC16Hi = 0xff;
int CL = 0x1;
int CH = 0xA0;
for (int b : Data)
{
CRC16Lo ^= b;
for (int flag=0; flag<8; flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = CRC16Hi/2;
CRC16Lo = CRC16Lo/2;
if((SaveHi & 0x01) == 0x01)
CRC16Lo |= 0x80;
if((SaveLo & 0x01) == 0x01)
{
CRC16Hi ^= CH;
CRC16Lo ^= CL;
}
}
}
Data.add(CRC16Lo & 0xff);
Data.add(CRC16Hi & 0xff);
}
public static void main(String[] args)
{
List<Integer> lst = new ArrayList<Integer>();
ReadHoldRegisters(lst, 1, 1, 10);
for (int value: lst)
{
System.out.print(String.format("%02x", value));
System.out.print(" ");
}
}
}
Related
I am trying to understand an implementation of a b+ Tree. I don't understand what this overloaded method exactly do. Why in the first method having Inputsteam is as an argument declare 4 variables which are i1,i2,i3 and i4. In the second method using ObjectInput in as an argument, i understand that it returns a byte from 0 to 255, why is result=251? It will be helpful to explain each line and what it do.
First method:
public final static int readLuposInt(final InputStream is) throws IOException {
final int i1 = is.read();
if (i1 < 0) {
return i1;
}
final int i2 = is.read();
if (i2 < 0) {
return i2;
}
final int i3 = is.read();
if (i3 < 0) {
return i3;
}
final int i4 = is.read();
if (i4 < 0) {
return i4;
}
return (0xFF & i1) | ((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8;
}
overloaded method:
public final static int readLuposInt(final ObjectInput in) throws IOException {
final int i0 = in.read();
if (i0 <= 251){
return i0;
}
int result = 251;
int offset = 1;
for (int i = 1; i <= i0 - 251; i++) {
result += in.read() * offset;
offset <<= 8;
}
return result;
}
You could have used a debugger to find the following result.
The first method reads an 4 byte integer from an input stream. It seems to be stored as little-endian value.
the bytes are read in sequentially
ff any of the bytes is missing, -1 is returned.
to return the complete integer, a computation is made by shifting the more significant bytes to the left.
Example:
The number 2293742 represents the hex number 22 FF EE, which will be stored in reverse order: 0xEE 0xFF 0x22 0x00
now the data gets read
i1 = 0xEE
i2 = 0xFF
i3 = 0x22
i4 = 0x00
now the return value is computed:
(0xFF & i4) << 8 = (0xFF & 0x00) << 8 = 0x0000
((0xFF & i3) | (0xFF & i4) << 8) << 8) = ((0x22 | 0x0000) << 8) = (0x0022 << 8) = 0x002200
((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8 = (0xFF | 0x002200) << 8 = 0x0022FF00
(0xFF & i1) | ((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8 = 0xEE | 0x0022FF00 = 0x0022FFEE
The second method reads unicode characters from the stream, encoded in an UTF-8 encoding. Much can be said about unicode and their character encodings, see Wikipedia how that is working.
This question already has answers here:
How to calculate crc16 in php
(2 answers)
Closed 8 years ago.
How to convert the Java CRC16 code to PHP code? PHP doesn't accept byte and >>>
public static int CRC16(final byte[] buffer) {
int crc = 0xffff;
for (int i = 0; i < buffer.length; i++) {
crc = ((crc >>> 8) | (crc << 8)) & 0xffff;
crc ^= (buffer[i] & 0xff);
crc ^= ((crc & 0xff) >> 4);
crc ^= (crc << 12) & 0xffff;
crc ^= ((crc & 0xff) << 5) & 0xffff;
}
crc &= 0xffff;
return crc;
}
Replace crc >>> 8 with (crc >> 8) & 0xff.
Let me start to say that I have no knowledge at all of Delphi...
I'm trying to port an old app written in delphi to java, but things aren't working...
I have this function that does some binary operation to two bytes. Here's the code in Delphi:
function TMainForm.mixthingsup(x, y: byte): word;
var
counter: byte;
answer1, answer2: byte;
begin
answer1 := $9D xor x;
for counter := 1 to 8 do
begin
if (answer1 and $80) = $80 then
answer1 := (answer1 shl 1) xor $26
else
answer1 := (answer1 shl 1);
end;
answer2 := answer1 xor y;
for counter := 1 to 8 do
begin
if ((answer2 and $80) = $80) then
answer2 := ((answer2 shl 1) xor $72)
else
answer2 := (answer2 shl 1);
end;
Result := (answer1 shl 8) or answer2;
end;
And here's my java code:
public static String mixthingsup(String data)
{
byte[] conv=null;
byte c9d;
byte c80;
byte c26;
byte c72;
byte x,y;
byte res1, res2;
byte res;
conv=hexStringToByteArray(data.substring(0, 2));
x=conv[0];
conv=hexStringToByteArray(data.substring(2, 4));
y=conv[0];
conv=hexStringToByteArray("9d");
c9d=conv[0];
conv=hexStringToByteArray("80");
c80=conv[0];
conv=hexStringToByteArray("26");
c26=conv[0];
conv=hexStringToByteArray("72");
c72=conv[0];
res1=(byte) (c9d ^ x);
for(int i=1; i<9; i++)
{
if((res1 & c80) == c80)
res1=(byte) ((res1 << 1) ^ c26);
else
res1=(byte) (res1 << 1);
}
res2=(byte) (res1 ^ y);
for(int i=1; i<9; i++)
{
if((res2 & c80) == c80)
res2=(byte) ((res2 << 1) ^ c72);
else
res2=(byte) (res2 << 1);
}
res=(byte) ((res1 << 8) | res2);
return Integer.toHexString(res);
}
When the delphi function returns CA BA for A8 77, for instance, the java function returns FF FF FF BA
Any thoughts? Any help?
Thanks,
Pedro
Look at this line:
res=(byte) ((res1 << 8) | res2);
When you cast it to byte you are truncating a 16 bit value into 8 bits and so lose res1.
You should cast to a 2 byte value, short.
That said, it might be easier just to return your two bytes in an array. Like this:
public static byte[] MixThingsUp(byte x, byte y)
{
byte answer1 = (byte) (0x9D ^ x);
for (int i=0; i<8; i++)
if ((answer1 & 0x80) == 0x80)
answer1 = (byte) ((answer1 << 1) ^ 0x26);
else
answer1 = (byte) (answer1 << 1);
byte answer2 = (byte) (answer1 ^ y);
for (int i=0; i<8; i++)
if ((answer2 & 0x80) == 0x80)
answer2 = (byte) ((answer2 << 1) ^ 0x72);
else
answer2 = (byte) ((answer2 << 1));
return new byte[] { answer1, answer2 };
}
If I were you I would separate the bitwise manipulations and the conversions to and from string. The way you have it in your question mixes the two concerns.
I'm trying to mask an integer in order to separate each byte individually like so:
int a = (0xffffffff & 0xff000000) >> 24;
int b = (0xffffffff & 0x00ff0000) >> 16;
int c = (0xffffffff & 0x0000ff00) >> 8;
int d = 0xffffffff & 0x000000ff;
b, c and d give the correct answer in this case, 255, however, a continues to give me -1 and other negative numbers no matter what I change it to, I even tried:
int a = (0xefffffff & 0xff000000) >> 24;
and it gives me -17.
Does someone know how do I solve this problem so that in this boundary case a gives me 255 and other positive numbers?
This is because of sign extension. If the top-most bit is 1, then >> shifts in 1s. This is to preserve the sign of the argument. You want to use >>> which always shifts in 0. Or, mask after the shift:
int a = (0xffffffff >> 24) & 0x000000ff;
You are doing a signed shift, so the sign is preserved.
int a = (0xffffffff & 0xff000000) >>> 24; // unsigned shift.
or
int a = 0xffffffff >>> 24; // unsigned shift and all the bottom bits are lost anyway
int b = (0xffffffff >>> 16) & 0xFF;
int c = (0xffffffff >>> 8) & 0xFF;
int d = 0xffffffff & 0xFF;
I think you need an unsigned shifting,
Try it this way...
(0xffffffff & 0xff000000) >>> 24
I have to convert bytes to signed/unsigned int or short.
The methods below are correct? Which is signed and which unsigned?
Byte order: LITTLE_ENDIAN
public static int convertTwoBytesToInt1(byte b1, byte b2) {
return (int) ((b2 << 8) | (b1 & 0xFF));
}
VS.
public static int convertTwoBytesToInt2(byte b1, byte b2) {
return (int) (( (b2 & 0xFF) << 8) | (b1 & 0xFF));
}
and
public static int convertFourBytesToInt1(byte b1, byte b2, byte b3, byte b4){
return (int) ((b4<<24)+(b3<<16)+(b2<<8)+b1);
}
VS.
public static int convertFourBytesToInt2(byte b1, byte b2, byte b3, byte b4){
return (int) (( (b4 & 0xFF) << 24) | ((b3 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b1 & 0xFF));
}
I'm interested only in this conversion forms. Thanks!
The first method (convertXXXToInt1()) of each pair is signed, the second (convertXXXToInt2()) is unsigned.
However, Java int is always signed, so if the highest bit of b4 is set, the result of convertFourBytesToInt2() will be negative, even though this is supposed to be the "unsigned" version.
Suppose a byte value, b2 is -1, or 0xFF in hexadecimal. The << operator will cause it to be "promoted" to an int type with a value of -1, or 0xFFFFFFFF. After the shift of 8 bits, it will be 0xFFFFFF00, and after a shift of 24 bytes, it will be 0xFF000000.
However, if you apply the bitwise & operator, the higher-order bits will be set to zero. This discards the sign information. Here are the first steps of the two cases, worked out in more detail.
Signed:
byte b2 = -1; // 0xFF
int i2 = b2; // 0xFFFFFFFF
int n = i2 << 8; // 0x0xFFFFFF00
Unsigned:
byte b2 = -1; // 0xFF
int i2 = b2 & 0xFF; // 0x000000FF
int n = i2 << 8; // 0x0000FF00
There is a problem with the 4-byte unsigned conversion, because it doesn't fit into an int. The routines below work correctly.
public class IntegerConversion
{
public static int convertTwoBytesToInt1 (byte b1, byte b2) // signed
{
return (b2 << 8) | (b1 & 0xFF);
}
public static int convertFourBytesToInt1 (byte b1, byte b2, byte b3, byte b4)
{
return (b4 << 24) | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
}
public static int convertTwoBytesToInt2 (byte b1, byte b2) // unsigned
{
return (b2 & 0xFF) << 8 | (b1 & 0xFF);
}
public static long convertFourBytesToInt2 (byte b1, byte b2, byte b3, byte b4)
{
return (long) (b4 & 0xFF) << 24 | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
}
public static void main (String[] args)
{
byte b1 = (byte) 0xFF;
byte b2 = (byte) 0xFF;
byte b3 = (byte) 0xFF;
byte b4 = (byte) 0xFF;
System.out.printf ("%,14d%n", convertTwoBytesToInt1 (b1, b2));
System.out.printf ("%,14d%n", convertTwoBytesToInt2 (b1, b2));
System.out.printf ("%,14d%n", convertFourBytesToInt1 (b1, b2, b3, b4));
System.out.printf ("%,14d%n", convertFourBytesToInt2 (b1, b2, b3, b4));
}
}