Skip to content
Snippets Groups Projects
Select Git revision
  • b732cac4b3c938a2483f8dd25abfbc5b50b83645
  • main default protected
2 results

morse.c

Blame
  • 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);
        }
    }