HP 16500C Notes
This file is part of OpenGPIB.
For details, see http://opengpib.sourceforge.net
Copyright (C) 2008-2009 Doug Springer <gpib a t rickyrockrat d o t net>
OpenGPIB is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3
as published by the Free Software Foundation. Note that permission
is not granted to redistribute this program under the terms of any
other version of the General Public License.
OpenGPIB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenGPIB. If not, see <http://www.gnu.org/licenses/>.
The License should be in the file called COPYING.
The HP16500C manuals do not describe the configuration data stream.
These notes describe some of the reverse-engineering done to figure out
the fields in the configuration data returned from the :SYSTEM:SETUP?
command.
The data stream begins as a block (as described in the programming manual). Here is an example file dump of the start of the config file. Sections are cut out that are not yet decoded.
0 1 2 3 4 5 6
7 8 9 A B C D
E F
00000000 23 38 30 30 32 32 30 31 36 30 43 4f 4e 46 49 47 #800220160CONFIG
00000010
20 20 20 20 02 22 00 00 80 c8 4d 41 43 48 49
4e ."....MACHIN
00000020 45 20 31 20 00 00 00 00 00 01 00 00 00 00 00 00 E 1 ............
00000030 00 00 00 00 00 02 ff ff ff ff 00 20 00 06 00 20 ........... ...
00000040 00 06 00 66 00 00 00 2a aa aa ff ff ff ff ff ff ...f...*........
00000050 ff ff ff ff ff ff ff ff ff ff 4d 41 43 48 49 4e ..........MACHIN
00000060 45 20 32 20 00 00 00 00 00 00 00 00 00 00 00 00 E 2 ............
00000070 00 00 00 00 00 02 ff ff ff ff 00 20 00 18 00 20 ........... ...
00000080 00 18 00 78 00 00 00 2a aa aa ff ff ff ff ff ff ...x...*........
00000090 ff ff ff ff ff ff ff ff ff ff 00 00 00 04 00 1f ................
000000a0 ff e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000270 ff ff 00 00 00 00 00 00 00 00 00 00 01 4a ff ff .............J..
00000280 ff ff 00 00 00 00 00 00 00 00 00 00 00 64 ff ff .............d..
00000290 ff ff 00 00 43 4c 4b 20 20 20 00 00 00 00 00 af ....CLK ......
000002a0 df 30 00 00 00 00 01 01 01 37 44 49 4f 31 20 20 .0.......7DIO1
000002b0 00 00 00 01 00 af df 3c 00 00 00 00 01 01 02 37 .......<.......7
000002c0 44 49 4f 32 20 20 00 00 00 01 00 af df 48 00 00 DIO2 .......H..
000002d0 00 00 01 01 03 37 52 2f 4c 20 20 20 00 00 00 01 .....7R/L ....
000002e0 00 af df 54 00 00 00 00 01 00 04 37 50 4f 4c 20 ...T.......7POL
000002f0 20 20 00 00 00 01 00 af df 60 00 00 00 00 01 01 .......`......
00000300 05 37 4c 44 20 20 20 20 00 00 00 01 00 af df 6c .7LD .......l
00000310 00 00 00 00 01 01 06 37 30 45 20 20 20 20 00 00 .......70E ..
Looking at the dump above, you can clearly see the two machine names, so that's pretty obvious.
Byte 29 tells us this machine 1 is in timing mode. Byte 31 tells us we are using full channel mode.
For
some reason, the pod assignment map (3D, 41, and 43) is
duplicated places (at least in the timing mode I tested). It tells
us pod 1/2 is assigned to machine 1. You'll note that machine 2 has pod
3/4 assigned to it, but since it is off, the point is moot.
Here is the C structure for the two machine entries above:
#define POD_INFO_A1 0x02
#define POD_INFO_A2 0x04
#define POD_INFO_A3 0x08
#define POD_INFO_A4 0x10
/**10 bytes */
struct pod_assignment {
uint8 unknown1[3];
uint8 pod_info0; /**pod_info0 and 1 always seem to be equal to each other No pods=0 */
uint8 unknown2[3];
uint8 pod_info1;
uint8 unknown3;
uint8 pod_info2; /**this is 0x06 with no pods assigned to either
analyzer, 0x66 if pod1/2, 0x78 if pod 3/4, 0x1E if pod1,2,3,4. */
}__attribute__((__packed__));
/**defines for the mode byte below */
#define MACHINE_MODE_OFF 0
#define MACHINE_MODE_TIMING 1
#define MACHINE_MODE_STATE 2
#define MACHINE_MODE_CMP_SPA 3
/*defines for mode2 below */
#define MACHINE_MODE2_FULL 0
#define MACHINE_MODE2_HALF 1
/*64 bytes per machine config*/
struct machine_config {
char name[11];
uint8 unknown3[4];
uint8 mode; /**0=off,1=timing,2=state,3=statecompare or SPA */
uint8 unknown4[7];
uint8 mode2; /*0=fullchannel, 1=half channel*/
uint8 unknown5[8];
struct pod_assignment assign;
uint8 un[22];
}__attribute__((__packed__));
The label sections begin at 294. If you look at just this section (22 bytes per line):
43 4C 4B 20 20 20 00 00 00 00 00 AF DF 30 00 00 00 00 01 01 01 37
44 49 4F 31 20 20 00 00 00 01 00 AF DF 3C 00 00 00 00 01 01 02 37
|Label
|
B P ADDR
B E S
You will see that it starts with a label name that is always 6 bytes. The above above bits are as follows:
B=#bits (lines) for this signal - it seems to be repeated twice, so I assume one means something else.
E=enabled
S=Sequence #
ADDR
is an offset further into the code to the bit positions. After *much*
scrounging about, I came up with this formula: Take the address here
(i.e. AFDF30) subtract AF6BFC from it and you get the real absolute
(i.e. beginning of file) offset.
At this address you will find the following bit fields
00 00 00 00 00 00 00 00 00 00 00 00
?J ?? H4L H3L H2L H1L ????
Decoding, I suspect the top 2 bytes are the clock. The J is for J Clock. The H4L means High byte Low byte for pod 4.
Here are the C structures and defines for this:
#define LABEL_RECORD_LEN 22
#define LABEL_MAP_LEN 12
#define POD_ARRAYSIZE 10
struct label_map {
/**offset 0= hi byte. */
uint8 clk_pods[POD_ARRAYSIZE]; /**0 and 1 index are clk, 2 idx is hi byte of pod4 */
uint8 unknown;
}__attribute__((__packed__));
T
struct labels {
char name[6];
uint8 unknown1[3];
uint8 polarity;
uint8 unknown2;
uint8 strange_offset;
uint16 strange_offsetlo;
uint8 unknown3[4];
uint8 bits;
uint8 enable;
uint8 sequence;
uint32 actual_offset;
struct label_map map;
}__attribute__((__packed__));