Mobile Security System - Revision 1.0

Dependencies:   FXOS8700Q N5110 SDFileSystem SRF02 mbed

main.cpp

Committer:
el14dg
Date:
2016-05-03
Revision:
8:8a3d1c07bdec
Parent:
7:8ac5aee0c13e
Child:
9:a5614f53d435

File content as of revision 8:8a3d1c07bdec:

/* ELEC2645 Project */

#include "main.h"

int main()
{

    init_serial(); // set up UART connection with PC for debugging
    init_K64F(); // set up K64F on board LEDs and switches
    init_buttons(); // set up the three external buttons
    init_variables(); // initialise all variables to 0
    lcd.init(); // initialise the Nokia 5110 LCD

    read_pin(); // read current pin from the SD card to the set_pin array

    buzzer.period(1.0/500.0); // set the buzzer period - 500 Hz

    buzzer.write(0.5); // duty cycle = 0.5 ----> Square Wave

    wait(2); // wait two seconds to allow LCD to initialise

    screen_selection(); // initial screen

    wait(4);

    g_next_state = 1;

    screen_selection(); // menu screen

    g_current_state = 1;


    while (1) {


        if (g_button_0_flag) { // if button_0 is pressed

            pc.printf("g_button_0_flag = %d \n", g_button_0_flag);

            g_button_0_flag = 0;

            button_0_protocol();

        }

        if (g_button_1_flag) { // if button_1 is pressed

            pc.printf("g_button_1_flag = %d \n", g_button_1_flag);

            g_button_1_flag = 0;

            button_1_protocol();

        }

        if (g_button_c_flag) { // if button_c is pressed

            pc.printf("g_button_c_flag = %d \n", g_button_c_flag);

            g_button_c_flag = 0;

            button_c_protocol();

        }

        if (g_setting_distance_flag) { // state 4 - initial setting distance

            g_setting_distance_flag = 0;

            get_setting_distance();

        }

        if (g_intruder_distance_flag) { // state 5 - current distance compared to initial setting distance

            g_setting_distance_flag = 0;

            get_intruder_distance();

        }

        if (g_setting_screen_flag) { // state 4 loading bar and percentage animation

            g_setting_screen_flag = 0;

            setting_animation();

        }

        if (g_led_buzzer_flag) { // toggles LED and buzzer

            g_led_buzzer_flag = 0;

            led_alarm = !led_alarm;

            if (buzzer == 0) {

                buzzer = 0.5;

            }

            else {

                buzzer = 0;

            }                   

        }
        
        if (g_acc_flag) {
            
            g_acc_flag = 0;
            
            if (g_current_state == 4) {
                
                compare_axis_data();
                
            }
            
        }    

        if (g_pin_timeout_flag) { // state 7 - 20 second timeout

            g_pin_timeout_flag = 0;

            timeout_protocol();

        }

        if (g_next_state != g_current_state) {

            pc.printf("TRANSITION \n");

            screen_selection(); //  the screen is determined by the value of g_next_state

            g_current_state = g_next_state;

            pc.printf("Current State = %d \n",g_current_state);

        }

        sleep();


    }

}


// Initialisation Functions

void init_serial()
{
    // Ensure terminal software matches
    pc.baud(115200);
}

void init_K64F()
{
    // on-board LEDs are active-low, so they are set high to turn them off.
    r_led = 1;
    g_led = 1;
    b_led = 1;

    // since the on-board switches have external pull-ups, we should disable the internal pull-down
    // resistors that are enabled by default using InterruptIn
    sw2.mode(PullNone);
    sw3.mode(PullNone);

}

void init_buttons()
{
    // all external buttons trigger the relevant ISR when the voltage at the K64F pin falls
    button_0.fall(&button_0_isr);
    button_1.fall(&button_1_isr);
    button_c.fall(&button_c_isr);

    // enable the internal pull-down resistors
    button_0.mode(PullDown);
    button_1.mode(PullDown);
    button_c.mode(PullDown);

}

void init_variables()
{

    one_second_distance = 0;
    one_second_avg_distance = 0;
    initial_setting_distance = 0;

    pin_counter = 0;
    incorrect_pin_flag = 0;

    setting_distance_counter = 0;
    intruder_distance_counter = 0;

    g_button_0_flag = 0;
    g_button_1_flag = 0;
    g_button_c_flag = 0;
    g_setting_distance_flag = 0;
    g_intruder_distance_flag = 0;
    g_pin_timeout_flag = 0;

    g_current_state = 0;

    reset_entered_pin();
    
    acc.enable();

}

// Interrupt Service Routines (ISRs)

void setting_distance_isr()
{
    g_setting_distance_flag = 1;

}

void intruder_distance_isr()
{
    g_intruder_distance_flag = 1;

}

void button_0_isr()
{
    g_button_0_flag = 1;

}

void button_1_isr()
{
    g_button_1_flag = 1;

}

void button_c_isr()
{
    g_button_c_flag = 1;

}

void led_buzzer_isr()
{
    g_led_buzzer_flag = 1;

}

void acc_isr()
{
    g_acc_flag = 1;

}

void pin_timeout_isr()
{
    g_pin_timeout_flag = 1;

}

void setting_screen_isr()
{
    g_setting_screen_flag = 1;

}

// Button Functions

void button_0_protocol()
{

    // states 2, 3, 6 and 7 require a pin to be entered

    if (g_current_state == 2) {

        if (pin_counter < 4) { // entered_pin has four elements

            entered_pin[pin_counter] = 0;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 3) {

        if (pin_counter < 4) { // entered_pin has four elements

            entered_pin[pin_counter] = 0;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 6) {

        if (pin_counter < 4) { // entered_pin has four elements

            entered_pin[pin_counter] = 0;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 7) { // entered_pin has four elements

        if (pin_counter < 4) {

            entered_pin[pin_counter] = 0;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else {

        g_next_state = fsm[g_current_state].nextState[0]; // filters through fsm to find the next state

    }

}

void button_1_protocol()
{

    // states 2, 3, 6 and 7 require a pin to be entered

    if (g_current_state == 2) {

        if (pin_counter < 4) {  // entered_pin has four elements

            entered_pin[pin_counter] = 1;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 3) {

        if (pin_counter < 4) {  // entered_pin has four elements

            entered_pin[pin_counter] = 1;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 6) {

        if (pin_counter < 4) {  // entered_pin has four elements

            entered_pin[pin_counter] = 1;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else if (g_current_state == 7) {

        if (pin_counter < 4) {  // entered_pin has four elements

            entered_pin[pin_counter] = 1;

            pin_counter++;

        }

        enter_pin(); // prints '*' to the LCD

    }

    else {

        g_next_state = fsm[g_current_state].nextState[1]; // filters through fsm to find the next state

    }

}

void button_c_protocol()
{

    // states 2, 3, 6 and 7 require a pin to be entered
    // the screen only progresses if the correct pin is entered

    if (g_current_state == 2) {

        screen_progression();

    }

    else if (g_current_state == 3) {

        screen_progression();

    }

    else if (g_current_state == 6) {

        screen_progression();

    }

    else if (g_current_state == 7) {

        screen_progression();

    }

    else {

        g_next_state = fsm[g_current_state].nextState[2]; // filters through fsm to find the next state

    }

}

// State Functions

void state_0_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Mobile",27,1);

    lcd.printString("Security",18,2);

    lcd.printString("System",27,3);

    lcd_border();

    // set LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    lcd.refresh();

}

void state_1_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Set Alarm",15,1);

    lcd.printString("Set New Pin",9,4);

    lcd_border();

    for (int i = 0; i < WIDTH; i++) {

        lcd.setPixel(i,24);

    }

    // detach tickers

    pin_timeout.detach();
    
    accelerometer.detach();
    
    intruder_distance.detach();
    
    alerts.detach();

    // set LED and buzzer

    led_alarm = 0;

    buzzer.write(0);

    // reset counter

    pin_timeout_counter = 0;

    lcd.refresh();

}

void state_2_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Enter 4 Digit",3,1);

    lcd.printString("Pin Below",15,2);

    pin_text_box();

    lcd_border();

    // set the LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    lcd.refresh();

}

void state_3_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Enter New 4",9,1);

    lcd.printString("Digit Pin",15,2);

    pin_text_box();

    lcd_border();

    // set the LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    lcd.refresh();

}

void state_4_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Setting",21,1);

    lcd_border();

    lcd.drawRect(0,20,84,5,0); // blank setting bar

    lcd.printString("0%",41,4); // 0% of setting complete

    // reset counter

    setting_alarm_counter = 0;

    // set LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    // attach tickers

    alerts.attach(&led_buzzer_isr,0.5);
    
    setting_distance.attach(&setting_distance_isr,0.1);
    
    accelerometer.attach(&acc_isr,0.1);

    setting_screen.attach(&setting_screen_isr,0.28);
    
    // get setting accelerometer data
    
    get_axis_data();
    
    pc.printf("Printing setting accelerometer data....\n");    
    
    setting_acc_X = acc_X;
    
    setting_acc_Y = acc_Y;
    
    setting_acc_Z = acc_Z;
    
    pc.printf("X = %.4f \nY = %.4f \nZ = %.4f \n",setting_acc_X,setting_acc_Y,setting_acc_Z);
    
    lcd.refresh();

}

void state_5_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("Alarm Set",15,1);

    lcd.printString("DEACTIVATE?",9,4);

    lcd_border();

    for (int i = 0; i < WIDTH; i++) {

        lcd.setPixel(i,20);

    }

    // detach tickers

    alerts.detach();
    
    accelerometer.detach();

    setting_screen.detach();
    
    // attach ticker
    
    intruder_distance.attach(&intruder_distance_isr,0.1);

    // set LED and buzzer

    led_alarm = 1;

    buzzer.write(0.5);

    // turn off buzzer after 1 second

    buzz.attach(&alarm_setting_buzz,1);

    lcd.refresh();

}

void state_6_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("DEACTIVATE",12,1);

    lcd.printString("Enter Pin",15,2);

    lcd_border();

    pin_text_box();

    // set the LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    // attach ticker

    alerts.attach(&led_buzzer_isr,0.5);
    
    // detach ticker
    
    intruder_distance.detach();
    lcd.refresh();

}

void state_7_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("INTRUDER",18,1);

    lcd.printString("Enter Pin",15,2);

    lcd_border();

    lcd.drawRect(1,30,15,10,0);

    pin_text_box();

    // set the LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    // attach tickers

    alerts.attach(&led_buzzer_isr,0.5);

    pin_timeout.attach(&pin_timeout_isr,1);
    
    // detach ticker
    
    intruder_distance.detach();

    lcd.refresh();

}

void state_8_screen()
{
    lcd.clear();

    // print the screen

    lcd.printString("ALARM",27,1);

    lcd.printString("TRIGGERED",15,2);

    lcd.printString("Menu?",27,4);

    lcd_border();

    // set the LED and buzzer

    led_alarm = 0;

    buzzer.write(0.0);

    // detach tickers

    alerts.detach();

    pin_timeout.detach();

    // attach ticker

    alerts.attach(&led_buzzer_isr,0.2);

    lcd.refresh();
}

void lcd_border()
{
    lcd.drawRect(0,0,83,47,0);

    lcd.drawRect(1,1,81,45,0);

}

void pin_text_box()
{
    lcd.drawRect(15,30,15,10,0);    // transparent box, just outline
    lcd.drawRect(29,30,15,10,0);    // transparent box, just outline
    lcd.drawRect(43,30,15,10,0);    // transparent box, just outline
    lcd.drawRect(57,30,15,10,0);    // transparent boox, just outline

}

void screen_progression()
{
    if (g_current_state == 3) { // set new pin state

        if (pin_counter > 3) { // if a four digit pin has been entered

            change_pin(); // save entered_pin to the SD card

            read_pin(); // read the pin from the SD card to the set_pin array

            g_next_state = fsm[g_current_state].nextState[2];

        }

        else {

            g_next_state = fsm[g_current_state].nextState[3];

        }

    }

    else { // if the current state is either 2, 6 or 7

        check_pin(); // sets incorrect_pin_flag to 1 if entered pin doesn't match set_pin

        if (incorrect_pin_flag == 1) {

            incorrect_pin_flag = 0;

            g_next_state = fsm[g_current_state].nextState[3]; // go to previous state or alarm triggered state

            pc.printf("g_next_state = %d\n",g_next_state);

        }

        else {

            g_next_state = fsm[g_current_state].nextState[2]; // proceed

            pc.printf("g_next_state = %d\n",g_next_state);

        }

    }

}

void screen_selection()
{

    reset_entered_pin(); // re-set each element of the entered pin array to -1

    if (g_next_state == 0) {

        state_0_screen();

    }

    else if (g_next_state == 1) {

        state_1_screen();

    }

    else if (g_next_state == 2) {

        state_2_screen();

    }

    else if (g_next_state == 3) {

        state_3_screen();

    }

    else if (g_next_state == 4) {

        state_4_screen();

    }

    else if (g_next_state == 5) {

        state_5_screen();

    }

    else if (g_next_state == 6) {

        state_6_screen();

    }

    else if (g_next_state == 7) {

        state_7_screen();

    }

    else {

        state_8_screen();

    }

}

// Screen Animation Functions

void setting_animation()
{
    setting_alarm_counter = setting_alarm_counter + 5; //  increment setting_alarm_counter in steps of five

    if (setting_alarm_counter < 101) {

        lcd.drawRect(0,20,setting_alarm_counter,5,1); // prints the loading bar to the LCD

        // format how the percentage is displayed depending on its value
        if (setting_alarm_counter < 10) {

            length = sprintf(buffer,"0%d%%",setting_alarm_counter);

        }

        else {

            length = sprintf(buffer,"%d%%",setting_alarm_counter);

        }

        if (length <= 14) { // if length of string will fit on the screen ( WIDTH = 6 * 24 = 84 pixels )

            if (setting_alarm_counter < 100) {

                lcd.printString(buffer,33,4);

            }

            else {

                lcd.printString(buffer,30,4); // this string is four characters long and is therefore shifted to the left of the screen

            }

        }

        lcd.refresh(); // refresh screen

    }
}

void timeout_protocol()
{

    pin_timeout_counter++;

    seconds_till_timeout = 21 - pin_timeout_counter; // timeout counts down from 20

    if (seconds_till_timeout == 0) { // if 20 seconds passes

        g_next_state = 8;

        pin_timeout_counter = 0;

    }

    else { // less than 20 seconds has passed

        // These if statements manage the formatting of the number of seconds remaining

        if (seconds_till_timeout >= 10) {

            length = sprintf(buffer,"%d",seconds_till_timeout);

        }

        else {

            length = sprintf(buffer,"0%d",seconds_till_timeout);

        }

        // if the length of the formatted string will fit on the screen print it ( WIDTH = 14 * 6 = 84 pixels )

        if (length <= 14)
            lcd.printString(buffer,3,4);

        lcd.refresh();

    }

}

// Read Distance Functions

void get_setting_distance()
{
    distance[setting_distance_counter] = srf02.getDistanceCm(); // distance array stores 10 distance readings

    setting_distance_counter++;

    if (setting_distance_counter == 10) { // if distance array has 10 new readings (arrays are zero indexed)

        setting_distance.detach();

        calculate_setting_distance(); // find the average of the 10 distance readings

    }

}

void get_intruder_distance()
{

    distance[intruder_distance_counter] = srf02.getDistanceCm(); // distance array stores 10 distance readings

    intruder_distance_counter++;

    if (intruder_distance_counter == 10) { // if distance array has 10 new readings (arrays are zero indexed)

        intruder_distance.detach();

        calculate_intruder_distance(); // find the average of the 10 distance readings

    }

}

void calculate_setting_distance()
{

    for (int i = 0; i < 10; i++) {

        one_second_distance = one_second_distance + distance[i]; // add all 10 readings together

    }

    initial_setting_distance = (one_second_distance / 10);

    pc.printf("Initial Setting Distance = %.2f cm\n",initial_setting_distance);

    setting_distance_counter = 0;

    one_second_distance = 0;

    transition.attach(&screen_5_transition,5); // transition to the set screen in five seconds

}

void calculate_intruder_distance()
{

    for (int i = 0; i < 10; i++) {

        one_second_distance = one_second_distance + distance[i]; // add all 10 distance readings together

    }

    one_second_avg_distance = one_second_distance / 10;

    pc.printf("Intruder Distance = %.2f cm\n",one_second_avg_distance);

    intruder_distance_counter = 0;

    one_second_distance = 0;


    if (one_second_avg_distance > (1.1*initial_setting_distance)) { // if the current average distance is 10% greater than the initial_setting_distance set off the alarm

        g_next_state = 7;

        g_current_state = 7;

        screen_selection();

    }

    else if (one_second_avg_distance < (0.9 * initial_setting_distance)) { // if the current average distance is 10% smaller than the initial_setting_distance set off the alarm

        g_next_state = 7;

        g_current_state = 7;

        screen_selection();

    }

    else { // if the current distance is within 10% of the initial_setting_distance carry on reading distance

        intruder_distance.attach(&intruder_distance_isr,0.1);

    }

}

// Timeout Functions

void screen_5_transition()
{
    g_next_state = 5;
    
    accelerometer.detach();

    screen_selection(); // sets the LCD to screen 5

    g_current_state = 5;

}

void pin_confirm()
{
    lcd.clear();

    lcd_border();

    lcd.printString("Press C",24,1);

    lcd.printString("to",36,2);

    lcd.printString("Confirm",24,3);

    if (g_current_state == 7) {

        lcd.drawRect(1,30,15,10,0);

    }

    lcd.refresh();

}

void device_tampered()
{
    g_next_state = 1;

    screen_selection();

    g_current_state = 1;

}

void alarm_setting_buzz()
{

    buzzer.write(0.0); // turn off buzzer

}

// Accelerometer Function

void get_axis_data()
{

    acc.getX(acc_X);
    acc.getY(acc_Y);
    acc.getZ(acc_Z);

}

void compare_axis_data()
{
    get_axis_data();

    pc.printf("X1 = %.4f \nY1 = %.4f \nZ1 = %.4f \n",acc_X,acc_Y,acc_Z);

    if (abs(acc_X) < 0.2f*abs(setting_acc_X)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_X < setting_acc_X\n");
        
    }
    
    else if (abs(acc_X) > 5.0f*abs(setting_acc_X)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_X > setting_acc_X\n");
        
    }    
    
    else if (abs(acc_Y) < 0.2f*abs(setting_acc_Y)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_Y < setting_acc_Y\n");

    }
    
    else if (abs(acc_Y) > 5.0f*abs(setting_acc_Y)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_Y > setting_acc_Y\n");
        
    } 
    
    else if (abs(acc_Z) < 0.2f*abs(setting_acc_Z)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_Z < setting_acc_Z\n");

    }
    
    else if (abs(acc_Z) > 5.0f*abs(setting_acc_Z)) {
        
        device_tampered_protocol();
        
        pc.printf("acc_Z > setting_acc_Z\n");
        
    } 
    
    else {
        
    }    

}

void device_tampered_protocol()
{
    setting_distance.detach();

    setting_screen.detach();
    
    accelerometer.detach();

    transition.detach();

    lcd.clear();

    lcd.printString("DEVICE MOVED",6,1);

    lcd.printString("SETTING",21,3);

    lcd.printString("INCOMPLETE",12,4);

    lcd_border();

    lcd.refresh();

    tamper_transition.attach(&device_tampered,3);

}

// Pin Functions

void enter_pin()
{

    // current value of the pin_counter determines where '*' is printed

    if (pin_counter == 1) {

        lcd.printString("*",20,4);

    }

    else if (pin_counter == 2) {

        lcd.printString("*",34,4);

    }

    else if (pin_counter == 3) {

        lcd.printString("*",48,4);

    }

    else if (pin_counter == 4) {

        lcd.printString("*",62,4);

        confirm.attach(&pin_confirm,0.5); // 'Press C to Confirm' screen

    }

}

void reset_entered_pin()
{
    for (int i = 0; i < 4; i++) {

        entered_pin[i] = -1;

    }

    pin_counter = 0;

}

void check_pin()
{
    for (int i = 0; i < 4; i++) {

        if (entered_pin[i] != set_pin[i]) { // if any element of entered_pin doesn't match set_pin

            pc.printf("entered pin doesn't match set pin...");

            incorrect_pin_flag = 1;

            break;

        }

    }

}

void change_pin()
{
    delete_file("/sd/test.txt");

    pin = fopen("/sd/test.txt", "a");

    if (pin == NULL) {  // if it can't open the file then print error message

        pc.printf("Error! Unable to open file!\n");

    }

    else {

        pc.printf("Writing to file....\n");

        for(int i = 0; i < 4; i++) {

            int pin_element = entered_pin[i];;  // pin_element takes on the value of each element in the entered_pin array

            fprintf(pin, "%d,%d\n",i,pin_element);  // pin element is printed to SD card file (CSV)
        }

        for(int i = 0; i < 4; i++) {

            pc.printf("[%d] %d\n",i,entered_pin[i]); // print to PC for debugging purposes
        }

        pc.printf("Done.\n");

        fclose(pin);  // close the file after writing

    }

}

void read_pin()
{
    pin = fopen("/sd/test.txt", "r");

    int i = 0;

    pc.printf("Reading into set_pin array...\n");

    while (fscanf(pin, "%d,%d",&index_array[i],&set_pin[i]) != EOF) { // EOF ---> End of File
        i++;  // read data into array and increment index
    }

    fclose(pin);  // close the file after reading

    for(int i = 0; i < 4 ; i++) {

        pc.printf("[%d] %d\n",i,set_pin[i]); // print to PC for debugging purposes

    }

    pc.printf("Done.\n");

}

void delete_file(char filename[])
{
    pc.printf("Deleting file '%s'...",filename);

    FILE *fp = fopen(filename, "r");  // try and open file

    if (fp != NULL) {  // if it does open...

        fclose(fp);    // close it

        remove(filename);  // delete the file

        pc.printf("Done!\n");

    }

    // if it can't be opened, it doesn't exist and can't be deleted

}