Interface and Application Programming

Making software using VB language

Assignments

  • To design Software GUI and farming and implementing procols for communicating with Hardware


  • As in my final project I had a requirement of a software which will be used for communicating with the board I decided to utilized this week for designing and implementing it.

    Software will be communicating with the controller over RS 232 interface.

    Software will be divided into 3 sections

  • i. For establising connection.
  • ii. For uploading data.
  • iii. For downloading data.
  • Before starting with actual implementation of software have made rough sketches of same using paper pen.

    Have decided to use VB language for software development and .Net framework as found it to be convinient for my application

    Software development using Microsoft Visual studio

  • Have started by installing microsoft visual studio on my machine. It is a license software and requires license to start with.
  • Step 1: Is to start by selecting new template. Of the available template select Windows form application.
  • Step 2: Name your project and select okay then a blank form will appare on the screen. On left side there is a list of all tools available and on right side project list and properties of each tool.
  • Step 3: Drag and drop the items required for your project from left. As I was requiring serial port have added it.
  • Step 4: As Serial port is the backbone of my software started by writing a sample code for testing serial interface.
  • This test code detect the available COM ports and shows them in drop box list

    Second dropdown provides the list of baud rates which we want to use for communication

    Using button 1 we can open the port and button 2 was used to send data written onto text box on selected COM port at selected baud rate. For testing whatever data listen on serial is shown in output window. For testing purpose have shorted RX and TX of my laptop serial port so if every thing is working okay should be able to see the data I am sending on debug output window.

  • Step 5: Deciding on protocols for communication between board and software.
  • Again had started by writing it on paper

    Communication Protocol

    1. For connection
      • Tab will be provided for selecting the baud rate and COM port
      • A test command("CC") will be send on selected COM port at selected baud rate, if device is connected on the COM port and baud rate is correct it will respond saying Connection okay("CCOK").
    2. For upload
      • Provision to upload card number
        Command : "UC+8digit_card_no.+expiry_date DDMMYYYY"
        Reply : "UCOK" if okay and "UCERR" in case of error
      • Provision to set date and time
        Command : "SD+DDMMYYYYhhmmss"
        Reply : "SDOK" if okay and "SDERR" in case of error
    3. For download
      • Provision to read date and time from controller
        Command : "GD"
        Reply : "GD+DDMMYYhhmmss"
      • Provision to download logs
        Command : "GL"
        Reply : "GL+logs"
        Each log will have below structure --> Event_ID + YYMMDDhhmmss + 8digit_card_no.
        Each log will be comma separated.
        eg. GL117061520392500000000,417061520402500000000,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512345678,217061520392512344678,317061520392512344678,317061520392512344678,317061520392512344678
  • Step 6: GUI design and Protocol implementation.
  • Started with new project by name Amol_FAB_BOMBAY_PROJECT


    Have created a module where I am going to define all the commands and there replies. The reason was so I will be able to modify it easy in future. Also if there are multiple form each form is able to access these values.


    Designing forms and writting backend code.


    Tab 1 : This form will be used for establishing connection with the controller board. Using drop down user has to select the COM port and baud rate and then click on connect button. If connection is successful Connection success message will be displayed else Error in connection message will be displayed.


    Tab 2 : Here user has to enter card number(max 8 digit) and then select expiry date for the card. Later click onUpload card button. If card is uploaded successfully Success dialogue box will pop up else error dialogue box.
    Using Get Date/Time button we can read the date/time set inside the controller. It will get displayed in Date and Time boxes. If we wish set the date click on set date/time button. When this button is pressed PC date and time is sync with the controller.


    Tab 3 : It is used for downloading log from the controller. When user click on Get Log button, logs from controller are read and shown on display grid. Also the logs gets stored into text file at location were software exe is kept.


    As the activity of downloading the log takes longer time "Please wait message is shown to inform user to wait."


    Pre defined time out is added for all commands. Whenever there is no response from the controller. Software display a dialogue box saying "Error connecting to device"


    Now the 2nd part was developing same protocol and communication interface in firmware. As hardware was ready I started will serial implementation in hardware.

    Firmware Development

    Serial Implementation

    1. Initializing controller Serial port and setting serial parameters like baud rate as 9600, data bit as 8, parity as none and enabling serial interrupt.
    2. // Enable the peripherals SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2 ); SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOG ); // Set GPIO G0 and G1 as UART pins. GPIOPinTypeUART( GPIO_PORTG_BASE, Serial2_Rx | Serial2_Tx ); // Configure the UART for 9600, 8-N-1 operation. UARTConfigSetExpClk( UART2_BASE, SysCtlClockGet(), 9600, ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE ) ); //Set the UART FIFO Level UARTFIFOLevelSet( UART2_BASE, UART_FIFO_TX1_8,UART_FIFO_RX1_8 ); // Enable the UART interrupt. IntEnable( INT_UART2 ); UARTIntEnable( UART2_BASE, UART_INT_RX | UART_INT_RT );
    3. #defines for Serial communication. Buffer sizes should be defined larger than the data you are expecting to receive. Timeout is unit to clear the data incase entire data is not received.
    4. #define RX_BUFFER_SIZE_2 100 #define TX_BUFFER_SIZE_2 5000 #define TX_TIMEOUT_2 1 #define RX_TIMEOUT_2 1
    5. Writing Driver functions for serial
    6. -------------------------------------CLEAR UART 2 TX BUFFER------------------------------------ void clear_uart_2_tx_buffer() { unsigned int i; tx_timeout_counter_2=0; for (i=0;i < TX_BUFFER_SIZE_2;i++) { tx_buffer_2[i] = 0; } } -------------------------------------CLEAR UART 2 RX BUFFER------------------------------------ void clear_uart_2_rx_buffer() { unsigned int i; rx_count_2 = 0; rx_start_2 = false; rx_command_ready_2 =false; rx_timeout_counter_2=0; for (i=0;i < RX_BUFFER_SIZE_2;i++) { rx_buffer_2[i] = 0; } }
    7. Writing serial interrupt handler function - This function is used to fill the data into receive buffer and when entire data is received set data receive flag as true.
    8. void UART2IntHandler(void) { unsigned long ulStatus; tBoolean rx_interrupt = false; tBoolean tx_interrupt = false; unsigned char received_char = 0; // Get the interrrupt status. ulStatus = UARTIntStatus( UART2_BASE, true ); if( UART_INT_RX ) { rx_interrupt = true; } if( UART_INT_TX ) { tx_interrupt = true; } // Clear the asserted interrupts. Clearing an interrupt takes time. UARTIntClear( UART2_BASE, ulStatus ); if(rx_interrupt == true) { received_char = UARTCharGetNonBlocking( UART2_BASE ); if (rx_command_ready_2 == false) //Ensuring that previous data has been processed { rx_buffer_2[rx_count_2++] = received_char; rx_start_2 = true; if(rx_count_2 == 2) { if((rx_buffer_2[0] == 'C') && (rx_buffer_2[1] == 'O')) { rx_command_ready_2 = true; rx_start_2 = false; cmd_no = 1; } if((rx_buffer_2[0] == 'G') && (rx_buffer_2[1] == 'D')) { rx_command_ready_2 = true; rx_start_2 = false; cmd_no = 4; } if((rx_buffer_2[0] == 'G') && (rx_buffer_2[1] == 'L')) { rx_command_ready_2 = true; rx_start_2 = false; cmd_no = 5; } } if(rx_count_2 == 18) { if(rx_buffer_2[0] == 'U' && rx_buffer_2[1] == 'C') { rx_command_ready_2 = true; rx_start_2 = false; cmd_no = 2; } } if(rx_count_2 == 16) { if(rx_buffer_2[0] == 'S' && rx_buffer_2[1] == 'D') { rx_command_ready_2 = true; rx_start_2 = false; cmd_no = 3; } } if(rx_count_2 > 18) { clear_uart_2_rx_buffer(); cmd_no = 0; } } rx_interrupt = false; } if(tx_interrupt==true) { tx_interrupt=false; } }
    9. Writing application level function for processing the data received and sending response back
    10. void process_serial_command_2(void) { unsigned int i,length = 0; // long temp_read_pointer; unsigned char checksum = 0; long err_flag; if(rx_command_ready_2 == true) { switch (cmd_no) { case 1: tx_buffer_2[0] = 'C'; tx_buffer_2[1] = 'O'; tx_buffer_2[2] = 'O'; tx_buffer_2[3] = 'K'; for(i = 0 ; i < 4 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } break; case 2: ascii_to_digit(2,2,18); err_flag = InsertDelTimeZone(rx_buffer_2); if(err_flag == 0) //SUCCESS; { tx_buffer_2[0] = 'U'; tx_buffer_2[1] = 'C'; tx_buffer_2[2] = 'O'; tx_buffer_2[3] = 'K'; for(i = 0 ; i < 4 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } } else if(err_flag == -1) //FAILURE; { tx_buffer_2[0] = 'U'; tx_buffer_2[1] = 'C'; tx_buffer_2[2] = 'E'; tx_buffer_2[3] = 'R'; tx_buffer_2[3] = 'R'; for(i = 0 ; i < 5 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } } else if(err_flag == -2) //MEMORY_FULL; { tx_buffer_2[0] = 'U'; tx_buffer_2[1] = 'C'; tx_buffer_2[2] = 'E'; tx_buffer_2[3] = 'R'; tx_buffer_2[3] = 'R'; for(i = 0 ; i < 5 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } } break; case 3: ascii_to_digit(2,2,16); new_present_time.date = (rx_buffer_2[2] * 10); new_present_time.date = (new_present_time.date + rx_buffer_2[3]); new_present_time.month = (rx_buffer_2[4] * 10); new_present_time.month = (new_present_time.month + rx_buffer_2[5]); new_present_time.year = (rx_buffer_2[8] * 10); new_present_time.year = (new_present_time.year + rx_buffer_2[9]); new_present_time.hour = (rx_buffer_2[10] * 10); new_present_time.hour = (new_present_time.hour + rx_buffer_2[11]); new_present_time.min = (rx_buffer_2[12] * 10); new_present_time.min = (new_present_time.min + rx_buffer_2[13]); new_present_time.sec = (rx_buffer_2[14] * 10); new_present_time.sec = (new_present_time.sec + rx_buffer_2[15]); err_flag = set_Current_Date_Time(&new_present_time); insert_attendence_log(DateTime_Set,0,0); if(err_flag == 0) //SUCCESS; { tx_buffer_2[0] = 'S'; tx_buffer_2[1] = 'D'; tx_buffer_2[2] = 'O'; tx_buffer_2[3] = 'K'; for(i = 0 ; i < 4 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } } else if(err_flag == -1) //FAILURE; { tx_buffer_2[0] = 'S'; tx_buffer_2[1] = 'D'; tx_buffer_2[2] = 'E'; tx_buffer_2[3] = 'R'; tx_buffer_2[3] = 'R'; for(i = 0 ; i < 5 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } } break; case 4: tx_buffer_2[0] = 'G'; tx_buffer_2[1] = 'D'; sprintf(tx_buffer_2+2,"%02d",date_time_variable.date); sprintf(tx_buffer_2+4,"%02d",date_time_variable.month); sprintf(tx_buffer_2+6,"%02d",date_time_variable.year); sprintf(tx_buffer_2+8,"%02d",date_time_variable.hour); sprintf(tx_buffer_2+10,"%02d",date_time_variable.min); sprintf(tx_buffer_2+12,"%02d",date_time_variable.sec); for(i = 0 ; i < 14 ; i++) { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); } break; case 5: tx_buffer_2[0] = 'G'; tx_buffer_2[1] = 'L'; SendAllEvent(); for(i = 0 ; i < 3000 ; i++) { if(tx_buffer_2[i] == 0) {} else { length++; } } for(i = 0 ; i < length ; i++) //2690 { UARTCharPutNonBlocking(UART2_BASE, tx_buffer_2[i]); mili_sec(5); } break; default: break; } clear_uart_2_rx_buffer(); rx_command_ready_2 = false; } }

    Have written driver files for serial UART2 for PC communication

    The files can be downloaded from the link provided at the end of this page.

    Board can be connected to software using 3 wires Rx, Tx and GND

    Flash implementation

    6965 has 256KB of internal flash. I am using the same flash for storing Employee data and logs.

    1. Defining structure for storing employee data and logs.
    2. typedef struct { unsigned long empid; unsigned char exp_date; //card expiry date,month and year unsigned char exp_month; unsigned char exp_year; unsigned char reserve; unsigned short int nextrec; // structure padding unsigned char reserved[6]; }employee_rec; typedef struct { unsigned char event; unsigned char source; unsigned char year; unsigned char month; unsigned char date; unsigned char hour; unsigned char min; unsigned char sec; unsigned long empid; unsigned char read_status; unsigned char reserved[3]; // structure padding }event_rec;

      This structure has to be kept in multiple of 8.
      Nextrec in employee is used for jumping to next location if employee data is reinserted . So it helps in fast searching.

    3. #defines
    4. #define PARAM_1B_PAGES ((sizeof(param_1b)*MAX_PARAM_1B)/PAGE_SIZE)+1 #define PARAM_1B_REC_PER_PAGE PAGE_SIZE/sizeof(param_1b) #define PARAM_4B_PAGES ((sizeof(param_4b)*MAX_PARAM_4B)/PAGE_SIZE)+1 #define PARAM_4B_REC_PER_PAGE PAGE_SIZE/sizeof(param_4b) #define EVENT_PAGES ((sizeof(event_rec)*MAX_EVENT_REC)/PAGE_SIZE)+1 #define EVENT_REC_PER_PAGE PAGE_SIZE/sizeof(event_rec) #define EMPLOYEE_PAGES ((sizeof(employee_rec)*MAX_EMPLOYEE)/PAGE_SIZE)+1 #define EMPLOYEE_REC_PER_PAGE PAGE_SIZE/sizeof(employee_rec)
      #define PARAM_1B_START (param_1b *)0x00019400 #define PARAM_4B_START (param_4b *)((unsigned long)(PARAM_1B_START) + ((PARAM_1B_PAGES)*PAGE_SIZE) + BUFFER) #define EVENT_START (event_rec *)((unsigned long)(PARAM_4B_START) + ((PARAM_4B_PAGES)*PAGE_SIZE) + BUFFER) #define EMPLOYEE_START (employee_rec *)((unsigned long)(EVENT_START) + ((EVENT_PAGES)*PAGE_SIZE) + BU

      Param are used for storing various 1 byte and 4 byte data which is required to be stored and retained in non volatile flash.

    5. Different driver function for Event bank : These are majorly used for locating the write pointer and to write logs in cyclic fashion
    6. int read_attd_log_complete(void) { event_rec cur_rec; int writeerr; memset(&cur_rec,0xff,sizeof(event_rec)); writeerr = -1; /* error by default */ if(read_pointer != write_pointer) { /* record modification is required */ memcpy(&cur_rec,read_pointer,sizeof(event_rec)); if(cur_rec.event != 0xff) { cur_rec.read_status = 0x00; writeerr = FlashProgram((unsigned long *)&cur_rec,(unsigned long )read_pointer,sizeof(event_rec)); } if((unsigned long)((unsigned long)read_pointer + sizeof(event_rec)) == (unsigned long)((unsigned long)EVENT_START + sizeof(event_rec)* MAX_EVENT_REC)) { read_pointer = EVENT_START; } else { read_pointer++; } } return (writeerr); } event_rec* read_attd_log(void) { event_rec *ret; if(read_pointer != write_pointer) { if(read_pointer->event == 0xff || read_pointer->read_status == 0x00) { init_attd_pointers(); } if(read_pointer == write_pointer) { ret = NULL; }else { ret = read_pointer; } } else { ret = NULL; } return(ret); } long init_attd_pointers(void) { event_rec *search; int count; unsigned char read_found = 0,write_found = 0,temp_read = 0; event_log_count = 0; search = EVENT_START; for(count = 1; count <= MAX_EVENT_REC; count++) { /*Write Pointer */ if(write_found == 0) { if(search->event == 0xff) { write_pointer = search; write_found = 1; } else { event_log_count++; } if(count == MAX_EVENT_REC && write_found == 0)/*Memory corrput case */ { //clear_all_logs(); read_pointer = EVENT_START; write_pointer = EVENT_START; read_found = 1; write_found = 1; } } /*Read pointer */ if(read_found == 0) { /*Flash has overflowed once */ if(g_sParameters.attd_flash_cycle_complete == 1) { if(temp_read == 0) { if(search->event != 0xff) { if(search->read_status == 0xff) { temp_read = 3; } else if(search->read_status == 0x00) { temp_read = 1; }else { temp_read = 0; } } else if(search->event == 0xff) { temp_read = 2; }else { temp_read = 0; } } else if(temp_read == 1) { if(search->event == 0xff) { read_pointer = search; read_found = 1; }else { } if(search->event != 0xff) { if(search->read_status == 0xff) { read_pointer = search; read_found = 1; }else { } }else { } } else if(temp_read == 2) { if(count == EVENT_REC_PER_PAGE+1) { if(search->event == 0xff)/*Memory corrupt case */ { //clear_all_logs(); read_pointer = EVENT_START; write_pointer = EVENT_START; read_found = 1; write_found = 1; } else { /*Search read pointer normally */ if(search->read_status == 0xff) { read_pointer = search; read_found = 1; } else if(search->read_status == 0x00) { temp_read = 1; }else { } } }else { } } else if(temp_read == 3) { if(search->event == 0xff) { temp_read = 4; }else { } } else if(temp_read == 4) { if(search->event != 0xff) { if(search->read_status == 0xff) { read_pointer = search; read_found = 1; } else if(search->read_status == 0x00) { temp_read = 5; }else { } }else { } } else if(temp_read == 5) { if(search->event != 0xff && search->read_status == 0xff) { read_pointer = search; read_found = 1; }else { } }else { } } else/*Flash has not been full yet */ { if(temp_read == 0) { if(search->event != 0xff) { if(search->read_status == 0xff) { read_pointer = search; read_found = 1; } else if(search->read_status == 0x00) { temp_read = 1; }else { } }else if(search->event == 0xff)/*Normal case when all the flash is blank */ { /*or Unusual case if valid read or unread records are found after first page */ temp_read = 2; }else { } } else if(temp_read == 1)/*Some read log is found and searches for a unread log */ { if(search->event == 0xff) { read_pointer = search; read_found = 1; } else if(search->event != 0xff) { if(search->read_status == 0xff) { read_pointer = search; read_found = 1; }else { } } } else if(temp_read == 2) { if(count == EVENT_REC_PER_PAGE+1) { if(search->event == 0xff) { read_pointer = EVENT_START; read_found = 1; } else { /*Search read pointer normally */ if(search->read_status == 0xff) { read_pointer = search; read_found = 1; } else if(search->read_status == 0x00) { temp_read = 1; } } }else { } }else { } } }else { } search++; if ((count % (EVENT_REC_PER_PAGE)) == 0) /* count starts with 1 */ { if(write_found == 0) { latest_pagewrite_start = search; event_log_count = 0; }else { } }else { } if((read_found == 1) && (write_found == 1)) { break; }else { } } return 1; } long add_attendence_rec(event_rec* pbuffer) { event_rec cur_rec,prev_rec,*temp_addr; long writeerr; unsigned long address = 0; writeerr = -1; /* error by default */ memset(&cur_rec,0xff,sizeof(event_rec)); memset(&prev_rec,0xff,sizeof(event_rec)); if(write_pointer == EVENT_START) { if(g_sParameters.attd_flash_cycle_complete) { temp_addr = (event_rec*)((unsigned long)EVENT_START + ((EVENT_PAGES-1)*PAGE_SIZE)-sizeof(event_rec)); memcpy(&prev_rec,temp_addr,sizeof(event_rec)); memcpy(&cur_rec,write_pointer,sizeof(event_rec)); if(cur_rec.event != 0xff || prev_rec.event == 0xff) { init_attd_pointers(); } } } else { memcpy(&prev_rec,write_pointer-1,sizeof(event_rec)); memcpy(&cur_rec,write_pointer,sizeof(event_rec)); if(cur_rec.event != 0xff || prev_rec.event == 0xff) { init_attd_pointers(); } } if(event_log_count == ((EVENT_REC_PER_PAGE)-1)) { if((unsigned long)((unsigned long)write_pointer+sizeof(event_rec)) == (unsigned long)((unsigned long)EVENT_START + sizeof(event_rec)* MAX_EVENT_REC)) { address = (unsigned long)EVENT_START; writeerr = FlashErase(address); writeerr = FlashProgram((unsigned long *)pbuffer, (unsigned long)write_pointer, sizeof(event_rec)); write_pointer = EVENT_START; latest_pagewrite_start = write_pointer; event_log_count = 0; if(g_sParameters.attd_flash_cycle_complete == 0) { g_sParameters.attd_flash_cycle_complete = 1; SaveParam1b(ATTD_FLASH_ID); } } else { address = (unsigned long)((unsigned long)latest_pagewrite_start + PAGE_SIZE); writeerr = FlashErase(address); writeerr = FlashProgram((unsigned long *)pbuffer, (unsigned long)write_pointer, sizeof(event_rec)); write_pointer++; latest_pagewrite_start = write_pointer; event_log_count = 0; } if((read_pointer >= write_pointer) && ((unsigned long)read_pointer < (unsigned long)((unsigned long)write_pointer+PAGE_SIZE))) { read_pointer = (event_rec*)((unsigned long)write_pointer+PAGE_SIZE); } } else { writeerr = FlashProgram((unsigned long *)pbuffer, (unsigned long)write_pointer, sizeof(event_rec)); write_pointer++; event_log_count++; /*take care what happens when it becomes greater than 32 */ } return(writeerr); }
    7. Different driver level function for employee bank : They functions are used while adding a employee into employees. So these function search for empty space. If it is not available scans all pages and clear and rewrite the page having maximum number of deleted enteries
    8. These function are required as in flash we can't erase byte but having to erase entire page of 1KB and flash has fixed number of read write cycles.

      int update_bankstatus_employee(void) { int count,pageno,free_pageno; employee_rec *cur_rec; employee_current_page.free = 0; employee_current_page.deleted = 0; employee_current_page.active = 0; employee_maxfree_page.free = 0; employee_maxfree_page.deleted = 0; employee_maxfree_page.active = 0; free_pageno = 0; pageno = 0; cur_rec = EMPLOYEE_START; for(count = 1; count <= MAX_EMPLOYEE; count++) { if (cur_rec->empid != 0xffffffff) { if (cur_rec->nextrec != 0xffff) { employee_current_page.deleted++; }else { employee_current_page.active++; } }else { employee_current_page.free++; } cur_rec++; if ((count % (TIMEZONE_REC_PER_PAGE)) == 0) // count starts with 1 { if (employee_current_page.deleted > employee_maxfree_page.deleted) { employee_maxfree_page.free = employee_current_page.free; employee_maxfree_page.deleted = employee_current_page.deleted; employee_maxfree_page.active = employee_current_page.active; free_pageno = pageno; } employee_current_page.free = 0; employee_current_page.deleted = 0; employee_current_page.active = 0; pageno++; } } if (employee_current_page.deleted > employee_maxfree_page.deleted) { employee_maxfree_page.free = employee_current_page.free; employee_maxfree_page.deleted = employee_current_page.deleted; employee_maxfree_page.active = employee_current_page.active; free_pageno = pageno; } return (free_pageno); } employee_rec * defragment_timezone(void) { int count, pageno; employee_rec *cur_rec; unsigned char temp_page[PAGE_SIZE]; unsigned char *temp_page_start; //temp_page = (unsigned char *)malloc(PAGE_SIZE); temp_page_start = temp_page; memset(temp_page,0xff,PAGE_SIZE); pageno = update_bankstatus_employee(); cur_rec = NULL; if (employee_maxfree_page.deleted > 0) { cur_rec = (employee_rec *)((unsigned long)TIMEZONE_START + (pageno * PAGE_SIZE)); for(count = 1; count <= TIMEZONE_REC_PER_PAGE; count++) { if (cur_rec->nextrec == 0xffff) { memcpy(temp_page_start,(unsigned char *)cur_rec,sizeof(employee_rec)); }else { memset(temp_page_start,0xff,sizeof(employee_rec)); } cur_rec++; temp_page_start += sizeof(employee_rec); } cur_rec = (employee_rec *)((unsigned long)TIMEZONE_START + (pageno * PAGE_SIZE)); FlashErase((unsigned long )cur_rec); FlashProgram((unsigned long *)temp_page,(unsigned long)cur_rec,PAGE_SIZE); cur_rec = (employee_rec *)((unsigned long)TIMEZONE_START + (pageno * PAGE_SIZE)); for(count = 1; count <= TIMEZONE_REC_PER_PAGE; count++) { if ((cur_rec->empid == 0xffffffff) && (cur_rec->nextrec == 0xffff)) { break; } cur_rec++; } if (count > TIMEZONE_REC_PER_PAGE) { cur_rec = NULL; } } // free(temp_page); return(cur_rec); } employee_rec * get_free_employee(void) { employee_rec *search; int count, found; search = TIMEZONE_START; found = -1; for (count = 1; count <= MAX_EMPLOYEE; count++) { if (search->empid == 0xffffffff && search->nextrec == 0xffff) { found = count; break; } search++; } if (found < 0) { search = defragment_timezone(); } return(search); } employee_rec * check_employee(employee_rec *pbuffer) { int found; int count,prev_count; employee_rec *reference,*prev_reference; reference = TIMEZONE_START; found = -1; for(count = 1; count <= MAX_EMPLOYEE; count++) { if (reference->empid == pbuffer->empid) { if(reference->nextrec == 0xffff) { found = count; break; } else if(reference->nextrec != 0x0000) { prev_count = count; prev_reference = reference; count = (reference->nextrec); reference = (employee_rec*)((unsigned long)(TIMEZONE_START) + ((reference->nextrec)*sizeof(employee_rec))); if(reference->empid != pbuffer->empid) { count = prev_count; reference = prev_reference; reference++; } } else { reference++; } } else { reference++; } if(reference > (employee_rec*)((unsigned long)(TIMEZONE_START) +((MAX_EMPLOYEE)*sizeof(employee_rec)))) { break; } } if (found < 0) { reference = NULL; } return(reference); } long add_employee(employee_rec *pbuffer) { int compare; long writeerr; employee_rec *newrec ; employee_rec *tmprec ; employee_rec *temp_rec; unsigned long *temp_char; unsigned char temp_page[PAGE_SIZE]; // temprary page of 1K int pageno, offset; temp_rec = (employee_rec *) malloc(sizeof(employee_rec)); //temp_page = (unsigned long *)((unsigned char *)malloc(PAGE_SIZE)); offset = sizeof(employee_rec); writeerr = -1; // error by default newrec = check_employee(pbuffer); if (newrec != NULL) { if (pbuffer->nextrec != 0xffff)// delete exisiting record { // update existing record writeerr = FlashProgram((unsigned long *)pbuffer,(unsigned long)newrec,sizeof(employee_rec)); }else { // record found in bank compare = memcmp(pbuffer,newrec,sizeof(employee_rec)); if (compare != 0) { // record modification is required memcpy(temp_rec , newrec , sizeof(employee_rec)); tmprec = newrec; newrec = get_free_employee(); if (newrec != NULL) { temp_rec->nextrec = ((unsigned long)newrec - (unsigned long)TIMEZONE_START)/sizeof(employee_rec); writeerr = FlashProgram((unsigned long *)temp_rec,(unsigned long )tmprec,sizeof(employee_rec)); writeerr = FlashProgram((unsigned long *)pbuffer,(unsigned long)newrec,sizeof(employee_rec)); }else { // copy entire page in ram // modify contents of struct required // erase page // write page back to memory from ram newrec = tmprec; pageno = ((unsigned long)newrec - (unsigned long)TIMEZONE_START)/PAGE_SIZE; temp_char = (unsigned long *)((unsigned long)TIMEZONE_START + (pageno * PAGE_SIZE)); offset = (unsigned long)newrec - (unsigned long)temp_char; memcpy((unsigned char *)temp_page,(unsigned char *)temp_char,PAGE_SIZE); newrec = (employee_rec *)((unsigned long)temp_page + offset); memcpy(newrec,pbuffer,sizeof(employee_rec)); writeerr = FlashErase((unsigned long)tmprec); writeerr = FlashProgram((unsigned long *)temp_page,(unsigned long)temp_char,PAGE_SIZE); } }else { // matching record already exists writeerr = 0;// return (0); } } }else { if (pbuffer->nextrec == 0xffff) { // no record found in bank newrec = get_free_employee(); if (newrec != NULL) { writeerr = FlashProgram((unsigned long *)pbuffer, (unsigned long)newrec, sizeof(employee_rec)); }else { writeerr = -2; // buffer full } }else { writeerr = 0;// no record found to delete } } free(temp_rec); //free(temp_page); return(writeerr); }
    9. Event bank Application functions : This function is used for reading and sending the events
    10. void SendAllEvent() { event_rec *reference; unsigned long count = 0x00000000; unsigned int byte_no,i; unsigned char checksum; reference = EVENT_START + count; /// Incrementing reference as to point to start location count = count + 1; byte_no = 2; for(; count <= MAX_EVENT_REC; count++) { if (reference->event == 0xFF) { reference++; } else { sprintf(tx_buffer_2+byte_no,"%01d",reference->event); sprintf(tx_buffer_2+byte_no+1,"%02d",reference->year); sprintf(tx_buffer_2+byte_no+3,"%02d",reference->month); sprintf(tx_buffer_2+byte_no+5,"%02d",reference->date); sprintf(tx_buffer_2+byte_no+7,"%02d",reference->hour); sprintf(tx_buffer_2+byte_no+9,"%02d",reference->min); sprintf(tx_buffer_2+byte_no+11,"%02d",reference->sec);; sprintf(tx_buffer_2+byte_no+13,"%08d",reference->empid); if(count == MAX_EVENT_REC) {} else { tx_buffer_2[byte_no+21] = ','; } byte_no += 22; reference++; } } }
    11. Employee bank Application functions : These function are used to find the count, delete the entire bank, Add or delete a particular entry.
    12. unsigned char SendTimeZoneCount(void) { time_zone_rec *reference; unsigned int i,count; reference = TIMEZONE_START; count = 0; for(i = 1; i <= MAX_TIME_ZONE; i++) { if (reference->empid != 0xffffffff) { if(reference->nextrec == 0xffff) { count++; } } reference++; } return(count); } /*----------------------------------------------------------------------------------------------- */ long InsertDelTimeZone(unsigned char* tcp_rcv) { time_zone_rec time_zone_temp; long adderr; unsigned char i; time_zone_temp.empid = 0; time_zone_temp.empid = (tcp_rcv[2] * 10000000); time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[3] * 1000000); time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[4] * 100000); time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[5] * 10000) ; time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[6] * 1000) ; time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[7] * 100); time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[8] * 10) ; time_zone_temp.empid = time_zone_temp.empid + (tcp_rcv[9]) ; time_zone_temp.exp_date = (tcp_rcv[10] * 10) ; time_zone_temp.exp_date = time_zone_temp.exp_date + (tcp_rcv[11]) ; time_zone_temp.exp_month =(tcp_rcv[12] * 10) ; time_zone_temp.exp_month = time_zone_temp.exp_month + (tcp_rcv[13]) ; time_zone_temp.exp_year = (tcp_rcv[16] * 10) ; time_zone_temp.exp_year = time_zone_temp.exp_year + (tcp_rcv[17]) ; insert_attendence_log(Access_bank_upload,0,time_zone_temp.empid); if(tcp_rcv[1] == 'C') { time_zone_temp.nextrec = 0xffff; } else if (tcp_rcv[1] == 'D') ///For deleting record { time_zone_temp.nextrec = 0x0000; adderr = add_time_zone(&time_zone_temp); return(adderr); } for(i=0;i<=5;i++) { time_zone_temp.reserved[i] = 0x00; } time_zone_temp.reserve = 0x00; adderr = add_time_zone(&time_zone_temp); return(adderr); } /*----------------------------------------------------------------------------------------------- */ long DelAllTimeZone(void) { long ret_val = -1; unsigned long totalpages; unsigned long address; totalpages = (TIMEZONE_PAGES); address = (unsigned long )TIMEZONE_START; while(totalpages--) { ret_val = FlashErase(address); address += PAGE_SIZE; } return(ret_val);//-1 = Error, 0 = Success }

    Final Software screenshots

    1. Connection_tab


    2. Selecting_COM_port


    3. Selecting_Baudrate


    4. Clicking_on_Connect_Button


    5. Waiting_for_connection


    6. Error_in_connection


    7. Device_getting_successfully_connected


    8. Upload_Tab


    9. Entering_card_number


    10. Selecting_expiry_date


    11. Error_connecting_device_popup


    12. Card_uploaded_Successfully


    13. Reading_controller_date_time


    14. synchronizing_Controller_date_Time_with_PC


    15. Download_log_Tab


    16. Log_being_shown_on_grid


    17. Logs_text_file_being_generated


    18. Log_data_in_text_file






    Output files

  • Software .exe file
  • Software code
  • Serial .c file
  • Serial .h file