/*********************************************************************************/ /** * File: main.c * Author: Jan Dvořák z Vozerovic * FEL-ID: dvoraj42 * e-mail: dvorkaman@gmail.com * site: dvorkaman.php5.cz */ #include "stdio.h" /* OWN INCLUDES */ #include "dvoraj42.c" #include "letters.c" #include "others.c" /* SYSTEM CLOCK */ volatile timeStruct SYSTEM_CLOCK; // volatile - used in interrupt /* KEYBOARD */ volatile int state, subState; // volatile - used in interrupt int lastDrawnState, lastDrawnSubState; int keyboardLock; /* USERS */ #define MAX_USERS 64 // flash from 800 to C00; size of user = 256b int USER_COUNT; user USERS[MAX_USERS]; char grantedUserName[USER_NAME_LENGT]; /* HEADERS */ void USART_message(int ch); void drawState(bool checkSubState); void enterUserPassword(void); void enterAdminPassword(void); void lcdPrintLines(char * line1, char * line2); password readPassword(bool showChars, bool abortOnF); void blinkingOfColon(void); void emptyFunction(void); void loadUsers(void); void FLASHSaveUsers(void); void restoreFLASHToDefault(void); void accessGranted(void); void invalidPassword(void); int findUserWithPassword(int password); void waitForKey(int key, bool longPress, int changeToState, int changeToSubState); void getUserName(int id); void administratorMenu(void); void changeAdministratorPassword(void); void readUserName(int userId, char* uname); char incrementChar(char letter, int positions); int chooseUser(void); void changeUser(void); void passwordIsNotUnique(void); void createUser(void); void removeUser(void); void removeUserFromData(int id); /*********************************************************************************/ /** * Main method */ int main(void) { /* 1) Enable ports, configuration, interrupt */ RCC_Configuration(); // source: http://neuron.feld.cvut.cz/micro/stm32/tut-03-usart-irq.html#config GPIO_Configuration(); // source: http://neuron.feld.cvut.cz/micro/stm32/tut-03-usart-irq.html#config NVIC_Configuration(); // source: http://neuron.feld.cvut.cz/micro/stm32/tut-03-usart-irq.html /* 2) Configuration of peripheries */ configureKeyboard(); configureSegment(); configureLCD(); initializeLCD(); GPIO_WriteBit(GPIOC, GPIO_Pin_8, (BitAction)1); GPIO_WriteBit(GPIOC, GPIO_Pin_9, (BitAction)1); keyboardLock = 0; USARTsendChar('C'); writeToSegment(SEGMENT_C); LCDSendString("_"); //restoreFLASHToDefault(); loadUsers(); /* STATE 0: Entering password: User 1: Entering password: Admin 2: Pass OK: User - show welcome ; sub state = user ID (index) 3: Pass FAIL: 4: Admin menu; sub state = indication of function 0: change admins menu 1: add user 2: edit user 3: leave 5: Change admin password 6: Create user 0: Enter name 1: Enter pass 7: Edit user 0: Locate user 1: Enter name 2: Enter pass 8: Password is not unique 9: Remove user 0: Locate user */ state = 0; lastDrawnState = -1; while(1) { switch(state) { case 0: enterUserPassword();break; case 1: enterAdminPassword();break; case 2: accessGranted();break; case 3: invalidPassword();break; case 4: administratorMenu(); break; case 5: changeAdministratorPassword(); break; case 6: createUser(); break; case 7: changeUser(); break; case 8: passwordIsNotUnique(); break; case 9: removeUser(); break; } } } /*********************************************************************************/ /** * State 0: Entering user password */ void enterUserPassword(void) { int id; password pass; keyboardLock = 0; drawState(FALSE); // do not check sub states pass = readPassword(FALSE, FALSE); if( pass.longF == TRUE ) { state = 1; // enter admin pass return; } // validate id = findUserWithPassword(pass.value); if( id>0 ) { state = 2; subState = id; }else{ state = 3; } } /*********************************************************************************/ /** * State 1: Entering admin password */ void enterAdminPassword(void) { password pass; drawState(FALSE); // do not check sub states pass = readPassword(FALSE, FALSE); if( pass.longF == TRUE ) { state = 0; // enter user pass return; } // validate if( pass.value==USERS[0].pass ) { state = 4; lastDrawnSubState = -1; // force redraw subState = 0; }else{ state = 3; } } /*********************************************************************************/ /** * State 2: Access granted * remark: SubState is equal to users id */ void accessGranted(void) { drawState(FALSE); // do not check sub states waitForKey('N', FALSE, 0, 0); } /*********************************************************************************/ /** * State 3: InvalidPassword */ void invalidPassword(void) { drawState(FALSE); // do not check sub states waitForKey('N', FALSE, 0, 0); } /*********************************************************************************/ /** * State 4: Administrator menu */ void administratorMenu(void) { input inp; drawState(TRUE); // chech sub states while(1) { inp = readInput(emptyFunction); // exit admin menu if( inp.key=='F' && inp.longF==TRUE ) { state = 0; return; } // choose function else if( inp.key=='N' && inp.longN==FALSE ) { switch(subState) { case 0: state = 5; break; // change pass case 1: state = 6; break; // create user case 2: state = 7; break; // edit user case 3: state = 9; break; // remove user case 4: state = 0; break; // leave } return; } // switch between functions else if( inp.key>='1' && inp.key<='5' ) { subState = inp.key - '1'; // 0 - 3 } // redraw drawState(TRUE); } } /*********************************************************************************/ /** * State 5: Change administrator password */ void changeAdministratorPassword(void) { password pass; int id; drawState(FALSE); // do not check sub states pass = readPassword(TRUE, TRUE); // state after password state = 4; subState = 0; lastDrawnSubState = -1; // force redraw // detect abortion if( pass.F == TRUE ) { return; } // unique? id = findUserWithPassword(pass.value); if( id!=-1 ) { state = 8; return; } // store USERS[0].pass = pass.value; FLASHSaveUsers(); } /*********************************************************************************/ /** * State 6: Create user */ void createUser(void) { // substates: // 0 = enter name // 1 = enter password int id, fid; char uname[USER_NAME_LENGT]; password pass; lastDrawnState = -1; // checks if( USER_COUNT == MAX_USERS-1 ) { subState = 0; state = 4; } /* 1) Get Name */ subState = 0; drawState(TRUE); // chech sub states readUserName(id, uname); if( uname[0]=='\0' ) { lastDrawnSubState = -1; // force redraw state = 4; // back to admin menu return; } /* 2) Get Pass */ subState = 1; drawState(TRUE); // chech sub states pass = readPassword(TRUE, TRUE); state = 4; subState = 0; lastDrawnSubState = -1; // force redraw // detect abortion if( pass.F == TRUE ) { return; } // unique? fid = findUserWithPassword(pass.value); if( fid!=-1 ) { state = 8; return; } /* 3) Store */ id = USER_COUNT++; // post increment USERS[id] = getEmptyUser(); strcpy(USERS[id].name, uname); USERS[id].pass = pass.value; FLASHSaveUsers(); } /*********************************************************************************/ /** * State 7: Edit user */ void changeUser(void) { // substates: // 0 = select user // 1 = enter name // 2 = enter password int id, fid; char uname[USER_NAME_LENGT]; password pass; lastDrawnState = -1; // checks if( USER_COUNT == 1 ) { subState = 0; state = 4; } /* 1) Choose user */ subState = 0; drawState(TRUE); // chech sub states id = chooseUser(); if( id==-1 ) { lastDrawnSubState = -1; // force redraw state = 4; // back to admin menu return; } /* 2) Get Name */ subState = 1; drawState(TRUE); // chech sub states readUserName(id, uname); if( uname[0]=='\0' ) { lastDrawnSubState = -1; // force redraw state = 4; // back to admin menu return; } /* 3) Get Pass */ subState = 2; drawState(TRUE); // chech sub states pass = readPassword(TRUE, TRUE); // state after password state = 4; subState = 0; lastDrawnSubState = -1; // force redraw // detect abortion if( pass.F == TRUE ) { return; } // unique? fid = findUserWithPassword(pass.value); if( fid!=-1 ) { state = 8; return; } // store strcpy(USERS[id].name, uname); USERS[id].pass = pass.value; FLASHSaveUsers(); } /*********************************************************************************/ /** * State 8: Password is not unique */ void passwordIsNotUnique(void) { drawState(FALSE); lastDrawnSubState = -1; // force redraw waitForKey('N', FALSE, 4, 0); } /*********************************************************************************/ /** * State 9: Remove user */ void removeUser(void) { int id; lastDrawnState = -1; // checks if( USER_COUNT == 1 ) { subState = 0; state = 4; } /* 1) Choose user */ drawState(FALSE); id = chooseUser(); // preapre for admin menu lastDrawnSubState = -1; // force redraw state = 4; // back to admin menu if( id==-1 ) { return; } /* 2) Remove and save */ removeUserFromData(id); FLASHSaveUsers(); } /*********************************************************************************/ /** * Remove user * @param{int} id */ void removeUserFromData(int id) { int i, o; // remove and shift for( i = id + 1; i < USER_COUNT; i++ ) { USERS[i-1].pass = USERS[i].pass; USERS[i-1].crc = USERS[i].crc; for( o = 0; o < USER_NAME_LENGT; o++ ) { USERS[i-1].name[o] = USERS[i].name[o]; } } // clear pream. of last entry USERS[USER_COUNT - 1].preambule = 0x0; USER_COUNT--; } /*********************************************************************************/ /** * Wait for key is pressed and change state * @param{int} key * @param{bool} longPress * @param{int} changeToState * @param{int} changeToSubState */ void waitForKey(int key, bool longPress, int changeToState, int changeToSubState) { input inp; while(1) { inp = readInput(emptyFunction); if( inp.key==key) { if( longPress==TRUE ) { if( key=='N' && inp.longN==FALSE )continue; if( key=='F' && inp.longF==FALSE )continue; } state = changeToState; subState = changeToSubState; return; } } } /*********************************************************************************/ /** * Find user with password * @param{int} password * @returns{int} user ID; -1 if not found */ int findUserWithPassword(int password) { int i; for( i = 0; i< USER_COUNT; i++ ) { if( USERS[i].pass == password )return i; } return -1; } /*********************************************************************************/ /** * Read password * @param{bool} showChars True if we want do show pressed key; otherwise shows '*' * @param{bool} abortOnF True if we want do abort entering of password; false if we want to clear the pass */ password readPassword(bool showChars, bool abortOnF) { input inp; int digits = 0; password pass = getEmptyPassword(); // set cursor LCDSetCursor(0,1); while(1) { inp = readInput( blinkingOfColon ); // Pass ACK if( inp.key=='N' ) { if( inp.longN==TRUE || digits < 4 )continue; // minimal length is 4 letters return pass; } // Clear || Special function if( inp.key=='F' ) { if( inp.longF ) { pass.longF = TRUE; return pass; } if( abortOnF==TRUE ) { pass.F = TRUE; return pass; } // clear LCDSetCursor(0,1); LCDSendString(" "); LCDSetCursor(0,1); pass = getEmptyPassword(); digits = 0; continue; } // Pressed key if( digits < 8 ) { // show on lcd LCDSetCursor(digits, 1); if(showChars==TRUE) LCDSendChar(inp.key); else LCDSendChar('*'); // store digits++; pass.value = pass.value * 10 + (inp.key - '0'); } } } /*********************************************************************************/ /** * Draw LCD according to state / sub state if necessary */ void drawState(bool checkSubState) { char* bottomLine; if( lastDrawnState==state && checkSubState==FALSE ) return; if( checkSubState==TRUE && lastDrawnSubState==subState ) return; lastDrawnSubState = subState; lastDrawnState = state; switch(state) { case 0: lcdPrintLines("Zadejte heslo: ", " [N]"); writeToSegment(SEGMENT_L); break; case 1: lcdPrintLines("Zadejte heslo ", " [N]"); break; case 2: // granted getUserName(subState); lcdPrintLines("Vitejte uzivateli ", grantedUserName); writeToSegment(SEGMENT_0); break; case 3: lcdPrintLines("Neplatne heslo! ", "Pokracujte stiskem N"); break; case 4: // admin menu switch(subState) { case 0: bottomLine = "Zmenit heslo [N]"; break; case 1: bottomLine = "Pridat uziv. [N]"; break; case 2: bottomLine = "Upravit uziv. [N]"; break; case 3: bottomLine = "Odebrat uziv. [N]"; break; case 4: bottomLine = "Ukoncit [N]"; break; } lcdPrintLines("Administrator [1-4]", bottomLine); break; case 5: lcdPrintLines("Zmenit adm. heslo: ", " [N]"); break; case 6: // select each step switch(subState) { case 0: lcdPrintLines("Uzivatelske jmeno: ", " "); break; case 1: lcdPrintLines("Uzivatelske heslo: ", " [N]"); break; } break; case 7: // select each step switch(subState) { case 0: lcdPrintLines("Vyber uzivatele: [N]", " "); break; case 1: lcdPrintLines("Uzivatelske jmeno: ", " "); break; case 2: lcdPrintLines("Uzivatelske heslo: ", " [N]"); break; } break; case 8: lcdPrintLines("Zadane heslo neni...", "... unikatni! [N]"); break; case 9: lcdPrintLines("Vyber uzivatele: [N]", " "); break; } } /*********************************************************************************/ /** * Get user name of user given by id * @param{int} id of user */ void getUserName(int id) { int i; for( i = 0; i< USER_NAME_LENGT; i++ ) { grantedUserName[i] = USERS[id].name[i]; } } /*********************************************************************************/ /** * Print two lines to LCD */ void lcdPrintLines(char * line1, char * line2) { LCDSetCursorHome(); LCDSendString(line1); LCDSetCursor(0,1); LCDSendString(line2); } /*********************************************************************************/ /** * Function whose pointer is given to ReadInput function */ void blinkingOfColon(void) { int chr = 0; if( state!= 1 )return; if( SYSTEM_CLOCK.ms == 0)chr = ' '; else if( SYSTEM_CLOCK.ms == 499) chr = ':'; if( chr!=0 ) { LCDSetCursor(13, 0); LCDSendChar( chr ); } } /*********************************************************************************/ /** * Function whose pointer is given to ReadInput function */ void emptyFunction(void) { } /*********************************************************************************/ /** * Load users from FLASH memory */ void loadUsers(void) { uint32_t* userData; // destination uint32_t addr = FLASH_START; // origin user* u; int i; userData = (uint32_t*)(&USERS[0]); u = (user * )userData; USER_COUNT=0; while( USER_COUNT< MAX_USERS) { for(i = 0; ipreambule!=0x69696969 ) break; USER_COUNT++; u++; // move to another entry } } /*********************************************************************************/ /** * Save users to flash * @{author} STMicroelectronics (STM32VLDISCOVERY firmware package (AN3268).zip) * @{author} modified by Jan Dvořák z Vozerovic */ void FLASHSaveUsers(void) { int n, i, addr; uint32_t* userData; FLASH_Status status = FLASH_COMPLETE; int wroteUsers = 0; userData = (uint32_t*)(&USERS[0]); FLASH_UnlockBank1(); n = (FLASH_END - FLASH_START) / FLASH_PAGE_SIZE; // clear flags FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_BSY); /* 1) We must erase flash before write... */ for(i = 0; (i < n) && (status == FLASH_COMPLETE); i++) { status = FLASH_ErasePage(FLASH_START + (FLASH_PAGE_SIZE * i)); } /* 2) No we can save data*/ addr = FLASH_START; while((addr < FLASH_END) && (status == FLASH_COMPLETE)) { // write single user for(i = 0; i we red 4 units } wroteUsers++; if( wroteUsers>= USER_COUNT) break; // done } FLASH_LockBank1(); } /*********************************************************************************/ /** * Create Default users: Admin + 'Jan Dvorak z Vozer.' */ void restoreFLASHToDefault(void) { int i; char name[USER_NAME_LENGT] = "Jan Dvorak z Vozer. "; char name2[USER_NAME_LENGT] = "Kliment Ponozka jr. "; user u = getEmptyUser(); user u2 = getEmptyUser(); u.pass = 11234; // leading '1' USERS[0] = u; u.pass = 18888; for( i = 0; i=0 && positions<=9 ) { // out of first range if( c>'Z' && letter>='A' && letter<='Z') { c = 'a' + (c - 'Z') - 1 ; // start from 'a' so many position as owerflowed 'Z' } // out of second range if( c>'z' && letter>='a' && letter<='z') { if( c == 'z' + 1 )c =' '; // space else c = 'A' + (c - 'z') - 2 ; // start from 'aA so many position as owerflowed 'z' + space } // after space if(c > ' ' && letter==' ') { c = 'A' + (c - ' ') - 1; } // Decrement }else if(positions==-1){ if( letter==' ' )c='z'; else if( letter=='a' ) c='Z'; else if( letter=='A' ) c=' '; }else{ return letter; // no change } // return return c; } /*********************************************************************************/ /** * Choose user * @returns {int} selected user's id */ int chooseUser(void) { int id=1; input inp; // read data while(1) { // show currently selected getUserName(id); LCDSetCursor(0,1); LCDSendString(grantedUserName); inp = readInput(emptyFunction); // Storno if( inp.key=='F' ) { if(inp.longF==FALSE) { return -1; } } // User ACK else if( inp.key=='N' ) { if( inp.longN==FALSE ) { return id; } } // Next else if( inp.key=='1' ) { id++; if( id>= USER_COUNT) id=1; } } }