Select Git revision
-
William Grant authoredWilliam Grant authored
morse.c 9.56 KiB
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "buzzer.h"
// buffer sizes
static const size_t MAX_CHARS = 100u;
static const size_t MORSE_SIZE = MAX_CHARS * 6u;
// the 'unit' time in miliseconds
static const uint64_t UNIT_TIME = 50u;
typedef enum {
SHORT_SPACE, // the space between letters, 7 time units long
LONG_SPACE, // the space between words, 3 time units long
DOT, // a dot, 1 time unit long
DASH // a dash, 3 time units long
} morse_t;
// enable I/O and configure the pwm
static inline void setup() {
stdio_init_all();
buzzer_init();
sleep_ms(1000); // I've found it helps if you wait a bit for everything to get going
}
// convert the given string to morse code
static size_t string_to_morse(morse_t* morse, char* string, size_t size) {
size_t n = 0;
for (size_t i = 0; i < size; ++i) {
switch (string[i]) {
case 'a':
case 'A':
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'b':
case 'B':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 'c':
case 'C':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 'd':
case 'D':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 'e':
case 'E':
morse[n++] = DOT;
break;
case 'f':
case 'F':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 'g':
case 'G':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 'h':
case 'H':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 'i':
case 'I':
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 'j':
case 'J':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case 'k':
case 'K':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'l':
case 'L':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 'm':
case 'M':
morse[n++] = DASH;
morse[n++] = DASH;
break;
case 'n':
case 'N':
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 'o':
case 'O':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case 'p':
case 'P':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 'q':
case 'Q':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'r':
case 'R':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case 's':
case 'S':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case 't':
case 'T':
morse[n++] = DASH;
break;
case 'u':
case 'U':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'v':
case 'V':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'w':
case 'W':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case 'x':
case 'X':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case 'y':
case 'Y':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case 'z':
case 'Z':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case '1':
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case '2':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case '3':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
morse[n++] = DASH;
break;
case '4':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DASH;
break;
case '5':
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case '6':
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case '7':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case '8':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
morse[n++] = DOT;
break;
case '9':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DOT;
break;
case '0':
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
morse[n++] = DASH;
break;
default:
break; // skip unknown charaters
}
if (string[i] == ' ') {
// avoid double and leading spaces
if (n > 0u && morse[n - 1u] == SHORT_SPACE) {
morse[n - 1u] = LONG_SPACE;
}
} else {
morse[n++] = SHORT_SPACE;
}
}
return n;
}
// print the morse code to the terminal and play it with the buzzer
static void play_morse(morse_t* morse, size_t size) {
for (size_t i = 0; i < size; ++i) {
switch (morse[i]) {
case SHORT_SPACE:
putchar(' ');
sleep_ms(UNIT_TIME * 2u);
break;
case LONG_SPACE:
printf(" // ");
sleep_ms(UNIT_TIME * 6u);
break;
case DOT:
putchar('.');
buzzer_toggle(UNIT_TIME);
break;
case DASH:
putchar('-');
buzzer_toggle(UNIT_TIME * 3u);
break;
}
sleep_ms(UNIT_TIME);
}
putchar('\n');
}
// get a line of input from the user
static size_t get_line(char* buf, size_t size) {
size_t i;
printf(">> ");
for (i = 0; i < size; ++i) {
char c = getchar();
if (c == EOF || c == '\r' || c == '\n') {
putchar('\n');
buf[i] = '\0';
break;
} else {
putchar(c);
buf[i] = c;
}
}
return i;
}
int main(void) {
setup();
char* char_buf = malloc(sizeof(char) * MAX_CHARS);
morse_t* morse_buf = malloc(sizeof(morse_t) * MORSE_SIZE);
if (char_buf == NULL || morse_buf == NULL) {
perror("could not allocate buffers");
exit(1);
}
while (true) {
// read a line from input
size_t char_size = get_line(char_buf, MAX_CHARS);
// output line as morse code
size_t morse_size = string_to_morse(morse_buf, char_buf, char_size);
play_morse(morse_buf, morse_size);
}
}