In my project, I need to make readable 96-bit UID. In STM32F0xx reference manual RM0091 section 33.1 Unique device ID register, it is described how the number is encoded:

struct Uid {
    uint16_t X;  // x-coordinate
    uint16_t Y;  // y-coordinate
    uint8_t WAF;  // Wafer number
    char LOT[7];  // Lot number

My question is how x and y coordinates are encoded, if 0x0000 is in middle of wafer or one side?

Here are some examples which I see in X-coordinate: 0x0000, 0x0001, 0x0006, 0x8001, 0x8004, 0x801f, .... some numbers have the MSB bit set.

In Y-coordinate I always see numbers where MSB is NOT set, like: 0x0001, 0x0003, 0x0005, 0x001f, 0x0030, 0x003f, ...

I don't have so many samples to read many numbers and get better statistics of numbering so my question is: what does it mean if a number has the MSB bit set in the coordinate? I think that this is sign, but I'm not sure.

The reason why I am interested about this, is that I need to decrease the size of this number and remove some bits from this UID. My idea is to remove bits 11-14 from each coordinate to keep position and (probably) sign and make this number smaller and still unique. I need to decrease it by 8 bits only.

MCU is STM32F0xx

UPDATE: I have small statistic from 75 pcs of STM32F031 and here are unique values for:

X: 0003, 0008, 0009, 000a, 000b, 000e, 0010, 0013, 0014, 0015, 0016, 0018, 001c, 0021, 0024, 002a, 8001, 8002, 801b, 801c, 801d, 8020
Y: 0003, 0005, 0006, 0007, 000c, 000f, 0010, 0011, 0013, 0014, 0016, 0017, 0018, 0019, 001a, 001b, 001e, 001f, 0020, 0022, 0024, 0028, 0029, 002a, 002c, 002d, 002e, 0030, 0032, 0033, 0034, 0035, 0037, 0038, 0039, 003a, 003c, 003f, 0042, 0044, 0045, 0046, 0047, 0048, 0049, 004b, 004e
WAF: 0b, 0c, 0d, 0e, 18

Seems that X and Y and WAFER is not BCD but HEX and MSB bit in X coordinate will be probably be sign.

  • 2
    \$\begingroup\$ It says that X and Y are expressed in BCD format. So the mentioned 0x801f can't be right. Also I don't think you can reduce this number and maintain it unique. There is a reason 96 bits were selected. You might be able to compress it though... \$\endgroup\$
    – Eugene Sh.
    Commented Nov 7, 2017 at 14:52
  • \$\begingroup\$ Stumbled over here because of me, too, discovering some coordinate value appearing invalid (0x000B). RM says using BCD format, couldn't find, though, which one. F appearing as nimble value hints to 4221 format being used (so F corresponding to 9, E to 8, B to 7 as would D as well). Can anyone confirm? \$\endgroup\$
    – Aconcagua
    Commented Sep 24, 2018 at 8:47
  • \$\begingroup\$ As for compression (if yet of relevance): Lot number seems to contain only digits and upper case ASCII letters ([0-9A-Z]), so could be considered a base36-encoded number; strtoull should be fine for decoding as 36^7 fits into 5 bytes -> sparing two bytes already; be aware that there might be leading space, though, which would have to be considered 0... \$\endgroup\$
    – Aconcagua
    Commented Sep 24, 2018 at 8:59
  • 1
    \$\begingroup\$ @Aconcagua, I added more samples and seems that these numbers are hexadecimal. \$\endgroup\$
    – vlk
    Commented Sep 24, 2018 at 10:57
  • 4
    \$\begingroup\$ @vlk I won't write an answer because it is not authoritative, but it seems it may be a mistake in the manual: community.st.com/s/question/0D50X00009XkeO9SAJ/… \$\endgroup\$
    – dim
    Commented Sep 24, 2018 at 13:31

2 Answers 2


My question is how x and y coordinates are encoded

You don't actually care how they are encoded. They are just a source of unique bits. You take the whole Uid and hash it and then use the hash. The hash can be trimmed to a length that is reasonable for your expected number of units sold over the lifetime of the device, and for the number of usable bits or nibbles in the Uid.

Since the Uid is 12 bytes long, you don't need to use more than 24 hex digits of the hash. Since you discovered that there are at least 4 nibbles that are unused across the X, Y and WAF fields, so 20 hex characters out of a longer hash will be plenty for collision-free mapping from Uid to a hash. Realistically, given that you're probably not selling billions of those devices, 16 hex characters or 8 bytes of the hash is all you'll need.

If this is for licensing purposes then also remember that hash collisions will be inconsequential. The likelihood that the same customer gets two different units with the same partial hash is so low, that you may as well let them enjoy this as a gesture of good will. It won't ever happen in practice.


If all you need to reduce number of bits, but don't know which ones are significant, you can always "xor" them together. for example, xor upper and lower bytes: 0x801f -> 0x80 ^ 0x1f = 0x9f

This requires that your high and low bytes are independent (for example if numbers have a step of 0x101, then the algorithm would not work well). But from your data, it looks like you will be fine.

  • 8
    \$\begingroup\$ It won't guarantee that the resulting number will still be unique per chip, unless you can guarantee, for example, that the first byte will always be 0x80 or 0x00 and that the second will be <= 0x7f. But the spec does not give strong guarantee on that, and seems even inconsistent with the actual values. As I understand the question, this is the problem OP is having: in which range the values are (to ensure strong guarantees on unicity), it is not in how to combine them (this is the easy part). \$\endgroup\$
    – dim
    Commented Sep 24, 2018 at 20:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.