The PR-8210A has a PCM serial communications interface, the same as a PR-8210 except it is an electrical connection instead of optical. The PR-8210A has a signal (pin 9) to select control input from the IR interface at the front or the electrical one on the back. The communications interface is one way and it uses an additional signal (video squelch) from the LDP as an ACK on search commands.
The PR-8210A also has additional signals for video timing and to control the video output from the LDP. As far as performance, it is no different to a PR-8210. Build quality is less than that of an LD-V1000 since the PR-8210 was aimed at the consumer market.
DATA pin: To capture digital picture number data with logic analyzer, capture speed must be 2 MHz minimum. 1 MHz is the native data rate (1 microsecond is 1 sample) and trying to capture at this rate is almost good enough but not quite. This is verified with real hardware.
|Pin||Name||Direction relative to player||Star Rider connected||Description|
|1||VSYNC'||Out||Yes (star rider schematics call it 'VREF')||Vertical sync signal separated from the COMP SYNC'|
|2||DATA||Out||No||Frame data separated from the video signal (ie picture numbers)|
|3||VIDEO SQ'||Out||Yes||Prohibits video signal from being sent to TV set|
|4||COMP SYNC'||Out||Yes||Sync signal separated from video signal|
|5||STAND BY||Out||Yes||Lights stand by indicator|
|6||SCAN C||In||Yes||Determines direction of track jump and scan. Low means go backward, high means go forward. When disc is paused, or scanning in reverse, SCAN C is low (see page 27 in pr8210-a service manual). MAME source also suggests that high means forward and low means backward.|
|7||SCAN C INT/EXT'||In||Yes (tied with JUMP TRIGGER INT/EXT')||When high, internal SCAN C line is active. When low, external SCAN C line is active. Internal 10k pull-up (R8, page 102) keeps it high when not connected.|
|8||DISPLAY ON/OFF'||In||Yes||Prohibits sending display characters to TV screen|
|9||REMOTE CONTROL INT/EXT'||In||Yes||When high, IR internal line is active. When low external REMOTE CONTROL line is active. Internal 10k pull-up (R6, page 102) keeps it high when not connected.|
|10||REMOTE CONTROL||In||Yes||Serial code signal for various operation commands.|
|11||JUMP TRIGGER INT/EXT'||In||Yes (tied with SCAN C INT/EXT')||When high, internal JUMP TRIGGER line is active. When low, external JUMP TRIGGER line is active. Internal 10k pull-up (R7, page 102) keeps it high when not connected.|
|12||JUMP TRIGGER'||In||Yes||Activates track jump. Number of tracks jumped appears to be 1. Also known as "jump back trigger." MAME suggests that jump takes place on falling edge of this line. Pulse width seems to be 41 uS (see page 27 of PR-8210A service manual). "During still/step and slow motion playback modes, jump-back trigger is [..] applied [..] together with [..] SCAN C (L) [..]. Although the output pattern of this jump-back trigger differ according to the type of playback mode, it is generated during the v blanking under Philips code control." (from page 20 of PR-8210A manual). Also see page 33 and 34 for details on how track jump works; the diagrams on page 34 corresponds to the diagrams on page 33 (this confused me at first). To achieve still frame (pause), reverse track jump occurs after bottom field has finished. To achieve 3x forward play, forward track jump occurs at the end of each field. To achieve 3x reverse play, two reverse track jumps occur at the end of each field. Etc...|
|13-24||GROUND||Star Rider has all of these connected to its own GND.|
Useful questions (with answers!)
- When does the PR-8210A send JUMP TRIGGER pulses in relation to CSYNC/VSYNC when the disc is paused?
Jump trigger gets sent in the middle of line 8 if the disc is paused.
If the PR-8210A is controlling the jump trigger, then ~250 microseconds after vsync goes low.
- When does Star Rider send JUMP TRIGGER pulses in relation to CSYNC/VSYNC when the disc is paused?
In the middle of line 9 if the disc is paused.
- How long does star rider hold JUMP TRIGGER low when it sends it?
Logic analyzer shows this as being 48 microseconds. I had previously thought that it was exactly 96 cycles, or 96 microseconds. See $F9A9-$F9B8. NOTE : PR-8210A holds JUMP TRIGGER low for about 41 uS.
- How long is VSYNC pulse from PR-8210A (page 27 suggests it is 440 uS) and is the line held constantly low or does it follow the serrated pattern from the video signal itself? UPDATE: based on $F880-$F894, it appears that star rider relies heavily on the correct updated FIELD (via the VGG board) being available before the vsync pulse ends. PR-8210A service manual, page 62, says that the vsync trailing edge should be aligned with the position between the 1st and 2nd equalizing pulse of COMP SYNC (pin-6 of Z201).
IMPORTANT: Vsync pulse is unusually long and can last ~690-700uS. Star Rider may rely on this extra long vsync pulse. $F884 enables interrupts and then waits for vsync. It may be possible for the IRQ to still be active when the vsync pulse starts, and unless the pulse lasts this unusually long time, vsync will finish before the IRQ service routine exits, which will cause the PIF rom to reboot at $F887.
- What does the output of the DATA line look like? (optional since star rider doesn't use it)
Don't have an exact answer, but preliminary data suggests that it is the Manchester data from either line 17 or line 18 and that it is in TTL form where high corresponds to 100 IRE and low corresponds to 0 IRE.
- When does star rider change the SCAN C line?
Update, I can see this pretty clearly via emulation now so capturing it on real hardware is optional
- Does star rider ever give up control over SCAN C and JUMP TRIGGER and if so, when does it do it in relation to the other signals?
Yes, Star Rider gives up control over SCAN C and JUMP TRIGGER during disc searches. This is because the PR-8210A uses jump triggers to perform the search. After the search, Star Rider will resume control over JUMP TRIGGER and SCAN C.
- Does PR8210A's CSYNC match LM1881's CSYNC (or do we need to massage the LM1881 CSYNC data before sending it along) ?
Not sure yet but it appears that they do match.
- How does the STAND BY indicator behave when doing things like searches, spinning up the disc, etc?
STAND BY toggles during both disc spin up and disc search.
STAND BY does not appear to be controlled by a clock, but rather by a CPU/MCU. It is not very accurate. Frequency is roughly 2 Hz. It begins some time after Video Squelch' starts.
STAND BY ends a little before Video Squelch' ends.
- Does Video Squelch stay low for the entire search duration? Is it low any other time (such as disc spin up) ?
Video Squelch' does stay low for the entire search duration and also stays low during disc spin-up. It goes low a little after vsync.
It goes high a little after vsync.
Every command starts with the pattern 0, 0, 1, followed by 5 bits (the actual command), followed by 0, 0 at the end.
Commands are sent serially over the REMOTE CONTROL line. The wire is held at 5V when there is no communication and when a command is ready to be sent, the wire is pulled low to GROUND to initiate one PULSE. The wire is supposed to be held low for 260 microseconds (from PR-8210A service manual, page 37).
To determine which bit is being sent, one must observe the space of time between these pulses.
|Space of time between falling edge of two adjacent pulses||Interpretation|
|1.05 milliseconds||0 bit|
|2.11 milliseconds||1 bit|
|More than 3 milliseconds (just a guess)||End of message|
Commands are documented here: http://www.dragons-lair-project.com/tech/command/command8210.asp
My very strong theory about how commands are interpreted (based on observations of Mach 3, Cliff Hanger, Cobra Command, and Star Rider; may differ with what you read elsewhere):
- When a new 10-bit command is sent the first time, it is ignored.
- When it is sent the second time in a row, it is accepted/processed.
- Any subsequent repetition of command is ignored.
Star Rider PIF board
CPU: M6809E at 1 MHz (crystal on board is 4 MHz divided down to 1)
For proper operation, it appears that Star Rider uses all of its PIA port B inputs, that is vsync, field, and STAND BY. In order to generate jump trigger, it also uses the 4MS IRQ input and some parts of the non-IRQ portion of the program will block waiting for the IRQ service routine to run.
ROM: AMD AM2732DC
The program keeps a log of what it does, presumably to help troubleshoot in the event of critical failure. At address 0x100, codes are stored followed by the ASCII sequence "END". At address 0x200, IRQ counts (1-8) are stored, also followed by the ASCII sequence "END". The function to add to this log is at $FBD0.
Some of the codes are:
- 0x84: have not received FIRQ command 2 (hello) see f63d
- 0x89: received FIRQ command 2 (hello) see fca4
- 0x8B: watchdog counter exceeded limit (IRQ starvation)
- 0x8D: NMI called (video squelch)
- 0x8E: REJECT command has succeeded, disc is stopped (not an error) 0xf634
- 0x90: sanity check failed
- 0x91: sanity check failed inside IRQ
- 0x93: $F823 (sync irq counter to field) started
- 0x94: vsync never detected (f974)
- 0x95: stand by was raised when it should not have been (f993)
- 0x96: SWI2 occurred
- 0x97: SWI3 occurred
At memory location 0x300, there is what appears to be an array of commands that are executed by the MainLoop. On startup, this array is populated with the following values from 0xF032: D2 (R), E9 (i), E3 (c), E8 (h), A0 (' '), D7 (W), E9 (i), F4 (t), F4 (t), B, 30, 1A, 17, 1A, 14.
Bytes with the high bit set are an apparent Easter Egg ("Rich Witt" if you clear the high bit and then do an ASCII lookup). Maybe this guy wrote the ROM? :) I tried googling him and nothing jumped out at me. I'd love to talk to him and tell him that someone found his little message. Any value with a high bit set (ie Easter Egg message) is ignored.
Commands with high-bit clear are fair game and seem to refer to a table of callbacks stored at $F042.
Most of the lower commands match up to the FIRQ commands quite closely.
|0||Sets default state to have the disc paused. (this gets called an overabundance of times and seems quite redundant)|
|1||see FIRQ command|
|2||Do SWI (software interrupt)|
|3||DISC FRAME SEARCH. This searches to the 16-bit word pointed to by $12-$13. This is equivalent to the FIRQ command 0x03. When invoked via FIRQ, the frame word is passed in. When invoked via the command array at 0x300, the frame word must follow the 0x03 (support for this can be seen at $f6f6-$f6fa). I have not seen anywhere in the code to suggest this latter case is ever used (but I may be proved wrong).|
|4||same as 2|
|5 - 0x13||see FIRQ command|
|0x14||Issues play command, sets playback direction policy to 'forward', enable left/right audio, enable PIA A's interrupt so that we can now start receiving FIRQ commands, and acknowledges (via CA2 handshake) previously received FIRQ cmd 2 ("HELLO") if it was received and caused a soft reboot.|
|0x15||set policy to forward direction|
|0x16||Raises remote control line|
|0x17||Lowers remote control line|
|0x19||set policy to reverse direction|
|0x1A||Set jump trigger count from the value stored at memory location 0x0B.|
|0x1B||same as 0|
|0x1C||sync irq counter to vsync and field|
|0x30-0x39||Sets jump trigger count based on the lower nibble of the value stored at $14, which I strongly believe will be the same as the value of this command (see $F2CB). So a 0x30 will probably set the jump trigger count to 0. The jump trigger count will be stored at memory location 0x0B.|
Upon power-up, the PIF ROM program goes through the following steps:
- RAM test ($F091)
- ROM checksum test ($F121)
- Sends REJECT ($F142)
- Sends PLAY (waits for disc spin-up) and STEP FORWARD command ($F145). Vsync ($F82E), and STAND BY ($F5CD) lines used to determine success (see note 1 below).
- Syncs up its IRQ counter with vsync and the end of the bottom field ($F827).
- IRQ test ($F148). If incoming "4MS" line is timed correctly, IRQ test passes ($F957). If timing is off, IRQ test fails ($F953). If incoming "4MS" line is not present at all, IRQ test will block indefinitely ($F93F).
- Fill upper stack ($400-$5FF) with 0x3F ($f159)
- Setup PIA A port ($f170-$f180)
- Send another PLAY/STEP laserdisc command ($f183)
- Sync up irq counter with vsync/bottom-field again ($f188).
If any of these tests fail, it counts as a fatal, non-recoverable error and an error code is output ($F3DD) via the PR8210A's Left/Right audio LEDs on the front of the player (internally the left and right audio is toggled on/off to show error state).
Once these tests pass, the program goes into its main loop ($F18B) which continuously checks the Command Array (at $300) for new commands and processes them if they are available. MainLoop does its work when IRQ counter is 1 (start of new frame) because cpu is available for non-critical tasks ($F1BC). When IRQ counter hits 6, FIRQ is disabled because we are entering the time-critical section ($F1B4). MainLoop maintains a watchdog counter ($F19C and $F1CC) which causes a system reboot if it ever reaches 0xFFFF. It gets reset by having the IRQ counter change ($F1CC-$F1E4) which is caused by regular 4MS activity ($FD04).
If vsync check fails at $F82E, the program jumps to a pre-RESET address which stops the disc from playing, sets some defaults, and then flows into the RESET entry point, essentially causing a "reboot". The log information stored at 0x100 and 0x200 will be wiped clean and no diagnostic information will ever be sent via the PR8210A's audio LEDs.
The IRQ service routine is primarily responsible for sending time-critical track jump triggers to the PR-8210A in order to support still-frame, normal, or multi-speed playback in either forward or reverse direction.
IRQ service routine is also responsible for updating state related to the unknown FIRQ 04 command.
If memory location $16 is 0xFF, the IRQ instead will increment a counter as part of the IRQ self-test ($FCE3).
The IRQ keeps a counter that can be from 1 to 8 which is used to indicate when it is getting close to the end of the bottom field of a frame (jump triggers must be sent either right before vblank period or inside the vblank period at a time critical spot, I don't yet know what the exact timing is). 1 means that a new frame has just started and all of the non-critical work of the ROM takes place mostly at this time. 8 means that we are at the time critical part and need to perform jump trigger (if we are going to perform one at all). The IRQ counter is incremented each time the IRQ fires (see 4MS input section below).
4 MS input
The board relies on an input which is labeled 4MS on the schematic. The rising edge of this signal brings IRQ' line low (ie enables it). This originates from the VGG and is shown on VGG page 3/5 of the schematics. It is called VA11 on this page and appears to be bit 5 (where 0 is the first bit) of an 8-bit vertical line counter, meaning it is off for 32 lines, then on for 32 lines, then off, etc. If each line is 63.5 microseconds, this means that this line will complete one off/on cycle every 63.5*64 (4064) microseconds (4.064 milliseconds), hence the 4MS label.
Unverified guess: This may mean that the 4MS will experience a rising edge transition on lines 32, 96, 160, and 224 (262.5 is the end of the field so the counter will presumably reset at that point). This is unverified because I have not studied the counter schematic enough to know what triggers it to reset back to 0 or even what triggers it to increment. There are a lot of unknowns here but this is probably a decent guess for now.
There are 20 theoretical commands that can come from the Video Graphics Generator board. They come by lowering CA1 ("HAND1" on schematics) which triggers FIRQ' ($FC1B). They start at 0 and go to 0x13 ($FC2B). If command is specified which is higher, it will by interpreted as a 0 ($FC2F). Commands are either 1 or 3 bytes long and do not get processed until the final byte is received ($FC37).
After a command has been completed (including a search being completed), and if command 2 has already been received (see command 2 description), CA2 ("HAND2" on schematics) will be lowered and raised quickly (as fast as the CPU can possibly do it) See $FC51-$FC58. Command 2 will itself be acknowledged by command 0x14, which always gets executed on reset (thus it will be acknowledged in a delayed manner).
Command lengths are stored in lookup table at $FC07-$FC1A. Command callback addresses are stored in lookup table at $FC6F-$FC95.
|0 (or anything greater than 0x13)||Illegal command. This puts the program into a default error state. Upon receiving a 0 command, the game will lock itself into an endless loop sending AUDIO left/right toggle commands over and over again. If vsync is not present during this, the error reporting will "fail" and force a reboot (thus going through the REJECT cycle again). The error reporting can be considered successful if the audio L/R toggle commands keep coming indefinitely.|
|1||Send play command to PR-8210A|
|2||Main CPU Hello command. This basically notifies the PIF board that the main CPU is alive and ready to start sending commands. Upon receiving this command, the PIF board will do a partial reboot (it won't redo the self-tests), eventually acknowledge the command (by automatically calling command 0x14) and will start to ACK all subsequent FIRQ commands via CA2 (as described above). Before receiving this command, the PIF board will process FIRQ commands but will not acknowledge them.|
|3 and 0x13||This is "search to frame number" command (see $FCAE). The frame number is stored in the 2nd and 3rd byte of this command, and it is in regular unsigned binary format (the code converts it to decimal at the $f6cb loop). For example, if I wanted to search to frame 1234, I'd pass in the command "0x03 0x04 0xD2". It is unclear what the difference between 3 and 0x13 command is, but my guess at the moment is that there is no difference.|
|4||This is a 3 byte command (see $FCC2). It is used to change playback direction by raising or lowering the SCAN C line. If the second word is negative (ie 0x8000 or greater), SCAN C will be lowered, otherwise it will be raised. This word is also used to set up some kind of slow timer, but I have not yet been able to step through the code to see what the purpose is.|
|5||This command is a NOP.|
|6||Enable left and right audio|
|7||Disable left and right audio|
|8||Still step forward|
|9||Still step reverse|
|0xB||Go External. Sets policy so that SCAN C, JMP TRIG, and REMOTE CONTROL lines will be in external mode so that they are controlled by the PIA (instead of being controlled via the PR8210A's internal signals). Also disables audio, and plays the disc, and sets policy to have the disc paused.|
|0xC||This initiates a PIA I/O test between the VGG board and the PIF board. It loops 8 times. Each loop iteration is as follows: PIF board brings CA2 low then high again, then waits (indefinitely) for IRQA' to become active (low). It then reads the peripheral data register and compares it with an expected byte value. If incoming byte value matches the expected byte value, the test moves to the next iteration until 8 iterations have been completed at which point the test exits. If the comparison fails, the test exits early. The byte values are 1, 2, 4, 8, 0x10, 0x20, 0x40, and 0x80 and they correspond to the loop iteration count. For example, the first loop will look for a byte value of 1, the second loop will look for a byte value of 2, etc. See $F349-$F370 in ROM.|
|0xD||play forward 0 jump triggers (1X); skip 1 track forward (see $1BA3 in the main CPU ROM program)|
|0xE||play forward 1 jump trigger (2X); skip 2 tracks forward|
|0xF||play forward 2 jump triggers (3X); skip 3 tracks forward|
|0x10||play forward 3 jump triggers (4X); skip 4 tracks forward|
|0x11||play reverse 2 jump triggers (1X); skip 1 track backward (see $1BC1 in the main CPU ROM program)|
|0x12||play reverse 3 jump triggers (2X); skip 2 tracks backward|
The NMI is hooked up to the PR-8210A's video squelch pin. The NMI service routine is very short and only does some quick sanity checks. If the sanity checks fail, it reboots. It is my opinion that the ROM would work properly whether or not NMI is connected (it is nice to have some clues about what the game considers proper state, however).
Sanity checks: If the last callback called was GoInternal (0xA), or Search (0x3 or 0x13), then Video Squelch is expected to trigger NMI. Otherwise, if we just rebooted and are setup to do an IRQ test, this is also acceptable criteria for Video Squelch to be called. Otherwise, the ROM reboots with a fatal error.
Stand By Line
The ROM uses the Stand By line to determine when disc has finished spinning up or a seek has finished. It appears that the Stand By line is supposed to blink at rate of about 2 blinks per second. This is verified on a real PR-8210 by Warren filming the LED on the front of his player with a camera. For safety, toggling STAND BY every 112.5 ms should act well with the way the ROM is written.
VIDEO SQUELCH' will trigger the NMI which will execute quickly, and from that point on, the STAND BY line is used to determine when a seek has finished.
The function that waits for STAND BY to stop blinking is at $FA75. It basically waits for STAND BY to go low (by checking every 150 ms for 3 times) and gives an error if it doesn't go low. Then it waits a little longer for STAND BY to stay low (stop blinking) by checking every 50 ms for 10 times. If STAND BY keeps blinking, it will loop at $FA98 indefinitely. Notice that it doesn't seem to care whether STAND BY never goes high.
Now almost completely disassembled. Only the FIRQ command 04 remains a mystery:
PIF board schematic (good quality)
ROM program memory map
|0xE000-0xFFFF||ROM (U3, only 4k so memory region repeats every 0-0xFFF)|
|0xA000-0xCFFF||not connected to anything|
|0x8000-0x9FFF||PIA control (U1), only lower 2 bits in address matter (A0 and A1)|
|0x8000||access PIA peripheral register A or data direction register A depending on control register|
|0x8001||PIA control register A|
|0x8002||same as 0x8000 except for port B (PR-8210A)|
|0x8003||same as 0x8001 except for port B (PR-8210A)|
|0x6000-0x7FFF||connected to IC that is not installed, so I/O in this address space will have no effect|
|0x4000-0x5FFF||"ENABLE'" Writing (or reading) anywhere in this memory region will raise ("enable") the CPU's IRQ' line (so that the ISR can be exited). It most likely is used right before exiting the ISR.|
|0x2000-0x3FFF||"CONTROL" Masks/unmasks J2-13 ("4MS") from being able to lower IRQ' and thus cause an interrupt. Write any value where bit 0 is 0 in this range, and incoming "4MS" low->high transition will set IRQ' to 1 (disabled) Write any value where bit 0 is 1 in this range, and incoming "4MS" low->high transition will set IRQ' to 0 (enabled)|
|0x0000-0x1FFF||RAM (U2, only 2k so memory region repeats every 0-0x7FF)|
Relationship of vsync and field
Star Rider's VGG board derives the field (odd/even) from the composite sync from the PR-8210A (it ignores vsync entirely). However, the PIF board program does use the PR-8210A's vsync output, and it clearly expects the field input (from the VGG) to be updated before the PR-8210A's vsync pulse ends. This is very important as far as accurate emulation is concerned because it means that that the vsync pulse duration matters and is used to sync up the timer of the PIF board with the video signal. See $F880-$F89D.
When capturing I/O from the PIF board to the laserdisc player, one may get confused about the way that the laserdisc player's internal jump triggers interact with the PIF board's external jump triggers.
The process is as follows:
- PIF board allows the player to send its own internal jump triggers while it is sending a search command. If the laserdisc player had previously received a play command (common), this will briefly have the effect of letting the disc player forward a few frames while the commands are transmitted. When the player realizes that it is receiving a search command, it will automatically pause the disc.
- The search command will be completed and the disc will search to the desired frame and then pause, using internal jump triggers to maintain the pause.
- The PIF board will send the play command three times. It will transition into providing its own external jump triggers to maintain the paused state. The paused frame does not change ('wobble') during this time.
To compensate for Dexter's short vsync pulse compared to a real PR-8210A, one must modify the PIF ROM (or else the game will not run reliably).
The mod is:
Address 0x970 and 0x971 from 0x00 0xAA to 0x3 0xFF (this increases the 'wait 4 vsync' timeout from 20 ms to a lot longer, to give the game time to see Dexter's vsync if it misses it on its first attempt). Address 0x5 from 0xF2 to 0x4A (updates CRC value so that the PIF CRC check still passes)