forum.getinpulse.com
http://www.getinpulse.com/hack/forum/

Morse code... code
http://www.getinpulse.com/hack/forum/viewtopic.php?f=6&t=191
Page 1 of 1

Author:  jlait [ Fri Apr 08, 2011 10:07 am ]
Post subject:  Morse code... code

I didn't see any other mention of morsecode, but personally I find it a rather nifty way to interface with the watch. In the interest of seeing other's use it, or better yet, improve my code, here's the respective code.

Since I haven't built a local toolchain yet, I'm just catting all my .c files into one chunk and sending to compileandload that way. Thus no header :>

The idea is you add updates in your button up/ down/ main loop event loops and pass in the current millisecond time. The timing of dot vs dash is the MORSE_DOT define - my experiments found 250 best - 200 still got some false dashes.

I was only caring about RAM usage, not code size when writing this, so ways to crunch the code to be smaller would be appreciated.

//
// Defines the morse functions.
// Hook up, passing in current millisec
//    morse_buttondown(int ms)
//    morse_buttonup(int ms)
//    morse_mainloop(int ms)
//
// Read with, which return 0 if none on stack.
// u8 morse_getchar()
//
// RAM use: 11 bytes
//

//
// Prototypes
//
u8 morse_getchar();
void morse_mainloop(int ms);
void morse_buttonup(int ms);
void morse_buttondown(int ms);
void morse_reset();

//
// Implementation
//

#define         MORSE_DOT               250
#define         MORSE_ENDOFSYMBOL       400
#define         MORSE_SPACEPUSH         1100

u32 morse_downtime = 0;
u32 morse_uptime = 0;

u8      morse_seq;
u8      morse_symbols = 0;
u8      morse_char = 0;

void
morse_pushdot()
{
    // zero by default
    morse_symbols++;
}

void
morse_pushdash()
{
    morse_seq |= 1 << morse_symbols;
    morse_symbols++;
}

void
morse_pushchar(u8 c)
{
    morse_char = c;
}

void
morse_pushcode()
{
    if (morse_symbols == 0)
        return;

    if (morse_symbols < 5)
    {
        const char *lut =
            //
               " "
            //  oI
               "et"
            //  oIoI
            //  ooII
               "inam"
            //  oIoIoIoI
            //  ooIIooII
            //  ooooIIII
               "sdrgukwo"
            //  oIoIoIoIoIoIoIoI
            //  ooIIooIIooIIooII
            //  ooooIIIIooooIIII
            //  ooooooooIIIIIIII
               "hblzfcp-vx-q-yj-"
            ;
        int     off;
        off = 1 << morse_symbols;
        off--;
        off += morse_seq;
        morse_pushchar(lut[off]);
    }

    // Longer lengths take special codes.
    else if (morse_symbols == 5)
    {
        // NOTE: These are all backwards bit patterns!
        switch (morse_seq)
        {
            // Number patterns
            case 0b11110:
                morse_pushchar('1');
                break;
            case 0b11100:
                morse_pushchar('2');
                break;
            case 0b11000:
                morse_pushchar('3');
                break;
            case 0b10000:
                morse_pushchar('4');
                break;
            case 0b00000:
                morse_pushchar('5');
                break;
            case 0b00001:
                morse_pushchar('6');
                break;
            case 0b00011:
                morse_pushchar('7');
                break;
            case 0b00111:
                morse_pushchar('8');
                break;
            case 0b01111:
                morse_pushchar('9');
                break;
            case 0b11111:
                morse_pushchar('0');
                break;

            // Punctuation
            case 0b01001:
                morse_pushchar('/');
                break;
            case 0b01101:
                morse_pushchar('(');
                break;
            case 0b00010:
                morse_pushchar('&');
                break;
            case 0b10001:
                morse_pushchar('=');
                break;
            case 0b01010:
                morse_pushchar('+');
                break;
        }
    }
    else if (morse_symbols == 6)
    {
        // NOTE: These are all backwards bit patterns!
        switch (morse_seq)
        {
            case 0b000000:
                // All e's, error code.
                morse_pushchar('\b');
                break;
            case 0b101010:
                morse_pushchar('.');
                break;
            case 0b110011:
                morse_pushchar(',');
                break;
            case 0b001100:
                morse_pushchar('?');
                break;
            case 0b011110:
                morse_pushchar('\'');
                break;
            case 0b101011:
                morse_pushchar('!');
                break;
            case 0b101101:
                morse_pushchar(')');
                break;
            case 0b000111:
                morse_pushchar(':');
                break;
            case 0b010101:
                morse_pushchar(';');
                break;
            case 0b100001:
                morse_pushchar('-');
                break;
            case 0b101100:
                morse_pushchar('_');
                break;
            case 0b010010:
                morse_pushchar('"');
                break;

            // Recent addition from 2004.
            case 0b010110:
                morse_pushchar('@');
                break;

        }
    }

    else if (morse_symbols == 7)
    {
        switch (morse_seq)
        {
            case 0b0000000:
                // All e's, error code.
                morse_pushchar('\b');
                break;
            case 0b1001000:
                morse_pushchar('$');
                break;
        }
    }
    // 6 or more e's is considered error, ie, backspace, so
    // we detect
    else if (!morse_seq)
    {
        morse_pushchar('\b');
    }

    // Reset in any case.
    morse_symbols = 0;
    morse_seq = 0;
}

void
morse_process(bool signal, int lenms)
{
    if (signal)
    {
        if (lenms < MORSE_DOT)
            morse_pushdot();
        else
            morse_pushdash();
    }
    else
    {
        if (lenms > MORSE_ENDOFSYMBOL)
        {
            morse_pushcode();
        }
        if (lenms > MORSE_SPACEPUSH)
        {
            morse_uptime = 0;
            morse_pushchar(' ');
        }
    }
}

void
morse_buttondown(int ms)
{
    morse_uptime = 0;
    morse_downtime = ms;
}

void
morse_buttonup(int ms)
{
    morse_uptime = ms;
    morse_process(true, morse_uptime - morse_downtime);
    morse_downtime = 0;
}

void
morse_mainloop(int ms)
{
    if (morse_uptime)
    {
        morse_process(false, ms - morse_uptime);
    }
}

u8
morse_getchar()
{
    u8          c;
    c = morse_char;
    morse_char = 0;
    return c;
}

void
morse_reset()
{
    morse_char = 0;
    morse_seq = 0;
    morse_uptime = 0;
}

Author:  jlait [ Mon Apr 11, 2011 6:13 pm ]
Post subject:  Re: Morse code... code

I've since found that inlinining the hook functions cuts a lot of code. Likewise, the 5 bit length codes can also be dumped into the LUT, while it is only half full, it saves more bytes of code than is wasted.

Here's the latest:
//
// Defines the morse functions.
// Hook up, passing in current millisec
//    morse_buttondown(int ms)
//    morse_buttonup(int ms)
//    morse_mainloop(int ms)
//
// Read with, which return 0 if none on stack.
// u8 morse_getchar()
//
// RAM use: 11 bytes
//

//
// Prototypes
// Commented out inline methods
//
u8 morse_getchar();
//void morse_mainloop(int ms);
//void morse_buttonup(int ms);
//void morse_buttondown(int ms);
void morse_reset();

//
// Implementation
//

#define      MORSE_DOT      250
#define      MORSE_ENDOFSYMBOL   400
#define      MORSE_SPACEPUSH      1100

u32 morse_downtime = 0;
u32 morse_uptime = 0;

u8   morse_seq;
u8   morse_symbols = 0;
u8   morse_char = 0;

inline void
morse_pushdot()
{
    // zero by default
    morse_symbols++;
}

inline void
morse_pushdash()
{
    morse_seq |= 1 << morse_symbols;
    morse_symbols++;
}

inline void
morse_pushchar(u8 c)
{
    morse_char = c;
}

inline void
morse_pushcode()
{
    if (morse_symbols == 0)
   return;

    if (morse_symbols < 6)
    {
   const char *lut =
       //
          " "
       //  oI
          "et"
       //  oIoI
       //  ooII
          "inam"
       //  oIoIoIoI
       //  ooIIooII
       //  ooooIIII
          "sdrgukwo"
       //  oIoIoIoIoIoIoIoI
       //  ooIIooIIooIIooII
       //  ooooIIIIooooIIII
       //  ooooooooIIIIIIII
          "hblzfcp-vx-q-yj-"
       //  oIoIoIoIoIoIoIoI   oIoIoIoIoIoIoIoI
       //  ooIIooIIooIIooII   ooIIooIIooIIooII
       //  ooooIIIIooooIIII   ooooIIIIooooIIII
       //  ooooooooIIIIIIII   ooooooooIIIIIIII
       //  oooooooooooooooo   IIIIIIIIIIIIIIII
          "56 7   8 /+  ( 9" "4=      3   2&10"
       ;
   int   off;
   off = 1 << morse_symbols;
   off--;
   off += morse_seq;
   morse_pushchar(lut[off]);
    }

    // Longer lengths take special codes.
    else if (morse_symbols == 6)
    {
   // NOTE: These are all backwards bit patterns!
   switch (morse_seq)
   {
       case 0b000000:
      // All e's, error code.
      morse_pushchar('\b');
      break;
       case 0b101010:
      morse_pushchar('.');
      break;
       case 0b110011:
      morse_pushchar(',');
      break;
       case 0b001100:
      morse_pushchar('?');
      break;
       case 0b011110:
      morse_pushchar('\'');
      break;
       case 0b101011:
      morse_pushchar('!');
      break;
       case 0b101101:
      morse_pushchar(')');
      break;
       case 0b000111:
      morse_pushchar(':');
      break;
       case 0b010101:
      morse_pushchar(';');
      break;
       case 0b100001:
      morse_pushchar('-');
      break;
       case 0b101100:
      morse_pushchar('_');
      break;
       case 0b010010:
      morse_pushchar('"');
      break;

       // Recent addition from 2004.
       case 0b010110:
      morse_pushchar('@');
      break;

   }
    }
    else if (morse_symbols == 7)
    {
   switch (morse_seq)
   {
       case 0b0000000:
      // All e's, error code.
      morse_pushchar('\b');
      break;
       case 0b1001000:
      morse_pushchar('$');
      break;
   }
    }
    // 6 or more e's is considered error, ie, backspace, so
    // we detect
    else if (!morse_seq)
    {
   morse_pushchar('\b');
    }

    // Reset in any case.
    morse_symbols = 0;
    morse_seq = 0;
}

void
morse_process(bool signal, int lenms)
{
    if (signal)
    {
   if (lenms < MORSE_DOT)
       morse_pushdot();
   else
       morse_pushdash();
    }
    else
    {
   if (lenms > MORSE_ENDOFSYMBOL)
   {
       morse_pushcode();
   }
   if (lenms > MORSE_SPACEPUSH)
   {
       morse_uptime = 0;
       morse_pushchar(' ');
   }
    }
}

inline void
morse_buttondown(int ms)
{
    morse_uptime = 0;
    morse_downtime = ms;
}

inline void
morse_buttonup(int ms)
{
    morse_uptime = ms;
    morse_process(true, morse_uptime - morse_downtime);
    morse_downtime = 0;
}

inline void
morse_mainloop(int ms)
{
    if (morse_uptime)
    {
   morse_process(false, ms - morse_uptime);
    }
}

u8
morse_getchar()
{
    u8      c;
    c = morse_char;
    morse_char = 0;
    return c;
}

void
morse_reset()
{
    morse_char = 0;
    morse_seq = 0;
    morse_uptime = 0;
}

Page 1 of 1 All times are UTC - 8 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/