Date: Fri, 31 Aug 2007 09:42:51 +0000 From: Poul-Henning Kamp <phk@phk.freebsd.dk> To: arch@freebsd.org Subject: Proof of concept: soundcard as console device Message-ID: <8412.1188553371@critter.freebsd.dk>
next in thread | raw e-mail | index | archive | help
Yesterday while I was futzing with my new laptop and ACPI suspend/resume, I once again found myself cursing the nutjob who took away our serial ports. Then my mind wandered around a bit and suddenly it struck me: all modern hardware have built in AC97 sound hardware, and it offers a channel with a pretty decent bandwidth. This morning I ran a simple experiment, from userland, but the result show clearly that the idea is workable. The transmission format I used: send a negative transient to start a character and after N samples, send a positive transient, where N is the ASCII value of the character + a small constant. I have attached my proof-of-concept code, which uses the two stereo channels as a differential wire (not sure if this is a actually good idea). In my first attempt, I was able to transmit around 320 characters per second with something that looks like 1% error rate. What's left to do: * optimize transmission schema. This can be done with two computers, a jack-jack cable and a bit of C-coding. The difference in sample rate between the two machines causes off-by-one errors. I don't know of a peak detector which interpolates can resolve this, of if we need use oversampling in the receiver. The two pulses can have two different polarities each, so we can transmit two bits just that way, this could speed up transmission by a factor of four, if we can find a way to synchronize properly. The two stereo channels can be used independently, offering a doubling in speed. * write a kernel console driver which talks to the sound hardware without using interrupts. I don't know what the hardware interface to a sound card looks like, but I suspect this might be fairly easy. Even if the connection is one-way, kernel-hackers like me will worship any person who completes this task. Have at it... Poul-Henning ----------------------------------------------------------------------- /* proof of concept transmission code */ #include <stdio.h> #include <assert.h> #include <fcntl.h> #include <sys/soundcard.h> #define OFF 5 static short int buf[2*128 + 2 * OFF]; int main(int argc __unused, char **argv __unused) { int fd_dsp; int i, j, k, c; fd_dsp = open("/dev/dsp0.1", O_RDWR); if (fd_dsp < 0) err(1, "open /dev/dsp"); i = ioctl(fd_dsp, SNDCTL_DSP_RESET, &j); assert(i == 0); j = 2; i = ioctl(fd_dsp, SNDCTL_DSP_CHANNELS, &j); assert(i == 0); j = 44100; i = ioctl(fd_dsp, SNDCTL_DSP_SPEED, &j); assert(i == 0); j = 16; i = ioctl(fd_dsp, SNDCTL_DSP_SETFMT, &j); assert(i == 0); while (1) { c = getchar(); if (c == EOF) break; buf[OFF] = 32000; buf[OFF + 1] = -32000; buf[OFF + 2 * c] = -32000; buf[OFF + 2 * c + 1] = 32000; i = write(fd_dsp, buf, sizeof buf); assert(i == sizeof buf); buf[OFF + 2 * c] = 0; buf[OFF + 1 + 2 * c] = 0; } exit (0); } ----------------------------------------------------------------------- /* proof of concept reception code */ #include <assert.h> #include <stdio.h> static int sample(FILE *f, const char *p) { short l, r; int i, s; i = fread(&l, sizeof l, 1, stdin); assert(i == 1); i = fread(&r, sizeof l, 1, stdin); assert(i == 1); s = l; s -= r; if (0 && p != NULL) printf("%6d %s\n", s, p); return (s); } static void find_neg_peak(FILE *f) { int s, sl; while (1) { s = sample(stdin, "v"); if (s < -10000) break; } sl = s; while (1) { s = sample(stdin, "N"); if (s > sl) return; sl = s; } } static int find_pos_peak(FILE *f) { int s, sl, k; k = 0; while (1) { k++; s = sample(stdin, "^"); if (s > 10000) break; } sl = s; while (1) { k++; s = sample(stdin, "P"); if (s < sl) return (k); sl = s; } } int main(int argc __unused, char **argv) { short l, r; int i, k, p, s, sl; k = 0; p = 0; while (1) { find_neg_peak(stdin); k = find_pos_peak(stdin); if (k == 10) printf("\\n\n"); else if (k >= ' ' && k <= '~') printf("%c", k); else printf("\\x%02x", k); } exit (0); } ----------------------------------------------------------------------- -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk@FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?8412.1188553371>