/*
* JDN inspired by many :-)
* (C) Jens Dalsgaard Nielsen
* PHK beer license
* simple morse module for sound(tone) or just dig port
* morse alphabeth in prog flash for saving space
*
* Code might be to big but readability is preferred to real compact
*/

#include "morse.h"

// in progmem for saving ram
// max 6 dot/dashes in a symbol
// 1: dot  2:dash   0: end of symbol
// you can add more symbols
// remember to add symbol in function chkC
const prog_char arC[] PROGMEM= {
  2,2,2,2,2,0,//0 -----
  1,2,2,2,2,0,//1 .----
  1,1,2,2,2,0,//2 ..---
  1,1,1,2,2,0,//3 ...--
  1,1,1,1,2,0,//4 ....-
  1,1,1,1,1,0,//5 .....
  2,1,1,1,1,0,//6 -....
  2,2,1,1,1,0,//7 --...
  2,2,2,1,1,0,//8 ---..
  2,2,2,2,1,0,//9 ----.
  1,2,2,1,2,1,//@ .--.-. 10
  1,2,0,0,0,0,//A .-
  2,1,1,1,0,0,//B -...
  2,1,2,1,0,0,//C -.-.
  2,1,1,0,0,0,//D -..
  1,0,0,0,0,0,//E .
  1,1,2,1,0,0,//F ..-.
  2,2,1,0,0,0,//G --.
  1,1,1,1,0,0,//H ....
  1,1,0,0,0,0,//I ..
  1,2,2,2,0,0,//J .--- 20
  2,1,2,0,0,0,//K -.-
  1,2,1,1,0,0,//L .-..
  2,2,0,0,0,0,//M --
  2,1,0,0,0,0,//N -.
  2,2,2,0,0,0,//O ---
  1,2,2,1,0,0,//P .--.
  2,2,1,2,0,0,//Q --.-
  1,2,1,0,0,0,//R .-.
  1,1,1,0,0,0,//S ...
  2,0,0,0,0,0,//T - 30
  1,1,2,0,0,0,//U ..-
  1,1,1,2,0,0,//V ...-
  1,2,2,0,0,0,//W .--
  2,1,1,2,0,0,//X -..-
  2,1,2,2,0,0,//Y -.--
  2,2,1,1,0,0,//Z --..
  1,2,1,2,1,2,//.  .-.-.-37
  2,2,1,1,2,2,//,  --..--
  2,2,2,1,1,1,//:  ---...
  1,1,2,2,1,1,//?  ..--..40
  1,2,1,1,2,1,//'  .-..-.
  2,1,1,1,2,0,//=  -...-
  2,1,1,1,1,2,//-  -....-
  1,2,1,2,1,0,//+  .-.-.
  2,1,2,1,2,2,// ! -.-.-- 45 and last
};

int _pin;
int _sound;
int _dotLength;

int mSoundFreq = SOUNDFREQ;

//----------------------------------------------------------
int mInit(int sound, int pin,int dotLength)
{
  if (sound == 0)
    pinMode(pin, OUTPUT);

  _pin = pin;
  _sound = sound;
  _dotLength = dotLength;
  return (0);
}

//----------------------------------------------------------
void mDot()
{
  if (_sound)
    tone(_pin,mSoundFreq);
  else
    digitalWrite(_pin, HIGH);

  delay(_dotLength);

  if (_sound)
    noTone(_pin);
  else
    digitalWrite(_pin, LOW);

  delay(_dotLength);
}

//----------------------------------------------------------
void mDash()
{
  if (_sound)
    tone(_pin,mSoundFreq);
  else
    digitalWrite(_pin, HIGH);

  delay(3*_dotLength);

  if (_sound)
    noTone(_pin);
  else
    digitalWrite(_pin, LOW);

  delay(_dotLength);
}

//----------------------------------------------------------
void mcSpace()
{
  delay(2 *_dotLength);   // already 1 from ch
}

//----------------------------------------------------------
void mwSpace()
{
  delay(4 * _dotLength);  // word space == 7 * dot  NB already got 3 from last char
}

//----------------------------------------------------------
int chkC(char c)
{

  if ('@' <= c && c <= 'Z')
    return ( (int)c - (int)('@') +10); // bypass num chars by adding 10
  else if ('0' <= c && c <= '9')       // num chars is in first 10 places in array
    return ( ((int)c) -(int)('0') ); // int
  else {
    switch(c) {
    case ',':
      return (37); // 37,38,... corresponds to location in array arC
    case ':':
      return (38);
    case '?':
      return (39);
    case '/':
      return (40);
    case '\'':
      return (41);
    case '=':
      return (42);
    case '-':
      return (43);
    case '+':
      return (44);
    case '!':
      return (45);
    default:
      return (-1); // err not valid ch
    }
  }
}

//----------------------------------------------------------
void morseC(char c)
{
  int indx;
  unsigned char i,cc;

  indx = chkC(c);

  if (0 <= indx) {
    for (i=0; i < 6; i++) {
      cc = pgm_read_byte_near(arC + i + indx*6); // get morse code

      if (cc == 1)
        mDot();
      else if (cc ==2)
        mDash();
    }
    mcSpace();
  }
}

//----------------------------------------------------------
void morseS(char c[])
{
  int l,i;
  l = strlen(c);
  for (i=0; i < l ; i++) {
    if (c[i] == ' ')
      mwSpace();
    else
      morseC(c[i]);
  }
}

//----------------------------------------------------------
void morseDotDash(char c[])
{
  int l,i;
  l = strlen(c);
  for (i=0; i < l ; i++) {
    switch (c[i]) {
    case '.':
      mDot();
      break;
    case '-':
      mDash();
      break;
    case ' ':
      mcSpace();
      break; // use three " " for word delim
    default:;                     // "... --- ...   ... --- ..."
    }
  }
}

//----------------------------------------------------------
void morseI(int i)
{
  char const digit[] = "0123456789";
  char b[10],*p=b;
  if(i<0) {
    *p++ = '-';
    i = -i;
  }
  int k = i;
  do { //Move to where representation ends
    ++p;
    k = k / 10;
  } while(k);

  *p = '\0';

  do { //Move back, inserting digits as u go
    *--p = digit[i%10];
    i = i/10;
  } while(i);

  morseS(b);

}

