Appendix A - Numerical representation of data
Probably you are a little bit confused about the numerical notation of the command bytes etc. in this document. Don't worry, it's quite simple. This appendix is intended for developers and programmers or any interested party who want's to understand better what's going on here.
A number is a number is a number...
A number is a number is a number - no matter how you present it. We are used to the decimal system, i.e. we use ten different symbols to represent our numbers. If we have to count farther then ten we use the placement of the digits to show it's weight. Let's take the number 142.
- 1 times 100
- 4 times 10
- 2 times 1
(1 x 100) + (4 x 10) + (2 x 1) = 142
So we use base 10 as our usual representation system. The first (rightmost) digit has a weight of 1, the next position is ten times larger, the next position is ten times larger and so on. For a base 10 number system we need ten different symbols to represent the individual value of each position: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Yet, 142 can be represented in many other ways, with different numerical bases. Like 2. This means that the rightmost digit still is one, but the next position is two times larger, the next position is two times larger and so on. With base 2 we only need two symbols to represent our number: we choose 0 and 1.
So 142 at base 2 is shown as 10001110.
10001110 is (from left to right)
- 1 times 128
- 0 times 64
- 0 times 32
- 0 times 16
- 1 times 8
- 1 times 4
- 1 times 2
- 0 times 1
(1x 128) + (1 x 8) + (1 x 4) + (1 x 2) = 142
Enter the computer
The above method, using binary representation is useful sometimes when working with computers. Why? Because each position can be either 0 or 1, on or off, and that's just what our computer works with: two states, on/off, signal/no signal, charge/no charge etc. This basic unit of information is called one bit.
Still, binary notation is somewhat tedious because large numbers get pretty long and hard to read. So with programmers you will most often find yet another base for numerical data: hexadecimal. That's base 16. Our rightmost digit has a weight of one, the next has a weight of 16, then the next one of 256 and so on, each position 16 times larger than the previous. Isn't that stupid?
No, it isn't stupid. Working with computers you soon learn that basic memory chunks are organized in 8 bit groups, called one byte. This has a historical reason, but is still used as a basic memory unit, even if our current computers usually work with larger chunks 32 or 64 bits long. Still we measure the size of a file in how many (thousands or million) bytes it occupies.
The hexadecimal (base 16) system
But let's look at hexadecimal data. As we already know, hexadecimal means that the base is 16, each position is 16 times the previous positions weight. So 142 becomes:
- 0 times 256
- 8 times 16
- 14 times 1
(8 x 16) + (14 x 1) = 142
Written in hexadecimal - now, wait a minute. I can write '8' as the leftmost (highest) digit, but how do I write '14'. That's two symbols for one position. Exactly, we need 16 symbols to write a number in hexadecimal (base 16) system. We use 0 to 9 and then A to F. 'A' represents a value of 10, 'B' is eleven and so on. 14 is 'E'. So 142 (in decimal) becomes 8E in hexadecimal.
The hexadecimal system is convenient for programmers, because two symbols are sufficient to describe one byte. One byte consists of 8 bits, so each symbol in hex representation takes care of 4 bits. That's quite easy to remember and handle by a programmer (well, most).
Let's look at other examples: 255 in decimal is (16 x 16) + (16 x 1). And 16 is written as 'F' in hex notation. So 255 decimal becomes FF in hex (and is the largest number still fitting in one byte). What is decimal 1561 in hex? (6 x 256) + (1 x 16) + (9 x 1) = 619. That number spans more than one byte, it takes two.
Prefixes for other numeric bases
But how do we know that 619 is meant as a base 16 number, and not a base 10 number? So how do we know that 619 equals 1561 in decimal and not sixhundred and nineteen? This is where a notational prefix comes in.
To differentiate between various number representations, numbers not in decimal format (the standard) are usually prefixed by some other symbols. This stems from different programming languages, where the programmer has to tell the software how he want's the nmber to be interpreted.
One of the most widely used programming languages is 'C', so the prefixes used there also widely used for designation of the base used for a number. In C the prefix for hexadecimal numbers is 0x. So my 1561 (decimal, no prefix) becomes 0x619 in hexadecimal. 142 is 0x8E.
Unfortunately other programming languages use different prefix notations. For example basic uses '&h' and Pascal uses the '$'. Since I mostly used Pascal (Delphi) when I started these pages I use the $symbol as a prefix for hexadecimal notation. So everytime you see something like $FE you know I am talking about one byte with the decimal value of 254.
Enter BCD - Binary coded Decimal
So what has all this to do with the way Icom codes numerical values in the CI-V protocol? Easy. Let's look at the command to read an S-Meter value. The documentation says that the value returned can be zero to 255. So that would easily fit in one byte, written in hex as $00 to $FF.
Now the problem is: an S-Meter can return any value from $00 to $FF. Any value! That includes bytes like $FE, $FC, $FD etc. But these bytes have a very special meaning in the CI-V protocol.
Consider this: I have sent an interrogation command to my trusty IC-R8500 to tell me the current S-Meter reading. The response might be 163 or $A3 in hex:
All ok so far. But what when the S-Meter value rises and returns 253 or $FD in hex?
Oops, my receiving routine, which looks for $FD as an end of telegram delimiter would suddenly stop one byte earlier than it should. It does not know how to discern between $FD as a data value (S-Meter) or $FD as the end-of-telegram delimiter!
So representing arbitrary data in hexadecimal is dangerous, as it corrupts the protocol reserved values. The solution is to represent each data value in something called BCD - Binary Coded Decimal.
What is done is to take each decimal digit and put it into one half of a byte. So I would write 253 as $02 $53 in hexadecimal. And that's how Icom sends all data:
This makes it a little harder for me (as a programmer) to read the value out of the telegram, but it avoids 'forbidden' values. Whatever value the S-Meter shows, it will never be sent as $FD, $FA, $FC or anything else. Only the digits 0 to 9 can show up. Ok, I have to check whether one or two bytes are returned, the telegram is always as short as possible. S-Meter values below 100 would return with a shorter telegram:
But that's a task for the programmer.