The morse code screwdriver

At my birthday I got a „special“ present from my friends. A screwdriver on which are two 1.5 volt batteries are taped on it. That symbolic „electrical screwdriver“ was decorated with some 5 euro banknotes from which I should buy an electrical screwdriver.
After thinking about the screwdriver with the two batteries an idea come into my mind. I can tape a led and a Atmel AVR microcontroller on this present and the led can blink a morse code message. I locked at the morse code wikipage and found how the morse code alphabet is coded. So I soldered an ATTiny85 with a 51 Ohm resistor and a red led together an wrote the following program.

/*
 * MorseCode.c
 *
 * Created: 17.12.2014
 *  Author: Matthias Jentsch
 *
 * The program let a led blink on PB3 to form a morse code. The fixed message will be send.
 */ 

#include <avr/io.h>
#define F_CPU 1000000UL     /* Internal 8MHz clock divided by 8 = 1MHz clock */
#ifndef DEBUG
#include <util/delay.h>
#endif
#include <avr/pgmspace.h> 
#include <avr/eeprom.h>

// The sending speed factor; above 1 means send slower; below 1 means send faster
#define FACTOR 1.5
// The SHORT signal period
#define SHORT 100 * FACTOR
// The LONG signal period
#define LONG 300 * FACTOR
// The period of silence between two SHORT/LONG signals
#define SYMBOL_SPACE 100 * FACTOR
// The period of silence between two characters
#define CHARACTER_SPACE 300 * FACTOR
// The period of silence between two words
#define WORD_SPACE 700 * FACTOR
// The period of silence after the complete sentence/message was sent
#define SENTENCE_SPACE 3000 * FACTOR

// That's the messsage that shoul be send
const char PROGMEM _message[] =
"First line of the message " \
"Next line of the message " \
"Last line of the message";

// The morse code alphabet
// The first byte in the line is the count of symbols that are needed to form a character
// The second byte forms the short/long symbols for each character
// Example: 0x04, 0x09 describes the symbols "long short short long" for the character 'X'
const uint8_t _symbols[40][2] =
{
	{ 0x02, 0x02 },	// A
	{ 0x04, 0x01 },	// B
	{ 0x04, 0x05 },	// C
	{ 0x03, 0x01 },	// D
	{ 0x01, 0x00 },	// E
	{ 0x04, 0x04 },	// F
	{ 0x03, 0x03 },	// G
	{ 0x04, 0x00 },	// H
	{ 0x02, 0x00 },	// I
	{ 0x04, 0x0E },	// J
	{ 0x03, 0x05 },	// K
	{ 0x04, 0x02 },	// L
	{ 0x02, 0x03 },	// M
	{ 0x02, 0x01 },	// N
	{ 0x03, 0x07 },	// O
	{ 0x04, 0x06 },	// P
	{ 0x04, 0x0B },	// Q
	{ 0x03, 0x02 },	// R
	{ 0x03, 0x00 },	// S
	{ 0x01, 0x01 },	// T
	{ 0x03, 0x04 },	// U
	{ 0x04, 0x08 },	// V
	{ 0x03, 0x06 },	// W
	{ 0x04, 0x09 },	// X
	{ 0x04, 0x0D },	// Y
	{ 0x04, 0x03 },	// Z
	{ 0x05, 0x1F },	// 0
	{ 0x05, 0x1E },	// 1
	{ 0x05, 0x1C },	// 2
	{ 0x05, 0x18 },	// 3
	{ 0x05, 0x10 },	// 4
	{ 0x05, 0x00 },	// 5
	{ 0x05, 0x01 },	// 6
	{ 0x05, 0x03 },	// 7
	{ 0x05, 0x07 },	// 8
	{ 0x05, 0x0F }	// 9
};

// Send one SHORT signal
void BlinkShort()
{
	PORTB &= ~(1 << PB3);
	#ifndef DEBUG
	_delay_ms(SHORT);
	#endif
	PORTB |= (1 << PB3);
}

// Send one LONG signal
void BlinkLong()
{
	PORTB &= ~(1 << PB3);
	#ifndef DEBUG
	_delay_ms(LONG);
	#endif
	PORTB |= (1 << PB3);
}

// Wait the SYMBOL_SPACE period
void WaitSymbolSpace()
{
	#ifndef DEBUG
	_delay_ms(SYMBOL_SPACE);
	#endif
}

// Wait the CHARACTER_SPACE period
void WaitCharacterSpace()
{
	#ifndef DEBUG
	_delay_ms(CHARACTER_SPACE);
	#endif
}

// Wait the WORD_SPACE period
void WaitWordSpace()
{
	#ifndef DEBUG
	_delay_ms(WORD_SPACE);
	#endif
}

// Wait the SENTENCE_SPACE period
void WaitSentenceSpace()
{
	#ifndef DEBUG
	_delay_ms(SENTENCE_SPACE);
	#endif
}

// Output one character code; pIndex: Index in _symbols array
void OutputCode(uint8_t pIndex)
{
	uint8_t symbolCount = _symbols[pIndex][0];
	uint8_t symbols = _symbols[pIndex][1];
	for (uint8_t i = 0; i < symbolCount; i++)
	{
		if ((symbols & (1 << i)) > 0)
		{
			BlinkLong();
		}
		else
		{
			BlinkShort();
		}
		if (i != symbolCount - 1)
		{
			WaitSymbolSpace();
		}
	}
	WaitCharacterSpace();
}

// Output one character; pCharacter: The character to send
void OutputCharacter(char pCharacter)
{
	// Upper case characters
	if (pCharacter >= 'A' && pCharacter <= 'Z')
	{
		OutputCode(pCharacter - 'A');
	}
	// Lower case characters
	else if (pCharacter >= 'a' && pCharacter <= 'z')
	{
		OutputCode(pCharacter - 'a');
	}
	// Decimals
	else if (pCharacter >= '0' && pCharacter <= '9')
	{
		OutputCode(26 + pCharacter - '0');
	}
	// The german Ä
	else if (pCharacter == 'Ä' || pCharacter == 'ä')
	{
		// will be splitted into AE
		OutputCharacter('A');
		OutputCharacter('E');
	}
	// The german Ö
	else if (pCharacter == 'Ö' || pCharacter == 'ö')
	{
		// will be splitted into OE
		OutputCharacter('O');
		OutputCharacter('E');
	}
	// The german Ü
	else if (pCharacter == 'Ü' || pCharacter == 'ü')
	{
		// will be splitted into UE
		OutputCharacter('U');
		OutputCharacter('E');
	}
	// The german ß
	else if (pCharacter == 'ß')
	{
		// will be splitted into SS
		OutputCharacter('S');
		OutputCharacter('S');
	}
	// The space between two words
	else if (pCharacter == ' ')
	{
		WaitWordSpace();
	}
}

// The entry point
int main( void )
{
    DDRB = ( 1 << PB3 );        // set PB3 at PORTB as output
	PORTB |= (1 << PB3);

	// read the save point
	uint16_t savePoint = eeprom_read_word((const uint16_t*)0);
	if (savePoint == 0xFFFF)
	{
		savePoint = 0;
	}
	
    while(1)
	{
		// output header (training for the receiving app)
		OutputCharacter('x');
		OutputCharacter('x');
		OutputCharacter('x');
		OutputCharacter(' ');
		// output the message
		int max = sizeof(_message) - savePoint;
		for (uint16_t i = savePoint; i < max; i++)
		{
			uint8_t nextCharacter = pgm_read_byte(_message + i);
			OutputCharacter(nextCharacter);
			// a complete word sent? (current character was a space)
			if (nextCharacter == ' ')
			{
				// write the save point to the last word
				eeprom_write_word((uint16_t*)0, savePoint);
				// the next save point is the start of the next word (current space + 1)
				savePoint = i + 1;
			}
		}
		// reset the save point
		eeprom_write_word((uint16_t*)0, 0);
		WaitSentenceSpace();
    }
    return 0;
}

In the _message variable I programmed a special greetings message for my friend. At christmas I gave this morse code blinkig led pen as a present back to my friend. They were really amazed about the present.