Skip to content

Instantly share code, notes, and snippets.

@versusvoid
Created August 13, 2015 11:45
Show Gist options
  • Save versusvoid/7ed681cd899173ce8db4 to your computer and use it in GitHub Desktop.
Save versusvoid/7ed681cd899173ce8db4 to your computer and use it in GitHub Desktop.
AVR morse hello world
#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