From owner-freebsd-arch@FreeBSD.ORG Fri Aug 31 10:42:31 2007 Return-Path: Delivered-To: arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E708416A417 for ; Fri, 31 Aug 2007 10:42:30 +0000 (UTC) (envelope-from phk@critter.freebsd.dk) Received: from phk.freebsd.dk (phk.freebsd.dk [130.225.244.222]) by mx1.freebsd.org (Postfix) with ESMTP id F207913C428 for ; Fri, 31 Aug 2007 10:42:29 +0000 (UTC) (envelope-from phk@critter.freebsd.dk) Received: from critter.freebsd.dk (unknown [192.168.61.5]) by phk.freebsd.dk (Postfix) with ESMTP id 7B2A417105 for ; Fri, 31 Aug 2007 09:42:52 +0000 (UTC) Received: from critter.freebsd.dk (localhost [127.0.0.1]) by critter.freebsd.dk (8.14.1/8.14.1) with ESMTP id l7V9gpKg008413 for ; Fri, 31 Aug 2007 09:42:52 GMT (envelope-from phk@critter.freebsd.dk) To: arch@freebsd.org From: Poul-Henning Kamp Date: Fri, 31 Aug 2007 09:42:51 +0000 Message-ID: <8412.1188553371@critter.freebsd.dk> Sender: phk@critter.freebsd.dk Cc: Subject: Proof of concept: soundcard as console device X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Aug 2007 10:42:31 -0000 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 #include #include #include #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 #include 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.