Author Topic: Quick Repair: Standford Research PS350 5KV 5mA(Fixed but working on calibration)  (Read 5364 times)

0 Members and 1 Guest are viewing this topic.

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
I thought this would be a longer repair log but it's going to be really quick.
I got a PS350 off eBay for a decent price (made an offer and was accepted)
Listing stated for parts/not working.   transformer loose inside unable to test.

This is the only image I had before the repairs


I I got it and indeed something was loose inside.   I opened it open and barely hanging on was the large 2amp 750uH Inductor 
I did not do any kind of power test at this point for safety reasons.



This was the bad boy



I removed it completely and tested it on the LCR meter and it measure at 775uH and everything else was in spec so it was good but the legs were busted.   I found and ordered a replacement (Part # is  HL-20154/AB from hurricaneelectronics.com.) then thought since it was measuring high anyways I could try un-winding the legs 1/2 turn to lengthen them. which I did.  trimmed to length and cleaned the ends and measured it at 749.3uH (can't beat that) put it back in and gave it the power on test.

It came to life.



so now it was powering up.   I did some quick tests and thing looked ok but there where several switch issues.
on the rear the Set/Mon switch was busted so I replaced it

this is the switch I replaced


and this is new one in place



next I found the front panel Off/On/Trip switch was not functioning correctly in the off position.  ie. once the HV output was enabled it could not be disabled via the switch.  only a power off or a condition which tripped a limit would disable the output

in this image it is the black switch on the left


I removed the switch to properly test is and indeed the off position was always open.  the momentary switch part worked fine so you could enable the output.

this is the switch from the back side.   removing it was easy but the front panel had to be removed to make it easier to work with.


this switch is a Marquardt 1808.0202 6A IP40 Momentary Rocker Switch SPDT On-Off(On).   finding this one was a pain and only found it in the UK.   so again I ordered the part then figured I would try repairing the switch (something I've not done successfully before)

so I opened it up and the contacts where crusted. I pulled the center rocker bar (don't know correct name for it) out and sprayed the whole thing in contact cleaner.  let it set for a bit the used a q-tip to get in there and get that crusty stuff out.   after not to long a time I got the contacts looking pretty good and after reassembling the switch was surprised it worked (meaning it moved to each position correctly, which is usually where I've gone wrong.   I put it on the meter and tested each position and they all worked now.  So I put the switch back in.

While i had it opened I noticed 3 chips where not populated.


these are the GPIB interface chips including the
TMS9914A
75160A
75161A

on the back you see that Opt 01 is installed but these chips and the GPIB connector are not there



I located the IC's on ebay and ordered them.   and I found a GBIP connector with break/out board that will allow me to wire up the 24 pin ribbon correctly I hope and restore the GPIB interface

so now that all that was done I gave it a power on and Low and HV test
this is at 50V


Now shown is my meter reading 50V also so it was working find at a low voltage.

next I hooked up a 1000:1 HV Probe to my meter and connected to the output of the PS350 and programmed in 5000V
after hearing the static sound of it charging up I read 4.996V on the meter so I was getting 4996V out of this supply. :-+



The front switch now worked and I could now turn off the HV output.

I checked more voltage settings and all where within tolerances.

A few final clean up items.  the main board needs a good cleaning off which I have yet to do.
I repaired the case and cleaned it up also

which you may have noticed in the front pictures
here's a side photo as well



all the screws were rusted so I took some fine sand paper to them and cleaned it off the a ultra black paint marker and restored the color to them.  I had to repair the front face as it was bent badly and the rear of the case was bent also which I repaired.

I think I can call this fixed, it was a easy repair really

I also did find the schematics for it so have them as a reference.
Standford wants $100 for the hard copy of the manual with schematics for those wanting original.  you can order on their site www.thinksrs.com

hope you enjoyed this even though I forgot the before photos.

Sandra
« Last Edit: July 24, 2017, 12:44:39 am by smgvbest »
Sandra
(Yes, I am a Woman :p )
 
The following users thanked this post: edavid, rastro, doktor pyta, nidlaX, alm

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
Re: Quick Repair: Standford Research PS350 5KV 5mA (FIXED)
« Reply #1 on: July 07, 2017, 01:37:11 am »
That unit must have been abused. Mechanical damage on the inside, back and front. Maybe shipped loose in a box and knocked around? Dropped multiple times? Seems very smart to me to treat a HV power supply that way :P.
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
Re: Quick Repair: Standford Research PS350 5KV 5mA (FIXED)
« Reply #2 on: July 07, 2017, 02:30:21 am »
good question and very probable. I will say it arrived to me packed very well with a hard foam all around and it was centered in the shipping box which was oversized.

but i agree,  who ever owned it or worked on it (though I see no signs of anyone working on it) was very rough on it.
Sandra
(Yes, I am a Woman :p )
 

Offline BFX

  • Frequent Contributor
  • **
  • Posts: 358
  • Country: sk
Re: Quick Repair: Standford Research PS350 5KV 5mA (FIXED)
« Reply #3 on: July 07, 2017, 08:56:32 am »
 :-+ nice repair and nice photos  8)
enjoy new gear  :-DMM
 

Offline eb4eqa

  • Regular Contributor
  • *
  • Posts: 77
Re: Quick Repair: Standford Research PS350 5KV 5mA (FIXED)
« Reply #4 on: July 07, 2017, 09:21:16 am »
Nice writing and pictures. Thanks for sharing.

Roberto
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
Re: Quick Repair: Standford Research PS350 5KV 5mA (FIXED)
« Reply #5 on: July 16, 2017, 07:34:49 am »
So now that the Unit is working I'm going to get the GPIB interface going again as I stated.
I've ordered and installed the following components.

TMS9914A
75160A
75161A
GPIB Connector

After installing it seems it doesn't work.  I get a Err5 when trying to set the GPIB Address
this is not good.  so apparently my thought that this unit had GPIB was incorrect.  so onto making work anyways.

there was a similar route taken for a PS310 posted here
https://www.eevblog.com/forum/testgear/srs-ps310-rom-code-supports-gpib-option-needed/25/
referring to this post I have a PS350 V1.40 rom dump and soon as I get a 2764 EPROM(Maybe Replace with a 28C64 ) I'll burn one and install which should get me GPIB.  however I'll loose my calibration value's and is the point of this.  to identify the calibration value and if possible figure how to calculate them to improve the calibration.

so first thing I've done is look further at all the IO/MEMORY and other stuff and adding more information to it and more to come as I want to document the EPROM and SRAM addresses.

updated with more details
Code: [Select]
MEMORY ADDRESS OF EPROM: 0000~1FFF (PROGRAM SPACE:8KB,ST M2764A)

SRAM: 4000~47FF (DATA SPACE:2KB,HITACHI HM6116)

IRQ_ROUTIINE:  0038h
SOURCE:  SHEET 6
CLK->(U610)->TIMER @ 976.56hz/0.001024ms   (4Mhz/4096(U610)74HC4020)
GPIB


SRAM ADDRESSES:
SRAM_MISC = 413AH
SRAM_STATUS1 = NA
SRAM_STATUS2 = 401CH

EPROM ADDRESSES:
193BH GPIB COMMAND
1F9EH
19FAH 000019fah: F3 CD D5 11 FB 0E 00 C3 D4 15 CD 9D 17 C2 FD 17 ; óÍÕ.û..ÃÔ.͝.Âý.
                                00001a0ah: 21 8D 1F 11 3C 41 01 09 00 ED B0                ; !..<A...í°     
1F7BH 00001f7bh: 5A 31 33 34                                     ; Z134
1F7FH EPROM_VERSION_NUMBER 00001f7fh: 31 2E 33 34                                     ; 1.34
1F83H                       00001f83h: 88 13 88 13 82 14 82 14 64 00                   ; ˆ.ˆ.‚.‚.d.
1F85H
1F8DH 00001f8dh: 00 00 88 13 82 14 82 14 00 00 00 00 00 00 00 00 ; ..ˆ.‚.‚.........
00001f9dh: 0E 48 0D                                        ; .H.
1FA0H 00001fa0h: AC 09 E4 55 0B 52 C4 09 54 52 54 52 BC 09 19 52 ; ¬.äU.RÄ.TRTR¼..R
00001fb0h: 53 4E BB 09 28 52 55 4E AC 09 E6 BF E2 C1 BD 09 ; SN».(RUN¬.æ¿âÁ½.
00001fc0h: E0 C1 E4 C3 00 00 93 43 93 43 A6 09 96 55 F6 51 ; àÁäÃ..“C“C¦.–UöQ
00001fd0h: C4 09 54 52 54 52 D1 09 31 51 30 4D D0 09 52 51 ; Ä.TRTRÑ.1Q0MÐ.RQ
00001fe0h: 22 4D A6 09 12 C0 E2 C1 D2 09 78 C2 84 C4 00 00 ; "M¦..ÀâÁÒ.x„Ä..
00001ff0h: 93 43 93 43 00 00 76 CA 00 00 76 CA             ; “C“C..vÊ..vÊ
1FFCH EPROM_SERIAL_NUMBER       00001ffch: 31 31 33 37                                     ; 1137

00001935h: 44 41 43 BE 1C 00 43 4C 53 6A 1A 45 53 45 3C 1E ; DAC¾..CLSj.ESE<.
00001945h: 45 53 52 AE 1E 49 44 4E B0 19 50 53 43 72 1E 52 ; ESR®.IDN°.PSCr.R
00001955h: 43 4C 5A 1D 52 53 54 4E 1A 53 41 56 35 1D 53 52 ; CLZ.RSTN.SAV5.SR
00001965h: 45 06 1E 53 54 42 08 1F 00 56 4F 46 14 1A 56 4F ; E..STB...VOF..VO
00001975h: 4E 24 1A 00 4C 49 4D 7F 1B 4F 55 54 7E 1C 54 52 ; N$..LIM.OUT~.TR
00001985h: 50 EE 1B 00 4D 4F 44 9E 1C 00 43 4C 52 3B 1A 4D ; Pî..MODž..CLR;.M
00001995h: 4F 44 FF 1C 00 4C 49 4D 06 1B 4F 55 54 5D 1C 53 ; ODÿ..LIM..OUT].S
000019a5h: 45 54 87 1A 00 4F 52 44 77 1D 00                ; ET‡..ORDw..

GPIB
DAC  CLS ESE  ESR
IDN  PSC RCLZ RSTN
SAV5 SRE STB  VOF
VON  LIM OUT  TRP
MOD  CLR MOD  LIM
OUT  SET ORD


I/O ADDRESSES:

U504  (A3-A5 -> A-C, A6-G1, WR->!G2A, IORQ->!G2B )
40H: SPARE
48H:-SETS -> U407/U408
------------------------------
BIT0: U407A /
BIT1: U407B /
BIT2: U408A / ANALOG_VOLTAGE
BIT3: U408B / I_OUT_MONITOR
BIT4: U408C / CV_SET
BIT5: U408D / DV_LIM
BIT6: U407C / I_LIM
BIT7: U407D / I_TRIP
------------------------------

50H:-DAC
50H  DAC_LOW_NIBBLE
51H  DAC_MID_NIBBLE
52H  DAC_HIGH_NIBBLE
53H  DAC_LOAD

58H:-LED
------------------------------
BIT0: U611 L0
BIT1: U611 L1
BIT2: U611 L2
BIT3: U611 -AD0
BIT4: U611 -AD1
BIT5: U611 -AD2
BIT6: U611 -IO
BIT7: U611 UNUSED
------------------------------

60H:-SEGB U606
------------------------------
BIT0: EDP
BIT1: EG
BIT2: EF
BIT3: EE
BIT4: ED
BIT5: EC
BIT6: EB
BIT7: EA
------------------------------

68H:-SEGA U609
------------------------------
BIT0: ODP
BIT1: OG
BIT2: OF
BIT3: OE
BIT4: OD
BIT5: OC
BIT6: OB
BIT7: OA
------------------------------

70H:-STROBE     (STROB0-STROB5 LED)  (STROB2-4 KEYBOARD SCAN OUT)
------------------------------
BIT0: STROB0  (LED)
BIT1: STROB1 (LED)
BIT2: STROB2  (LED,KBD)
BIT3: STROB3  (LED,KBD)
BIT4: STROB4  (LED,KBD)
BIT5: STROB5  (LED)
BIT6: STROB6  ()
BIT7: STROB7  ()
------------------------------

78H: MISC -> (U507,74HC374 OCTAL D-TYPE FLIP-FLOP) >CLK
------------------------------
BIT0: -SHUTDOWN
BIT1: UPOK
BIT2: -FLAG_RESET
BIT3: -TIMER_RESET
BIT4: (SPARE)
BIT5: -POS
BIT6: -NEG
BIT7: FILTER
------------------------------

U505 (A3-A5 -> A-C, !M1->G1, A6->!G2A, IORQ->!G2B )
00H: SPARE
08H: SPARE
10H: SPARE
18H: SPARE

20H: STATUS1
------------------------------
BIT0: COMPARE
BIT1: I_FAULT
BIT2: CUR_LIM
BIT3: PRI_FAULT
BIT4: V_FAULT
BIT5: TIMER
BIT6: J504
BIT7: GND
------------------------------

28H: STATUS2
------------------------------
BIT0: HV_ON
BIT1: HV_OFF
BIT2: J501
BIT3: J502
BIT4: GND
BIT5: GND
BIT6: GND
BIT7: GND
------------------------------

30H: -KBD
------------------------------
BIT0: KBD0
BIT1: KBD1
BIT2: KBD2
BIT3: KBD3
BIT4: KBD4
BIT5: KBD5
BIT6: KBD6
BIT7: KBD7

key press display
01 Man         
02 GPIB       
03 left-arrow 
04 Right arrow
05 up-arrow   
06 down-arrow 
07 Enter       
08 Select     
09 STO         
10 RCL         
11 CLR         
12 .           
13 0           
14 7           
15 4           
16 1           
17 8           
18 5           
19 2           
20 9           
21 6           
22 3           
------------------------------

38H: -GPIB
------------------------------
READ
38H GPIB_INT_STATUS_0
BIT0: INT0 (1 WHEN STATUS 1 BIT SET)
BIT1: INT1 (1 WHEN BITS 2-7 OF STATUS 0 SET)
BIT2: BI    (BYTE IN)
BIT3: BO    (BYTE OUT)
BIT4: END  (LAST BYTE RECEIVED)
BIT5: SPAS (RSV1/2 SERVICE REQUEST)
BIT6: RCL  (REMOTE/LOCAL CHANGE)
BIT7: MAC  (ADDRESS CHANGE)
39H GPIB_INT_STATUS_1
BIT0: GET (GROUP EXECUTE TRIGGER)
BIT1: ERR (ERROR)
BIT2: UNC   (UNRECOGNIZED COMMAND)
BIT3: APT  (ADDRESS PASS THROUGH)
BIT4: DCAS  (DEVICE CLEAR ACTIVE STATE)
BIT5: MA    (MY ADDRESS)
BIT6: SRQ   (SERVICE REQUEST)
BIT7: IFC (INTERFACE CLEAR)
3AH GPIB_ADDRESS_STATUS
BIT0: REM
BIT1: LLO
BIT2: ATN
BIT3: LPAS
BIT4: TPAS
BIT5: LADS
BIT6: TADS
BIT7: ULPA
3BH GPIB_BUS_STATUS
3EH GPIB_CMD_PASS_THRU
3FH GPIB_DATA_IN

WRITE
38H GPIB_INT_MASK_0
39H GPIB_INT_MASK_1
3BH GPIB_AUXILIARY_CMD
3CH GPIB_ADDRESS
3DH GPIB_SERIAL_POLL
3EH GPIB_PARALLEL_POLL
3FH GPIB_DATA_OUT
------------------------------

I've also started running thru the disassembly and trying to figure things out so I can figure which are the calibration locations
one thing I do know is they copied allot of stuff from EPROM to SRAM then work from the SRAM location while running

some basics
0038H is the start of the IRQ service routine,  timer driven mainly checks STATUS1 and handles KBD and GPIB
below is not the complete routine,  just the start of it


Code: [Select]
0028   0038 08    IRQ_SERVICE:  EX AF,AF' ; ENTRY POINT FOR IRQ SERVICE ROUTINE
0029   0039 DB 20             IN A,(STATUS1)                 ; READ STATUS1
0030   003B CB 6F             BIT 5,A ; TEST IF BIT 5 SET IN STATUS1 WHICH IS THE TIMER BIT
0031   003D 28 06             JR Z,TIMER_EVENT            ; IF TIMER EVENT JUMP TO TIMER_EVENT
0032   003F CD BB 0E        CALL IRQ_SERVICE_1 ; TBD
0033   0042 08                  EX AF,AF'
0034   0043 FB                  EI ; ENABLE INTERUPTS
0035   0044 C9                  RET ; RETURN FROM IRQ
0036   0045 D9    TIMER_EVENT:  EXX
0037   0046 DB 38             IN A,(GPIB_INT_STATUS_0) ; A GETS GPIB_INT_STATUS_0
0038   0048 47                  LD B,A ; COPY A -> B
0039   0049 DB 39             IN A,(GPIB_INT_STATUS_1) ; A GETS GPIB_INT_STATUS_1
0040   004B CB 5F             BIT 3,A ; TEST BIT 3 (Address Pass Through) IN GPIB_INT_STATUS_1 IS SET
0041   004D C2 11 13        JP NZ,L0006 ; JUMP L0006 IF NOT ZERO
0042   0050 CB 50             BIT 2,B ; TEST BIT 2 (Byte In) IN GPIB_INT_STATUS_0 IS SET
0043   0052 C2 09 13         JP NZ,L0007 ; JUMP TO L0007 IF NOT ZERO
0044   0055 CB 68 L0256:  BIT 5,B         ; TEST BIT 5 (SPAS) IN GPIB_INT_STATUS_0 IS SET
0045   0057 C2 1E 13         JP NZ,L0008 ; JUMP TO L0008 IF NOT ZERO
0046   005A CB 60             BIT 4,B ; TESST BIT 5 (END) OF GPIB_INT_STATUS_0 IS SET (LAST BYTE RECEIVED)
0047   005C 28 03             JR Z,L0009 ; JUMP TO L0009 IF ZERO
0048   005E C3 59 13        JP L0010             ; JUMP TO L0010 UNCONDITIONALLY
0049   0061 D9      L0009: EXX
0050   0062 08                  EX AF,AF'
0051   0063 FB                  EI    ; ENABLE INTERRUPTS
0052   0064 C9                  RET ; RETURN

I have a EPROM coming to burn the 1.40 version in.  mine is a 1.34 version currently so comparing directly won't help allot
now if anyone has a V1.40 without GPIB support they can share that would be great.

too me so far it looks like the area from 1F83H-1FFC may contain calibration data and may be only part needed to copy to maintain calibration.
but I want to look and find the details so we can calibrate without sending back to SSR.

« Last Edit: July 17, 2017, 01:42:46 am by smgvbest »
Sandra
(Yes, I am a Woman :p )
 
The following users thanked this post: alm

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
I received my EPROM and burned a replacement changing only the Serial Number at the end and that worked fine to enable my GPIB change.
I discovered my Agilent 82357B wasn't working looking like it might have blown a 75160B/75162B inside.  I have both coming.
I have a cheapy ebay unit that only works with it's own software so was able to verify the GPIB interface was working so that's fixed

My calibration was off.  at 5Kv it was reading 4991V and it also didn't go as low.  prior to change i was down at the 25V range (though spec is 50V) after the EPROM change it's sitting at 35V but reading 40V on the DMM. 

So I copied the memory area starting at 1FA0 also this time

Code: [Select]
1FA0H 00001fa0h: AC 09 E4 55 0B 52 C4 09 54 52 54 52 BC 09 19 52 ; ¬.äU.RÄ.TRTR¼..R
00001fb0h: 53 4E BB 09 28 52 55 4E AC 09 E6 BF E2 C1 BD 09 ; SN».(RUN¬.æ¿âÁ½.
00001fc0h: E0 C1 E4 C3 00 00 93 43 93 43 A6 09 96 55 F6 51 ; àÁäÃ..“C“C¦.–UöQ
00001fd0h: C4 09 54 52 54 52 D1 09 31 51 30 4D D0 09 52 51 ; Ä.TRTRÑ.1Q0MÐ.RQ
00001fe0h: 22 4D A6 09 12 C0 E2 C1 D2 09 78 C2 84 C4 00 00 ; "M¦..ÀâÁÒ.x„Ä..
00001ff0h: 93 43 93 43 00 00 76 CA 00 00 76 CA             ; “C“C..vÊ..vÊ

in addition to the serial number and burned another EPROM.  Loaded it up and my cal values where back

so in that block is indeed where the calibration values are stored.   this is good.

I'm thinking this bit of code copies the calibration values to SRAM @ 413CH

Code: [Select]
0066   007A 01 11 00    L0011:  LD BC,0011H   ; TRANSFER 17 BYTES
0067   007D 21 8D 1F                LD HL,1F8DH   ; FROM EPROM
0068   0080 11 3C 41                LD DE,413CH   ; TO SRAM @ 413C
0069   0083 ED B0                    LDIR       ; MOVE FROM 1F8D TO 413C

if so the 1F8D thru 1F9E contain the calibration values

Code: [Select]
00001f8dh: 00 00 88 13 82 14 82 14 00 00 00 00 00 00 00 00 ; ..ˆ.‚.‚.........
00001f9dh: 0E 48                                           ; .H

I'll try another burn of the EPROM without this section to see if I do or do not have calibration values next.

oh, I do have a few 28C64's coming soon.  I'll replace the 27C64 with one of these and if that works well and no reason I know it won't I'll be able to reflash it instead of UV erasing which will make things easier to play with

« Last Edit: July 24, 2017, 01:01:48 am by smgvbest »
Sandra
(Yes, I am a Woman :p )
 
The following users thanked this post: alm

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics

So I tried to remove this section
replacing
Code: [Select]
00001f8dh: 00 00 88 13 82 14 82 14 00 00 00 00 00 00 00 00 ; ..ˆ.‚.‚.........
00001f9dh: 0E 48                                           ; .H
with
Code: [Select]
00001f8dh: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ..ˆ.‚.‚.........
00001f9dh: 00 00                                           ; .H

Then powered up with CLR pressed to restore default from the EPROM and then measured at
50V
500V
5000V

Comparing to the values prior this I noticed no difference so (a few millivolts was about it)

So unless the calibration range is so small then these are not the calibration values

On to more searching
Sandra
(Yes, I am a Woman :p )
 

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
For a device that is specified as 0.01% of value + 0.05% of range accurate, or +/- 3V for 5 kV, I find it hard to believe that the adjustment range is only a few millivolts. Unless your device happens to be at the very bottom end of its adjustment range, my money is that these are indeed not the calibration values. Either that or it is using values from an alternate location because of a failed checksum (hard to believe with EPROM).

I have seen primary cal values in battery-backed SRAM and backup copies in EEPROM, but I do not see the point of having two copies in the same EPROM.

I am guessing these devices can not do any kind of adjustment through GPIB so you could at least see the SRAM locations that were modified? Adjustment probably exists of measuring a bunch of values and then burning these values into an EPROM. Sounds like a messy way of adjustment.
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
There are other values copied from the EPROM to SRAM so I'm going to look at those and see if they effect anything.   I so make sure to either hold CLR when powering on to restore defaults so it copies from EPROM to SRAM the new values or do a RCL 0 to restore factory defaults.

looking at what looks looks to be the GPIB command area  there is this

Code: [Select]
193BH GPIB COMMAND     00001935h: 44 41 43 BE 1C 00 43 4C 53 6A 1A 45 53 45 3C 1E ; DAC¾..CLSj.ESE<.
    00001945h: 45 53 52 AE 1E 49 44 4E B0 19 50 53 43 72 1E 52 ; ESR®.IDN°.PSCr.R
    00001955h: 43 4C 5A 1D 52 53 54 4E 1A 53 41 56 35 1D 53 52 ; CLZ.RSTN.SAV5.SR
    00001965h: 45 06 1E 53 54 42 08 1F 00 56 4F 46 14 1A 56 4F ; E..STB...VOF..VO
    00001975h: 4E 24 1A 00 4C 49 4D 7F 1B 4F 55 54 7E 1C 54 52 ; N$..LIM.OUT~.TR
    00001985h: 50 EE 1B 00 4D 4F 44 9E 1C 00 43 4C 52 3B 1A 4D ; Pî..MODž..CLR;.M
    00001995h: 4F 44 FF 1C 00 4C 49 4D 06 1B 4F 55 54 5D 1C 53 ; ODÿ..LIM..OUT].S
    000019a5h: 45 54 87 1A 00 4F 52 44                         ; ET‡..ORD

the DAC and ORD would appear to be commands.  I tried variations on the DAC command like DAC? A-Z[DAC]? *DAC? all resulted in a time out.   I need to understand the command parser better and maybe can figure out how they the calibration.   the websites states it's calibrated in a automated setup.   now that doesnt' mean it's over GPIB though.   they may plug in a calibration device in-place of the z80 and get the DAC values then assemble the EPROM with those values or have a EPROM they use just to calibrate the unit.

ultimately is looks like it is just a offset to the DAC so finding that in the code would help.   for me last time I did z80 stuff was in the late 80's
I'm using a z80 simulator on the EPROM code to examine things.  nice thing is I get what the SRAM looks like also.  they do all the work out of the sram after things are copied in.   

I'm happy to post the simulation files and SRAM dump of anyone is interested.
Sandra
(Yes, I am a Woman :p )
 

Offline Tony_G

  • Frequent Contributor
  • **
  • Posts: 587
  • Country: us
  • Checkout my old test gear channel (link in sig)
    • TGSoapbox
Great post. What simulator are you using?

TonyG

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
I am using this one "Z80 Simulator IDE v10.36" from http://www.oshonsoft.com/

Attached are the memory dump and sim file along with my bin file and most recent update to the disassembly
I had to zip them to attach them


Sandra
(Yes, I am a Woman :p )
 

Offline nidlaX

  • Frequent Contributor
  • **
  • Posts: 649
  • Country: us
That was definitely a "DON'T turn it on before taking it apart" type of repair! :-BROKE :-+
 

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
Did a bit of digging in the rom/ram dump you posted. The data at 0x191C looks indeed like a GPIB command table. The structure is a bit odd:
Code: [Select]
ROM:191C                 db '$'
ROM:191D                 dw 1935h
ROM:191F                 db '*'
ROM:1920                 dw 193Bh
ROM:1922                 db 'H'
ROM:1923                 dw 196Eh
ROM:1925                 db 'I'
ROM:1926                 dw 1979h
ROM:1928                 db 'S'
ROM:1929                 dw 1989h
ROM:192B                 db 'T'
ROM:192C                 dw 198Fh
ROM:192E                 db 'V'
ROM:192F                 dw 199Ah
ROM:1931                 db 'W'
ROM:1932                 dw 19AAh
ROM:1934                 db    0
ROM:1935                 db  44h ; D
ROM:1936                 db  41h ; A
ROM:1937                 db  43h ; C
ROM:1938                 dw 1CBEh
ROM:193A                 db    0
ROM:193B                 db  43h ; C
ROM:193C                 db  4Ch ; L
ROM:193D                 db  53h ; S
ROM:193E                 dw 1A6Ah
ROM:1940                 db  45h ; E
ROM:1941                 db  53h ; S
ROM:1942                 db  45h ; E
ROM:1943                 dw 1E3Ch
ROM:1945                 db  45h ; E
ROM:1946                 db  53h ; S
ROM:1947                 db  52h ; R
ROM:1948                 dw 1EAEh
ROM:194A                 db  49h ; I
ROM:194B                 db  44h ; D
ROM:194C                 db  4Eh ; N
ROM:194D                 dw 19B0h
ROM:194F                 db  50h ; P
ROM:1950                 db  53h ; S
ROM:1951                 db  43h ; C
ROM:1952                 dw 1E72h
ROM:1954                 db  52h ; R
ROM:1955                 db  43h ; C
ROM:1956                 db  4Ch ; L
ROM:1957                 dw 1D5Ah
ROM:1959                 db  52h ; R
ROM:195A                 db  53h ; S
ROM:195B                 db  54h ; T
ROM:195C                 dw 1A4Eh
ROM:195E                 db  53h ; S
ROM:195F                 db  41h ; A
ROM:1960                 db  56h ; V
ROM:1961                 dw 1D35h
ROM:1963                 db  53h ; S
ROM:1964                 db  52h ; R
ROM:1965                 db  45h ; E
ROM:1966                 dw 1E06h
ROM:1968                 db  53h ; S
ROM:1969                 db  54h ; T
ROM:196A                 db  42h ; B
ROM:196B                 dw 1F08h
ROM:196D                 db    0
ROM:196E                 db  56h ; V
ROM:196F                 db  4Fh ; O
ROM:1970                 db  46h ; F
ROM:1971                 dw 1A14h
ROM:1973                 db  56h ; V
ROM:1974                 db  4Fh ; O
ROM:1975                 db  4Eh ; N
ROM:1976                 dw 1A24h
ROM:1978                 db    0
ROM:1979                 db  4Ch ; L
ROM:197A                 db  49h ; I
ROM:197B                 db  4Dh ; M
ROM:197C                 dw 1B7Fh
ROM:197E                 db  4Fh ; O
ROM:197F                 db  55h ; U
ROM:1980                 db  54h ; T
ROM:1981                 dw 1C7Eh
ROM:1983                 db  54h ; T
ROM:1984                 db  52h ; R
ROM:1985                 db  50h ; P
ROM:1986                 dw 1BEEh
ROM:1988                 db    0
ROM:1989                 db  4Dh ; M
ROM:198A                 db  4Fh ; O
ROM:198B                 db  44h ; D
ROM:198C                 dw 1C9Eh
ROM:198E                 db    0
ROM:198F                 db  43h ; C
ROM:1990                 db  4Ch ; L
ROM:1991                 db  52h ; R
ROM:1992                 dw 1A3Bh
ROM:1994                 db  4Dh ; M
ROM:1995                 db  4Fh ; O
ROM:1996                 db  44h ; D
ROM:1997                 dw 1CFFh
ROM:1999                 db    0
ROM:199A                 db  4Ch ; L
ROM:199B                 db  49h ; I
ROM:199C                 db  4Dh ; M
ROM:199D                 dw 1B06h
ROM:199F                 db  4Fh ; O
ROM:19A0                 db  55h ; U
ROM:19A1                 db  54h ; T
ROM:19A2                 dw 1C5Dh
ROM:19A4                 db  53h ; S
ROM:19A5                 db  45h ; E
ROM:19A6                 db  54h ; T
ROM:19A7                 dw 1A87h
ROM:19A9                 db    0
ROM:19AA                 db  4Fh ; O
ROM:19AB                 db  52h ; R
ROM:19AC                 db  44h ; D
ROM:19AD                 dw 1D77h
ROM:19AF                 db    0
The data at the top contains the first character (e.g. '*' at 191F) and a reference to an array of:
Code: [Select]
struct {
    char cmd[3];
    void *addr;
}
Terminated by a 00. For '*', cmd would be CLS, IDN, etc. The complete list:
Code: [Select]
$DAC
*CLS
*ESE
*ESR
*IDN
*PSC
*RCL
*RST
*SAV
*SRE
*STB
HVOF
HVON
ILIM
IOUT
ITRP
SMOD
TCLR
TMOD
VLIM
VOUT
VSET
WORD

The *addr are code references that will presumably take the desired action. Parsing seem to take place around 1587:
Code: [Select]
ROM:1587 parse_gpib_commands:                    ; CODE XREF: read_gpib_key+ACp
ROM:1587                                         ; parse_gpib_commands+E4j
ROM:1587                 ld      a, (word_40EB)
ROM:158A                 and     a
ROM:158B                 ret     z
ROM:158C                 call    sub_17D0
ROM:158F                 call    sub_17F1
ROM:1592                 ld      c, 0
ROM:1594                 jp      z, loc_161B
ROM:1597                 call    sub_181B
ROM:159A                 ld      b, a
ROM:159B                 ld      c, 1
ROM:159D                 ld      hl, 191Ch       ; data_gpib_commands
ROM:15A0
ROM:15A0 loc_15A0:                               ; CODE XREF: parse_gpib_commands+24j
ROM:15A0                 ld      a, (hl)
ROM:15A1                 inc     hl
ROM:15A2                 and     a
ROM:15A3                 jp      z, end_of_string
ROM:15A6                 cp      b
ROM:15A7                 jr      z, loc_15AD
ROM:15A9                 inc     hl
ROM:15AA                 inc     hl
ROM:15AB                 jr      loc_15A0

A cursory look at the code at 1cbe (referenced by $DAC) suggests that it does not accept $DAC?, but expects a value:
Code: [Select]
ROM:1CBE                 call    check_question_mark
ROM:1CC1                 jp      z, syntax_error
ROM:1CC4                 ld      hl, 1
ROM:1CC7                 ld      a, 0
ROM:1CC9                 call    sub_1851
ROM:1CCC                 jp      nz, end_of_string
ROM:1CCF                 push    hl
ROM:1CD0                 call    sub_17E7
ROM:1CD3                 pop     hl
ROM:1CD4                 jp      nz, syntax_error
ROM:1CD7                 ld      c, 0
ROM:1CD9                 bit     0, l
ROM:1CDB                 jr      z, loc_1CF8
ROM:1CDD                 ld      hl, 0
ROM:1CE0                 ld      a, (byte_412D)
ROM:1CE3                 or      a
ROM:1CE4                 jr      z, loc_1CE8
ROM:1CE6                 set     7, h
I have not looked into what it does with this value yet.
 
The following users thanked this post: smgvbest

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
@alm
Wow,  you're far better at this than I am.   Thank you.
That shed a bunch of light on things.
the not supporting $DAC? makes sense since the DAC can not be read.   they would have to Save the current DAC value and return it and guess they didn't need that feature to calibrate.

given that setting the DAC maybe possible what I imagine they do then is basically (and crudely)

HVON
FOR TEST_VALUE IN 50,1000,2000,3000,4000,5000  < just random values but they would have fixed test points
DO
VSET TEST_VALUE
READ OUTPUT VOLTAGE
 COMPARE TEST_VALUE TO OUTPUT
 IF IN SPEC SAVE TEST_VALUE, OFFSET AND NEXT VALUE
 ELSE  $DAC +/-OFFSET
 LOOP BACK TO READ
DONE
HVOFF

then they would write those offsets to EPROM.
kind of a clunky way of doing it but given the hardware here the only way that would work reliably I think.   they could write to sram for cal but if your battery died you'd loose cal and with not battery monitor they can't alert you to change the battery.


Sandra
(Yes, I am a Woman :p )
 

Offline Dexter2

  • Contributor
  • Posts: 28
  • Country: si
I also got through a repair of one PS350 recently and done the GPIB upgrade trough a donors ROM. In the progress, I also loosen my calibration but luckily, it’s not so much off. But a possibility to calibrate it would be great.

Below the attached ROMs I have both V1.4 but quite different when I did the compare (GPIB vs Non-GPIB version), maybe they will help you to figure out where the calibration locations are more quicklly.


 

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
given that setting the DAC maybe possible what I imagine they do then is basically (and crudely)
[...]

I agree that it would probably be something like that (if they wanted to reduce calibration time, they would use some sort of binary search or interpolation for finding the offset).

Looks to me like WORD takes two comma-separated numbers that somehow may affect either vset, vlim, ilim or itrp. WORD? is also implemented and takes a single number. I believe the first parameter selects vset, vlim, ilim or itrp. Not sure what the point of this command is.

This looks to me like it might be subtracting calibration offsets. Depending on the value of port 0x28 bit 2 (J501 according to your earlier post, a calibration jumper? model indicator?), it uses 4026 or 4026+2A as base address. Then it does some math that as far as I can tell boils down to the parameter number (0..3) * 6. By my reading (which may very well be wrong), the first of the three words is an offset that is subtracted from the set voltage. Depending on the polarity of the result of this subtraction, it will either pick the second or third word and do something that looks like multiplication with it. If my analysis is correct, the calibration constants would live in 0x4026 up to something like 0x4082. Figuring out how the constants affect the DAC value should not be difficult by a more careful reading of the code.
Code: [Select]
; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }

ROM:08FD loc_8FD:                                ; CODE XREF: check_limits+Ej
ROM:08FD                 push    af
ROM:08FE                 ld      a, (var_status2)
ROM:0901                 bit     2, a
ROM:0903                 ld      hl, byte_4026
ROM:0906                 jr      z, loc_90B
ROM:0908                 ld      hl,  byte_4026+2Ah
ROM:090B
ROM:090B loc_90B:                                ; CODE XREF: check_limits+2Bj
ROM:090B                 pop     af              ; a = param { 0..3 } << 1, e = a << 1, bc = var_vset
ROM:090C                 rlca
ROM:090D                 add     a, e
ROM:090E                 ld      e, a
ROM:090F                 add     hl, de
ROM:0910                 ld      e, (hl)
ROM:0911                 inc     hl
ROM:0912                 ld      d, (hl)
ROM:0913                 inc     hl
ROM:0914                 push    hl
ROM:0915                 ld      h, b
ROM:0916                 ld      l, c
ROM:0917                 or      a
ROM:0918                 sbc     hl, de
ROM:091A                 pop     de
ROM:091B                 jr      c, loc_91F
ROM:091D                 inc     de
ROM:091E                 inc     de
ROM:091F
ROM:091F loc_91F:                                ; CODE XREF: check_limits+40j
ROM:091F                 ld      a, 0
ROM:0921                 call    c, cpl_word     ; hl = -hl
ROM:0921                                         ; a = 1
ROM:0924                 ex      de, hl
ROM:0925                 ld      c, (hl)
ROM:0926                 inc     hl
ROM:0927                 ld      b, (hl)
ROM:0928                 ld      (byte_40E6), a
ROM:092B                 pop     af
ROM:092C                 push    af
ROM:092D                 push    bc
ROM:092E                 ld      hl, 99Fh
ROM:0931                 add     a, l
ROM:0932                 ld      l, a
ROM:0933                 jr      nc, loc_936
ROM:0935                 inc     h
ROM:0936
ROM:0936 loc_936:                                ; CODE XREF: check_limits+58j
ROM:0936                 ld      a, (hl)
ROM:0937                 cp      0
ROM:0939                 jr      z, loc_942
ROM:093B                 ld      b, a
ROM:093C
ROM:093C loc_93C:                                ; CODE XREF: check_limits+65j
ROM:093C                 sla     e
ROM:093E                 rl      d
ROM:0940                 djnz    loc_93C

This appears to be the code responsible for copying:
Code: [Select]
ROM:0094                 ld      bc, 5Ch ; '\'
ROM:0097                 ld      hl, unk_1FA0
ROM:009A                 ld      de, byte_4026
ROM:009D                 ldir

$DAC seems to control the VSET DAC directly, ignoring any calibration constant or voltage setting (as expected). It does not appear to affect the other DACs like VLIM, ILIM and ITRP. So the calibration procedure would be something like:
Code: [Select]
For DAC_VALUE in 0x0 0x7F 0x7FF 0x7FFF 0x807F 0x87FF 0xFFFF ; for a 16-bit DAC
    $DAC DAC_VALUE
    Measure voltage
    Store DAC_VALUE, voltage

Then fit two linear functions of the form voltage -> DAC_VALUE for positive and negative voltages.

Seems like it should be doable if you know the syntax of $DAC and the exact meaning of the constants. It will probably involve a lot of EPROM erase/flash cycles, however. Have you considered converting it to EEPROM? ;)

Let me know if all this makes sense and if it matches reality. I am not very familiar with Z80 assembly (had to keep the Z80 family CPU user manual open), and neither do I have access to one of these units, so I could easily be way off. There are definitely a few spots where I do not see how the code can do anything useful. I did go through a decent fraction of the code and have labeled a bunch of functions and variables. Especially around the GPIB commands and the DAC stuff.
« Last Edit: July 30, 2017, 11:51:57 pm by alm »
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
J501/J502/J503 monitor the polarity switch on the back of the supply.   J501 would tell it is operating in POSITIVE,  the pin is pulled high normally so a LOW would indicate Positive

J504 monitors the SET/MONITOR switch on the back of the supply.  a HIGH should be SET, a LOW should be MONITOR

That word command may be how they read and/or set the each of those parms manually.  perhaps part of their calibration process?
i'll try some commands to both $DAC and WORD and see what i get.

Sounds like WORD would be WORD? 1

FYI, the DAC used is a 12bit DAC

I have some 28C64's on the way ;)

appreciate all your assistance here.   it's been very helpfull and seems to be right on.

if you are correct about the calibration values being in the 4026h range then this bit of code copies from EPROM to SRAM

Code: [Select]
0079   0094 01 5c 00  ld bc,005ch       ; transfer 5c bytes
0080   0097 21 a0 1f   ld hl,1fa0h        ; from eprom
0081   009a 11 26 40  ld de,4026h      ; to sram @ 4026
0082   009d ed b0       ldir                  ; do the transfer

this is the block of data being copied

Code: [Select]
1FA0H 00001fa0h: AC 09 E4 55 0B 52 C4 09 54 52 54 52 BC 09 19 52 ; ¬.äU.RÄ.TRTR¼..R
00001fb0h: 53 4E BB 09 28 52 55 4E AC 09 E6 BF E2 C1 BD 09 ; SN».(RUN¬.æ¿âÁ½.
00001fc0h: E0 C1 E4 C3 00 00 93 43 93 43 A6 09 96 55 F6 51 ; àÁäÃ..“C“C¦.–UöQ
00001fd0h: C4 09 54 52 54 52 D1 09 31 51 30 4D D0 09 52 51 ; Ä.TRTRÑ.1Q0MÐ.RQ
00001fe0h: 22 4D A6 09 12 C0 E2 C1 D2 09 78 C2 84 C4 00 00 ; "M¦..ÀâÁÒ.x„Ä..
00001ff0h: 93 43 93 43 00 00 76 CA 00 00 76 CA             ; “C“C..vÊ..vÊ
« Last Edit: July 31, 2017, 04:50:59 am by smgvbest »
Sandra
(Yes, I am a Woman :p )
 

Offline Dexter2

  • Contributor
  • Posts: 28
  • Country: si
Just did the compare of two different V1.4 EPROMS.

The differences start from 0x01FA0 all the way to the end. So this all plays along with what has been discoverd so far by alm and smgvbest

« Last Edit: July 31, 2017, 05:47:41 am by Dexter2 »
 
The following users thanked this post: alm

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
Okay, then the two blocks are obviously for the negative and positive polarity. The first block would be used if J501 is low (positive polarity), and the second block for negative polarity. The use second or third word depends on the polarity of vset - word1. If this is negative, then the second word is used. Otherwise the second word is skipped and the third word is used. The result is fed in this function that I can not completely figure out:
Code: [Select]
ROM:08A1 ; de = intermediate dac value (= word1 - vset)
ROM:08A1 ; hl = calib word 2 or 3
ROM:08A1
ROM:08A1 some_calc_hl_de:                        ; CODE XREF: check_limits+69p
ROM:08A1                                         ; sub_A39+3Bp ...
ROM:08A1                 ld      c, l
ROM:08A2                 ld      b, h
ROM:08A3                 ld      hl, 0
ROM:08A6                 ld      a, 10h
ROM:08A8
ROM:08A8 loc_8A8:                                ; CODE XREF: some_calc_hl_de+16j
ROM:08A8                 sla     l
ROM:08AA                 rl      h
ROM:08AC                 rl      e
ROM:08AE                 rl      d
ROM:08B0                 jr      nc, loc_8B6
ROM:08B2                 add     hl, bc
ROM:08B3                 jr      nc, loc_8B6
ROM:08B5                 inc     de
ROM:08B6
ROM:08B6 loc_8B6:                                ; CODE XREF: some_calc_hl_de+Fj
ROM:08B6                                         ; some_calc_hl_de+12j
ROM:08B6                 dec     a
ROM:08B7                 jr      nz, loc_8A8
ROM:08B9                 ret
ROM:08B9 ; End of function some_calc_hl_de
Clearly the intermediate calibration value (word1 - vset) is added to an accumulator up to 0x10 times, depending on the value of word 2 / 3. Plus a bunch of bit shifting. Does anyone recognize this as a common mathematical function? Anyway, word 2 / 3 does seem some kind of multiplier/exponent. It presumably translates the signed 16-bit value to an unsigned 12-bit value.

This is the context of that function call. It comes immediately after the block I posted in my previous post:
Code: [Select]
ROM:0942 loc_942:                                ; CODE XREF: check_limits+5Ej
ROM:0942                 pop     hl
ROM:0943                 push    de
ROM:0944                 call    some_calc_hl_de ; in:
ROM:0944                                         ; de = intermediate dac value
ROM:0944                                         ; hl = calib word 2 or 3
ROM:0944                                         ; out:
ROM:0944                                         ; hl = result
ROM:0944                                         ; de = ???
ROM:0947                 bit     7, h
ROM:0949                 jr      z, loc_94C
ROM:094B                 inc     de
ROM:094C
ROM:094C loc_94C:                                ; CODE XREF: check_limits+6Ej
ROM:094C                 pop     hl
ROM:094D                 add     hl, de
ROM:094E                 ld      a, (byte_40E6)
ROM:0951                 bit     0, a
ROM:0953                 jr      z, loc_957
ROM:0955                 set     7, h
ROM:0957
ROM:0957 loc_957:                                ; CODE XREF: check_limits+78j
ROM:0957                 pop     af
ROM:0958                 ret
So after the operation the result hl is ignored, and the result de is added to (word1 - vset).

There may be some other data in there: by my math the four blocks of six bytes should only take 0x18 bytes, yet the second block starts at +0x2a (at 0x1fca). There does appear data between 0x1fb8 and 0x1fca. Is my understanding wrong? Or is this data really not used? If the second block is also 0x2a bytes long, it should stop at 0x1ff4, yet it copies until 0x1ffc.

This code appears to check an additional parameter block at 0x099F. This is a four byte block of zeroes in Sandra's ROM dump. This appears to indicate the number of iterations of the loop at 0x093c. So this could be an additional linearity correction or something (maybe used for different ranges, e.g. 5 kV vs 10 kV models). Though the different location in the firmware and the fact that it is not copied to RAM seems odd for calibration, and seems to argue for different models.
Code: [Select]
ROM:092E                 ld      hl, unk_99F
ROM:0931                 add     a, l
ROM:0932                 ld      l, a
ROM:0933                 jr      nc, loc_936
ROM:0935                 inc     h
ROM:0936
ROM:0936 loc_936:                                ; CODE XREF: check_limits+58j
ROM:0936                 ld      a, (hl)
ROM:0937                 cp      0
ROM:0939                 jr      z, loc_942
ROM:093B                 ld      b, a
ROM:093C
ROM:093C loc_93C:                                ; CODE XREF: check_limits+65j
ROM:093C                 sla     e
ROM:093E                 rl      d
ROM:0940                 djnz    loc_93C
ROM:0942
ROM:0942 loc_942:

Actually, on second thought, it looks like WORD? can query words from the calibration RAM:
Code: [Select]
ROM:1DE5 parse_word?:                            ; CODE XREF: ROM:1D7Aj
ROM:1DE5                 ld      hl, 2Dh ; '-'
ROM:1DE8                 call    get_gpib_num3
ROM:1DEB                 jp      nz, end_of_string
ROM:1DEE                 push    hl
ROM:1DEF                 call    gpib_check_end_command
ROM:1DF2                 pop     hl
ROM:1DF3                 jp      nz, syntax_error
ROM:1DF6                 ld      de, byte_4026
ROM:1DF9                 ex      de, hl
ROM:1DFA                 add     hl, de
ROM:1DFB                 add     hl, de
ROM:1DFC                 ld      e, (hl)
ROM:1DFD                 inc     hl
ROM:1DFE                 ld      d, (hl)
ROM:1DFF                 ex      de, hl
ROM:1E00                 call    sub_1878
ROM:1E03                 jp      end_of_string
The initial hl is the max input it accepts. So it expects a decimal integer up to 0x2d (45). And it adds this address twice to 0x4026. By my math that puts it two bytes short from the 0x5c bytes copied at 0x94. Either that or I made an off-by-one error. sub_1878 looks GPIB related, so may very well send a response back. I was also wrong about the WORD write. It appears to write the calibration RAM, and then changes the DAC setting to match the new calibration value. That was I was confused about it settings a value: it does call set_control value, but only to update the DAC with the new calibration constants. This is the complete code:
Code: [Select]
ROM:1D77 parse_word:
ROM:1D77                 call    check_question_mark
ROM:1D7A                 jp      z, parse_word?
ROM:1D7D                 ld      hl, 2Dh ; '-'
ROM:1D80                 call    get_gpib_num3
ROM:1D83                 jp      nz, end_of_string
ROM:1D86                 ld      (var_temp_word_address), hl
ROM:1D89                 call    check_comma
ROM:1D8C                 jp      nz, syntax_error
ROM:1D8F                 ld      hl, 0FFFFh
ROM:1D92                 call    get_gpib_num3
ROM:1D95                 jp      nz, end_of_string
ROM:1D98                 push    hl
ROM:1D99                 call    gpib_check_end_command
ROM:1D9C                 pop     hl
ROM:1D9D                 jp      nz, syntax_error
ROM:1DA0                 ld      de, calibration_ram
ROM:1DA3                 ld      bc, (var_temp_word_address)
ROM:1DA7                 ex      de, hl
ROM:1DA8                 add     hl, bc
ROM:1DA9                 add     hl, bc
ROM:1DAA                 ld      (hl), e
ROM:1DAB                 inc     hl
ROM:1DAC                 ld      (hl), d
ROM:1DAD                 ld      a, c
ROM:1DAE                 cp      0Ch
ROM:1DB0                 jr      c, loc_1DBA
ROM:1DB2                 sub     15h
ROM:1DB4                 jr      c, loc_1DE0
ROM:1DB6                 cp      0Ch
ROM:1DB8                 jr      nc, loc_1DE0
ROM:1DBA
ROM:1DBA loc_1DBA:                               ; CODE XREF: ROM:1DB0j
ROM:1DBA                 cp      3
ROM:1DBC                 jr      nc, loc_1DC5
ROM:1DBE                 ld      a, 0
ROM:1DC0                 call    set_control_value ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:1DC3                 jr      loc_1DE0
ROM:1DC5 ; ---------------------------------------------------------------------------
ROM:1DC5
ROM:1DC5 loc_1DC5:                               ; CODE XREF: ROM:1DBCj
ROM:1DC5                 cp      6
ROM:1DC7                 jr      nc, loc_1DD0
ROM:1DC9                 ld      a, 1
ROM:1DCB                 call    set_control_value ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:1DCE                 jr      loc_1DE0
ROM:1DD0 ; ---------------------------------------------------------------------------
ROM:1DD0
ROM:1DD0 loc_1DD0:                               ; CODE XREF: ROM:1DC7j
ROM:1DD0                 cp      9
ROM:1DD2                 jr      nc, loc_1DDB
ROM:1DD4                 ld      a, 2
ROM:1DD6                 call    set_control_value ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:1DD9                 jr      loc_1DE0
ROM:1DDB ; ---------------------------------------------------------------------------
ROM:1DDB
ROM:1DDB loc_1DDB:                               ; CODE XREF: ROM:1DD2j
ROM:1DDB                 ld      a, 3
ROM:1DDD                 call    set_control_value ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:1DE0
ROM:1DE0 loc_1DE0:                               ; CODE XREF: ROM:1DB4j
ROM:1DE0                                         ; ROM:1DB8j ...
ROM:1DE0                 ld      c, 0
ROM:1DE2                 jp      end_of_string

So if my theory is correct, WORD? 0 should return 0x09AC (probably as decimal and possibly in different endianess). WORD 0,256 should change the value at 0x4026 and WORD? 0 after that should return 256. Basically a peek and poke, but only for the calibration memory. If this works, then it would make reverse-engineering the calibration parameters a whole lot faster and save a lot of wear and tear on the EEPROM burner.
« Last Edit: July 31, 2017, 11:57:44 am by alm »
 
The following users thanked this post: Dexter2

Offline Dexter2

  • Contributor
  • Posts: 28
  • Country: si
I have tested and the PS350 behaves as ALM has described.

WORD? <0..45> fetches data from RAM that is read at boot time from EPROM location "0x1FA0" and up to "0x1FFB" just up to the serial number.

WORD <0..45>,<0..65535> writes to same calibration section in RAM. After a power cycle values return to what is stored in EPROM.

I have made a map from what was discovered up to now.
« Last Edit: August 01, 2017, 11:08:05 am by Dexter2 »
 

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
Thanks for confirming my theory!
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
Thanks, I was about to post the same

before I forget,  I got the 28C64's today.  I'll flash one and verify everything is good.   then no more UV eraser needed.   

Burning the 28C64B in the minipro

old EPROM in the unit

new 28C64B in place

finishing touch, a nice shinny new label

powering on all looks good.


no more UV Erasing the EPROM  :-+

Now, onto the topic at hand
Here's the actual values read from my unit and they match the 1FA0-1FFB area of ROM

Code: [Select]
WORD? # VALUE ROMHEX
0 2476         AC09
1 21988 E455
2 21003 0B52
3 2500         C409
4 21076 5452
5 21076 5452
6 2492         BC09
7 21017 1952
8 20051 534E
9 2491         BB09
10 21032 2852
11 20053 554E
12 2476         AC09
13 49126 E6BF
14 49634 E2C1
15 2493         BD09
16 49632 E0C1
17 50148 E4C3
18 0         0000
19 17299 9343
20 17299 9343
21 2470         A609
22 21910 9655
23 20982 F651
24 2500         C409
25 21076 5452
26 21076 5452
27 2513         D109
28 20785 3151
29 19760 304D
30 2512         D009
31 20818 5251
32 19746 224D
33 2470         A609
34 49170 12C0
35 49634 E2C1
36 2514         D209
37 49784 78C2
38 50308 84C4
39 0         0000
40 17299 9343
41 17299 9343
42 0         0000
43 51830 76CA
44 0         0000
45 51830 76CA

based on we now know the WORD command writes to SRAM my guess now this is how they calibrate the unit.   
they probably stick a EPROM in with no cal values in it (ie 1FA0-1FFB = 00)
run various tests and program SRAM until it is cal'd.
read out those values and burn into the units EPROM

I guess the next thing is to figure out what they impact and what the calibration values are
are all 46 values for voltage only or are there other calibration values.

also note the DAC is used in a successive approximation ADC with 13bit resolution via U402A(integrator), U404(comparitor) and U409(analog switch which chooses VMON,IMON and the external Analog Volt input) and the U410(DAC) when the comparitor trips it sets the COMPARE bit[0] in STATUS1

Would it maybe be good to look at the VSET to figure out when and where they use the calibration values?
« Last Edit: July 31, 2017, 11:51:24 pm by smgvbest »
Sandra
(Yes, I am a Woman :p )
 

Offline smgvbest

  • Supporter
  • ****
  • Posts: 368
  • Country: us
    • Kilbourne Astronomics
here's an update.   I did a WORD 0,0 and wow what a change
at 0v actual volt was ~2400V
at 3000V it ran to 5600V  (this is interested)

so just changing the first byte has major impact
I then did a WORD 0,2476 and everything was back to normal

I then tried word 0,2477 and at 50V i got 48.4 which means the higher value actually lowered the output
I then tried word 0,2475 and at 50V I got 50.2V then shows for word 0 a value change of 2 has a 0.8v swing

next I tried setting word 1 to 0 with word 0 back to normal
with the word 00 at 0v I had ~650V on the DMM
everything below 3000V was scewed. above 3000V things where basicaly normal

I'l do more checking and will actually need to try to find at which values does each word have effect.
short of tring to figure out the code now that we know where cal values are
Sandra
(Yes, I am a Woman :p )
 

Offline alm

  • Super Contributor
  • ***
  • Posts: 1257
  • Country: 00
no more UV Erasing the EPROM  :-+
Yay!

I added the meaning of the calibration values based on my current understanding of the code (what I posted earlier):
Code: [Select]
WORD? # VALUE ROMHEX
0 2476        AC09 ; +pol vset offset
1 21988       E455 ; +pol vset exponent/multiplier/non-linear parameter if vset < word0
2 21003       0B52 ; +pol vset exponent/multiplier/non-linear parameter if vset >= word0
3 2500        C409 ; +pol vlim offset
4 21076       5452 ; +pol vlim exponent/multiplier/non-linear parameter if vlim < word3
5 21076       5452 ; +pol vlim exponent/multiplier/non-linear parameter if vlim >= word3
6 2492        BC09 ; +pol ilim offset
7 21017       1952 ; +pol ilim exponent/multiplier/non-linear parameter if ilim < word6
8 20051       534E ; +pol ilim exponent/multiplier/non-linear parameter if ilim >= word6
9 2491        BB09 ; +pol itrp offset
10 21032       2852 ; +pol itrp exponent/multiplier/non-linear parameter if itrp < word9
11 20053       554E ; +pol itrp exponent/multiplier/non-linear parameter if itrp >= word9
12 2476        AC09
13 49126       E6BF
14 49634       E2C1
15 2493        BD09
16 49632       E0C1
17 50148       E4C3
18 0           0000
19 17299       9343
20 17299       9343
21 2470        A609 ; -pol vset offset
22 21910       9655 ; -pol vset exponent/multiplier/non-linear parameter if vset < word21
23 20982       F651 ; -pol vset exponent/multiplier/non-linear parameter if vset >= word21
24 2500        C409 ; -pol vlim offset
25 21076       5452 ; -pol vlim exponent/multiplier/non-linear parameter if vlim < word24
26 21076       5452 ; -pol vlim exponent/multiplier/non-linear parameter if vlim >= word24
27 2513        D109 ; -pol ilim offset
28 20785       3151 ; -pol ilim exponent/multiplier/non-linear parameter if ilim < word27
29 19760       304D ; -pol ilim exponent/multiplier/non-linear parameter if ilim >= word27
30 2512        D009 ; -pol itrp offset
31 20818       5251 ; -pol itrp exponent/multiplier/non-linear parameter if itrp < word30
32 19746       224D ; -pol itrp exponent/multiplier/non-linear parameter if itrp >= word30
33 2470        A609
34 49170       12C0
35 49634       E2C1
36 2514        D209
37 49784       78C2
38 50308       84C4
39 0           0000
40 17299       9343
41 17299       9343
42 0           0000
43 51830       76CA
44 0           0000
45 51830       76CA
However, this does not account for approximately half of the calibration memory, so either there is some unused data in there, or my analysis is incomplete. The data looks very similar to the values that I can account for, so it does not look like unused memory to me. I welcome any pointers to where I am wrong. I believe I posted all relevant code, but I am also happy to post a complete listing file.

It might be interesting to zero each set of six bytes using WORD and see if indeed zeroing the first set of bytes only affects the set voltage, the second set only affects the limit, etc. I saw no sign of a checksum on the calibration data apart from a possible checksum for the whole ROM.

based on we now know the WORD command writes to SRAM my guess now this is how they calibrate the unit.   
they probably stick a EPROM in with no cal values in it (ie 1FA0-1FFB = 00)
run various tests and program SRAM until it is cal'd.
read out those values and burn into the units EPROM
I would expect them to indeed calibrate with some sort of identity value of the calibration parameters (if there is a multiplier in there, you probably do not want to zero it :P). $DAC appeared to only affect the VSET DAC, which would make it useless for VLIM/ILIM/ITRP calibration. However, the VSET calibration is by far the most critical, so maybe they use a more complicated algorithm similar to what I proposed earlier (try a range of DAC values and fit a curve to the corresponding output voltages), and a simpler two-point calibration for the less critical parameters.

Would it maybe be good to look at the VSET to figure out when and where they use the calibration values?
VSET is not very interesting. It starts at 0x1a87. First it does some parsing and error checking (e.g. does the sign of the value match the polarity setting on the front panel, status2 bit 2, checks that abs(vset) <= vlim). Then the actual work:
Code: [Select]
ROM:1ABF                 ld      (var_vset), de  ; store value for set_control_value
ROM:1AC3                 ld      a, 0            ; select vset parameter
ROM:1AC5                 call    set_control_value ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
After that some housekeeping (updating variables I have not figured out the meaning of), but no I/O or other interesting stuff. var_vset is a block of four words:
Code: [Select]
ROM:413C var_vset:       dw 0                    ; DATA XREF: ROM:03F4r
ROM:413C                                         ; apply_calib_consts+5o ...
ROM:413E var_vlim:       dw 1388h                ; DATA XREF: ROM:03E7r
ROM:413E                                         ; reset_stuff+56r ...
ROM:4140 var_ilim:       dw 1482h                ; DATA XREF: ROM:1BA8w
ROM:4140                                         ; ROM:1BBFr ...
ROM:4142 var_itrp:       dw 1482h                ; DATA XREF: ROM:1C17w
ROM:4142                                         ; ROM:1C2Er ...

set_control_value is the real meat. It is called by the VSET/VLIM/ISET/ITRP commands, and the WORD command (hence my initial guess that WORD was setting parameters). This is the interesting part, the rest is more of the same and some housekeeping (like keeping track for the function that sets the DAC which parameter was changed and updating some status variables):
Code: [Select]
ROM:0959 ; a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:0959
ROM:0959 set_control_value:                      ; CODE XREF: ROM:0425p
ROM:0959                                         ; reset_stuff+6Cp ...
ROM:0959                 call    conv_value_to_dac ; in: a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:0959                                         ; out: hl (dac value corresponding to the set value based on calibration constants)
ROM:095C                 di
ROM:095D                 cp      0
ROM:095F                 jr      nz, set_vlim
ROM:0961                 ld      (var_dac_vset), hl ; set_vset
ROM:0964                 ld      hl, byte_401A
ROM:0967                 bit     7, (hl)
ROM:0969                 jr      z, set_done
ROM:096B                 ld      hl, byte_40E5
ROM:096E                 set     0, (hl)
ROM:0970                 ld      hl, byte_401A
ROM:0973                 res     0, (hl)
ROM:0975                 jr      set_done
ROM:0977 ; ---------------------------------------------------------------------------
ROM:0977
ROM:0977 set_vlim:                               ; CODE XREF: set_control_value+6j
ROM:0977                 cp      1
ROM:0979                 jr      nz, set_ilim
ROM:097B                 ld      (var_dac_vlim), hl
ROM:097E                 jr      set_done
It first calls the function conv_value_to_dac (more on that later), and then stores the result from conv_value_to_dac in the appropriate memory location (0x4094 to 0x40a3, non-consecutive). It also stores which value it modified. The DAC function (run from timer interrupt) checks these variables, and based on that figures out which values to send to the DAC. Now for conv_value_to_dac:
Code: [Select]
ROM:08DB ; in: a = { 0: vset, 1: vlim, 2: ilim, 3: itrp }
ROM:08DB ; out: hl (dac value corresponding to the set value based on calibration constants)
ROM:08DB
ROM:08DB conv_value_to_dac:                      ; CODE XREF: set_control_valuep
ROM:08DB                 push    af
ROM:08DC                 rlca
ROM:08DD                 ld      e, a
ROM:08DE                 ld      d, 0
ROM:08E0                 ld      hl, var_vset
ROM:08E3                 add     hl, de          ; figure out where to find the input data
ROM:08E4                 ld      c, (hl)         ; load input data in bc
ROM:08E5                 inc     hl
ROM:08E6                 ld      b, (hl)
ROM:08E7                 cp      2
ROM:08E9                 jr      nz, find_calib_ram
ROM:08EB                 ld      hl, (vlim_max_input) ; only for vlim
ROM:08EE                 push    de
ROM:08EF                 push    bc
ROM:08F0                 push    af
ROM:08F1                 ld      de, 0Ah
ROM:08F4                 call    find_hl_magnitude ; input: de = usually 0x0a, hl = ?
ROM:08F4                                         ; out: hl = 16 - log2(hl) + log2(de) (approximately)
ROM:08F7                 pop     af
ROM:08F8                 pop     bc
ROM:08F9                 pop     de
ROM:08FA                 add     hl, bc
ROM:08FB                 ld      b, h
ROM:08FC                 ld      c, l
ROM:08FD
ROM:08FD find_calib_ram:                         ; CODE XREF: conv_value_to_dac+Ej
ROM:08FD                 push    af
ROM:08FE                 ld      a, (var_status2)
ROM:0901                 bit     2, a
ROM:0903                 ld      hl, calibration_ram
ROM:0906                 jr      z, apply_calib_con1
ROM:0908                 ld      hl,  calibration_ram+2Ah
ROM:090B
ROM:090B apply_calib_con1:                       ; CODE XREF: conv_value_to_dac+2Bj
ROM:090B                 pop     af              ; a = param { 0..3 } << 1, e = a << 1, bc = var_vset
ROM:090C                 rlca
ROM:090D                 add     a, e
ROM:090E                 ld      e, a
ROM:090F                 add     hl, de
ROM:0910                 ld      e, (hl)
ROM:0911                 inc     hl
ROM:0912                 ld      d, (hl)
ROM:0913                 inc     hl
ROM:0914                 push    hl
ROM:0915                 ld      h, b
ROM:0916                 ld      l, c
ROM:0917                 or      a
ROM:0918                 sbc     hl, de
ROM:091A                 pop     de
ROM:091B                 jr      c, apply_calib_con2_or_3 ; figure out if we use the 2nd or 3rd calib word
ROM:091D                 inc     de
ROM:091E                 inc     de
ROM:091F
ROM:091F apply_calib_con2_or_3:                  ; CODE XREF: conv_value_to_dac+40j
ROM:091F                 ld      a, 0
ROM:0921                 call    c, cpl_word     ; hl = -hl
ROM:0921                                         ; a = 1
ROM:0924                 ex      de, hl
ROM:0925                 ld      c, (hl)
ROM:0926                 inc     hl
ROM:0927                 ld      b, (hl)
ROM:0928                 ld      (var_status_thing), a
ROM:092B                 pop     af
ROM:092C                 push    af
ROM:092D                 push    bc
ROM:092E                 ld      hl, byte_99F
ROM:0931                 add     a, l
ROM:0932                 ld      l, a
ROM:0933                 jr      nc, loc_936
ROM:0935                 inc     h
ROM:0936
ROM:0936 loc_936:                                ; CODE XREF: conv_value_to_dac+58j
ROM:0936                 ld      a, (hl)
ROM:0937                 cp      0
ROM:0939                 jr      z, loc_942
ROM:093B                 ld      b, a
ROM:093C
ROM:093C loc_93C:                                ; CODE XREF: conv_value_to_dac+65j
ROM:093C                 sla     e
ROM:093E                 rl      d
ROM:0940                 djnz    loc_93C
ROM:0942
ROM:0942 loc_942:                                ; CODE XREF: conv_value_to_dac+5Ej
ROM:0942                 pop     hl
ROM:0943                 push    de
ROM:0944                 call    some_calc_hl_de ; in:
ROM:0944                                         ; de = intermediate dac value
ROM:0944                                         ; hl = calib word 2 or 3
ROM:0944                                         ; out:
ROM:0944                                         ; hl = result
ROM:0944                                         ; de = ???
ROM:0947                 bit     7, h
ROM:0949                 jr      z, loc_94C
ROM:094B                 inc     de
ROM:094C
ROM:094C loc_94C:                                ; CODE XREF: conv_value_to_dac+6Ej
ROM:094C                 pop     hl
ROM:094D                 add     hl, de
ROM:094E                 ld      a, (var_status_thing)
ROM:0951                 bit     0, a
ROM:0953                 jr      z, loc_957
ROM:0955                 set     7, h
ROM:0957
ROM:0957 loc_957:                                ; CODE XREF: conv_value_to_dac+78j
ROM:0957                 pop     af
ROM:0958                 ret
This is the entire function. I have discussed my analysis of a fair amount of the code in previous posts. My analysis of find_hl_magnitude (at 0x08ba) is new and preliminary, but is only relevant for vlim. Could be a form of rounding to order of magnitude (it tries to shift left hl until hl > de). Then it retrieves the calibration word1 (what I call offset) and subtracts it from the set value. If this result is negative, the second word is used for the subsequent calculation, otherwise the third word. Regardless of the polarity, it inverts the polarity (two's complement). Lets call this result the intermediate dac value. The block at 0x93c is skipped unless the values at 0x99f are non-zero (they are not in this dump).

Then the second or third word go into the creatively named some_calc_hl_de function that I posted earlier and suggested it is some sort of non-linear function (any insights would be appreciated!). I am not familiar with math in assembly on micros without multiplier, so I do not recognize this algorithm. I could do some digging or try to run it in a simulator to see what it does I guess. Let me know if you want me to dive into that.

Then it discards one of the result (16 bit * 16 bit multiply that discards the lower 16 bits?), and adds this to the intermediate dac value. Then it sets bit 7 based on a status variable, and that is the result that will be sent to the DAC. I have not looked into the details of that, but I know it happens in the function at 0x0ebb, which is called from the interrupt handler.
« Last Edit: August 01, 2017, 01:55:49 am by alm »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf