Date: Fri, 31 Aug 2007 07:06:46 -0500 From: Tony Shadwick <tshadwick@oss-solutions.com> To: Poul-Henning Kamp <phk@phk.freebsd.dk> Cc: arch@freebsd.org Subject: Re: Proof of concept: soundcard as console device Message-ID: <46D80456.5020301@oss-solutions.com> In-Reply-To: <8412.1188553371@critter.freebsd.dk> References: <8412.1188553371@critter.freebsd.dk>
next in thread | previous in thread | raw e-mail | index | archive | help
Brilliant! :D I don't care if it doesn't get committed to the main tree. Put it in the ports tree....that's one heck of a hack! I love it! :) Poul-Henning Kamp wrote: > 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); > } > ----------------------------------------------------------------------- > > > >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?46D80456.5020301>