Electronics > Repair
HP 3478A: How to read/write cal SRAM
lmester:
My code uses the Prologix W command to send the cal RAM address (0-255). It also uses the escape sequence when the address is a Prologix reserved character <CR><LF><ESC> and +.
It does look like there is a problem with the binary write or escape sequence logic.
--- Code: ---print #main.Terminal,"Reading calibration data."
print #comm,"D2READING CAL" '"READING CAL" message on meter display
call sleep 10 'Fix for "John AR488" Firmware
y=0
for x = 0 to 255 'Read 256 nibbles
cp$=chr$(x)
'<ESC> sequence to send reserved binary chars to Prologix adapter
select case x
case 13 '<CR>
cp$=esc$+cp$
case 10 '<LF>
cp$=esc$+cp$
case 27 '<ESC>
cp$=esc$+cp$
case 43 '"+"
cp$=esc$+cp$
end select
'Read instrument config data. Each char contains one nibble.
ICal$(x)=QuerySERB$("W"+cp$,cr$,1,1)
if len(ICal$(x))<>1 then
if DBug then print #main.Terminal,"RC:Fail query W :";ICal$(x);" Len:";len(ICal$(x))
print #main.Terminal,"Instrument com fail."
if handle$ <> "NoSave" then
notice "Instrument com fail. Calibration not read."
else
notice "Instrument com fail during calibration data backup!"
end if
InstOK=0:goto [CalAbort] 'Instrument com fail
end if
y=y+1:if y>24 then print #main.Terminal,"*";:y=0
next x
'print #main.Terminal,":";ICal$(0);":";asc(ICal$(0)) 'Test for Girlando 0x00 binary send bug
print #main.Terminal,cr$;"Verify checksums."
CRSum=1 'init read data checsum is valid
for x = 0 to 18 'Checksum for 19 cal entries
cs=0 'Checksum
for y= 0 to 10 '11 nibbles data in each entry
nib=asc(ICal$((x*13)+y+1))
nib=nib and 15 'mask hi nibble
print #main.Terminal,ICal$((x*13)+y+1);
cs=cs+nib
cs=cs and 255 'Truncate to 8 bits
next y
dcs=cs
nib=asc(ICal$((x*13)+12))
nib=nib and 15 'mask hi nibble
print #main.Terminal,ICal$((x*13)+12);
nib=nib * 16 'Shift left 4 bits
cs=cs+nib
cs=cs and 255 'Truncate to 8 bits
nibh=nib
nib=asc(ICal$((x*13)+13))
nib=nib and 15 'mask hi nibble
print #main.Terminal,ICal$((x*13)+13);" : CkSum = (";
print #main.Terminal,nib+nibh;" ";
cs=cs+nib
cs=cs and 255 'Truncate to 8 bits
if dcs>10 then 'Format text
print #main.Terminal,"+ ";dcs;") ";
else
print #main.Terminal,"+ ";dcs;") ";
end if
if cs=255 then
print #main.Terminal,"Checksum OK."
else
if x=5 or x=16 or x=18 then
print #main.Terminal,"Checksum fail unused loc-ignore."
else
print #main.Terminal,"Checksum Fail."
CRSum=0 'Checksum fail
end if
end if
next x
print #main.Terminal,cr$;
print #main.Terminal,"Reading calibration data complete."
if CRSum=1 then
print #main.Terminal,"Calibration data checksum valid."
' if handle$<> "NoSave" then '
print #main.Terminal,"Calibration data saved to:";CalFileU$
open CalFileU$ for output as #5
for x = 0 to 255
print #5,ICal$(x);
next x
close #5
' end if
else
if handle$<> "NoSave" then
print #main.Terminal,"Calibration data not saved. Invalid checksum!"
notice "Calibration data not saved. invalid checksum!"
else
print #main.Terminal,"Invalid checksum during calibration data read!"
notice "Invalid checksum during calibration data backup!"
end if
end if
'====================================================
function QuerySERB$(icmd$,irsp$,blen,timeout)
'This function sends a command, then waits for a response or timeout
'Allows blen # of binary chars to be retrieved.
'icmd$ = command to send
'irsp$ = expected response
'blen = binary data flag >0 = number of expected bytes
'timeout = # seconds to abort (ms resolution)
if icmd$<>"" then if lof(#comm) > 0 then rs$ = input$(#comm, lof(#comm)) 'Flush buffer
if icmd$<>"" then print #comm,icmd$ 'Send command if present
if VTD>0 then call sleep VTD 'Time delay for Arduino adapter
' if DBug then print #main.Terminal,"QuerySERB: READ EOI"
if blen>0 then
print #comm,"++read eoi" 'Request response wait for EOI
' if DBug then print #main.Terminal,"QuerySERB:++read eoi"
else
print #comm,"++read eoi"
' in QueryserB Girlando adapter chokes on this:
' just use read eoi for now
' print #comm,"++read ";asc(right$(irsp$,1)) 'Request response no EOI wait for last char in irsp$
' if DBug then print #main.Terminal,"QuerySERB:++read "; asc(right$(irsp$,1));":"
end if
' if DBug then print #main.Terminal,"QuerySERB: READ EOIx"
ok = 0 'Start with error flag set
dl=0 'Binary data length
er$ = "" 'Instrument response
RTimeS=time$("ms") 'Init the timer
while ETime(RTimeS) < (timeout*1000) and ok = 0
if lof(#comm) > 0 then
rs$ = input$(#comm, lof(#comm))
er$ = er$ + rs$
dl=len(er$)
if blen<>0 then
'Use length if length > 0
if dl>=blen then ok=1 'Got all # bytes?
else
'Use ASCII terminator if length = 0
if instr(er$,irsp$) > 0 then ok = 1 'Found terminating string?
end if
RTimeS=time$("ms") 'Init the timer
end if
call sleep 1 'Don't be a CPU hog
wend
' if counter >0 then print #main.Terminal, "RespQS$: ";counter
QuerySERB$=er$ 'Return string
if ok = 0 then QuerySERB$="" 'Return null for error
' if DBug then print #main.Terminal,"QuerySERB Send:";qt$;icmd$;qt$;"QSB Reply:";qt$;er$;qt$;"QSB Delay:";VTD;"ms"
' if DBug then
' for n=1 to len(er$):print #main.Terminal, asc(mid$(er$,n,1));"%";:next
' end if
if lof(#comm) > 0 then er$ = input$(#comm, lof(#comm)) 'Clear any remaining from buffer
end function
--- End code ---
WaveyDipole:
Thanks Luke. Yes, that also occurred to me when I realised that the first character position in row 3 is the 27th character. So we have the 10th, 13th and 27th characters that are suspect. When looking at how the calibration values reading routine works I then saw this in your HP3478 code:
--- Code: --- select case x
case 13 '<CR>
cp$=esc$+cp$
case 10 '<LF>
cp$=esc$+cp$
case 27 '<ESC>
cp$=esc$+cp$
case 43 '"+"
cp$=esc$+cp$
end select
--- End code ---
Coincidence? The character codes of the characters that are correctly being escaped in your code seem to coincide with the character positions that are incorrect in the cal data output, except maybe character position 43?
The output shown in #157 is very interesting. Thank you David. You have highlighted the lines with the W command (hex 0x57). One can then see the <addr> byte followed by CRLF (0x0d, 0x0a), except in the 10th and 13th request where we only see CRLF. I am curious whether then same is true in the block for address 43 (0x2b).
Now I need to have a look at my code and figure out what the problem is, but I agree, its likely related to the escaping of certain characters.
WaveyDipole:
Does the cal data reading process set ++eoi 1? Could someone run a test reading the cal data with ++eoi 1 set please and post whether they get a successful read or the same result?
djrm:
--- Quote from: WaveyDipole on March 17, 2024, 07:09:53 pm ---Does the cal data reading process set ++eoi 1? Could someone run a test reading the cal data with ++eoi 1 set please and post whether they get a successful read or the same result?
--- End quote ---
Greetings,
T
I see in the console that the hp3478.exe program sends a "++eoi 0" command at startup, If I manually send "++eoi 1" afterthe program has started from another shell then a subsequent read of the cal setting succeeds.
hth David
fenugrec:
Am I reading correctly that you guys are sending (as seen on GPIB) W \r <addr> \n ?
In my code (uses NI libs, tested once or twice on a DOS machine), I was doing " W <addr> \n", in other words no \r at all :
--- Code: --- cmd[0]='W';
cmd[2]='\n';
for (idx=0; idx < CALSIZE; idx++) {
cmd[1] = (uint8_t) idx;
ibwrt(Dev, cmd, 3);
if (ibsta & ERR) {
printf("wrt problem @ 0x%X\n", idx);
goto badexit;
}
ibrd(Dev, &buf[idx], 1);
--- End code ---
It sure looks like there may be some escaping problems in AR488 but removing the \r entirely may help on unpatched firmware ? (cannot test myself)
https://github.com/fenugrec/hp3478a_utils/blob/master/hp3478util.c#L429
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version