rfid lock build to interface with mf7 rfid reader using white / black list

Dependencies:   mbed

main.cpp

Committer:
pwheels
Date:
2011-02-09
Revision:
0:c9e183da8303

File content as of revision 0:c9e183da8303:

/*
 * Copyright (c) 2011 Paul van der Wielen, Pro-Serv
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to use
 * and implement the software for none commercial reason and usage only and
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Usage and assumptions:
 * a RFID reader Model MF7(1.05) is configured in ascii mode and attached to p10 via
 * a level converter (rs232 at ttl level to 3.3V), which also inverses the signal
 * The imbedded local drive holds a white list and black list file in csv format.
 * Operation signalling is available via default LED 1-4 being:
 * LED1 - access granted, LED2 - access denied, LED3 - door unlocked, LED4 - file reading
 *
 * the white list master card should be at white[0], being first entry in white list csv file
 * while the black list master card should be at white[1], being second entry in white list csv
 * file, mind these two card DON'T provide access and/or door unlocking operations
 *
 * Used device = LPC1768, basic logging is availabe as needed on the serial to usb port via
 * terminal emulator like Tera, extend logging or debugging data is available by uncomment
 * the #define DEBUG statement
 */

#include "mbed.h"
#include <string.h>

//#define DEBUG

Serial pc(USBTX, USBRX); // tx, rx
Serial device(p9, p10);  // tx, rx
LocalFileSystem local("local");

const char *wl = "/local/list_wht.csv";
const char *bl = "/local/list_blk.csv";

const char *ver = "V1.1";

/*
 * In order to assure proper white & black list operation we assume to
 * have the master card for white & black list to be at index 0 and 1 resp.
 */
unsigned long white[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0
                           };

unsigned long black[64]  = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
                            0,0,0,0,0,0,0,0,0,0,0,0,0
                           };

unsigned int hex2int(char a);
bool rfid_match_wl( unsigned long b);
bool rfid_match_bl( unsigned long b);
int add_card(const char *ft, char *xx);
int get_list(const char *ft, unsigned long *xx);

void    memdump( char *p, int n );

char rfid[10];
char buffer[32];

unsigned char tmp;
int cnt = 0;
int pnt = 0;
int mst = 0;    // usage format abxxxxxn where a = white, b = black operation, n indicates second step

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);

int main() {

#ifdef DEBUG
    char    mem[ 1024 ];    //  memory, it should be aligned to word boundary
#endif

    float release = 7.0;
    unsigned long val = 0;

    printf( "\r\nRFID Lock System, version: %s\r\n", ver);
    printf( "  CPU running %dkHz\r\n", SystemCoreClock / 1000 );

    cnt = get_list(wl, white);
#ifdef DEBUG
    memcpy(&mem, &white, 1024);

    printf( "Showing `White List` content ...\r\n" );
    memdump( mem, 256 * 4 );
#endif
    printf( "Started with %d known RFID 'White list' cards\r\n\n", cnt);

    cnt = get_list(bl, black);
#ifdef DEBUG
    memcpy(&mem, &black, 256);

    printf( "Showing `Black List` content ...\r\n" );
    memdump( mem, 256 * 1 );
#endif
    printf( "Started with %d known RFID 'Black list' cards\r\n\n", cnt);

    while (1) {
        if (device.readable()) {
            tmp = device.getc();
            switch (tmp) {
                case 0x02:
                    cnt = 0;
                    val = 0;
                    break;
                case 0x03:
                    rfid[cnt++] = 0x00;
                    val = strtoul(rfid, 0, 16);
#ifdef DEBUG
                    pc.printf("%s  %u", rfid, val ); // define for debug mode
#endif
                    pc.printf("%s", rfid );
                    if ((rfid_match_wl(val)) && !(rfid_match_bl(val)) && (mst == 0x00)) {
                        // green led - access provided
                        myled1 = 1;
                        // activate lock for 'release' time duration
                        myled3 = 1;
                        // we will need to add a defenition for DigitalOut here
                        wait(0.25);
                        myled1 = 0;
                        wait(release-0.25);
                        myled3 = 0;
                        // we will need to add a defenition for DigitalOut here
                        pc.printf(" -> Granted\r\n" );
                    } else {
                        if (mst == 0x81) {
                            // master mode, add new card to white list
                            white[cnt++] = val;
                            mst = 0;
                            pc.printf(" -> Card added\r\n" );
                            if (add_card(wl, rfid) != 0) {
                                pc.printf("%s -> WL Add Failed\r\n", rfid );
                            }
                        } else if (mst == 0x41) {
                            // master mode, add new card to white list
                            black[cnt++] = val;
                            mst = 0;
                            pc.printf(" -> Card Removed\r\n" );
                            if (add_card(bl, rfid) != 0) {
                                pc.printf("%s -> BL Remove Failed\r\n", rfid );
                            }
                        } else {
                            // red led - no access
                            myled2 = 1;
                            wait(0.25);
                            myled2 = 0;
                            if (mst == 0x80) {
                                pc.printf(" -> White List Mode!\r\n");
                            } else if (mst == 0x40) {
                                pc.printf(" -> Black List Mode!\r\n");
                            } else {
                                pc.printf(" -> Denied !\r\n" );
                            }
                        }
                    }
                    break;
                case 0x0a:
                case 0x0d:
                    break;
                default:
                    // data from MF7 (ascii mode) is in `litle endian` format, so need
                    // to swap groups but, we will store rfid card as a value
                    // char array addressing = [group + count - count offset]
                    switch (cnt) {
                        case 0x00:
                        case 0x01:
                            rfid[6 + cnt] = tmp;
                            break;
                        case 0x02:
                        case 0x03:
                            rfid[4 + cnt - 2] = tmp;
                            break;
                        case 0x04:
                        case 0x05:
                            rfid[2 + cnt - 4] = tmp;
                            break;
                        case 0x06:
                        case 0x07:
                            rfid[0 + cnt - 6] = tmp;
                            break;
                    }
                    cnt++;
            }
        }
    }
}
/*
 * All used functions are listed below
 *
 * function to add a card to selected list (black or white)
 */
int add_card(const char *ft, char *xx) {

    FILE *fp;

    if ((fp = fopen(ft, "a")) == NULL)  {
        fprintf(stderr, "File %s could not be opened!\r\n", ft);
        return -1;
    }
    fprintf(fp,"%s\r\n", xx);
    fclose(fp);
    return 0;
}

/*
 * function to read initial content for selected list (black or white)
 */
int get_list(const char *ft, unsigned long *xx) {

    FILE *fp;

    if ((fp = fopen(ft, "r")) == NULL)  {
        fprintf(stderr, "File %s could not be opened!\r\n", ft);
        return 0;
    } else {
        cnt = pnt = 0;
        printf("Reading Data File...\r\n");
        // reading file content
        while ((tmp = getc(fp)) != 0xff) {
            switch (tmp) {
                case 0x0d:
                    myled4 = 1;
                    rfid[pnt++] = 0x00;
                    xx[cnt++] = strtoul(rfid, 0, 16);
#ifdef DEBUG
                    printf( "  %s !\r\n", rfid); // define for debug mode
#endif
                    pnt = 0;
                    myled4 = 0;
                    break;
                case 0x0a:
                    break;
                default:
                    rfid[pnt++] = tmp;
                    break;
            }
        }
        printf("Closing Data File...\r\n");
        fclose(fp);
    }
    return cnt;
}

/*
 * function to match current card against selected white list
 */
bool rfid_match_wl( unsigned long myval) {
    int i;

    if (( mst == 0x80 ) || ( mst == 0x40 )) {
        mst++;
    }
    for (i = 0; i < sizeof(white)/sizeof(white[0]); i++) {
        if (white[i] == myval) {
            // if master card (being first in list) is presented twice ! -> add new card
            if (( i == 0 ) && (mst == 0)) {
                mst = 0x80;
            } else if (( i == 1 ) && (mst == 0)) {
                mst = 0x40;
            } else {
                ;
            }
#ifdef DEBUG
            pc.printf("%u  %u\r\n", white[i], i); // define for debug mode
#endif
            return true;
        }
    }
    return false;
}

/*
 * function to match current card against selected black list
 */
bool rfid_match_bl( unsigned long myval) {
    int i;

    for (i = 0; i < sizeof(black)/sizeof(black[0]); i++) {
        if (black[i] == myval) {
            return true;
        }
    }
    return false;
}

/*
 * function to convert single character value it's decimal value
 */
unsigned int hex2int(char a) {
    unsigned int val = 0;

    if ((int)a <= 57)
        val = ((int)a-48);
    else
        val = ((int)a-55);
    return val;
}

/*
 * function to dump specific memory block
 */
void memdump( char *base, int n ) {
    unsigned int    *p;

    printf( "  memdump from 0x%08X for %d bytes", (unsigned long)base, n );

    p   = (unsigned int *)((unsigned int)base & ~(unsigned int)0x3);

    for ( int i = 0; i < (n >> 2); i++, p++ ) {
        if ( !(i % 4) )
            printf( "\r\n  0x%08X :", (unsigned int)p );

        printf( " 0x%08X", *p );
    }

    printf( "\r\n" );
}