Friday, February 26, 2010

Adding a "submit on enter" in ExtJS formpanels.

I had to retrospectively setup "submit on enter" to some existing ExtJS forms.
Googling only turned up some fairly unappetizing solutions.
Here's a way using defaults. Just change the getCmp or parametize it if you want, I've left it as a constant for illustration purposes.
Add this to your FormPanel constructor and all your fields will get "submit-on-enter".
If you only want 1 field to have it then just add everything inside the defaults to that 1 field.

defaults:{
  enableKeyEvents:true,
  listeners:{
    specialKey: function(field, el)
    {
      if(el.getKey() == Ext.EventObject.ENTER)
      {
        Ext.getCmp('address-search-button').fireEvent('click');
      }
    }
  }
}

Saturday, February 20, 2010

Decode Encrypted CueCat Output With Ugly Python

import sys; from string import maketrans as m; from binascii import a2b_uu as d
q = lambda x,y: ''.join([chr(c) for c in range(ord(x), ord(y) + 1)])
t = m(q('a','z') + q('A','Z') + q('0','9') + '+-', q(' ','_'))
def u(st): return ''.join([chr(ord(c) ^ 67) for c in d(chr(32 + 3 * len(st) / 4) + st)])
print "ID: %s, Type: %s, Barcode: %s"%(tuple([u(b.translate(t)) for b in sys.stdin.read().split('.')[1:-1]]))

Saturday, February 13, 2010

12 Bar Blues on an Arduino

Using a small 8ohm analogue speaker hooked up to pin 11, by strobing the pin, I generate a square wave (a kind of annoying timbre to be honest).
I generate 2 octaves of semitones starting with A-220 and index into it.
The timing is currently inaccurate as the note length for lower notes runs slightly longer (half a pulse width) than higher notes due to how the strobing currently works. It's surprisingly noticeable. I need to work on that to make it more consistent. Probably by using timer interrupts instead of delays.

To do:

Alter the volume by using analogWrite() to set the duty cycle of the pin... 255 = loud 0 = off.
I think I can use that mechanism to generate other waveforms, I'll probably try sawtooth next.
Proper ADSR waveforms.
Multichannel output (haw haw).


const int baseFreq = 220; // A
const int numHalfTones = 24; // 2 Octaves
long frequencies[numHalfTones];
long halfFreqs[numHalfTones];

/* 12 semi-tones per octave
  | Bf| | | C#| Ef| | |F# |G# |
 -+---+ | +---+---+ | +---+---+-
| A | B | C | D | E | F | G | A |
+---+---+---+---+---+---+---+---+
 
 2 octaves: 
 0  1  2  3  4  5  6  7  8  9 10 11
 A Bf  B  C C#  D Ef  E  F F#  G G# 
 12 13 14 15 16 17 18 19 20 21 22 23
 */

int seq[] = {
  3,  7, 10, 12, 13, 12, 10 , 7,
  3,  7, 10, 12, 13, 12, 10 , 7,
  8, 12, 15, 17, 18, 17, 15, 12,
  3,  7, 10, 12, 13, 12, 10 , 7,
  10, 14, 17, -1,  8, 12, 15, -1
};

int notes = 40;

long getTimeHigh(int i)
{
  return halfFreqs[i]; 
};

void ToneGen(void)
{
  float baseMult;
  int i;
  int lastTone = baseFreq;  
  baseMult = pow(2.0 , 0.083333);
  for(i = 0; i < numHalfTones; ++i)
  {
    long frequency = baseFreq;
    if(i)
    {
      frequency = (0.5 + (frequencies[i - 1] * baseMult));
    }
    frequencies[i] = frequency;
    halfFreqs[i] = (0.5 + (1000000.0 / frequency / 2.0));
  } 
};

void setup(void) {
  pinMode(11, OUTPUT);
  ToneGen();
  Serial.begin(57600);
}

int rest_count = 100;
long duration = (60 * 1000000) / 288;

void playNote(int idx)
{
  long tone = 0;
  if (idx >= 0)
  {
    tone = getTimeHigh(idx);
  }

  long endTime = micros() + duration ;
  if (tone > 0) 
  { 
    int val = HIGH;  
    while (micros() < endTime) 
    {
      digitalWrite(11,val);
      delayMicroseconds(tone);
      val = !val;
    } 

  }
  else 
  {
    delay(duration / 1000);
  }   
  digitalWrite(11, LOW); 
}

void loop(void) {
  analogWrite(11, 0);
  for(int i = 0; i < notes; ++i)
  {  
    playNote(seq[i]); 
    delay(10);
  }
}