Combo AV EX+

Being an arcade collector, I enjoy a variety of hard-to-find games, some JAMMA, some JVS, but all of them not terribly easy to play unless you have a spare cabinet around with a compatible control panel.  Earlier this year, I set out on the task of building my own supergun: a generic term for an adapter that provides the power commonly used by arcade games (generally just +12/+5v, but sometimes -5v is needed) as well as converts the video, audio and control signals used.  The result worked, but my control panel was raw, to say the least (laser cut by a friend on a single sheet of acrylic: I had no means to support it, the buttons had an odd spacing, and the acrylic chosen was slightly too thick for the buttons to clip in properly).  Also, I relied on a chain of adapters.  Power supplies are hard to get right, so I used an ATX power supply to provide +12v and +5v (note that current revisions of ATX remove -5v; to create this voltage, I used an isolating DC-DC converter that outputs 5v, with the positive output connected to ground).  Similarly, I have games that sync at any of the three common refresh rates: while the vast majority use 15kHz, I have a few 31kHz and a few 24kHz.  15kHz is easy to convert, since it's relatively close to NTSC (and there are dedicated ICs for this purpose), but the other refresh rates are a bit more challenging.  As a result, I decided to use a Gonbes GBS-8220 to convert the video signal.  Sure, it may not be perfect, but the quality is quite decent, the board is readily available at low cost, and the result is a nicely upscaled VGA picture.  Ultimately, this resulted in a mess of adapters, and while the resulting project was fun, it was by no means easy to carry with me (the original goal), nor was it convenient to use.

Enter the Combo AV EX+: an all-in-one JAMMA to VGA or HDMI adapter with a host of options.  The standard configuration from TOPS (a Japanese distributor of used games and control boxes) comes with a two player, twelve button configuration using Seimitsu joysticks.  I'm not a die-hard Sanwa fan, so saving a bit of money here seemed okay.  The control panel itself is beautifully constructed: the case is stainless steel, the control panel is professionally cut out of a nicely patterned plastic, the positioning of the buttons and sticks are compact, but spaced enough to remain comfortable.  The controller also features an internal speaker and 3.5mm jack.  Internally, the wiring is nicely constructed.  The buttons use quick connects (so, if you later want to upgrade to Sanwa buttons, it is easily accomplished), and the parts are largely commercially available.  Internally, the VGA is converted using the same GBS-8220.  The HDMI is converted from that, with what appears to be a VGA2HDMI PCB.  There's also an RGB output for video, but using this requires disconnceting the input to the GBS-8220 to switch it over.  Finally, there appears to be an option to also output composite and S-Video; this appears to take advantage of the GBS-8100.  The power supply is a DIN rail style power supply, common to most arcade machines (note that there are some power supplies that are exclusively 12v or 5v; in this case, the three voltages are converted internally).  Finally, there's a custom I/O board that is able to do rapid-fire on any of the 12 buttons.  The delay is selectable, as are the buttons the rapid-fire assigns to, although I have not used this functionality.

Use is simple: plug in the JAMMA connector to the board (although most boards have the JAMMA connector recessed slightly, so using an adapter to handle this for you) is probably the best bet.  Plug in the power video and switch the power on.  Volume is controlled on the back via a knob, although there are two switches on the back related to the A/V output.  A slider switch selects the audio output: HDMI or the internal speaker.  A small rocker switch provides power to the HDMI output.  The two larger black buttons provide coin input for P1/P2, and the smaller black button is wired to the test switch.  24mm start buttons for each player are also provided, just above the 6 buttons for that player.

Now, for the problems.  First, shortly after receiving the unit, I found that the internal speaker eventually stopped functioning entirely.  I traced this down to the volume knob reading a much higher resistance than it should have been.  Normally, the volume knob should read approximately 0-100 ohms; we were almost a factor of 200 off from that (20 kOhm).  Additionally, this is not exactly a standard part: it's a 100 ohm B-scale potentiometer.  Thankfully, the manufacturer was able to provide a replacement through TOPS, and it was fairly simple to replace myself.  A word of caution here: I'd avoid making any changes to the audio while the game is on, and operate both the board and internal speaker levels at a conservative volume: note that every game under the JAMMA standard outputs powered audio for an 8 ohm speaker in the cabinet.  This is a much lower impedance than the high-Z inputs used by headphones and other hi-fi equipment (it's really just a small amplified speaker).  Even the case uses a 10W rated 8 ohm speaker.  Not sure if anything here was to blame, but better safe than sorry.

The second problem was related to the video: sometimes, in an intense game, the video would scramble, I'd lose a few frames, and it'd pick right back up.  This took me a while to figure out was related to the Gonbes GBS-8220.  At first, it looked like the game was losing sync.  After some troubleshooting, though, I figured out the metal frame of the controller is common with earth ground, but the DC common output was isolated from this ground.  However, whenever the post or shroud of the VGA connector would contact the metal frame nearby, the screen would jump, since suddenly the DC offset has changed.  Eventually, I just worked around this issue by keeping the DC common at the same level as the earth ground by using a short jumper wire.  Not the prettiest solution, but I figured it's nicer than the video signal serving the same purpose. (An alternative would have been to insulate everything with tape, but this looked like it might pose its own unique challenges.

Overall, I've been quite impressed with the quality of the controller.  It functions as advertised, is quite solidly built, and the harness I'm using has a built-in kick harness for games that support it.  Combine this with some excellent support, and I'm satisfied with such a high quality product.

More Arcade Repair Tips

So, if you've read some of my other posts, you'll find I repair arcade games. I also don't like paying outrageous prices for simple parts I can change myself (all discrete thru-hole components), or replacing entire boards if one or two parts will do.

Most recently, I've been repairing an Entropy 2000 Ticket Dispenser (continuous), which is a fairly simple clone of Deltronic models. (Maybe "clone" is the wrong word. Entropy did their own mechanical design, and while it may not be built like a tank, it certainly is a workhorse unit. I have nothing against them.) Anyway, the symptom was simple: tickets would not increment. Similar to Deltronic's original design, the circuit involved here is a photointerrupter, hex inverter/buffer, and transistor with the collector wired to the "notch sense" line in the four-pin connector. Pretty simple. (The schematic is readily available online for those of you curious.)

First guess was the transistor. I had some 2N2222A transistors, so I replaced it, and it worked for a while then quit again. I tried replacing it again, and the same symptom resulted. Clearly, this was strange. The Entropy rebuild kit you can buy from distributors comes with 2N4401 transistors in place of the 2N2222A (okay, this is a fine swap), plus a socket and the inverting buffer, a CD40106BE. It also has a TIP122 (readily available power transistor for driving the motor), and NTE294 (a sub for the hard to find A966 originally used).

Since my initial attempts failed, and I had plenty of parts from the rebuild kit, I figured I'd try the shotgun approach and change them out, having a good feeling that the only part that may help would be the hex inverter. Indeed, there was no change... And actually, the symptom got worse. Now it may only read one ticket before quitting. Physically inspecting the photointerrupter (removing the clear plastic guide, checking it, and reinserting the guide) would let it work once again before running into the same problem.

The original photointerrupter is a SY509, a hard-to-find part with difficult to match physical dimensions. Failing to find this, I went looking for subs. On a hunch, I tried the TCST1202 from Vishay (it was the closest match I could find from data sheet measurements), and lo and behold, it's a nearly perfect drop-in replacement. The clear plastic guide is a little loose, but it fits well enough, and electrically, it's a perfect sub!

Hopefully this tip helps someone else out there; I know it cost me a lot of time to find a match.

TV Repair Sites...

As you may know, I do some hobbyist electronics repair.  So far, I've been pretty successful, but the most recent endeavor in fixing a Mitsubishi projection TV with a high-voltage shutdown issue has been... interesting...  In short, I found a company that claimed to be selling a "repair kit" (for way more than it was worth), and I said, eh, okay, if it gets things working, it's worth the cost.  Well, what a mistake that was...

For your entertainment, here's the review I wrote after purchasing (and returning) a kit which didn't come close to matching up to the TV I have.  In fact, $50 for 7 capacitors was... downright amusing.  Oh well.  So, let this be a lesson to everyone.  If you're buying a cap kit, make sure you know what you're getting into.  And, better yet, make sure they actually know what differences between models of TVs are.

First of all, the item I ordered, a "blinking light kit" for a Mitsubishi projection TV was a very expensive "capacitor kit." These aren't uncommon, and I was willing to pay the outrageous price for fewer than ten components that cost far less, assuming they did some work to identify common failures as they claimed. For reference, the components sent from reputable electronics distributors would probably cost on the order of $15 including shipping -- so, they've added some markup... and lots of it.

The order was shipped via First Class Mail, for about what Priority Mail flat rate costs ($7). When the order finally arrived, I was surprised to see the instructions asked me to remove a board which clearly did not exist on this particular model, and replace these nonexistent capacitors.

I decided to return the kit unused (if I'm paying $40 for something that clearly wasn't even researched, I didn't even want to waste the time with their tech support), and accepted the 20% restocking fee. They claim that "once an order ships a restocking fee applies to cover the non recoverable cost of shipping, order processing, parts research, kit build time, and refund processing time." While this may be reasonable, I've already paid for shipping separately (and as they claim, shipping isn't refundable, of course -- I wouldn't expect that). I may even accept that their research is valuable time -- but clearly they didn't research the model advertised (even a quick peek at the service manual would show that the board they describe doesn't exist). In addition, they have an unused kit which still can be resold.

In short, I would not advise purchasing from this company, unless you're desperate and not afraid of disappointment. They did ship the product and process my refund in a timely manner, so I can't fault them for that. Some of their components may be difficult to find through normal channels (but not capacitors, sorry!), so you may have no other choice. If you decide to do business with this company, they will take every last cent from you they can. As a final anecdote, after all their other high costs, the end of their tutorial even has the gall to ask for donations for the author of the tutorial... when in fact, nearly the exact same guide was found for free on other websites.

Automatically Updating Git Repositories

Part of what I do for real life is managing several version control servers, including Gerrit and Gitolite.  Now, this in itself has its own fun problems, but recently, in the midst of my routine auditing, I saw a large number of people using the server on a holiday weekend.  This had me thinking, who works on a holiday?  Even more interesting, the requests appeared to be at regular intervals, which led me to think it was some automated process.  I asked both users what was going on, and they explained they were using Atlassian SourceTree (a rather beautiful Git frontend, I might add).  Apparently, it defaults to updating its repositories every 10 minutes.

Now, in a centralized VCS, you might ping the status of your files and see if you're outdated (and need to update before you commit), but with distributed version control, you're actually pulling down the latest and greatest code all the time (all without changing your working tree).  In a busy repository, this can show when you're working on an outdated file - maybe pretty useful.  But, at the same time, I think there may be a few negative sides that need to be considered.

Code Churn

Yep. If your repository is really so active you need to know where it is at all times, you're going to spend a lot of your time needlessly rebasing your change to keep it at the tip of development.  Now, that's not to say you shouldn't do this sometime, but particularly when I've been writing a feature in an active repository, I write it on an isolated version that I know is working well for what I need, test everything, then when my feature is complete, I can update and test again.  If it's broken now or I have a merge conflict, I have two points I can easily bisect and fix.  By the same token, this is the reason why Git makes it so simple to branch and merge: you don't need to me working alongside everyone else - merging can be a much more coordinated effort, but when developing a feature, it can be done in isolation (for the most part).  If you join the camp of Git Rebasers, they would say this is messy and you should always rebase your change (for a more detailed discussion, Git team workflows: merge or rebase? is a good explanation on the two sides).  Personally, if I'm doing a simple change that doesn't require an independent feature branch, I may write my change, and before submitting to review on Gerrit, I'll rebase once just to make sure I'm in sync with the world and there are no conflicts before other developers spend time reviewing it.  There, now I don't need to worry about a bunch of churn from my side, and I didn't ping the server continuously.

Destructive History

This is something I have to worry about less: we intentionally block all operations via Gerrit and Gitolite permissions that would be destructive to history.  But, there have been a number of documented cases where users have inadvertently reverted months of history through a simple force push.  For a few examples, Git Patterns and Anti-Patterns documents the specific case where Eclipse accidentally wiped out some history.  Ironically, Luca Milanesio (the author of the Git Patterns and Anti-Patterns refsheet) accidentally force-pushed 186 Jenkins plugin repositories on GitHub.  The force-push is the enemy of automatic updates, since your remote would be rewound to the point that the force-push took it, and you'd have no way of knowing the rewind happened (aside from looking at the reflog, but see the note under "Pattern #9" on the patterns/anti-patterns).  In either of these cases, if you happened to fetch manually, at least you'd see that a forced-rewind happened, and you'd have a chance to investigate.  In a scenario where data has been lost, sometimes a developer's repository may be useful in disaster recovery - after all, a Git repository is a Git repository.  That said, you should still have other disaster recovery methods in place, but it's always good to have other options, too.

Conclusions

At the end of the day, is the automatic update feature useful?  I don't think so.  While there are some limited scenarios it could make things better, I also see a whole lot of cases where it can do more harm than good, even though the incremental fetches are rather inexpensive from a server perspective.  Interestingly, I've pulled myself out of several pinches by looking at a Gerrit replication mirror and restoring content from that.  At the same time, deletes are never pushed to the mirror (only new content), and non-fast-forwards are rejected.  As a developer, you should probably not need to anticipate some of these "worst case" scenarios, but the time lost by rebasing your change indefinitely is real, and I would advise against even that unless you need to.  Gerrit has options to resolve conflicts if it can (i.e. trivial rebase), or you may not even need to rebase at all.  The tools like Gerrit and Jenkins are there to make your life easier by worrying about the code compiling and merging so you don't have to - second guessing them by posting rebases all the time can only waste your time (and CI time).

Skype Security Vulnerability Exploited in the Wild

Well, Skype has a fun little security vulnerability, and despite trying to take every action possible to report it to Skype/Microsoft properly, they just don't seem to listen too well. I have seen this vulnerability exploited in the wild, so I really don't feel too bad about disclosing the details.  It's also not like it's anything super-serious like the ability to run malicious code remotely, but it is likely to confuse new users.

The issue is, Skype processes Unicode.  Perhaps a bit too well.  In a file transfer, Skype interprets the Unicode "Right to Left Override" character in a filename.  This can be exploited by an attacker to hide the true extension of a file.  In the specific case I observed, it was a filename like Screenshot1234<RTL>gnp.scr, which the client displayed to users as Screenshot1234rcs.png.  Looks like an image, to the untrained eye.  Of course, when viewing the filename in Mac OS X, the RTL override character is not interpreted and instead replaced with a substitution character ("?").

I really don't expect much from this issue.  Just make sure users are aware of the true extensions of files when being sent a file.  Similar types of issues are the IDN Homograph Attack where attackers utilize similar characters in the Unicode character set along with the IDN system to confuse users about the site they're visiting, and the SSL Certificate Null Character Attack, where a null character is used to obscure the actual domain and confuse users about the real site they're visiting.  Both of these aren't by themselves a huge risk, but by confusing a legitimate (but perhaps uninformed/unaware) user, they can be leveraged for much greater attacks.

Followup: Skype did eventually understand that this wasn't a support request, so maybe they're working on it.  Also, the way the Skype clients function, the "is sending a file" messages work is the client is actually sending the text to the other user with their form of the "/me" command.  So, it's still strange and I don't like it, but who knows what can be done, especially if a remote user can send whatever they want there?

Troubleshooting Dig Dug (Rev B)

So, recently, I acquired a Dig Dug (Rev B) in nearly mint condition, and a Galaga in slightly less-than-mint condition.  Both games worked great, and have been an excellent addition to my little home arcade (with an Ikari III JAMMA cab running Gradius II most of the time, and a Keyboardmania 2ndMIX).  That all changed when I went on vacation: suddenly, the Dig Dug decided it wouldn't work for more than 15 minutes at a time.

I checked the obvious problems.  Checked voltages on the power supply, checked the Atari power brick's filter cap ("Big Blue") using the Bob Parker/BLUE ESR Meter, and checked all the other electrolytic caps.  Finding nothing suspicious, I started looking for things a bit more out of the ordinary.  I even compared voltages before and after the crash on the +12, +5, and +10.6 (unregulated) outputs, and saw no differences.  Even the -29V generated for the EAROM was fine--some levels were a bit high, but not enough for me to be really suspicious.  If I had my scope (it's been on semi-permanent loan to the local hackerspace), I'd happily check to see if there's excessive ripple voltage on any of the DC lines--sadly my DMM isn't a true RMS meter--so putting it in AC mode doesn't remove any DC offset--it just reads bogus values.

I noticed when the game crashed, the output on the monitor went blank.  It wasn't playing blind, even--it was completely dead.  Indeed, using a DMM, I confirmed the !CSYNC line was a solid 5.00V -- so, nothing's syncing anything to the monitor.  Strange.  I tried pulling all three Z80s and seeing a fair amout of oxidation, cleaned the pins, and was able to reproduce the issue, even with the Z80s removed.  Started sniffing around the Y1 crystal -- 18.432MHz.  Indeed, getting CLOSE to this crystal could cause the game to glitch--no sync generated to the monitor.  Turns out this game uses the Namco 07xx custom IC, which is a sync generator.  A CPLD replacement is available, or some new old stock are also available... if it comes to that.  Galaga happens to use the same custom IC, so that could also be used to test.  Still, despite the sync generators getting quite hot, they seem to be a symptom rather than a problem--the sync generator also drives the watchdog reset, which also gets tripped.  I also happened to note that the !RESET signal sits at a place that may be in an exclusion zone for some chips--somewhere between 2-3V (higher when not working--but either way, looks to be okay).  The rest of the clock circuit seems to be a 74S04 hex inverter, the crystal, a 100pF mica capacitor and a 74LS107 dual J-K flip flop being used as a clock divider, as it seems.  The board's 18MHz test point can isolate things down to the 74S04, cap, and crystal, and indeed, that point's DC average voltage does seem to be higher when failed (2.3v vs. 1.07v working).  The presence of the multimeter alone seems to be enough to occasionally disturb the frequency of the crystal oscillator.

So, some things are definitely much easier with an actual scope or true RMS multimeter.  It seems strange that this issue comes about after the game's been on longer, but without pulling a scope in to look at the issue, I may be replacing all three parts in question (although the mica cap probably won't fail--a crystal or 74S04 seems far more likely.  It may still be worth double-checking for AC ripple on the DC voltages, and possibly replacing the "big blue" cap again (or any possibly-affected axial caps on the regulator/amplifier board).

UPDATE 8/2/2013

Ordered a new crystal and inverter, installed it, and so far, everything's been running stable.  Also, an unusual buzzing noise whenever the game was on seems to have gone away, making me believe the problem is indeed resolved.

Making Code Reviews Practical

Let me preface this by saying I'm not a code review expert.  I just happen to have experienced everything from a very formal code review meeting to a very informal peer-review system.  And I like code reviews.  No, I love them.  They really do help produce better code overall, and also help developers familiarize themselves with the code.  Done properly, it will end up saving the company significant amounts of money and developer time by fixing errors before they make it into production.

So, here's what I've seen.  Formal reviews that are checklists and formal meetings are time consuming, but are also very thorough--something that's helpful when you have a detailed set of requirements.  Slightly less formal peer audits can be useful, but there are a few problems I've noticed.  First of all, depending on who reviews the code, different issues tend to be caught.  Theoretically, everyone should be working out of the same guidelines, but different reviewers pick up different things.  That's human nature.  Also, one book on developing code review standards made a very good point: don't sweat the small stuff. Depending on the circumstances, "small stuff" may have different meanings to different people.  For one person, spaces vs. tabs may not be relevant, for others, maybe it's eliminating the requirement for Hungarian notation.  In either case, you need to figure out what works well for you.

Now, here are some of the problems I've seen: the fact that reviews are completed by different people means some people will review a change and approve it with no comments, where others will pick the code to the point where there's nothing left.  Even more amusingly are getting comments that are completely unhelpful or wrong on working code, while other code is being checked in that won't even compile.  This all boils down to the absence of one particularly vital role: the moderator.  The moderator is an independent third party whose job it is to check the comments, ensure they are all applicable, and also ensure all concerns are properly addressed before the review passes.  By placing all the power in a single reviewer, you have destroyed the system of checks and balances that would exist otherwise.  If the reviewer doesn't like your code for some reason, sorry, but not today.

The most effective system I have seen so far was a rather informal system using Atlassian Crucible (yes, I really was pleased with their product), but where reviewers were randomly assigned to the review.  Then, a few of the reviewers (a minimum of two) would look over for defects and suggestions.  Only defects (such as security issues or gross violations of the standards) needed to be corrected, and suggestions for improvement were left up to the discretion of the programmer.  A moderator would observe the comments, decide on which ones were actually necessary to fix, and overall steer the discussion in productive ways.  After reaching the minimum number of reviews, the review would be closed with a simple pass/fail status, and re-review would be required for failed status.  The moderator would then ensure all comments were appropriately addressed in future reviews.

Basically, using this method, reviews were both fast and simple, and didn't waste a large amount of time.  At the same time, the comments out of a review were, on the whole, helpful, and provided a forum for a developer to make their point if they disagreed with some of the comments.  Take this for what you will, but I have found moderated informal pass-arounds to be the most effective reviews.

Two-Factor Auth with pam_google_authenticator

So, this is something pretty spiffy, and a lot of people have set it up already, provided nice walkthroughs, etc.  Since there are many good walkthroughs already (like here or here), I won't go into too much detail.  It's stunningly simple to set up, if you don't mind manually pulling the module's source out of version control and building it yourself.


But, one thing struck me as necessary.  I have users that don't use two-factor auth right now, and they may not want to.  So, how can I make this optional?  Well, PAM makes this pretty painless, although it's not built into the module itself:
auth    [default=ignore success=1]      pam_succeed_if.so quiet user notingroup secure
auth    required        pam_google_authenticator.so

That's it.  Basically, you have a group "secure," that if users are in, they will be required to use two-factor auth.  The way it works is by skipping the following rule if users are not in the "secure" group, but ignoring the result of pamsucceedif if they are.  Otherwise, they aren't.  Get it?  Now, this does mean that users need to be manually added to this group in order to be graced with two-factor authentication, but it's still better than nothing.  If you're curious about a related enhancement, this bug report details some additional thoughts on transitioning to two-factor auth.

Why People Suck at Driving

This shouldn't be a revelation.  But in some senses, it is.  I've noticed a few trends driving here in the winter.

  1. Oh shit, white stuff? (And no, not cocaine, kids.)  Really.  The moment this mysterious "white stuff" appears, people's brains immediately fly out the window, and traffic comes to a grinding halt.  The roads could be perfectly fine, but it doesn't matter.  Top speeds are 45MPH in a 70.
  2. We don't need no stinkin' brakes! Shortly after the snow has been on the ground, people immediately believe the roads will have magically improved.  It could be 1 minute or 1 day after the plows go through, but immediately speeds are back up to and BEYOND the speed limit.  All this occurs when there is still visible ice on the roads, so any attempt to stop at those speeds would be an exercise in futility.  Also, it follows that extreme tailgating becomes a popular passtime in this phase.
  3. Traction? What's that?  It really seems that the people committing offenses #1 and #2 are also the people least suited to be in a snowstorm.  That's right, giant SUVs and rear-wheel drive trucks.  Most trucks haven't even bothered to weight the bed with any type of snow, and it shows as they fishtail their way down the interstate.  Also, I see a surprising number of minivans and SUVs along the side of the road, in rather precarious positions from various spins.  I guess the pickups manage to find a way to pull themselves out.  Hurrah for that, at least.
Maybe it's just the county's elitist "I'm better than you, so get out of my way" attitude that is to blame, but really, I'm sick of it.  If you're going to drive like an idiot, please do it in the driveway of your mansion so you can kill yourself and not me.  Thanks.

Update: Another round of this stuff... and sure enough, wrecks immediately.  Always fun when you think, "hm, I think I'll turn here" and your car decides, "hm, no you won't."  But hey, I managed to control it and not cause any extra problems.  Also, remember kids, the (!) light is the "you're driving awesome" light.

Excess of the Electronics Industry?

So, it's fairly well known that boards that can be made for pennies on the dollar frequently go for ten times that amount, if not more.  To some extent, this is understandable, as a lot of engineering time and labor went into designing and producing the boards.  These costs are forgotten when you evaluate the parts cost per-board.  But, at what point is this excessive?

Just the other day, I was troubleshooting a relatively simple board.  A set of infrared LEDs and photodiodes, resistor network, some diodes and assorted resistors, a transistor, visible LED, and a single IC.  All in all, I would estimate the cost of the board at about $40, assuming you didn't want to mass-produce the PCBs and were silly enough to pay for them one-by-one.  The vendor, however (and they are quite reputable, too), wanted $120 for a replacement part.

The way the board had failed wasn't terribly uncommon--the output was essentially signaling that an IR beam was being broken at all times.  The manufacturer gives a relatively good troubleshooting guide for symptoms and their causes, and sure enough, this lined up with what the device was behaving like.  They also give a good set of schematics for the mainboard, but curiously enough, omit schematics for some of the subassemblies.  The troubleshooting guide stated something along the lines of, "If you see this condition, the sensor board is bad and should be replaced."  This was really fishy to me... no way would the entire board be bad.

I check all the photodiodes, and sure enough, they're all receiving the IR beam properly.  My next thought from tracing this very simplistic two-layer PCB was that either the IC or the transistor was dead.  The transistor seemed to be more related to driving the LED as a visual indicator, so I put my money on the IC.  Of course, without a parts list or schematic, determining what this IC was from the chip markings proved a little difficult.  After misreading one digit, I determined the part was an 8-channel Darlington sink array.  The logic diagram on the datasheet showed exactly what was going on: this was essentially being used as a giant NAND gate (really, more like a negative input logic OR, but who's counting?).  I place my order with an electronics supplier for a handful of this IC and the transistor and wait for them to show up.  Part cost for the IC?  $0.80/ea (for singles).  The transistor was even less.

Once the parts arrive, I go ahead and decide to swap the IC first.  After all, it's socketed, and sure beats desoldering the transistor on the board.  I go plug it into the unit for a quick test, and no LED lit.  Halfway there, so I break the beam, and the LED lights.  Yup.  Bad IC.  So, for $0.80 in parts, I fixed a board that the manufacturer wanted $120 for.  Yeah.  Totally makes sense why they wouldn't want to release schematics or parts list, huh?

In short, when electronics die, it's often not worth troubleshooting.  But if the device is simple and expensive enough, it's quite possible you may be able to beat the game and repair your device for far less than a replacement.  In this case, there was absolutely no actual hard work required: just diagramming the circuit used mentally and swapping a socketed IC.  Just look before you pitch something and start over.