Sunday, October 22, 2017

Building a Seeburg Wall-O-Matic Interface (Part 1)

Introduction

Last year we moved into a house that had some interesting touches left by a previous owner. Most notably, there was a "play room" decorated in the style of a 50's Diner. It had a booth, table, chairs, and plenty of decoration. We joked that this room's decor was what sold us on the house!


In any case, one notable thing missing from this room was a jukebox! Or at least, taking things slightly more sensibly, the jukebox controller that such diners often have sitting at their tables. It was at this point that I started learning all about the iconic Seeburg Wall-O-Matic.



Flash forward a year, and I was finally in the process of resurrecting my electronics workbench. I started watching a few too many EEVblog videos, built a shelf/bench setup using components from Ikea, unpacked all the gear I'd kept in boxes for a few too many years, and even made a few upgrades.

 
 
The one thing I desperately needed? Projects! Given that I knew I was going to have a lot of free time coming up in the near future, I reopened my research into the Wall-O-Matic and began to scour eBay.

Background Research

One of the first things I stumbled across were these commercial "products" designed to provide a modern interface from the wallbox:

CD Adapter
Wallbox2mp3

Unfortunately, these projects were less than desirable for my tastes. I was also looking for a project, not an off-the-shelf solution. These devices also seemed a bit dated, of limited availability, and quite proprietary. They also seemed to focus on playback a bit too "locally," rather than using the wallbox as an actual remote for a real stereo system. My house had in-wall speakers installed in many rooms, including the "diner" room, and I really wanted to use those. Since I had already connected many of my in-wall speakers to a Sonos rig, I kept wondering if there was a way I could just use that.


The next thing I did was dig into these hobbyist projects which seemed much closer to what I actually wanted to accomplish:

Wall Box SONOS Controller [Stephen Devlin]
Seeburg Wall-O-Matic [Retro Future Electrics]
Raspberry Pi Project – A 1960s wallbox interfaced with Sonos [Phil Lavin]

One common theme among these projects was simplicity. Minimal components to interface the wallbox to a Raspberry Pi, and minimal work to control a Sonos system based on the result. They also provided enough schematic and component details to give me a tangible starting point. Even if I decided to take a different path with my own project, at least I had a good foundation to build upon.

Project Goals

So thinking through what I wanted to accomplish with this project, I decided I wanted to build a device that could do the following:
  • Provide power to the wallbox
  • Read the signal pulses, and decode them into a song selection
  • Enqueue selected songs with my Sonos system, simulating the functionality of a jukebox
  • Electronically toggle the coin switches, so that inserting actual coins would be optional
At a lower level, I also knew I wanted to take things seriously in the design of the circuit I was going to use to accomplish all of this. That meant:
  • Complete and detailed schematic
  • Complete and detailed BOM (bill-of-materials)
  • Real fabricated PCB (printed circuit board) design
(The BOM and PCB being things that I'd never actually done before. Every prior circuit of mine was a hand-constructed mess of wires on a pre-drilled pad-per-hole PCB. Thankfully, in this day and age, doing it "right" is now quite accessible.)

I'll attempt to break this blog series apart based on the major progression of this project. I may not discuss things in the actual order that I did them, since there was a lot of back-and-forth between the various elements. However, it should flow in an order that makes sense. Most likely it'll be something like this:

Sunday, August 16, 2015

BlackBerry 10: Tracking the Virtual Keyboard from Cascades

There are things in BlackBerry 10 that are relevant to the UI of an application, which are not directly exposed via the API for the Cascades UI framework. One such thing is the state of the virtual keyboard. While you can infer this by the focus state of the text fields on a screen, that only takes you so far. Sometimes you really just need to know whether the keyboard is visible and how tall it is. Fortunately, they actually did expose an API for this through BPS.

What I'll be showing in this article is how you can wrap this event-providing BPS API for use from within a Cascades UI. In order to do this, we'll have to do several things:

Saturday, October 18, 2014

BlackBerry 10: Multiple OS versions from one source tree

Since launch, we've been iterating through several major versions of the BlackBerry 10 OS (10.0, 10.1, 10.2, 10.2.1, 10.3, and soon 10.3.1). Given that many users can't or don't upgrade immediately, and some never upgrade at all, this means we now have a wide variety in the field. While developers often want to provide quality support for the latest OS version, they also don't want to cut off support for older ones.

To keep the latest version of your app available across the full range of OS versions that users are running, it takes a few tricks. I figured it was about time to start writing up some of the tricks I've used to manage this.


Sunday, May 04, 2014

Tips for Hub Integration on BlackBerry 10

A central feature on the BlackBerry 10 platform is the "BlackBerry Hub." This is the unified inbox of the device, where users expect to see all their messages and notifications. Starting in OS 10.2, there is now a (limited access) public API for integrating with this feature. Apps that integrate with the hub are able to provide their own icon, category, and actions within it. Apps that don't are limited to posting fairly simple notification items. If you develop an app that is messaging-oriented, users are likely to want you to become hub integrated.

Monday, October 24, 2011

Qt for the BlackBerry PlayBook

At the keynote to the BlackBerry Developer Conference last week, two very interesting things were announced.  First, the BlackBerry PlayBook Native SDK is finally in public release (it had previously been in a semi-closed beta).  Second, RIM unveiled the Native Open Source Components Initiative on GitHub.  This GitHub site includes ports of many open source libraries to the PlayBook, including the Qt Framework!  The only real downside here is that all they've done so far is to push out the code.  No how-to documentation has been provided.  Therefore, I'm going to attempt to give a walkthrough for setting yourself up to use their Qt port for PlayBook development.

Sunday, October 02, 2011

The mythical $800 hammer

I'm currently at the cusp of a major job transition.  For many years, my career has revolved around the world of Gov't contracts.  This began with a brief but meaningful stint as a federal employee, and has continued as a long journey through the world of Gov't contracting.  I've had a lot of personal reservations about this world, mainly in terms of the dynamics of the business models it supports.  With all the doom and gloom currently overshadowing the federal budget, and the industry downsizing and reorganization that is likely to follow, I think its time for me to move on.


For the last few years, I've spent a lot of my personal time on a major BlackBerry software project.  At many points, this personal project has provided far more interesting technical challenges and professional growth opportunities than what I was actually being paid to work on.  Soon I'll be flipping it all around, and doing mobile software development as my actual day job.  I'm curious to see how it will go, and especially how I'll sink or swim in the faster-paced world of non-gov't software development.

That all being said, I'd like to offer some slightly tongue-in-cheek commentary on why everything the Gov't buys is so expensive:

Where does the $800 Hammer come from?
  • First you need to have a DARPA program to fund research into advanced nail insertion technology (ANIT)
  • Then you have some Federally-Funded Research and Development Center (FFRDC) do an involved trade study that concludes that a simple hammer is preferable to the DARPA-developed ANIT prototype.
  • A program executive office (PEO) now hosts an industry day presentation on the US Army's Tactical Hammer Needs to the tool-making industries
  • The PEO now publishes a Request For Information (RFI) to solicit information from industry on steel hardening and handle-forming capabilities that could be used for the hammers
  • Finally a Request for Proposal (RFP) is published, along with a detailed performance spec, requirements list, and statement of work
    • There are a limited number of hammers desired, with options for buying more later
    • They also have to conform to various Military standards that no tool you'd buy at Home Depot would ever have to conform to
    • They need to be made in the US in a facility that holds the proper security clearances
  • The PEO finally selects one of the submitted proposals, awarding the contract
    • One of the loosing contractors decides to file a formal protest, and drags the process out longer
    • Eventually a settlement is made, and the selected prime contractor takes them on as a subcontractor for handle-to-head integration tasks
  • After several rounds of requirements engineering, systems engineering, and product R&D, along with approvals at preliminary and critical design reviews (PDR/CDR), the government gives the go-ahead to enter Low-Rate Initial Production (LRIP)
  • Testing eventually finds issues in the initial batch. Some design changes are made, costs are passed along, and eventually the hammer enters full-rate production (FRP)
  • Following training and deployment, the MK42 Tactical Nail Insertion Device (code-name "Hammer") is deployed into the field
  • Meanwhile, nails are getting tougher, and follow-on program for the MK49 Objective Nail Banger is announced

Friday, March 07, 2008

C# WTF: Abuse of events

Someone actually noticed my last post, so I'm going to start putting more of that stuff on here.

Getting a property through events:

Common uses:

  • Pretending to decouple classes for no apparent reason.



public delegate int GetSomeValueDelegate();

 

class Foo

{

    public event GetSomeValueDelegate GetSomeValue;

 

    public void DoStuff()

    {

        /* . . . */

        if (this.GetSomeValue != null && this.GetSomeValue > 4)

        {

            OtherStuff();

        }

        /* . . . */

    }

}

 

class Bar

{

    private Foo foo;

    private int someValue;

 

    public Bar()

    {

        foo = new Foo();

        foo.GetSomeValue += new GetSomeValueDelegate(this.HandleGetSomeValue);

    }

 

    public void Run()

    {

        foo.DoStuff();

    }

 

    private int HandleGetSomeValue()

    {

        return this.someValue;

    }

}



Common variants:

  • Having the event return a reference to the Bar instance that manages Foo.

  • Having the event return a property of singleton that is accessible from both classes.





Externalizing logic through events
Common uses:

  • Decoupling a class from its internal logic.



public delegate void ResultsEventHandler(string[] results);

 

class Foo

{

    public event ResultsEventHandler ResultsEvent;

 

    private string[] resultsData;

 

    public string[] Results

    {

        get { return this.resultsData; }

        set { this.resultsData = value; }

    }

 

    public void DoStuff()

    {

        string[] results = PerformOperation();

        if (ResultsEvent != null)

        {

            ResultsEvent(results);

        }

    }

}

 

class FooManager

{

    private Foo foo;

    private Bar bar;

 

    public FooManager()

    {

        foo = new Foo();

        bar = new Bar();

        foo.ResultsEvent += new ResultsEventHandler(this.OnResultsEvent);

    }

 

    public void DoStuff()

    {

        foo.DoStuff();

        ProcessResults(foo.Results);

    }

 

    private void OnResultsEvent(string[] results)

    {

        foo.Results = results;

        bar.Data = results;

    }

}