Vortex Race 3 TKL LED Programming for Mac

I decided to switch to my Vortex Race 3 TKL for a more programming-centric job from the Vortex Tab 90M that felt a little better for email and spreadsheets. The Race 3 has Cherry MX Silent Reds vs. the Vortex Tab 90M’s Cherry MX Silent Blacks.

A couple of things that were a little bit difficult to follow were:

  1. How to set up the Race 3 for Mac (it had been used on a Windows PC most recently and never really used on a Mac). This Reddit thread gives some suggestions on how to optimize that.
  2. How to program the LEDs (for just basic effects):

The LED programming was fairly simple once I understood it (see here for a copy of the manual). The cool LED effects when you type are accessible by pressing the Pn key + one of the ‘1’ through ‘5’ keys. ‘4’ and ‘5’ have multiple effects:

Pn + ‘4’ cycles different “display single color LED mode”s which means that the interactive LED effects appear in context with your

  • [no effect?]
  • Interactive mode – keys light up as you type.
  • Flash vortex mode – keys pulse around the keyboard originating from your keystrokes
  • Aurora mode – keys pulse in color around the keyboard originating from your keystrokes

Pn + ‘5’ cycles different “Display full color LED mode”s which means “display on all the keys regardless of context”:

  • [no effect]
  • Full key light mode – just 100% on
  • Breath mode – keyboard pulses
  • Vortex mode – RGBs cycle in different phases with each other.
  • Rain drop mode – random drops of “color” appear on the keys

Pn + X – brightness down for the above effects

Pn + V – brightness up for the above effects

Pn + [< key] and Pn + [> key] are LED speed up and down.

Removing a Broken Headphone Plug from an iPhone

Broken Headphone Plug and iPhone. 😱

The headphone jack is a pretty key port for anyone not on an iPhone 7 or later, so a broken headphone plug shoved in the jack renders a phone pretty much useless. It’s also too small a space for needle nose pliers.

So what do you do if something breaks off in it? Well, searching around on iFixit lead me to the existence of a headphone plug extraction tool (for $50!!!) Unfortunately, my daughter actually uses her phone for school, so the wait (plus $50) was unacceptable if we could find another solution.

Other solutions?

  • Crazy glue the broken headphones to its counterpart (and risk sealing it up for good?!)
  • Small drill bit.
  • Bamboo toothpick.
  • Soda straw cut to squeeze around the broken plug.

Ok, the soda straw sounded reasonable and, if nothing else, low risk. So I tried with some IKEA straws and got close to extracting a piece out, but no further. The problem was that there was too much in the plug. (The headphone plug is concentric cylinders that had been shoved all the way in.)


So I kept reading… CUTICLE SCISSORS! My wife had a small pair that worked well to extract one of the pieces. Grab what you can with the scissors, push the straw around the remainder and tug to extract. The plug tip slid far enough out in this process to grab with my fingernails.

Below is the final carnage with extraction tools.

Cuticle scissors, straw, headphone plug pieces

Go Concurrency Benchmarking on a Raspberry Pi

In hindsight, no one claimed that a Raspberry Pi of any model was a powerhouse machine. However, I had thoughts about how to benchmark computing power after leaving Dreamhost and noticing that even tar and gzipping my WordPress installs performed like an ancient machine despite the processor statistics. That made me think about a raw benchmarking metric that could deployed anywhere. I was also learning Go and trying to understand Go concurrency. I ended up with a “concurrency” of 2 because the lower power systems didn’t get any more out of an additional goroutine.

package main
import (
func main() {
var before string
var after [64]byte
var base64Encoding string
var result chan string = make(chan string)
var resultString string
var addOnStart int64
start := time.Now()
addOn := 0
concurrency := 2
sem := make(chan bool, concurrency)
for {
before = fmt.Sprintf("Message%d", addOn)
after = sha3.Sum512([]byte(before))
base64Encoding = base64.StdEncoding.EncodeToString(after[:])
if strings.HasPrefix(base64Encoding, "TEST") {
fmt.Printf("%d seconds\n", int64(time.Since(start)/time.Second))
fmt.Printf("%d: %s\n", addOn, base64Encoding)
addOnStart = 0
start = time.Now()
for {
sem <- true
go scan1000000(addOnStart, result, sem)
select {
case resultString, _ = <-result:
fmt.Printf("%d seconds\n", int64(time.Since(start)/time.Second))
func scan1000000(addOnStart int64, result chan string, sem chan bool) {
var before string
var after [64]byte
var base64Encoding string
defer func() { <-sem }()
for i := addOnStart * 1000000; i < (addOnStart+1)*1000000; i++ {
before = fmt.Sprintf("Message%d", i)
after = sha3.Sum512([]byte(before))
base64Encoding = base64.StdEncoding.EncodeToString(after[:])
if strings.HasPrefix(base64Encoding, "TEST") {
result <- fmt.Sprintf("%d: %s\n", i, base64Encoding)

view raw
hosted with ❤ by GitHub

The program requires 13,135,013 sha3 hashes and conversions to base 64 to come up with a string that starts with “TEST”.

My work workstation’s output:

[Specs: Late 2013 Retina MacBook Pro 15″, 2.3 GHz Core i7 – (I7-4850HQ)]

  • Single thread: 16 seconds
  • Concurrency of two: 10 seconds
  • Compared with PassMark:
    • 9066
    • Single thread 1964

A Late 2011 MacBook Pro 13″, 2.4 GHz Core i5 (I5-2435M):

  • Single thread: 34 seconds
  • Concurrency of two: 19 seconds
  • Compared with PassMark:
    • 3269
    • Single Thread 1347

A Core i3-5010U 2.10 GHz NUC (Windows 10 Pro)

  • Single thread: 27 seconds
  • Concurrency of two: 17 seconds
  • Compared with PassMark:
    • 3060
    • Single Thread 1171

A Mid 2009 MacBook Pro 13″, 2.26 GHz Core 2 Duo (P7550)

  • Single thread: 57 seconds (Originally was 83 on go1.3.3, but better results with 1.8.3)
  • Concurrency of two: 32 seconds (Originally was 80 on go1.3.3)
  • Compared with PassMark:
    • 1521
    • Single Thread 892

A ThinkPad 11e with A4-6210 APU (1.8 GHz – Windows 10 Home)

  • Single thread: 135 seconds
  • Concurrency of two: 65 seconds
  • Compared with PassMark:
    • 2143
    • Single Thread 697

Raspberry Pi 3B

  • Single thread: 1265 seconds
  • Concurrency of two: heat warnings!

For the purposes of this “performance” benchmark, there is definitely a non-linear relationship between a canned benchmark score and the score in a brute force operation that has a heavy calculation component. I’m also isolating only one aspect of system performance. There is a SATA SSD on the newest machine, a SATA HDD on the 2011 and 2009 machines, and an SD card on the Raspberry Pi. The RAM is different in every machine as well. Still, it was a fun experiment that motivated me to spend a little extra time in Go and learning Go Concurrency.

Using an Arduino to keep a Seiki 4K Display On

I love my Seiki 4k Display for writing code on my Mac. The one downside is that it times out and goes to sleep after 2 or 4 hours of inactivity (from the remote, not the screen). I decided to fix this problem in a somewhat complicated way: With an Arduino Uno that I already had, and an IR control kit.

I used the IR receiver to find the Seiki “Volume Up” and “Volume Down” codes, which appear to be structured like NEC codes. Those are hardcoded because I haven’t really bothered to refine the setup or code any more. The IRBlaster library uses digital out 3 for the IR sends, and I used digital 8, 9, and 10 for red, yellow, and green indicators to give some indication of where in the refresh cycle things are. The code as-is sends the volume up and volume down signals every hour or so, and the indicators start with a slow blink on red, a slightly faster blink on yellow, and a fast blink before remote send on green.

IR Blaster set up (with IR receiver partially wired in still)

IR Blaster set up (with IR receiver partially wired in still)


IRsend irsend;
int led = 13;
int red = 8;
int yellow = 9;
int green = 10;

void setup()
  pinMode(led, OUTPUT);
  pinMode(red, OUTPUT);
  pinMode(yellow, OUTPUT);

  pinMode(green, OUTPUT);

int choice(int i) {
  if(i > 1300) {
    return red;
  } else if (i > 900) {
    return yellow;
  return green;

void ledOn(int i) {
  digitalWrite(choice(i), HIGH);
void ledOff(int i) {
  digitalWrite(choice(i), LOW);

void loop() {
  while(true) {
    irsend.sendNEC(1086232679, 32); // seiki volume up
    irsend.sendNEC(1086206159, 32); // seiki volume down
    for(int i=1800; i >=0; i--) {

What should I do with this existing desktop?

I have a mostly custom built desktop, and want to replace it with adequately current hardware, but no real plans for gaming.

  • The IDE Hard Drives are going out.
  • On the existing desktop:
    • Windows 2000 is installed, but I rarely boot to it.
    • Ubuntu 9.04 is installed.
  • I have a SATA 250 GB drive that works perfectly fine, but which I have from another system which I upgraded to 2 x 500 GB.
  • The Antec case is a fairly nice, but dated, mid-tower ATX case.
  • I think the power supply handles SATA power.
  • The existing motherboard only supports IDE, up to a 3.06 Northwood core processor.
  • I currently do not have *any* Windows 7 installs.

I also have a Dell Desktop which is our main desktop in the home:

  • Windows XP
  • 3 GB of RAM
  • 2 x 500 GB SATA hard drives
  • 2.16 GHz [E6400?] Core 2 Duo processor
  • iTunes, media, and photos are on this box.

Some interests:

  • Windows 7 64-bit would be nice to play around with.
  • Would still like to end up with a Ubuntu install somewhere.

Some options that I’ve thought of:

  1. Upgrade the custom build (that’s a mobo/processor and ram minimally, even if integrated video)
  2. Get a recent refurb desktop, replace the Dell with it, and replace the custom build with a Dell
  3. Buy a Mac desktop, move the Dell downstairs.

More issues with my Lenovo T61

Here’s a nice shot of the nVidia driver context menu wackiness in windows XP. The longer a window is open, the more of these that appear. (Considering the window in question is Safari, that time span is probably 2-3 hours.)

Meanwhile, I spent 10-15 minutes trying to get the laptop to recognize that my external monitor was plugged in, and then trying to close windows for a graceful shutdown.

Can I just get a new laptop?

Major PC issues. VPN/Wireless/System not playing well together.

Laptop Replacements

Netbooks For Road Warriors On A Budget — netbooks — InformationWeek.  In the headline, the phrase “laptop replacment” is used.  The work laptop that I use on a daily basis is a “desktop replacement,” but I don’t want to have to pay for my own–yet I don’t want to be tied to my desktop’s location either.

If I could just get a laptop that was dirt cheap, yet had decent horsepower and disk space…

From the review, it looks like Asus is the primary option for my interests still.  As for the suggetions on gear, I don’t think I’m going for a rubberized roll-up keyboard.

Kryder’s law and hard drive pricing.

Hard Disk Historical Pricing (found from Kryder’s Law – A rule of thumb for hard drive growth).

It’s amazing that in March of 1986, $48/MB was the sweet spot for a hard drive.

By other milestones in my life:

By the time I started college in 1994, the cost was under $1 per MB.

By the time I started my first full time job in late 1999, the price for hard drives was $20 per GB!   (The cost of “high grade” flash memory now).

When my first daughter was born in August 2004, the price per GB was near $1.

When my son was born in August 2008, I remember seeing drives for 5 GB per $1.

Now, you can get about 10 GB per $1.  Even the large solid state hard drives are only $2 per GB, but yet I’ve been in conversations about how we could not imagine paying “that much” for them.

Other fun variants of Moore’s Law are linked from the Wikipedia article.

Solid State Disk Hype?

I opened up InformationWeeek today and saw this article:  Solid State Disks, Demystified.  So, the current benefits of SSD technology may be exaggerated.

  • Faster boots:  Read time bias and slimmed-down OS have helped exaggerate these results.
  • Battery life:  Other devices are still consuming the same amount of power, which is not insignificant in the power usage.  My counterpoints:
    • Max battery life power management settings would actually make for a usable computer without the need to stop the hard drive as a primary power saver.
    • Optical drives are not an option on many notebooks with SSDs (MacBook Air, sub-notebooks), so the example of watching a movie on DVD draining battery would not be a possibility on those notebooks.

I see some misses on this article:

  • What about heat generation/dissipation?  Would SSDs make less of a contribution to system heating, allowing for less fan usage or no fan at all?  (Thus saving power)
  • What abou mean time between failure (MTBF)…  A commenter on the article remarked on this.  The experimental MTBF indicates significantly longer lifetimes, but may have been in a read-heavy environment.  Indeed, write endurance may be a concern, but at 100k-300k write cycles that would still mean 20+ years before failure.  Of course, then there was this SSD failure debacle.  I’ve had a compact flash card in a camera fail on me within a month, and there isn’t a chance for recovery before failure.
  • Shock resistance 1500G/0.5 ms vs 300G/2.0 ms and 160G/1.0 ms.
  • Much wider operating temperature range (-25’C to 85’C).