mattjlewis / diozero

Java Device I/O library that is portable across Single Board Computers and microcontrollers. Tested with Raspberry Pi, Odroid C2, BeagleBone Black, Next Thing CHIP, Asus Tinker Board and Arduinos / Pico. Supports GPIO, I2C, SPI as well as Serial communication. Also known to work with Udoo Quad.
https://www.diozero.com
MIT License
256 stars 59 forks source link

MFRC522 - The change uid example does not work. #112

Closed kyngs closed 1 year ago

kyngs commented 1 year ago

After solving #111, when I attempt to run it, I get this error: 17:38:49.051 [main] ERROR com.diozero.devices.MFRC522.mifareSetUid - MIFARE_Write() failed: TIMEOUT

I've found out that this status originates from: https://github.com/mattjlewis/diozero/blob/1d2c229c31e865437b31e1152fa8f450eb5d19f4/diozero-core/src/main/java/com/diozero/devices/MFRC522.java#L1769-L1771

I have no idea what to do with it :<

mattjlewis commented 1 year ago

The MFRC522 code needs a bit of an overhaul I think…

kyngs commented 1 year ago

Yeah, I am a bit confused how it works. It uses byte[] for reading and writing, but considering Java uses signed bytes I am not sure how I should input values over 127

EAGrahamJr commented 1 year ago

I think you're conflating int and byte - when working at this level, it's usually just easier to work with hex, rather than decimal.

byte biggerThanThat = 0xFA; // decimal 250
output.write(biggerThanThat);
kyngs commented 1 year ago

I think you're conflating int and byte - when working at this level, it's usually just easier to work with hex, rather than decimal.

byte biggerThanThat = 0xFA; // decimal 250
output.write(biggerThanThat);

The issue is, you cannot do that. Because 0xFA is an integer, therefore you need to cast it to a byte. source:

public static void main(String[] args) {
        byte b = (byte) 0xFA;
        System.out.println(b);
    }

output:

-6 //For some reason
kyngs commented 1 year ago

Maybe I am wrong, but I will try replacing all the bytes with ints and see whether it works.

mattjlewis commented 1 year ago

Reading and writing bytes is fine - the sign bit only becomes relevant when attempting to manipulate the numbers, e.g. add, subtract, multiply. diozero uses bytes for the vast majority of devices just fine. Quite often need to convert to an int to manipulate, just need to make sure you mask with 0xff (& 0xff).

mattjlewis commented 1 year ago

So if you do:

public static void main(String[] args) {
  byte b = (byte) 0xFA;
  System.out.println(b);
  System.out.println(b & 0xff);
}

you will get -6 and 250.

kyngs commented 1 year ago

While I understand that it is possible, is there any reason to do this instead of using ints? I guess you save a bit of memory, but IMO it is not worth it.

Anyway, back to the original topic, do you have any idea how to fix this?

mattjlewis commented 1 year ago

The reason is that there are specific low-level interfaces for reading and writing byte values. In some cases (I2C) there are also low-level interfaces for reading/writing short values.

On the original topic - once I clear my current backlog I will dig out relevant hardware and do some testing / updates. In the meantime, can you clarify what does and doesn't work currently please.

kyngs commented 1 year ago

The reason is that there are specific low-level interfaces for reading and writing byte values. In some cases (I2C) there are also low-level interfaces for reading/writing short values.

On the original topic - once I clear my current backlog I will dig out relevant hardware and do some testing / updates. In the meantime, can you clarify what does and doesn't work currently please.

Please provide me a list of all methods I should test, thanks. IIRC authenticating and reading ID worked correctly, I can test more. Thanks for your help

kyngs commented 1 year ago

OK, so I found the HW I used to test this. It appears that the unbrick function works, indicating that the issue must be the payload used in the write in the change uid function

EDIT: Interestingly, after using the unbrick function it changes the device type from MIFARE_1K to MIFARE_UL EDIT2: When modifying the payload in the unbrick function and setting it to the UID block from my other card, it shows again as MIFARE_1K and also with the same UID as the other card. Thus solving my original issue. I'm going to try to find out the issue with the modify UID function