The Idea:
For a Radio Station (eg.
SubEther) you need to control your mixer volumes smoothly in an analog way to fade from one channel to another.
The Concept:
The well known Joystick port is just an Analog interface, and almost any mainstream PC Soundcard has one. The generic support provieds 4 Axis and 4 Buttons. We can use one Axis per mixer channel. Thus we can controll 4 different mixer channels on one fader board.
The Heck:
So let me see. The Linux kernel already has 'joyport' support. So compile the nesecarry modules:
Character devices --->
Joysticks --->
[M] Game port support
[M] Classic ISA/PnP gameports
[M] Microsoft SideWinder digital joysticks and gamepads
Normally the input module ns558.o supports 4 channels (Axis: X, Y) so we are able to fade VOL, PCM, LINE and CD.
I had a SideWinder for testing purpose. This can be used with an additional module that can read 6 analog channels (2 more Axis: for Ruder and Throttle) from a digital controller inside the joystick.
Documentation/input/joystick.txt
Is a good point to start reading. And a few googles later there was some code:
The Code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <libintl.h>
#include <locale.h>
Just the default bunch of include headers. And joystick.h for the js kernel API
#include <linux/joystick.h>
The Sound stuff is included because we need to access the mixer device
#include <linux/sound.h>
#include <linux/soundcard.h>
Some predefines
#define JS_EVENT_BUTTON 0x01 /* button pressed/released */
#define JS_EVENT_AXIS 0x02 /* joystick moved */
#define JS_EVENT_INIT 0x80 /* initial state of device */
#define NAME_LENGTH 128
#define SCALE1 28934
#define DIVIDE1 290
#define SCALE2 27273
#define DIVIDE2 273
#define SCALE3 27624
#define DIVIDE3 277
#define SCALE4 29372
#define DIVIDE4 294
#define SHIFT 99
main()
int main(int argv, char *argc[])
{
int fd, mixfd;
unsigned char axes = 4;
unsigned char buttons = 4;
int version = 0x000800;
char name[NAME_LENGTH] = "Unknown";
int *axis;
int *button;
unsigned char i,j,k,l;
int m,n,o,p;
struct js_event js;
Open the devices /dev/js0 and /dev/mixer
if ((fd = open("/dev/js0" , O_RDONLY)) < 0) {
perror("potmix");
return 1;
}
if ((mixfd = open("/dev/mixer", O_RDWR)) < 0) {
perror("potmix");
return 1;
}
setup the joystick device
ioctl(fd, JSIOCGVERSION , &version);
ioctl(fd, JSIOCGAXES , &axes);
ioctl(fd, JSIOCGBUTTONS , &buttons);
ioctl(fd, JSIOCGNAME(NAME_LENGTH), name);
axis = (int*)calloc(axes , sizeof(int));
button = (int*)calloc(buttons, sizeof(char));
Now the ugly part, first an infinite loop.
while (1) {
this reads the structure with status information from the joystick
if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
perror("\npotmix: error reading");
return 2;
}
write the button or axis state into an array
switch(js.type & ~JS_EVENT_INIT) {
case JS_EVENT_BUTTON:
button[js.number] = js.value;
break;
case JS_EVENT_AXIS:
axis[js.number] = js.value;
break;
}
due to the fact that we recive the axis state as signed integer, we have to
calculate values between 0-100(decimal) for the mixer.
if (axes) {
// + 32757 ) / 655;
i = ((((axis[0])*(-1) + SCALE1 ) / DIVIDE1 ) - SHIFT) ;
j = ((((axis[1])*(-1) + SCALE2 ) / DIVIDE2 ) - SHIFT) ;
k = ((((axis[2])*(-1) + SCALE3 ) / DIVIDE3 ) - SHIFT) ;
l = ((((axis[3])*(-1) + SCALE4 ) / DIVIDE4 ) - SHIFT) ;
this part is used to wirte the new value to the mixer device, thanks roh for
m = ((((i) & 0xff) <<8) | ((i) & 0xff));
n = ((((j) & 0xff) <<8) | ((j) & 0xff));
o = ((((k) & 0xff) <<8) | ((k) & 0xff));
p = ((((l) & 0xff) <<8) | ((l) & 0xff));
ioctl(mixfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &m);
ioctl(mixfd, MIXER_WRITE(SOUND_MIXER_PCM) , &n);
ioctl(mixfd, MIXER_WRITE(SOUND_MIXER_CD) , &o);
ioctl(mixfd, MIXER_WRITE(SOUND_MIXER_LINE) , &p);
the rest is foo, the whole thing is an evil hack, does never reach the return,
and hopefully will live a ling time.
printf("\r (%5d,%5d,%5d,%5d) 0x%2x 0x%2x 0x%2x 0x%2x ",i,j,k,l,m,n,o,p);
usleep(1000);
}
fflush(stdout);
}
return 23;
}
exit 23;
The Hardware:
100 kOhm oder so zeuch...roh