Making software using VB language
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
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
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.
Again had started by writing it on paper
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.
	
	// 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 );
    
    
    
#define RX_BUFFER_SIZE_2 					100
#define TX_BUFFER_SIZE_2 					5000
#define	TX_TIMEOUT_2						1
#define	RX_TIMEOUT_2						1
    
    
    
-------------------------------------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; 			
	}
}    
    
    
    
    
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;
	}
} 
        
    
    
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
6965 has 256KB of internal flash. I am using the same flash for storing Employee data and logs.
 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.
#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.
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);
}   
   
   
   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);
}   
   
   
   
   
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++;
		}
	}
}   
   
   
   
 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 
}