root/trunk/libffado/src/dice/focusrite/saffire_pro24.cpp

Revision 2139, 10.6 kB (checked in by jwoithe, 12 years ago)

dice: default router setup patch 6/10 from Philippe Carriere: DICE EAP Saffire Pro 24 Introduce specific default routing functions. The default configuration for low mid rate has been extracted from output listing from a Pro 24 user. For mid rate, it is an extrapolation which might require further corrections.

Line 
1 /*
2  * Copyright (C) 2009 by Pieter Palmers
3  * Copyright (C) 2009 by Arnold Krille
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 #include "saffire_pro24.h"
26 #include "focusrite_eap.h"
27
28 namespace Dice {
29 namespace Focusrite {
30
31 int SaffirePro24::SaffirePro24EAP::commandToFix(unsigned offset) {
32     if (offset<0x14) return 2;
33     if (offset<0x3C && offset>=0x14) return 1;
34     if (offset<0x58 && offset>=0x50) return 1;
35     if (offset<0x40 && offset>=0x3C) return 3;
36     if (offset<0x60 && offset>=0x58) return 4;
37     return 0;
38 }
39 FocusriteEAP::Poti* SaffirePro24::SaffirePro24EAP::getMonitorPoti(std::string name) {
40     return new FocusriteEAP::Poti(this, name, 0x50);
41 }
42 FocusriteEAP::Poti* SaffirePro24::SaffirePro24EAP::getDimPoti(std::string name) {
43     return new FocusriteEAP::Poti(this, name, 0x54);
44 }
45
46 /*
47 void SaffirePro24::SaffirePro24EAP::setupSources() {
48     addSource("SPDIF",  6,  2, eRS_AES);
49     addSource("ADAT",   0,  8, eRS_ADAT);
50     addSource("Analog", 0,  4, eRS_InS0);
51     addSource("Mixer",  0, 16, eRS_Mixer);
52     addSource("1394",   0,  8, eRS_ARX0);
53     addSource("Mute",   0,  1, eRS_Muted);
54 }
55 void SaffirePro24::SaffirePro24EAP::setupDestinations() {
56     addDestination("SPDIF",  6,  2, eRD_AES);
57     addDestination("Analog", 0,  6, eRD_InS0);
58     addDestination("Mixer",  0, 16, eRD_Mixer0);
59     addDestination("Mixer",  0,  2, eRD_Mixer1, 16);
60     addDestination("1394",   0, 16, eRD_ATX0);
61     addDestination("Mute",   0,  1, eRD_Muted);
62 }
63 */
64
65 void SaffirePro24::SaffirePro24EAP::setupSources_low() {
66     addSource("SPDIF",  6,  2, eRS_AES, 1);
67     addSource("ADAT",   0,  8, eRS_ADAT, 1);
68     addSource("Analog", 0,  4, eRS_InS0, 1);
69     addSource("Mixer",  0, 16, eRS_Mixer, 1);
70     addSource("1394",   0,  8, eRS_ARX0, 1);
71     addSource("Mute",   0,  1, eRS_Muted);
72 }
73 void SaffirePro24::SaffirePro24EAP::setupDestinations_low() {
74     addDestination("SPDIF",  6,  2, eRD_AES, 1);
75     addDestination("Analog", 0,  6, eRD_InS0, 1);
76     addDestination("Mixer",  0, 16, eRD_Mixer0, 1);
77     addDestination("Mixer",  0,  2, eRD_Mixer1, 17);
78     addDestination("1394",   0, 16, eRD_ATX0, 1);
79 // Is a Mute destination useful ?
80 //    addDestination("Mute",   0,  1, eRD_Muted);
81 }
82
83 void SaffirePro24::SaffirePro24EAP::setupSources_mid() {
84     addSource("SPDIF",  6,  2, eRS_AES, 1);
85     addSource("ADAT",   0,  4, eRS_ADAT, 1);
86     addSource("Analog", 0,  4, eRS_InS0, 1);
87     addSource("Mixer",  0, 16, eRS_Mixer, 1);
88     addSource("1394",   0,  8, eRS_ARX0, 1);
89     addSource("Mute",   0,  1, eRS_Muted);
90 }
91 void SaffirePro24::SaffirePro24EAP::setupDestinations_mid() {
92     addDestination("SPDIF",  6,  2, eRD_AES, 1);
93     addDestination("Analog", 0,  6, eRD_InS0, 1);
94     addDestination("Mixer",  0, 16, eRD_Mixer0, 1);
95     addDestination("Mixer",  0,  2, eRD_Mixer1, 17);
96     addDestination("1394",   0, 12, eRD_ATX0, 1);
97 // Is a Mute destination useful ?
98 //    addDestination("Mute",   0,  1, eRD_Muted);
99 }
100
101 void SaffirePro24::SaffirePro24EAP::setupSources_high() {
102     printMessage("High (192 kHz) sample rate not supported by Saffire Pro 24\n");
103 }
104
105 void SaffirePro24::SaffirePro24EAP::setupDestinations_high() {
106     printMessage("High (192 kHz) sample rate not supported by Saffire Pro 24\n");
107 }
108
109 /**
110  * The default configurations for the Saffire Pro 24 router.
111  *  For coherence with hardware, destinations must follow a specific ordering
112  *  There must be 44 destinations at low samplerate
113  *  Front LEDs are connected to the first four router entries
114  */
115 void
116 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_low() {
117     unsigned int i;
118     // the 1394 stream receivers except the two "loops" one
119     for (i=0; i<4; i++) {
120         addRoute(eRS_InS0, i, eRD_ATX0, i);
121     }
122     for (i=0; i<2; i++) {
123         addRoute(eRS_AES, i+6, eRD_ATX0, i+4);
124     }
125     for (i=0; i<8; i++) {
126         addRoute(eRS_ADAT, i, eRD_ATX0, i+6);
127     }
128     // The audio ports
129     // Ensure that audio port are not muted
130     for (i=0; i<6; i++) {
131         addRoute(eRS_ARX0, i%2, eRD_InS0, i);
132     }
133     // the SPDIF receiver
134     for (i=0; i<2; i++) {
135         addRoute(eRS_Muted, 0, eRD_AES, i+6);
136     }
137     // the "loops" 1394 stream receivers
138     for (i=0; i<2; i++) {
139         addRoute(eRS_Muted, i, eRD_ATX0, i+14);
140     }
141     // the Mixer inputs
142     for (i=0; i<4; i++) {
143         addRoute(eRS_InS0, i, eRD_Mixer0, i);
144     }
145     for (i=0; i<2; i++) {
146         addRoute(eRS_AES, i+6, eRD_Mixer0, i+4);
147     }
148     for (i=0; i<8; i++) {
149         addRoute(eRS_ADAT, i, eRD_Mixer0, i+6);
150     }
151     for (i=0; i<2; i++) {
152         addRoute(eRS_ARX0, i, eRD_Mixer0, i+14);
153     }
154     for (i=0; i<2; i++) {
155         addRoute(eRS_Muted, 0, eRD_Mixer1, i);
156     }
157     // The two mute destinations
158     for (i=0; i<2; i++) {
159         addRoute(eRS_Mixer, i, eRD_Muted, 0);
160     }
161 }
162
163 /**
164  *  There must be 40 (?) destinations at mid samplerate
165  *  Front LEDs are connected to the first four router entries
166  */
167 void
168 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_mid() {
169     unsigned int i;
170     // the 1394 stream receivers except the two "loops" one
171     for (i=0; i<4; i++) {
172         addRoute(eRS_InS0, i, eRD_ATX0, i);
173     }
174     for (i=0; i<2; i++) {
175         addRoute(eRS_AES, i+6, eRD_ATX0, i+4);
176     }
177     for (i=0; i<4; i++) {
178         addRoute(eRS_ADAT, i, eRD_ATX0, i+6);
179     }
180     // The audio ports
181     // Ensure that audio port are not muted
182     for (i=0; i<6; i++) {
183         addRoute(eRS_ARX0, i%2, eRD_InS0, i);
184     }
185     // the SPDIF receiver
186     for (i=0; i<2; i++) {
187         addRoute(eRS_Muted, 0, eRD_AES, i+6);
188     }
189     // the "loops" 1394 stream receivers
190     for (i=0; i<2; i++) {
191         addRoute(eRS_Muted, i, eRD_ATX0, i+10);
192     }
193     // the Mixer inputs
194     for (i=0; i<4; i++) {
195         addRoute(eRS_InS0, i, eRD_Mixer0, i);
196     }
197     for (i=0; i<2; i++) {
198         addRoute(eRS_AES, i+6, eRD_Mixer0, i+4);
199     }
200     for (i=0; i<4; i++) {
201         addRoute(eRS_ADAT, i, eRD_Mixer0, i+6);
202     }
203     for (i=0; i<2; i++) {
204         addRoute(eRS_ARX0, i, eRD_Mixer0, i+10);
205     }
206     for (i=0; i<4; i++) {
207         addRoute(eRS_Muted, 0, eRD_Mixer0, i+12);
208     }
209     for (i=0; i<2; i++) {
210         addRoute(eRS_Muted, 0, eRD_Mixer1, i);
211     }
212     // The two mute destinations
213     for (i=0; i<2; i++) {
214         addRoute(eRS_Mixer, i, eRD_Muted, 0);
215     }
216 }
217
218 /**
219  *  High rate not supported
220  */
221 void
222 SaffirePro24::SaffirePro24EAP::setupDefaultRouterConfig_high() {
223     printMessage("High (192 kHz) sample rate not supported by Saffire Pro 40\n");
224 }
225
226 class SaffirePro24::LineInstSwitch : public Dice::Focusrite::FocusriteEAP::Switch
227 {
228 public:
229     LineInstSwitch(Dice::Focusrite::FocusriteEAP* eap, std::string name, size_t offset, int activevalue)
230         : Dice::Focusrite::FocusriteEAP::Switch(eap, name, offset, activevalue) {}
231     std::string getBooleanLabel(bool n) {
232         if ( n ) return "Instrument";
233         return "Line";
234     }
235 };
236 class SaffirePro24::LevelSwitch : public Dice::Focusrite::FocusriteEAP::Switch
237 {
238 public:
239     LevelSwitch(Dice::Focusrite::FocusriteEAP* eap, std::string name, size_t offset, int activevalue)
240         : Dice::Focusrite::FocusriteEAP::Switch(eap, name, offset, activevalue) {}
241     std::string getBooleanLabel(bool n) {
242         if ( n ) return "High";
243         return "Low";
244     }
245 };
246
247 SaffirePro24::SaffirePro24( DeviceManager& d,
248                             std::auto_ptr<ConfigRom>( configRom ))
249     : Dice::Device(d , configRom)
250     , m_ch1(NULL)
251     , m_ch2(NULL)
252 {
253     debugOutput(DEBUG_LEVEL_VERBOSE, "Created Dice::Focusrite::SaffirePro24 (NodeID %d)\n",
254                 getConfigRom().getNodeId());
255 }
256
257 SaffirePro24::~SaffirePro24()
258 {
259     //debugOutput(DEBUG_LEVEL_VERBOSE, "Deleting the saffirePro24\n");
260     /// I wonder whether we should really save only on clean exits or also each time a setting is
261     //  changed. Or should we provide a function (and thus gui-button) to save the state of the
262     //  device?
263     getEAP()->storeFlashConfig();
264     getEAP()->deleteElement(m_ch1);
265     getEAP()->deleteElement(m_ch2);
266     if (m_ch1) delete m_ch1;
267     if (m_ch2) delete m_ch2;
268 }
269
270 bool SaffirePro24::discover() {
271     if (Dice::Device::discover()) {
272         fb_quadlet_t* tmp = (fb_quadlet_t *)calloc(2, sizeof(fb_quadlet_t));
273         getEAP()->readRegBlock(Dice::EAP::eRT_Application, 0x00, tmp, 1*sizeof(fb_quadlet_t));
274         //hexDumpQuadlets(tmp, 2); // DEBUG
275         // 0x00010004 is a pro24, 0x00010008 is the pro24dsp
276         if (tmp[0] != 0x00010004 && tmp[0] != 0x00010008) {
277             debugError("This is a Focusrite Saffire Pro24 but not the right firmware. Better stop here before something goes wrong.\n");
278             debugError("This device has firmware 0x%x while we only know about versions 0x%x and 0x%x.\n", tmp[0], 0x10004, 0x10008);
279             return false;
280         }
281         //getEAP()->readRegBlock(Dice::EAP::eRT_Command, 0x00, tmp, 2*sizeof(fb_quadlet_t)); // DEBUG
282         //hexDumpQuadlets(tmp, 2); // DEBUG
283
284         FocusriteEAP* eap = dynamic_cast<FocusriteEAP*>(getEAP());
285         m_ch1 = new LineInstSwitch(eap, "Ch1LineInst", 0x58, 2);
286         getEAP()->addElement(m_ch1);
287         m_ch2 = new LineInstSwitch(eap, "Ch2LineInst", 0x58, 2<<16);
288         getEAP()->addElement(m_ch2);
289         m_ch3 = new LevelSwitch(eap, "Ch3Level", 0x5C, 1);
290         getEAP()->addElement(m_ch3);
291         m_ch4 = new LevelSwitch(eap, "Ch4Level", 0x5C, 1<<16);
292         getEAP()->addElement(m_ch4);
293
294         m_monitor = new FocusriteEAP::MonitorSection(eap, "Monitoring");
295         getEAP()->addElement(m_monitor);
296         return true;
297     }
298     return false;
299 }
300
301 void SaffirePro24::showDevice()
302 {
303     debugOutput(DEBUG_LEVEL_VERBOSE, "This is a Dice::Focusrite::SaffirePro24\n");
304     Dice::Device::showDevice();
305 }
306 Dice::EAP* SaffirePro24::createEAP() {
307     return new SaffirePro24EAP(*this);
308 }
309
310 bool SaffirePro24::setNickname( std::string name ) {
311     return getEAP()->writeRegBlock( Dice::EAP::eRT_Application, 0x40, (fb_quadlet_t*)name.c_str(), name.size() );
312 }
313
314 std::string SaffirePro24::getNickname() {
315     char name[16];
316     getEAP()->readRegBlock( Dice::EAP::eRT_Application, 0x40, (fb_quadlet_t*)name, 16 );
317     return std::string( name );
318 }
319
320 }
321 }
322
323 // vim: et
Note: See TracBrowser for help on using the browser.