3478A cal RAM readout idea - Page 1
Forum section: electronics / testgear

author: wolfalex
author_rank: Regular Contributor
timestamp: June 18, 2015, 04:47:31 am
content: Hello, good evening,I got a second used 3478A on ebay, and now I have to swap another lithium battery to make sure I do not loose thecal RAM data. I really dislike the whole procedure, and I am sure a lot of other people too. Trying to read the caldata without breaking the device seems to be a pain (especially because all parts are soldered directly onto thePCB), and therefore I guess pretty much all people just buy a new battery and go through the pain again.I was wondering if there is a way to safely read the contents of the cal RAM for backup. In my oppinion soldering wiresto the pins of the uC or other devices is not safe enough... one slip or short and probably the RAM or another part isgone. Therefore I almost gave up on the idea again... but then I looked at a internal picture of my 3478a again, and Isaw something interesting: one single devices seems to have a socket (at least in my meter): RP527. This part iskind of weird in the schematic: the schematic symbol looks like it is just a bunch of 0 ohm bridges...I thoughtprobably it is there for helping during error search: it could be used to isolate both sides of the busses from each other by simplytaking the part out. In a list which decodes old HP part numbers this part is listed as some sort of 100 ohms resistor network. I am actually not sureyet if this device is now a short or more a resistor..I would need to measure its resistance to know for sure.But seeing this part in a socket gave me the following idea: I should be able to take this part out of the socket andinstead I slide a connector of a custom build PCB back into the same socket, which basically reconnects boths sides again, butat the same time allows easily to monitor the data lines D0 up to D7 (the ones were we will also see the CAL ram valuesgo through during startup of the 3478A).But of course there is a problem: if I do not have the adress lines at the same time as the data I do not know where thencal RAM data byte came from initially during the readout. I gave almost up again thinking about that, before I saw the following:The data lines D0 up to D7 which I should already be able to sniff easily via RP527 socket do also transport the adress lines A0 up to A7.I just must know when the adress is transported and when a data byte which of course is the job of the ALE line. So my next thought was:Is there a easy and undangerous way to get ALE (again I do not want to solder in my unit)...and actually there is: thankfully there is atestheader/pinheader for debugging (TP3) -> so my idea would be the following: My custom made readout board has simply its own ALE latch on it.This latch then generates the adress lines A0 up to A7 for me at the same time as U513 on the original board by use ALE. This should give me the adress infoI need.The last info I would need is when there is actually an read access from the CAL ram. Three signals should help me here: /OE1, OD and maybe CE2.R/W is not interesting I think, because until the CAL enable switch is enabled this line should never go to write access anyway.So from where do I get this signals without soldering? Again i found test pinheaders: OD is connected to /RD (TP5->easy).But /OE1 comes from another latch (U506) -> bad.... But on the input side of the latch on the same bit line is debugging jumper JM501...of courseI would not want to change the setting of this jumper, but the third unused pin of the pinheader/jumper allows easy connection to this signal as well(without changing the position of this jumper).And this latch is also clocked by ALE again -> we should be able to reconstruct this signal also on our own board. The only signal I am not sure rightnow is CE2...maybe it is needed but I am not sure yet.So now my idea: the readout board has an onboard RAM device (maybe dual port RAM) which sniff the cal data from the bus in realtime during startup of the3578A via the testpoints I described above. Then after the 3478A is started up and running an onboard uC on the selfbuild readout board reads this captured CAL RAM data fromthe capture RAM and stores it into a FLASH or EEPROM device for eternity, or for later transfer to a PC via the same uC.What do you think about this idea? Any feedback? I know there is still a long way to go from a simple idea to the final working circuit, and I also know the problem is normally in the details... Could this idea work? Do all units have the weird device RP527 in a socket? If not then the idea does not help much.But if so then this could be a way to read and backup the CAL RAM data without risk and soldering from any 3478A out there.I added a part of the schematic to this post, and also the internal picture from my unit, as well as the datasheet of the used CAL RAM(at least I think this is the datasheet for this part, if not please tell me).Any feedback is very welcome, thank you very much,have a nice evening,day or morningWolf Alexander

author: wolfalex
author_rank: Regular Contributor
timestamp: June 18, 2015, 05:17:44 am
content: Sorry for the bad picture quality. I added a better version of the same picture.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 18, 2015, 05:20:06 am
content: And as a sidenote: I think I have a more old version of the 3478A, because I have the isolation via transformer. So I hope this socketed part was not removed on later revisions of theboard.

author: MarkL
author_rank: Unknown
timestamp: June 18, 2015, 03:54:26 pm
content: As posted recently in another thread, an easy way to get a copy of the cal data is to use a logic analyzer on the cal RAM to capture the nibbles as they are readout upon boot (or self-test). The processor cycles through all the relevant cal locations so it can compute a checksum. Not every single location is read out, but presumably the other locations are not important. This will work with a lot of different test gear from that era.You can also make the 3478A cycle through ALL cal RAM locations by putting it in the service mode described in 7-D-23, a through e. This is really meant for signature analysis but can allow an analyzer to grab everything.I have done both of the above with my 3478A. No soldering necessary.If you lose the cal data, getting it back in the RAM is more complicated and you may need to physically isolate some of the control signals as you describe and have an external processor re-write the data.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 19, 2015, 12:14:51 am
content: Thank you very much for your response, and the information. I completely forgot about the possibility to do the same with a logic analyzer. Does somebody know if there is alsoa newer USB PC based logic analyzer which would be able to do this? I mean to read out the Cal RAM during startup?Which signals have you used to trigger the logic analyzer? I guess the logical combination between /RD and /CE1, or? Because the /CE1 line is also connected to the LCD Syncpin I guess this signal is used also for other things, and therefore trigger on /CE1 alone would not be enough. Is this correct?Does somebody actually know how the meter firmware calculates the checksum? This would be very interesting

author: MarkL
author_rank: Unknown
timestamp: June 19, 2015, 02:54:40 am
content: In this case, you would use the processor /RD signal as the clock with the RAM /CE1 as a qualifier, plus of course the 4 data and 8 address lines. The RAM R/W is always a read since the CAL switch is disabled, so that can be ignored. And the RAM /CE2 can also be ignored since it's is always true.For a USB based analyzer, I've used a Saleae 16-input analyzer to do this, but there are a ton of other makes/models that are equally capable.EEVBlog user "Sailor" has disassembled and understands large portions of the 3468A and 3478A startup code. You could try PM'ing him to see if he knows how it computes the checksum.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 19, 2015, 04:03:09 am
content: Unfortunately I do not have a logic analyzer right now, but thanks for the information which one you have used, and how it is done. Either I get a LA, or I try out a selfbuild circuit witha RAM to capture the data. I guess as long as I do not make a short on an adress/data line (and damage an onboard component with it) the CAL data should be save in the RAM,because the write access to the RAM is inactive anyway all the time (of course only if the CAL enable switch stays in the off position).Today I thought it would be interesting to use a FRAM for the data capture... then the saved data would be even non-volatile, and can be easily transfered.Knowing how to calculate the checksum would be a great thing... then at least one can check if the captured data is valid without writing it back to the device, and probably brickingit during the validation.How have you tested if your captured data is valid?

author: Sailor
author_rank: Regular Contributor
timestamp: June 19, 2015, 08:27:45 am
content: Quote from: MarkL on June 19, 2015, 02:54:40 amI wishBecause my resurrected 3468A complains about the Cal RAM (Error 1) I need to get into the nitty-gritty of this also. Not only to stop mine complaining, but to understand the format of the cal data and how it is applied. The 8-bit ROM checksum is calculated in the normal manner except for one aspect - if an addition to the sum generates a carry, that carry is added back into the sum with the next byte value, and so on. Unusual, but there it is. The ROM checksum over the 4k 'half-ROM' is zero, so obviously there is a pre-computed byte stuffed somewhere to make it so. When we obtained the new ROM image I quickly ran it through my checksum script to verify that it was ok, but I didn't look anywhere for that byte - I should do so. I would expect it to be the last byte, but there is nothing that says it has to be.I will look up how they handle the 4-bit RAM checksum - do they clear the top nibble of each value read, do they still do the add-carry thing, etc. I should be able to look at it tomorrow.

author: MarkL
author_rank: Unknown
timestamp: June 19, 2015, 04:03:54 pm
content: Quote from: wolfalex on June 19, 2015, 04:03:09 amI haven't. But I've captured the data with 3 different logic analyzers at 3 different times and they all agree. I'm confident I have the right data. (Yeah, I know, famous last words...)One other thought on restoring data. As you pointed out, there's a data bus break jumper in the 3478A. It should be possible to write a small program in an external EPROM or parallel flash that rewrites the RAM nibbles, and then substitute that for the real ROM in the unit.You could do this by removing the jumper, putting the temporary EPROM in parallel with the address and control lines, and feed the EPROM data output directly into the processor. When the processor booted, the temporary program would rewrite the RAM contents. No soldering necessary.It's too bad all equipment doesn't have a data bus break.The FRAM idea is interesting. It's like a removable logic state capture device.EDIT: No, the temporary EPROM is not such a great idea. The RAM inputs would be isolated from the processor databus too. It could still be done but would need an additional tri-state driver to allow passage of data from the processor to the RAM only on writes. Still no soldering, but more complicated than I had first thought.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 19, 2015, 10:41:06 pm
content: Sorry for the late response, but during work I try not to post in forumsgood thing that the weekend starts soon, and now I have much more time.@Sailor: Thanks for your input and knowledge. It would be so beneficial to know the way the checksum is done. Then I would not need to risk the calibration of a 3478A during the firsttest of the idea in the futureMaybe you find out how the do it. I have never seen the actual readout of the CAL RAM until now,...like I do not even know how much bytes theuse. Maybe somebody can send me a file with some valid readout data.. would be very interesting.@MarkL: I think after reading out the data in three different ways with always the same result I would also be more confident that the data is correctAn easy way of course to test thiswould be to find an already uncalibrated 3478A (with invalid RAM), try to upload your data into its RAM, and then just switch it on. Then you should get Self test OK, even if it is notthe cal values from this exact unit, or? Or does 3478A figure out itself in whatever way that the supplied cal values are bogus? (even if the checksum is OK).I really like the idea of supplying the uC with your own program to do certain things. One way of uploading your data would maybe to open the bus breaker, give the uC your ownprogram for upload via the uC data lines (to trigger write strobes to the RAM), and at the same time force the correct information on the other side of the bus breaker to the RAM inputs).wrong comment: (see edit2 below) /*But the main problem would be, that the onboard program ROM outputs have to be disabled in whatever way to prevent shorts on the bus. (and I am not sure if there is an easy way to do that).*/ end wrong commentEDIT: i forgot to mention the biggest problem: I do not know until now how to program the 8039AHEDIT2: I think I made a mistake. The ROM output drivers will not short with the RAM input data forced via the bus breaker lower side, because the ROM is only driving the BUS duringprogram code fetch... so the own circuit just has to go high impedance during program fetch, and then after program fetch does drive the data to the RAM on the now usable lowerbus.

author: Sailor
author_rank: Regular Contributor
timestamp: June 19, 2015, 11:47:53 pm
content: @MarkLMark, could you post (or PM me) a file with your cal RAM values? Hex, bin, or intelhex would be fine.Quote from: wolfalex on June 19, 2015, 10:41:06 pm@wolfalexI've attacheda couple of docs about the 8048. They won't teach youhowto write assembler for the 8048, but they do tell you everything that you need to know (almost). The same as writing assembler for any processor, you need to read the manuals (a hundred times) until you totally understand every nuance, and then recognize what the manuals, datasheets etchaven'ttold you, and what implications those omissions may have.EDIT: The file sizes are too large for eevblog. PM me your email address and I'll send them to you (three files, total size ~10MB)

author: wolfalex
author_rank: Regular Contributor
timestamp: June 20, 2015, 01:01:17 am
content: I found a document which shows all the command codes for the 8048. The first one I was interested to find was NOP. And of course a NOP is available. Maybe this command will behelpful. From the 8051 I know that if you simply apply NOP opcode all the time then the program counter will start at adr. 0 and simply count up one by one (like a counter) until thePC overflows, and everything starts again from 0. I do not know if the 8048 is the same, but maybe applying a continious NOP opcode could be used too at least readout the program ROM (which I would also like to try at one point in time) as a whole, and store it in an FRAM.I have to think about everything in detail first and learn more about the 3478AEDIT: maybe the watchdog timer will not like a continious NOP opcode, but maybe it can also be disabled with the jumper

author: wolfalex
author_rank: Regular Contributor
timestamp: June 20, 2015, 02:17:06 am
content: The 8048 emulator is already installed and runningNow I should even be able to run the original 3478A firmware

author: MarkL
author_rank: Unknown
timestamp: June 20, 2015, 03:09:49 am
content: Quote from: Sailor on June 19, 2015, 11:47:53 pmSure!Attached; have at it...

author: Sailor
author_rank: Regular Contributor
timestamp: June 20, 2015, 03:27:24 am
content: Thanks Mark. Interesting, yours look like about as much junk as mine- except that yours are ok and the 3468 spits the dummy at mine.Quote from: wolfalex on June 20, 2015, 01:01:17 amThe ROM contents are already available on K04BB's site.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 20, 2015, 04:02:27 am
content: Attached is the cal RAM readout idea. Bus Break Device is removed and its socket allows easy access. I know it looks complicated, but still I would be interested if this works.I still have not checked the bus timings, and if this can even work (setup, hold times and so on).Because my own running firmware allows me now to only trigger an access to the cal RAM I think I do not need the signal /CE1anymore. The firmware can trigger an read event fromall of the cal RAM adresses and then just halt the uC.The program could be something like that (i am sure the program is still missing some important things...like the watchdog reset), but just to give you an idea. If my program below is completely wrong please give me feedbackAt least in the emulator it seems to do the right thing. But it is also bascially my first assembler program..org 0CLR AMOV R0, Aloop:movx A,@R0INC R0MOV A, R0JNZ loopend:JMP end

author: wolfalex
author_rank: Regular Contributor
timestamp: June 20, 2015, 04:17:27 am
content: And here the cal RAM writeback scenario.

author: Sailor
author_rank: Regular Contributor
timestamp: June 20, 2015, 08:55:56 am
content: Basically, that looks reasonable. Just a couple of points:1. While your program (specifically, the movx instruction) will generate the /RD signal, you will need to have both /CE1 and CE2 active at the same time. CE2 should be ok from the power-on circuit, but /CE1 comes from U506-6, which is the ALE-latched output of P23. The RESET signal to the processor sets the port outputs to the high state, so before entering your read-out loop, you will need to write a '0' to that port bit.2. U510 is a DM81LS95 which requires both enables (/G1 and /G2) to be low to enable its outputs (which would be in contention with the RAM outputs). The /RD signal drives /G1, but /G2 is another bit from U506, so you will need to be certain that when you write the '0' to P23, you also write a '1' to P22.3. Similarly, you will also need to be sure to write a '1' to P21, otherwise you will enable the HPIB chip, and the /RD would make it also in contention with the RAM.I don't think I see anything else, but no guarantees.Good luck.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 20, 2015, 02:42:47 pm
content: @Sailor: Thank you very much for sharing your thoughts on the readout/writeback sketch. About P20 up to P23: If I am not wrong during a external program memory fetch this linesare automatically controlled by the program counter to get the correct program data (therefore the are not a GPIO pin in this case). But to do bank switching during an external RAM access, do I have to set P20 up to P23 as a normal GPIO pin, and I have to care about their state myself? Or is there also some kind of automatic mechanism in place?What my program is also yet missing is to reset the watchdog, and to make sure that all other GPIO pins are also in a state where nothing can go wrong.

author: Sailor
author_rank: Regular Contributor
timestamp: June 20, 2015, 11:39:53 pm
content: Quote from: wolfalex on June 20, 2015, 02:42:47 pmA couple of things:1. The signals in question (/CE1 for the RAM, /G2 for the U510 driver, and /CS for the HPIB chip) are controlled by thelatchedvalues of P23 - P20 in U506, not by the port bits directly. The I/O values of P23 - P20 are latched into U506 on the leading edge of every ALE pulse, which occurs oneverycycle of the 8039.2. The movx instruction is a 2-cycle instruction, and during the first cycle when it is fetching the instruction from program memory, the normal I/O values of P23 - P20 are replaced by address bits <11:8>. But that is only until the end of the /PSEN pulse. At that time the normal I/O values are restored and shortly after that the ALE pulse that starts the second cycle of the instruction once again latches the (same) port values into U506, and shortly after that the /RD signal is generated. Note that the 8039 was designed with only the intrinsic capability of addressing 256 bytes of external data RAM, and so it only needs to output 8 bits of address, which it does on the BUS lines. Port P23 - P20 are not designed to have any special function during a movx instruction.3. If you want to have the ability to address more than 256 bytes of external data RAM, then yes, you will need to set up and control your own bank-switching signals, using any port bits that are available in your design. There is nothing internal to the 8039 that will be related to your alternate bank access. As far as the 8039 is concerned it is simply addressing one of 256 locations.The waveforms in the datasheet contained in the MCS-48 User Manual tell most of the story (remember what I said about 'what isnotin the datasheets'). The datasheet produced by Fujitsu is minutely more illuminating (thanks, MarkL), and I'll send that to you also.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 21, 2015, 12:09:55 am
content: My plan would be right now to just program/handle the pins P21 up to P23 as GPIO pins, and set their level before I enter the readout loop as needed. (P21 = 1, P22 = 1, P23 = 0).This would prevent the bus collisions as you have already noted.For pin P20 I do not really know what level is needed because in the schematic it only goes to the LCD and I have not yet seen what the purpose of this signal is. But I assume that the reset pin level of P20 must be at least a safe condition for the hardware. And for the readout P20 does not matter anyway.Thanks again for your very helpful information.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 23, 2015, 03:16:11 am
content: I have opened now the 2nd 3478A I got on Ebay lately. I am a little bit disappointed now, because it seems in the newer Revisions of the 3478A the bus breaker RP527 was removed (no socket), and seems to be replaced with some wire-jumpers on the PCB. Also some of the test points are not mounted/soldered onto the PCB, like in my other 3478A.So opening the bus breaker will be a little bit more work on the newer revision.I was happy to see that my second 3478A also passes the Self Test, and it basically measures OK. The only problem I found with it is, that the display disappears randomly after some minutes of operation. So operation is intermittent, like somebody would switch it on and off all the time. Maybe the reset circuit triggers, or something is wrong with the displaySo not really a complete winner.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: June 23, 2015, 08:05:59 am
content: How do they write that cal data at factory? Why don't look for some serial port/service mode?

author: dom0
author_rank: Super Contributor
timestamp: June 23, 2015, 08:20:39 am
content: They just calibrate it as outlined in the manual. You can do that fully automated over GPIB ; just connect GPIB, four/five wires from your universal calibrator and run the calibration program.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 24, 2015, 12:25:08 am
content: Now I only need the universal calibrator

author: wolfalex
author_rank: Regular Contributor
timestamp: June 27, 2015, 04:18:41 am
content: I have already learned that the 8048 can adress 4K of ROM by using 2 different pages. But the ROM is twice as big, and the adress bit A12 is controlled with a line on port2.Does the firmware of the 3478A in normal run mode use all 8k of ROM for program execution?Technically it should be possible that the firmware changes the level on A12 via a P2 port write, and then it does simply a JMP to the new target adress in the upper ROM area, or?The CPU would not know that it actually executes from another memory area, but in this way probably the useable program memory was increased.Could this be? I was just wondering how much program code is stored in the area between 4k and 8k when I looked at the disassembly results from the 3478A firmware.

author: Sailor
author_rank: Regular Contributor
timestamp: June 27, 2015, 11:53:42 pm
content: Terminology - the 2k segments of a 'standard' 4k program memory address space are called banks. A page is a 256-byte segment of the address space.Blocks are selected by the SEL MB0 and SEL MB1 instructions. Those instructions merely set or clear a flop that they somewhat euphemistically call 'bit 11 of the program counter'. It isn't really a part of the PC, it's simply a bank-select flop. Importantly, it only comes into play during JMP and CALL instruction execution - you can set or clear it whenever and as many times as you like while executing 'normal' code without it having any effect whatsoever. Pages are accessed via the MOVP and MOVP3 instructions. These limited addressing capabilities mean that you need to get fairly creative when writing a large program.The use of the Port 2 bit to provide additional addressing range is dramatically different. The 8039/8048 architecture does not have any knowledge of such a feature, so it isn't a case of 'and then it does simply a JMP to the new target adress in the upper ROM area'. A change of the ROM address bit 12 by writing to Port 2 causes aninstantaneoustransfer of control to the other 4k memory segmentat the address following the instruction that altered Port 2. i.e. you don't have a choice of a destination address like you do in a normal JMP or CALL. This means that you need to guarantee the placement of your code in the 'other' 4k bank is such that program execution continues in the manner that you expect. These same considerations apply when / if you want to return to the original code, which is why you will generally see the following sort of construct:Assume we are in the lower 4k region0x345 ORL P2, #0x40 ;set address bit 120x347 NOP0x348 xxx ;code continues after returning from upper 4kIn the upper 4k region we see0x345 ANL P2, #0xbf ;clear address bit 120x347 NOP0x348 xxx ;code to be executed in upper 4k...JMP 0x345 ;go clear address<12> and 'return' to lower 4k regionOf course, there is no particular reason why a routine in one region should 'return' to carry on in the other region, and you will see examples where the code in one region is obviously crafted to expect 'jumps' to arrive from anywhere, be it from the same region via a JMP, or from the other region via address<12> manipulation.Another thing that must be kept in mind while working like this is that the Bank-Select state transfers (i.e. continues) when swapping regions, and furthermore the stack contents (which also include the Bank-Select bit) continue to be in play, so that if a RET/RETR is executed in the 'other' region, it will transfer control to the appropriate address of the upper or lower bank within that region. So, once again, your code must be placed correctly to ensure that things work as planned.It's messy!

author: wolfalex
author_rank: Regular Contributor
timestamp: June 28, 2015, 12:14:58 am
content: Thank you so much for the time you spend explaining this in detail to me. I must confess I have not really used assembler much in my live (instead I use C on microcontrollers on a daily basis). But I still think that I can read an assembler program and that I bascially know what it does and why.After dissassembling the 3478A ROM and my first looks at the output listing I must say that the whole code looked really strange to me... random single NOPs between a long list of "normal" commands, and then weird JMP commands all over the place. I think after knowing now how much black magic the had to use to increase the program space and tomake it work on the 8039 (which I also do not know much yet) I also understand now why the assembler code looked so strange to me.Now I also know why the emulator jumped just weirdly through the 3478 firmwareIt has basically no chance to run through the program normally.How were you able to locate the ROM checksum routine in the disassembler listing? Yesterday I tried to locate the place in the firmware where the LCD communication takes place and it was very difficult to do so.

author: Sailor
author_rank: Regular Contributor
timestamp: June 28, 2015, 12:56:10 am
content: I'll be busy for the next 6 hours or so. Then I will show you the reasoning that led me to the checksum routine in the 3468, then how it is different in the 3478. In the meantime, try and think aboutwhatthe routine has to do, and (given the limited addressing capabilities of the 8039)howit might achieve it.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 28, 2015, 04:40:38 am
content: My thought process is the following: I learnt two commands are for program memory access: MOVP and MOVP3.MOVP3 seems to allow access to page 3 of the program memory.. but that means it can not access all of program memory if I am not wrong.So it is not useful for this purpose.so this leaves only the MOVP command... but the problem is MOVP only allows to access program code in an area of one page aroundthe current program counter value. So this is a big limitation.Initially I was searching for a construct with for-loops and a single read program memory command which access all of ROM.....like I would do it in C. But now given the limitations of MOVP I actually think the only way to achieve the checksum over the whole ROM isto split and spread the checksum calculation routine over the whole ROM (each page must contain one part of the routine).And then each part of the routine has a jump command to the next part.I think the following codes parts take part in the ROM checksum calculation: (3 example blocks)L00FC:00FC : FF " " mov a,r700FD : A3 " " movp a,@a00FE : 7E "~" addc a,r600FF : AE " " mov r6,a0100 : FF " " mov a,r70101 : A3 " " movp a,@a0102 : 7E "~" addc a,r60103 : AE " " mov r6,a0104 : 44 FC "D " jmp L02FC02FC L02FC:02FC : FF " " mov a,r702FD : A3 " " movp a,@a02FE : 7E "~" addc a,r602FF : AE " " mov r6,a0300 : FF " " mov a,r70301 L0301:0301 : A3 " " movp a,@a0302 : 7E "~" addc a,r60303 : AE " " mov r6,a0304 : 84 FC " " jmp L04FC04FC L04FC:04FC : FF " " mov a,r704FD : A3 " " movp a,@a04FE : 7E "~" addc a,r604FF : AE " " mov r6,a0500 : FF " " mov a,r70501 : A3 " " movp a,@a0502 : 7E "~" addc a,r60503 : AE " " mov r6,a0504 : C4 FD " " jmp L06FDas can be seen one block jumps to the next block. you also wrote that the checksum is done by adding up to a sum, and also that the carry is added to the next byte.So after the movp is an addition which fits to your description. Simular blocks like above can also be found at other program memory locations.But unfortunetly I am not able right now to see the big picture, i mean I do not know where the routine starts and where it actually ends.It is pretty complicated to try and find the red line through the code. And I am also not sure if there are actually enough blocks like above to reach all parts of the ROM.I also tried to search for "OUTL P2, #0BFH" commands to alter A12, but there are to many to use them as an orientation point.Am I on the right track with my assumptions? I can not wait to read your answer and to see if I am correct or not. Unfortunetly I have to go to bed now and I will onlybe able to answer again in 8 hours... it seems we are maybe in different time zonesThank you very much again for your insight, it makes a lot of fun to go through the code and try to find the things you describe or point out.

author: Sailor
author_rank: Regular Contributor
timestamp: June 28, 2015, 08:38:46 am
content: Very good, Alex. As you surmise, the code has to be distributed, and you have done well to identify the method so quickly. I said earlier that I would show you the way the 3468A did it, and the differences to the 3478A. But I'm not going to keep my end of the bargain (at least, not just yet), and I'll tell you why.I have been writing assembler (and other languages) for mainframes, minis, and micros since the mid-1960s, and I strongly believe that EEs should have a good background in the real nut'n'bolts of embedded micros. Unfortunately, it seems to be a dying art, so when someone shows not only interest, but also ability, I want to encourage them.To that end:Doing is 1000 times better than being shown.Doing and succeeding is extremely satisfying.Doing promotes remembering.So, getting back to the questions:Quote from: wolfalex on June 28, 2015, 04:40:38 amYou obviously have a disassembler that produces a usable file. And an editor with search capabilities. And you have identified a string of code-segments that are connected by JMPs. The last of those segments ends with aSo, how did the first segment get executed?How much of the memory did one execution of these code segments cover?What is the significance of r7?When you have the checksum routine sorted out (I don't think it will take you long), I think you will find it both interesting and instructive to trace the first ~ 100 instructions (and their subroutine calls, etc) following a RESET. Code execution begins at the start of the upper 4k of ROM.BTW, what disassembler are you using?

author: wolfalex
author_rank: Regular Contributor
timestamp: June 28, 2015, 05:58:24 pm
content: Hi,Sorry for the late answer, but my 7 month old daughter uses most of my freetime nowI used a program called "DASMx" Version 1.4 from Conquest Consultants I found online for the disassembly.I also attached the result I got to this email if somebody is interested.Thank you for your nice words. Without your hints it would also most likely have taken way longer to find the ROM checksum parts (because I would not have expected that this code is distributed over the whole code). Thanks to you I also now know that the program starts in the higher 4k of ROM. I completely forgot that A12 is high after uP reset, and that this actually means execution does not start in the lower 4k. Until now I always started to read the firmware from the wrong adress(this explains also why it did not make sense at all).I will take the new information and look again at the firmware in the next hours when I have more time. And I will try to look at the first 100 instructions as you have pointed out. Will be very interesting.What I would like to achieve at the end is to find the RAM checksum calculation in the firmware.I agree on your points made about programmers/EE today concerning uC. What I see every day is that there seems to be 2 groups of programmers out there: one (like me) which handles the uC from the EE point of view: bits, switches, logic gates, timing: If I use a functional block for example I start with the description from the block in the datasheet, then I write an init routine to set every needed bit in the block, and then I go from there...The other group comes more from the PC side of things, and the often start using some sort of libraries or finished routines. And I guess the often do not start with the functional diagram of the block itself, or the do not really care about the bit level/circuitry so much.For me I prefer option one. For me it is fun to understand the blocks more in detail and use them from scratch. And I also think this leads to much better/more reusable code in most of the cases.

author: Sailor
author_rank: Regular Contributor
timestamp: June 29, 2015, 02:10:38 am
content: To all those who may be interested, and who may be able to offer some insights, here is the format of the data contained in the 3478A Cal RAM. The attached image is a dump of data kindly provided by MarkL. Starting from offset 01 there are eighteen 13-byte (nibble) records, with the first few plus the last one outlined. Each record consists of 11 nibbles of data plus two nibbles which are concatenated to form an 8-bit checksum. Note that these two are presented in the order most-significant _ least-significant nibble e.g. the 8-bit checksum of the first record is 0xd2 (and there is no funny 'carry' as in the ROM checksums).I do not know the significance of the data values - at a guess, I would suspect they are ADC count errors, but...There are a number of questions surrounding them; are they signed values (doesn't allow much range)? Why eleven values? Why eighteen records? Given the number of functions to be calibrated (DCV, ACV, DCA, ACA, and Ohms), and the number of points at which those functions are calibrated, I don't see how it ties up. Furthermore, the method of referencing the records is odd. In the main ROM there is a table of the offsets of records in the Cal RAM, despite the fact that the records are of a known size at known, computable, locations. Added to that is that the ROM table is 50 elements in size, quite a few of which are zero (denoting a non-record), and several of which are duplicates. The table is shown below (I have added decimal equivalents for the RAM offset values because I inadvertently displayed decimal offsets in the WinHex image).R RO AM MA Od fd fr se es ts0e0f - 00 00e10 - 01 10e11 - 0e 140e12 - 1b 270e13 - 28 400e14 - 35 530e15 - 00 00e16 - 00 00e17 - 00 00e18 - 4f 790e19 - 4f 790e1a - 4f 790e1b - 4f 790e1c - 00 00e1d - 00 00e1e - 00 00e1f - 00 00e20 - 5c 920e21 - 69 1050e22 - 76 1180e23 - 83 1310e24 - 90 1440e25 - 9d 1570e26 - aa 1700e27 - 00 00e28 - 5c 920e29 - 69 1050e2a - 76 1180e2b - 83 1310e2c - 90 1440e2d - 9d 1570e2e - aa 1700e2f - 00 00e30 - b7 1830e31 - c4 1960e32 - 00 00e33 - 00 00e34 - 00 00e35 - 00 00e36 - 00 00e37 - 00 00e38 - de 2220e39 - de 2220e3a - 00 00e3b - 00 00e3c - 00 00e3d - 00 00e3e - 00 00e3f - 00 00e40 - aa 170One option that may help is if my 3468A has a similar format, I could do a 'bad' calibration and see how the number change. A better solutionis to understand how the values are used, but so far I haven't traced the ADC functions in the code.All suggestions welcome!

author: wolfalex
author_rank: Regular Contributor
timestamp: June 29, 2015, 04:14:41 am
content: Thank you very much for your fantastic job on finding out more about the cal RAM checksum and structure. I find this information very interesting. Also a big thanks again to MarkL for providing the readout data. I can not wait to see what other additional findings we will get from this.Unfortunetly I had no time today to revisit the Rom checksum routine in detail, but I will try to do that tomorrow.

author: Sailor
author_rank: Regular Contributor
timestamp: June 29, 2015, 05:45:28 am
content: Alex, I had a look at the disassembly listing that you attached earlier, and downloaded the DASMx archive. I suspect that the disassembler that I use (D48), and yours, both have the same origins. Yours may even be a later, glossier development of D48. I presume that you have read the section in DASMx.pdf regarding their 'code threading' and 8048 disassembly operations, and that you have disabled it. While I agree completely with the difficulties that can be encountered with the (internal, 2k) bank switching in the 8048, I find that it is more of a help than it is a hindrance. D48 doesn't have the ability to turn the threading on or off - it may not even perform the thread-following algorithm (I haven't looked at the source code) - but it does handle the SEL1 / SEL0 influence on the destinations of CALLs and JMPs made local to the SELx instructions, and I find that to be useful.It is undoubtedly safer to 'handle it yourself' either with pencil and paper, notes made in your disassembly file, or a (very) good memory. Nevertheless, I prefer to let the machine do as much as it can for me, and if I find it reports a destination address that doesn't look rational I simply backtrack a little to determine which SEL state is in effect. The very limited stack depth in the 8039/8048 means that the depth of subroutine CALLs is very shallow, so it's not a huge burden.Just my thoughts. YMMV.

author: Sailor
author_rank: Regular Contributor
timestamp: June 29, 2015, 06:54:44 am
content: I've just been reading DASMx.pdf again, and it isn't specifically linking code threading to SELx handling. It's worse than that! This extract from page 16:" it is advised that code threading be not used if the size of the 8048 source image exceeds 2 Kbytes. If images greater than this are disassembled, even with threading disabled, some errors in automatically generated labels may be expected."seems to mean that it doesn't handle SELxat all! The following is an extract from your disassembly listing:0421 : F0 " " mov a,@r00422 : 12 59 " Y" jb0 L04590424 : F5 " " sel mb10425 : D4 00 " " call L06000427 : E5 " " sel mb00428 : A8 " " mov r0,aThe CALL at location 425 is to a destination at 0x0e00, not 0600 i.e. DASMx didn't take any notice of the SEL1 instruction. This is fine if you are prepared to be vigilant and do the address modification yourself every time. The danger arises (as in this case) when the non-adjusted destination leads to apparently rational code:0600 L0600:0600 : A5 " " clr f10601 : 8A 80 " " orl p2,#080H0603 : B8 00 " " mov r0,#000H0605 L0605:0605 : 46 0B "F " jnt1 L060B0607 : E8 05 " " djnz r0,L06050609 : C4 2D " -" jmp L062D;060B L060B:060B : 35 "5" dis tcntietcinstead of the correct code at0E00 : 8A 0F " " orl p2,#00FH0E02 : 9A F7 " " anl p2,#0F7H0E04 : B8 3F " ?" mov r0,#03FH0E06 : F0 " " mov a,@r00E07 : 77 "w" rr a0E08 : 77 "w" rr a0E09 : 53 3F "S?" anl a,#03FH0E0B : 03 07 " " add a,#007H0E0D : A3 " " movp a,@a0E0E : 93 " " retrI'm afraid that I find life easier (I'm lazy) with the following output of D48:mov a,@r0 ; 0421 - f0 pjb0 X0459 ; 0422 - 12 59 .Ysel mb1 ; 0424 - f5 ucall X0e00 ; 0425 - d4 00 T.sel mb0 ; 0427 - e5 emov r0,a ; 0428 - a8 (andX0e00: orl p2,#0fh ; 0e00 - 8a 0f ..anl p2,#0f7h ; 0e02 - 9a f7 .wmov r0,#3fh ; 0e04 - b8 3f 8?mov a,@r0 ; 0e06 - f0 prr a ; 0e07 - 77 wrr a ; 0e08 - 77 wanl a,#3fh ; 0e09 - 53 3f S?add a,#7 ; 0e0b - 03 07 ..X0e0d: movp a,@a ; 0e0d - a3 #retr ; 0e0e - 93 .Either way, it's a personal choice.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 30, 2015, 02:38:33 am
content: The problem is at the point in time when I downloaded the disassembler and the emulator I was not yet aware about all the specialities of the 8048 and how complex the adressing is.My only knowledge at this point in time was derived from my experience with the 8051, and there in comparision it is quite simple: one program counter with full width, no sel commands and so on. So at this point in time I still thought the disassembler output must be ok, despite the fact that I already saw that the listing does not always seen to make sense.After your explainations, after I saw that the use A12 for program memory switching and the usage of sel commands I was already afraid that the disassembler maybe does not do a good job. But after your last post I am now really aware of the problem. I also already tried to follow the code from the start and at the first sel command and call I saw already how difficult it is to calculate the correct jump adress yourself. First you must know the current logic state of the A12 line, then the last sel command issued, and then also take in account the adress of the call command itself.

author: wolfalex
author_rank: Regular Contributor
timestamp: June 30, 2015, 03:29:51 am
content: I have now installed d48 instead the disassembler I have used until now. Thanks for correcting my mistake.If I get now the following output: (the same location you have shown above)X041f: mov r0,#41h ; 041f - b8 41 8Amov a,@r0 ; 0421 - f0 pjb0 X0459 ; 0422 - 12 59 .Ysel mb1 ; 0424 - f5 ucall X0e00 ; 0425 - d4 00 T.Can I now simply follow the target adresses in the listing for all the calls (like 0e00 at location 0425), or do I have to calculate the target adresses again myself. It seems the sel mb1in the line before is already taken into account in the adress call target adress 0e00, isn´t it?I guess the only bit that has to be corrected by me is the MSB of the call adress, because the disassembler can not be aware of the current state of bit A12, or?Sorry for asking the same questions over and over again, but I want to prevent that I make another mistake again, and I am really interested into learning more about how to use the output of the disassemblerThank you very much.***************************I added an example what I mean: right at the start of the firmware I see a jmp at adr 1001 to adr X082a. But I also know that A12 on the ROM is still high -> so I would expect now that the next adress I have to go to in the listing is 182a.org 1000h;clr f0 ; 1000 - 85 .jmp X082a ; 1001 - 04 2a .*;but then if I try to locate adr 182a in the disassembler output i can not find it. There is only a command one byte before and afterwards of this adress. So clearly I must be wrong with my assumption, or?jnc X182b ; 1827 - e6 2b f+jb1 X18f2 ; 1829 - 32 f2 2rjb1 X1833 ; 182b - 32 33 23jb3 X1890 ; 182d - 72 90 r.jb4 X1890 ; 182f - 92 90 ..jb2 X188a ; 1831 - 52 8a R.