Tuesday, May 29, 2012

I won the LayerOne badge-hacking contest!!! (WARNING, LOOOONG...)




Ok, the short version, its a CW (morse code) beacon transmitter, and I was really pleasantly surprised (and grateful!) for how well-received the project was, and by how many people seemed genuinely interested in it.

P1040448

Click this link for a little bit better picture

Now the rest of the story:

I've never been to a (ahem) "Security" Conference before. I offer up no excuse, its just one of those things I should have resolved to do long ago. So this weekend's LayerOne was my first. I didn't stay in Anaheim, as its "only" 64 or so miles away. (I take a really bizarre way down to the OC, 210 to the 57, I can't tolerate the old, narrow part of the 5 between the East LA interchange and Disneyland. Adds miles and I can drive faster, fewer CHiPs too.) So I missed alot of the after-hours hijinks, which was fine, my heavy drinking days are long passed. (Why do hackers drink so damn much???)

Anyway , I had a great time, and learned a bunch of new things, even thoughy a lot of what was discussed was totally over my head.

The greatest tip off was the May 24th Hack a Day post, http://hackaday.com/2012/05/24/layerone-badges-stop-bullets-drive-away/

linking to charliex's blog post with gave all the pertinent details on the badge:

http://charliex2.wordpress.com/2012/05/24/preparing-for-layerone-2012/

Ok, they're going to give me a microcontroller with an integrated transmitter and encourage me to hack it. Its on. A CW beacon transmitter was pretty much a forgone conclusion. I made sure to bring the appropriate USB cables, my USBtiny AVR programmer, and made sure I had the latest Arduino IDE that I could stuff onto my aging netbook. That was the battle plan!

Ok, fast-forward to lunchtime on Saturday at the L1 hacking village. Paid my $20 and got my parts kit and RC car. Had already decided I was going with the beacon transmitter idea, and that I'd keep the car "whole" to torment the cat as a new cat toy. Molten solder and SMD parts began to fly everywhere. Ok, not really.

Lesson #1: Flux pens are the bomb, I need to get one.

A while later, I had a badge that blinked a blue LED, but wasn't able to do much else. Time to go back to the speaker hall and learn some good stuff.

Fast forward to when I got back home in Burbank later in the evening. Yeah, sure I missed a party, so what, I got a good night's sleep and I wasn't hung over the next day!

I pilfered a 16mhz crystal from another arduino kit I had. The parts kit didn't include an xtal, and the "slowduino" firmware had been causing me trouble. Tack soldered my through-hole xtal to the smd pads ugly-style... yes, its a "hack." ;) For the next challenge, the kit came with an Atmega328, not an Atmega328P. Subtle difference that required some modification of an Arduino IDE config file, namely /usr/share/arduino/hardware/tools/avrdude.conf  .

See:
~~~~~~~~~~~~~~~
#------------------------------------------------------------
# ATmega328P   ...has a signature of 0x1e 0x95 0x0F; for plain '328 use 0x1e 0x95 0x14
#------------------------------------------------------------

part
    id                  = "m328p";
    desc                = "ATMEGA328P";
    has_debugwire       = yes;
    flash_instr         = 0xB6, 0x01, 0x11;
    eeprom_instr        = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
                          0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
                          0x99, 0xF9, 0xBB, 0xAF;
    stk500_devcode      = 0x86;
    # avr910_devcode    = 0x;
    signature           = 0x1e 0x95 0x14;
    pagel               = 0xd7;
    bs2                 = 0xc2;
    chip_erase_delay    = 9000;

~~~~~~~~~~~~~~~

I basically tricked avrdude into thinking my 328 was a 328p, told it to burn me a "Duemilanove w/ Atmega328" bootloader" and all was working right.

Lesson #2: What I just wrote about avrdude. ;) Sure, I could have done it all from the command line, but in my sleep-deprived state, I did't want to become an expert on Atega fuse settings, I wanted the Arduino IDE to do the thinking for me. Besides, I was finding some "old" and conflicting information via google and wanted to go to bed, not experiment.

Got up early and soldered the remaining remote-control section of the board together. SMD is fun after a big jolting cup of French Roast. Especially since the battery holder on the back of the board made the whole thing emulate a teeter-totter.

Verified that I could in fact control the car with the finished article, albeit not so smoothly, as I hadn't bothered to go through the final steps to move the receive frequncy on the car a few kilohertz to match the transmitter. I found that the car truly did scare the absolute crap out of the cat, I had hoped he'd just try to kill it like he does with every other rodent, marsupial, and avian.

Back to the documentation for a plan. I already knew I couldn't simply key one of the  controller's push-button lines, as the chip outputs a burst of FSK. Sounded crummy on the radio, and it was way too long of a burst to make even passible CW.

The key bit of info came from the documentation in CharlieX's blog post, namely one of the assumed transmitter circuits:

http://www.circuitstoday.com/5-channel-radio-remote-control

Look at the 1st transistor (on the left) with the crystal. Thats the carrier oscillator, thats what I'm interested in. The second transistor is the power amplifier. Hey, 1930's technology! a MoPa! (master oscillator, power amplifier) Not quite. Pin 9 powers 'em both up, pin 8 applies the modulating signal to the final, and frequency-shifts the oscillator. I'll just key up pin 9 and be in business. Nope... Pin 9 already has  voltage on it once the remote is "woken up." Heard the carrier nice and clear and clean on my receiver.

I cut the trace powering the controller. Chip is now out of the picture. Got lucky and found that if I keyed pin 10, it would back-feed through the IC and supply voltage to the oscillator from pin 9. Talk about lucky!

Wired the arduino pin 13 (where the LED is) to pin 10 of the chip. Added bonus, this lights the LED on the controller too! Had a nice "Sputnik" (beep, beep beep,) with the blink sketch. I knew I was in business at that point. Tacked on a few inches of wire as a "gestural" antenna. As in, "thats a nice gesture, but its not a real antenna." ;)

Loaded up the "Vaca Beacon" sketch, and after a couple tweaks, it was perfect.

I got this code from Brian Yee, W6BY, who has it running on an arduino on top of Mt. Vaca in Northern CA, and its keying a 10Ghz beacon!  Code originally came from Mark VandeWettering, K6HX, who writes the awesome brainwagon blog, http://brainwagon.org

Now, I figured I might be the only one who could head-copy the CW coming out of this thing, so I made sure I had a working copy of fldigi http://www.w1hkj.com/Fldigi.html running on my netbook, so all interested parties would be able to know what the beacon was transmitting.

Grabbed an extra set of AA batteries for the little Yaesu VR-500 (meh, but it does the job) and hopped in the car and headed back to hotel row a block south of that theme park owned by that Media Conglomerate that has various times previously employed me. (Not now, and possibly never again, who knows!)

I was late due this project, talks had started, and I was there to learn, so I listened with rapt attention, couldn't show the project to anybody until lunch time. I must confess I was pretty blown away by how positively it was received (ok literally) by the Null Space folks!  I got to put in a few plugs for Ham Radio to a few who might be interested in getting licensed, and also found that there actually were a few Hams there. (I won't "out" anybody!) I even got to put in a few plugs for the San Bernardino Microwave Society. http://www.ham-radio.com/sbms/

Actually winning the contest was pretty darn cool too, thanks again to all the folks who put in so much work putting together such a great conference!

Here's what I won! I don't know, I might save it until Winter when we actually NEED to heat the house.

P1040432

You tube, showing a few more details:


The code:


// Vaca beacon, Brian Yee, W6BY
//
// Simple Arduino Morse Beacon
// Written by Mark VandeWettering K6HX
// Email: k6hx@arrl.net
// 
// This code is so trivial that I'm releasing it completely without 
// restrictions.  If you find it useful, it would be nice if you dropped
// me an email, maybe plugged my blog @ http://brainwagon.org or included
// a brief acknowledgement in whatever derivative you create, but that's
// just a courtesy.  Feel free to do whatever.
//
// Modified for LayerOne Conference 5/2012 by Jason Sogolow W6IEE / w6iee.blogspot.com/ Dynotronix.com

struct t_mtab { char c, pat; } ;

struct t_mtab morsetab[] = {
   {'.', 106},
 {',', 115},
 {'?', 76},
 {'/', 41},
 {'A', 6},
 {'B', 17},
 {'C', 21},
 {'D', 9},
 {'E', 2},
 {'F', 20},
 {'G', 11},
 {'H', 16},
 {'I', 4},
 {'J', 30},
 {'K', 13},
 {'L', 18},
 {'M', 7},
 {'N', 5},
 {'O', 15},
 {'P', 22},
 {'Q', 27},
 {'R', 10},
 {'S', 8},
 {'T', 3},
 {'U', 12},
 {'V', 24},
 {'W', 14},
 {'X', 25},
 {'Y', 29},
 {'Z', 19},
 {'1', 62},
 {'2', 60},
 {'3', 56},
 {'4', 48},
 {'5', 32},
 {'6', 33},
 {'7', 35},
 {'8', 39},
 {'9', 47},
 {'0', 63}
} ;

#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))

#define SPEED  (13)  // Beacon speed in words per minute
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))
#define VOLUME 64

int LEDpin = 13 ;
int KeyPin_Low = 12;
int KeyPin_High = 11;
int SPKpin = 9 ;   /* PWM output */

void dash()
{
  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  analogWrite(SPKpin, VOLUME) ;
  delay(DASHLEN);
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Unkey the transmitter
  analogWrite(SPKpin, 0) ;
  delay(DOTLEN) ;
}

void dit()
{
  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  analogWrite(SPKpin, VOLUME) ;
  delay(DOTLEN);
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Unkey the transmitter
  analogWrite(SPKpin, 0) ;
  delay(DOTLEN);
}

void
send(char c)
{
  int i ;
  if (c == ' ') {
    Serial.print(c) ;
    delay(7*DOTLEN) ;
    return ;
  }
  for (i=0; i<N_MORSE; i++) {
    if (morsetab[i].c == c) {// Vaca beacon, Brian Yee, W6BY
//
// Simple Arduino Morse Beacon
// Written by Mark VandeWettering K6HX
// Email: k6hx@arrl.net
// 
// This code is so trivial that I'm releasing it completely without 
// restrictions.  If you find it useful, it would be nice if you dropped
// me an email, maybe plugged my blog @ http://brainwagon.org or included
// a brief acknowledgement in whatever derivative you create, but that's
// just a courtesy.  Feel free to do whatever.
//
// Modified for LayerOne Conference 5/2012 by Jason Sogolow W6IEE / w6iee.blogspot.com/ Dynotronix.com

struct t_mtab { char c, pat; } ;

struct t_mtab morsetab[] = {
   {'.', 106},
 {',', 115},
 {'?', 76},
 {'/', 41},
 {'A', 6},
 {'B', 17},
 {'C', 21},
 {'D', 9},
 {'E', 2},
 {'F', 20},
 {'G', 11},
 {'H', 16},
 {'I', 4},
 {'J', 30},
 {'K', 13},
 {'L', 18},
 {'M', 7},
 {'N', 5},
 {'O', 15},
 {'P', 22},
 {'Q', 27},
 {'R', 10},
 {'S', 8},
 {'T', 3},
 {'U', 12},
 {'V', 24},
 {'W', 14},
 {'X', 25},
 {'Y', 29},
 {'Z', 19},
 {'1', 62},
 {'2', 60},
 {'3', 56},
 {'4', 48},
 {'5', 32},
 {'6', 33},
 {'7', 35},
 {'8', 39},
 {'9', 47},
 {'0', 63}
} ;

#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))

#define SPEED  (13)  // Beacon speed in words per minute
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))
#define VOLUME 64

int LEDpin = 13 ;
int KeyPin_Low = 12;
int KeyPin_High = 11;
int SPKpin = 9 ;   /* PWM output */

void dash()
{
  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  analogWrite(SPKpin, VOLUME) ;
  delay(DASHLEN);
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Unkey the transmitter
  analogWrite(SPKpin, 0) ;
  delay(DOTLEN) ;
}

void dit()
{
  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  analogWrite(SPKpin, VOLUME) ;
  delay(DOTLEN);
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Unkey the transmitter
  analogWrite(SPKpin, 0) ;
  delay(DOTLEN);
}

void
send(char c)
{
  int i ;
  if (c == ' ') {
    Serial.print(c) ;
    delay(7*DOTLEN) ;
    return ;
  }
  for (i=0; i<N_MORSE; i++) {
    if (morsetab[i].c == c) {
      unsigned char p = morsetab[i].pat ;
      Serial.print(morsetab[i].c) ;

      while (p != 1) {
          if (p & 1)
            dash() ;
          else
            dit() ;
          p = p / 2 ;
      }
      delay(2*DOTLEN) ;
      return ;
    }
  }
  /* if we drop off the end, then we send a space */
  Serial.print("?") ;
}

void
sendmsg(char *str)
{
  while (*str)
    send(*str++) ;
  Serial.println("");
}

void setup() {
  char mytime[] = __TIME__;  // Current time and date when this was modified
  char mydate[] = __DATE__;
  
  pinMode(LEDpin, OUTPUT) ; pinMode(KeyPin_High, OUTPUT); pinMode(KeyPin_Low, OUTPUT);
  pinMode(SPKpin, OUTPUT) ;
  Serial.begin(9600) ;
  Serial.println("WA8RJF Beacon") ;
  Serial.print("Version 1.0,  ") ; Serial.print(mydate); Serial.print(", "); Serial.println(mytime);
  Serial.println("") ;
}

void loop() {
  int i;
  
  sendmsg(" VVV DE LAYERONE/B ") ;
  delay(1000) ;  // One second delay
/*  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  for(i = 0; i < 61; i++){
    delay(1000);  // hold the carrier on for one minute
  };
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Key the transmitter
  */
  /* Special dashes for Steve, KB8VAO */
/*  for(i = 0; i < 120; i++){
    dash();
  };
  delay(1000) ;*/
}

      unsigned char p = morsetab[i].pat ;
      Serial.print(morsetab[i].c) ;

      while (p != 1) {
          if (p & 1)
            dash() ;
          else
            dit() ;
          p = p / 2 ;
      }
      delay(2*DOTLEN) ;
      return ;
    }
  }
  /* if we drop off the end, then we send a space */
  Serial.print("?") ;
}

void
sendmsg(char *str)
{
  while (*str)
    send(*str++) ;
  Serial.println("");
}

void setup() {
  char mytime[] = __TIME__;  // Current time and date when this was modified
  char mydate[] = __DATE__;
  
  pinMode(LEDpin, OUTPUT) ; pinMode(KeyPin_High, OUTPUT); pinMode(KeyPin_Low, OUTPUT);
  pinMode(SPKpin, OUTPUT) ;
  Serial.begin(9600) ;
  Serial.println("WA8RJF Beacon") ;
  Serial.print("Version 1.0,  ") ; Serial.print(mydate); Serial.print(", "); Serial.println(mytime);
  Serial.println("") ;
}

void loop() {
  int i;
  
  sendmsg(" VVV DE LAYERONE/B ") ;
  delay(1000) ;  // One second delay
/*  digitalWrite(LEDpin, HIGH) ;
  digitalWrite(KeyPin_High, HIGH); digitalWrite(KeyPin_Low, LOW);  // Key the transmitter
  for(i = 0; i < 61; i++){
    delay(1000);  // hold the carrier on for one minute
  };
  digitalWrite(LEDpin, LOW) ;
  digitalWrite(KeyPin_High, LOW); digitalWrite(KeyPin_Low, HIGH);  // Key the transmitter
  */
  /* Special dashes for Steve, KB8VAO */
/*  for(i = 0; i < 120; i++){
    dash();
  };
  delay(1000) ;*/
}


*****
And yes, I'm hooked, I need to figure out a strategy to convince my work to let me get away to go to DefCon.

2 comments:

  1. Can we be best friends, because that was pretty cool.

    ReplyDelete
  2. Nicely done Jason. I was searching around for an arduino cw beacon sketch, found Mark's (K6HX) post on his brainwagon blog, and came across this post soon after. Congrats on the win! Nice bit of test equipment you've got there also. 73, Ron NR8O

    ReplyDelete