DELPHI PROGRAMMING MAIN PAGE | | |MICROLAN STUFF MAIN PAGE | | |Other material for programmers

Delphi: Data type vocabulary for MicroLan (aka 1-wire) programming

This has good information, and a search button at the bottom of the page

Please don't dismiss it because it isn't full of graphics, scripts, cookies, etc!



Click here if you want to know more about the source and format of these pages.


Delphi Data Types for MicroLan Programmers

This tutorial was written to save you some of the confusion I went through because of differences between what Borland calls, say, a byte, and the way those terms are used in the Dallas documentation. There are also some observations which you may find useful even in non- MicroLan (aka 1-Wire) work.

Some essentials:
Delphi type   Dallas type name    Description of type
    name        (SDK docs)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  smallint         short                   16-bit signed
  longint          long                    32-bit signed
  shortint         char                    8-bit signed
  byte             unsigned char           8-bit unsigned
Next I offer a brief introduction to the concept of "type". (Experienced programmers... just be patient for about 10 paragraphs, please?)

With a pen and paper, I don't have to think at all before I write down my dog's name, the number of children in my class, or how far it is to my home. Things aren't so simple when you go to put data into a computer.

In every programming language, to a greater or lesser degree, you have to respect certain rules about the "containers" (variables, fields) into which you put data. Pascal, the basis of Delphi, insists that you be quite particular about these rules... which is a good thing. It minimizes the places bugs can hide.

Put those thoughts to one side for a moment. Think about the lowest level of the computer: An organized collection of ones and zeros. With ONLY ones and zeros, we can tell the computer what we want the program to do, store how many children are in the class, store the words Shakespeare wrote... or even store the words of this tutorial, and some graphics to go with it (if we were graphics inclined!!)

The "secret" is that, say, 01000001 in one place will be treated as 65, but in another place it will be understood to mean "A". How the 1s and 0s are interpreted depends on how we got to where we are.

There are many "codes" in common use.... and you don't often have to worry much about the details. When you write a program in Delphi, before you save something in a variable, you declare tell the program what sort of data you will be putting in the variable. This is known as declaring the variable's type. Once the type has been declared, Delphi takes care of the messy stuff.

Different types have different pros and cons. Byte type variables (using the word as Delphi uses it) can only store 0, 1, 2, 3... 253, 254, or 255... but those variables take up very little space (once more important than it is today), and arithmetic with byte-type variables is quicker than it is with more complex data types. The valuable range checking that you can turn on in Delphi (Just put {$R+} in your code. This is UNRELATED to the IMPORTANT {$R *.DFM} which you'll find Delphi has put in your code, and which you should leave alone. RAnge checking is not applied to the inc or dec functions. I think this is so that they can just roll over if you "try" to increment (or decrement) something too many times.)

The pros and cons of the various data types for storing numbers are...
How much space they take to store a value.
What is the biggest number you can store?
Can you store negative numbers?
Are you restricted to whole numbers, or can you show fractions?
How much resolution does the data type offer? Some data types let you store very big numbers, but you can't store many decimal places of fraction with some of them.

Right. That's your introduction. If you need more, pester me to write the relevant articles for my more general online Delphi Tutorial. (How to contact me is available via the link at the bottom of the page.)

So. I hope the concise table further up the page now makes more sense if you needed the background stuff. Now I'll present some more specific odds and ends. Apologies if I've got anything wrong... but here's my best guess.... Towards the end of the tutorial there are some less central things which may help.


I'm pretty sure that Dallas calls a signed 8 bit number a "byte" whereas in Delphi-speak a byte is an unsigned 8 bit number. The TMEX routine TMTouchByte returns a signed 16 bit number, not a byte, in spite of it's name. It is true that when all is well often only interested in 8 bits of what is returned. Use the Delphi "smallint" type for variables filled by TMTouchByte.


Some Delphi chips, e.g. the DS2423 counter, return an unsigned 32 bit number.... but, unless you want to use the cardinal type, Delphi doesn't (as far as I know!) offer an unsigned 32 bit type. It seems a bit silly to incur the overheads of one of the "real" types, say single. My "solution" is to throw away the most significant bit in the counter and put the answer in a longint type variable. So the counter, as seen by my program, rolls over after 2 billion counts instead of after 4 billion (or is it after 1 billion instead of 2?) In my applications, the "faster" rollover is NOT a great concern! The following shows how to implement my solution. It is simplified for clarity. It assumes that the 32 bit number is passed from the Dallas chip 8 bits at a time, as is the case with the DS2423. A real program would have error handling and some other stuff preceding what I show below.
var liAns:longint;

liAns:=GetByteFromChip; (*Assumes chip sends least significant byte first*)
liAns:=GetByteFromChip+(liAns*256);
liAns:=GetByteFromChip+(liAns*256);
liAns:=(GetByteFromChip and $7F)+(liAns*256);

The following is presented in a "Just do it" tone of voice. I don't fully understand why one thing works and the other doesn't... but maybe I can save you some puzzling.

Each Dallas chip has it's own 8 byte ID. I tend to store the IDs of the chips in a system in an array of arrays of bytes. Prior to accessing a chip, you have to tell the TMEX interface WHICH chip you want to access. Part of doing this is to put the chip's id into a scratchpad chunk of memory, and then using a pointer with a call of TMRom. When you see the "@" sign in Delphi code, you are seeing pointers in use. Search my demo programs for the variable siaDMLRom (or calls of TMRom) and you'll see instances of what I am talking about.

They mystery "secret": the way to establish the "scratchpad chunk of memory" is to declare it as an array of smallint elements, not of byte elements. The latter seems to throw up problems if one of the bytes in the chip's ID is $FF.

While we're on the subject of the TMRom buffer, it does want to be NINE smallints long, not the eight that you might assume. If memory serves, the last smallint is used for returning the checksum that can be used to be sure all went well with your call to TMEX.


Use a longint type variable for holding the session handle, i.e. the value returned by TMExtendedStartSession. Most of the other routines I call want a smallint type variable to return a value to. (E.g. TMAccess, TMTouchByte, TMSetup, TMTouchReset, TMValidSession)


In English, we speak of words being made from letters. Okay so far, I hope. In mathematics, we speak of numbers being made from digits. 4 is both number AND a digit, but 44 is a number made of the digit "4" twice. In binary mathematics there are just two digits, 1 and zero. A binary number is made of bits... Binary digITs. In the early days, the electronics processed those bits in groups of eight, and eight bits became called a "byte"... an elision of "by eight." (There was even something called a nibble- a group of four bits- but that doesn't concern us here, and I don't think that Apple's and nibbles were ever connected.)

Any machine, and most languages, are set up to deal most easily with bits in certain sized groups. As I said, many early machines processed the bits eight bits at a time. Then we got machines that worked with 16 bits at a time, and now we're up to 64 bit machines (and higher in esoteric situations). The size of the "normal" group of bits is the machine's word length... in general terms. In Delphi, the term "word" has a different meaning: It always means an unsigned 16 bit number, i.e. "word" type variables can hold any whole number from 0 to 65535.

Happy yet? Don't worry... there's more!

In Delphi version 1, an integer, as far as Delphi is concerned, is a signed 16 bit number. That is, it can store whole numbers from about -32,000 to +32,000. However, in Delphi 2, integer type variables can hold 32 bit signed numbers... which, according to the Delphi 2 help file, means numbers from about -2 billion to numbers about +2 billion. There is a similarly platform dependant type called "cardinal" (not mentioned in the Delphi 1 help file, but it will compile). This is supposed to be an unsigned 16 or 32 bit number. The Delphi 2 help file says that this will hold from 0 to about 64,000 when it is a 16 bit number (which I agree with), but it also says that it will hold from 0 to about 2 billion when it is a 32 bit number. Now either this is wrong, and it will hold from 0 to about 4 billion, or the 32 bit integer can only hold from about -1 billion to about +1 billion. (Or they're both wrong! I'm not multiply in 2x2x2x2x2... to 32 (or is it 31?) 2s to find out for you. I think that (256x256x256x256)-1 will also tell you the biggest 32 bit unsigned number... but again, I'm not doing the sum!

Conclusion? I'm trying to avoid using the Delphi types "integer" and "cardinal". However, if a) You know your program is only going to be run on a 16 bit or 32 bit system, and b) You need maximum processing speed, you may find that integer and cardinal type variables get processed more quickly than other things.

Another legal Delphi data type I avoid is the "real" type. The Delphi 2 help file tells us that this is provided for backward compatibility, but that it is slower than alternatives, such as single and double. These are types you use when you need to be able to show fractions.... and haven't "cheated" you way out of needing them. As an example of the cheating I mean, in some parts of one of my program I store values in centivolts instead of the more obvious, but fraction-needing volts. In other words, I can store 4.27 volts as 427 centivolts and thus avoid the need for a single or double type variable.


   Search this site or the web        powered by FreeFind
 
  Site search Web search
Site Map    What's New    Search


Click here if you're feeling kind! (Promotes my site via "Top100Borland")
Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!

Click here to visit editor's freeware, shareware page.


Link to MicroLan stuff main index
Link to MicroLan Delphi programming main page

Click here to learn how to contact this page's editor, Tom Boyd.


Valid HTML 4.01 Transitional Page WILL BE tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....