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.