When Geeks Watch TV

I live about 10 miles outside of Boston, and probably about 5 miles from all the towers that the Boston stations use.

I rarely watch TV, so I opted to not get cable TV. (To the fury of Comcast, FiOS, and RCN, who each send me several advertisements every week.) However, I do want to watch local TV every once in a blue moon. Not having time to go to the store the first time I wanted to watch TV, I just strung a length of random wire behind the TV, connecting it to the antenna input. It worked passably at best. The signals were fairly weak and would occasionally drop frames or lose synchronization and drop out entirely for a bit.

I eventually hooked a higher-gain handheld ham radio antenna, and found that it works great. However, the setup was even more outrageously improvised: the antenna was a male BNC and I had the existing wire ‘antenna’ twisted around the center pin. This was a really unstable connection, so I used some electrical tape. This was really just a jury-rigged test. But it worked phenomenally well: the weak signals that dropped out are now DFQ. (Okay, “DFQ” isn’t meant to describe HDTV, but I can’t bring myself down to the level of describing my TV as having “full bars” now, and I don’t have a signal meter to be able to give an actual signal strength.)

I refused to buy a real HDTV antenna, partially because they’re $75+, partially because they’re huge, and largely because they’re typically meant for people who live further away and tend to feature preamps which can’t possibly do me any good. So my homebrew setup works great. It is, however, a touch, umm, improvisational.

Radio Shack does not sell female BNC connectors. Seriously. I found five separate types of uncrimped male BNCs, but not a single female. So that set me up for trouble right away. I eventually found a bulkhead-style connector that was female on both sides, and realized I could use that. I didn’t find any good stand, so I improvised a bit:

The opening in the top is just wide enough for the connector to stick through, but the white plastic connector doesn’t. Sadly, my inability to find a crimp-on female BNC connector means that the coax you see is just sitting with its conductor in the connector, not attached in any way. It’s secure enough that I don’t think it’ll pop out, though.

I also didn’t have any proper crimping equipment, so for the F connector into my TV, I had to try to crimp it with pliers, which didn’t work so well:

(An astute observer may not that it’s not even on right. It won’t screw in.) Obviously, if this were some sort of transmitting apparatus, the build quality would have to be much higher. But for receiving multi-kilowatt TV transmitters five miles away, I can get away with a lot.

When it’s all said and done, here’s how it looks:

From the couch, you can’t see it.

Of course, what really matters isn’t how ridiculously amateur it looks, but how it performs. And in that regard, well, it’s perfect. And since it’s over-the-air HDTV, I get flawless, uncompressed 1080p.

Science is Neat

I can’t even begin to explain–or even understand for myself–how I got to be reading up on these things, but here are some things I’ve read about recently that I think are fascinating:

  • MagLev Trains, which, instead of having wheels riding on metal rails, levitate on electromagnets. MagLev trains have reached speeds exceeding 300mph.
  • The biggest obstacle with train speed now is air drag. And when air is harshing your mellow, what else is there to do but move into a vacuum? Vactrains, which don’t actually exist in production yet, are trains running in vacuums — tunnels “evacuated” of air — eliminating air drag and are predicted to be able to move around 5,000 mph.
  • MagLev trains depend on superconducting magnets. I had assumed that superconductors were materials that were excellent conductors, which is partially correct. In actuality, superconductors have zero resistance. (Not “really small” resistance, but exactly zero resistance.) Seemingly like a lot of things that turn everything I thought I knew about science on its head, superconductors only exist when cooled to absurdly low temperatures approaching absolute zero, but this isn’t as big of a hurdle as one might assume, and they’re apparently common in scientific settings. Since they have no resistance, it’s possible to “close the loop” and have them just retain their strong magnetic charge.
  • Superfluids are the liquid equivalent of superconductors, having absolutely no viscosity. The details are way, way over my head, but superfluids can do things like climb the walls of their containers and leak out. Here’s a more approachable introduction.
  • Biochar is charcoal mixed into soil. It’s popular now because it’s a good means of ‘sequestering’ carbon rather than releasing it into the atmosphere. But, incidentally, it’s excellent for soil. It comprises one of the major components found in terra preta, extremely fertile soil found in the Amazon basin.
  • Continuing on the super- line of thinking, there are superhydrophobes, substances which are exceptionally good at causing water (and other substances) to bead off. A common example is the Lotus effect, named after the Lotus plant. Water won’t stick to Lotus leaves, but, more interestingly, nothing really does: dirt and such are suspended on the surface. When water hits the leaves, the water droplets pick up the other contaminants, leaving the plant uncannily clean. There are countless obvious uses of superhydophobicity in real life, such as clothing. (Car wax?) Sto Corporation sells Lotusan paint, which claims to biomimic the Lotus plant.
  • Aerogel is interesting, too. The nickname “solid smoke” is somewhat fitting its construction, though it’s not literally smoke. They’re the least-dense solid known, and are exceptionally good thermal and conductive insulators.

Wish: An HDR Camera

I’m a big fan of HDR. These days, it’s done by taking a bracketed set of photos and then using software like Photomatix to combine them.

I’d like to think that some day I’m going to tell people about this process, and it’s going to sound just as absurd as describing how, once upon a time, photographers took their pictures on light-sensitive plastic film, washed it through a blend of horrible chemicals, and then projected it onto light-sensitive paper to expose an image… Which then went through more horrible chemicals.

If you view that image as the very small image I’ve posted, it looks great. The HDR really just makes it look more like it did in person. The camera just can’t capture such a wide gamut of brightness and colors.

But if you click on the image and view it at any reasonable size, you’ll realize that the image is worthless. The leaves are cloned all over the place. This is my biggest problem with HDR (well, that and the fact that it typically produces unrealistic-looking photos): in stacking the images and picking the ‘best’ parts of each, they rarely line up right. The software can correct for shifts — I moved the camera slightly from one shot to the next, and it’s easy enough for it to align them. But what it can’t possibly do is realize that the leaves and waves are in different positions in each shot and correct for that.

Last time I tried my hand at HDR, all of the shots were utterly useless because of similar problems, though it had more to do with me not holding the camera. So this time I brought a tripod. But it turns out that, if there’s any wind at all, you just shouldn’t bother.

I eagerly await the day when camera sensors have a couple extra stops of dynamic range on either end, so that it only takes a single exposure for shots like these.

Dead Rising 2: A Mini-Review

I loved Dead Rising. Like, really loved it. So when Dead Rising 2 came out, and I saw that you could combine weapons, I decided to replace my broken Xbox with a new one just to play it.

Having had a couple days to play it, I feel compelled to review it: I hate it.

There’s lots and lots to love about it. But people play video games to have fun, not to perform laborious tasks and juggle conflicting priorities. That’s real life, and part of the reason people play video games is to get away from it for a while.

In the game, my daughter’s been bitten by a zombie, so she needs to be given Zombrex every 24 hours or she’ll turn into a zombie. (It sounds terrible, but since it’s a video game, I’ll add that just letting her die is apparently not an option.) But you can’t just walk to the convenience store and get Zombrex. It’s extremely hard to find and is usually given to you for completing a really tough mission that you’d just as soon have not done. You can only give her her daily dose between 7am and 8am, which means that if you find some and get back at 6am, you might as well put down the controller and go make yourself a sandwich (IRL), because you don’t have enough time to do anything meaningful before 7am, and God help you if you’re not back by 8.

But finding Zombrex is hard. It’s especially hard when you have other time-sensitive missions, and a crazy lady constantly texting you missions. Your quest for Zombrex means that you can’t complete a mission, but whoops, that mission was required and now you’ve lost. So you try again and focus on the mission, but whoops, now you missed giving the Zombrex and lost, too.

Right now some evil villain is looting the city, specifically the casino vaults. Why it’s my job to stop him, I’m not quite sure. I want to slay the zombies, not stop looters. The casinos, for some reason, are always packed with zombies, which makes merely walking through one a chore. But now, on top of that, I’m being shot at by an army of mercenaries hired by the evil looting villain. I eventually clobbered one of the mercenaries to death with my crowbar — no easy task when I’m also being mauled by zombies and being shot at by four other mercenaries who suddenly got grenades too. I died at least a half-dozen times first.

Once he was dead, I got his gun. But it requires manual aiming to be any good, and standing still in a swarm of zombies is pretty hard, because they’ll start to attack you too. Or, right as you’ve got your shot lined up, one of the other mercenaries will shoot you, and you’ll have to start aiming all over. Killing a mercenary requires most of the 30 rounds in the gun, which means that if you miss more than a couple shots — perhaps because you’re being shot at, or perhaps because a zombie is gnawing on your neck — you’ll have to drop the gun and somehow bludgeon him with an axe or something, which is no easy task when he and his compatriots have automatic weapons.

I finally defeated my second set of mercenaries, concluding that the game was really just not fun with crap like this. And then, an “URGENT” text message came in: there were more! This time, there’s probably more like a dozen. I’ve tried this one over and over. There are so many zombies that my health is usually seriously depleted by the time I get there. So I pack a bunch of juice and whiskey and cake (all of which are used to restore health) in place of weapons, which helps for a while, but then I don’t have enough weapons. (Oh, and speaking of health, the beer, wine, and whiskey restore health, but if you have too much, you begin vomiting uncontrollably. But all that you’ll find in the casinos is alcohol, which means that if you try to restore too much health at once, you’ll be in the middle of fighting off another mercenary when you suddenly bend over and vomit, dropping your weapon in the process.)

So Rockstar, I have no idea how you’ve done it, but you’ve managed to make a game where you get to combine weapons — like a boat paddle and chainsaws — and kill zombies with them into something tedious and irritating. I’ve stopped playing and am going to go pack up my summer clothes and move my air conditioner into storage, because that seriously sounds like more fun right now.

Productivity

This is reassuring: a good programmer might write about 10 lines of code a day in the long run. I often recognize this in my own work without believing it’s normal. Before I started doing this professionally, and before I learned that you’re supposed to think before you start writing code, I’d have guessed 500-1000 lines. Part of it’s just that good code shouldn’t really take ten thousand lines. But the other part is that programming is really much more about thinking and just slightly about actually producing code. I’ve known for a long time that “lines of code” is a horrible inaccurate measure of productivity, and yet I can’t stop counting subconsciously.

I think it’s probably normal for programmers to have days when they spend the entire day tracking down an obscure bug. You can’t reproduce it, but then after another 30 minutes of going through exception logs you figure out that it only happens in some oddball case, and finally you’re able to make it fail, though you still don’t have the first clue why. You start looking through it more closely, and start debugging in earnest. Finally, after a couple hours, you find the line of code where the weirdness is happening, though you’re still baffled about why it’s failing the way it is. And then it finally hits you what’s happening, and it’s something really trivial and kind of silly. You chuckle, make some extremely trivial change to one line of code, check it in, and then it’s 5:30 and you have a train to catch.

I still try to measure my productivity in terms of lines of code. All day and I made a minor change to one line? What a waste! But what’s hard for me to get used to is that everyone else just sees that I spent all day working hard on a difficult problem before emerging victorious. And yet my total time spent writing code was about one minute, and my total output was a trivial change to one line.

Of course we have days when we add a lot more. I added about 100 lines today, but that’s because I added some new classes and added several features that took long and floury code. But, in the game where productivity is measured by lines of code, it makes up for the days when I’ll work even harder and end up netting one line of code. Or “worse,” the days when I delete substantially more code than I add.

Building a Macintosh

At work, I came to be a Mac fan. It’s based on BSD, but adds a much more polished GUI. It’s got a very user-friendly interface, and yet it’s trivial for me to pull up the command line and do “real” things there. So when I decided to build a new desktop, I decided I wanted to build something that would run OS X. Unfortunately, Apple’s hardware is ludicrously expensive, and I was on a budget. The good news is that you can build your own!

It used to be that you had to download a “cracked” version of OS X, which had a bunch of patches applied to make it run on non-Apple hardware. Now, though, the tweaks occur elsewhere — some minor changes to the bootloader, and a couple kernel modules to do the rest. The install process wasn’t too convoluted, and the result was well worth it:

It’s not actually a Xeon, but that’s okay.

Here’s what I used for hardware. I tried to stick to things that were fairly close to the hardware Apple uses, to ensure compatibility:

  • Motherboard: Gigabyte EX58-UD5. NewEgg hasn’t carried it in a long time. I got mine somewhere else. This is one of the few components that you have to be careful about, verifying them with hardware compatibility lists.
  • CPU: Intel i7-930, a quad-core 2.8 GHz processor with plenty of cache.
  • CPU cooler: I’m used to my laptop running hot, so I went overboard and bought a huge Zalman cooler.
  • Graphics: I went for an EVGA-branded GeForce 9800GT, because it’s easy to get working. This and the motherboard are the two main components to watch for OS X compatibility. A fairly simple “enabler” script brought me from crappy VESA display to dual displays at 1920×1080, with 3D acceleration. I was going to skimp on the video card, but Kyle convinced me that I’d regret it. Within a couple weeks of building the system, Steam launched a Macintosh client, so I was in business playing TF2. The card runs great.
  • RAM: 6x 2GB DIMMs. I went for these OCZ sticks. The RAM ended up costing me more than any other component, but I’ve spent pretty much my entire life wishing I had more RAM. It’s really great to have more than enough. I probably would have been okay with 6GB, but in my experience, 4GB is inadequate, and I wanted room to grow.
  • Hard drive: I should have bought an SSD, in hindsight. But I was trying to keep the cost down, and I was used to having inadequate disk space, so I sprung for a 2TB SATA disk. At 5400rpm, it’s a slow performer, but I don’t do anything too disk-intensive. Some day I may pick up an SSD for the OS, applications, and the portion of my home directory that isn’t 75GB of photographs or 10GB of music or 250GB of backups.
  • Bluetooth adapter: this little AZiO adapter fits in one of the myriad USB slots, protruding only a minuscule amount, powering my Bluetooth mouse. I was concerned about Mac support, and the reviews are full of people complaining that it doesn’t work on Windows 7. But it’s plug-and-play on the Mac.
  • Case: I got a nice big, roomy Zalman case. It’s kind of a ludicrous amount of money for a case, but I think it’s well worth it to have a really quality case. Little details, like slide-in rails for the power supply — or the fact that the power supply is the bottom and not the top — plus tons of hot-swap bays on the front — make it a pleasure to work with. The USB ports on the top front are a nice touch, too.

I have an actually-legally-purchased copy of OS X. I used the digital_dreamer install scripts, which required having an already-functioning Mac. Luckily I had a Mac laptop. I connected the hard drive via USB (about the thousandth time that I realized my USB-to-IDE/SATA adapter was a great purchase) and formatted it properly, did a retail install of OS X to the drive, and then ran a script to patch in the requisite drivers. Then I plunked the drive into my new machine, booted it up, downloaded the latest OS updates, and ran a couple things like the “enabler” scripts for my Ethernet cards and the graphics. Now it runs superbly well; the only thing I lack is a sleep mode. I think that’s easy to fix, actually, but I haven’t bothered yet.

For fun, a few photos of the build.

This kind of amused me. The processor came in a huge package. In the course of removing the heatsink, this little silver square fell out. The little silver square, of course, is the processor:

Here’s the motherboard fitted with the processor and the default heatsink:

But I didn’t trust that fan. Here it is with the Zalman cooler installed. (Yes, the protective plastic is still on. This was a dry fit, before everything was mounted. Yes, I remembered to remove it when I installed it for real.)

Quite a bit larger. Good thing I got a roomy case.

I’ve been quite happy with the setup, and I’d highly recommend it.

Photoshopped Art

I tend to be a Photoshop purist — you can use Photoshop to perform minor technical fixes. Correct white balance, enhance contrast, crop the shot a big tighter. Sometimes I think minor things are okay — in a portrait, it’s okay to clone out a cell tower in the background, or in an artistic landscape shot, it’s okay to clone out the litter. But I’ve never been fond on the ultra-tacky practice of applying random Photoshop filters and calling it art.

Consequentially, I have pretty mixed feelings about the Cutout tool. On one hand, it creates stuff that looks pretty good on its own. On the other hand, I don’t know that snapping an uninspiring photograph, applying a basic Photoshop filter and sliding a dial constitutes art. I’m pretty certain it doesn’t, in fact. But at the same time, I like these:

Nashua River

Mobilgas Sign

Thinking Like an Engineer

Lately a lot of my work as a web developer has been way at the back-end, and, for whatever reason, it tends to focus heavily on third parties. I spent a while fixing a bizarre intermittent error with our credit card processor, moved on to connecting with Facebook, and am now working on a major rewrite of the API client we use to talk to our e-mail provider. Sometimes it starts to bleed over into my personal life.

This kind of turned into crazy-person babble, but I haven’t posted in a while, so here goes a perhaps-horrifying look into how my mind works:

  • Driving home one night, I went through the FastLane / EZPass lane, as I often do. Only this time, instead of thinking, “I hate that I have to slow down for this,” I started thinking about latency. Latency is one of the biggest enemies of people working with third parties. It was at the crux of our problems with the credit card processor — we’d store a card and immediately try to charge it, when sometimes we had to wait “a little bit” before the card was available throughout their system to be charged. So I had to introduce a retry loop with exponential backoff. The email API work has major hurdles around latency and timeouts. We’ve moved almost all of it into a background queue so that it doesn’t delay page load, but even then we have intermittent issues with timeouts. So driving through the FastLane lane today, I slowed to about 45, and thought how remarkable it was that, even at that speed, it was able to read the ID off my transponder, look it up in a remote database somewhere, and come back with a value on what to do. I’d have assumed that they’d just queue the requests to charge my account, but if my prepaid balance is low, I get a warning light shown. It seems that there’s actually a remote call. It’s got to happen in a split-second, though, and that’s pretty impressive. I wonder how they do it. I thought a lot about this, actually.
  • I work on the fourth floor of a building with one, slow elevator. A subsection of Murphy’s Law indicates that the elevator will always be on the exact opposite floor: when I’m on the first floor, it’s on the fourth, for example. So one day while waiting for the elevator, I started thinking that it needed an API. I could, from my desk, summon it to our floor to lessen my wait time. Likewise, I could build an iPhone app allowing me to call the elevator as I was walking towards it. The issue of people obnoxiously calling the elevator way too early seems like a problem, but I think it’s okay — if you call it too soon, it will arrive, and then someone else will call it and you’ll miss out entirely. It’s in everyone’s interest to call it “just right” or err on the side of a very slight wait.
  • While thinking more about the elevator API, I started thinking about how elevators aren’t really object-oriented. (I’m pretty sure that’s never been written before.) It seems an elevator is really pretty procedural, running something like goToFloor(4). The obvious object would be Floors, but that’s not really right. You’re not adding Floors to the building, or even changing properties of Floors. The object is really CallRequest, and it would take two attributes: an origin and a direction. “Come to floor two, I’m going up.” It made me think that there are some places that being object-oriented just doesn’t make a ton of sense.
  • You really want to add authentication. To get to our floor, you need to swipe your badge. The elevator API needs to account for the fact that some requests require validating a user’s credentials to see if they’re authorized to make the request they are.
  • “Code an elevator” would actually be an interesting programming assignment. But I fear it’s too far removed from most normal coding. I started thinking that you’d want to sort CallRequests in some manner, use some algorithms, and then iterate over CallRequests. I think you actually want to throw out that concept. You have a tri-state to control direction: Up, Down, and Idle. Then you have two arrays: UpwardCalls and DownwardCalls. They don’t even need to be sorted. As you near a floor, you see if UpwardCalls contains that floor. If so, you stop. If not, you continue. If you’ve reached the highest floor in UpwardCalls, you check to see if DownwardCalls has an elements. If so, you set your direction to Down and repeat the same procedure for DownwardCalls. If there are no DownwardCalls, you set your state to Idle. The problem is that this is really not how I’m used to thinking. I want to iterate over CallRequests as they come in, but this means that the elevator is going all over the place. The person on the 4th floor wants go to the 2nd, so we make that happen. But right as they put that request in, the person on the 3rd wants to go to the 1st. So you’d go 4 to 2 to 3 to 1. “Fair” queuing, but ridiculously inefficient. On your way from the 4th to the 2nd, stop on the 3rd to pick the person up.
  • I wonder how things work when you have multiple elevators. In big buildings you’ll often have something like 8 elevators. I’m far too tired to try to figure out the ideal way to handle that. They need to be smart enough to have a common queue so that I don’t have to hit “Up” on all eight elevators and just take whatever comes first, but deciding what elevator can service my request first is interesting. I kind of think it’s another case of elevators not being the same as the programming I’m used to, and it’s just whatever elevator happens to pass my floor in its service going in the right direction. But what if there’s an idle elevator? Can it get to me first, or will an already-running elevator get there first? Do you start the idle elevator first and make it event-driven? What if the already-running elevator has someone request another floor between its present location and my floor? You’d need to recompute. You’re probably better off dispatching an idle elevator and just giving me whatever gets there first.
  • You then need to figure out what’s important. If you have an idle elevator that can get to me more expediently than an already-running elevator, but the wait time wouldn’t be that much longer, do you start up the idle elevator, or do you save power and have me wait? How do you define that wait? Is this something elevator-engineers actually tune?
  • I think you want to track the source of a request — whether it came from within the elevator or from the external button on a floor. If it’s within the elevator, you obviously need to stop, or the elevator has effectively “kidnapped” the person. But if it’s an external button, you might want to just skip it and let another elevator get to it, if you have a bunch of CallRequests you’re working through. Ideally, you’d also approximate the occupancy of the elevator based on the weight (from reading the load on the motors?), and when the elevator was at perhaps 75% capacity, stop processing new external requests.
  • Should the elevator controller try to be proactive? It might keep a running log of the most “popular” floors out of, say, the last 50 CallRequests, and, when it was done processing all CallRequests, go to whatever the most popular was and sit idle there? Or perhaps it should work its way towards the middle floor? If you had multiple elevators you could split them apart that way. Is it worth the power conservation?
  • The office thermostat should have an API, too. (I bet the good ones do. But we don’t have those.) Thermostats are a pain to use. readTemperature and setTemperature are the obvious API calls, though advanced thermostats would have a TemperaturePlan concept.