Merge branch 'master' of wf:webapps/gitweb/repos/libcm
This commit is contained in:
commit
0cc1cefe19
@ -33,6 +33,9 @@ cmSRC += src/libcm/cmAudioPort.c src/libcm/cmApBuf.c src/libcm/cmAudioAggDev.c s
|
||||
cmHDR += src/libcm/cmMidiFilePlay.h src/libcm/cmMidiPort.h src/libcm/cmMidiFile.h src/libcm/cmMidi.h
|
||||
cmSRC += src/libcm/cmMidiFilePlay.c src/libcm/cmMidiPort.c src/libcm/cmMidiFile.c src/libcm/cmMidi.c
|
||||
|
||||
cmHDR += src/libcm/cmSerialPort.h
|
||||
cmSRC += src/libcm/cmSerialPort.c
|
||||
|
||||
cmHDR += src/libcm/cmAudioFile.h src/libcm/cmAudioFileMgr.h src/libcm/cmMsgProtocol.h src/libcm/cmAudioSys.h src/libcm/cmAudioPortFile.h src/libcm/cmAudioFileDev.h
|
||||
cmSRC += src/libcm/cmAudioFile.c src/libcm/cmAudioFileMgr.c src/libcm/cmMsgProtocol.c src/libcm/cmAudioSys.c src/libcm/cmAudioPortFile.c src/libcm/cmAudioFileDev.c
|
||||
|
||||
|
@ -815,6 +815,7 @@ void cmApBufInputToOutput( unsigned iDevIdx, unsigned oDevIdx )
|
||||
|
||||
unsigned byteCnt = ip->dspFrameCnt * sizeof(cmApSample_t);
|
||||
|
||||
|
||||
if( oBufPtrArray[i] != NULL )
|
||||
{
|
||||
// the input channel is not disabled
|
||||
@ -846,17 +847,19 @@ void cmApBufReport( cmRpt_t* rpt )
|
||||
unsigned ii = 0;
|
||||
unsigned oi = 0;
|
||||
unsigned fn = 0;
|
||||
cmApSample_t mtr = 0;
|
||||
for(k=0; k<ip->chCnt; ++k)
|
||||
{
|
||||
cmApCh* cp = ip->chArray + i;
|
||||
ii += cp->ii;
|
||||
oi += cp->oi;
|
||||
fn += cp->fn;
|
||||
mtr += _cmApMeterValue(cp);
|
||||
}
|
||||
|
||||
cmRptPrintf(rpt,"%s - i:%7i o:%7i f:%7i n:%7i err %s:%7i ",
|
||||
cmRptPrintf(rpt,"%s - i:%7i o:%7i f:%7i n:%7i err %s:%7i mtr:%5.4f ",
|
||||
j==0?"IN":"OUT",
|
||||
ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt);
|
||||
ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt, mtr);
|
||||
|
||||
}
|
||||
|
||||
|
60
cmAudDsp.c
60
cmAudDsp.c
@ -19,6 +19,7 @@
|
||||
#include "cmApBuf.h"
|
||||
#include "cmMidi.h"
|
||||
#include "cmMidiPort.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "dsp/cmDspValue.h"
|
||||
#include "cmMsgProtocol.h"
|
||||
#include "cmThread.h"
|
||||
@ -91,6 +92,12 @@ typedef struct
|
||||
unsigned msgsPerClientPoll;
|
||||
const cmChar_t* dfltProgramLabel;
|
||||
|
||||
char* serialDeviceStr;
|
||||
unsigned serialBaud;
|
||||
unsigned serialCfgFlags;
|
||||
unsigned serialPollPeriodMs;
|
||||
cmSeH_t serialPortH;
|
||||
|
||||
cmAdAggDev_t* aggDevArray;
|
||||
unsigned aggDevCnt;
|
||||
|
||||
@ -169,6 +176,7 @@ cmAdRC_t _cmAdParseSysJsonTree( cmAd_t* p )
|
||||
cmJsonNode_t* nrtDevArrNodePtr = NULL;
|
||||
cmJsonNode_t* afpDevArrNodePtr = NULL;
|
||||
cmJsonNode_t* audDspNodePtr = NULL;
|
||||
cmJsonNode_t* serialNodePtr = NULL;
|
||||
const cmChar_t* errLabelPtr = NULL;
|
||||
unsigned i;
|
||||
cmJsRC_t jsRC = kOkJsRC;
|
||||
@ -190,12 +198,28 @@ cmAdRC_t _cmAdParseSysJsonTree( cmAd_t* p )
|
||||
"aggDevArray", kArrayTId | kOptArgJsFl, &aggDevArrNodePtr,
|
||||
"nrtDevArray", kArrayTId | kOptArgJsFl, &nrtDevArrNodePtr,
|
||||
"afpDevArray", kArrayTId | kOptArgJsFl, &afpDevArrNodePtr,
|
||||
"serial", kObjectTId | kOptArgJsFl, &serialNodePtr,
|
||||
NULL )) != kOkJsRC )
|
||||
{
|
||||
rc = _cmAdParseMemberErr(p, jsRC, errLabelPtr, "aud_dsp" );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// parse the serial port cfg
|
||||
if( serialNodePtr != NULL )
|
||||
{
|
||||
if(( jsRC = cmJsonMemberValues( serialNodePtr, &errLabelPtr,
|
||||
"device", kStringTId, &p->serialDeviceStr,
|
||||
"baud", kIntTId, &p->serialBaud,
|
||||
"flags", kIntTId, &p->serialCfgFlags,
|
||||
"pollPeriodMs", kIntTId, &p->serialPollPeriodMs,
|
||||
NULL )) != kOkJsRC )
|
||||
{
|
||||
rc = _cmAdParseMemberErr(p, jsRC, errLabelPtr, "serial" );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
// parse the aggregate device specifications into p->aggDevArray[].
|
||||
if( aggDevArrNodePtr != NULL && (p->aggDevCnt = cmJsonChildCount(aggDevArrNodePtr)) > 0)
|
||||
{
|
||||
@ -382,6 +406,22 @@ cmAdRC_t _cmAdSetup( cmAd_t* p )
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmAdRC_t _cmAdCreateSerialPort( cmAd_t* p )
|
||||
{
|
||||
cmAdRC_t rc = kOkAdRC;
|
||||
|
||||
if( p->serialDeviceStr != NULL )
|
||||
{
|
||||
p->serialPortH = cmSeCreate( &p->ctx, &p->serialPortH, p->serialDeviceStr, p->serialBaud, p->serialCfgFlags, NULL, NULL, p->serialPollPeriodMs );
|
||||
|
||||
if( !cmSeIsOpen(p->serialPortH) )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kSerialDevCreateFailAdRC,"The serial device '%s' creation failed.",cmStringNullGuard(p->serialDeviceStr));
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmAdRC_t _cmAdCreateAggDevices( cmAd_t* p )
|
||||
{
|
||||
cmAdRC_t rc = kOkAdRC;
|
||||
@ -570,6 +610,15 @@ cmAdRC_t _cmAudDspFree( cmAd_t* p )
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmSeIsOpen(p->serialPortH) )
|
||||
{
|
||||
if( cmSeDestroy(&p->serialPortH) != kOkSeRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kSerialPortFailAdRC,"Serial port finalize failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if( cmMpIsInitialized() )
|
||||
if( cmMpFinalize() != kOkMpRC )
|
||||
{
|
||||
@ -695,6 +744,13 @@ cmAdRC_t cmAudDspAlloc( cmCtx_t* ctx, cmAdH_t* hp, cmMsgSendFuncPtr_t cbFunc, vo
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// create the serial port
|
||||
if( _cmAdCreateSerialPort(p) != kOkAdRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kSerialPortFailAdRC,"The MIDI system initialization failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// initialize the MIDI system
|
||||
if( cmMpInitialize(ctx,NULL,NULL,p->midiPortBufByteCnt,"app") != kOkMpRC )
|
||||
{
|
||||
@ -713,7 +769,7 @@ cmAdRC_t cmAudDspAlloc( cmCtx_t* ctx, cmAdH_t* hp, cmMsgSendFuncPtr_t cbFunc, vo
|
||||
goto errLabel;
|
||||
|
||||
// initialize the DSP system
|
||||
if( cmDspSysInitialize(ctx,&p->dsH,p->netH) )
|
||||
if( cmDspSysInitialize(ctx,&p->dsH,p->netH,p->serialPortH) )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kDspSysFailAdRC,"The DSP system initialization failed.");
|
||||
goto errLabel;
|
||||
@ -1143,7 +1199,7 @@ cmAdRC_t _cmAudDspLoadAudioSys( cmAd_t* p, unsigned asCfgIdx )
|
||||
{
|
||||
// ... and allocate additional DSP systems when more than one sub-sys is
|
||||
// defined in the audio system configuration
|
||||
if( cmDspSysInitialize(&p->ctx,&dsH,p->netH) != kOkDspRC )
|
||||
if( cmDspSysInitialize(&p->ctx,&dsH,p->netH,p->serialPortH) != kOkDspRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->err,kDspSysFailAdRC,"Unable to initialize an additional DSP system.");
|
||||
goto errLabel;
|
||||
|
@ -13,6 +13,7 @@ extern "C" {
|
||||
kAudioPortFailAdRC,
|
||||
kAudioSysFailAdRC,
|
||||
kMidiSysFailAdRC,
|
||||
kSerialPortFailAdRC,
|
||||
kDspSysFailAdRC,
|
||||
kFileSysFailAdRC,
|
||||
kJsonFailAdRC,
|
||||
@ -21,6 +22,7 @@ extern "C" {
|
||||
kNoPgmLoadedAdRC,
|
||||
kInvalidSubSysIdxAdRC,
|
||||
kUnknownMsgTypeAdRC,
|
||||
kSerialDevCreateFailAdRC,
|
||||
kAggDevSysFailAdRC,
|
||||
kAggDevCreateFailAdRC,
|
||||
kNrtDevSysFailAdRC,
|
||||
|
@ -743,6 +743,8 @@ int cmApPortTest( bool runFl, cmRpt_t* rpt, int argc, const char* argv[] )
|
||||
if( r.inDevIdx != r.outDevIdx )
|
||||
cmApBufSetup( r.inDevIdx, r.srate, r.framesPerCycle, r.bufCnt, cmApDeviceChannelCount(r.inDevIdx,true), r.framesPerCycle, cmApDeviceChannelCount(r.inDevIdx,false), r.framesPerCycle );
|
||||
|
||||
cmApBufEnableMeter( r.inDevIdx, -1, kEnableApFl );
|
||||
|
||||
// setup an output device
|
||||
if(cmApDeviceSetup(r.outDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkApRC )
|
||||
cmRptPrintf(rpt,"Out device setup failed.\n");
|
||||
|
30
cmAudioSys.c
30
cmAudioSys.c
@ -15,6 +15,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmAudioSysMsg.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmMidi.h"
|
||||
@ -37,6 +38,7 @@ typedef struct
|
||||
cmTsMp1cH_t htdQueueH; // host-to-dsp thread safe msg queue
|
||||
cmThreadMutexH_t engMutexH; // thread mutex and condition variable
|
||||
cmUdpNetH_t netH;
|
||||
cmSeH_t serialPortH;
|
||||
bool enableFl; // application controlled pause flag
|
||||
bool runFl; // false during finalization otherwise true
|
||||
bool statusFl; // true if regular status notifications should be sent
|
||||
@ -507,6 +509,13 @@ void _cmAudioSysMidiCallback( const cmMidiPacket_t* pktArray, unsigned pktCnt )
|
||||
|
||||
}
|
||||
|
||||
void _cmAudioSysSerialPortCallback( void* cbArg, const void* byteA, unsigned byteN )
|
||||
{
|
||||
//_cmAsCfg_t* p (_cmAsCfg_t*)cbArg;
|
||||
|
||||
// TODO: handle serial receive
|
||||
}
|
||||
|
||||
cmAsRC_t cmAudioSysAllocate( cmAudioSysH_t* hp, cmRpt_t* rpt, const cmAudioSysCfg_t* cfg )
|
||||
{
|
||||
cmAsRC_t rc;
|
||||
@ -832,6 +841,7 @@ cmAsRC_t cmAudioSysInitialize( cmAudioSysH_t h, const cmAudioSysCfg_t* cfg )
|
||||
cp->iMeterArray = cmMemAllocZ( double, cp->status.iMeterCnt );
|
||||
cp->oMeterArray = cmMemAllocZ( double, cp->status.oMeterCnt );
|
||||
cp->netH = cfg->netH;
|
||||
cp->serialPortH = cfg->serialPortH;
|
||||
|
||||
// create the audio System thread
|
||||
if((rc = cmThreadCreate( &cp->threadH, _cmAsThreadCallback, cp, ss->args.rpt )) != kOkThRC )
|
||||
@ -874,6 +884,16 @@ cmAsRC_t cmAudioSysInitialize( cmAudioSysH_t h, const cmAudioSysCfg_t* cfg )
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// install the serial port
|
||||
if( cmSeIsOpen(cp->serialPortH) )
|
||||
{
|
||||
if( cmSeSetCallback(cp->serialPortH, _cmAudioSysSerialPortCallback, cp ) != kOkSeRC )
|
||||
{
|
||||
rc = _cmAsError(p,kSerialPortFailAsRC,"Serial port callback installation failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
// setup the sub-system status notification
|
||||
cp->statusUpdateSmpCnt = floor(cmApBufMeterMs() * cp->ss.args.srate / 1000.0 );
|
||||
cp->statusUpdateSmpIdx = 0;
|
||||
@ -886,6 +906,16 @@ cmAsRC_t cmAudioSysInitialize( cmAudioSysH_t h, const cmAudioSysCfg_t* cfg )
|
||||
rc = _cmAsError(p,kThreadErrAsRC,"Thread start failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmSeIsOpen(cp->serialPortH) )
|
||||
{
|
||||
if( cmSeStart( cp->serialPortH ) != kOkSeRC )
|
||||
{
|
||||
rc = _cmAsError(p,kSerialPortFailAsRC,"Serial port start failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,6 +73,7 @@ extern "C" {
|
||||
kBufTooSmallAsRC,
|
||||
kNoMsgWaitingAsRC,
|
||||
kMidiSysFailAsRC,
|
||||
kSerialPortFailAsRC,
|
||||
kMsgSerializeFailAsRC,
|
||||
kStateBufFailAsRC,
|
||||
kInvalidArgAsRC,
|
||||
@ -197,6 +198,7 @@ extern "C" {
|
||||
cmTsQueueCb_t clientCbFunc; // Called by cmAudioSysReceiveMsg() to deliver internally generated msg's to the host.
|
||||
// Set to NULL if msg's will be directly returned by buffers passed to cmAudioSysReceiveMsg().
|
||||
cmUdpNetH_t netH;
|
||||
cmSeH_t serialPortH;
|
||||
} cmAudioSysCfg_t;
|
||||
|
||||
extern cmAudioSysH_t cmAudioSysNullHandle;
|
||||
|
@ -92,6 +92,12 @@ extern "C" {
|
||||
//< If 'b' == 0 then return 'f' with the bits in 'm' cleared.
|
||||
//< otherwise return 'f' with the bits in 'm' set.
|
||||
|
||||
// In-place assignment version of the above bit operations
|
||||
#define cmSetBits(f,m) ((f) |= (m)) // Set 'f' with the bits in 'm' set.
|
||||
#define cmClrBits(f,m) ((f) &= (~(m))) // Set 'f' with the bits in 'm' cleared.
|
||||
#define cmTogBits(f,m) ((f)^=(m)) // Return 'f' with the bits in 'm' toggled.
|
||||
#define cmEnaBits(f,m,b) ((b) ? cmSetBits(f,m) : cmClrBits(f,m)) // Set or clear bits in 'f' based on bits in 'm' and the state of 'b'.
|
||||
|
||||
|
||||
#define cmMin(v0,v1) ((v0)<(v1) ? (v0) : (v1)) //< Return the minimum arg.
|
||||
#define cmMax(v0,v1) ((v0)>(v1) ? (v0) : (v1)) //< Return the maximum arg.
|
||||
|
579
cmSerialPort.c
Normal file
579
cmSerialPort.c
Normal file
@ -0,0 +1,579 @@
|
||||
#include "cmPrefix.h"
|
||||
#include "cmGlobal.h"
|
||||
#include "cmRpt.h"
|
||||
#include "cmErr.h"
|
||||
#include "cmCtx.h"
|
||||
#include "cmMem.h"
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmThread.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h> // close()
|
||||
#include <fcntl.h> // O_RDWR
|
||||
#include <sys/ioctl.h> // TIOCEXCL
|
||||
|
||||
typedef struct cmSerialPort_str
|
||||
{
|
||||
cmErr_t _err;
|
||||
cmThreadH_t _thH;
|
||||
const char* _deviceStr;
|
||||
int _deviceH;
|
||||
unsigned _baudRate;
|
||||
unsigned _cfgFlags;
|
||||
cmSeCallbackFunc_t _cbFunc;
|
||||
void* _cbArg;
|
||||
struct termios _ttyAttrs;
|
||||
struct pollfd _pollfd;
|
||||
unsigned _pollPeriodMs;
|
||||
} cmSerialPort_t;
|
||||
|
||||
cmSerialPort_t* _cmSePtrFromHandle( cmSeH_t h )
|
||||
{
|
||||
cmSerialPort_t* p = (cmSerialPort_t*)h.h;
|
||||
assert(p!=NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
void _cmSeSetClosedState( cmSerialPort_t* p )
|
||||
{
|
||||
if( p->_deviceStr != NULL )
|
||||
cmMemFree((char*)(p->_deviceStr));
|
||||
|
||||
p->_deviceH = -1;
|
||||
p->_deviceStr = NULL;
|
||||
p->_baudRate = 0;
|
||||
p->_cfgFlags = 0;
|
||||
p->_cbFunc = NULL;
|
||||
p->_cbArg = NULL;
|
||||
|
||||
}
|
||||
|
||||
cmSeRC_t _cmSeGetAttributes( cmSerialPort_t* p, struct termios* attr )
|
||||
{
|
||||
if( tcgetattr(p->_deviceH, attr) == -1 )
|
||||
return cmErrSysMsg(&p->_err,kGetAttrFailSeRC,errno,"Error getting tty attributes from %s.",p->_deviceStr);
|
||||
|
||||
return kOkSeRC;
|
||||
}
|
||||
|
||||
cmSeRC_t _cmSePoll( cmSerialPort_t* p, unsigned timeOutMs )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
int sysRC;
|
||||
|
||||
if((sysRC = poll(&p->_pollfd,1,timeOutMs)) == 0)
|
||||
rc = kTimeOutSeRC;
|
||||
else
|
||||
{
|
||||
if( sysRC < 0 )
|
||||
rc = cmErrSysMsg(&p->_err,kReadFailSeRC,errno,"Poll failed on serial port.");
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
bool _cmSeThreadFunc(void* param)
|
||||
{
|
||||
cmSerialPort_t* p = (cmSerialPort_t*)param;
|
||||
cmSeH_t h;
|
||||
h.h = p;
|
||||
unsigned readN;
|
||||
if( cmSeIsOpen(h) )
|
||||
cmSeReceiveCbTimeOut(h,p->_pollPeriodMs,&readN);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
cmSeRC_t _cmSeDestroy( cmSerialPort_t* p )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
|
||||
|
||||
// stop the thread first
|
||||
if( cmThreadDestroy(&p->_thH) != kOkThRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->_err,kThreadErrSeRC,"Thread destroy failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// Block until all written output has been sent from the device.
|
||||
// Note that this call is simply passed on to the serial device driver.
|
||||
// See tcsendbreak(3) ("man 3 tcsendbreak") for details.
|
||||
if (tcdrain(p->_deviceH) == -1)
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kFlushFailSeRC,errno,"Error waiting for serial device '%s' to drain.", p->_deviceStr );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// It is good practice to reset a serial port back to the state in
|
||||
// which you found it. This is why we saved the original termios struct
|
||||
// The constant TCSANOW (defined in termios.h) indicates that
|
||||
// the change should take effect immediately.
|
||||
|
||||
if (tcsetattr(p->_deviceH, TCSANOW, &p->_ttyAttrs) == -1)
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kSetAttrFailSeRC,errno,"Error resetting tty attributes on serial device '%s'.",p->_deviceStr);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( p->_deviceH != -1 )
|
||||
{
|
||||
if( close(p->_deviceH ) != 0 )
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kCloseFailSeRC,errno,"Port close failed on serial dvice '%s'.", p->_deviceStr);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
_cmSeSetClosedState(p);
|
||||
}
|
||||
|
||||
cmMemPtrFree(&p);
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
cmSeH_t cmSeCreate( cmCtx_t* ctx, cmSeH_t* hp, const char* deviceStr, unsigned baudRate, unsigned cfgFlags, cmSeCallbackFunc_t cbFunc, void* cbArg, unsigned pollPeriodMs )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
struct termios options;
|
||||
cmSeH_t h;
|
||||
|
||||
// if the port is already open then close it
|
||||
if((rc = cmSeDestroy(hp)) != kOkSeRC )
|
||||
return *hp;
|
||||
|
||||
cmSerialPort_t* p = cmMemAllocZ(cmSerialPort_t,1);
|
||||
|
||||
cmErrSetup(&p->_err,&ctx->rpt,"Serial Port");
|
||||
|
||||
p->_deviceH = -1;
|
||||
|
||||
// open the port
|
||||
if( (p->_deviceH = open(deviceStr, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1 )
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kOpenFailSeRC,errno,"Error opening serial '%s'",cmStringNullGuard(deviceStr));
|
||||
goto errLabel;;
|
||||
}
|
||||
|
||||
// Note that open() follows POSIX semantics: multiple open() calls to
|
||||
// the same file will succeed unless the TIOCEXCL ioctl is issued.
|
||||
// This will prevent additional opens except by root-owned processes.
|
||||
// See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
|
||||
|
||||
if( ioctl(p->_deviceH, TIOCEXCL) == -1 )
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kResourceNotAvailableSeRC,errno,"The serial device '%s' is already in use.", cmStringNullGuard(deviceStr));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
// Now that the device is open, clear the O_NONBLOCK flag so
|
||||
// subsequent I/O will block.
|
||||
// See fcntl(2) ("man 2 fcntl") for details.
|
||||
/*
|
||||
if (fcntl(_deviceH, F_SETFL, 0) == -1)
|
||||
|
||||
{
|
||||
_error("Error clearing O_NONBLOCK %s - %s(%d).", pr.devFilePath.c_str(), strerror(errno), errno);
|
||||
goto errLabel;
|
||||
}
|
||||
*/
|
||||
|
||||
// Get the current options and save them so we can restore the
|
||||
// default settings later.
|
||||
if (tcgetattr(p->_deviceH, &p->_ttyAttrs) == -1)
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kGetAttrFailSeRC,errno,"Error getting tty attributes from the device '%s'.",deviceStr);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
// The serial port attributes such as timeouts and baud rate are set by
|
||||
// modifying the termios structure and then calling tcsetattr to
|
||||
// cause the changes to take effect. Note that the
|
||||
// changes will not take effect without the tcsetattr() call.
|
||||
// See tcsetattr(4) ("man 4 tcsetattr") for details.
|
||||
options = p->_ttyAttrs;
|
||||
|
||||
|
||||
// Set raw input (non-canonical) mode, with reads blocking until either
|
||||
// a single character has been received or a 100ms timeout expires.
|
||||
// See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios")
|
||||
// for details.
|
||||
cfmakeraw(&options);
|
||||
options.c_cc[VMIN] = 1;
|
||||
options.c_cc[VTIME] = 1;
|
||||
|
||||
|
||||
// The baud rate, word length, and handshake options can be set as follows:
|
||||
|
||||
|
||||
// set baud rate
|
||||
cfsetspeed(&options, baudRate);
|
||||
|
||||
options.c_cflag |= CREAD | CLOCAL; // ignore modem controls
|
||||
|
||||
// set data word size
|
||||
cmClrBits(options.c_cflag, CSIZE); // clear the word size bits
|
||||
cmEnaBits(options.c_cflag, CS5, cmIsFlag(cfgFlags, kDataBits5SeFl));
|
||||
cmEnaBits(options.c_cflag, CS6, cmIsFlag(cfgFlags, kDataBits6SeFl));
|
||||
cmEnaBits(options.c_cflag, CS7, cmIsFlag(cfgFlags, kDataBits7SeFl));
|
||||
cmEnaBits(options.c_cflag, CS8, cmIsFlag(cfgFlags, kDataBits8SeFl));
|
||||
|
||||
cmClrBits(options.c_cflag, PARENB); // assume no-parity
|
||||
|
||||
// if the odd or even parity flag is set
|
||||
if( cmIsFlag( cfgFlags, kEvenParitySeFl) || cmIsFlag( cfgFlags, kOddParitySeFl ) )
|
||||
{
|
||||
cmSetBits(options.c_cflag, PARENB);
|
||||
|
||||
if( cmIsFlag(cfgFlags, kOddParitySeFl ) )
|
||||
cmSetBits( options.c_cflag, PARODD);
|
||||
}
|
||||
|
||||
// set two stop bits
|
||||
cmEnaBits( options.c_cflag, CSTOPB, cmIsFlag(cfgFlags, k2StopBitSeFl));
|
||||
|
||||
|
||||
// set hardware flow control
|
||||
//cmEnaBits(options.c_cflag, CCTS_OFLOW, cmIsFlag(cfgFlags, kCTS_OutFlowCtlFl));
|
||||
//cmEnaBits(options.c_cflag, CRTS_IFLOW, cmIsFlag(cfgFlags, kRTS_InFlowCtlFl));
|
||||
//cmEnaBits(options.c_cflag, CDTR_IFLOW, cmIsFlag(cfgFlags, kDTR_InFlowCtlFl));
|
||||
//cmEnaBits(options.c_cflag, CDSR_OFLOW, cmIsFlag(cfgFlags, kDSR_OutFlowCtlFl));
|
||||
//cmEnaBits(options.c_cflag, CCAR_OFLOW, cmIsFlag(cfgFlags, kDCD_OutFlowCtlFl));
|
||||
|
||||
cmClrBits(options.c_cflag,CRTSCTS); // turn-off hardware flow control
|
||||
|
||||
// 7 bit words, enable even parity, CTS out ctl flow, RTS in ctl flow
|
||||
// note: set PARODD and PARENB to enable odd parity)
|
||||
//options.c_cflag |= (CS7 | PARENB | CCTS_OFLOW | CRTS_IFLOW );
|
||||
|
||||
// Cause the new options to take effect immediately.
|
||||
if (tcsetattr(p->_deviceH, TCSANOW, &options) == -1)
|
||||
{
|
||||
|
||||
rc = cmErrSysMsg(&p->_err,kSetAttrFailSeRC,errno,"Error setting tty attributes on serial device %.", deviceStr);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
memset(&p->_pollfd,0,sizeof(p->_pollfd));
|
||||
p->_pollfd.fd = p->_deviceH;
|
||||
p->_pollfd.events = POLLIN;
|
||||
|
||||
p->_deviceStr = cmMemAllocStr( deviceStr );
|
||||
p->_baudRate = baudRate;
|
||||
p->_cfgFlags = cfgFlags;
|
||||
p->_cbFunc = cbFunc;
|
||||
p->_cbArg = cbArg;
|
||||
p->_pollPeriodMs = pollPeriodMs;
|
||||
|
||||
// create the listening thread
|
||||
if( cmThreadCreate( &p->_thH, _cmSeThreadFunc, p, &ctx->rpt) != kOkThRC )
|
||||
{
|
||||
rc = cmErrMsg(&p->_err,kThreadErrSeRC,"Thread initialization failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( hp != NULL )
|
||||
hp->h = p;
|
||||
else
|
||||
h.h = p;
|
||||
|
||||
errLabel:
|
||||
if( rc != kOkSeRC )
|
||||
{
|
||||
_cmSeDestroy(p);
|
||||
h.h = NULL;
|
||||
}
|
||||
|
||||
return hp != NULL ? *hp : h;
|
||||
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeDestroy(cmSeH_t* hp )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
|
||||
if( hp==NULL || !cmSeIsOpen(*hp) )
|
||||
return kOkSeRC;
|
||||
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(*hp);
|
||||
|
||||
if((rc = _cmSeDestroy(p)) != kOkSeRC )
|
||||
return rc;
|
||||
|
||||
hp->h = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeSetCallback( cmSeH_t h, cmSeCallbackFunc_t cbFunc, void* cbArg )
|
||||
{
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
p->_cbFunc = cbFunc;
|
||||
p->_cbArg = cbArg;
|
||||
return kOkSeRC;
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeStart( cmSeH_t h )
|
||||
{
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if( cmThreadPause(p->_thH,0) != kOkThRC )
|
||||
return cmErrMsg(&p->_err,kThreadErrSeRC,0,"Thread start failed.");
|
||||
|
||||
return kOkSeRC;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool cmSeIsOpen( cmSeH_t h)
|
||||
{
|
||||
if( h.h == NULL )
|
||||
return false;
|
||||
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
return p->_deviceH != -1;
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeSend( cmSeH_t h, const void* byteA, unsigned byteN )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if( !cmSeIsOpen(h) )
|
||||
return cmErrWarnMsg( &p->_err, kResourceNotAvailableSeRC, "An attempt was made to transmit from a closed serial port.");
|
||||
|
||||
if( byteN == 0 )
|
||||
return rc;
|
||||
|
||||
// implement a non blocking write - if less than all the bytes were written then iterate
|
||||
unsigned i = 0;
|
||||
do
|
||||
{
|
||||
int n = 0;
|
||||
if((n = write( p->_deviceH, ((char*)byteA)+i, byteN-i )) == -1 )
|
||||
{
|
||||
rc = cmErrSysMsg(&p->_err,kWriteFailSeRC,errno,"Write failed on serial port '%s'.", p->_deviceStr );
|
||||
break;
|
||||
}
|
||||
|
||||
i += n;
|
||||
|
||||
|
||||
}while( i<byteN );
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
cmSeRC_t cmSeReceiveCbNb( cmSeH_t h, unsigned* readN_Ref)
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
const unsigned bufN = 512;
|
||||
char buf[ bufN ];
|
||||
|
||||
if( readN_Ref != NULL)
|
||||
*readN_Ref = 0;
|
||||
|
||||
if((rc = cmSeReceiveNb(h,buf,bufN,readN_Ref)) == kOkSeRC )
|
||||
if( readN_Ref > 0 && p->_cbFunc != NULL )
|
||||
p->_cbFunc( p->_cbArg, buf, *readN_Ref );
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeReceiveCbTimeOut( cmSeH_t h, unsigned timeOutMs, unsigned* readN_Ref)
|
||||
{
|
||||
cmSeRC_t rc;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if((rc = _cmSePoll(p,timeOutMs)) == kOkSeRC )
|
||||
rc = cmSeReceiveCbNb(h,readN_Ref);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeReceiveNb( cmSeH_t h, void* buf, unsigned bufN, unsigned* readN_Ref)
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if( readN_Ref != NULL )
|
||||
*readN_Ref = 0;
|
||||
|
||||
if( !cmSeIsOpen(h) )
|
||||
return cmErrWarnMsg(&p->_err, kResourceNotAvailableSeRC, "An attempt was made to read from a closed serial port.");
|
||||
|
||||
int n = 0;
|
||||
|
||||
// if attempt to read the port succeeded ...
|
||||
if((n =read( p->_deviceH, buf, bufN )) != -1 )
|
||||
*readN_Ref = n;
|
||||
else
|
||||
{
|
||||
// ... or failed and it wasn't because the port was empty
|
||||
if( errno != EAGAIN)
|
||||
rc = cmErrSysMsg(&p->_err,kReadFailSeRC,errno,"An attempt to read the serial port '%s' failed.", p->_deviceStr );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmSeRC_t cmSeReceive( cmSeH_t h, void* buf, unsigned bufByteN, unsigned timeOutMs, unsigned* readN_Ref )
|
||||
{
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if((rc = _cmSePoll(p,timeOutMs)) == kOkSeRC )
|
||||
rc = cmSeReceiveNb(h,buf,bufByteN,readN_Ref);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char* cmSeDevice( cmSeH_t h)
|
||||
{
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
return p->_deviceStr;
|
||||
}
|
||||
|
||||
unsigned cmSeBaudRate( cmSeH_t h)
|
||||
{
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
return p->_baudRate;
|
||||
}
|
||||
|
||||
unsigned cmSeCfgFlags( cmSeH_t h)
|
||||
{
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
return p->_cfgFlags;
|
||||
}
|
||||
|
||||
unsigned cmSeReadInBaudRate( cmSeH_t h )
|
||||
{
|
||||
struct termios attr;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if((_cmSeGetAttributes(p,&attr)) != kOkSeRC )
|
||||
return 0;
|
||||
|
||||
return cfgetispeed(&attr);
|
||||
|
||||
}
|
||||
|
||||
unsigned cmSeReadOutBaudRate( cmSeH_t h)
|
||||
{
|
||||
struct termios attr;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if((_cmSeGetAttributes(p,&attr)) != kOkSeRC )
|
||||
return 0;
|
||||
|
||||
return cfgetospeed(&attr);
|
||||
|
||||
}
|
||||
|
||||
unsigned cmSeReadCfgFlags( cmSeH_t h)
|
||||
{
|
||||
struct termios attr;
|
||||
unsigned result = 0;
|
||||
cmSerialPort_t* p = _cmSePtrFromHandle(h);
|
||||
|
||||
if((_cmSeGetAttributes(p,&attr)) == false )
|
||||
return 0;
|
||||
|
||||
switch( attr.c_cflag & CSIZE )
|
||||
{
|
||||
case CS5:
|
||||
cmSetBits( result, kDataBits5SeFl);
|
||||
break;
|
||||
|
||||
case CS6:
|
||||
cmSetBits( result, kDataBits6SeFl );
|
||||
break;
|
||||
|
||||
case CS7:
|
||||
cmSetBits( result, kDataBits7SeFl);
|
||||
break;
|
||||
|
||||
case CS8:
|
||||
cmSetBits( result, kDataBits8SeFl);
|
||||
break;
|
||||
}
|
||||
|
||||
cmEnaBits( result, k2StopBitSeFl, cmIsFlag( attr.c_cflag, CSTOPB ));
|
||||
cmEnaBits( result, k1StopBitSeFl, !cmIsFlag( attr.c_cflag, CSTOPB ));
|
||||
|
||||
if( cmIsFlag( attr.c_cflag, PARENB ) )
|
||||
{
|
||||
cmEnaBits( result, kOddParitySeFl, cmIsFlag( attr.c_cflag, PARODD ));
|
||||
cmEnaBits( result, kEvenParitySeFl, !cmIsFlag( attr.c_cflag, PARODD ));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//====================================================================================================
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
void _cmSePortTestCb( void* arg, const void* byteA, unsigned byteN )
|
||||
{
|
||||
const char* text = (const char*)byteA;
|
||||
|
||||
for(unsigned i=0; i<byteN; ++i)
|
||||
printf("%c:%i ",text[i],(int)text[i]);
|
||||
|
||||
if( byteN )
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
cmSeRC_t cmSePortTest(cmCtx_t* ctx)
|
||||
{
|
||||
// Use this test an Arduino running study/serial/arduino_xmt_rcv/main.c
|
||||
cmSeRC_t rc = kOkSeRC;
|
||||
const char* device = "/dev/ttyACM0";
|
||||
unsigned baud = 38400;
|
||||
unsigned serialCfgFlags = kDefaultCfgSeFlags;
|
||||
unsigned pollPeriodMs = 50;
|
||||
cmSeH_t h;
|
||||
|
||||
h.h = NULL;
|
||||
|
||||
h = cmSeCreate(ctx,&h,device,baud,serialCfgFlags,_cmSePortTestCb,NULL,pollPeriodMs);
|
||||
|
||||
if( cmSeIsOpen(h) )
|
||||
cmSeStart(h);
|
||||
|
||||
bool quitFl = false;
|
||||
printf("q=quit\n");
|
||||
while(!quitFl)
|
||||
{
|
||||
char c = getchar();
|
||||
|
||||
if( c == 'q')
|
||||
quitFl = true;
|
||||
else
|
||||
if( '0' <= c && c <= 'z' )
|
||||
cmSeSend(h,&c,1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
cmSeDestroy(&h);
|
||||
return rc;
|
||||
}
|
93
cmSerialPort.h
Normal file
93
cmSerialPort.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef cmSerialPort_h
|
||||
#define cmSerialPort_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned cmSeRC_t;
|
||||
|
||||
enum
|
||||
{
|
||||
kOkSeRC = cmOkRC,
|
||||
kFlushFailSeRC,
|
||||
kSetAttrFailSeRC,
|
||||
kCloseFailSeRC,
|
||||
kOpenFailSeRC,
|
||||
kResourceNotAvailableSeRC,
|
||||
kGetAttrFailSeRC,
|
||||
kWriteFailSeRC,
|
||||
kReadFailSeRC,
|
||||
kTimeOutSeRC,
|
||||
kThreadErrSeRC
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
kDataBits5SeFl = 0x0001,
|
||||
kDataBits6SeFl = 0x0002,
|
||||
kDataBits7SeFl = 0x0004,
|
||||
kDataBits8SeFl = 0x0008,
|
||||
kDataBitsSeMask = 0x000f,
|
||||
|
||||
k1StopBitSeFl = 0x0010,
|
||||
k2StopBitSeFl = 0x0020,
|
||||
|
||||
kEvenParitySeFl = 0x0040,
|
||||
kOddParitySeFl = 0x0080,
|
||||
kNoParitySeFl = 0x0000,
|
||||
|
||||
kDefaultCfgSeFlags = kDataBits8SeFl | k1StopBitSeFl | kNoParitySeFl
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (*cmSeCallbackFunc_t)( void* cbArg, const void* byteA, unsigned byteN );
|
||||
|
||||
typedef cmHandle_t cmSeH_t;
|
||||
|
||||
cmSeH_t cmSeCreate( cmCtx_t* ctx, cmSeH_t* hp, const char* device, unsigned baudRate, unsigned cfgFlags, cmSeCallbackFunc_t cbFunc, void* cbArg, unsigned pollPeriodMs );
|
||||
cmSeRC_t cmSeDestroy(cmSeH_t* hp );
|
||||
|
||||
cmSeRC_t cmSeSetCallback( cmSeH_t h, cmSeCallbackFunc_t cbFunc, void* cbArg );
|
||||
cmSeRC_t cmSeStart( cmSeH_t h );
|
||||
|
||||
bool cmSeIsOpen( cmSeH_t h);
|
||||
|
||||
cmSeRC_t cmSeSend( cmSeH_t h, const void* byteA, unsigned byteN );
|
||||
|
||||
|
||||
// Make callback to listener with result of read - Non-blocking
|
||||
cmSeRC_t cmSeReceiveCbNb( cmSeH_t h, unsigned* readN_Ref);
|
||||
|
||||
// Make callback to listener with result of read - Block for up to timeOutMs.
|
||||
cmSeRC_t cmSeReceiveCbTimeOut( cmSeH_t h, unsigned timeOutMs, unsigned* readN_Ref);
|
||||
|
||||
// Return result of read in buf[bufByteN] - Non-blocking.
|
||||
cmSeRC_t cmSeReceiveNb( cmSeH_t h, void* buf, unsigned bufByteN, unsigned* readN_Ref);
|
||||
|
||||
// Return result of read in buf[bufByteN] - Block for up to timeOutMs.
|
||||
cmSeRC_t cmSeReceive( cmSeH_t h, void* buf, unsigned bufByteN, unsigned timeOutMs, unsigned* readN_Ref );
|
||||
|
||||
const char* cmSeDevice( cmSeH_t h);
|
||||
|
||||
// Get the baud rate and cfgFlags used to initialize the port
|
||||
unsigned cmSeBaudRate( cmSeH_t h);
|
||||
unsigned cmSeCfgFlags( cmSeH_t h);
|
||||
|
||||
// Get the baud rate and cfg flags by reading the device.
|
||||
// Note the the returned buad rate is a system id rather than the actual baud rate,
|
||||
// however the cfgFlags are converted to the same kXXXFl defined in this class.
|
||||
unsigned cmSeReadInBaudRate( cmSeH_t h );
|
||||
unsigned cmSeReadOutBaudRate( cmSeH_t h);
|
||||
unsigned cmSeReadCfgFlags( cmSeH_t h);
|
||||
|
||||
cmSeRC_t cmSePortTest(cmCtx_t* ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -27,6 +27,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmDspSys.h"
|
||||
@ -5564,6 +5565,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
|
||||
cmActiveMeasClassCons,
|
||||
cmAmSyncClassCons,
|
||||
cmNanoMapClassCons,
|
||||
cmPicadaeClassCons,
|
||||
cmRecdPlayClassCons,
|
||||
cmGoertzelClassCons,
|
||||
cmSyncRecdClassCons,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
@ -128,7 +129,7 @@ void* cmDspInstAllocate(
|
||||
}
|
||||
|
||||
// determine the space needed for matrices of known size
|
||||
if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
|
||||
if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn)>0 )
|
||||
{
|
||||
unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );
|
||||
varDataByteCnt += n;
|
||||
@ -238,7 +239,7 @@ void* cmDspInstAllocate(
|
||||
}
|
||||
|
||||
// assign memory to the matrix types of known size
|
||||
if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
|
||||
if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn)>0 )
|
||||
{
|
||||
cmDsvSetMtx( &ip->varArray[i].value, flags, varDataPtr, rn, argV[i].cn );
|
||||
unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
130
dsp/cmDspKr.c
130
dsp/cmDspKr.c
@ -18,6 +18,8 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
|
||||
//( { file_desc:"'snap' audio effects performance analysis units." kw:[snap]}
|
||||
|
||||
#include "cmTime.h"
|
||||
@ -2801,6 +2803,134 @@ cmDspClass_t* cmNanoMapClassCons( cmDspCtx_t* ctx )
|
||||
return &_cmNanoMapDC;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
//)
|
||||
//( { label:cmDspPicadae file_desc:"Control a MIDI synth." kw:[sunit] }
|
||||
|
||||
enum
|
||||
{
|
||||
kPgmPcId,
|
||||
kStatusPcId,
|
||||
kD0PcId,
|
||||
kD1PcId,
|
||||
kThruPcId
|
||||
};
|
||||
|
||||
cmDspClass_t _cmPicadaeDC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cmDspInst_t inst;
|
||||
|
||||
} cmDspPicadae_t;
|
||||
|
||||
cmDspRC_t _cmDspPicadaeSend( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned st, unsigned d0, unsigned d1 )
|
||||
{
|
||||
cmDspSetUInt(ctx,inst,kD1PcId,d1);
|
||||
cmDspSetUInt(ctx,inst,kD0PcId,d0);
|
||||
cmDspSetUInt(ctx,inst,kStatusPcId,st);
|
||||
return kOkDspRC;
|
||||
}
|
||||
|
||||
void _cmDspPicadaePgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
|
||||
{
|
||||
//cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
|
||||
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<kMidiChCnt; ++i)
|
||||
{
|
||||
_cmDspPicadaeSend(ctx,inst,kCtlMdId+i,121,0); // reset all controllers
|
||||
_cmDspPicadaeSend(ctx,inst,kCtlMdId+i,123,0); // turn all notes off
|
||||
_cmDspPicadaeSend(ctx,inst,kCtlMdId+i,0,0); // switch to bank 0
|
||||
_cmDspPicadaeSend(ctx,inst,kPgmMdId+i,pgm,0); // send pgm change
|
||||
cmSleepMs(15);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cmDspInst_t* _cmDspPicadaeAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
|
||||
{
|
||||
cmDspVarArg_t args[] =
|
||||
{
|
||||
{ "pgm", kPgmPcId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reprogram all channels to this pgm." },
|
||||
{ "status", kStatusPcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI status" },
|
||||
{ "d0", kD0PcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d0" },
|
||||
{ "d1", kD1PcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d1" },
|
||||
{ "thru", kThruPcId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Enable pass through."},
|
||||
{ NULL, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
cmDspPicadae_t* p = cmDspInstAlloc(cmDspPicadae_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
|
||||
|
||||
cmDspSetDefaultUInt(ctx,&p->inst, kPgmPcId, 0, 0 );
|
||||
|
||||
return &p->inst;
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspPicadaeReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
cmDspRC_t rc = kOkDspRC;
|
||||
|
||||
cmDspApplyAllDefaults(ctx,inst);
|
||||
|
||||
_cmDspPicadaePgm(ctx,inst,cmDspUInt(inst,kPgmPcId));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspPicadaeRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
//cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
|
||||
|
||||
switch( evt->dstVarId )
|
||||
{
|
||||
case kPgmPcId:
|
||||
cmDspSetEvent(ctx,inst,evt);
|
||||
_cmDspPicadaePgm(ctx,inst,cmDspUInt(inst,kPgmPcId));
|
||||
break;
|
||||
|
||||
case kStatusPcId:
|
||||
{
|
||||
unsigned status = cmDsvGetUInt(evt->valuePtr);
|
||||
unsigned stat_no_ch = status & 0xf0;
|
||||
if( stat_no_ch == kNoteOnMdId || stat_no_ch == kNoteOffMdId || stat_no_ch == kCtlMdId )
|
||||
{
|
||||
//unsigned d0 = cmDspUInt(inst,kD0PcId);
|
||||
unsigned ch = 0; //d0 % 8;
|
||||
status = (status & 0xf0) + ch;
|
||||
cmDspSetUInt(ctx,inst,kStatusPcId,status);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
cmDspSetEvent(ctx,inst,evt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return kOkDspRC;
|
||||
}
|
||||
|
||||
cmDspClass_t* cmPicadaeClassCons( cmDspCtx_t* ctx )
|
||||
{
|
||||
cmDspClassSetup(&_cmPicadaeDC,ctx,"Picadae",
|
||||
NULL,
|
||||
_cmDspPicadaeAlloc,
|
||||
NULL,
|
||||
_cmDspPicadaeReset,
|
||||
NULL,
|
||||
_cmDspPicadaeRecv,
|
||||
NULL,
|
||||
NULL,
|
||||
"Picadaesynth Mapper");
|
||||
|
||||
return &_cmPicadaeDC;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
//)
|
||||
//( { label:cmDspRecdPlay file_desc:"Record audio segments from a live perfromance and play them back at a later time" kw:[sunit] }
|
||||
|
@ -17,6 +17,7 @@ extern "C" {
|
||||
struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmPicadaeClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmGoertzelClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmSyncRecdClassCons( cmDspCtx_t* ctx );
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -72,6 +72,7 @@ extern "C" {
|
||||
cmDspPresetMgr_t pm;
|
||||
unsigned nextInstId;
|
||||
unsigned pgmIdx;
|
||||
cmSeH_t serialPortH;
|
||||
|
||||
|
||||
cmUdpNetH_t netH; //
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
#include "cmDspCtx.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
@ -61,7 +62,7 @@ cmDspRC_t _cmDspSysPgm_TimeLineLite(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspInst_t* ai0 = cmDspSysAllocInst(h,"AudioIn", NULL, 1, 0);
|
||||
cmDspInst_t* ai1 = cmDspSysAllocInst(h,"AudioIn", NULL, 1, 1);
|
||||
//cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn", NULL, 2, "MOTU - Traveler mk3", "MIDI Port");
|
||||
cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn", NULL, 2, "Apple Inc. - IAC Driver", "Bus 1");
|
||||
//cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn", NULL, 2, "Apple Inc. - IAC Driver", "Bus 1");
|
||||
|
||||
cmDspInst_t* tlp = cmDspSysAllocInst(h,"TimeLine", "tl", 2, r.tlFn, r.tlPrefixPath );
|
||||
cmDspInst_t* scp = cmDspSysAllocInst(h,"Score", "sc", 1, r.scFn );
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmAudioSys.h"
|
||||
#include "cmProcObj.h"
|
||||
#include "cmDspCtx.h"
|
||||
@ -165,7 +166,7 @@ cmDspRC_t _cmDspSysFinalize( cmDsp_t* p )
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH )
|
||||
cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH, cmSeH_t serialPortH )
|
||||
{
|
||||
unsigned i;
|
||||
cmDspRC_t rc = kOkDspRC;
|
||||
@ -178,9 +179,10 @@ cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH )
|
||||
|
||||
cmErrSetup(&p->err,&ctx->rpt,"DSP System");
|
||||
//p->ctx.ctx = asCtx;
|
||||
p->cmCtx = *ctx;
|
||||
p->netH = netH;
|
||||
p->pgmIdx = cmInvalidIdx;
|
||||
p->cmCtx = *ctx;
|
||||
p->netH = netH;
|
||||
p->serialPortH = serialPortH;
|
||||
p->pgmIdx = cmInvalidIdx;
|
||||
|
||||
// create the DSP class linked heap
|
||||
if(cmLHeapIsValid( p->lhH = cmLHeapCreate(1024,ctx)) == false)
|
||||
@ -1560,6 +1562,13 @@ cmSymTblH_t cmDspSysSymbolTable( cmDspSysH_t h )
|
||||
return p->ctx.stH;
|
||||
}
|
||||
|
||||
cmSeH_t cmDspSysSerialPort( cmDspSysH_t h )
|
||||
{
|
||||
cmDsp_t* p = _cmDspHandleToPtr(h);
|
||||
return p->serialPortH;
|
||||
}
|
||||
|
||||
|
||||
unsigned cmDspSysRegisterStaticSymbol( cmDspSysH_t h, const cmChar_t* symLabel )
|
||||
{ return cmSymTblRegisterStaticSymbol( cmDspSysSymbolTable(h), symLabel ); }
|
||||
|
||||
|
@ -23,7 +23,7 @@ extern "C" {
|
||||
// Control Functions
|
||||
//
|
||||
|
||||
cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH );
|
||||
cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH, cmSeH_t serialPortH );
|
||||
cmDspRC_t cmDspSysFinalize( cmDspSysH_t* hp );
|
||||
|
||||
bool cmDspSysIsValid( cmDspSysH_t h );
|
||||
@ -156,6 +156,7 @@ extern "C" {
|
||||
double cmDspSysSampleRate( cmDspSysH_t h );
|
||||
cmJsonH_t cmDspSysPgmRsrcHandle( cmDspSysH_t h );
|
||||
cmSymTblH_t cmDspSysSymbolTable( cmDspSysH_t h );
|
||||
cmSeH_t cmDspSysSerialPort( cmDspSysH_t h );
|
||||
|
||||
unsigned cmDspSysRegisterStaticSymbol( cmDspSysH_t h, const cmChar_t* symLabel );
|
||||
unsigned cmDspSysRegisterSymbol( cmDspSysH_t h, const cmChar_t* symLabel );
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "cmThread.h"
|
||||
#include "cmUdpPort.h"
|
||||
#include "cmUdpNet.h"
|
||||
#include "cmSerialPort.h"
|
||||
#include "cmTime.h"
|
||||
#include "cmAudioSys.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user