Thursday, December 22, 2016

Passing "this" Around In Polymer

Lately, I have decided to write the front ends for my personal Web projects in Polymer.  It gives me the ability to construct the UI, and even tie in AJAX actions and database calls, by simply including Web Components as elements in the DOM, just like plain HTML.  To me, it seems less bloated and denser than even Angular 1 (sorry, haven't played with Angular 2 yet), not to mention plain JavaScript or JQuery where you still need to write out most of the interactions between the model, view, controller, and external APIs yourself.  The Web Components aspect was most appealing to me because now I could leverage previous work, standing on the shoulders of giants, rather than reinventing the wheel for the needed interactions.  Better yet, if I use Google's implementations of Web components, I can even get Material styling on my DOM elements with no extra work.

However, Polymer suffers from some of the problems I've had with Perl too.  You really need to be in the right frame of mind when writing in Polymer because the syntax is deceptively short and you need to be intimately aware of what the framework is handling for you.  This could make it tougher to explain what's going on in the code if haven't looked at it in a while.  "Oh yes, you can build this in Polymer, and it looks just like HTML!" I once touted to a crowd, but then upon closer inspection -- no -- there were a lot of other idiosyncrasies specific to Polymer they would need to know before they could go off on their own and replicate my work!  Finally, while Perl is generally easy to find help for, it can be frustrating in the world of Polymer because many answers pertain to older versions of the framework,

Despite these pitfalls, many people who love front-end website design and are adept with XML-based layouts have been flocking to use Polymer for building fully-functional Web apps.  In fact, now you don't even need to write JavaScript to do 3D scenery in a browser, so if you enjoy using A-Frame for building 3D scenery and you need to build an entire Web app, then you would probably enjoy Polymer as well.  For me, it's about doing more with less, and Polymer seems to minimize the amount of code I need to write, not to mention the amount of technology I need to get involved -- the days of having to build an API on your server to talk to the remote API might be coming to an end!

One of the biggest things I've busted my head on in Polymer thus far was working with the this variable.  You use this to access the functions and properties defined within the scope of Polymer.  This is OK when you have a diverse set of interactions taking place in your application, but what about those times when you have something fairly repetitive?  The principles of DRY dictate you should move such repetitive code into a function.  That's easy to do if you want to keep everything within the scope of Polymer:

  is: 'my-element',
  properties: {},

  scopeFxn1: function() {
    console.log(this);  // just as you would expect in the Polymer scope

  ready: function() {

However, imagine if you have a bunch of different interactions you need to define as functions.  This could start to make your Polymer element and its JavaScript properties a bit long and messy-looking.  The first thought is to move these functions outside the scope of Polymer and possibly into a separate file containing your JavaScript logic.  However, note the caveat to that:

this doesn't propagate into your function.  Watch out!

If you define a function outside the scope of Polymer, and try to call it from within a function that is in the scope of Polymer, the browser will not know what this is anymore and that could prove very frustrating for you if you want to take advantage of any of the benefits this brings you, such as manipulating variables bound to DOM elements or updating properties of your data objects.

outsideFxn1: function() {
  console.log(this);  // nope, does not compute

  is: 'my-element',
  properties: {},

  ready: function() {

One potential workaround: simply pass this as an argument from within the scope of Polymer to your external functions.

outsideFxn1: function(element) {
  console.log(element);  // same as this, but outside Polymer scope now!

  is: 'my-element',
  properties: {},

  ready: function() {

This way, you can use element (or whatever you end up calling it) to update the data bindings on your UI and run the set() function on your objects in order to properly broadcast updates to their properties.

To be honest, I had this article waiting in the wings for a long time but posted it now simply because my upcoming features on ATmega fuses and retrocomputing reminiscence aren't quite ready yet, and I wanted to get something out for this week.  But since originally getting the idea for this article, I learned about Polymer behaviors.

Behave Yourself, You Big Group Of Functions!

Polymer behaviors are like mix-ins in other popular languages like Java where there is no concept of multiple inheritance but people still have the need to incorporate functions belonging to different classes of objects.  It's the best of both worlds; you can have all the functions you need in order to do all the operations you want to do on your DOM and your data, but without the weird side effects and useless baggage you would get if you had to do multiple inheritance as in C++.  And because Polymer behaviors are defined in the scope of Polymer in your application, the functions (whether you write them or not) in these behaviors understand the true meaning of this once they are initialized.  I'm not going to provide an example here because there are tonnes of other places where you could obtain them, including the link to the official Google doc above (as long as 1.0 is still relevant).

As such, you could probably pass this around between functions inside and outside the scope of Polymer, as described initially, but you know what they say about "when in Rome..."  I would argue it's wiser and more sustainable to stick to the conventions given to you by the framework.  If you're looking to attain DRY nirvana in your code and want to push functions out of the scope of any individual Polymer element you write, just implement the code in a Polymer behavior, save your this, and call it a day.

Thursday, December 15, 2016

Last-Minute Stocking Contest Entry Takes the Cake!

The place I work at during the day tries to foster a whole lot of creativity as we tackle tough problems from many different angles, starting with carefully designed user experiences and including the best performance and functionality in order to delight our customers.  We have incredibly talented people working as leaders and contributors on our tech and design teams, and it takes lots of incentives in order to keep a team such as this together without suffering from attrition.  Many of my coworkers came from the startup world and, for all we know, are only trying to pay off some bills while chasing their great big hit on the side.

One particular perk I've had a big hand in lately hasn't quite been mentioned on the Internet yet that I could tell, other than hinted at within various event invitations that you could probably dig up if you tried hard or maybe within social media interactions originating from the attendees, thus I'll refrain from talking about that particular perk in great detail just yet.  However, I'll say that out of this particular resource, we held a Christmas stocking decorating contest.

This contest kicked off on Nov. 30 during one of the monthly parties in our workspace, and I saw many people from the design team crank out very creative stocking ideas within just a short period of time.  While I was standing there awed by this raw talent being flaunted, two directors came up to me and said "I expect that yours will have LEDs on it."  The challenge was on!

Early entries in the contest.

I still didn't know what exactly the theme should be, and as someone who has spent more than the last three years writing incredibly geeky posts on this blog regarding various aspects of game shows, options, software, and hardware, I know that my right brain has a very hard time actually executing on its vision, if it can even come up with something that looks good in the first place.  I think I used up all my artistic energy being the Vice President of Public Relations for the Residential College Board at Northwestern University from 2006-08, so it would require a lot of meditation, hopes, and prayers to see it through.

Enter Stacy, who can certainly execute well on the good ideas that come out of her brain.  She definitely has her own style, and while it might not be quite as polished as people who do this for a living, it's amazing that someone can have such a strong left brain and right brain.  She fulfills that artistic side which at one time I thought I had for myself, but now that I have her for myself, I won one in the end anyway.  (We keep trying to figure out who got the better end of the deal in our relationship. :-P)

Anyway, my initial thoughts on the matter revolved around using my secret "charlieplex110" project (well mostly kept secret from the Internet; folks at work have seen it and maybe you've seen it on Google+ if you were watching closely) on the stocking in order to display messages, but thought that wouldn't be very Christmas-y and not really be easily integrated into a Christmas theme.  Using a BriteBlox display would be silly because the dot pitch on those things would be too large to display a coherent Christmas-related message without spanning several stockings.

The weekend before the contest, I intended to bring a blank stocking home and meditate on it in order to come up with a vision for what I wanted -- except I forgot it somewhere and ended up getting distracted with other things over the weekend.  Then I had a holiday party to attend on Monday night, which left me with strictly Tuesday in order to finish the stocking for the Wednesday afternoon contest.  I was hoping to bounce things off Stacy that night, but she spent most of the night fixing her mother's computer and didn't get home until very late.  As such, in my soporific and possibly somewhat depressed state of mind, I had a flash of inspiration to make Santa's sleigh being pulled by reindeer.  Also, the reindeer needed to have moving legs.  But, in fact, doing all that would be really tedious, so I settled on just having one reindeer with legs affixed to the servo motor.  I finally managed to churn out some code that would light a string of WS2812 LEDs (which I had just had a lot of first-hand experience with) with alternating & switching red & green colors, and then also spin a servo motor 90 degrees in order to move the legs, using the Sparkfun Pro Micro development board.  Most of this was, in fact, code that was easily leveraged from other projects, but still seemed to take me more time to finish for some reason than I'm willing to admit.

Some of the hurdles I faced included:

  • Not being able to find felt anywhere -- I wanted to use felt in the construction of Rudolph on the stocking
  • One of my servos didn't want to work with the Pro Micro, and the other servo had a smaller Grove-style interface that couldn't hook up directly with the headers on the Pro Micro
  • I wanted to include a PIR sensor to make these effects motion-activated, but didn't know where it was off-hand and wasted too much time locating other things
Once I got the LED strip and the servo all working in harmony, it was time to draw the artwork.  We have a large collection of colored Sharpie markers at home, and despite being the normal size, the lines actually came out quite thin on the stocking due to the type of material it was made out of.  I'll just say again that people who have the capability to draw fascinate me.  I used to think I had a knack for drawing too, but now I'll say I've pretty much been reduced to just tracing patterns onto the paper and then doing coloring on top.  That's fine, though my stocking came out way more hand-drawn than many of the other offerings that took advantage of the physical accent pieces available to add.

My goal was to keep it hidden until adding the final feature to it right before the contest; that would be a blinking nose for Rudolph.  It took me way longer than it should have just to blink a stupid LED, thanks in part to having to improvise on some of the cabling, said cabling being difficult to put together (and having to cope with long leads liable to touch each other), and then a goofy firmware glitch I caused when I tried to write the servo data and toggle the LED from the same output pin.  Unfortunately this problem was compounded when Windows stopped acknowledging my Pro Micro on the USB port.  Of course, when Windows screws up, you have to reboot, and it's not quite as smart as Mac OS is about re-spawning all your applications.  However, even a reboot didn't fix it right away; it took somehow even more monkeying with the Arduino IDE (sigh) before I could re-upload the firmware with the bug fix.  By this time, the party had already started, but not a lot of folks had voted yet.

Electioneering Efforts Near the Polling Place

The vice-president over me, who is mostly in charge of the Tech side of things (i.e. not Design), quizzed my teammates on who made a stocking.  It became apparent that I was probably the only person in Tech who attempted it, but was out of pocket trying to get that blasted LED for Rudolph's nose working.  When I went back to my desk, I affirmed that I did in fact have an entry, and I was told to show it to the others in Tech and have them vote for it just to support their own kind, since basically the designers came up with every last other stocking.

Getting it hung up on the judging board was met with a bit of resistance, as the admins were jokingly jealous of the level of awesomeness of the final product.  "No, I'm not putting it up..." "Ok, I'll put it up, but I'm putting my name by it!"  Then, as one of our executives began explaining the rules and procedure of voting, I realized there'd be a problem.  Votes were to be cast by stuffing the stockings with jingle bells that would be counted later, but as mine was stuffed with "electronic crap," there was very little room to put jingle bells inside it and it could even pose a safety hazard (shorting a lithium ion battery) if anyone attempted it.  The crowd gasped and laughed once I basically revealed which one my stocking was.  Some jokingly said "Too bad!" since it was pretty clear (or pretty well-illuminated perhaps) who would win, and others feared it would turn into a popularity contest for me versus the others.  Luckily someone offered a good suggestion to actually hang a blank stocking next to mine, and people could put their jingle bells inside that one so they all would fit without messing up my electronics.  Nevertheless, while I was awkwardly standing nearby someone we are all extremely fortunate to have with us in our group and in life in general, I happened to see the counting committee dump out approximately four jingle bells from inside my actual decorated stocking.  Sigh... At least no one broke anything during either the jingle bell insertion or removal phase!

As the time came, for some reason, it was about as nerve-racking as a contestant awaiting the results of the Super Match on Match Game.  They start by revealing the third place, then move onto the second place, and then finally show the first place winner.  The stakes were high, since the winners would take home Amazon gift cards of up to $100 in value.  Pretty good just for some stocking-making!  Anyway, I can't even remember the other two due to the sheer level of excitement and anticipation (had that feeling before), but I probably wouldn't have written up a close to 2000-word article unless I didn't personally take that $100 prize home.

Afterward, one of the product managers told me to watch my back, as next year, he would be bringing some serious hardware & IoT know-how to the table to make yet another technologically awesome stocking.  Fine with me; after my director told me that mine really exuded the values of our particular workspace and our maker culture, let's hope even the designers take some time to put in hardware features next year!

My lil' ol' contest entry.  Unfortunately, by this time, Rudolph's nose LED wiring fell apart somehow (surprise surprise) and the chenille pipe cleaners being rotated by the servo motor (for "Spider Legs Rudolph") also fell off.  The good news this is already two nights after my contest, so none of my coworkers saw it in such disarray.

Thursday, December 8, 2016

You Had the Time Of Your Life 40 Years Ago... Now What?

We all have our happy places and fond, cherished memories.  For many, it's taking part in a unique experience or getting distinctive recognition.  For some, it's the time they peaked in life.  And for still others, it's when you won something big on a game show (or at least got to go up and kiss Bob Barker).  And for a select few people, maybe all of these honors happened at once!

Whatever the case may be, I would argue that if you didn't have a good time on a game show, you're doing it wrong -- and as such, most people want to relive the adrenaline rush of what it was like to be a contestant, recall that question that set them on their nerves, and that big moment when the payoff landed or it all went bust.  And as the years go by, we all look younger and younger as we watch ourselves on TV through recordings.

As someone who owns a game show website featuring a whole lot of clips, accounts, and details, I often get written by contestants and their relatives asking how they can obtain copies of their appearance on TV.  But let's step back for a bit: I want to go more into the website and how all that got started.

Geekdom Started At a Young Age

Quick aside: As I like to say, "hone your craft".  The best start when they are young, and in my youth, that mostly meant you would practice at sports all the time to be the next great athlete, though some would take up musical instruments and become virtuosos.  Well I started in computers from a very young age, and look where I am now: writing about game shows on an otherwise geeky blog. :-P

I'd been dabbling with HTML and JavaScript since probably 1998 or 1999.  It was simple stuff I'd run off my own computer until I figured out how to get free hosting from places like 50megs (holy ****, this one still exists?!) and 100megsfree (pretty much gone the way of GeoCities).  I became friends in middle school with another Internet-savvy person, and he helped me get proper paid hosting and even bought me domain names for my birthday (including the one I just linked to, which just marked off 12 years a couple weeks ago).  Even still, I turn to him (well, really, now her) for advice on Web hosting matters, which now basically reflects preferences for which cloud hosting provider, which stack, and which security services -- much different than what paid hosting used to be!

The website really began in earnest in January or February 2005, shortly after receiving my first tape trade.  By this point, the other predominant website (, at the time owned by Tony Harrison) was starting to diminish in updates and wasn't really being maintained with the times.  I sought to correct all that by putting up clips in my own website in a similar format to how he listed his, but with more modernities like stylistic updates, content management systems for clip organization and comments, databases, possibly Silverlight to play videos right from the browser, etc. (Remember it was only 2009 by then and people were starting to get real sick of Flash but Silverlight was pretty much the only alternative as people awaited the HTML5 video spec.)

Where does this have you now?

My biggest year of tape trading had to have been in 2007.

Wait, back up again... tape trading is a thing?

Yes, this is a thing (see #15 in this link) that happens among fans of obscure television shows.  Since there are very few outlets that provide reruns of game shows since GSN pretty much only shows Steve Harvey's Family Feud plus their own original content anymore, and Buzzr only shows like the same eight episodes of $ale of the Century, it's kind of up to ourselves to steward the "library of our own amusement" among ourselves.  Tape trading is legal as long as you don't receive remuneration for anything, and while once upon a time I tried to search the Library of Congress to see what shows had lapsed into the public domain so I could sell it, ultimately it seemed like a lot of effort in order to tap into a very small market of people who probably already had what I had to offer anyway, unless I wanted to spend years of hapless hours sitting in dark basements of television stations watching all their aircheck footage from over the years hoping for some kind of relevant gem (though believe it or not, this is how the original 1972-1975 run of The Joker's Wild was found).

It's 2016, but my tape stash is very much alive and well.  I'm guessing this is the largest collection of VHS in the neighborhood, but there's several Betamax tapes in there for good mix too, with working players for all this stuff sitting right across the room from this shelf.

For real this time... Where does this have you now?

I haven't really traded much since 2013 when the entrepreneurial & startup & DIY/maker bug hit me, but by 2009, I'd amassed enough stuff cataloged online that I guess I started to get good page rankings on Google.  People from out of the woodwork started hitting me up for copies of episodes that they or their family members appeared on.  It's always gratifying to receive these types of requests from people because from watching game shows, I know they bring out a lot of true emotion in people (almost always happy ones) and I believe everyone needs to be able to relive that.

The first such request I can recall came to me in August of 2007 from a fellow named Brian, who appeared on The Price Is Right back in 1992 and somehow caught wind that my copy of the episode might be in slightly better shape than his, so he wrote me to see if he could get a copy.  As a matter of fact, there are a series of episodes from 1992 on a couple tapes that my mom actually recorded for me back then when they were originally broadcast, and almost 25 years later, they still exist in all their glory with original commercials and not much worse for wear despite that they're on VHS.  (If you don't believe that VHS tapes can stay good that long, check out how well J-Shea's early 1980s TPIR episodes have aged.  Those videos were mostly published online in the mid-late 2000s, so those recordings were pushing 20 to 30 years old themselves.)  Anyway, apparently I really was impressed by Brian when I saw this episode as a youngster, since I wrote a bunch of notes on the tape about what he did.  Years later, when I dug this up out of my own archives, I made a page devoted to his episode, and he was impressed (or possibly a little weirded out) when I showed it to him.  Nevertheless, he was gracious enough to answer at length all the interview questions I asked him; I really appreciated the level of detail he went into on his experiences with the show, the taping, his prizes, and how life in general has been up to that point.  I hope he's still out there somewhere doing well.

Other notable requests I've received:

In 2009, a prominent TV meteorologist from the NBC network wrote me to obtain copies of when her grandmother was on The Price Is Right.  It just so happens that her grandmother was on the nighttime version of the show back in 1963 (during its original format) and won over $70,000 in prizes over 6 episodes.

Also in 2009, the grandson of Stanley Skeens wrote me to request a copy of Stanley's appearance on the $64,000 Question, hosted by Hal March, from around 1955.  I was extremely intrigued by this one, as there aren't many people still around who participated in a show related to the Quiz Show Scandals.  I tried to prepare a list of questions for Stanley, but his grandson said unfortunately Stanley's health was failing and was doing badly from COPD thanks to years of coal mining.  Sadly, Stanley passed away on April 15, 2012, as did his own recollections of his experience.

In 2011, a lady who was on an early 1973 episode of The Price is Right wrote me for a copy of her episode.  I had a studio master copy of it, which was particularly exciting.  We had a good conversation about the memories and eventually I convinced her to return to The Price is Right for another shot at a big prize sometime shortly thereafter, but alas she didn't have such luck again with making it into Contestants' Row.

As you can tell, I enjoy living vicariously through these people's accounts of their episodes.  I can't totally relate, because I haven't been a contestant on a show yet (whaaaaaatttttttt????) but from the aspect of the game show nerd getting to meet people who have done such cool things, I love getting to know the back story on to how all these great things transpired.  Nevertheless, some requests take a really long time for me to process, or can possibly be left hanging, because either there's not enough information to get the date or else I don't have a copy of that particular show. For instance:

In 2014, another lady wrote me who played Make Your Move on The Price Is Right back in 1989 for a car.  Only 12 people have ever played Make Your Move for a car in the history of The Price Is Right, so it was great that I could have the privilege to get to know her story.  As it turns out, I did not have this episode, so this one was put on hold until later that summer when I found out who to contact for copies of these shows.  I emailed her right away, but by then, she ended up finding it her own stash, and was gracious enough to send me a copy of her tape (on a DVD of course) for my time & effort.  She was rather unimpressed with the quality of her VHS tape, but I told her it actually looked better than most other original-broadcast shows I have from the same era.

Ok, but 2009 is kind of a long time ago, and 2014 isn't that recent... what about *now* now?

Now that I have this contact, who happens to be an archivist for a major production company, I have almost exclusively helping people track down the exact airdate of their episode and helping them make the contact with the archivist.  Most folks, given the chance to see a pristine studio master (SM) copy of an episode versus some 2nd-generation VHS or DVD recording of the show from over the air, are going to want that studio master, unless the OTA recording was recorded from their own hometown, which is highly unlikely.  And even then, they might prefer the SM copy anyway.  I'll generally take it however I can get it, and would even double it up if it's of particular interest.  Highest quality and completeness are both important to me when I'm collecting episodes, so there are several cases where I have multiple copies of the same show.  But even still, that's not how most people work.  In fact, a vast majority of the people I write back with this information usually just say "Thanks" and leave it at that.  A small percentage of folks follow up once they've received the SM copy, thus indicating about how long it takes to receive the episode once they've asked.  Usually the archivists are pretty fast (about a 1-week turnaround) unless you catch them while they're on vacation, and then you could be waiting several weeks.

Just once in all this time have I ever had someone write me back to offer me a copy of something they got from the archivist, and it was something that doesn't even exist in the trading circuit as yet.  The episode would happen to have quite a bit of significance on its own due to one of the games that was played, but even a hard-core fan would overlook such trivia when they see what Bob was up to with one of the contestants before Act 5:

"You didn't have any place to put your name tag, Leslie?  Well, I could think of, heh, a couple places to put it, heh heh, Leslie!"

The Importance Of This Stuff

As fellow trader Chris Powney told me, not many people in his home country of Australia gave much thought to salvaging these old reruns of game shows.  There is evidently quite a bit of material that even the networks themselves didn't keep copies of, and as a central repository, Chris has even been involved with helping produce retrospective shows, documentaries on game show scandals, and so forth by providing the footage that would go into the new show or documentary.  I can't possibly imagine how this turns out, since the vast majority of my tape collection confuses people as to why it looks so bad (read: not totally pristine broadcast quality, not to mention mostly in 480p these days rather than in any semblance of HD).

But as for me, I still get contacted by random people around the country at least once a month to help them track down episodes they themselves or their relatives appeared on.  These interactions I get do nothing but bring joy to both parties -- you as the contestant and me as a big fan.  As such, this is why I haven't included the information on how to get a hold of these archivists directly.  I want you to contact me first!  Then maybe I can learn more about your story and get a chance to enjoy it more deeply than simply watching it play out in the recording.

Missed my contact info?  Get it from my Website:

Thursday, December 1, 2016

The story of those awesome "shaky benches" from TechWeek Dallas 2016

For all this time, I have touted myself as someone familiar and adept at working with hardware, and try to stay on top of all the latest & greatest gadgets in the arena.  Of course, that's very hard to do, and eventually you will find that you've ignored something that virtually everybody else in your circles seems to have already played with.  For me, that was the WS2812 LED strip.  Sure, I've used WS2812 lights recently in an IoT sensor product, but really Stacy wrote that code and we are only driving one of them per board, so it's not truly all that interesting.  Now, it's time for me to get serious with what the WS2812 lights are really meant for.

What is (was) TechWeek?

TechWeek is an event held in cities across the country. It attempts to discuss various tech trends by bringing together numerous panel discussions on things such as ed-tech [1] [2], healthcare, and smart cities, plus individual speakers talking about things like the path to driving a startup culture inside a large enterprise organization (in fact a "big bank", if "large enterprise organization" wasn't already scary enough for you).  The event began in earnest on 11/2, preceded by a Halloween party on Monday 10/31 and tours around various innovative corporate campuses on 11/1 (including at the aforementioned big bank, which I helped facilitate), and wrapped up by an epic concert featuring The Neighbourhood and others on Friday 11/4.  The keynote was given on Friday by Alexis Ohanian, co-founder of Reddit.  There are other things to do besides plenty of networking opportunities, such as startup pitch contests, startup job fairs, and lots of drinking & partying & concerts besides just the one on 11/4.

The highlight of TechWeek for me was the "Surround Sound" event at The Bomb Factory in Deep Ellum, which is where most of TechWeek took place.  At this event, attendees would be exposed to various ways in which sound could be transduced and manifested into other sensory experiences such as visual or haptic effects.  Among the pieces presented were an artist on-stage making a 3D interpretive painting with an HTC Vive, a large LED wall producing art based on live spectral analysis of the music coming from the DJ booth and an additional microphone, holographic screens where you could dance with people across the room... and my piece.

Getting in on this not just by who I work for

One of my friends from the Dallas Makerspace approached me sometime over the summer (maybe end of July or August) about working on a project that would fit the essence of what Surround Sound would be all about.  I told him to keep me posted, and it wasn't until mid-September (at the DMS Open House) when he mentioned with certainty that he'd be participating and building out his dream for the event.  It really had to do with getting paid the grant money; it would have been an expensive project to take on and have the potential of something failing or not working out.  Unfortunately that left only about six weeks to the show, thus I was recruited to assist given my knowledge of LEDs and electronics.

Nick owns a print shop and design studio, and is a very crafty fellow in the realm of everything from graphic design to embroidery as well as other unrelated hobbies such as shooting and ammunition reloading.  As such, he put himself in charge of fabricating the actual components of the piece.  This included two circular benches 4 feet in diameter with little tiny holes cut out in the top of the plywood for light to shine through.  The benches were covered by custom-cut white Spandex, which the lights from the holes projected nicely onto.  Speaking of the lights, there would be 240 WS2812 LEDs in each bench, broken up into strips of 10, 20, and 30, located in each quadrant of the circle.  At the base of each table would be a ButtKicker amp that could deliver 1500 watts at 2 ohms worth of frequencies between 1 and 200 Hz.  This amp was not really designed for propagating audio through the air, but through some solid medium like a chair that you sit on and really feel the bass tones.  Then, there would be a control table, also fashioned out of plywood and covered with Spandex, that would have 160 WS2812 LEDs in it in addition to two sonar sensors mounted into 3D-printed coverings over holes cut into the plywood.  All of the plywood was cut on the CNC router at the Dallas Makerspace and was designed to be press-fit -- no nails or staples were used to hold the furniture together.

Then there was Darcy, tasked with creating the audio effects to be used in this installation.  The idea was to allow party-goers to manipulate the audio signal into the benches somehow by using the sonar sensors.  She worked out calibrating the sonar sensors to respond to objects moving at various distances.  The sensor outputs were consumed by me through the PWM pins of the Teensy she was using (v3.2) to read the sensors, and also interpreted for the sake of performing sound synthesis with the Teensy Audio Adaptor Board.

My colleagues downstairs worked with a publicity company who managed the engagement with Nick and Darcy.  They were impressed at the scale of my network when I mentioned I knew them and they had spoken of this project with me, and then they thought it was really cool when I told them I would be helping out on the project too!

Affecting Effects

I was brought in to do the lighting effects, despite that I practically minored in sound synthesis in college.  It turns out I have a lot more LED experience of recent note, so that makes sense.  In fact, I briefly dappled in using mathematics to make art (or at least wonky patterns on 3D graphs) in college, so I applied the similar mindset (if not my long-lost knowledge of multi-variable calculus) into making the LED effects for this project.  Since this was not a true LED matrix, but rather 3 bands of lights around the circumference of the benches, it didn't make sense to do something over-complicated and two-dimensional.  A simple yet compelling one-dimensional effect that can go in a circle is simply an undulating sine wave.  Here is my first crack at such a wave:

This wave was built by calculating the value of sin²(x) at various points along 0 <= x < 2π.  Originally I used a step size of 2π/61 because my prototype had 61 LEDs, but later I changed the step size to be 2π/100 to be standard.  Now, sin(x) produces a very wide waveform relative to a single period, and doesn't make a lot of distinction between lights that should be on versus lights that should be totally dark.  By squaring the sine of x, values close to 1 become even closer to 1, and values close to 0 become even closer to 0, thus making the waveform even "peakier."  Actually, I avoided doing an annoying squaring operation by looking this function up in Wolfram Alpha and finding out I could calculate (1 - cos(2x))/2 instead.  And speaking of looking things up, I stuffed all the output values from this function into a lookup table for convenience later.  As the program would constantly be calculating the same values over and over (and wasting an untold amount of CPU cycles in doing so), I figured the lookup table would be best for performance in the long run.  (All the people who developed wavetable audio synthesis products would probably agree with me.)

I also coded additional lookup tables to vary the color of the LEDs over time.  Originally we would swing them from red to purple to blue based on the value of one of the sensors.  The sensor would influence which index of the color lookup tables we would access; the same index for both the red and blue channels would be used.  (For this case, green could always stay 0.)  These lookup tables were based on simple ramp functions that slowly eased the value of that color channel from 0 to 255, and then held it constant; one channel's graph looks like the other one reflected over the Y axis.  Then, the speed of the undulation (the wave spinning around the circle) was affected by interpolating the other sensor's value to a number between 1 and 14, which corresponded to the offset we would add to the lookup table to calculate each LED's intensity.  This way, the waves would appear to move around the benches and table.

Stressing Over the Finishing Touches -- Heck, Just Getting It To Work!

After a couple more weeks where Nick & Darcy were working on their parts, I got engaged again to make further modifications to the LED effects and to help with the assembly.  One enhancement was to change the colors to sweep from red to white to blue.  To change purple to white, I took advantage of the green color channel.  The function for green is simply the negative absolute value of x so the lookup table ramps from 0 to 255 and then back down to 0.  Now each RGB channel has its own lookup table.  We also continued to toy with the exact formula producing the sine wave, and I made some changes to the sine wave lookup table so that the same lookup table could be used among the three different-length LED strands below the bench.

The few days prior to the event were quite stressful, and we put in long hours to get the finished product working.  The hardware we were using wasn’t even nailed down, so I attempted to use a Raspberry Pi to drive the LEDs and perform audio signal analysis all from a single source.  It ended up being overly complicated; audio signal analysis doesn’t go incredibly fast on the Pi, and lots of things would need to be downloaded and compiled for it to work.  It turns out that doing such analysis probably wasn’t even necessary anyway because people really seemed to enjoy adding simply the bass drops; it is something concrete and distinct that folks can understand rather than having one of us standing around the whole time explaining to people how to compare some subtle property of the audio with the audio signal in general.  Lastly, I tried to implement some beat detection with the Arduino so as to synchronize the bass drops with the beat of the music and perhaps do one or more bass drops per beat.  Ultimately, time ran out for that enhancement.  The hardware we ended up using consisted of a Teensy in the control table for sensors and sounds, an Arduino Uno in the control table to drive the lights, and then the benches had either an Arduino Uno or Leonardo in them to run their lights, depending on whatever we had on hand.

Since the Teensy reading the sensors needed to drive signals consumed by the other Arduinos to produce the light effects, I had to be careful not to use outputs on the Teensy that overlapped with the pins that the audio board needed.  For this reason, I used three specific PWM pins to output to the three other Arduinos so that each pin would only have to drive one TTL load.  However, the Arduinos would need to read these signals in as analog, so I used specific values of resistors and capacitors to make an RC circuit with characteristics that made me happy.  The biggest thing to consider in an RC circuit is the tradeoff between signal rise time and ripple.  Too much ripple in the output would cause bizarre pulsing of the colors or a confusing change in the rate the sine wave would spin around the table.  However, too much rise time would cause the sensors not to react fast enough to make the effect make sense to people interacting with it.  I played around with some websites to calculate the theoretical values of resistors and capacitors I needed, ultimately settling on 100 ohms and 10 μF (if I recall correctly), and then verified their behavior with an oscilloscope.  Once I was satisfied, I added the components to the breadboard and wired up the RC circuit to the analog inputs on each device, and then the appropriate outputs on each device to the LEDs.

Wow, what a mess…

Apparently WS2812 LED strips are quite sensitive to noise.  This pernicious problem can come from all sorts of sources, including shoddy soldering/cabling or EMI through unshielded cables.  Thus, for our long cable runs, we spliced up twisted-pair CAT 5 cables to provide power, ground, and data to each device.  We twisted up regular wires using a power screwdriver/drill to provide the same type of cross-talk cancellation between our LED light strips.  The problem is there were so many LED strips under each table that it required soldering almost 40 wires per table.  There's not a lot of landing room on the pads once you've cut them up, and remember we're soldering in some cases upside-down right on a plywood surface!  Talk about a fire hazard.  And even with all this precaution taken, we still had a big issue with noise, but only on the art project.  The lights would work just fine on a regular uncut LED strip, but the exact same code would produce all kinds of odd rainbowing and strobing effects in the installation pieces.  We tried reducing the noise by putting a resistor on the data line, but that didn’t help.  We then brought in Stacy, resident capacitor expert, to solve the problem that way.  Since the power line was noisy, she simply placed a capacitor across power and ground on one LED strip in each art piece, and now all that weird flickering and strobing went away, leaving us with the desired effect.  Of course, all this messing around with wiring didn’t come without occasionally shorting our power supply or zapping ourselves with 5V at 60A.  I can’t claim to have felt anything, but Nick says he got zapped a few times.  Maybe I’m just immune to 5V shocks anymore, even at 60A!

The audio synthesis code was a bit suspect at times too due to various bugs writing the frequency and amplitude to the two different audio streams.  I found out that each sensor was writing to one single stream in turn, very rapidly, which was probably not the desired effect.  We played around with “glitches” by writing various sensor parameters as either amplitude or frequency to the audio stream until we found something we liked.  This made me think: when will they come out with SuperCollider for embedded systems?

Wastes of Time, Including That Mother-F***ing Map Function

One thing that really wasted my time was trying to use the map() function provided by Arduino.  Literally all this function does is solve y = mx + b by taking two points of x and two points of y.  That’s really how they should describe it in the documentation.  Instead, they go on about some hand-wavy type of description that doesn’t make it clear what kind of boundary conditions exist when you use this function.  Apparently, there are no boundary conditions, and I needed them.  The PWM pins from the Teensy were basically sending me values between [0, 32) but scaled to between [0, 1024) because that’s the range of the ADC on an Arduino.  As I received input, I needed it to consider what would be actually appropriate ranges for those input values because they were being directly used as the indices for our lookup tables.  By simply re-implementing the map function to do what I needed it to do in the first place, I could have saved having to debug program crashes from index-out-of-bounds errors, which resulted in hours of busting my head on why the LED effects would freeze.  Of course, I could have just added min()’s and max()’s to the output from map(), but by that time, I was ready to call up the university of whoever made that function (or at least the documentation for it) and tell them to revoke his or her degree.

Another thing that sank a lot of my time was chasing down the correct signal lines.  As we added all the devices to the breadboard in the control table, the circuitry became rather jammed and hard to work with.  Often, I would find myself probing the wrong output when trying to test why the analog signals were causing different or undesired results between the different pieces.  On the final night before the big show, I wasted about 80 minutes in this manner trying to debug one single problem.  By the time you’ve worked so much on something and are feeling a lot of pressure, it can be easy to overlook such simple things as you stress the technical issues that you think it could be.

But When It’s All Said And Done…

Nevertheless, despite what it could have been and what it ended up being, we all believed it worked out the best for what the show was.  Anything more and it could have been overwhelming or confusing (or even annoying) to people, despite how much fun it would have been to get geeky with signal processing to, say, add in sparkling effects, add more spinning waves, or even use a solenoid to bang a drum.  Here is a short video of what we produced:

The code for the project is on GitHub at .  Some highlights from that code:

We ended up going with sin^6(x) as the function to produce the wave in our lookup table.  It was achieved with this for loop:

for (i = 0, x = 0.0; i < 100; i++, x += (PI / double(100))) {
    overallAmplitude[i] = ((-15 * cos(2.0 * x)) + (6.0 * cos(4.0 * x)) - cos(6.0 * x) + 10) / 32.0; 

The lookup table consists of 100 float values.  Originally the literal 100 was a constant called QUANTA.  So, no, the actual code does not have me writing double(100) like some kind of weirdo.

The benches had 240 LED lights apiece within three circles.  One circle had 40 lights, the second had 80, and the biggest had 120.  However, these three circles were treated as a single string, so the first 40 were drawn on the string, then the next 80, then the last 120.  But it’s in fact even more complicated than that: when the tables were wired up, each quadrant (i.e. section of 10, 20, and 30) were wired together before the string would go on to the next quadrant.  This is why the tableSide variable exists in the showFrame() function.  The variable p inside each for loop keeps track of specifically which pixels from each circle are being drawn, and the variable scaledIndex converts the proportion of (pixel index : string length) to find the pixel index relative to the lookup table of length 100.

for (int p = int(PIXELS_INNER * beginRatio); p < int(PIXELS_INNER * endRatio); p++, pp++) {
    scaledIndex = p * 100.0 / PIXELS_INNER;
    rVal[pp] = figureColor(scaledIndex, redColor[colorIndex]);

The lookup tables for red, green, and blue values were defined as bytes rather than floats in order to save memory.  Had I chosen floats, the Arduino Uno would not have enough memory to store all the lookup tables I desired.  Originally I wrote the functions providing the lookup tables to provide floating-point outputs between [0, 1].  When using a byte array, I rewrote them to output integers between [0, 100].  This allowed me to scale the final output by 2.55 rather than 255 when coming up with the final intensity values for each pixel.

Before new data would be pushed to the LED string, the color value for each LED would be stored into an array of type byte as well.  The value in the array was derived from solving an equation relating the LED’s position index in the strip and the motion offset of the sine wave to which value of the lookup table it should get for its intensity.  This intensity value was used to scale the color values from each channel’s lookup table, and the index used to look up the channel values was given by the most recent reading from one of the sensors.  The final color of each LED is given by this function:

byte figureColor(float scaledIndex, float colorAmount) {
  return overallAmplitude[int((waves * scaledIndex) + stringOffset) % QUANTA]
        * colorAmount
        * 2.55;


Thursday, November 24, 2016

Making a ROM hack of an old arcade game

(Addendum: Follow along my thought process below with this extra pedagogical material: )

An interesting work project, right?

I was invited to take my Giant NES Controller to a recruiting event for work taking place at a local brewery.  But you can't just have an NES controller without anything to play, right?  Thus, I pitched a couple ideas on custom games to go along with the giant controller since I didn't want participants playing anything standard either.  The thing they agreed to was to feature the Tapper arcade game, by Bally/Midway in 1983, but modified to show the brewery's logo instead of being Budweiser-branded like it was originally.

My handiwork, about 80% done, and with a tiny glitch.  Can you spot the remaining issues?

Now you might be thinking Tapper wasn't ever ported to NES, and that's correct.  However, with the help of the MAME arcade emulator and a Hyperkin USB->NES adapter, I could add the Giant NES Controller as an input to this old arcade game, and no one would be the wiser.  To facilitate this required lots of learning about MAME, though, because I assumed it would just work right away with my controller.  However, the inputs have to be set up to look for button presses coming from the controller; by default, it is only listening for the keyboard.  The Giant NES Controller is very unwieldy, so I set it up first with one of the regular NES controllers around the house.  The first one I tried was flaky, and I got scared for a moment that my project wouldn't work.  However, I grabbed a more reliable one that conveyed the correct button presses rock-solid, and luckily my Giant NES Controller worked just as well anyway.

Ready to look at lots and lots of hex code?

The Tapper hack was done thanks to the help of MAME's awesome tools and a hex editor.  I downloaded the ROMs for the game and figured out the naming convention they used to describe what the files are.  There are four program ROMs, two background graphics ROMs, at least one foreground graphics ROM, and several others including sound ROMs.  Among these, I only needed to edit 3 of the program ROMs and the background ROMs to change the logos on-screen.

The first thing to figure out was how the background tiles were arranged and how the colors were encoded in the background ROMs.  Luckily, MAME's tile viewer helped me see which tiles would be where in the memory.

A snapshot of tiles 0xF0 - 0x19F in Major Color Palette 1 using MAME's tile viewer.  By this time, I already replaced most of what I needed with Community.  Their original arrangement of tiles clearly doesn't lend well to seeing what the intended image was; maybe they were using something like Gray codes to optimize memory accesses.  I said "to hell with all that stuff" and opted for sequential tile addresses and image clarity.  I haven't noticed a performance difference. :-P

I opened up a hex editor (specifically Hexplorer, which has a color scheme like The Matrix which makes it really easy to detect large vs. small hex values in each byte) to look for similar patterns as what appeared in the tile viewer.  I discovered somewhat similar patterns, but not exactly 100% identical.  This is because each background ROM actually has a two-bit encoding per pixel of the tile.  One ROM contains a background color of index 0-3 and the other ROM contains the palette number of 0-3.  Thus, two different-colored pixels could have the same background color index but a different palette number, making them appear different in the game but indistinguishable from each other in the color-index file viewed in the hex editor.  I experimented with editing the tiles, and my first couple attempts did not yield the desired results, but eventually I got the hang of it.  It's a very tedious process to do by hand.

The first few bytes of both tile files.  One is already changing because it's the two-bit encoding of what color to use from the minor palette.  The other is not changing yet because the minor palette to use is desired to stay constant for the time being.

The first step is to see how many pixels each tile is in height, and then line up the hex editor so it seems like each change in data or each pattern seems to take up that many rows.  (I was afraid the graphics would be compressed with RLE at a minimum, but was extremely pleased that they used just a strange encoding scheme rather than any compression.)  This gives you a feel for how many bytes there are per row.  Note there are only two bytes per row, and with eight pixels per row, this means each pixel is encoded with just two bytes in each file.  It was easier to determine this by looking at the solid colors at the very beginning of the tile files rather than trying to spot a particularly distinctive tile with a letter or graphic because rendering in your head what (for instance) 0x55 looks like versus 0x17 just doesn't come quickly.

Really, it's all just a game of pattern recognition

The next thing was to rearrange the tile order on the screen so I could have it say Community.  Community's logo is shorter but wider than Budweiser, so I wanted the tiles remapped so I could maximize the space where I needed it.  Now on top of doing pattern recognition for the background ROMs to find the right tile number, I had to analyze the program ROMs to find out how they actually drew the backgrounds.  Luckily, this was fairly easy to do.  I found out that each tile is represented by two bytes, and there are 32*20 tiles on-screen per level.  Thus, there are 1280 bytes in each screen, and roughly 16K worth of screens.  But I didn't find that out until I used a bit of intuition while searching the ROMs for the clues from the tile viewer.

Think about this in terms of probability or from an entropy perspective.  The Zilog Z80 instruction set is comprised of a great many opcodes, making big chunks of code look random and uniform (as in a uniform distribution, where all byte values from 0 to 255 seem equally likely) to someone inspecting the machine code in a hex editor.  However, the background tiles will seem to take on much less of a uniform distribution, exhibiting tendencies to repeat the same or very similar numbers many times over.  You might also start to see some of the tile addresses called out from the tile viewer.  In fact, the byte highlighted in red is where the screen for the 1st level begins.

Because the tile information is in program ROMs 1 & 2 (zero-based, as in 0, [1, 2], 3), this presented yet another problem: whenever you change the contents of these ROMs without modifying the checksum in ROM 3, you will get a ROM error corresponding to whichever one(s) are wrong when you boot the game next.  I eventually learned how to modify the checksum, but not without using the MAME debugger.  This was a real trip, because I used the debugger to figure out when the memory address for any byte in the string "ROM ERROR" was read.  (I was extremely fortunate that they used ASCII encoding for this string, otherwise it might have never been apparent where this occurred!)  Once the debugger read this address, it continued to read the other addresses in sequence, so I stepped back in the debugger to find out what code caused all the bytes in the ROM to be read.  It ended up being somewhat of a hassle to figure the checksums each time, but then a mega hassle to program them in, especially for ROM 3, as you end up creating a circular reference.  For instance, if ROM 3 calculates its own checksum to be 1 more than what is programmed into itself, when you modify it to be 1 more, then it calculates it to still be 1 more than the new value you just wrote in. :-P  I knew I would be modifying the tile map in ROMs 1 & 2 a whole bunch before I was finally done, so I ended up replacing the code that verifies the checksum with a bunch of NOP instructions so that the game would never call the code that calculates the checksum at boot.

The final thing was to perfect the artwork.  Stacy hand-traced the Community logo scaled down to the right size and with the respective palette.  I wrote a program that would take a .BMP file consisting of this imagery, along with a "tile file" and "color file", and overwrite the part of the ROMs designated in the tile file with the appropriate 2-bit representation of the colors as dictated by the color file.  The color file mapped each color present in the bitmap to a background palette number for that ROM and a color index for the other ROM.  The reason I had to write this utility (in Python) was because the other tile editors on didn't seem to be up to the task of parsing old arcade ROMs correctly.  The closest I got was one that added an offset to each tile so that it was scooted left a couple pixels.  Also it seems like they aren't accustomed to having to deal with *two* asset files for a single tile.  I'll have to clean up this utility so it's a little bit more user-friendly and then share it.

Oh, and one other thing: there's yet another palette setting that gets you *four* groups of four groups of four. :-P  So now, besides the 2-bit color index and the 2-bit background palette number, there's actually a tile designator that selects which group of 16 colors applies to the tile.  This isn't in the background ROMs, but in the program ROMs.  What it seems like to me is that the tile ROMs start in a particular address in memory, and then get aliased (e.g. the contents are all the same between addresses 0x3500, 0x5500, 0x7500, and 0x9500) but the higher-order address bits actually indicate which set of 16 colors get used for that tile.  Part of that addressing scheme also seems to indicate if the tile should be drawn right-side up or upside-down, but I've only encountered about 6 spaces in the game where this happens and wasn't able to make it do exactly what I wanted.  Originally it had drawn in one tile the upper half of the Budweiser bow, and then mirrored it in the tile below, rather than basically duplicating that tile except drawing it upside-down.  I wanted it to be changed to a U shape, so I drew in a U into the background ROMs and then thought I changed the tile map to call the new tile un-reflected, but instead what I ended up with is two parallel bars (the top of the U).  So that still has yet to be figured out...

ROM Hacking Is For Players Only

As you can imagine, there was lots & lots of play testing along the way.  It is important to make sure all the graphics are working just as you expect, otherwise you might get embarrassed if someone gets farther along in the game than you did and sees tons of glitches.  The good news is you will have plenty of time to practice (assuming you're not up against a really close deadline).  I had saved states on MAME for Tapper all the way up to level 9, which I still haven't managed to beat by this article's posting date.  That's OK, because at the event, I was sure someone would get up even higher than that, but most people didn't even make it past level 1!  A couple of my coworkers at the recruiting event challenged me to see what kind of score I could get on Tapper, but by the time I finally lost, they clearly got sick of watching me and had wandered off. :-P  I managed about 25,000 as my highest score that night with the giant NES controller but the next best person only got about 6,000 or so.

I ended up installing RetroPie onto a 64GB SD card in a Raspberry Pi, and then I copied the Tapper hack from a USB stick into the right directory on the file system.  After restarting RetroPie, it recognized Tapper as a legitimate option, and I was grateful that MAME's own internal checksums did not stop me from running the game!  On my laptop where I was making the hack, I had to open MAME with the command line argument to start Tapper, because loading the hacked Tapper through the regular menu would cause a fatal error telling me the expected checksums mismatched.

So yeah, that's the long story of how a ROM hack gets done... Anyway, I have set up a class at the Dallas Makerspace to go over these techniques in greater detail on 12/4/2016 at 3 PM local time.  Join me if you're interested in learning more!

(EDIT: In case you missed the class... I ran it again as a livestream at LPGE 2017 :-P and here are the slides from that version: Good luck, and let me know what you make!)