1Beta release of the rme96xx (driver for RME 96XX cards like the
2"Hammerfall" and the "Hammerfall light")
3
4Important: The driver module has to be installed on a freshly rebooted system,
5otherwise the driver might not be able to acquire its buffers.
6
7features:
8
9 - OSS programming interface (i.e. runs with standard OSS soundsoftware)
10 - OSS/Multichannel interface (OSS multichannel is done by just aquiring
11   more than 2 channels). The driver does not use more than one device
12   ( yet .. this feature may be implemented later )
13 - more than one RME card supported
14
15The driver uses a specific multichannel interface, which I will document
16when the driver gets stable. (take a look at the defines in rme96xx.h,
17which adds blocked multichannel formats i.e instead of
18lrlrlrlr --> llllrrrr  etc.
19
20Use the "rmectrl" programm to look at the status of the card ..
21or use xrmectrl, a GUI interface for the ctrl program.
22
23What you can do with the rmectrl program is to set the stereo device for
24OSS emulation (e.g. if you use SPDIF out).
25
26You do:
27
28./ctrl offset 24 24
29
30which makes the stereo device use channels 25 and 26.
31
32Guenter Geiger <geiger@epy.co.at>
33
34copy the first part of the attached source code into rmectrl.c
35and the  second part into xrmectrl (or get the program from
36http://gige.xdv.org/pages/soft/pages/rme)
37
38to compile: gcc -o rmectrl rmectrl.c
39------------------------------ snip ------------------------------------
40
41#include <stdio.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/ioctl.h>
45#include <fcntl.h>
46#include <linux/soundcard.h>
47#include <math.h>
48#include <unistd.h>
49#include <stdlib.h>
50#include "rme96xx.h"
51
52/*
53  remctrl.c
54  (C) 2000 Guenter Geiger <geiger@debian.org>
55  HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
56*/
57
58/* # define DEVICE_NAME "/dev/mixer" */
59# define DEVICE_NAME "/dev/mixer1"
60
61
62void usage(void)
63{
64     fprintf(stderr,"usage: rmectrl [/dev/mixer<n>] [command [options]]\n\n");
65     fprintf(stderr,"where command is one of:\n");
66     fprintf(stderr,"  help                       show this help\n");
67     fprintf(stderr,"  status                     show status bits\n");
68     fprintf(stderr,"  control                    show control bits\n");
69     fprintf(stderr,"  mix                        show mixer/offset status\n");
70     fprintf(stderr,"  master <n>                 set sync master\n");
71     fprintf(stderr,"  pro <n>                    set spdif out pro\n");
72     fprintf(stderr,"  emphasis <n>               set spdif out emphasis\n");
73     fprintf(stderr,"  dolby <n>                  set spdif out no audio\n");
74     fprintf(stderr,"  optout <n>                 set spdif out optical\n");
75     fprintf(stderr,"  wordclock <n>              set sync wordclock\n");
76     fprintf(stderr,"  spdifin <n>                set spdif in (0=optical,1=coax,2=intern)\n");
77     fprintf(stderr,"  syncref <n>                set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n");
78     fprintf(stderr,"  adat1cd <n>                set ADAT1 on internal CD\n");
79     fprintf(stderr,"  offset <devnr> <in> <out>  set dev (0..3) offset (0..25)\n");
80     exit(-1);
81}
82
83
84int main(int argc, char* argv[])
85{
86     int cards;
87     int ret;
88     int i;
89     double ft;
90     int fd, fdwr;
91     int param,orig;
92     rme_status_t stat;
93     rme_ctrl_t ctrl;
94     char *device;
95     int argidx;
96
97     if (argc < 2)
98	  usage();
99
100     if (*argv[1]=='/') {
101	  device = argv[1];
102	  argidx = 2;
103     }
104     else {
105	  device = DEVICE_NAME;
106	  argidx = 1;
107     }
108
109     fprintf(stdout,"mixer device %s\n",device);
110     if ((fd = open(device,O_RDONLY)) < 0) {
111	  fprintf(stdout,"opening device failed\n");
112	  exit(-1);
113     }
114
115     if ((fdwr = open(device,O_WRONLY)) < 0) {
116	  fprintf(stdout,"opening device failed\n");
117	  exit(-1);
118     }
119
120     if (argc < argidx+1)
121	  usage();
122
123     if (!strcmp(argv[argidx],"help"))
124        usage();
125     if (!strcmp(argv[argidx],"-h"))
126        usage();
127     if (!strcmp(argv[argidx],"--help"))
128        usage();
129
130     if (!strcmp(argv[argidx],"status")) {
131	  ioctl(fd,SOUND_MIXER_PRIVATE2,&stat);
132	  fprintf(stdout,"stat.irq %d\n",stat.irq);
133	  fprintf(stdout,"stat.lockmask %d\n",stat.lockmask);
134	  fprintf(stdout,"stat.sr48 %d\n",stat.sr48);
135	  fprintf(stdout,"stat.wclock %d\n",stat.wclock);
136	  fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint);
137	  fprintf(stdout,"stat.syncmask %d\n",stat.syncmask);
138	  fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed);
139	  fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy);
140	  fprintf(stdout,"stat.tc_out %d\n",stat.tc_out);
141	  fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate);
142	  fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error);
143	  fprintf(stdout,"stat.bufid %d\n",stat.bufid);
144	  fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid);
145	  exit (0);
146     }
147
148     if (!strcmp(argv[argidx],"control")) {
149	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
150	  fprintf(stdout,"ctrl.start %d\n",ctrl.start);
151	  fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency);
152	  fprintf(stdout,"ctrl.master %d\n",ctrl.master);
153	  fprintf(stdout,"ctrl.ie %d\n",ctrl.ie);
154	  fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48);
155	  fprintf(stdout,"ctrl.spare %d\n",ctrl.spare);
156	  fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed);
157	  fprintf(stdout,"ctrl.pro %d\n",ctrl.pro);
158	  fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis);
159	  fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby);
160	  fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out);
161	  fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock);
162	  fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in);
163	  fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref);
164	  fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset);
165	  fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select);
166	  fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock);
167	  fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write);
168	  fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd);
169	  exit (0);
170     }
171
172     if (!strcmp(argv[argidx],"mix")) {
173	  rme_mixer mix;
174	  int i;
175
176	  for (i=0; i<4; i++) {
177	       mix.devnr = i;
178	       ioctl(fd,SOUND_MIXER_PRIVATE1,&mix);
179	       if (mix.devnr == i) {
180		    fprintf(stdout,"devnr %d\n",mix.devnr);
181		    fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset);
182		    fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset);
183	       }
184	  }
185	  exit (0);
186     }
187
188/* the control flags */
189
190     if (argc < argidx+2)
191	  usage();
192
193     if (!strcmp(argv[argidx],"master")) {
194	  int val = atoi(argv[argidx+1]);
195	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
196	  printf("master = %d\n",val);
197	  ctrl.master = val;
198	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
199	  exit (0);
200     }
201
202     if (!strcmp(argv[argidx],"pro")) {
203	  int val = atoi(argv[argidx+1]);
204	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
205	  printf("pro = %d\n",val);
206	  ctrl.pro = val;
207	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
208	  exit (0);
209     }
210
211     if (!strcmp(argv[argidx],"emphasis")) {
212	  int val = atoi(argv[argidx+1]);
213	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
214	  printf("emphasis = %d\n",val);
215	  ctrl.emphasis = val;
216	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
217	  exit (0);
218     }
219
220     if (!strcmp(argv[argidx],"dolby")) {
221	  int val = atoi(argv[argidx+1]);
222	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
223	  printf("dolby = %d\n",val);
224	  ctrl.dolby = val;
225	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
226	  exit (0);
227     }
228
229     if (!strcmp(argv[argidx],"optout")) {
230	  int val = atoi(argv[argidx+1]);
231	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
232	  printf("optout = %d\n",val);
233	  ctrl.opt_out = val;
234	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
235	  exit (0);
236     }
237
238     if (!strcmp(argv[argidx],"wordclock")) {
239	  int val = atoi(argv[argidx+1]);
240	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
241	  printf("wordclock = %d\n",val);
242	  ctrl.wordclock = val;
243	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
244	  exit (0);
245     }
246
247     if (!strcmp(argv[argidx],"spdifin")) {
248	  int val = atoi(argv[argidx+1]);
249	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
250	  printf("spdifin = %d\n",val);
251	  ctrl.spdif_in = val;
252	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
253	  exit (0);
254     }
255
256     if (!strcmp(argv[argidx],"syncref")) {
257	  int val = atoi(argv[argidx+1]);
258	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
259	  printf("syncref = %d\n",val);
260	  ctrl.sync_ref = val;
261	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
262	  exit (0);
263     }
264
265     if (!strcmp(argv[argidx],"adat1cd")) {
266	  int val = atoi(argv[argidx+1]);
267	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
268	  printf("adat1cd = %d\n",val);
269	  ctrl.adat1_cd = val;
270	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
271	  exit (0);
272     }
273
274/* setting offset */
275
276     if (argc < argidx+4)
277	  usage();
278
279     if (!strcmp(argv[argidx],"offset")) {
280	  rme_mixer mix;
281
282	  mix.devnr = atoi(argv[argidx+1]);
283
284	  mix.i_offset = atoi(argv[argidx+2]);
285	  mix.o_offset = atoi(argv[argidx+3]);
286	  ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix);
287	  fprintf(stdout,"devnr %d\n",mix.devnr);
288	  fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset);
289	  fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset);
290	  exit (0);
291     }
292
293     usage();
294     exit (0); /* to avoid warning */
295}
296
297
298---------------------------- <snip> --------------------------------
299#!/usr/bin/wish
300
301# xrmectrl
302# (C) 2000 Guenter Geiger <geiger@debian.org>
303# HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
304
305#set defaults "-relief ridged"
306set CTRLPROG "./rmectrl"
307if {$argc} {
308    set CTRLPROG "$CTRLPROG $argv"
309}
310puts "CTRLPROG $CTRLPROG"
311
312frame .butts
313button .butts.exit -text "Exit" -command "exit" -relief ridge
314#button .butts.state -text "State" -command "get_all"
315
316pack .butts.exit -side left
317pack .butts -side bottom
318
319
320#
321# STATUS
322#
323
324frame .status
325
326# Sampling Rate
327
328frame .status.sr
329label .status.sr.text -text "Sampling Rate" -justify left
330radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times
331radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times
332radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times
333radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw  -variable srate -value 96000 -font times
334
335pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3
336
337# Lock
338
339frame .status.lock
340label .status.lock.text -text "Lock" -justify left
341checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times
342checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times
343checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times
344
345pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3
346
347# Sync
348
349frame .status.sync
350label .status.sync.text -text "Sync" -justify left
351checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times
352checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times
353checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times
354
355pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3
356
357# Timecode
358
359frame .status.tc
360label .status.tc.text -text "Timecode" -justify left
361checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times
362checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times
363checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times
364
365pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3
366
367# SPDIF In
368
369frame .status.spdif
370label .status.spdif.text -text "SPDIF In" -justify left
371label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times
372checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times
373
374pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3
375
376pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1
377
378
379#
380# CONTROL
381#
382
383proc setprof {} {
384    global CTRLPROG
385    global spprof
386    exec $CTRLPROG pro $spprof
387}
388
389proc setemph {} {
390    global CTRLPROG
391    global spemph
392    exec $CTRLPROG emphasis $spemph
393}
394
395proc setnoaud {} {
396    global CTRLPROG
397    global spnoaud
398    exec $CTRLPROG dolby $spnoaud
399}
400
401proc setoptical {} {
402    global CTRLPROG
403    global spoptical
404    exec $CTRLPROG optout $spoptical
405}
406
407proc setspdifin {} {
408    global CTRLPROG
409    global spdifin
410    exec $CTRLPROG spdifin [expr $spdifin - 1]
411}
412
413proc setsyncsource {} {
414    global CTRLPROG
415    global syncsource
416    exec $CTRLPROG syncref [expr $syncsource -1]
417}
418
419
420proc setmaster {} {
421    global CTRLPROG
422    global master
423    exec $CTRLPROG master $master
424}
425
426proc setwordclock {} {
427    global CTRLPROG
428    global wordclock
429    exec $CTRLPROG wordclock $wordclock
430}
431
432proc setadat1cd {} {
433    global CTRLPROG
434    global adat1cd
435    exec $CTRLPROG adat1cd $adat1cd
436}
437
438
439frame .control
440
441# SPDIF In & SPDIF Out
442
443
444frame .control.spdif
445
446frame .control.spdif.in
447label .control.spdif.in.text -text "SPDIF In" -justify left
448radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times
449radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times
450radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times
451
452checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times
453
454pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd
455
456label .control.spdif.space
457
458frame .control.spdif.out
459label .control.spdif.out.text -text "SPDIF Out" -justify left
460checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times
461checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times
462checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times
463checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times
464
465pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom
466
467pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1
468
469# Sync Mode & Sync Source
470
471frame .control.sync
472frame .control.sync.mode
473label .control.sync.mode.text -text "Sync Mode" -justify left
474checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times
475checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times
476
477pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc
478
479label .control.sync.space
480
481frame .control.sync.src
482label .control.sync.src.text -text "Sync Source" -justify left
483radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times
484radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times
485radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times
486radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times
487
488pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom
489
490pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1
491
492label .control.space -text "" -width 10
493
494# Buffer Size
495
496frame .control.buf
497label .control.buf.text -text "Buffer Size (Latency)" -justify left
498radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times
499radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times
500radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times
501radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times
502radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times
503radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times
504radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times
505radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times
506
507pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3
508
509# Offset
510
511frame .control.offset
512
513frame .control.offset.in
514label .control.offset.in.text -text "Offset In" -justify left
515label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
516label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
517label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
518label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
519
520pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3
521
522label .control.offset.space
523
524frame .control.offset.out
525label .control.offset.out.text -text "Offset Out" -justify left
526label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
527label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
528label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
529label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
530
531pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom
532
533pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1
534
535
536pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1
537
538
539label .statustext -text Status -justify center -relief ridge
540label .controltext -text Control -justify center -relief ridge
541
542label .statusspace
543label .controlspace
544
545pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1
546
547
548proc get_bit {output sstr} {
549    set idx1 [string last [concat $sstr 1] $output]
550    set idx1 [expr $idx1 != -1]
551    return $idx1
552}
553
554proc get_val {output sstr} {
555    set val [string wordend $output [string last $sstr $output]]
556    set val [string range $output $val [expr $val+1]]
557    return $val
558}
559
560proc get_val2 {output sstr} {
561    set val [string wordend $output [string first $sstr $output]]
562    set val [string range $output $val [expr $val+2]]
563    return $val
564}
565
566proc get_control {} {
567    global spprof
568    global spemph
569    global spnoaud
570    global spoptical
571    global spdifin
572    global ssrate
573    global master
574    global wordclock
575    global syncsource
576    global CTRLPROG
577
578    set f [open "| $CTRLPROG control" r+]
579    set ooo [read $f 1000]
580    close $f
581#    puts $ooo
582
583    set spprof [ get_bit $ooo "pro"]
584    set spemph [ get_bit $ooo "emphasis"]
585    set spnoaud [ get_bit $ooo "dolby"]
586    set spoptical [ get_bit $ooo "opt_out"]
587    set spdifin [ expr [ get_val $ooo "spdif_in"] + 1]
588    set ssrate [ expr [ get_val $ooo "latency"] + 1]
589    set master [ expr [ get_val $ooo "master"]]
590    set wordclock [ expr [ get_val $ooo "wordclock"]]
591    set syncsource [ expr [ get_val $ooo "sync_ref"] + 1]
592}
593
594proc get_status {} {
595    global srate
596    global ctrlcom
597
598    global adatlock1
599    global adatlock2
600    global adatlock3
601
602    global adatsync1
603    global adatsync2
604    global adatsync3
605
606    global tcbusy
607    global tcout
608    global tcvalid
609
610    global spdiferr
611    global crystal
612    global .status.spdif.text
613    global CTRLPROG
614
615
616    set f [open "| $CTRLPROG status" r+]
617    set ooo [read $f 1000]
618    close $f
619#    puts $ooo
620
621# samplerate
622
623    set idx1 [string last "sr48 1" $ooo]
624    set idx2 [string last "doublespeed 1" $ooo]
625    if {$idx1 >= 0} {
626	set fact1 48000
627    } else {
628	set fact1 44100
629    }
630
631    if {$idx2 >= 0} {
632	set fact2 2
633    } else {
634	set fact2 1
635    }
636    set srate [expr $fact1 * $fact2]
637#   ADAT lock
638
639    set val [get_val $ooo lockmask]
640    set adatlock1 0
641    set adatlock2 0
642    set adatlock3 0
643    if {[expr $val & 1]} {
644       set adatlock3 1
645    }
646    if {[expr $val & 2]} {
647       set adatlock2 1
648    }
649    if {[expr $val & 4]} {
650       set adatlock1 1
651    }
652
653#  ADAT sync
654    set val [get_val $ooo syncmask]
655    set adatsync1 0
656    set adatsync2 0
657    set adatsync3 0
658
659    if {[expr $val & 1]} {
660       set adatsync3 1
661    }
662    if {[expr $val & 2]} {
663       set adatsync2 1
664    }
665    if {[expr $val & 4]} {
666       set adatsync1 1
667    }
668
669# TC busy
670
671    set tcbusy [get_bit $ooo "busy"]
672    set tcout [get_bit $ooo "out"]
673    set tcvalid [get_bit $ooo "valid"]
674    set spdiferr [expr [get_bit $ooo "spdif_error"] == 0]
675
676#  000=64kHz, 100=88.2kHz, 011=96kHz
677#  111=32kHz, 110=44.1kHz, 101=48kHz
678
679    set val [get_val $ooo crystalrate]
680
681    set crystal "--.- kHz"
682    if {$val == 0} {
683        set crystal "64 kHz"
684    }
685    if {$val == 4} {
686        set crystal "88.2 kHz"
687    }
688    if {$val == 3} {
689        set crystal "96 kHz"
690    }
691    if {$val == 7} {
692        set crystal "32 kHz"
693    }
694    if {$val == 6} {
695        set crystal "44.1 kHz"
696    }
697    if {$val == 5} {
698        set crystal "48 kHz"
699    }
700    .status.spdif.sr configure -text $crystal
701}
702
703proc get_offset {} {
704    global inoffset
705    global outoffset
706    global CTRLPROG
707
708    set f [open "| $CTRLPROG mix" r+]
709    set ooo [read $f 1000]
710    close $f
711#    puts $ooo
712
713    if { [string match "*devnr*" $ooo] } {
714	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
715	set val [get_val2 $ooo i_offset]
716	.control.offset.in.off0 configure -text "dev\#0: $val"
717	set val [get_val2 $ooo o_offset]
718	.control.offset.out.off0 configure -text "dev\#0: $val"
719    } else {
720	.control.offset.in.off0 configure -text "dev\#0: -"
721	.control.offset.out.off0 configure -text "dev\#0: -"
722    }
723    if { [string match "*devnr*" $ooo] } {
724	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
725	set val [get_val2 $ooo i_offset]
726	.control.offset.in.off1 configure -text "dev\#1: $val"
727	set val [get_val2 $ooo o_offset]
728	.control.offset.out.off1 configure -text "dev\#1: $val"
729    } else {
730	.control.offset.in.off1 configure -text "dev\#1: -"
731	.control.offset.out.off1 configure -text "dev\#1: -"
732    }
733    if { [string match "*devnr*" $ooo] } {
734	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
735	set val [get_val2 $ooo i_offset]
736	.control.offset.in.off2 configure -text "dev\#2: $val"
737	set val [get_val2 $ooo o_offset]
738	.control.offset.out.off2 configure -text "dev\#2: $val"
739    } else {
740	.control.offset.in.off2 configure -text "dev\#2: -"
741	.control.offset.out.off2 configure -text "dev\#2: -"
742    }
743    if { [string match "*devnr*" $ooo] } {
744	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
745	set val [get_val2 $ooo i_offset]
746	.control.offset.in.off3 configure -text "dev\#3: $val"
747	set val [get_val2 $ooo o_offset]
748	.control.offset.out.off3 configure -text "dev\#3: $val"
749    } else {
750	.control.offset.in.off3 configure -text "dev\#3: -"
751	.control.offset.out.off3 configure -text "dev\#3: -"
752    }
753}
754
755
756proc get_all {} {
757get_status
758get_control
759get_offset
760}
761
762# main
763while {1} {
764  after 200
765  get_all
766  update
767}
768