Created
August 13, 2015 11:45
-
-
Save versusvoid/7ed681cd899173ce8db4 to your computer and use it in GitHub Desktop.
AVR morse hello world
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/io.h> | |
#include <avr/interrupt.h> | |
#include <avr/sleep.h> | |
#include <stdint.h> | |
// First four bits encode morse code - 1 is dash and 0 is dot | |
// then goes length of code | |
char message[] = { | |
0x04, // .... - H | |
0x01, // . - E | |
0x44, // .-.. - L | |
0x44, // .-.. - L | |
0x73, // --- - O | |
0x00, // space | |
0x33, // .-- - W | |
0x73, // --- - O | |
0x23, // .-. - R | |
0x44, // .-.. - L | |
0x43, // -.. - D | |
}; | |
// index of letter | |
uint8_t messageIndex = 0; | |
// index of morse symbol, 0 - leftmost | |
uint8_t subIndex = 0; | |
// flag, whether it is pause between morse symbols | |
// not necessary, PORTD7 bit can be used, but more readable | |
uint8_t pause = 1; | |
const uint8_t MaxIndex = sizeof(message)/sizeof(char); | |
// number of cycles for single morse dot symbol | |
const uint16_t DotCyclesNum = 5000; | |
int main(void) | |
{ | |
//Setup the clock | |
cli(); //Disable global interrupts | |
TCCR1B |= 1<<CS11 | 1<<CS10; //Divide by 64 | |
TCCR1B |= 1<<WGM12; //Put Timer/Counter1 in CTC mode | |
OCR1A = DotCyclesNum; //set timer period | |
TIMSK |= 1<<OCIE1A; //enable timer compare interrupt | |
//Setup the I/O for the LED | |
DDRD |= (1<<DDD7); //Set PortD Pin7 as an output | |
PORTD |= (0<<PORTD7); //Set PortD Pin7 low to turn off LED | |
set_sleep_mode(SLEEP_MODE_IDLE); | |
sleep_enable(); | |
sei(); //Enable global interrupts | |
while(1) { sleep_cpu(); } //Loop forever, interrupts do the rest | |
} | |
// signal dot or dash | |
void proceedMessageDisplay() { | |
uint8_t maxSubIndex = message[messageIndex] & 0x0F; // length of letter in morse code | |
// if one - signal dash, else dot | |
if (message[messageIndex] & (0x1 << (3 + maxSubIndex - subIndex))) { | |
OCR1A = 3*DotCyclesNum; | |
} else { | |
OCR1A = DotCyclesNum; | |
} | |
} | |
void pauseMessageDisplay() { | |
// there are three types of pauses: | |
uint8_t symbolPause = 1, | |
characterPause = 0, | |
wordPause = 0; | |
subIndex += 1; | |
if (subIndex >= (message[messageIndex] & 0x0F)) { | |
// moving to next letter | |
symbolPause = 0; | |
characterPause = 1; | |
subIndex = 0; | |
messageIndex += 1; | |
} | |
uint8_t overflow = messageIndex == MaxIndex; | |
if (overflow || message[messageIndex] == 0x00) { | |
// moving to next word or cycling | |
characterPause = 0; | |
wordPause = 1; | |
if (overflow) { | |
messageIndex = 0; | |
} else { | |
messageIndex += 1; | |
} | |
} | |
if (symbolPause) { | |
OCR1A = DotCyclesNum; | |
} else if (characterPause) { | |
OCR1A = 3*DotCyclesNum; | |
} else { | |
OCR1A = 7*DotCyclesNum; | |
} | |
} | |
ISR(TIMER1_COMPA_vect) //Interrupt Service Routine | |
{ | |
cli(); | |
if (pause) { | |
proceedMessageDisplay(); | |
} else { | |
pauseMessageDisplay(); | |
} | |
pause ^= 1; | |
SFIOR |= 1<<PSR10; // reseting timer | |
sei(); | |
PORTD ^= (1<<PORTD7); // switching led | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment