Post Reply 
Service module (SM1C) and peripherial flags
05-27-2024, 08:46 AM (This post was last modified: 05-27-2024 08:50 AM by ThomasF.)
Post: #1
Service module (SM1C) and peripherial flags
Hi,

I was pointed to a piece of code in the Service module for the HP41, which apparently checks or tests the peripheral flags.

For me, the code looks quite strange, I understand what the test tries to do, but I can't understand how it could or should work!

Apparently it loads a flag pattern in the C register, and then checks to see if the FI flags are set accordingly.
But I can't understand how the flags are updated, IMHO only specific hardware can drive the FI lines and setting of the flags, this is not possible by just software.

Code:
 We start by initializing the C register ...
 460A 04E          C=0 ALL
 460B 2DC          R= 13
 460C 3D0          LD@R F
 460D 3D0          LD@R F
 460E 3D0          LD@R F
 460F 3D0          LD@R F
 4610 09C          R= 5
 4611 3D0          LD@R F
 4612 3D0          LD@R F
 4613 3D0          LD@R F
 4614 01C          R= 3

 Now register C contains FFFF0000FFF000

 In the following code we check all FI flags - which actually matches the content of the C register!
 Remember that FI is active low, i.e. a low value on FI represents an active state (ie carry set).
  * If C[i] contains '0', the corresponding PF flag should be active (?FI= i -> carry), and if no carry we jump (JNC).
  * If C[i] contains 'F', the corresponding PF flag should not be active (?FI= i -> no carry), and if carry we jump (JC).

 4615 3AC          ?FI= 0
 4616 0DB          JNC +27 4631
 4617 32C          ?FI= 1
 4618 0CB          JNC +25 4631
 4619 22C          ?FI= 2
 461A 0BB          JNC +23 4631
 461B 02C          ?FI= 3
 461C 0AF          JC +21 4631  ; C[3] = F
 461D 06C          ?FI= 4
 461E 09F          JC +19 4631  ; C[4] = F
 461F 0AC          ?FI= 5
 4620 08F          JC +17 4631  ; C[5] = F
 4621 16C          ?FI= 6
 4622 07B          JNC +15 4631
 4623 2AC          ?FI= 7
 4624 06B          JNC +13 4631
 4625 12C          ?FI= 8
 4626 05B          JNC +11 4631
 4627 26C          ?FI= 9
 4628 04B          JNC +9 4631
 4629 0EC          ?FI= 10
 462A 03F          JC +7 4631  ; C[10] = F
 462B 1AC          ?FI= 11
 462C 02F          JC +5 4631  ; C[11] = F
 462D 36C          ?FI= 12
 462E 01F          JC +3 4631  ; C[12] = F
 Finally we check FI:13 and since C[13] is 'F' the flag should not be active, so we should jump (JNC)
 462F 2EC          ?FI= 13
 4630 01B          JNC +3 4633 ; C[13] = F

 We end up here if and only if any flag (i) mismatches the value in C[i]!
 I interpret that this is an "error" state, i.e. we jump here only if C[i] doesn't correspond to the actual flag!
 We set B[3] = 0, and sets cpu flag 11
 4631 022          B=0 @R
 ; B = .00FFFFFFF0...
 4632 188          SETF 11

 We only jump directly here from 4630 if (and only if) all FI flags corresponds to the valuec in C.
 4633 05E          C=0 MS

So after this test is executed, cpu flag 11 is set if any peripheral flag mismatches the value in C.
Maybe the pattern in C is only a reference to what is expected, but the values are not used by the code, it would only make sense if C is somehow shifted out on the FI bus - but I can't see how that could be done!

Or maybe if no peripheral is selected, does the value of C drive the FI-flags instead? This is something I have missed if that is the case!
But that would make no sense either - since normally no peripheral is selected, and any '0' in C[S] would then cause a service request (?FI= 13 aka ?SERV).

My next step is to try and write a small test program that executes this code, or just try to trace the Service module to see if this code works, or even if it is actually executed (maybe the code is left in the ROM but never used).

Maybe someone has some thoughts or ideas about this?

Cheers,
Thomas

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
05-27-2024, 09:41 AM
Post: #2
RE: Service module (SM1C) and peripherial flags
Is C used further on in the code?

Initially it is set to FFFF0000FFF000, but at 4633 is cleared to 00000000000000.

cheers

Tony
Find all posts by this user
Quote this message in a reply
05-27-2024, 10:39 AM
Post: #3
RE: Service module (SM1C) and peripherial flags
(05-27-2024 09:41 AM)teenix Wrote:  Is C used further on in the code?

Initially it is set to FFFF0000FFF000, but at 4633 is cleared to 00000000000000.

cheers

Tony

Hi Tony,

Well, at 4633 only the most significant nibble is cleared, ie. C = 0FFF0000FFF000.
After that PRPHSLCT is called, and C[XS] is incremented, both uses only the last 3 last nibbles.
RAMSLCT would then select RAM at 0x0100, and we write 0x0FFF0000FFF100 to the register at 0x100, clear the C register and read it back to verify if 0x100 exists in the address space (first register in memory module 1 (in a 41C)).

But, I have not looked much at the code yet, but seems like it tries to see what memory is available, but the actual value in C is not used (only last 3 nibbles to point at the wanted reg address).

Cheers,
Thomas


Code:
 4633 05E          C=0    MS     ; C = 0FFF0000FFF000
 4634 3F0          PRPHSLCT      ; Deselect any peripherial
 4635 236          C=C+1    XS   ; C = 0FFF0000FFF100
 4636 0A0          SLCTP
 4637 3DC          R=R+1
 4638 10E          A=C    ALL    ; A = 0FFF0000FFF100
 4639 270          RAMSLCT       ; Select register address 0x100
 463A 2F0          WRITDATA      ; Write C to register at 0x100
 463B 04E          C=0    ALL    ; Clear register C
 463C 038          READDATA      ; Read back from 0x100
 463D 36E          ?A#C    ALL   ; Still same value?
 463E 02B          JNC    +5 4643 ; Jump to 4643 if equal (memory exists)
 463F 17E          A=A+1    MS   ; Increment A[MS] ( A = 0FFF0000FFF200)
 4640 0AE          A<>C    ALL   ; Restore C
 4641 10E          A=C    ALL  
 4642 022          B=0    @R

 4643 0E0          SLCTQ
 4644 31C          R=    1
 4645 130140       LDIS&X    140
 4647 20A          C=C+A    R<   ; Ram-addr += 0x140
 4648 373          JNC    -18 4636  ; Try again ...
 4649 0A0          SLCTP
 464A 309118       ?NCXQ    46C2
 464C 05E          C=0    MS
 464D 23E          C=C+1    MS
 464E 37E          ?A#C    MS
 464F 0FF          JC    +31 466E
 4650 05C          R=    4
 4651 052          C=0    P-Q
 4652 272          C=C-1    P-Q
 4653 0F2          B<>C    P-Q
 4654 18C          ?FSET    11
 4655 0CF          JC    +25 466E
 4656 14D11C       ?NCXQ    4753
 4658 328          WRIT    12
 4659 328          WRIT    12
 465A 09D11C       ?NCXQ    4727
 465C 013          JNC    +2 465E
 465D 014          ?R=    3
 465E 012          A=0    P-Q
 465F 00F          JC    +1 4660
 4660 010          LD@R    0
 4661 120          ?P=Q
 4662 24111C       ?NCXQ    4790
 4664 3CC          ?KEY
 4665 1DD103       ?CGO    4077
 4667 18C          ?FSET    11
 4668 027          JC    +4 466C
 4669 2CC          ?FSET    13
 466A 3ED117       ?CGO    45FB
 466C 201102       ?NCGO    4080
 466E 2DC          R=    13
 466F 188          SETF    11
 4670 290          LD@R    A
 4671 235118       ?NCXQ    468D
 4673 0C6          C=B    S&X
 4674 0F10F2       ?NCGO    3C3C
 4676 0F3          JNC    +30 4694

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
05-27-2024, 10:43 AM
Post: #4
RE: Service module (SM1C) and peripherial flags
(05-27-2024 08:46 AM)ThomasF Wrote:  Apparently it loads a flag pattern in the C register, and then checks to see if the FI flags are set accordingly.
But I can't understand how the flags are updated, IMHO only specific hardware can drive the FI lines and setting of the flags, this is not possible by just software.

Yes, that test won't work without a "flag-wired" module, which presumably loops the DATA signal (which usually presents the value of C) to the FI signal. It might be just a direct connection, though there's a small chance that they might have buffered it.

I brought this up once before here, and people didn't seem to believe me. The flag-wired module is mentioned in the service manuals, e.g. in the original 41C Service Manual, Table 4-1 on page 4-1, item ET-11967 "Flag-Wired Memory Module", diagnostic test table step 1 Preparation on page 4-2, and and step 12 on page 4-4, step 1 in table 4-2 on page 4-6, step 12 on page 4-11, and aslo in the Service Note 41C-35 page 3 which is generally found appended to scans of the 41C/CV/CX service manual. (For the 41CV and 41CX it would have to ba a flag-only wired module, and no P/N is given, as compared to the flag-wired-memory module for the 41C.)

Diego says that the ET-11967 is a double memory module, hard-addressed, with the flag wiring, but he apparently didn't speciificallly investigate the flag wiring. Perhaps I didn't read closely enough, but I don't recall anything in the service manual suggested to me that it had to be a double mem.
Find all posts by this user
Quote this message in a reply
05-27-2024, 10:56 AM
Post: #5
RE: Service module (SM1C) and peripherial flags
(05-27-2024 10:43 AM)brouhaha Wrote:  
(05-27-2024 08:46 AM)ThomasF Wrote:  Apparently it loads a flag pattern in the C register, and then checks to see if the FI flags are set accordingly.
But I can't understand how the flags are updated, IMHO only specific hardware can drive the FI lines and setting of the flags, this is not possible by just software.

Yes, that test won't work without a "flag-wired" module,

Ah, thanks Eric, that makes much more sense!
So, looking at the memory usage further down in the code, it might be possible figure out the memory specs as well.

This brings me on a new trail - it should be possible to have the Pico emulating the ET-11976 and get the Service module up and running too ... Wink

Cheers,
Thomas

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
05-27-2024, 12:56 PM
Post: #6
RE: Service module (SM1C) and peripherial flags
This is great new info. Is there someone here with that module who can help us out? Would be great to be able to borrow it to make some bus traces

Regards, Meindert
Find all posts by this user
Quote this message in a reply
05-28-2024, 06:38 AM
Post: #7
RE: Service module (SM1C) and peripherial flags
Thanks for the info about the ET-11967 module!

I updated my Tiny41 software in the Pico board I have to shortcut DATA into FI if the Service SM-1C ROM is loaded, and yes, that seems to work!

As can be seen in the log none of the PF flag tests jumps except ?SERV and we end up at 4633 as expected.

Basically I added the following pseudo code (dataFI is active high - if "high" drive FI line low):

Code:
 if( serviceRom )
    dataFI = ~data56; // Invert DATA line since FI is active low
  else
    dataFI = modules.getFI(); // Get any FI-flags from modules
dataFI is then used to drive FI low (if dataFI[n] is active) for each nibble (i.e. each PF flag) during the next bus cycle.

That the test fails further on is another problem (probably when checking memory - have to trace and see what happens there) - but at least this shows that we are probably able to emulate the 11967 module as well ...

Cheers,
Thomas

Part of a trace from a HP-41CV running Service Module (SM-1C) loaded on the Pico41 board:
Code:
 D 2252>0000|00000000000000 *x 460A           04E - C=0      ALL
 D 2253>0000|00000000000000 *x 460B           2DC - PT= 13
 D 2254>0000|00000000000000 *x 460C           3D0 - LC 15 (F)
 D 2255>0000|00000000000000 *x 460D           3D0 - LC 15 (F)
 D 2256>0000|F0000000000000 *x 460E           3D0 - LC 15 (F)
 D 2257>0000|FF000000000000 *x 460F           3D0 - LC 15 (F)
 D 2258>0000|FFF00000000000 *x 4610           09C - PT= 5
 D 2259>0000|FFFF0000000000 *x 4611           3D0 - LC 15 (F)
 D 225A>0000|FFFF0000000000 *x 4612           3D0 - LC 15 (F)
 D 225B>0000|FFFF0000F00000 *x 4613           3D0 - LC 15 (F)
 D 225C>0000|FFFF0000FF0000 *x 4614           01C - PT= 3
 D 225D>0000|FFFF0000FFF000 *x 4615           3AC - ?PBSY
 D 225E>0000|FFFF0000FFF000 *x 4616           0DB - JNC      +1B [4631]
 D 225F>0000|FFFF0000FFF000 *x 4617           32C - ?CRDR
 D 2260>0000|FFFF0000FFF000 *x 4618           0CB - JNC      +19 [4631]
 D 2261>0000|FFFF0000FFF000 *x 4619           22C - ?WNDB
 D 2262>0000|FFFF0000FFF000 *x 461A           0BB - JNC      +17 [4631]
 D 2263>0000|FFFF0000FFF000 *x 461B           02C - ?PF 3
 D 2264>0000|FFFF0000FFF000 *x 461C           0AF - JC       +15 [4631]
 D 2265>0000|FFFF0000FFF000 *x 461D           06C - ?PF 4
 D 2266>0000|FFFF0000FFF000 *x 461E           09F - JC       +13 [4631]
 D 2267>0000|FFFF0000FFF000 *x 461F           0AC - ?EDAV
 D 2268>0000|FFFF0000FFF000 *x 4620           08F - JC       +11 [4631]
 D 2269>0000|FFFF0000FFF000 *x 4621           16C - ?IFCR
 D 226A>0000|FFFF0000FFF000 *x 4622           07B - JNC      +0F [4631]
 D 226B>0000|FFFF0000FFF000 *x 4623           2AC - ?SRQR
 D 226C>0000|FFFF0000FFF000 *x 4624           06B - JNC      +0D [4631]
 D 226D>0000|FFFF0000FFF000 *x 4625           12C - ?FRAV
 D 226E>0000|FFFF0000FFF000 *x 4626           05B - JNC      +0B [4631]
 D 226F>0000|FFFF0000FFF000 *x 4627           26C - ?FRNS
 D 2270>0000|FFFF0000FFF000 *x 4628           04B - JNC      +09 [4631]
 D 2271>0000|FFFF0000FFF000 *x 4629           0EC - ?ORAV
 D 2272>0000|FFFF0000FFF000 *x 462A           03F - JC       +07 [4631]
 D 2273>0000|FFFF0000FFF000 *x 462B           1AC - ?TFAIL
 D 2274>0000|FFFF0000FFF000 *x 462C           02F - JC       +05 [4631]
 D 2275>0000|FFFF0000FFF000 *x 462D           36C - ?ALM
 D 2276>0000|FFFF0000FFF000 *x 462E           01F - JC       +03 [4631]
 D 2277>0000|FFFF0000FFF000 *x 462F           2EC - ?SERV
 D 2278>0000|FFFF0000FFF000 *x 4630           01B - JNC      +03 [4633]

 D 2279>0000|FFFF0000FFF000 *x 4633           05E - C=0      MS
 D 227A>0000|FFFF0000FFF000 *x 4634           3F0 - PRPH SLCT
   227B>0000|0FFF0000FFF000 *x 4635           236 - C=C+1    XS

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
05-28-2024, 07:06 PM (This post was last modified: 05-28-2024 07:07 PM by ThomasF.)
Post: #8
RE: Service module (SM1C) and peripherial flags
(05-27-2024 10:43 AM)brouhaha Wrote:  I brought this up once before here, and people didn't seem to believe me.
...
but I don't recall anything in the service manual suggested to me that it had to be a double mem.

I can only agree - the DATA line must be fed to FI for the test to work (e.g. by connecting DATA and FI pins), and as my test and examine of the source code for the Service ROM shows, there must only by exactly 3 memory modules in the calculator when executing the test - otherwise it will fail.

It is also true that the Sevice Module SM-1C and the "IO PORT TEST" only works in a HP-41C (with 2 memory modules and the ET-11967 module) and can not be executed successfully in a CV or CX.
It must for the CV or CX be executed with another version of the Service Module (which support full memory) and a FI-wired module without any memory.

Cheers,
Thomas

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 2 Guest(s)