I may be mere steel but my heart melts when you're around.
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rate Thread Display Modes
  #16   Spotlight this post!  
Unread 12-10-2005, 23:28
Matt Krass's Avatar
Matt Krass Matt Krass is offline
"Old" and Cranky. Get off my lawn!
AKA: Dark Ages
FRC #0263 (Sachem Aftershock)
Team Role: Mentor
 
Join Date: Oct 2002
Rookie Year: 2002
Location: Long Island, NY
Posts: 1,187
Matt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond repute
Send a message via AIM to Matt Krass
Re: EEPROM Code

It risks getting caught in an infinite loop waiting for the queue and breaks the comm sync on the controller?
__________________
Matt Krass
If I suggest something to try and fix a problem, and you don't understand what I mean, please PM me!

I'm a FIRST relic of sorts, I remember when we used PBASIC and we got CH Flightsticks in the KoP. In my day we didn't have motorized carts, we pushed our robots uphill, both ways! (Houston 2003!)
  #17   Spotlight this post!  
Unread 12-10-2005, 23:29
sciguy125 sciguy125 is offline
Electrical Engineer
AKA: Phil Baltar
FRC #1351
Team Role: College Student
 
Join Date: Jan 2005
Rookie Year: 2004
Location: Sunnyvale, CA
Posts: 519
sciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond reputesciguy125 has a reputation beyond repute
Send a message via AIM to sciguy125 Send a message via MSN to sciguy125 Send a message via Yahoo to sciguy125
Re: EEPROM Code

Quote:
Originally Posted by Kevin Watson
Ugh, I just realized this code will cause the red-light-of-death. Anyone care to venture a guess as to why it won't work? I'll post corrected code tomorrow-ish.

-Kevin
I'm not sure, but I don't like that while

Code:
// wait, if necessary, for a free slot on the circular queue
while(EEPROM_Queue_Free_Space() == 0);
Won't that keep looping until the queue is full (which it never will be if it never leaves that loop)?
__________________

-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GE/S/P a-- e y-- r-- s:++ d+ h! X+++
t++ C+ P+ L++ E W++ w M-- V? PS+ PE+
5- R-- tv+ b+ DI+++ D- G
------END GEEK CODE BLOCK------
  #18   Spotlight this post!  
Unread 12-10-2005, 23:31
CJO's Avatar
CJO CJO is offline
Emeritus Pain in the $@#$@#$@#
AKA: Christopher J. O'Connell
None #1097 (Site 3 Engineering)
Team Role: Alumni
 
Join Date: Feb 2003
Location: Latrobe (over the rainbow), CA
Posts: 217
CJO will become famous soon enoughCJO will become famous soon enough
Re: EEPROM Code

Quote:
Originally Posted by Matt Krass
It risks getting caught in an infinite loop waiting for the queue and breaks the comm sync on the controller?
Which is the ultimate result of what I mentioned (put more nicely).
__________________
Team 1097 -- Site 3 Engineering
~~~~~~~~~~~~~~~~~~~~
2003 Sacramento Rookie All Star
2003 Silicon Valley Rookie All Star
2004 Sacramento Engineering Inspiration Award
2004 Sacramento Visualization Award
2004 Outstanding Volunteer Award (G. Glasser)
2004 Silicon Valley Sportsmanship Award
2004 National Visualization Runner Up
2004 Cal Games Finalist
2005 Sacramento Sportsmanship Award
2005 Sacramento #1 seed
2005 Sacramento Finalist

2005 Silicon Valley Sportsmanship Award
2005 Silicon Valley #1 Seed
2005 Silicon Valley Finalist

  #19   Spotlight this post!  
Unread 13-10-2005, 09:52
Mike Bortfeldt Mike Bortfeldt is offline
Registered User
FRC #1126 (& 1511)
Team Role: Mentor
 
Join Date: Oct 2004
Rookie Year: 2004
Location: Rochester, NY
Posts: 119
Mike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud of
Re: EEPROM Code

Kevin,

I haven't tried this, but from the PIC documentation, it looks like you only have to disable the interrupts during the period that you call "pre-write sequence" and "execute the write" in the EEPROM_Write_Handler routine. You should be able to re-enable the interrupts after these 3 lines (from the 39609b Microchip document, section 7.4) rather than waiting until the 2ms write is complete. This may also eliminate the code error by allowing the high priority interrupts to mostly go on schedule.

Mike
  #20   Spotlight this post!  
Unread 13-10-2005, 13:38
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by sciguy125
I'm not sure, but I don't like that while

Code:
// wait, if necessary, for a free slot on the circular queue
while(EEPROM_Queue_Free_Space() == 0);
Won't that keep looping until the queue is full (which it never will be if it never leaves that loop)?
Yep, it's the while loop. I'm trying to write ninety-one bytes, but the queue only has sixteen slots. The code sits in the for loop and eventually EEPROM_Queue_Free_Space() returns zero forever because EEPROM_Write_Handler() isn't getting called to do the actual EEPROM write. The only way the code would work is if he queue size were changed to ninety-one slots. The trig table code seems like something that teams could use, so I'm writing a version that'll generate sin()/cos() and tan() tables in EEPROM. I'll also write the code to do the table lookup.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #21   Spotlight this post!  
Unread 13-10-2005, 14:25
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by Mike Bortfeldt
Kevin,

I haven't tried this, but from the PIC documentation, it looks like you only have to disable the interrupts during the period that you call "pre-write sequence" and "execute the write" in the EEPROM_Write_Handler routine. You should be able to re-enable the interrupts after these 3 lines (from the 39609b Microchip document, section 7.4) rather than waiting until the 2ms write is complete.
Thanks for the suggestion. I'd heard from another source that interrupts had to be disabled for the entire period to ensure a reliable write. As I wasn't sure what the answer was, I decided to err on the conservative side and disable interrupts globally for the entire period (at least on the first revision). When I get some time to work on it, I'll talk with the folks at Microchip to see what they say.

Quote:
Originally Posted by Mike Bortfeldt
This may also eliminate the code error by allowing the high priority interrupts to mostly go on schedule.
That isn't a problem because the high-priority interrupt never gets disabled (i.e., EEPROM_Write_Handler() never gets called). The problem is that getdata() and putdata() won't be called once the code gets stuck in the while() loop, which makes the master processor cranky. BTW, if EEPROM_Write Handler() gets called from Process_Data_From_Master_uP(), disabling the high-priority interrupt isn't a problem because it won't fire-off again until the next SPI packet arrives from the master processor in a period of time much greater than two milliseconds.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #22   Spotlight this post!  
Unread 13-10-2005, 16:46
CJO's Avatar
CJO CJO is offline
Emeritus Pain in the $@#$@#$@#
AKA: Christopher J. O'Connell
None #1097 (Site 3 Engineering)
Team Role: Alumni
 
Join Date: Feb 2003
Location: Latrobe (over the rainbow), CA
Posts: 217
CJO will become famous soon enoughCJO will become famous soon enough
Re: EEPROM Code

On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?
__________________
Team 1097 -- Site 3 Engineering
~~~~~~~~~~~~~~~~~~~~
2003 Sacramento Rookie All Star
2003 Silicon Valley Rookie All Star
2004 Sacramento Engineering Inspiration Award
2004 Sacramento Visualization Award
2004 Outstanding Volunteer Award (G. Glasser)
2004 Silicon Valley Sportsmanship Award
2004 National Visualization Runner Up
2004 Cal Games Finalist
2005 Sacramento Sportsmanship Award
2005 Sacramento #1 seed
2005 Sacramento Finalist

2005 Silicon Valley Sportsmanship Award
2005 Silicon Valley #1 Seed
2005 Silicon Valley Finalist

  #23   Spotlight this post!  
Unread 13-10-2005, 16:51
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by CJO
On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?
The range is 0 to 1023. I guess I should add that bit of information to the read me file.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #24   Spotlight this post!  
Unread 13-10-2005, 16:59
CJO's Avatar
CJO CJO is offline
Emeritus Pain in the $@#$@#$@#
AKA: Christopher J. O'Connell
None #1097 (Site 3 Engineering)
Team Role: Alumni
 
Join Date: Feb 2003
Location: Latrobe (over the rainbow), CA
Posts: 217
CJO will become famous soon enoughCJO will become famous soon enough
Re: EEPROM Code

Thanks, this makes it perfect for recording tables

If you want (say) a table with the five attributes in each row
0, 5, 10, . . . = attribute a
1, 6, 11, . . . = attribute b
2, 7, 12, . . . = attribute c
3, 8, 13, . . . = attribute d
4, 9, 14, . . . = attribute e

Then to find a specific row number, you would take the row number, multiply by 5 and subtract five, and then start reading values?
__________________
Team 1097 -- Site 3 Engineering
~~~~~~~~~~~~~~~~~~~~
2003 Sacramento Rookie All Star
2003 Silicon Valley Rookie All Star
2004 Sacramento Engineering Inspiration Award
2004 Sacramento Visualization Award
2004 Outstanding Volunteer Award (G. Glasser)
2004 Silicon Valley Sportsmanship Award
2004 National Visualization Runner Up
2004 Cal Games Finalist
2005 Sacramento Sportsmanship Award
2005 Sacramento #1 seed
2005 Sacramento Finalist

2005 Silicon Valley Sportsmanship Award
2005 Silicon Valley #1 Seed
2005 Silicon Valley Finalist

  #25   Spotlight this post!  
Unread 13-10-2005, 19:29
Dave Flowerday Dave Flowerday is offline
Software Engineer
VRC #0111 (Wildstang)
Team Role: Engineer
 
Join Date: Feb 2002
Rookie Year: 1995
Location: North Barrington, IL
Posts: 1,366
Dave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond reputeDave Flowerday has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by CJO
On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?
As a rule of thumb, software people always count starting with 0.
  #26   Spotlight this post!  
Unread 13-10-2005, 21:46
CJO's Avatar
CJO CJO is offline
Emeritus Pain in the $@#$@#$@#
AKA: Christopher J. O'Connell
None #1097 (Site 3 Engineering)
Team Role: Alumni
 
Join Date: Feb 2003
Location: Latrobe (over the rainbow), CA
Posts: 217
CJO will become famous soon enoughCJO will become famous soon enough
Re: EEPROM Code

I have met one or two systems which did not, and not having a controller with me at the moment to test it out, I figured I might as well ask.
__________________
Team 1097 -- Site 3 Engineering
~~~~~~~~~~~~~~~~~~~~
2003 Sacramento Rookie All Star
2003 Silicon Valley Rookie All Star
2004 Sacramento Engineering Inspiration Award
2004 Sacramento Visualization Award
2004 Outstanding Volunteer Award (G. Glasser)
2004 Silicon Valley Sportsmanship Award
2004 National Visualization Runner Up
2004 Cal Games Finalist
2005 Sacramento Sportsmanship Award
2005 Sacramento #1 seed
2005 Sacramento Finalist

2005 Silicon Valley Sportsmanship Award
2005 Silicon Valley #1 Seed
2005 Silicon Valley Finalist

  #27   Spotlight this post!  
Unread 14-10-2005, 02:18
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

I just wrote and tested some quick-n-dirty trig table code. Grab a copy of the EEPROM code here and add the code below. I only create a table covering zero to ninety degrees because sin(x) in the other three quadrants can be derived using sin(x) data in quadrant one (exercise left to the student). I'll release a more polished version at a later time.

This code creates the table:

Code:
 
#include <math.h>
#include "printf_lib.h"
#include "eeprom.h"
/*******************************************************************************
*
* FUNCTION: Sine_Table()
*
* PURPOSE: Creates a sine table in EEPROM
*
* CALLED FROM:
*
* PARAMETERS: Unsigned int containing the address.
*
* RETURNS: 1 when finished creating table, 0 otherwise
*
* COMMENTS:
*
*******************************************************************************/
unsigned char Sine_Table(unsigned int address)
{
static unsigned char angle = 0;
static unsigned char done_flag = 0;
static unsigned char sine;
if(EEPROM_Queue_Free_Space() > 0 && done_flag == 0)
{
// calculate normalized sine value
sine = (unsigned char)255.0 * sin((float)angle * 3.14159265 / 180.0);
// write the angle and sine value to EEPROM
EEPROM_Write(address + angle, sine);
// send diagnostic information to the terminal
printf("writing x=%u sin(x)=%u\r", (unsigned int)angle, (unsigned int)sine);
// are we done?
if(angle == 90)
{
done_flag = 1;
printf("Finished!\r\n");
}
else
{
angle++;
}
}
return(done_flag);
}
This code verifies that EEPROM was written correctly:

Code:
 
/*******************************************************************************
*
* FUNCTION: Verify_Sine_Table()
*
* PURPOSE: Creates a sine table in EEPROM
*
* CALLED FROM:
*
* PARAMETERS: Unsigned int containing the address.
*
* RETURNS: 1 when finished creating table, 0 otherwise
*
* COMMENTS:
*
*******************************************************************************/
unsigned char Verify_Sine_Table(unsigned int address)
{
static unsigned char angle = 0;
static unsigned char done_flag = 0;
if(done_flag == 0)
{
if(EEPROM_Read(address+angle) == (unsigned char)(255.0 * sin((float)angle * 3.14159265 / 180.0)))
{
printf("angle=%u verified\r", (unsigned int)angle);
}
else
{
printf("angle=%u failed\r\n", (unsigned int)angle);
}
if(angle == 90)
{
done_flag = 1;
printf("Finished!\r");
}
else
{
angle++;
}
}
return(done_flag);
}
This code goes into Process_Data_From_Master_uP():

Code:
if(Sine_Table(0) == 1)
{
Verify_Sine_Table(0);
}
EEPROM_Write_Handler();
-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #28   Spotlight this post!  
Unread 09-11-2005, 14:11
kc8nod's Avatar
kc8nod kc8nod is offline
Registered User
AKA: Ted Hansen
FRC #1216 (Knights)
Team Role: Mentor
 
Join Date: Jan 2003
Rookie Year: 2003
Location: Oak Park Michigan
Posts: 43
kc8nod is on a distinguished road
Re: EEPROM Code

Quote:
Originally Posted by Kevin Watson
The range is 0 to 1023. I guess I should add that bit of information to the read me file.

-Kevin
Hi Kevin,

I've got a question about EEPROM_Write().

Code:
unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
	unsigned char return_value;

	// return error flag if the queue is full
	if(eeprom_queue_full == FALSE)
	{
		// put the byte and its address on their respective circular queues
		eeprom_queue_data[eeprom_queue_write_index] = data;
		eeprom_queue_address[eeprom_queue_write_index] = address;
	
		// increment the queue byte count
		eeprom_queue_count++;
The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?
  #29   Spotlight this post!  
Unread 09-11-2005, 15:09
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by kc8nod
Hi Kevin,

I've got a question about EEPROM_Write().

Code:
unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
	unsigned char return_value;
 
	// return error flag if the queue is full
	if(eeprom_queue_full == FALSE)
	{
		// put the byte and its address on their respective circular queues
		eeprom_queue_data[eeprom_queue_write_index] = data;
		eeprom_queue_address[eeprom_queue_write_index] = address;
 
		// increment the queue byte count
		eeprom_queue_count++;
The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?
Ugh, It may be a bug, but I won't have time to look at it until this evening.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #30   Spotlight this post!  
Unread 09-11-2005, 18:36
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: EEPROM Code

Quote:
Originally Posted by kc8nod
Hi Kevin,

I've got a question about EEPROM_Write().

Code:
unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
	unsigned char return_value;
 
	// return error flag if the queue is full
	if(eeprom_queue_full == FALSE)
	{
		// put the byte and its address on their respective circular queues
		eeprom_queue_data[eeprom_queue_write_index] = data;
		eeprom_queue_address[eeprom_queue_write_index] = address;
 
		// increment the queue byte count
		eeprom_queue_count++;
The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?
Yep, it certainly looks like a bug, an old bug. I'm not sure what happened, but the latest code isn't on the website. I'd added a EEPROM_Wipe( ) function and incorporated the change Mike Bortfeldt suggested (above), but for some reason the code never got uploaded. I guess I'll have to up the dosage on my brain fart medication <grin>. Thanks for catching this.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Out of the Box Camera Code russell Programming 9 21-10-2009 05:28
Code suddenly fails to initialize miketwalker Programming 11 19-02-2005 15:23
Team THRUST - Kevin's Code and Camera Code Combine Chris_Elston Programming 3 31-01-2005 22:28
Sourceforge for Code Repository and other stuff SilverStar Programming 9 15-01-2005 21:16
heres the code. y this not working omega Programming 16 31-03-2004 15:18


All times are GMT -5. The time now is 13:08.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi