IM-Me Dongle UART

In this post, I’ll detail how to add a serial port to an IM-Me dongle.

The first thing I did when I got my IM-Me was to try and communicate through the existing Cypress chip. It works, but it’s slow and clunky. I had to treat the channel as lossy and build an ACKing and retry system on top. It’s a hack.

A much better solution is to solder a real TTL level serial port onto the dongle and communicate with it that way.

Modifying the board for serial comms isn’t much harder than wiring on a GoodFET.

Here is an unmodified dongle:


Add an external power source:
On an unmodified IM-me dongle, 5V is supplied over USB. This drives the Cypress’ internal voltage regulator which produces 3V for the CC1110.
I run my boards with the Cypress powered down and I provide 3V directly into the CC1110. I am using a wall-wart and a 3.3V regulator, but 2xAA batteries work fine.
Connect your 3V power supply to ground and 3V on the dongle. The easiest connections are at the positive leg of the through hole capacitor and the GND pin of the USB plug.

Disable the Cypress chip:
It seems that supplying 3V to the board has the side effect of powering up the Cypress chip. It will immediately start writing junk over the SPI lines which will interrupt the serial communications. To disable it, cut or lift the Cypress VCC pin. This is best done by heating the pin with a soldering iron then levering it up with a small screwdriver.

Add serial:
Connect a standard 3V FTDI-type cable to the Cypress pins marked MOSI and MISO. MOSI is transmit and MISO is receive.
Connect the ground pin of your serial cable to GND on the board.

For reference, this may be useful (Note that most of the thin green wires connected to the Cypress won’t be needed)

Once the board is modified - here’s a test firmware image:

:0400000002001B32AD
:01000B0032C2
:03001300020117D0
:0300740002001671
:0500160012007780FEDE
:100077001200B01200DC1200CF43FD4012011A7AC1
:10008700647B017C808A828B838CF0120144FD6043
:10009700EE8D820ABA00010BC002C003C004120130
:0900A70038D004D003D00280DC43
:1001640057617272616E747920766F696465640D8B
:020174000A007F
:1000B000539ADFA2AFE433F452A82274FC55C9F579
:1000C000F0740345F0F5C953C9FB43C90880FE43EA
:1000D000F32843FD1443FE0275FF182253BEFBE5CF
:1000E000BE30E6FB53C6B8E5C620E6FB43BE04229D
:1000F000AA82AB831ABAFF011BC3E49A74808BF007
:1001000063F08095F0500F7CB07D041CBCFF011D96
:10011000EC4D70F780DE22C28B32AAF174FE5AF5E4
:10012000F0740245F0F5F143F33C7586C075C222C8
:1001300075C50CD28BD2AA228582C1E58630E1FB3F
:040140005386FD22C3
:06004A00E478FFF6D8FD8A
:100028007900E94400601B7A0090017678007593A6
:1000380000E493F2A308B800020593D9F4DAF27544
:0200480093FF24
:100050007800E84400600A7900759300E4F309D859
:10006000FC7800E84400600C7900900000E4F0A304
:04007000D8FCD9FAE5
:0D001B00758107120160E582600302001686
:1001440020F71430F6148883A88220F507E6A883E4
:1001540075830022E280F7E49322E0227582002274
:00000001FF

Then,

goodfet.cc erase
goodfet.cc flash dongle.hex

Connect to the serial port at 115200 8-N-1

Driving the UART from C using SDCC looks like this:

void uart0rx_isr(void) __interrupt URX0_VECTOR
{
    URX0IF = 0;
    // read U0DBUF and do something with it...
}

void uart_init(void)
{
    PERCFG = (PERCFG & ~PERCFG_U0CFG) | PERCFG_U1CFG;
    P0SEL |= BIT5 | BIT4 | BIT3 | BIT2;

    U0CSR = 0x80 | 0x40;    // UART, RX on

    U0BAUD = 34;    // 115200
    U0GCR = 12;

    URX0IF = 1;
    URX0IE = 1;
}

void uart_putc(uint8_t ch)
{
    U0DBUF = ch;
    while(!(U0CSR & U0CSR_TX_BYTE)); // wait for byte to be transmitted
    U0CSR &= ~U0CSR_TX_BYTE;         // Clear transmit byte status
}