HRESULT SoundDA::Open(IDaqEngine *engine, int id) { // assign the engine access pointer _engine = engine; _ASSERTE(engine!=NULL); _id=id; CComPtr<IProp> prop; CComVariant minvar,maxvar; UINT nDevs=waveOutGetNumDevs(); if (!nDevs) return E_NO_DEVICE; if (_id<0 || _id>nDevs-1) return E_INVALID_DEVICE_ID; CmwDevice::Open(engine); // common properties WaveCaps.LoadCaps(_id); _cSamplesPerSec.Attach(GetPropRoot(),L"SampleRate"); CComVariant val(DEFAULT_SAMPLE_RATE, VT_I4); _cSamplesPerSec=DEFAULT_SAMPLE_RATE; _cSamplesPerSec->put_DefaultValue(val); // device specific properties HRESULT hRes; bool supports16Bit=WaveCaps.Supports16Bit(); // sixteen-bit boards also support 8-bit mode if (supports16Bit) { hRes = _EnginePropRoot->CreateProperty(L"BitsPerSample", &CComVariant(16L), __uuidof(IProp),(void**) &prop); if (!(SUCCEEDED(hRes))) return hRes; minvar=4L; maxvar=32L; prop->SetRange(&minvar, &maxvar); } else { hRes = _EnginePropRoot->CreateProperty(L"BitsPerSample", &CComVariant(8L),__uuidof(IProp),(void**) &prop); if (!(SUCCEEDED(hRes))) return hRes; minvar=maxvar=8L; prop->SetRange(&minvar, &maxvar); prop->put_Value(CComVariant(8)); _bitsPerSample=8; { CComPtr <IProp> iProp; GetChannelProperty(L"conversionoffset",&iProp); iProp->put_DefaultValue(CComVariant(128.0)); } } prop->put_User((long)&_bitsPerSample); prop.Release(); // StandardSampleRates - device specific. hRes = _EnginePropRoot->CreateProperty(L"StandardSampleRates", &CComVariant(true), __uuidof(IProp),(void**) &prop); if (!(SUCCEEDED(hRes))) return hRes; prop->put_User((long)&_standardSampleRates); prop->put_IsReadonlyRunning(true); prop.Release(); // Channel ranges static double Neg1To1[]={-1,1}; CreateSafeVector(Neg1To1,2,&val); hRes = GetChannelProperty(L"outputrange", &prop); if (!(SUCCEEDED(hRes))) return hRes; prop->put_DefaultValue( val); hRes = prop->put_User(OUTPUTRANGE); if (!(SUCCEEDED(hRes))) return hRes; minvar=-1.0; maxvar=1.0; prop->SetRange(&minvar,&maxvar); prop.Release(); hRes = GetChannelProperty(L"unitsrange", &prop); if (!(SUCCEEDED(hRes))) return hRes; prop->put_DefaultValue( val); prop.Release(); // DaqHwInfo hRes = SetDaqHwInfo(); if (!(SUCCEEDED(hRes))) return hRes; hRes = GetChannelProperty(L"HwChannel", &prop); if (!(SUCCEEDED(hRes))) return hRes; prop->put_DefaultValue( CComVariant(1L)); prop->put_User((long)HwChan); if (WaveCaps.IsStereo()) prop->SetRange(&CComVariant(1L),&CComVariant(2L)); else prop->SetRange(&CComVariant(1L),&CComVariant(1L)); prop.Release(); _thread.Resume(); _thread.SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL); return S_OK; }
///////////////////////////////////////////////////////////////////////////// // Open() // // Function is called by the OpenDevice(), which is in turn called by the engine. // CetfarduinoAin::Open() function's main goals are .. // 1)to initialize the hardware and hardware dependent properties.. // 2)to expose pointers to the engine and the adaptor to each other.. // 3)to process the device ID, which is input by a user in the MATLAB command line. // The call to this function goes through the hierarchical chain: .. //..CetfarduinoAin::Open() -> CswClockedDevice::Open() -> CmwDevice::Open() // CmwDevice::Open() in its turn populates the pointer to the.. //..engine (CmwDevice::_engine), which allows to access all engine interfaces. // Function MUST BE MODIFIED by the adaptor programmer. ////////////////////////////////////////////////////////////////////////////// HRESULT CetfarduinoAin::Open(IUnknown* Interface, long ID) { if (ID < 0) { // Undocumented MATLAB Daq Engine bug! // When Open() returns an error, the reference to the analoginput object is leaked // and never freed! Thereby, all resources this object owns are also leaked since // the destructor is never called. // :TODO: Implement a way to free all resources without the dtor (cannot use RAII for // this object) return CComCoClass<ImwDevice>::Error(CComBSTR("etfarduino: Invalid device ID.")); } RETURN_HRESULT(TBaseObj::Open(Interface)); DeviceId = ID; TCHAR portName[10]; bool registered = service.CheckDeviceRegistered(DeviceId, portName); if (!registered) { char tempMessage[255]; sprintf(tempMessage, "etfarduino: Device %d not found.", DeviceId); return CComCoClass<ImwDevice>::Error(CComBSTR(tempMessage)); } wchar_t idStr[8]; swprintf(idStr, L"%d", ID); RETURN_HRESULT(_DaqHwInfo->put_MemberValue(CComBSTR(L"id"), CComVariant(idStr))); // Fixed device config values. They could be moved to a config file. m_minBoardSampleRate = 4; m_maxBoardSampleRate = 12500; // 80us period _engine->GetBufferingConfig(&m_engineBufferSamples, NULL); // ------------ // SetDaqHwInfo // ------------ wchar_t deviceName[30]; swprintf(deviceName, _T("etfarduino (Device %d)"), DeviceId); RETURN_HRESULT(InitHwInfo( VT_UI2, Bits, MAX_CHANNELS, // maximum number of channels SE_INPUT, // Setting Single Ended input channels Cetfarduinoadapt::ConstructorName, deviceName)); RETURN_HRESULT(SetDaqHwInfo()); //////////////////////////////// Properties /////////////////////////////////// // The following Section sets the Propinfo for the Analog input device // /////////////////////////////////////////////////////////////////////////////// // Attach to the ClockSource property ATTACH_PROP(ClockSource); // The etfarduino must work as both software and internally clocked EnableSwClocking(); pClockSource->AddMappedEnumValue(CLOCKSOURCE_SOFTWARE, TEXT("Software")); pClockSource->AddMappedEnumValue(CLOCKSOURCE_INTERNAL, TEXT("Internal")); pClockSource->put_DefaultValue(CComVariant(CLOCKSOURCE_INTERNAL)); pClockSource = CLOCKSOURCE_INTERNAL; // SampleRate property double defaultSampleRate = 1000; ATTACH_PROP(SampleRate); pSampleRate.SetDefaultValue(CComVariant(defaultSampleRate)); pSampleRate = defaultSampleRate; pSampleRate.SetRange(m_minBoardSampleRate, m_maxBoardSampleRate); RETURN_HRESULT(_DaqHwInfo->put_MemberValue(TEXT("minsamplerate"), CComVariant(m_minBoardSampleRate))); RETURN_HRESULT(_DaqHwInfo->put_MemberValue(TEXT("maxsamplerate"), CComVariant(m_maxBoardSampleRate))); // SamplesPerTrigger property // Needs to be set so that 1s of data is acquired with the default sample rate ATTACH_PROP(SamplesPerTrigger); pSamplesPerTrigger->put_DefaultValue(CComVariant(defaultSampleRate)); pSamplesPerTrigger = defaultSampleRate; // TriggerRepeat property // How many times will the trigger be repeated ATTACH_PROP(TriggerRepeat); // ---------------------------- // Postaviti InputRange default // ---------------------------- CRemoteProp remoteProp; CComVariant var; // Hardcoded input range of [0, 5] [V] double InputRange[2] = {0., 5.}; CreateSafeVector(InputRange, 2, &var); remoteProp.Attach(_EngineChannelList, TEXT("inputrange")); remoteProp->put_DefaultValue(var); remoteProp->put_User(USER_INPUTRANGE); remoteProp.SetRange(InputRange[0], InputRange[1]); remoteProp.Release(); TRemoteProp<long> pInputType; pInputType.Attach(_EnginePropRoot, L"InputType"); pInputType->AddMappedEnumValue(0, L"SingleEnded"); // TODO: May need to add the ChannelSkewMode enumerated property... return S_OK; } // end of Open()