-1

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?

Machado
  • 14,105
  • 13
  • 56
  • 97
  • Have you done any debugging? I expect you won't like me asking that question, but somebody needs to ask it. All you need to do, is to add diagnostics to both programs to observe the values being used at each step of the way. At some point the programs will diverge. Dig deeper until the problem becomes clear. I said this to you yesterday. If you had done what I said then you would have solved this already. I say this from experience of doing just that. – David Heffernan Jan 29 '15 at 14:23
  • Well David, I did actually. If you drop off the line if ((SaveHi & andop2) == andop2 ) CRC16Lo |= 0x80 & 0xff; depending on the input values it will work the very same way. Another thing is that the loop is running 3 or 1 more times, depending on the code block 1 fewer time, etc. – Machado Jan 29 '15 at 15:30
  • Did you log the intermediate values like I said? That would have shown the discrepancy in the flag loop execution count. 8 times in Delphi, 7 in your Java code. – David Heffernan Jan 29 '15 at 15:35
  • Yes. I did it yesterday and got 8 times in Java and 7 times at Delphi, maybe I made a mistake on the paper. – Machado Jan 29 '15 at 15:38
  • I believe I'm close to solving this but I'm stuck. – Machado Jan 29 '15 at 15:49
  • 1
    Please don't change the question by incorporating the fixes that have appeared in answers. That makes the answers look stupid. – David Heffernan Jan 29 '15 at 15:53

1 Answers1

2

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(" ");
        }
    }

}
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Well, I agree that was a dummy mistake and I appreciate for your help. The loop error is solved, , but it still doesn't works – Machado Jan 29 '15 at 15:37
  • What's the meaning of "12, 8768 and 12434" at ReadHoldRegisters(lst, 12, 8768, 12434) ? – Machado Jan 29 '15 at 15:55
  • Input data. I had to feed some data in. You didn't tell me what input data you were using. – David Heffernan Jan 29 '15 at 15:56
  • Oh sorry. Thought I had it included on the code. It is ReadHoldRegisters(lst, 1, 1, 10). – Machado Jan 29 '15 at 15:58
  • Yesss you nailed it! I'm sorry if I looked stupid a few times but I'm learning.. I was debugging too! But I've been trying to solve this for such a long time that I started to feel like my mind was stuck, if you ever had that feel. I wish I could upvote 10 times. Thanks – Machado Jan 29 '15 at 16:11
  • I know how you feel. Really laborious println debugging is the best way to tackle problems like this. You do need to keep a clear hard, which can be tricky when you've been staring at the same code for a long time. – David Heffernan Jan 29 '15 at 16:13