Index: /branches/libfreebob-2.0/src/motu/motu_avdevice.h =================================================================== --- /branches/libfreebob-2.0/src/motu/motu_avdevice.h (revision 302) +++ /branches/libfreebob-2.0/src/motu/motu_avdevice.h (revision 304) @@ -41,8 +41,10 @@ #define MOTUFW_RATE_MULTIPLIER_MASK (0x00000030) -#define MOTUFW_OPTICAL_MODE_OFF (0<<8) -#define MOTUFW_OPTICAL_MODE_ADAT (1<<8) -#define MOTUFW_OPTICAL_MODE_TOSLINK (2<<8) -#define MOTUFW_OPTICAL_MODE_MASK (0x00000300) +#define MOTUFW_OPTICAL_MODE_OFF 0x00 +#define MOTUFW_OPTICAL_MODE_ADAT 0x01 +#define MOTUFW_OPTICAL_MODE_TOSLINK 0x02 +#define MOTUFW_OPTICAL_IN_MODE_MASK (0x00000300) +#define MOTUFW_OPTICAL_OUT_MODE_MASK (0x00003000) +#define MOTUFW_OPTICAL_MODE_MASK (MOTUFW_OPTICAL_IN_MODE_MASK|MOTUFW_OPTICAL_MODE_MASK) #define MOTUFW_CLKSRC_MASK 0x00000007 @@ -55,7 +57,12 @@ #define MOTUFW_CLKSRC_AES_EBU 7 +#define MOTUFW_DIR_IN 1 +#define MOTUFW_DIR_OUT 2 +#define MOTUFW_DIR_INOUT (MOTUFW_DIR_IN | MOTUFW_DIR_OUT) + /* Device registers */ #define MOTUFW_REG_ISOCTRL 0x0b00 -#define MOTUFW_REG_RATECTRL 0x0b14 +#define MOTUFW_REG_OPTICAL_CTRL 0x0b10 +#define MOTUFW_REG_CLK_CTRL 0x0b14 #define MOTUFW_REG_ROUTE_PORT_CONF 0x0c04 #define MOTUFW_REG_CLKSRC_NAME0 0x0c60 @@ -102,8 +109,8 @@ signed int getIsoRecvChannel(void); signed int getIsoSendChannel(void); - unsigned int getOpticalMode(void); - signed int setOpticalMode(unsigned int mode); + unsigned int getOpticalMode(unsigned int dir); + signed int setOpticalMode(unsigned int dir, unsigned int mode); - signed int getEventSize(void); + signed int getEventSize(unsigned int dir); protected: Index: /branches/libfreebob-2.0/src/motu/motu_avdevice.cpp =================================================================== --- /branches/libfreebob-2.0/src/motu/motu_avdevice.cpp (revision 302) +++ /branches/libfreebob-2.0/src/motu/motu_avdevice.cpp (revision 304) @@ -170,27 +170,27 @@ int MotuDevice::getSamplingFrequency( ) { - /* - Implement the procedure to retrieve the samplerate here - */ - quadlet_t q = ReadRegister(MOTUFW_REG_RATECTRL); - int rate = 0; - - switch (q & MOTUFW_RATE_BASE_MASK) { - case MOTUFW_RATE_BASE_44100: - rate = 44100; - break; - case MOTUFW_RATE_BASE_48000: - rate = 48000; - break; - } - switch (q & MOTUFW_RATE_MULTIPLIER_MASK) { - case MOTUFW_RATE_MULTIPLIER_2X: - rate *= 2; - break; - case MOTUFW_RATE_MULTIPLIER_4X: - rate *= 4; - break; - } - return rate; +/* + * Retrieve the current sample rate from the MOTU device. + */ + quadlet_t q = ReadRegister(MOTUFW_REG_CLK_CTRL); + int rate = 0; + + switch (q & MOTUFW_RATE_BASE_MASK) { + case MOTUFW_RATE_BASE_44100: + rate = 44100; + break; + case MOTUFW_RATE_BASE_48000: + rate = 48000; + break; + } + switch (q & MOTUFW_RATE_MULTIPLIER_MASK) { + case MOTUFW_RATE_MULTIPLIER_2X: + rate *= 2; + break; + case MOTUFW_RATE_MULTIPLIER_4X: + rate *= 4; + break; + } + return rate; } @@ -199,9 +199,9 @@ { /* - * Set the device samplerate. + * Set the MOTU device's samplerate. */ char *src_name; quadlet_t q, new_rate=0; - int i, supported=true; + int i, supported=true, cancel_adat=false; switch ( samplingFrequency ) { @@ -228,8 +228,18 @@ break; case eSF_176400Hz: - new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_4X; + // Currently only the Traveler supports 4x sample rates + if (m_motu_model == MOTUFW_MODEL_TRAVELER) { + new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_4X; + cancel_adat = true; + } else + supported=false; break; case eSF_192000Hz: - new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_4X; + // Currently only the Traveler supports 4x sample rates + if (m_motu_model == MOTUFW_MODEL_TRAVELER) { + new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_4X; + cancel_adat = true; + } else + supported=false; break; default: @@ -237,11 +247,30 @@ } - // Update the clock control register. FIXME: there's more to it than this + // Update the clock control register. FIXME: while this is now rather + // comprehensive there may still be a need to manipulate MOTUFW_REG_CLK_CTRL + // a little more than we do. if (supported) { - quadlet_t value=ReadRegister(MOTUFW_REG_RATECTRL); + quadlet_t value=ReadRegister(MOTUFW_REG_CLK_CTRL); + + // If optical port must be disabled (because a 4x sample rate has + // been selected) then do so before changing the sample rate. At + // this stage it will be up to the user to re-enable the optical + // port if the sample rate is set to a 1x or 2x rate later. + if (cancel_adat) { + setOpticalMode(MOTUFW_DIR_INOUT, MOTUFW_OPTICAL_MODE_OFF); + } + value &= ~(MOTUFW_RATE_BASE_MASK|MOTUFW_RATE_MULTIPLIER_MASK); value |= new_rate; -// value |= 0x04000000; - if (WriteRegister(MOTUFW_REG_RATECTRL, value) == 0) { + + // In other OSes bit 26 of MOTUFW_REG_CLK_CTRL always seems + // to be set when this register is written to although the + // reason isn't currently known. When we set it, it appears + // to prevent output being produced so we'll leave it unset + // until we work out what's going on. Other systems write + // to MOTUFW_REG_CLK_CTRL multiple times, so that may be + // part of the mystery. + // value |= 0x04000000; + if (WriteRegister(MOTUFW_REG_CLK_CTRL, value) == 0) { supported=true; } else { @@ -259,5 +288,8 @@ break; case MOTUFW_CLKSRC_SPDIF_TOSLINK: - src_name = "SPDIF/TOSLink "; + if (getOpticalMode(MOTUFW_DIR_IN) == MOTUFW_OPTICAL_MODE_TOSLINK) + src_name = "TOSLink "; + else + src_name = "SPDIF "; break; case MOTUFW_CLKSRC_SMTPE: @@ -286,7 +318,7 @@ bool MotuDevice::setId( unsigned int id) { - debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id); - m_id=id; - return true; + debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id); + m_id=id; + return true; } @@ -294,7 +326,7 @@ MotuDevice::showDevice() const { - printf( "MOTU %s at node %d\n", - motufw_modelname[m_motu_model], - m_nodeId ); + debugOutput(DEBUG_LEVEL_VERBOSE, + "MOTU %s at node %d\n", motufw_modelname[m_motu_model], + m_nodeId); } @@ -303,6 +335,8 @@ int samp_freq = getSamplingFrequency(); - unsigned int optical_mode = getOpticalMode(); - unsigned int event_size = getEventSize(); + unsigned int optical_in_mode = getOpticalMode(MOTUFW_DIR_IN); + unsigned int optical_out_mode = getOpticalMode(MOTUFW_DIR_OUT); + unsigned int event_size_in = getEventSize(MOTUFW_DIR_IN); + unsigned int event_size_out= getEventSize(MOTUFW_DIR_OUT); raw1394handle_t handle = m_1394Service->getHandle(); @@ -356,6 +390,6 @@ m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor( - m_1394Service->getPort(), samp_freq, event_size); - + m_1394Service->getPort(), samp_freq, event_size_in); + // The first thing is to initialize the processor. This creates the // data structures. @@ -374,5 +408,5 @@ // Add audio capture ports - if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_mode)) { + if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_in_mode)) { return false; } @@ -423,5 +457,5 @@ // Do the same for the transmit processor m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor( - m_1394Service->getPort(), getSamplingFrequency(), event_size); + m_1394Service->getPort(), getSamplingFrequency(), event_size_out); m_transmitProcessor->setVerboseLevel(getDebugLevel()); @@ -440,5 +474,5 @@ // Add audio playback ports - if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_mode)) { + if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_out_mode)) { return false; } @@ -600,22 +634,53 @@ } -unsigned int MotuDevice::getOpticalMode(void) { +unsigned int MotuDevice::getOpticalMode(unsigned int dir) { unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF); - return reg & MOTUFW_OPTICAL_MODE_MASK; -} - -signed int MotuDevice::setOpticalMode(unsigned int mode) { + + if (dir == MOTUFW_DIR_IN) + return (reg & MOTUFW_OPTICAL_IN_MODE_MASK) >> 8; + else + return (reg & MOTUFW_OPTICAL_OUT_MODE_MASK) >> 12; +} + +signed int MotuDevice::setOpticalMode(unsigned int dir, unsigned int mode) { unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF); - - // FIXME: there seems to be more to it than this. - reg &= ~MOTUFW_OPTICAL_MODE_MASK; - reg |= mode & MOTUFW_OPTICAL_MODE_MASK; - return WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg); -} - -signed int MotuDevice::getEventSize(void) { + unsigned int opt_ctrl = 0x0000002; + + // Set up the optical control register value according to the current + // optical port modes. At this stage it's not completely understood + // what the "Optical control" register does, so the values its set to + // are more or less "magic" numbers. + if (reg & MOTUFW_OPTICAL_IN_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<8)) + opt_ctrl |= 0x00000080; + if (reg & MOTUFW_OPTICAL_OUT_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<12)) + opt_ctrl |= 0x00000040; + + if (mode & MOTUFW_DIR_IN) { + reg &= ~MOTUFW_OPTICAL_IN_MODE_MASK; + reg |= (mode << 8) & MOTUFW_OPTICAL_IN_MODE_MASK; + if (mode != MOTUFW_OPTICAL_MODE_ADAT) + opt_ctrl |= 0x00000080; + else + opt_ctrl &= ~0x00000080; + } + if (mode & MOTUFW_DIR_OUT) { + reg &= ~MOTUFW_OPTICAL_OUT_MODE_MASK; + reg |= (mode <<12) & MOTUFW_OPTICAL_OUT_MODE_MASK; + if (mode != MOTUFW_OPTICAL_MODE_ADAT) + opt_ctrl |= 0x00000040; + else + opt_ctrl &= ~0x00000040; + } + + // FIXME: there seems to be more to it than this, but for + // the moment at least this seems to work. + WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg); + return WriteRegister(MOTUFW_REG_OPTICAL_CTRL, opt_ctrl); +} + +signed int MotuDevice::getEventSize(unsigned int dir) { // -// Return the size of a single event sent by the MOTU as part of an iso -// data packet in bytes. +// Return the size in bytes of a single event sent to (dir==MOTUFW_OUT) or +// from (dir==MOTUFW_IN) the MOTU as part of an iso data packet. // // FIXME: for performance it may turn out best to calculate the event @@ -628,5 +693,5 @@ // all audio channels are sent using 3 bytes. signed int sample_rate = getSamplingFrequency(); -signed int optical_mode = getOpticalMode(); +signed int optical_mode = getOpticalMode(dir); signed int size = 4+6+8*3;