root/branches/libffado-2.0/src/motu/motu_controls.cpp

Revision 1300, 23.5 kB (checked in by jwoithe, 13 years ago)

MOTU: merge recent trunk mixer changes to 2.0 branch from revisions 1257, 1265 and 1274 ("svn merge -r REV" for REV = 1256:1257, 1264:1265, 1273:1274). Not yet tested.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2008 by Jonathan Woithe
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 // This also includes motu_controls.h
26 #include "motu_avdevice.h"
27
28 namespace Motu {
29
30 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg)
31 : Control::Discrete(&parent)
32 , m_parent(parent)
33 , m_register(dev_reg)
34 {
35 }
36
37 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg,
38              std::string name, std::string label, std::string descr)
39 : Control::Discrete(&parent)
40 , m_parent(parent)
41 , m_register(dev_reg)
42 {
43     setName(name);
44     setLabel(label);
45     setDescription(descr);
46 }
47
48 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
49   unsigned int val_mask, unsigned int setenable_mask)
50 : MotuDiscreteCtrl(parent, dev_reg)
51 {
52     m_value_mask = val_mask;
53     /* If no "write enable" is implemented for a given switch it's safe to
54      * pass zero in to setenable_mask.
55      */
56     m_setenable_mask = setenable_mask;
57 }
58
59 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
60     unsigned int val_mask, unsigned int setenable_mask,
61     std::string name, std::string label, std::string descr)
62 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
63 {
64     m_value_mask = val_mask;
65     /* If no "write enable" is implemented for a given switch it's safe to
66      * pass zero in to setenable_mask.
67      */
68     m_setenable_mask = setenable_mask;
69 }
70              
71 bool
72 MotuBinarySwitch::setValue(int v)
73 {
74     unsigned int val;
75     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for switch %s (0x%04x) to %d\n",
76       getName().c_str(), m_register, v);
77
78     // Set the value
79     if (m_setenable_mask) {
80       val = (v==0)?0:m_value_mask;
81       // Set the "write enable" bit for the value being set
82       val |= m_setenable_mask;
83     } else {
84       // It would be good to utilise the cached value from the receive
85       // processor (if running) later on.  For now we'll just fetch the
86       // current register value directly when needed.
87       val = m_parent.ReadRegister(m_register);
88       if (v==0)
89         val &= ~m_value_mask;
90       else
91         val |= m_value_mask;
92     }
93     m_parent.WriteRegister(m_register, val);
94
95     return true;
96 }
97
98 int
99 MotuBinarySwitch::getValue()
100 {
101     unsigned int val;
102     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for switch %s (0x%04x)\n",
103       getName().c_str(), m_register);
104
105     // FIXME: we could just read the appropriate mixer status field from the
106     // receive stream processor once we work out an efficient way to do this.
107     val = m_parent.ReadRegister(m_register);
108     return (val & m_value_mask) != 0;
109 }
110
111 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg)
112 : MotuDiscreteCtrl(parent, dev_reg)
113 {
114 }
115
116 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg,
117              std::string name, std::string label, std::string descr)
118 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
119 {
120 }
121              
122 bool
123 ChannelFader::setValue(int v)
124 {
125     unsigned int val;
126     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel fader 0x%04x to %d\n", m_register, v);
127
128     val = v<0?0:v;
129     if (val > 0x80)
130       val = 0x80;
131     // Bit 30 indicates that the channel fader is being set
132     val |= 0x40000000;
133     m_parent.WriteRegister(m_register, val);
134
135     return true;
136 }
137
138 int
139 ChannelFader::getValue()
140 {
141     unsigned int val;
142     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel fader 0x%04x\n", m_register);
143
144     // FIXME: we could just read the appropriate mixer status field from the
145     // receive stream processor once we work out an efficient way to do this.
146     val = m_parent.ReadRegister(m_register);
147     return val & 0xff;
148 }
149
150 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg)
151 : MotuDiscreteCtrl(parent, dev_reg)
152 {
153 }
154
155 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg,
156              std::string name, std::string label, std::string descr)
157 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
158 {
159 }
160              
161 bool
162 ChannelPan::setValue(int v)
163 {
164     unsigned int val;
165     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel pan 0x%04x to %d\n", m_register, v);
166
167     val = ((v<-64?-64:v)+64) & 0xff;
168     if (val > 0x80)
169       val = 0x80;
170     // Bit 31 indicates that pan is being set
171     val = (val << 8) | 0x80000000;
172     m_parent.WriteRegister(m_register, val);
173
174     return true;
175 }
176
177 int
178 ChannelPan::getValue()
179 {
180     unsigned int val;
181     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel pan 0x%04x\n", m_register);
182
183     // FIXME: we could just read the appropriate mixer status field from the
184     // receive stream processor once we work out an efficient way to do this.
185     val = m_parent.ReadRegister(m_register);
186     return ((val >> 8) & 0xff) - 0x40;
187 }
188
189
190 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent)
191 : Control::MatrixMixer(&parent, "MatrixMixer")
192 , m_parent(parent)
193 {
194 }
195
196 MotuMatrixMixer::MotuMatrixMixer(MotuDevice &parent, std::string name)
197 : Control::MatrixMixer(&parent, name)
198 , m_parent(parent)
199 {
200 }
201
202 void MotuMatrixMixer::addRowInfo(std::string name, unsigned int flags,
203   unsigned int address)
204 {
205     struct sSignalInfo s;
206     s.name = name;
207     s.flags = flags;
208     s.address = address;
209     m_RowInfo.push_back(s);
210 }
211
212 void MotuMatrixMixer::addColInfo(std::string name, unsigned int flags,
213   unsigned int address)
214 {
215     struct sSignalInfo s;
216     s.name = name;
217     s.flags = flags;
218     s.address = address;
219     m_ColInfo.push_back(s);
220 }
221
222 uint32_t MotuMatrixMixer::getCellRegister(const unsigned int row, const unsigned int col)
223 {
224     return m_RowInfo.at(row).address + m_ColInfo.at(col).address;
225 }
226
227 void MotuMatrixMixer::show()
228 {
229     debugOutput(DEBUG_LEVEL_NORMAL, "MOTU matrix mixer\n");
230 }
231
232 std::string MotuMatrixMixer::getRowName(const int row)
233 {
234     return m_RowInfo.at(row).name;
235 }
236
237 std::string MotuMatrixMixer::getColName(const int col)
238 {
239     return m_ColInfo.at(col).name;
240 }
241
242 int MotuMatrixMixer::getRowCount()
243 {
244     return m_RowInfo.size();
245 }
246
247 int MotuMatrixMixer::getColCount()
248 {
249     return m_ColInfo.size();
250 }
251
252 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent)
253 : MotuMatrixMixer(parent, "ChannelFaderMatrixMixer")
254 {
255 }
256
257 ChannelFaderMatrixMixer::ChannelFaderMatrixMixer(MotuDevice &parent, std::string name)
258 : MotuMatrixMixer(parent, name)
259 {
260 }
261
262 double ChannelFaderMatrixMixer::setValue(const int row, const int col, const double val)
263 {
264     uint32_t v;
265     v = val<0?0:(uint32_t)val;
266     if (v > 0x80)
267       v = 0x80;
268     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader setValue for row %d col %d to %lf (%ld)\n",
269       row, col, val, v);
270
271     // Bit 30 indicates that the channel fader is being set
272     v |= 0x40000000;
273     m_parent.WriteRegister(getCellRegister(row,col), v);
274
275     return true;
276 }
277
278 double ChannelFaderMatrixMixer::getValue(const int row, const int col)
279 {
280     uint32_t val;
281     // FIXME: we could just read the appropriate mixer status field from the
282     // receive stream processor once we work out an efficient way to do this.
283     val = m_parent.ReadRegister(getCellRegister(row,col)) & 0xff;
284
285     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelFader getValue for row %d col %d = %lu\n",
286       row, col, val);
287     return val;
288 }
289
290 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent)
291 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
292 {
293 }
294
295 ChannelPanMatrixMixer::ChannelPanMatrixMixer(MotuDevice &parent, std::string name)
296 : MotuMatrixMixer(parent, name)
297 {
298 }
299
300 double ChannelPanMatrixMixer::setValue(const int row, const int col, const double val)
301 {
302     uint32_t v;
303     v = ((val<-64?-64:(int32_t)val)+64) & 0xff;
304     if (v > 0x80)
305       v = 0x80;
306
307     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan setValue for row %d col %d to %lf (%ld)\n",
308       row, col, val, v);
309
310     // Bit 31 indicates that pan is being set
311     v = (v << 8) | 0x80000000;
312     m_parent.WriteRegister(getCellRegister(row,col), v);
313
314     return true;
315 }
316
317 double ChannelPanMatrixMixer::getValue(const int row, const int col)
318 {
319     int32_t val;
320     // FIXME: we could just read the appropriate mixer status field from the
321     // receive stream processor once we work out an efficient way to do this.
322     val = m_parent.ReadRegister(getCellRegister(row,col));
323     val = ((val >> 8) & 0xff) - 0x40;
324
325     debugOutput(DEBUG_LEVEL_VERBOSE, "ChannelPan getValue for row %d col %d = %lu\n",
326       row, col, val);
327     return val;
328 }
329
330 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent)
331 : MotuMatrixMixer(parent, "ChannelPanMatrixMixer")
332 , m_value_mask(0)
333 , m_setenable_mask(0)
334 {
335 }
336
337 /* If no "write enable" is implemented for a given switch it's safe to
338  * pass zero in to setenable_mask.
339  */
340 ChannelBinSwMatrixMixer::ChannelBinSwMatrixMixer(MotuDevice &parent, std::string name,
341   unsigned int val_mask, unsigned int setenable_mask)
342 : MotuMatrixMixer(parent, name)
343 , m_value_mask(val_mask)
344 , m_setenable_mask(setenable_mask)
345 {
346 }
347
348 double ChannelBinSwMatrixMixer::setValue(const int row, const int col, const double val)
349 {
350     uint32_t v;
351
352     debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw setValue for row %d col %d to %lf (%ld)\n",
353       row, col, val, val==0?0:1);
354
355     // Set the value
356     if (m_setenable_mask) {
357       v = (val==0)?0:m_value_mask;
358       // Set the "write enable" bit for the value being set
359       v |= m_setenable_mask;
360     } else {
361       // It would be good to utilise the cached value from the receive
362       // processor (if running) later on.  For now we'll just fetch the
363       // current register value directly when needed.
364       v = m_parent.ReadRegister(getCellRegister(row,col));
365       if (v==0)
366         v &= ~m_value_mask;
367       else
368         v |= m_value_mask;
369     }
370     m_parent.WriteRegister(getCellRegister(row,col), v);
371
372     return true;
373 }
374
375 double ChannelBinSwMatrixMixer::getValue(const int row, const int col)
376 {
377     uint32_t val;
378
379     // FIXME: we could just read the appropriate mixer status field from the
380     // receive stream processor once we work out an efficient way to do this.
381     val = m_parent.ReadRegister(getCellRegister(row,col));
382     val = (val & m_value_mask) != 0;
383
384     debugOutput(DEBUG_LEVEL_VERBOSE, "BinSw getValue for row %d col %d = %lu\n",
385       row, col, val);
386     return val;
387 }
388
389
390 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg)
391 : MotuDiscreteCtrl(parent, dev_reg)
392 {
393 }
394
395 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg,
396              std::string name, std::string label, std::string descr)
397 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
398 {
399 }
400              
401 bool
402 MixFader::setValue(int v)
403 {
404     unsigned int val;
405     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix fader 0x%04x to %d\n", m_register, v);
406
407     val = v<0?0:v;
408     if (val > 0x80)
409       val = 0x80;
410     // Bit 24 indicates that the mix fader is being set
411     val |= 0x01000000;
412     m_parent.WriteRegister(m_register, val);
413
414     return true;
415 }
416
417 int
418 MixFader::getValue()
419 {
420     unsigned int val;
421     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix fader 0x%04x\n", m_register);
422
423     // FIXME: we could just read the appropriate mixer status field from the
424     // receive stream processor once we work out an efficient way to do this.
425     val = m_parent.ReadRegister(m_register);
426     return val & 0xff;
427 }
428
429 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg)
430 : MotuDiscreteCtrl(parent, dev_reg)
431 {
432 }
433
434 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg,
435              std::string name, std::string label, std::string descr)
436 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
437 {
438 }
439              
440 bool
441 MixMute::setValue(int v)
442 {
443     unsigned int val, dest;
444     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix mute 0x%04x to %d\n", m_register, v);
445
446     // Need to read current destination so we can preserve that when setting
447     // mute status (mute and destination are always set together).
448     dest = m_parent.ReadRegister(m_register) & 0x00000f00;
449     // Mute status is bit 12
450     val = (v==0)?0:0x00001000;
451     // Bit 25 indicates that mute and destination are being set.  Also
452     // preserve the current destination.
453     val |= 0x02000000 | dest;
454     m_parent.WriteRegister(m_register, val);
455
456     return true;
457 }
458
459 int
460 MixMute::getValue()
461 {
462     unsigned int val;
463     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix mute 0x%04x\n", m_register);
464
465     // FIXME: we could just read the appropriate mixer status field from the
466     // receive stream processor once we work out an efficient way to do this.
467     val = m_parent.ReadRegister(m_register);
468     return (val & 0x00001000) != 0;
469 }
470
471 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg)
472 : MotuDiscreteCtrl(parent, dev_reg)
473 {
474 }
475
476 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg,
477              std::string name, std::string label, std::string descr)
478 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
479 {
480 }
481              
482 bool
483 MixDest::setValue(int v)
484 {
485     unsigned int val, mute;
486     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix destination 0x%04x to %d\n", m_register, v);
487
488     // Need to get current mute status so we can preserve it
489     mute = m_parent.ReadRegister(m_register) & 0x00001000;
490     val = v;
491     /* Currently destination values between 0 and 0x0b are accepted.
492      * Ultimately this will be device (and device configuration) dependent.
493      */
494     if (val<0 || val>0x0b)
495       val = 0;
496     /* Destination is given by bits 11-8.  Add in the current mute status so
497      * it can be preserved (it's set concurrently with the destination).
498      */
499     val = (val << 8) | mute;
500     // Bit 25 indicates that mute and destination are being set
501     val |= 0x02000000;
502     m_parent.WriteRegister(m_register, val);
503
504     return true;
505 }
506
507 int
508 MixDest::getValue()
509 {
510     unsigned int val;
511     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix destination 0x%04x\n", m_register);
512
513     // FIXME: we could just read the appropriate mixer status field from the
514     // receive stream processor once we work out an efficient way to do this.
515     val = m_parent.ReadRegister(m_register);
516     return (val >> 8) & 0x0f;
517 }
518
519 PhonesSrc::PhonesSrc(MotuDevice &parent)
520 : MotuDiscreteCtrl(parent, 0)
521 {
522 }
523
524 PhonesSrc::PhonesSrc(MotuDevice &parent,
525              std::string name, std::string label, std::string descr)
526 : MotuDiscreteCtrl(parent, 0, name, label, descr)
527 {
528 }
529              
530 bool
531 PhonesSrc::setValue(int v)
532 {
533     unsigned int val;
534     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for phones destination to %d\n", v);
535
536     /* Currently destination values between 0 and 0x0b are accepted.
537      * Ultimately this will be device (and device configuration) dependent.
538      */
539     val = v;
540     if (val<0 || val>0x0b)
541       val = 0;
542     // Destination is given by bits 3-0.
543     // Bit 24 indicates that the phones source is being set.
544     val |= 0x01000000;
545     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
546
547     return true;
548 }
549
550 int
551 PhonesSrc::getValue()
552 {
553     unsigned int val;
554     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for phones destination\n");
555
556     // FIXME: we could just read the appropriate mixer status field from the
557     // receive stream processor once we work out an efficient way to do this.
558     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
559     return val & 0x0f;
560 }
561
562 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg)
563 : MotuDiscreteCtrl(parent, dev_reg)
564 {
565 }
566
567 OpticalMode::OpticalMode(MotuDevice &parent, unsigned int dev_reg,
568              std::string name, std::string label, std::string descr)
569 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
570 {
571 }
572              
573 bool
574 OpticalMode::setValue(int v)
575 {
576     unsigned int val;
577     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for optical mode %d to %d\n", m_register, v);
578
579     // Need to get current optical modes so we can preserve the one we're
580     // not setting.  Input mode is in bits 9-8, output is in bits 11-10.
581     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF) & 0x00000f00;
582
583     // Set mode as requested.  An invalid setting is effectively ignored.
584     if (v>=0 && v<=3) {
585       if (m_register == MOTU_DIR_IN) {
586         val = (val & ~0x0300) | ((v & 0x03) << 8);
587       } else {
588         val = (val & ~0x0c00) | ((v & 0x03) << 10);
589       }
590     }
591     // Bit 25 indicates that optical modes are being set
592     val |= 0x02000000;
593     m_parent.WriteRegister(MOTU_REG_ROUTE_PORT_CONF, val);
594
595     return true;
596 }
597
598 int
599 OpticalMode::getValue()
600 {
601     unsigned int val;
602     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for optical mode %d\n", m_register);
603
604     // FIXME: we could just read the appropriate mixer status field from the
605     // receive stream processor once we work out an efficient way to do this.
606     val = m_parent.ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
607     if (m_register == MOTU_DIR_IN)
608       val = (val >> 8) & 0x03;
609     else
610       val = (val >> 10) & 0x03;
611     return val;
612 }
613
614 InputGainPad::InputGainPad(MotuDevice &parent, unsigned int channel, unsigned int mode)
615 : MotuDiscreteCtrl(parent, channel)
616 {
617     m_mode = mode;
618     validate();
619 }
620
621 InputGainPad::InputGainPad(MotuDevice &parent, unsigned int channel, unsigned int mode,
622              std::string name, std::string label, std::string descr)
623 : MotuDiscreteCtrl(parent, channel, name, label, descr)
624 {
625     m_mode = mode;
626     validate();
627 }
628
629 void InputGainPad::validate(void) {
630     if (m_register > MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL) {
631         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid channel %d: max supported is %d, assuming 0\n",
632             m_register, MOTU_CTRL_TRIMGAINPAD_MAX_CHANNEL);
633         m_register = 0;
634     }
635     if (m_mode!=MOTU_CTRL_MODE_PAD && m_mode!=MOTU_CTRL_MODE_TRIMGAIN) {
636         debugOutput(DEBUG_LEVEL_VERBOSE, "Invalid mode %d, assuming %d\n", m_mode, MOTU_CTRL_MODE_PAD);
637         m_mode = MOTU_CTRL_MODE_PAD;
638     }
639 }
640
641 unsigned int InputGainPad::dev_register(void) {
642     /* Work out the device register to use for the associated channel */
643     if (m_register>=0 && m_register<=3) {
644       return MOTU_REG_INPUT_GAIN_PAD_0;     
645     } else {
646       debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported channel %d\n", m_register);
647     }
648     return 0;
649 }
650              
651 bool
652 InputGainPad::setValue(int v)
653 {
654     unsigned int val;
655     unsigned int reg, reg_shift;
656     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mode %d input pad/trim %d to %d\n", m_mode, m_register, v);
657
658     reg = dev_register();
659     if (reg == 0)
660         return false;
661     reg_shift = (m_register & 0x03) * 8;
662
663     // Need to get current gain trim / pad value so we can preserve one
664     // while setting the other.  The pad status is in bit 6 of the channel's
665     // respective byte with the trim in bits 0-5.  Bit 7 is the write enable
666     // bit for the channel.
667     val = m_parent.ReadRegister(reg) & (0xff << reg_shift);
668
669     switch (m_mode) {
670         case MOTU_CTRL_MODE_PAD:
671             // Set pad bit (bit 6 of relevant channel's byte)
672             if (v == 0) {
673                 val &= ~(0x40 << reg_shift);
674             } else {
675                 val |= (0x40 << reg_shift);
676             }
677             break;
678       case MOTU_CTRL_MODE_TRIMGAIN:
679             // Set the gain trim (bits 0-5 of the channel's byte).  Maximum
680             // gain is 53 dB.
681             if (v > 0x35)
682                 v = 0x35;
683             val = (val & ~(0x3f << reg_shift)) | (v << reg_shift);
684             break;
685       default:
686         debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
687         return false;
688     }
689
690     // Set the channel's write enable bit
691     val |= (0x80 << reg_shift);
692
693     m_parent.WriteRegister(reg, val);
694
695     return true;
696 }
697
698 int
699 InputGainPad::getValue()
700 {
701     unsigned int val;
702     unsigned int reg, reg_shift;
703     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mode %d input pad/trim %d\n", m_mode, m_register);
704
705     reg = dev_register();
706     if (reg == 0)
707         return false;
708     reg_shift = (m_register & 0x03) * 8;
709
710     // The pad status is in bit 6 of the channel's respective byte with the
711     // trim in bits 0-5.  Bit 7 is the write enable bit for the channel.
712     val = m_parent.ReadRegister(reg);
713
714     switch (m_mode) {
715         case MOTU_CTRL_MODE_PAD:
716             val = ((val >> reg_shift) & 0x40) != 0;
717             break;
718       case MOTU_CTRL_MODE_TRIMGAIN:
719             val = ((val >> reg_shift) & 0x3f);
720             break;
721       default:
722         debugOutput(DEBUG_LEVEL_VERBOSE, "unsupported mode %d\n", m_mode);
723         return 0;
724     }
725
726     return val;
727 }
728
729 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
730 : MotuDiscreteCtrl(parent, infotype)
731 {
732 }
733
734 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
735              std::string name, std::string label, std::string descr)
736 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
737 {
738 }
739              
740 bool
741 InfoElement::setValue(int v)
742 {
743     /* This is a read-only field, so any call to setValue() is technically
744      * an error.
745      */
746     debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
747     return false;
748 }
749
750 int
751 InfoElement::getValue()
752 {
753     unsigned int val;
754     signed int res = 0;
755
756     switch (m_register) {
757         case MOTU_INFO_MODEL:
758             res = m_parent.m_motu_model;
759             debugOutput(DEBUG_LEVEL_VERBOSE, "Model: %d\n", res);
760             break;
761         case MOTU_INFO_IS_STREAMING:
762             val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
763             /* Streaming is active if either bit 22 (Motu->PC streaming
764              * enable) or bit 30 (PC->Motu streaming enable) is set.
765              */
766             res = (val & 0x40400000) != 0;
767             debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
768             break;
769         case MOTU_INFO_SAMPLE_RATE:
770             res = m_parent.getSamplingFrequency();
771             debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
772             break;
773         case MOTU_INFO_HAS_MIC_INPUTS:
774             /* Only the 828Mk2 has separate mic inputs.  In time this may be
775              * deduced by walking the port info array within the parent.
776              */
777             res = m_parent.m_motu_model == MOTU_MODEL_828mkII ? 1:0;
778             debugOutput(DEBUG_LEVEL_VERBOSE, "Has mic inputs: %d\n", res);
779             break;
780         case MOTU_INFO_HAS_AESEBU_INPUTS:
781             /* AES/EBU inputs are currently present on the Traveler and
782              * 896HD.  In time this may be deduced by walking the port info
783              * array within the parent.
784              */
785             val = m_parent.m_motu_model;
786             res = (val==MOTU_MODEL_TRAVELER || val==MOTU_MODEL_896HD);
787             debugOutput(DEBUG_LEVEL_VERBOSE, "HasAESEBUInputs: %d\n", res);
788             break;
789         case MOTU_INFO_HAS_SPDIF_INPUTS:
790             /* SPDIF inputs are present on all supported models except the
791              * 896HD and the 8pre.  In time this may be deduced by walking
792              * the port info array within the parent.
793              */
794             val = m_parent.m_motu_model;
795             res = (val!=MOTU_MODEL_8PRE && val!=MOTU_MODEL_896HD);
796             debugOutput(DEBUG_LEVEL_VERBOSE, "HasSPDIFInputs: %d\n", res);
797             break;
798         case MOTU_INFO_HAS_OPTICAL_SPDIF:
799             /* THe 896HD doesn't have optical SPDIF capability */
800             val = m_parent.m_motu_model;
801             res = (val != MOTU_MODEL_896HD);
802             debugOutput(DEBUG_LEVEL_VERBOSE, "HasOpticalSPDIF: %d\n", res);
803             break;
804     }
805     return res;
806 }
807
808 }
Note: See TracBrowser for help on using the browser.