Delphi Page

| Home Page| Delphi Code | Visual Basic Code

Code Snippets

K1VG's Grid and Time Algorithms

Tom is a professional programmer and has come up with some elegant alternatives to the code shown in the March and April QST issues. Be aware that some of the code shown below shown on multiple lines should be on a single line (shown in
green).

GregtoJul(M,D,Y : longint): Integer;
// Gregorian Date to Julian Date
var
Factor: integer;
begin
if M < 3 then
Factor := -1
else
Factor := 0;
GregtoJul := (1461*(Factor+4800+Y) div 4)+ ((M-2-(Factor*12))*367) div 12
- (3*((Y+4900+Factor) div 100) div 4)+ D- 32075;

end; {GregtoJul}

function DayOfYear(M,D,Y : Integer) : Integer;
begin
DayOfYear := Succ(GregToJul(M,D,Y)-GregToJul(1,1,Y));
end;

function DayOfYear2(M,D,Y : Integer) : Integer;
const
mthdays : array[1..12] of integer =
(0,31,59,90,120,151,181,212,243,273,304,334);
var
leapyear : integer;
begin
// check for leap-year
leapyear := 0;
if (M > 2) and ((Y mod 4 = 0) and ((Y mod 400 = 0) or (Y mod 100 <> 0))) Then
leapyear := 1;
DayOfYear2 := d+mthdays[m]+leapyear;
end;

Function LatLongToGrid(Lat,Long : Real) : String;
{ Expects Lat/Long in Degrees.Tenths, N&W are +, E&S are - }
Const
Letters = 'ABCDEFGHIJKLMNOPQRSTUVWZYZ';
Numbers = '0123456789';
Var
Lat1,
Long1 : Double;
i1,i2,i3,i4,i5,i6 : Integer;
Begin
Lat1 := Lat + 90.0;
Long1 := Long + 180.0;
i1 := Trunc(Long1 / 20) + 1;
i2 := Trunc(Lat1 / 10) + 1;
i3 := Trunc(Long1 / 2) - (Trunc(Long1 / 20)*10) + 1;
i4 := Trunc(Lat1) - (Trunc(Lat1 / 10) * 10) + 1;
i5 := Trunc(Abs((Trunc(long) - Long)*60.0) / 5) + 1;
If (Trunc(Long) Mod 2) <> 0 Then
i5 := i5 + 12;
i6 := Trunc(Abs((Trunc(Lat)-Lat)*60) / 2.5) + 1;
LatLongToGrid := Letters[i1]+Letters[i2]+ //FN
Numbers[i3]+Numbers[i4]+ //34
Letters[i5]+Letters[i6]; //MV
End;

 

Simple Delphi Clock

Delphi and Visual Basic have controls that simplify time keeping in your logging and other programs. The computer should add the date and time of each contact automatically in your logging program. The Timer control is the basis for an easy to use station clock. The clock's display can be formatted in a variety of ways using some manual code.

Most radio amateur's keep the time on their station computers in Universal Time Coordinated (UTC) although some operators may use local time. A computer's clock can be set to UTC programmatically or by using the Windows Date/Time settings through Control Panel. Windows can be used to set the computer’s time or date by clicking on Start --> Settings --> Control Panel --> Date and Time.

Your amateur radio software can add or subtract the time difference between local time and UTC. This allows a computer’s clock to be kept on the local time and use UTC within the logging environment. You don’t want to reset the difference between UTC and local time every time the program is run. Provide a preferences menu item in your logger to ling to a procedure to save a time difference value to a configuration file. The variable that represents the time zone difference at run time can be loaded from the configuration file. Making and using configuration files will be discussed in a future snippet.

Delphi Clock
Use the code and methodology described in the following discussion to retrieve simple date and time information for your logging program from your computer’s clock. The code snippets that are the basis for programming a simple clock utility can also update the date and time for each contact.

The Timer control in Delphi makes it easy to keep track of time. Some manual code gets the time information into a convenient format for a logging program. So, how can we keep track of time?

The procedure described below places a digital clock on a form's caption bar. A Timer and two Label controls report the time and date. The first Label is used to report the date. A second Label reports the time within the form. The routine places the current time in the form's caption position. The clock's digital readout is formatted by the 'hh:mm' code. Seconds can be included in the display by replacing the existing code with 'hh:mm:ss'. The Interval value selected in the example instructs the Timer control to change the clock once every second.

procedure TForm1.Timer1Timer(Sender: TObject);
var
DateTime : TDateTime;
Timestr,Timestr2 : string;
Datestr : string;

begin
DateTime := Time; // store the current date and time
Timestr2 := TimeToStr(DateTime); // convert the time into a string
Caption := Timestr2; // display the time on the form's caption
{Note This could have been done with the following line of code:
Caption := TimeToStr(Time); }


Timestr := formatDateTime('hh:mm', StrToDateTime(Timestr2));//format the time }
Label1.caption := DateToStr(Date);
Label2.caption := Timestr;
Form1.Caption := Caption; //puts time on Form Bar
// Label2.caption := TimeToStr(Time); //alternative method


end;



To use the code snippet in a program, put two Labels and a Timer control on a new form. Using the Object Inspector, set the Properties Interval for the Timer control to 1000. The units for Interval are milliseconds, 1000 of them equal one second.

As the code is written, the variables DateTime, Timestr, Timestr2 and Datestr are local variables resident in the Timer control event handler. Declare these variables globally and the variables can be used between procedures to report the time and date to the database used with your logger.

Delphi 1 does not recognize the formatting commands in the Timestr statement. If you code in Delphi 1, use the Label2.caption code that follows the double back slashes (captioned alternative method) instead of the existing code. Delete the line beginning with Timestr and delete the original Label2 line.

Copyright © 2003 Stephen J. Gradijan, WB5KIA
Back to Top


Links
Here are links to snippets and code on other sites:

VE3NEA OMNIRIG COM Control for CAT

OmniRig is an excellent COM control that makes programming CAT for multiple rigs relatively easy. It is usable with Delphi, VB, C++ etc. It is developed by Alex, VE3NEA. It's a great tool! Get a copy at www.dxsoft.com/OmniRig/

K0QED AGWPE TCP/IP Control

Download the latest version from
www.coloradoham.com/downloads.htm . This control is in Beta development. Lee posts revisions frequently. A detailed help file is comming soon. He has a small example program on revision 6.

"The install of a revised component isn't too bad once you get the process down. Let me see if I can help with a list:

1. Extract the new component source to wherever it is that you have the previous version

2. Delete .dcu files for the component units. (agwpeintf.dcu and msglogger.dcu in this case)

3. Load the package that you've installed the component in to. I usually just use the Borland Users package. The package is named dcluser50.dpk by default.

4. Compile the package

Now, when you load applications created with earlier versions of the component/package you may run into errors. Stream read errors are the common ones and they happen because there is a property or event defined in the project dfm file that is no longer supported by the component - renamed, removed... You can ignore these errors and the item will be removed from the dfm. Of course, it doesn't do anything to the code that may reference the now defunct property or event - that's a manual step...

---Lee, K0QED

 

LU7DID ActiveX and AGWPE

LU7DID's ActiveX control can control SV2AGW's Packet Engine with Delphi, Visual Basic and C++. (I discovered Pedro's control appears to have some bugs when used with Delphi 5 Pro). The control should be an interesting way to experiment with AGWPE and normal packet or APRS using Delphi.

The ActiveX control works with Visual Basic 5 Professional and probably will work with other versions of VB, including standard. The code at the Yahoo SV2AGW forum may get you started with versions of Delphi other than D5 Pro. The ActiveX did not load properly with my copy of D5P. The example programs output only the raw output from the Soundcard TNC. You need to parse the output strings to get the specific information you need from individual packets. (Join Yahoo groups -- search for SV2AGW, to get the example code provided on the Yahoo forum at the link described below).

Delphi 5 users should also be able to use Pedro's provided VCL. My experience indicates it only may be possible to do this if you use Delphi 5 Enterprise. The VCL appears to load OK in Delphi 5 but Delphi keeps looking for a library that is not distributed with Delphi 5 Professional. The VCL does not work with D6 or D7. I haven't been able to contact Pedro so I don't really know what the problem is. The Delphi problems continue. The ActiveX does not load properly into Delphi 5 Professional but appears fine on D6! When I did get the ActiveX to load with my D5P, the Compiler crashes because it is looking for a copy of vclmid50.bpl which is NOT distributed with Delphi Professional. This could be a problem on my end or related to the fact the control was developed with Delphi 5 Enterprise.

ALTERNATIVES FOR ACCESSING AGWPE

LU7DID's control lets you use high level programming techniques. I tried some low level techniques to communicate with AGWPE with limited success.

I have not gotten the agwpedll32 DLL to access AGWPE with Delphi. Information on the DLLs use with VB is in the develop.zip package on SV2AGW's web site. The DLLdemoVB folder source code works with VB fine although it only has a limited command set. First find the develop.zip files on SV2AGW's web site. Go to the folder agwdll. The VB code can be used as a model for your Delphi code. When you compile your program, the agwdll32.dll needs to be in the same directory as your source code. I believe it is possible to use the DLL with Delphi. Although I haven't been able to figure out how to receive data from AGWE , I can send data to it.

I tried DDE to communicate with AGWPE. My efforts with Delphi have only been partially successful. The Delphi dDeclient does not communicate with AGWPE in the same way it does with Hamscope, WinOrbit or other programs that can use DDE. The client finds those programs automatically but it does not find AGWPE!

TCP to communicate with AGWPE using K0QED's control is relatively easy. See above.

I do not expect that Pedro or George will make any improvements to these tools. George has a new shareware version of AGWPE and Pedro does not answer e-mail to the address I have for him. Regardless, even as the controls are, there is significant potential to successfully use soundcard packet with your project instead of a hardware TNC.

If you have been successful using either Pedro's or Georges techniques to control AGWPE with either Delhi or VB, especially using the DLL with Delphi, I would appreciate hearing from you.

I'll provide some Delphi example code here whenever I figure out how to get it working.

Pedro's site has his AGWPE ActiveX and Delphi VCL. www.qsl.net/lu7did/

The AGWPE (Soundcard Packet Engine) is available at George's site. Get the latest packet engine and look for the file develop.zip. It contains some example code. Of course, download the latest version of the standard AGWPE. www.elcom.gr/sv2agw

The SV2AGW Yahoo stuff is at www.groups.yahoo.com/mygroups/ or something like that.

 

ZS6MAW's MAW Grid/Loc Control. Marinus has taken the QST Great Circle and Grid programs and made a Delphi control! He has versions for D5, D6, and D7. He provides an example program showing how to use the control as shown below.

To get the latest package visit his web site at http://home.telkomsa.net/willemstijn/

 

Mapping conversion algorithms Geodesy by KC2GUI-- Original routines and routines converted from John Snyder's Map Projections... are available by e-mailing Victor Fraenckel at [email protected] Note: the last letter in vfraenc1 is the numeral one not the letter ell. Put the words GEODESY VB or GEODESY DELPHI somewhere on the subject line.

Back to Top

Applications
Here are links or downloads for source code for complete applications:

KIA K0QED AGWPE KIA K0QED AGWPE is a simple demonstration of Lee's TCP/IP control described above. As of 11/24/2003, this is a Beta...not all the commands are fully implemented. It receives APRS on 144.39 Mhz beautifully and should also receive DXCluster Packet signals etc. not in UI frames as soon as I discover how to handle byte arrays.

The example currently uses a timer and Application.ProcessMessages ... threads would be better. Anyone have any ideas?

SORRY...The example code is not ready yet. Try again end of January.

Download Example Source for use with Delphi Standard

Download Example Source for use with Delphi Pro etc.

The second example is more elaborate because it uses Delphi features not available with Delphi Standard.

If you successfuly use the control example, I would appreciate an e-mail. I like to know the code is being used...Thanks.

 

KIA TENTEN KIA TEN-TEN Lookup is an application programmed in Delphi to access the TenTen limited callsign/member number database. TenTen is an organization with aims of keeping the ten meter band active, especially during periods of relative low sunspot activity as is now approaching. They sponsor contests, nets and numerous awards.

The program returns a membership number when a callsign is entered or a callsignwhen a number is entered. A nice operating aid if you are 'collecting' 10-10 numbers. Modify the code to work with your own logger or to access other small databases. Version 1.0 uses a text base database
Version 2.0 uses a dbf database and is faster. Version 2.0 requires the free database control tDBF (This project used Version 6.0). If you don't have Delphi, read the Pascal algorithms with a text editor. Code them in Visual Basic etc. using the Pascasl text as a guide. Version 1.0 uses K4HAV's 1010.txt data file. Version 2.0 uses the same file but converts the information into a dbf file with the free control for Delphi for stand alone database applications called tDBF. Search the Internet for the latest version posted on SourceForge.

Send me an e-mail with the words TENTEN Version 1.0 or TENTEN Version 2.0 in the subject line and I would be glad to send you a copy of the source code via e-mail.

 

WB5KIA Bearing/List Combine the Bearing/Distance and List utilities from March and April QST. This utility uses the SMALOC.TXT database described in April QST. If you didn't download the little database at www.arrl.org/files/qst-binaries that is included in the file 0304Grad.zip, its included here. For more locations to populate the SMALOC.TXT file you might try: http://geography.about.com/gi/dynamic/offsite.htm?site=http%3A%2F%2Fwww.bcca.org%
2Fmisc%2Fqiblih%2Flatlong.html or a standard atlas (be sure to change the deg,min,sec format to decimal deg. and use the correct sign!)

The country file that is used with the shareware CT DOS logging program is a text file. It has coordinate information that can be used if one modifies the file or the source code. K1EA recently released the CT program into the public domain ...www.k1ea.com

Download Bearing/List Source Code

 

KC2GUI SunRiseSet Program SunRiseSet will compute the rising and setting phenomena for any day of the year for any latitude between +65 degrees and -65 degrees. The program calculates the Sun's rise and set times as well as the times for Civil, Nautical and Astronomical Twilight. The program is written in Delphi. I use Delphi7 but I have compiled SunRiseSet using Delphi4 as well. It should compile for D4-7. The program is open source and can be freely passed about and modified. Read the comments at the top of every module concerning the public licensing. SunRiseSet is built using several modules that I have written:

MapStuff - for various Geodesy related items
StrTokenizer - to break delimited strings into tokens
WICStrings - for my version of string utilities
RiseSet - for calculating the Rise/Set phenomena

Notice that I use a somewhat structured approach to writing code. For the controls that the user interacts with, I use meaningful names such as edtLat for an edit control or btnDoIt for a button control or lblSRTime for a label. This is a good way to help with the code documentation.

SunRiseSet

Take a look at the code in the module AppSunRise.pas. The bulk of the code is used to gather input from the user and to check the validity of that input. The Keypress routines for the input of latitude and longitude insure that only numeric data (and the backspace key) is allowed and constrains the user to entering only one decimal point. Each keypress is also checked against a set of valid characters maintained in the sets numset and delset. Since I have tried to make the input of latitude and longitude as free-form as possible, these values can be entered as dd.ddd, dd,mm.mmm or dd,mm,ss.sss. Here I am using the comma as a delimiter between the values (tokens). You may also use semicolon or colon for the delimiter. Upon exit from the edtLat and edtLong fields the text you entered is parsed by ParseLatLong in Mapstuff which returns the input value in decimal degrees. Similar sort of checking is done on the other input fields. Note how I have handled the business of N/S latitude and E/W longitude. Using the BitButtons btnNS and btnEW in this manner meant that I do not have to deal with the plus and minus in edtLat and edtLong. I urge you to look through my code in order to gain an understanding of how everything goes together and works.

73 de Vic, KC2GUI

Copyright © 2003 Vic Fraenckel, released under GPL license.

Download SunRiseSet Source Code

Back to Top

 

Suggestions from other Programmers

Here are comments from readers that may be of value for Delphi users:

ZS6MAW Database Programming. "One thing I must mention though that Is important in Databaseprogramming is to use Datamodules in Delphi. The reason for this is that all the business rules should reside on the events of the queries and all logic must be centralized. This way I have found you are able tochange your main interface for data input without having to change any
rules.
73's

Marinus Willemstijn
ZS6MAW"

N8ME - Using Strings with CASE Statements. You mentioned that Delphi doesn't support strings in case statments, which is true, but it sounds like you may have taken a more complicated solution. I thought I'd share a couple of the techniques I have used

The simples is a series if .. else if statements
if s = 'String 1' then
...
else if s = 'String 2' then
...
else if

While this is slightly more typing that the BASIC case statement, the underlying computation and performance is essentially the same. If performance is an issue, try to place the most likely strings first as Delphi has to do a string comparison for each string in the list. However, here's my preferred approach:

if the first character of the strings is unique, since a Delphi case statement can work on a character, you can do something like:

case s[1] of
'a' : ...
'b' : ...

If the first character isn't unique, but some other character is, you can use that character.

If there is no unique character, you can sometimes use nested case statements or an if statement within the case. For example, if the strings are year, month, day, hour, minute and second:

case s[1] of
'd' : day case
'h' : hour case
'm' : if s[2] = 'i'
then minute case
else month case
's' : second case
'y' : year case
end

It's usually a good idea with a Delphi case to put the selectors in order. That way the compiler may optimize the code to an indexed lookup and jump.

Again, thanks for the article. I hope it does inspire some new programmers.

73,
Mark"

 

Back to Top

 

DELPHI CONTROLS


January/February 2003

Early January, a leading developer of controls for use with Delphi announced it was going out of business. TurboPower had an excellent reputation but is closing down. Since it is leaving the business, they decided to release most of their code including products called Orpheus and Async Professional under a GPL license. This means that Orpheus, Async Professional and several other products are available for FREE. Read all about it at www.turbopower.com and search for the files at http://sourceforge.net/search/ using the words 'TurboPower'. Most of the controls they intend to release have been posted.

Their serial communications control, Async Professional, is more complicated than the serial control mentioned in the February QST but is more stable (I'm converting most of my projects to use it.)

 

updated 27/November/2004