morse.c


1
#include <stdint.h>
2
#include <stddef.h>
3
#include <stdio.h>
4
5
typedef uint8_t morse_symbol_t;
6
7
#define MORSE_MAPPING \
8
  X('A', 0x06) X('B', 0x11) X('C', 0x15) X('D', 0x09) \
9
  X('E', 0x02) X('F', 0x14) X('G', 0x0B) X('H', 0x10) \
10
  X('I', 0x04) X('J', 0x1E) X('K', 0x0D) X('L', 0x12) \
11
  X('M', 0x07) X('N', 0x05) X('O', 0x0F) X('P', 0x16) \
12
  X('Q', 0x1B) X('R', 0x0A) X('S', 0x08) X('T', 0x03) \
13
  X('U', 0x0C) X('V', 0x18) X('W', 0x0E) X('X', 0x19) \
14
  X('Y', 0x1D) X('Z', 0x13) X('1', 0x3E) X('2', 0x3C) \
15
  X('3', 0x38) X('4', 0x30) X('5', 0x20) X('6', 0x21) \
16
  X('7', 0x23) X('8', 0x27) X('9', 0x2F) X('0', 0x3F) \
17
  X(' ', 0x01) X('.', 0x6A) X(',', 0x73) X(':', 0x47) \
18
  X(';', 0x55) X('?', 0x4C) X('!', 0x75) X('-', 0x61) \
19
  X('_', 0x6C) X('(', 0x2D) X(')', 0x6D) X('\'', 0x5E) \
20
  X('=', 0x31) X('+', 0x2A) X('/', 0x29) X('@', 0x56)
21
22
#define X(C, M) [C] = M,
23
morse_symbol_t char_morse_map[] = {
24
  MORSE_MAPPING
25
  X('a', 0x06) X('b', 0x11) X('c', 0x15) X('d', 0x09)
26
  X('e', 0x02) X('f', 0x14) X('g', 0x0B) X('h', 0x10)
27
  X('i', 0x04) X('j', 0x1E) X('k', 0x0D) X('l', 0x12)
28
  X('m', 0x07) X('n', 0x05) X('o', 0x0F) X('p', 0x16)
29
  X('q', 0x1B) X('r', 0x0A) X('s', 0x08) X('t', 0x03)
30
  X('u', 0x0C) X('v', 0x18) X('w', 0x0E) X('x', 0x19)
31
  X('y', 0x1D) X('z', 0x13)
32
};
33
#undef X
34
const size_t char_morse_map_count = sizeof(char_morse_map) / sizeof(*char_morse_map);
35
36
#define X(C, M) [M] = C,
37
char morse_char_map[] = {MORSE_MAPPING};
38
#undef X
39
const size_t morse_char_map_count = sizeof(morse_char_map) / sizeof(*morse_char_map);
40
41
#undef MORSE_MAPPING
42
43
typedef char morse_symbol_sequence_t[8];
44
45
unsigned morse_symbol_sequence_unpack(morse_symbol_sequence_t ret, morse_symbol_t symbol){
46
  if(symbol == 1){ // 5 di pause and the prev+this symbol end di pause, makes a 7 di pause overall
47
    ret[0] = ' ';
48
    ret[1] = ' ';
49
    ret[2] = ' ';
50
    ret[3] = ' ';
51
    ret[4] = ' ';
52
    ret[5] = '\0';
53
    return 6;
54
  }
55
  unsigned i=0;
56
  while(symbol > 1){
57
    ret[i++] = ".-"[symbol%2];
58
    symbol /= 2;
59
  }
60
  ret[i] = '\0';
61
  return i;
62
}
63
64
morse_symbol_t morse_symbol_sequence_pack(const morse_symbol_sequence_t seq){
65
  if(seq[0]==' ' && seq[1]==' ' && seq[2]==' ' && seq[3]==' ' && seq[4]==' ' && seq[5]=='\0')
66
    return 0x1;
67
  morse_symbol_t res = 1;
68
  for(unsigned i; seq[i]; i++){
69
    char x = seq[i];
70
    res *= 2;
71
    if(x == '-'){
72
      res += 1;
73
    }else if(x != '.')
74
      return 0;
75
  }
76
  return res;
77
}
78
79
morse_symbol_t morse_lookup_char(char c){
80
  unsigned char uc = c;
81
  if(uc > char_morse_map_count)
82
    return 0;
83
  return char_morse_map[uc];
84
}
85
86
char morse_lookup_symbol(morse_symbol_t s){
87
  if(s > morse_char_map_count)
88
    return 0;
89
  return morse_char_map[s];
90
}
91
92
int func_puts(const char* c, int(*putchar)(int c)){
93
  if(!c) return -1;
94
  while(*c)
95
    if(putchar(*(c++)) == EOF)
96
      return -1;
97
  return 0;
98
}
99
100
int morse_putchar(int ch){
101
  morse_symbol_sequence_t sequence;
102
  morse_symbol_t symbol = morse_lookup_char(ch);
103
  if(!morse_symbol_sequence_unpack(sequence, symbol))
104
    {};
105
  printf("%s ", sequence);
106
  return ch;
107
}
108
109
int main(){
110
  func_puts("Hello World!", putchar);
111
  puts("");
112
  func_puts("Hello World!", morse_putchar);
113
  puts("");
114
  return 0;
115
}