| Electronics > Repair |
| Quick Repair: Standford Research PS350 5KV 5mA(Fixed but working on calibration) |
| << < (4/11) > >> |
| Dexter2:
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. |
| alm:
--- Quote from: smgvbest on July 30, 2017, 03:00:45 pm ---given that setting the DAC maybe possible what I imagine they do then is basically (and crudely) [...] --- End quote --- 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: ---; 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 --- End code --- This appears to be the code responsible for copying: --- Code: ---ROM:0094 ld bc, 5Ch ; '\' ROM:0097 ld hl, unk_1FA0 ROM:009A ld de, byte_4026 ROM:009D ldir --- End code --- $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: ---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. --- End code --- 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. |
| smgvbest:
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: ---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 --- End code --- this is the block of data being copied --- Code: ---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Ê --- End code --- |
| Dexter2:
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 |
| alm:
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: ---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 --- End code --- 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: ---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 --- End code --- 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: ---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: --- End code --- Actually, on second thought, it looks like WORD? can query words from the calibration RAM: --- Code: ---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 --- End code --- 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: ---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 --- End code --- 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. |
| Navigation |
| Message Index |
| Next page |
| Previous page |