Blink three time in row

Tom,

This form further down this forums postings.

/* =============================================================================
 * File - morse.pde
 * -----------------------------------------------------------------------------
 * Code formatted assuming 80 characters screen width
 *
 * Naming Convention
 *  e_      enumeration
 *  g_      global
 *  k_      constant
 *
 *  dt      delta time
 */


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

#include "WProgram.h"

#include <ctype.h>


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

struct encoding_t
{
    const char              ascii;
    const unsigned short    encoding;
};


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

enum { e_EOS = 0, e_DOT, e_DASH, eMASK };


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

static const encoding_t  morse_encodings[] =
{
    // a string of 2-bit values encode the morse sequence, LSb -> MSb
    // 00   end-of-sequence
    // 01   '.'
    // 10   '-'
    // 11   unused

    
    // --- Numeric
      { '0',    0x02AA }    // "-----"
    , { '1',    0x02A9 }    // ".----"
    , { '2',    0x02A5 }    // "..---"
    , { '3',    0x0295 }    // "...--"
    , { '4',    0x0255 }    // "....-"
    , { '5',    0x0155 }    // "....."
    , { '6',    0x0156 }    // "-...."
    , { '7',    0x015A }    // "--..."
    , { '8',    0x016A }    // "---.."
    , { '9',    0x01AA }    // "----."
    
    // --- Alphabetic
    , { 'A',    0x0009 }    // ".-"
    , { 'B',    0x0056 }    // "-..."
    , { 'C',    0x0066 }    // "-.-."
    , { 'D',    0x0016 }    // "-.."
    , { 'E',    0x0001 }    // "."
    , { 'F',    0x0065 }    // "..-."
    , { 'G',    0x001A }    // "--."
    , { 'H',    0x0055 }    // "...."
    , { 'I',    0x0005 }    // ".."
    , { 'J',    0x00A9 }    // ".---"
    , { 'K',    0x0026 }    // "-.-"
    , { 'L',    0x0059 }    // ".-.."
    , { 'M',    0x000A }    // "--"
    , { 'N',    0x0006 }    // "-."
    , { 'O',    0x002A }    // "---"
    , { 'P',    0x0069 }    // ".--."
    , { 'Q',    0x009A }    // "--.-"
    , { 'R',    0x0019 }    // ".-."
    , { 'S',    0x0015 }    // "..."
    , { 'T',    0x0002 }    // "-"
    , { 'U',    0x0025 }    // "..-"
    , { 'V',    0x0095 }    // "...-"
    , { 'W',    0x0029 }    // ".--"
    , { 'X',    0x0096 }    // "-..-"
    , { 'W',    0x00A6 }    // "-.--"
    , { 'Z',    0x005A }    // "--.."
    
    // --- Punctuation
    , { ',',    0x0A5A }    // "--..--"
    , { '.',    0x0999 }    // ".-.-.-"
    , { ':',    0x056A }    // "---..."
    , { '?',    0x05A5 }    // "..--.."
    , { '-',    0x0956 }    // "-....-"
    , { '/',    0x0196 }    // "-..-."
    , { '(',    0x09A6 }    // "-.--.-"
    , { ')',    0x09A6 }    // "-.--.-"
    
    // --- ARDUINO Windows IDE has problems with escaped ascii literals!
#if 0
    , { '\'',   0x06A9 }    // ".----."
    , { '\"',   0x0699 }    // ".-.--."
#endif
};

const int pin = 13;


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

int g_dtDot;
int g_dtDash;
int g_dtChar;
int g_dtWord;


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

static void dot()
{
    digitalWrite(pin, HIGH);
    delay(g_dtDot);
    
    digitalWrite(pin, LOW);
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

static void dash()
{
    digitalWrite(pin, HIGH);
    delay(g_dtDash);
    
    digitalWrite(pin, LOW);
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

static void blinkSequence(unsigned short encoding)
{
    do
    {
        switch ( encoding bitand eMASK )
        {
            case e_DOT: dot();      break;
            case e_DASH:dash();     break;
            default:                break;
        }
        
        encoding >>= 2;

        if ( encoding ) { delay(g_dtDot); }

    } while ( e_EOS != (encoding bitand eMASK) );
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

static void blinkCharactor(char ch)
{
    const int cEntries = sizeof(morse_encodings) / sizeof(morse_encodings[0]);
    
    for ( int i = 0; i < cEntries; i++)
    {
        if ( ch == morse_encodings[i].ascii )
        {
            blinkSequence(morse_encodings[i].encoding);
            return;
        }
    }
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

void setTimings(int dt)
{
    g_dtDot     = dt;
    g_dtDash    = 3 * dt;
    g_dtChar    = 3 * dt;
    g_dtWord    = 7 * dt;
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 * Any speed greater than 10-15 words per minute will be hard to read on an LED
 */

void setSpeedWordsPerMinute(int wpm)
{
#define WPM_MAX     (150)
    
    const unsigned long k_MPM           = (60 * 1000);  // millisec's per minute
    
    const unsigned long k_DOT           = 1;
    const unsigned long k_DASH          = 3;
    const unsigned long k_INTRA_SEQ     = 1;
    const unsigned long k_INTRA_CHAR    = 1;
    
    const char          standard[]      = { "PARIS" };
    
    // --- check and enforce words per minute boundries

    if ( wpm < 1 )          { wpm  = 1; }
    if ( wpm > WPM_MAX )    { wpm  = WPM_MAX; }
    

    // --- count 'dot' length of 'standard' word

    const char*         ptr = standard;
    unsigned long       dpw = 0;            // 'dot's per word
    char                ch;
    while ( ch = *ptr++ )
    {
        const int cEntries = sizeof(morse_encodings) / sizeof(morse_encodings[0]);
        
        for ( int i = 0; i < cEntries; i++)
        {
            if ( ch == morse_encodings[i].ascii )
            {
                unsigned short  encoding    = morse_encodings[i].encoding;
                
                do
                {
                    switch ( encoding bitand eMASK )
                    {
                        case e_DOT:     dpw += k_DOT;   break;
                        case e_DASH:    dpw += k_DASH;  break;
                        default:                        break;
                    }

                    encoding >>= 2;

                    if ( encoding ) { dpw += k_INTRA_SEQ; }

                } while ( e_EOS != (encoding bitand eMASK) );
            }
        }
        
        if ( *ptr ) { dpw += k_INTRA_CHAR; }
    }
    
    setTimings(k_MPM / (wpm * dpw));
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

void loop()
{
    const char      message[]   = { "ARDUINO ROCKS" };
    const char*     ptr         = message;
    
    char            ch;
    while ( ch = *ptr++ )
    {
        blinkCharactor(((isalpha(ch)) ? toupper(ch) : ch));
        delay(((' ' == *ptr) ? g_dtWord : g_dtChar));
    }
    
    // 3 SECONDS
    const int   dtMessageDelay = (3 * 1000);
    delay(dtMessageDelay);
}


/* =============================================================================
 * -----------------------------------------------------------------------------
 */

void setup()
{
    pinMode(ledPin, OUTPUT);

    setSpeedWordsPerMinute(25);
}