baud

Modem simulator
git clone https://git.woozle.org/neale/baud.git

Neale Pickett  ·  2024-01-22

baud.c

 1/*
 2 * Pretend to be a modem by throttling output.
 3 *
 4 * 2023-09-12 
 5 * Neale Pickett <neale@woozle.org>
 6 *
 7 * To the extent possible under law, 
 8 * I waive all copyright and related or neighboring rights to this software.
 9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stddef.h>
14#include <sysexits.h>
15#include <unistd.h>
16
17const int MICROSECOND = 1;
18const int MILLISECOND = 1000 * MICROSECOND;
19const int SECOND = 1000 * MILLISECOND;
20
21const int NOISINESS_DENOMINATOR = 36000;
22const int NOISELEN_DEFAULT = 16;
23
24int
25usage(char *me, char *error) {
26    if (error) {
27        fprintf(stderr, "ERROR: %s\n", error);
28    }
29    fprintf(stderr, "Usage: %s BAUD [NOISINESS] [NOISELEN]\n", me);
30    fprintf(stderr, "\n");
31    fprintf(stderr, "Reads stdin, and writes it back to stdout at BAUD bits per second.\n");
32    fprintf(stderr, "\n");
33    fprintf(stderr, "NOISINESS\tEvery bit can begin line noise, with probability NOISINESS/%d\n", NOISINESS_DENOMINATOR);
34    fprintf(stderr, "NOISELEN\tUp to this many bits of noise happens per burst (default: %d)\n", NOISELEN_DEFAULT);
35    return EX_USAGE;
36}
37
38int
39main(int argc, char *argv[]) {
40    if (argc < 2) {
41        return usage(argv[0], NULL);
42    }
43
44    int baud = atoi(argv[1]);
45    if (baud < 1) {
46        return usage(argv[0], "Invalid baud rate");
47    }
48
49    int noisiness = 0;
50    if (argc > 2) {
51        noisiness = atoi(argv[2]);
52    }
53    int noiselen = NOISELEN_DEFAULT;
54    if (argc > 3) {
55        noiselen = atoi(argv[3]);
56    }
57
58    int cps = baud / 10; // 8N1 has 10 bits per octet: 8 data, 1 start, 1 parity
59    int delay = SECOND / cps;
60    int noisybits = 0;
61    int c;
62    while ((c = getchar()) != EOF) {
63        usleep(delay);
64        for (int bit = 0; bit < 8; bit++) {
65            int r = random() % NOISINESS_DENOMINATOR;
66            if (r < noisiness) {
67                noisybits = random() % noiselen;
68            }
69
70            if (noisybits) {
71                c ^= (rand() & 1) << bit;
72                noisybits -= 1;
73            }
74        }
75        putchar(c);
76        fflush(stdout);
77    }
78    
79    return EX_OK;
80}