Sunday, February 6, 2011

Motorola's Xoom is more expensive than Apple's best iPad and it doesn't matter.

With Motorola pitting their tablet against Apple's mentality. I expected the Xoom to be the same price as the best iPad, maybe less. Engadget posted the price of the Xoom, it's $799 before any service contracts. That's $30 less than the best iPad at $829.

Sadly, you get less with the Xoom.

The Xoom comes with a paltry 1 GB of internal storage. To make up the memory difference an SD card is required. All of the 64 GB SD cards that I find are over $100. With the SD card the Xoom is $899, and the iPad $829.

The Xoom is at least $70 more expensive. That's before the astronomically priced data plans.

Which is where the real money is. Both Verizon and AT&T really gouge their customers on these data plans. To be fair Verizon's data plans aren't as bad as AT&T's. 10GB on Verizon's network costs $80. On AT&T's that cost is $125. Within 2 months on most of AT&T's network the cost of the Xoom is recouped.

That's an incredible amount of money. Even as a successful professional with a penchant for expensive gadgets, the first year cost ($1860) of a Xoom makes me gag. There are so many other gadgets that I could buy with that money, and still buy a data plan from T-Mobile for half the cost.

Motorola may be touting the Xoom as a change in mentality, away from Apple. The "Apple Premium" is a well known cost, what's different about the Xoom's pricing?

Saturday, January 22, 2011

The impossible device

  As I followed the onslaught of Android tablets announced at CES this year, each device I read about had at least one flaw that was severe enough to remove it from consideration as my next gadget.

  The Motorola Xoom is on Verizon and is rumored to be $800. The Asus Transformer is running Android 2.2 and is heavily skinned by Asus. The Motorola Atrix (the best device of CES) is on AT&T; with capped data service having such a device is pointless. The Notion Ink Adam is heavily skinned, with miserable resolution. The list of disappointments goes on.

  I began thinking about what I would want from my next gadget. I have a set digital needs that my laptop, e-book reader, and phone do not meet.

  Reading digital media is the foremost need I have. Between digital references for my professional work, fiction for pleasure, and materials for classes I'm reading more than I ever have before. Reading is a tough activity to facilitate with a digital device. The device must be light enough to use comfortably for long periods of time, the screen must be large, preferably 8.5" x 11" to match the original format. The dot-pitch must be high, and the screen must be readable in sunlight and in darkness. Qualcomm and Mirasol are still a long way off from making a large screen.

  Note Taking after testing many different applications for taking notes, xournal, org-mode, Google docs, and even Gimp. Nothing beats a pencil and paper for recording high quality notes. Software and a stylus solves this problem. Stylus' are a dime a dozen, sadly there's no software available that does an adequate job.

  Linux it's impossible for me to get by in class or at work without a constantly ready Linux environment. Ideally there would be a virtual machine running a user maintained Linux. Access to the virtual machine would be through an application such as VNC.

   A portable keyboard clamshell & desktop dock are needed to interact with the Linux environment. An on-screen keyboard is useful for only short messages, nothing more. To have a useful Linux environment the device needs a desktop dock for the home and the office, and a clamshell to stuff in the messenger bag.

  Android or Chrome nearly all of my online activities pass through Google's services. After going Google with my browser and now my phone. I prefer most of my Google interactions through my "native" phone applications.

  Connectivity the device must always have an unfettered data and voice connection. Seedy contracts with capped data usage and overage charges are designed to gouge the consumer. I'm not willing to pay for a such a service. I will however, pay a premium to be given unlimited data and voice connectivity.

  Wireless power and long battery life there's no room in my bag for power cords. Thankfully Qi base stations exist, the device just needs a receiver.

  With the exception of the large Mirasol display all the technologies exist. Sadly I'll never see a device that meets most of my needs. I'm willing to pay, I'm willing to put the effort into customizing a device that comes close to what I want.

  In the mean time I'll continue to be disappointed. 

Wednesday, November 24, 2010

CTGenR8 now available!

CTGenR8 is now available on the Android market.

It's my only and worst application, with a very limited purpose. I use this to generate integers and characters to test the solutions to the algorithms we study in class.

I learned a lot about Android, and a fair bit more about the publishing side than I wanted to. In the end it's all very rewarding to be able to post a QR code for my application on the Android market!



Enjoy, happy generating. Please send me your bugs!

Thursday, October 28, 2010

Threads in Java can be simpler

Apologies, I've been waiting for my project presentation for class before posting this.

In a previous post I complained about the Java Concurrency example. It showed how unimpressive and needlessly complicated threading can be in Java. What bothers me most isn't the concept of wait() and notify(). It is the decision to explain wait() and notify() before simpler methods of synchronization.

It happens that Java has quite a few helper classes to make synchronization much simpler. The Semaphore is one of those classes. I have constructed a simpler version of the Drop class using two Semaphores.

public class Drop {
    private static final int MAX_MESSAGE = 10;
    private String[] messages = new String[MAX_MESSAGE];
    private int next_available;
    private Semaphore taking = new Semaphore(0, true);
    private Semaphore putting = 
        new Semaphore(MAX_MESSAGE, true);
    
    public void put(String message) {
        try {
            putting.acquire();
        } catch (InterruptedException e) { }
        synchronized (messages) {
            messages[next_available] = message;
            next_available++;
        }
        taking.release();                                        
    }

    public String take() {
        String message;
        try {
            taking.acquire();
        } catch (InterruptedException e) { }
        synchronized (this) {
            next_available--;
            message = messages[next_available];
        }
        putting.release();
        return message;
    }
}

There are three conceptual pieces to that make this new Drop work. The first and second are two Semaphores, putting and taking.  The third piece is the synchronized code block

  1. The putting Semaphore protects against concurrent additions, and overflow.
  2. The taking Semaphore protects against concurrent removals, and underflow.
  3. The synchronized code block it utilizes the intrinsic lock on Drop creating an atomic section. Thereby protecting against concurrent manipulations of the messages array and next_available index into it.

These three pieces are much easier to understand than a broadcast system. Although we understand (or guess) that the underlying Semphore is implemented with the broadcasting wait() and notify() system.

Utilizing the provided utilities the example has become far simpler. There's no need to check the state of the Drop when the thread has resumed. There are no concerns of cascading execution of tasks.

Synchronization in Java could be presented as a simple use of the available utilities.

Monday, September 27, 2010

Learning about bounce

There's little opportunity to handle hardware interrupts in my day to day. Thankfully COSC 625 and Arduino present the opportunity for hardware interrupts and I to get acquainted.

Arduino has a nice online reference. The documentation for attachInterrupt includes a short example for creating a circuit that toggles an LED on or off.

There are two interrupts on the Duemilanove, pin 2 and 3. Pin 2 is interrupt 0, pin 3 is interrupt 1. The example uses pin 2. When pin 2 transitions from high to low, or low to high the interrupt service routine is called. The example has the LED turn on when the button is pressed, and off when released.

/* The pin the LED is attached to. */
#define LED_PIN 13

/* The initial state of the LED */
volatile int state = LOW;

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

void loop()
{
  digitalWrite(LED_PIN, state);
}

void blink()
{
  state = !state;
}


But that's not what happened! After pressing the button several times the LED would be on when the button was released.


Insert video here

After double checking the wiring, and the project source several times I went looking for other interrupt examples. When I stumbled across my problem, which is the well known problem of bouncing. It turns out that physical switches give dirty signals. A switch will turn on and off very quickly many times for even a single action. Something an electrical engineer is well aware of, something I had no idea about.

So well known that Arduino even has a debouncing library.

I had some difficulties with getting the library to work; it's more my fault than anything else. Instead the interrupt service routine debounces.

#define BOUNCE_MIN 250

voidstatic unsigned long int last;
  unsigned long int now;

  now = millis();
  if ((now - last) <= BOUNCE_MIN) {
    /* do nothing */
    return;
  }

  last = now;
  state = !state;
}

Which limits the frequency of state changes to 250ms.



It works!

Sunday, September 19, 2010

My first integrated circuit

It's really hard to put down a toy. The arduino is no exception, and the projects from oomlout are so easy to do. Put those two together and you've got the start of an addiction.

The CIRC05 project is the first to use an integrated circuit. It works by throwing a latch to tell the integrated circuit to receive data, then sending the data, finally releasing the latch at which point the data is displayed. The data being sent is an 8 bit number, each bit of the number corresponds to a pin. When a bit is set the pin is high (the LED is on), when a bit is clear the pin is low (the LED is off.)

I'm still learning about basic electricity and electronics, so I followed the wiring layout (pdf link) without any variation. I did want to continue playing around with the layout. To do that the source needed some modifications, allowing subsequent projects with the same layout to require minimal work.

First the original in action:


This is the modified version of the oomlout source, subsequent projects will provide unique get_pin_value() and get_delay_ms() functions. By modifying these two functions the LED behavior is easily varied.
#define PIN_DATA 2
#define PIN_CLOCK 3
#define PIN_LATCH 4

#define DELAY_MS 150

void setup() {
    pinMode(PIN_DATA, OUTPUT);
    pinMode(PIN_CLOCK, OUTPUT);
    pinMode(PIN_LATCH, OUTPUT);
}

void loop() {
    static int pin_value = 0;
    static int delay_ms;

    pin_value = get_pin_value(pin_value);
    delay_ms = get_delay_ms(pin_value);

    updateLEDs(pin_value);
    delay(delay_ms);
}

void updateLEDs(int value) {
    /* Pull the chip latch low */
    digitalWrite(PIN_LATCH, LOW);
    /* Puts the bits into the shift register */
    shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, value);
    /* Pulls the latch high, displaying the data */
    digitalWrite(PIN_LATCH, HIGH);
}

int get_pin_value(int i) {
    if (i == 255) {
 return (0);
    }
    return (++i);
}

int get_delay_ms(int i) {
    return (DELAY_MS);
}

The first modification was to make the LEDs light up sequentially.



The get_pin_value() and get_delay_ms() functions follow
int get_pin_value(int i) {
  if (i == 0 || i > 128) {
    return 1;
  }

  return (i*2);
}

int get_delay_ms(int i) {
    return (150);
}

The second modification was to light the LEDs sequentially keeping the previously lit LEDs on.



The get_pin_value() function is only marginally more complex, get_delay_ms() is unchanged
int get_pin_value(int i) {
    if (i == 0 || i > 255) {
        return 1;
    }

    return (i * 2 + 1);
}

int get_delay_ms(int i) {
    return (DELAY_MS);
}

The third modification was to light LEDs randomly, and delay randomly between displaying the values. This is my favorite.



The get_pin_value() and get_delay_ms() functions are simplistic.

int get_pin_value(int i) {
    /* In setup randomSeed(analogRead(0)); */
    return random(0, 256);
}

int get_delay_ms(int i) {
    return random(50, 200);
}

I am having a hard time putting this toy away, luckily I'm getting tired. Maybe I'll play with inputs tomorrow...

Saturday, September 18, 2010

8 LED Arduino

With a little free time this weekend, I invested it in my Arduino. I selected a project from ardx.orgCIRC02. The board layout (pdf link) involves 8 LEDs controlled by 8 output pins 2 through 9.

The initial project blinks the LEDs in ascending order, and then repeats. Wiring the board took longer than building the project




The original project source
int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9};

void setup() {
  for (int i = 0; i < 8; i++) {
      pinMode(ledPins[i], OUTPUT);
  }
}

void loop() {
  oneAfterAnotherNoLoop();
}

void oneAfterAnotherNoLoop() {
    int delayTime = 75;
    
    for (int i = 0; i < 8; i++) {
        digitalWrite(ledPins[i], HIGH);
        delay(delayTime);
        digitalWrite(ledPins[i], LOW);
        delay(delayTime);
    }
}

With the board wired up, the blinking LEDs didn't satisfy me. I created a few other projects that used the same wiring. Adding few utility functions, and an amplification array. With this basic set up, each project need only to implement an in_order() function
/**
 * Finds the number of elements in an array.
 */
#define NELE(array) (sizeof(array) / sizeof(array[0]))

/**
 * The amount to decay each pin by
 */
#define DECAY_AMOUNT 75

/**
 * The number of miliseconds to delay by
 */
#define DELAY_MS 80

int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
int ledAmp[NELE(ledPins)];

/**
 * setup
 *
 * Invoked by the arduino infrastructure to initialize state.
 */
void setup() {
  for (int i = 0; i < NELE(ledPins); i++) {
    pinMode(ledPins[i], OUTPUT);
    ledAmp[i] = 0;
  }
}

/**
 * Neverending loop
 */
void loop() {
  in_order();
}

/**
 * Decays all the pin outs that are in use
 *
 * @param[in] amount the amount to decay the pins by
 */
void decay_pins(int amount) {
  for (int i = 0; i < NELE(ledPins); i++) {
    ledAmp[i] -= amount;
    if (ledAmp[i] < 0) {
      ledAmp[i] = 0;
    }
  }
}

/**
 * Writes all the new pin values
 */
void write_pins() {
  for (int i = 0; i < NELE(ledPins); i++) {
    analogWrite(ledPins[i], ledAmp[i]);
  }
}
The high-top fade, the LEDs are faded left to right




Source to in_order
void in_order() {
  for (int i = 0; i < NELE(ledPins); i++) {
    ledAmp[i] = 255; /* Set the pin high */
    write_pins(); /* Write all pin values */
    delay(DELAY_MS);

    decay_pins(DECAY_AMOUNT); /* Decay all pins */
    write_pins();
    delay(DELAY_MS);
  }
}


The Battle Star Galactica, where the LEDs are fade left to right, then right to left.






Source to in_order
void in_order() {
  for (int i = 0; i < NELE(ledPins) - 1; i++) {
    ledAmp[i + 1] = 255; /* Set the pin high */
    ledAmp[i] = 255; /* Set the pin high */

    write_pins(); /* Write all pin values */
    delay(DELAY_MS);

    decay_pins(DECAY_AMOUNT); /* Decay all pins */
    write_pins();
    delay(DELAY_MS);
  }

  for (int i = NELE(ledPins); i > 0 ; i--) {
    ledAmp[i] = 255; /* Set the pin high */
    ledAmp[i - 1] = 255; /* Set the pin high */

    write_pins(); /* Write all pin values */
    delay(DELAY_MS);

    decay_pins(DECAY_AMOUNT); /* Decay all pins */
    write_pins();
    delay(DELAY_MS);
  }
}

The explosion, the center LED is lit up then fades away towards the edges





Source to in_order
void in_order() {
  int center = NELE(ledPins) / 2;
  for (int i = 0; i < NELE(ledPins) / 2; i++) {
    ledAmp[center - i] = 255; /* Set the pin high */
    ledAmp[center + i] = 255; /* Set the pin high */

    write_pins(); /* Write all pin values */
    delay(DELAY_MS);

    decay_pins(DECAY_AMOUNT); /* Decay all pins */
    write_pins();
    delay(DELAY_MS);
  }
  if (NELE(ledPins) % 2 == 0) {
    /* NELE(ledPins) is even */
    ledAmp[0] = 255;
  }
}