Famicom Network System (aka Famicom Modem) Investigations

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

I figured out 3 of the RF5A18 output signals going to the modem module, controlled by CPU2 register $4127:

$4127.4 -> RF5A18.60 /Phone Off Hook
$4127.5 -> RF5A18.61 /DTMF Output Enable
$4127.6 -> RF5A18.62 /Phone Audio Enable (to TV speakers)

$4127.7 -> RF5A18.63 (Modem P4-19) still unknown, I have always seen this signal high when connecting with PiT and JRA-PAT.

For the RF5A18 input signals from the modem module, I was very surprised not to find a signal that reflected whether there is a dial tone or not. I did find that normalized audio from the phone line gets sent from the modem module into RF5A18 pin 55 when phone is off hook (only), which is also quite unexpected. My 400Hz dialtone being injected gets squashed due to off hook to -1.54V to -3.68V peak-to-peak, and pin 55 gets a signal normalized to 0.15V to 4.87V peak-to-peak. It is slightly phase delayed but not inverted.

tek00012.png

That is the only path that I can find that could detect the dial tone. The signal going to pin 44 is a pretty digital looking signal; it could be that RF5A18 pin 55 is some sort of input capture and not necessarily anything fancy analog. If that is the route to dial tone detection, it must show up in a CPU2 $41xx register or Famicom $40Dx register somewhere. Given that CPU2 sends response command $80 with the status byte when the connection fails, it sure seems that CPU2 ought to be making the determination whether there is a dial tone or not, so I think that makes the $40Dx registers unlikely to be the only destination of the dial tone detection (and thus I didn't even look at those when testing.)

It is hard to snoop register reads for this because I am comparing something triggerable (disconnect), versus when it doesn't disconnect until later for different reason, so I don't know a good way to compare those. Also, since the dialing process takes ~5 seconds from when it takes the phone off hook to when it hangs back up, I don't know where to look and my scope just can't capture that much digital info all at once fine enough to decode it. I probably need to work at that from a different angle. I think it would be useful to know just exactly how it figures out if there is a dial tone or not.
Joe
Posts: 649
Joined: Mon Apr 01, 2013 11:17 pm

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Joe »

Ben Boldt wrote: Sun Apr 04, 2021 5:04 pmFor the RF5A18 input signals from the modem module, I was very surprised not to find a signal that reflected whether there is a dial tone or not.
The MSM6827L has a call-progress tone detector (bit 1 of DR) that can detect tones between 350Hz and 620Hz. I can't say for sure since I haven't looked through that part of the code yet, but I think that's how it detects the dial tone.

I'm curious what that DTMF output enable pin actually does. The MSM6827L can already generate DTMF signals without the help of external circuitry.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

Thanks for the info Joe, I bet that is exactly how it does it.
Joe wrote: Sun Apr 04, 2021 6:49 pm I'm curious what that DTMF output enable pin actually does. The MSM6827L can already generate DTMF signals without the help of external circuitry.
I based that on how the signal goes low exactly at the beginning the first number dialed and goes high exactly when finishing dialing the last number. And it does not do it in pulse mode. That could mean something else, that was just my best guess based on those observations.

I had attempted earlier to trace out the modem module with krzysiobal's awesome KrzysioPCB and I got to a point where I learned how to use the program better and really needed to start over... I was making progress making new parts but I ended up getting distracted with other stuff. I really need to spend some time removing all the SMT parts and measuring the ceramic caps, etc. This PCB is laid out in a way that makes it very difficult to see whether pads connect to traces or not. There are often holes in the PCB that aren't thru-holes but may or may not have a trace connecting across where that hole is... If I remove all those SMT and level everything off, I think it will make things much more clear and traceable. Luckily, the MSM6827L datasheet actually has some very similar example circuits, so that might help figure out how it works. (Though I was still totally clueless looking at that earlier as well.)

Also, my original idea about the signal that enabled the audio through to the TV speakers was incorrect; it ended up to be a different signal.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

Joe: how on earth did you ever make the connection from $4100/4101/4102 writes to the NMI handler? What led you to find that, seems like 2 very disconnected things from each other. I am very impressed.

I added a theory:
19.6608MHz RF5A18 crystal / 2^14 = 1200Hz.
That ends up exactly 1200Hz that way.

And how do you measure the timings you provided, do you have a system running that you are measuring? I want to know your methods how you approached this.
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by lidnariq »

Ben Boldt wrote: Tue Apr 06, 2021 3:46 pm 19.6608MHz RF5A18 crystal / 2^14 = 1200Hz.
Yes. Chosen for compatibility with standard RS232 rates. See https://en.wikipedia.org/wiki/Crystal_o ... requencies
Joe
Posts: 649
Joined: Mon Apr 01, 2013 11:17 pm

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Joe »

Ben Boldt wrote: Tue Apr 06, 2021 3:46 pmJoe: how on earth did you ever make the connection from $4100/4101/4102 writes to the NMI handler?
I found the code for dialing numbers. For pulse dialing in particular, it expects a NMI each time it disconnects or reconnects the line, and it has lookup tables it uses to pick values to write to $4100/4101 after each disconnect or reconnect. These same lookup tables are also used for tone dialing each time it starts or stops a tone. When it disconnects the line, the number it chooses to write to $4100 is about twice as big as when it connects the line, and each pulse is supposed to have the line disconnected for about twice as long as the line is connected. It also has two sets of numbers for pulse dialing, depending on the position of SW1-2, which appeared to correspond with the standard 10 pulses per second and Japan's unusual 20 pulses per second.

In other words, it looked exactly like it was programming a timer interrupt.
Ben Boldt wrote: Tue Apr 06, 2021 3:46 pmAnd how do you measure the timings you provided, do you have a system running that you are measuring?
The lookup tables are also used for tone dialing, so I worked out approximately how many tones it should dial in one second if my assumptions were correct and then compared with your video.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

Joe wrote: Tue Apr 06, 2021 7:30 pm
Ben Boldt wrote: Tue Apr 06, 2021 3:46 pmJoe: how on earth did you ever make the connection from $4100/4101/4102 writes to the NMI handler?
I found the code for dialing numbers. For pulse dialing in particular, it expects a NMI each time it disconnects or reconnects the line, and it has lookup tables it uses to pick values to write to $4100/4101 after each disconnect or reconnect. These same lookup tables are also used for tone dialing each time it starts or stops a tone. When it disconnects the line, the number it chooses to write to $4100 is about twice as big as when it connects the line, and each pulse is supposed to have the line disconnected for about twice as long as the line is connected. It also has two sets of numbers for pulse dialing, depending on the position of SW1-2, which appeared to correspond with the standard 10 pulses per second and Japan's unusual 20 pulses per second.

In other words, it looked exactly like it was programming a timer interrupt.
Cool.
Joe wrote: Tue Apr 06, 2021 7:30 pm
Ben Boldt wrote: Tue Apr 06, 2021 3:46 pmAnd how do you measure the timings you provided, do you have a system running that you are measuring?
The lookup tables are also used for tone dialing, so I worked out approximately how many tones it should dial in one second if my assumptions were correct and then compared with your video.
Wow, that's amazing. Please let me know anything you would like me to test or measure for you now or in the future. I can run arbitrary code on CPU2 as long as it doesn't use any RAM or stack, and I can trigger my scope on 16-bit address match, revealing the data byte read or written. The way the code is written with sub-vectors at $0100, I should also be able to have custom IRQ/NMI handlers but haven't ever attempted that before. I will see if I can confirm what starts and acknowledges the NMI timer this weekend, that will be fun. In addition, it will be interesting to see if there is a pin correlating to NMI. For example, pin 29 has only a 10k pull-up connected. I found that when I drive that pin low, it generates an NMI. I wonder if it drives itself low during NMI, or maybe a different pin, who knows? I will try to find out.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

I finally removed all the SMT parts from the modem module. I measured the capacitors as well. I will eventually use this to start over again with KrzysioPCB.

The SMT parts were actually held with glue but still came off really easy without damaging any of them. Either the heat or the age of the glue must have helped.

Edit:
Pardon the typo I copy/pasted on all 3 filenames...
Attachments
modem mudule smt values.jpg
modem mudule pcb front.jpg
modem mudule pcb back.jpg
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

I made a bit of progress tracing the PCB again, it went much smoother and faster than last time. I ran into a little bit of a snag again though, something I am not doing right in Eagle when I create a new component. I created the component "PC725V" which is an optocoupler with built-in resistor different than anything available built-in with Eagle. I get this error when trying to open the generated .SCH file:

Code: Select all

Error:

line 12074, column 32: attribute 'package' references undefined object 'DIP-6' in tag <device>
Which is pretty stupid because it is complaining about the package outline, which I am not even using that to make a schematic... I would just as soon leave it a blank package outline / don't care. But I did actually draw out that DIP-6 outline and connected everything. I am sure I messed something up with that though. Is anyone familiar with Eagle that could give me a pointer what I did wrong? It makes a good schematic that Eagle can open again if you do this:
  • In KrzysioPCB, press L with the mouse on any pin of IC4.
  • Press delete on the device.
  • Save, generate Eagle SCH file
Here are my files:
https://gofile.io/d/ijHaFT
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

As promised, I looked into the $4100/4101/4012 vs. NMI today. Here is the code I ran on CPU2:

Code: Select all

org $0000
fillvalue $FF

pad $0102
; NMI sub-vector
DW nmi_sub_vector

pad $01F9  ; $01F9 is the correct spot in the stack for the full system.
DW arbitrary_entry
pad $01FC  ; $01FC is the correct spot in the stack for the standalone chip.
DW arbitrary_entry

fillvalue $FF
pad $0200

arbitrary_entry:
    sei  ; disable interrupts

    lda #$78
    sta $4100  ; NMI timer LSB
    lda #$00
    sta $4101  ; NMI timer MSB
    lda #$02
    sta $4102
    
    cli  ; enable interrupts
    
noploop
    nop
    jmp noploop

nmi_sub_vector:
    jmp noploop
I don't get any NMIs this way. I verified the code is executing and does get into the NOP loop, but it never gets to the NMI. The CLI should not be necessary for this (theoretically) but I threw it in for good measure. I had always had that SEI at the very beginning in older stuff I did before.

So there must be more to the puzzle.

Edit:
Also, just for more verification of my setup, I have a 10k pull-up on pin 29. I took a jumper and shorted that pin to GND, and it did trigger the NMI the same as my previous observation. Furthermore, this did cause execution to grab the 16-bit NMI sub-vector from $0102, and it did follow through to "nmi_sub_vector" in my test code and continue the NOP loop from there, all as expected.

Edit 2:
I am remembering now that reading $4103 acknowledges the NMI (probably). CPU2 ROM initializes this at $F3D4:

Code: Select all

                lda   #$00
                sta   CPU2_REG_4102
                ldx   CPU2_REG_4103  ; Throws away X after this.
I did not do any such initialization like this, and my arbitrary code cuts in before it gets to this in the original ROM. I am not sure the behavior of an NMI left asserted, isn't it an edge-detected thing?

I did get an NMI when I grounded that pin afterall... And it was bouncy when I connected the jumper and I got probably ~10 NMIs, not ever having done any RTIs. That seems to prove that NMI is not stuck asserted and not waiting for RTI. Anyway, I better put that same exact initialization and try that next time I can.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

I got the NMI to happen today by copying more of the init code from the original ROM:

Code: Select all

org $0000
fillvalue $FF

pad $0102
; NMI sub-vector
DW nmi_sub_vector

pad $01F9  ; $01F9 is the correct spot for the full system.
DW arbitrary_entry
pad $01FC  ; $01FC is the correct spot in the stack for the standalone chip.
DW arbitrary_entry

fillvalue $FF
pad $0200

arbitrary_entry:
    sei  ; disable interrupts
    
timer_init:
    ; Init like the original ROM:
    lda #$00
    sta $4102
    ldx $4103
    lda #$00
    sta $4106
    sta $4107
    
    ; This middle part WAS necessary to get NMI's.
    lda #$00
    sta $4128
    sta $4137
    lda #$c1
    sta $412F
    
    lda #$2f
    sta $4105
    lda #$fd
    sta $4104
    lda #$03
    sta $4106


    ; Start NMI timer 
timer_reload:
    lda #$78
    ldx #$00
    sta $4100  ; NMI timer LSB
    stx $4101  ; NMI timer MSB
timer_start:
    lda #$02
    sta $4102  ; NMI timer enable flag?
    
noploop:
    nop
    jmp noploop

nmi_sub_vector:
    jmp timer_start
That code DOES generate NMIs each 100 msec. So from there I have a platform to narrow down what was necessary to make the NMI work. I am now writing this post as I continue testing, so you'll see how I am going about this.

If I change the nmi_sub_vector to jump to noploop, I only ever get 1 NMI, even after waiting several minutes. So it does seem that writing 1 to bit 1 of $4102 does cause the timer to reload and start, and does not loop on its own (unless there is a loop bit somewhere that I didn't set.).

I tried skipping the writes to $4100 and $4101 out of curiosity to see what their default values are. I read 52.86 seconds when the nominal of $FFFF would be 54.6125 seconds. That is a 3.2% error which is pretty big for a quartz crystal.

tek00013.png

So I changed the code to literally initialize to $FFFF, and sure enough I get 54.56 seconds (0.096% error). (52.86/54.56) * $FFFF = $F805. With too few significant figures, maybe $F800. Seems randomish to me.

Continuing to narrow down that init code, this still works:

Code: Select all

timer_init:
    ; Init like the original ROM:
    lda #$00
    sta $4102
    ldx $4103
    
    lda #$c1
    sta $412F
    
    ; Start NMI timer 
timer_reload:
    ;lda #$06
    lda #$78
    ldx #$00
    sta $4100  ; NMI timer LSB
    stx $4101  ; NMI timer MSB
timer_start:
    lda #$02
    sta $4102  ; NMI timer enable flag?
    
noploop:
    nop
    jmp noploop

nmi_sub_vector:
    jmp timer_start
So the write to $412F was necessary. I changed the value written to #$C0 and it no longer had NMIs. I then changed the value written to #$01, and I do get NMIs. I also tried value $3F (original value $C1 with all bits other than bit 0 inverted). That also still generated NMIs. So, $412F.0: 1 = enable timer NMI, 0 = disable.

I know that I could still generate pin 29 NMIs with $412F.0 = 0 earlier. So next I test if any of those other write bits can enable/disable pin 29-based NMI. I wrote value #$00 to $412F. This prevented timer NMIs, and still allowed pin 29 NMIs. I then tried value #$FE and that acted the same. So it doesn't seem there is a bit in that register that masks non-maskable-interrupts from pin 29.

Next, I put it back to value #$C1 for $412F and probed around to see if I can find any pin to reflect the timer NMI. I found no such pin, including pin 29, that reflected this.

Next, I thought, what if I skip reading register $4103? Well, I wasn't doing that anyway! I did some other stuff playing with this, only to realize that the built-in ROM is actually handling that before it passes execution to the NMI sub-vector. It is reading it already for me. So I can't test what happens if you don't read it. However, I do see that when I add an additional read of $4103 in my nmi_sub_vector, bit 0 was a 1 when the built-in ROM read it, and bit 0 has become 0 when I read it in my code the 2nd time. That seems to kind of confirm that the bit reflects the NMI flag.

Changing $412F back to $00 to disable the timer, then grounding pin 29, I find that $4103 bit 0 is always 0, so this flag reflects only the timer NMI flag.

I think I covered most of it, not really sure what else to try. I did not try setting $4102.1 = 1 before the timer expired and seeing if it restarted the period or not. I can't think of an easy way to try that. I also did not try changing $4100/$4101 with the timer running for the same reason.


Edit:
I found that $4102.0 is a loop bit. The timer restarts itself automatically with no further writes to $4102.1 when this bit is set.


Edit 2:
Theory: $4100,1,2,3 is the NMI timer, I am betting $4104,5,6,7 is an IRQ timer. It makes total sense that this chip would have 2 hardware timers of different priority. Clues that led me to this:
  • Reading $4107 clears an IRQ flag, just like reading $4103 clears the NMI flag.
  • Value $03 is written to $4106, which would mean start looping timer in $4102.
  • $4105,4 are write-only just like $4101,0, IRQ timer period.
Unfortunately I can't test that the same way because the built-in ROM's IRQ handler does a bunch of stuff requiring RAM before it passes off to the IRQ sub-vector at $0106. If I enable IRQs with CLI, that's a one-way trip into there and crash, for any reason that caused IRQ.


Edit 3:
Yes indeed, that's another timer, IRQ-based instead of NMI, and 1 count = 1 CPU cycle. I updated it in the wiki. I can't test its loop bit, or acknowledging the flag, but I was able to test it having the first IRQ and see it change with the period value, also verified the high byte of the period worked as expected. Cool stuff. :)


Edit 4:
The built-in ROM initializes the IRQ timer period to value $2FFD. $2FFD = 12285. 12285 / 2,457,600 = 0.004998779296875 seconds = 5 msec. It sets it into looping mode (writes #$03 to $4106) and not touches the period or mode again.
Joe
Posts: 649
Joined: Mon Apr 01, 2013 11:17 pm

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Joe »

That all sounds awfully familiar.

Have you found any other functions that can be enabled or disabled by writing $412F? (Could there be a similar register in the RF5C66?)
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

Yes, the RF5C66 has a very similar CPU cycle timer using registers $40A6,7,8, strikingly similar to the FDS as well. It seems to be acknowledged by reading from register $40A2.

$4127 bit 7 gets written with a 1 during CPU2 initialization, and written with a 0 elsewhere. It does not seem to have a way to be written with a 1 again. I don't have any ideas what that could mean.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by Ben Boldt »

I just realized my typo: I was talking about register $412F bit 7 in response to your question, I did not mean $4127. I keep looking at the FDS as a point of reference; there seem to be many similar design elements. Heck, even the name of the FDS chip RP2C33 is similar to RF5C66.

It is such a fun puzzle to poke at this stuff, almost a treasure hunt. One of the most intriguing parts is that there is no particular 'goal'. It is just interesting to see where it goes. Someone like you pops in Joe, and all of a sudden we have CRCs and more timers and NMIs and IRQs -- that is so exciting.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Famicom Network System (aka Famicom Modem) Investigations

Post by unregistered »

Ben Boldt, you created a device to emulate a dial tone? Our AT&T router has support for 2 phone lines... the AT&T router must be on for our house phone to work, but the house phone still has a dial tone. It’s not using the absent phone lines, but it acts just like a phone line. Just some small thoughts to your extreme undertaking. Carry on sir. :)
Post Reply