Search code examples
arraysarduinobytearduino-c++

Is there an efficient way to compare these arrays?


I have a NFC scanner that obtains a tag's UID and stores it in byte TagReadB[4].

I then need to compare it to a large number of other byte arrays to see if it matches with them (i.e. if it's a recognised tag).

The recognised tags are stored like this.

uint8_t RED1[4] = {0x15, 0x4C, 0xA9, 0xFB};
uint8_t RED2[4] = {0x67, 0xFC, 0x8A, 0x16};
uint8_t RED3[4] = {0xB7, 0xC4, 0xEA, 0xA4};
uint8_t RED4[4] = {0xE7, 0x32, 0xE7, 0xA4};
uint8_t RED5[4] = {0x87, 0x33, 0xED, 0x74};
uint8_t RED6[4] = {0xB7, 0x56, 0xFA, 0xA4};
uint8_t RED7[4] = {0xB5, 0x8A, 0xB6, 0xFB};
uint8_t RED8[4] = {0x07, 0xA6, 0xF3, 0xA4};
uint8_t RED9[4] = {0xE5, 0xB2, 0x9E, 0xFB};
uint8_t RED10[4] = {0x87, 0xF8, 0x8A, 0x16};
uint8_t RED11[4] = {0x47, 0x93, 0xDA, 0xA4};
uint8_t RED12[4] = {0x87, 0x1D, 0x8A, 0x16};
uint8_t RED13[4] = {0x85, 0x83, 0xB1, 0xFB};
uint8_t RED14[4] = {0x55, 0x33, 0x9C, 0xFB};
uint8_t RED15[4] = {0x45, 0x39, 0xB7, 0xFB};
uint8_t RED16[4] = {0xA5, 0xED, 0xA5, 0xFB};
uint8_t RED17[4] = {0x85, 0x6E, 0xA1, 0xFB};
uint8_t RED18[4] = {0x17, 0xC3, 0xEF, 0xA4};
uint8_t RED19[4] = {0x37, 0xCA, 0xEB, 0xA4};
uint8_t RED20[4] = {0x15, 0x66, 0xA0, 0xFB};
uint8_t YELLOW1[4] = {0x27, 0x44, 0x73, 0xE5};
uint8_t YELLOW2[4] = {0xD7, 0x44, 0xCB, 0xE2};
uint8_t YELLOW3[4] = {0x87, 0x6E, 0x78, 0xE5};
uint8_t YELLOW4[4] = {0x27, 0x49, 0x63, 0xE5};
uint8_t YELLOW5[4] = {0xA7, 0x0D, 0x6C, 0xE5};
uint8_t YELLOW6[4] = {0x87, 0x96, 0x69, 0xE5};
uint8_t YELLOW7[4] = {0x37, 0xF9, 0xCA, 0xE2};
uint8_t YELLOW8[4] = {0xD7, 0xAE, 0xCB, 0xE2};
uint8_t YELLOW9[4] = {0xA7, 0xE3, 0x78, 0xE5};
uint8_t YELLOW10[4] = {0x47, 0x72, 0x90, 0xE5};
uint8_t BLUE1[4] = {0x73, 0xD5, 0xB7, 0xAC};
uint8_t BLUE2[4] = {0x1D, 0x5D, 0xFC, 0x69};
uint8_t BLUE3[4] = {0xBD, 0xEC, 0x8F, 0x12};
uint8_t BLUE4[4] = {0xE6, 0x9F, 0x54, 0x73};
uint8_t BLUE5[4] = {0x38, 0x74, 0x7E, 0x33};
uint8_t BLUE6[4] = {0x6D, 0x05, 0x3E, 0x12};
uint8_t BLUE7[4] = {0x9C, 0x6B, 0x4A, 0x73};

I can do the following but there must be an easier way without having to repeat 20 OR statements?

if (!memcmp(TagReadB, RED1, 4) || !memcmp(TagReadB, RED2, 4) || ...)    {

        //do something

    }

Even better, it would be great to test on what colour of the recognised tag it matches with because there will be the same action for each colour.

e.g. if it's a red tag do x, yellow tag do y, blue tag do z.

Many thanks.


Solution

  • You could store the tags in multidimensional arrays:

    uint8_t RED_TAGS[][4] = {
        {0x15, 0x4C, 0xA9, 0xFB},
        {0x67, 0xFC, 0x8A, 0x16},
        ...
    };
    
    uint8_t YELLOW_TAGS[][4] = {
        {0x15, 0x4C, 0xA9, 0xFB},
        {0x67, 0xFC, 0x8A, 0x16},
        ...
    };
    
    uint8_t BLUE_TAGS[][4] = {
        {0x15, 0x4C, 0xA9, 0xFB},
        {0x67, 0xFC, 0x8A, 0x16},
        ...
    }
    

    Now you can check if a tag is in one of the multidimensional arrays using a for loop:

    int is_tag_in_array(uint8_t array[][4], int size, uint8_t tag[4]) {
        for (int i=0;i<size;i++) {
            if (memcmp(array[i], tag, 4) == 0)
                return 1;
        }
        return 0;
    }
    

    This way you can check for the color like this:

    if (is_tag_in_array(RED_TAGS, 20, TagReadB)) {
        // Do something for a red tag
    } else if (is_tag_in_array(YELLOW_TAGS, 10, TagReadB)) {
        // Do something for a yellow tag
    } else if (is_tag_in_array(BLUE_TAGS, 7, TagReadB) {
        // Do something for a blue tag
    } else {
        // Didn't match any color
    }