touch pad door lock with two phase authentication

Dependencies:   PinDetect mbed

Dependents:   IoT

main.cpp

Committer:
jsmith352
Date:
2015-11-24
Revision:
0:04dcbfb4388c

File content as of revision 0:04dcbfb4388c:

#include <mbed.h>
#include <mpr121.h>
#include <stdlib.h>
#include "PinDetect.h"

/* CODE_LENGTH needs to be double the amount of numbers you
      want in your authenticator/passcode because of the way interrupt.fall(&fallInterrupt)
      works. It is called twice every time an interrupt is detected.
      The extra numbers in the array will just be filled with zeros and ignored in checking 
      code sequences, so they will not matter either way */
      /* i.e, you want a code with 7 numbers, CODE_LENGTH needs to be 14 */
#define CODE_LENGTH 14

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

DigitalOut doorlock(p29);

// Create the interrupt receiver object on pin 26
InterruptIn interrupt(p30);

// Setup the i2c bus on pins 9 and 10
I2C i2c(p9, p10);

// Setup the Mpr121:
// constructor(i2c object, i2c address of the mpr121)
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);

// pc serial communication for testing
Serial pc(USBTX, USBRX);

// ***** GLOBALS ***** //
// Timer is to seed rand
Timer t1;
// code counter is the next position in inputCode array
int codeCounter;
// inputCode array is the sequence of numbers the user will enter
int inputCode[CODE_LENGTH];
bool code_enabled;
 
// Key hit/release interrupt routine
void fallInterrupt() {
    int key_code=0;
    int i=0;
    int value=mpr121.read(0x00);
    value +=mpr121.read(0x01)<<8;
    // LED demo mod
    i=0;
    // puts key number out to LEDs for demo
    for (i=0; i<12; i++) {
    if (((value>>i)&0x01)==1) key_code=i+1;
    }
    led4=key_code & 0x01;
    led3=(key_code>>1) & 0x01;
    led2=(key_code>>2) & 0x01;
    led1=(key_code>>3) & 0x01;
  
    // save the keypress to inputCode array
    if(codeCounter < CODE_LENGTH){
        // ignore odd numbers
        if(codeCounter % 2 != 0){
            inputCode[codeCounter] = 0;
        }
        // only save the even numbers (see lines 6-10)
        else{
            inputCode[codeCounter] = key_code - 1;
            pc.printf("codeCounter: %d  --  code:  %d\n\r", codeCounter, key_code - 1);
        }      
        codeCounter++;
    }
}

// generate randomized code
void generate_random_code(int (&codeArray)[CODE_LENGTH]){
    int i = 0;
    // only care about the even numbers (see lines 6-10)
    pc.printf("NEW CODE: ");
    for(i = 0; i < CODE_LENGTH; i+=2){
        srand(t1.read_us());
        codeArray[i] = rand() % 12;
        pc.printf("%d,  ", codeArray[i]);
    }
    pc.printf("\n\r");
}

// check if the code entered is the correct code
bool check_code_sequence(int (&codeArray)[CODE_LENGTH]){
    int i = 0;
    int j = 0;
    // only care about the even numbers (see lines 6-10)
    for(i = 0; i < CODE_LENGTH; i+=2){
        if(inputCode[i] == codeArray[i])
        j++; // count the number of right numbers
    }
    if(j == CODE_LENGTH/2)
        return(true);
    else
        return(false);
}
 
int main() {
    interrupt.fall(&fallInterrupt);
    interrupt.mode(PullUp);
    
    // authenticator is the randomly generated sequence of numbers by the machine
    // the user has to match this sequence to gain access, used for phase 2
    int authenticator[CODE_LENGTH];
    // passcode is the user's personal passcode, used for phase 1
    int passcode[CODE_LENGTH] = {0,0,1,0,2,0,3,0,4,0,5,0,6,0};
    codeCounter = 0;
    bool pass = false;
    
    // these 2 variables tell the machine when to generate a new random authentication code
    int new_code_timer = 0;
    int new_code_counter = 0;
    // this tells the state machine with phase of authentication we are in
    code_enabled = false;
    
    for(int i = 0; i < CODE_LENGTH; i++){
      authenticator[i] = 0;
      inputCode[i] = 0;
    }
    
    // go ahead and start the timer so that when a random code is generated,
    // the seed will always be random, unlike the predecessor version
    t1.start();
    
    // while loop constantly checks if the entered code sequence is right or wrong,
    // given that the correct amount of numbers were entered
    pc.printf("Please Enter Your Personal Security Code\n\r");
    while (1){
        switch(code_enabled){
            case false:
                if(codeCounter >= CODE_LENGTH){
                    pass = check_code_sequence(passcode);
                    if(pass == true){
                        pc.printf("SENDING AUTHENTICATION CODE...\n\r");
                        generate_random_code(authenticator);
                        t1.stop(); // reset the time
                        t1.reset(); // so that it is an even
                        t1.start(); // 30 seconds before 1st new code is generated
                        codeCounter = 0;
                        code_enabled = true;
                    }
                    else{
                        pc.printf("WRONG passcode\n\r");
                        codeCounter = 0;
                    }
                }
                break;
            case true:
                if(codeCounter >= CODE_LENGTH){
                    pass = check_code_sequence(authenticator);
                    if(pass == true){
                        pc.printf("ACCESS GRANTED\n\r");
                        doorlock = 1;
                        wait(5);
                        doorlock = 0;
                        pc.printf("Resetting....\n\r");
                        pc.printf("\n\n\rPlease Enter Your Personal Security Code\n\r");
                        codeCounter = 0;
                        code_enabled = false;
                    }
                    else{
                        pc.printf("ACCESS DENIED\n\r");
                        codeCounter = 0;
                    }
                }
                // this code generates a new authentication code every 30 seconds (30000 ms)
                new_code_timer = (int)(t1.read_ms()/30000);
                if(new_code_timer > new_code_counter){
                    new_code_counter++;
                    generate_random_code(authenticator);
                    codeCounter = 0;
                }
                break;
        }
        // reset the timer when the number gets too high, should last about 35 minutes
        //  We do this because int can only hold a number up to 2^32 - 1, preventing errors
        if(t1.read_us() > 2147400000){
            t1.stop();
            t1.reset();
            new_code_timer = 0;
            new_code_counter = 0;
            t1.start();
        }
    }
}