Electronics > Repair
Quick Repair: Standford Research PS350 5KV 5mA(Fixed but working on calibration)
<< < (5/11) > >>
Dexter2:
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.
alm:
Thanks for confirming my theory!
smgvbest:
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: ---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

--- End code ---

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?
smgvbest:
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
alm:

--- Quote from: smgvbest on July 31, 2017, 11:37:09 pm ---no more UV Erasing the EPROM  :-+

--- End quote ---
Yay!

I added the meaning of the calibration values based on my current understanding of the code (what I posted earlier):

--- Code: ---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

--- End code ---
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.


--- Quote from: smgvbest on July 31, 2017, 11:37:09 pm ---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

--- End quote ---
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.


--- Quote from: smgvbest on July 31, 2017, 11:37:09 pm ---Would it maybe be good to look at the VSET to figure out when and where they use the calibration values?

--- End quote ---
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: ---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 }

--- End code ---
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: ---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 ...

--- End code ---

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: ---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

--- End code ---
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: ---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

--- End code ---
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.
Navigation
Message Index
Next page
Previous page
There was an error while thanking
Thanking...

Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod