Example #1
0
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;

}
Example #2
0
HRESULT SoundDA::SetDaqHwInfo()
{    
    CComPtr<IProp> prop;     

    // hwinfo property container

    CComQIPtr<IPropContainer> pCont(GetHwInfo());   
        
    // total channels 
    CComVariant var,vids;
    short ids[]={1,2};
    if (WaveCaps.IsStereo())
    {
        var=2L;
        CreateSafeVector(ids,2,&vids);
    }
    else
    {
        var=1L;
        CreateSafeVector(ids,1,&vids);
    }

    HRESULT hRes = pCont->put_MemberValue(L"totalchannels",var);
    if (!(SUCCEEDED(hRes))) return hRes;        

    hRes = pCont->put_MemberValue(L"channelids", vids);
    if (!(SUCCEEDED(hRes))) return hRes;

    
    wchar_t idStr[8];
    swprintf(idStr, L"%d", _id);
    hRes = pCont->put_MemberValue(L"id", CComVariant(idStr));	
    if (!(SUCCEEDED(hRes))) return hRes;
    
    hRes = pCont->put_MemberValue(L"polarity", CComVariant(L"Bipolar"));
    if (!(SUCCEEDED(hRes))) return hRes;

    hRes = pCont->put_MemberValue(L"coupling", CComVariant(L"AC Coupled"));
    if (!(SUCCEEDED(hRes))) return hRes;

    // subsystem type
    hRes = pCont->put_MemberValue(L"subsystemtype",CComVariant(L"AnalogOutput"));
    if (!(SUCCEEDED(hRes))) return hRes;

    // autocal
    //hRes = pCont->put_MemberValue(CComBSTR(L"autocalibrate"),CComVariant(0L));
    //if (!(SUCCEEDED(hRes))) return hRes;
   
    hRes = pCont->put_MemberValue(L"sampletype",CComVariant(1L));
    if (!(SUCCEEDED(hRes))) return hRes;

    // number of bits
    CComVariant val;
    val = WaveCaps.Supports16Bit() ? 16L : 8L;
    hRes = pCont->put_MemberValue(CComBSTR(L"bits"),val);
    if (!(SUCCEEDED(hRes))) return hRes;
      
    hRes = pCont->put_MemberValue(L"adaptorname",
        CComVariant(L"winsound"));
    if (!(SUCCEEDED(hRes))) return hRes;

    // driver description    
    bstr_t name = WaveCaps.GetDeviceName();
    V_VT(&val) = VT_BSTR;
    V_BSTR(&val) = name;
    hRes = pCont->put_MemberValue(L"devicename",val);
    if (!(SUCCEEDED(hRes))) return hRes;    

    hRes = pCont->put_MemberValue(L"vendordriverdescription",
	CComVariant(L"Windows Multimedia Driver"));
    if (!(SUCCEEDED(hRes))) return hRes;
       
    hRes = pCont->put_MemberValue(L"vendordriverversion",CComVariant(WaveCaps.GetDriverVersion()));
    if (!(SUCCEEDED(hRes))) return hRes;

    // native data type
    var = WaveCaps.Supports16Bit() ? VT_I2 : VT_UI1;
    hRes = pCont->put_MemberValue(L"nativedatatype", var);	
    if (!(SUCCEEDED(hRes))) return hRes;


    SetSampleRateRange(8000,static_cast<long>(WaveCaps.GetMaxSampleRate()));

    // input ranges --> move to input group    
    SAFEARRAY *ps = SafeArrayCreateVector(VT_R8, 0, 2);
    if (ps==NULL) 
        return E_OUTOFMEMORY;

    val.parray=ps;
    val.vt = VT_ARRAY | VT_R8;

    double *pr;
    
    hRes = SafeArrayAccessData(ps, (void **) &pr);
    if (FAILED (hRes)) 
    {
        SafeArrayDestroy (ps);
        return hRes;
    }       

    pr[0]=-1;
    pr[1]=1;

    SafeArrayUnaccessData (ps);

    hRes = pCont->put_MemberValue(CComBSTR(L"outputranges"), val);	
    if (!(SUCCEEDED(hRes))) return hRes;    

    return S_OK;
}
Example #3
0
/////////////////////////////////////////////////////////////////////////////
// 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()