Saturday, February 26, 2011

dreams of a mini MAME cabinet bring out my c++ chops

so I wanna build me a mini MAME cabinet. something along the lines of this. but i'm cheap, and i can't justify dropping $350 just to get my old-school street fighter turbo on. so i dug out an old linux laptop and got xmame running on it. surprisingly it seems to hold up pretty well. so i gotz the screen and brains part of the cabinet accounted for.

a'course, you can't have a MAME cabinet without a nice set of arcade controls (or two sets ). i'm not _too_ picky, so the x-arcade joystick and button parts will do just nicely. $20 per player is hard to beat.

and to interface all those nice buttons to the laptop there's the teensy++ usb microcontroller board. this little guy (among other cooler, more complex microcontrollery things) can take physical button presses and translate them into usb keyboard presses my little linux box can understand. and with the teensyduino add-on, i can program this thing with easy-to-use arduino environment. w00t!

there's only one problem: the Keyboard class that's provided can only do up to 6 simultaneous virtual keypresses, not enough if i'm gonna wire up two sets of controllers on this thing.

never to fear, my c++ skills are here. i dug in to the directory where teensyduino got installed and added a generic send method to the Keyboard class. here's the deets (i copied most of send_now() and made a few modifications) (unfortunatly, i don't have a teensy board yet, so i don't even know if this poo is gonna work. who want's to by ol' dick a birthday present? =]):

usb_api.h
class usb_keyboard_class : public Print
{
 public:
 virtual void write(uint8_t);
 void write_unicode(uint16_t unicode_code_point);
 void set_modifier(uint8_t);
 void set_key1(uint8_t);
 void set_key2(uint8_t);
 void set_key3(uint8_t);
 void set_key4(uint8_t);
 void set_key5(uint8_t);
 void set_key6(uint8_t);
 void send_now(void);
 // here's the method i added
 void send(uint8_t, uint8_t*, uint8_t);
 private:
 void write_keycode(KEYCODE_TYPE key);
 void write_key(uint8_t code);
 uint8_t utf8_state;
 uint16_t unicode_wchar;
};

usb_api.cpp
void usb_keyboard_class::send(uint8_t modifier_keys, uint8_t* keys, uint8_t n_keys)
{
        uint8_t i, intr_state, timeout;

        if (!usb_configuration) return;
        intr_state = SREG;
        cli();
        UENUM = KEYBOARD_ENDPOINT;
        timeout = UDFNUML + 50;
        while (1) {
                // are we ready to transmit?
                if (UEINTX & (1<<RWAL)) break;
                SREG = intr_state;
                // has the USB gone offline?
                if (!usb_configuration) return;
                // have we waited too long?
                if (UDFNUML == timeout) return;
                // get ready to try checking again
                intr_state = SREG;
                cli();
                UENUM = KEYBOARD_ENDPOINT;
        }
        UEDATX = modifier_keys;
        UEDATX = 0;
        for(i = 0; i < n_keys; i++){
            UEDATX = keys[i];
        }
        
        UEINTX = 0x3A;
        keyboard_idle_count = 0;
        SREG = intr_state;
}

here's what i got on how to use this shiny new method:

arcadestick.pde
/**
  * Compile with Teensduino
  * Board: Teensy++ 2.0
  * USB Type: Keyboard + Mouse
  */

#ifdef STR_PRODUCT
#  undef STR_PRODUCT
#endif
#define STR_PRODUCT L"DeathByAutoScroll Arcade Stick (X-Arcade Dual Compatible)"

#define MAX_SIMULTANEOUS_KEYS 25

uint8_t keys[MAX_SIMULTANEOUS_KEYS];
uint8_t modifier_keys;
uint8_t n_keys;

void setupPins(){
  // no need, all pins are defaulted to INPUT
}

void reset(){
  modifier_keys = 0;
  n_keys = 0;
}

void addKey(uint8_t key){
  keys[n_keys++] = key;
}

void addModifierKey(uint8_t key){
  modifier_keys |= key;
}

void setKeys(){
  // convert physical button presses to keyboard keys presses
  // follows x-arcdae dual-joystick keyboard mapping scheme
  // see http://www.xgaming.com/service/ServiceFiles/X-Arcade%20Tankstick%20Manual%20USA.pdf
  
  // player1 buttons on PORTD
  // player2 buttons on PORTC
  // player1 direction on lower nibble of PORTA
  // player2 direction on upper nibble of PORTA
  
  // player 1
  // direction
  //p1 up
  if(PIN_A0){
    addKey(KEYPAD_8);
  }
  //p1 down
  if(PIN_A1){
    addKey(KEYPAD_2);
  }
  //p1 left
  if(PIN_A2){
    addKey(KEYPAD_4);
  }
  //p1 right
  if(PIN_A3){
    addKey(KEYPAD_6);
  }
  // buttons
  //p1 1
  if(PIN_D0){
    addModifierKey(MODIFIERKEY_LEFT_CTRL);
  }
  //p1 2
  if(PIN_D1){
    addModifierKey(MODIFIERKEY_LEFT_ALT);
  }
  //p1 3
  if(PIN_D2){
    addKey(KEY_SPACE);
  }
  //p1 4
  if(PIN_D3){
    addModifierKey(MODIFIERKEY_LEFT_SHIFT);
  }
  //p1 5
  if(PIN_D4){
    addKey(KEY_Z);
  }
  //p1 6
  if(PIN_D5){
    addKey(KEY_X);
  }
  //p1 start
  if(PIN_D6){
    addKey(KEY_1);
  }
  //p1 coin
  if(PIN_D7){
    addKey(KEY_3);
  }
  
  // player 2
  // direction
  //p2 up
  if(PIN_A4){
    addKey(KEY_R);
  }
  //p2 down
  if(PIN_A5){
    addKey(KEY_F);
  }
  //p2 left
  if(PIN_A6){
    addKey(KEY_D);
  }
  //p2 right
  if(PIN_A7){
    addKey(KEY_G);
  }
  // buttons
  //p2 1
  if(PIN_C0){
    addKey(KEY_A);
  }
  //p2 2
  if(PIN_C1){
    addKey(KEY_S);
  }
  //p2 3
  if(PIN_C2){
    addKey(KEY_Q);
  }
  //p2 4
  if(PIN_C3){
    addKey(KEY_W);
  }
  //p2 5
  if(PIN_C4){
    addKey(KEY_E);
  }
  //p2 6
  if(PIN_C5){
    addKey(KEY_LEFT_BRACE);
  }
  //p2 start
  if(PIN_C6){
    addKey(KEY_2);
  }
  //p2 coin
  if(PIN_C7){
    addKey(KEY_4);
  }
}

void setup(){
  setupPins();
}

void loop(){
  reset();
  setKeys();
  Keyboard.send(modifier_keys, keys, n_keys);
}

now all i need is a sheet or two of MDF, a little cash for the parts, and a lot of free time to make it all happen.

Tuesday, January 18, 2011

muscling through a minor migraine while staring at a monitor

i woke up with a a headache this morning. what a way to start the day, eh? and it didn't let up when i finally arrived at the office, as late as i already was. what's worse is that any sort of light in my eyes made my head pound more. now, i can't afford to take the day off of work, or even just an extended morning break, i've got deadlines to meet.

here's how i muscled through that mildly malicious migraine:

step 1: treat the damn thing

everything you learned on how to treat a hangover is fair game here. this morning's recipe for success:
  • two tabs of tylenol (your preferred headache medicine will do)
  • get something to eat, the fattier the better (all i had was a bit of pound cake, but that's better than an empty stomach)
  • hydrate hydrate hydrate, and when you're done with that, hydrate some more
  • if you drink coffee, by all means chug that coffee!! you can kick that caffeine habit some other day

step 2: take it easy while still being productive

with a headache even thinking hurts, which is a problem if your job relies on brain activity. in my line of work, even the most menial of coding task takes some brain power. the solution: don't think. while you wait for the drugs-food-water-coffee concoction to kick in, do your busy-work tasks. answer some emails. fire off that email to HR that they've been houding you about. make some notes in your pivotal tracker issues. or hell, just catch up on some lifehacker posts. =]

step 3: turn down the lights

i don't know about you, but when that headache kicks in i just can't stand bright light. i'm lucky that the fluorescent tubes in my section of the office have been out for the past two weeks. i still have a big bright iMac monitor i have to stare into, though, and it seems like every application and every web page insists on having a bright white background color. never to fear, there's ways to tame it the beast:

  • start with your desktop background. you can go the quick-and-dirty route with simple all back, or go with any dark wallpaper of your choosing (my personal favorite is the cli cheat-sheet useful wallpaper).
  • any text editor worth its salt will let you change the font and background color scheme. Some MacOSX favorites: in Xcode head over to Preferences : Fonts and Colors, and go with the Midnight theme

    In TextMate try out the Twilight theme (no sparkly vampires here, sorry ladies). While you're at it, try out the Homebrew theme in Terminal
  • try out arc90's Readability bookmarklet with the Inverse style to tame website's colors, not to mention make pages more, well, readable with no more cruft and clutter around a page's actual content
  • if all else fails, invert your screen's colors. this option is usually buried in your computer's accessibility setting, sometimes called "high contrast" mode. If you're on a Mac you can go into inverted color mode with a ctrl-opt-command 8

Tuesday, January 11, 2011

how Dropbox saved my command line - extended

i came across a clever blog post on the 'tubes. it described how one could harness the file-syncing powers of Dropbox to keep one's bash shell config files all lined up across several machines. this was just the ticket to keep my mac laptop, my work imac, and my linux box command lines all in harmony with each other.


of course, i couldn't just leave well enough enough alone.


MacOSX hostname discrepancies

the first problem i ran into was reliably getting a machine's hostname on the MacOSX side. the network at the office insists on setting my imacs's hostname dynamically, and it's never the same between bootups. luckily i stumbled on a command that'll get the local hostname of a MacOSX computer:


Listing 1: getting the local hostname in MacOSX:

$ scutil --get LocalHostName


this will spit out whatever name you have set in System Preferences -> Sharing -> Computer Name, regardless of what the local networks says.


why not synced bin directories, too?

i have a handful of utility shell scripts that i had spread out across my different machines. similar to syncing up the config files, i came up with a way to consolidate all those scripts into a single shared ~/Dropbox/sh/bin directory. i also have a ~/Dropbox/sh/bin/Darwin directory for my MacOSX-specific scripts, and a ~/Dropbox/sh/bin/Linux for my Linux scripts, all of which my PATH environment variable appropriately points to. See Listing 2 to see it in action.


older Dropbox versions can't remember which scripts are executable

the official stable version of Dropbox on Linux maxes out at 0.7.x, which unfortunately doesn't sync the executable bit on files. that means all that effort getting my bin directories would be for naught. all is not lost! there exist Dropbox beta builds that go up to 1.0.10, which do support executable-bit syncing. the easiest way to get the latest dropbox beta builds for Linux is with a utility by the name of dbupdate. Note: if you have Dropbox installed for a single user (e.g. not system-wide, like how crunchbang linux does it by default) you'll have to run dbupdate manually from the command line. problem solved!


the goods

without further ado:


Listing 2: bashbootstrap:

# bashbootstrap
if [ -z "$PS1" ]; then
 return
fi

localhostname() {
 case $(uname) in
  "Darwin" )
  echo $(scutil --get LocalHostName)
  ;;
  "Linux" )
  echo $(hostname)
  ;;
  * )
  echo $HOSTNAME
  ;;
 esac
}

dropboxshelldir=~/Dropbox/sh
dropboxdir=$dropboxshelldir/etc

masterbashrc=$dropboxdir/bashrc
masterbashrcpost=$dropboxdir/bashrcpost
osbashrc=$masterbashrc-$(uname)
localbashrc=$osbashrc-$(localhostname)

masterbin=$dropboxshelldir/bin
osbin=$masterbin/$(uname)
localbin=$osbin/$(localhostname)

echo -n "Applicable shell configs: "
for bashfile in "$masterbashrc" "$osbashrc" "$localbashrc" "$masterbashrcpost"; do
 if [ -r $bashfile ]; then
  . $bashfile
  echo -n "$(basename $bashfile) "
 fi
done
echo

echo -n "Applicable bin directories: "
for bindir in "$masterbin" "$osbin" "$localbin"; do
 if [ -d $bindir ]; then
  PATH=$PATH:$bindir
  echo -n "$(basename $bindir) "
 fi
done
echo

# Set convenience aliases
myed=${VISUAL:-${EDITOR:-vim}}
alias editbashrc="$myed $masterbashrc"
alias editbashrcpost="$myed $masterbashrcpost"
alias editosbashrc="$myed $osbashrc"
alias editlocalbashrc="$myed $localbashrc"

a few odds-and-ends

  • MacOSX gets confused with .bash_profile and .bashrc, check bash_profile vs. bashrc for a solution
  • need some idea on how to spruce up you command line? lifehacker terminal tweaks is a good place to start
  • Don't have a Dropbox account yet? Why not use this dropbox referral link to get an extra 250MB of sync space gratis! (full disclosure: i'll get and extra 250MB of space, too =] )

Sunday, September 12, 2010

experiment: a week's free time without internet research

i'm a victim of the internet.

god bless you, internet, for providing instantly assloads of information regarding nearly any subject imaginable. wikipedia, you've been a great friend in fueling nights of curiosity binges for this trivia whore; everything from C macros leading to the design history of Objective-C, to the Danger Doom discography leading to the next planned Deltron 3030 album, you make it so easy to dive into your many information rabbit-holes and play for hours on end.

but i've burnt out. i've heard it called "information overload". i like to think of it a symptom of "jack-of-all-trades-master-of-none"ness. i have plenty of interest, and the wonders of the wired make it trivial to gather more and more information on any of them, then (attempt to) stuff all that info in my head for some later use.

one problem of course is, if i don't use it i lose it, so everything i put in, if i don't do anything with it it just fades away as if i never learned it in the first place. the other danger is that i tend to use this "research" as distractions from actually accomplishing stuff, or from discovering, delving into, refining, and clarifying my own deeper personal thoughts.

so my resolve this week: no internet research outside of work hours.  i can't survive a complete internet blackout though. i need my wired to comunicate with everyone i care about and who care about me (a week without katie is torturous enough). aside from that, this week's after-work free time internet usage i'm going to limit to downloading games so as to rediscover some of my classic favorites (starting with zelda: a link to the past), discovering or rediscovering music and movies, looking up guitar tab to get more songs under my fingers, and more frequently spilling my thoughts and confessions onto this here blog.

shit, i don't know what's gonna happen. i don't even know if i can make it.

no more idle research, spike. do. or do not.

Thursday, September 2, 2010

transition from meager dad to rich dad

quite suddenly i've found myself, out of all those in my immediate family, to be making the most money. "don't be surprised, spike", you may say, "that's what that fancy computer science degree gets you". yeah, it's true, all those years of hard work in school and later in the workforce has finally started paying off, and in a big way. it's just a little strange, making more money than my old man, the one man i think so highly of and can never surpass. it feels odd.

and it's hard not to feel that it has all come so suddenly. just this time last year my contracting gig had no tasks for me and i found myself again without work and without income. not six months i was crashing on a homey's couch in san francisco, banging out code in his basement, thinking life couldn't get much better. these days i'm back at a stable office job, complete with my own desk, health insurance, and the biggest paychecks i've ever seen signed over to me.

my life seems to be on the verge of transition from meager dad to rich dad. i've tended to live my life in a pretty modest fashion so far, but i can't continue with my overly modest ways if i am to break out of this modest existence. time to start doing what rich dads do.

there's the big question. never being one myself, i can only make guesses what a rich dad does. here's my first incomplete stab at it: what does a rich dad do?
  • a rich dad doesn't have outstanding student loans
  • a rich dad puts away money for his kid's college fund
  • a rich dad helps out his parents and sisters when they need it, just as they helped him when he was in need
  • a rich dad helps out those friends in need who in the past propped him up when he was down and out
  • a rich dad loves the town and house in which he dwells
  • a rich dad dresses well (a combination of a shopping spree with raych and a shopping spree with katie should spruce up my wardrobe quite nicely)
this transforming into rich dad status certainly won't happen overnight. i've certainly a backlog of things to handle and take care of. i just need to start laying out a path, however vague, in which to follow forward.

did i leave anything out? am i totally off base? dear reader, won't you leave a comment?

Wednesday, August 25, 2010

"a new place to get my coding on", or "when RL happens"

i'm finally back at an honest-to-god full-time coding gig, and boy is it refreshing. you may have heard of my new employers before.

don't get me wrong, doing the indie thing with my boys at Ayumusoft was some of the best times of my coding career. i'm forever indebted to them for the opportunity i was afforded there, and the great times we had together. hell, my work at Ayumusoft led directly to landing my new gig. big-ups to Dani and Simar for bringing me aboard, and for believing in a guy and his skills.

i'm overdue for a regular paycheck and health insurance, though. my tyke is long overdue for that. and being at a place with a huge budget which lands an iMac, iPhone4, and an iPad on my desk, that's pretty nice too.

a full-time gig means my online presence has suffered. i haven't touched ye old blog in over a month. i check up on twitter only once a day and only on a good day. even my own flesh and bits FortuneBOT, i can go a week without taking the time to see what he says. a far cry from my contracting and unemployed days, when i lived almost exclusively on twitter and facebook.

i fib. my new full-time status isn't all to blame for my recent online absence. RL happened. i get to see my boy a lot more these days, once a weekend (hopefully soon a lot more than that); i've got an effing amazing, fun, and beautiful girl i get to call my girlfriend; and we're plenty busy trying to find an apartment where we can fully enjoy LA city living (as our times in SF has shown us: working, living, and playing in the same place is the only way to go).

i leave you now with a recent observation: new computer programming gigs, they always seem to begin the same way.

day one: "here's your new desk and new computer. spend the whole day installing a bunch of software, we'll get something for you to do tomorrow."

day two: "we still don't have any specific tasks for you to do. just grab the project from the SVN repo and start poking around the code."

day three: "how you like the codebase?" lots of hacks, but hey that's the nature of shipping software. i'm just glad i know how to refactor shit. "good good. here's some things the designer wants and/or needs fixed." on it.

lather, rince, repeat day three

Saturday, July 17, 2010

my recent techie prowess, plus HTTP hacking with curl, and the joy that is fortune

being between gigs at the moment, i have to keep my days busy lest grow used to inactivity, or worse, i slowly lose my mind (any more than i already am). that means working on my own projects, which include a couple of code-related things i'm working on, and a few non-code related things (more on the latter in the future).

on the coding front, i'm still putting in a little bit of work into Corner Flower Shoppe. today i helped to finally get Google Analytics sorted and working (woot!).

then there's my personal baby, FortuneBOT. for the uninitiated, fortune is a classic UNIX program that greets you with a random quote; sometimes like a fortune cookie, sometimes nerdy, sometimes offensive, but more often than not grin-inducing. FortuneBOT is literally fortune brought to you over twitter.

the problem with the way FortuneBOT is set up at the moment is that whatever quotes he serves up is dependent on what server he resides on. this was fine when he lived on a tiny little server at home (an NSLU2, or slug, running SlugOS). reliability concerns forced me to move him onto a Dreamhost server. don't get me wrong, he's quite happy living there, and since hasn't missed a scheduled tweet due to untimely power outages. since moving to Dreamhost, however, FortuneBOT has since cleaned up his potty-mouth: no more offensive quotes! and those were some of my favorites!

so long ago i decided FortuneBOT needed to be rewritten, from the ground up, and forgo it's humble 20-line python script roots. well, now i have the free time to do just that, and use it as an excuse for a crash-course in ruby-on-rails and HTTP / REST services (in a desperate attempt to stay relevant).

the REST part of the equation means i have to be able to GET responses from the web service in various formats, not just as HTML. it turns out cURL, along with a little header hacking thanks to the -H switch, makes for an easy way to do just that, all from a command prompt. to make the whole testing process easier i whipped up a quick sh script to do the dirty work for me.

Listing: curl.xml
#!/bin/sh
curl -H 'Accept: application/xml' $@

i've also made curl.json and curl.text scripts for JSON and plain text responses, respectively. you're welcome, internets =]

on that note, i'd like to leave you now with a quote from fortune itself, one of the things it does best (and something followers of FortuneBOT are currently missing) - a dirty limerick:

There once was a man named McSweeny
Who spilled some raw gin on his weeny.
 Just to be couth,
 He added vermouth,
And slipped his girlfriend a martini.