Browse Source

Merge branch 'master' of wf:webapps/gitweb/repos/libcm

master
kevin.larke 4 years ago
parent
commit
0cc1cefe19

+ 3
- 0
Makefile.am View File

@@ -33,6 +33,9 @@ cmSRC += src/libcm/cmAudioPort.c src/libcm/cmApBuf.c src/libcm/cmAudioAggDev.c s
33 33
 cmHDR += src/libcm/cmMidiFilePlay.h src/libcm/cmMidiPort.h src/libcm/cmMidiFile.h src/libcm/cmMidi.h 
34 34
 cmSRC += src/libcm/cmMidiFilePlay.c src/libcm/cmMidiPort.c src/libcm/cmMidiFile.c src/libcm/cmMidi.c 
35 35
 
36
+cmHDR += src/libcm/cmSerialPort.h
37
+cmSRC += src/libcm/cmSerialPort.c
38
+
36 39
 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 
37 40
 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
38 41
 

+ 6
- 3
cmApBuf.c View File

@@ -815,6 +815,7 @@ void cmApBufInputToOutput( unsigned iDevIdx, unsigned oDevIdx )
815 815
 
816 816
       unsigned    byteCnt  = ip->dspFrameCnt * sizeof(cmApSample_t);
817 817
 
818
+
818 819
       if( oBufPtrArray[i] != NULL )
819 820
       {      
820 821
         // the input channel is not disabled
@@ -846,18 +847,20 @@ void cmApBufReport( cmRpt_t* rpt )
846 847
       unsigned ii = 0;
847 848
       unsigned oi = 0;
848 849
       unsigned fn  = 0;
850
+      cmApSample_t mtr = 0;
849 851
       for(k=0; k<ip->chCnt; ++k)
850 852
       {
851 853
         cmApCh* cp = ip->chArray + i;
852 854
         ii += cp->ii;
853 855
         oi += cp->oi;
854 856
         fn += cp->fn;
857
+        mtr += _cmApMeterValue(cp);
855 858
       }
856 859
 
857
-        cmRptPrintf(rpt,"%s - i:%7i o:%7i f:%7i n:%7i err %s:%7i ",
860
+      cmRptPrintf(rpt,"%s - i:%7i o:%7i f:%7i n:%7i err %s:%7i  mtr:%5.4f ",
858 861
         j==0?"IN":"OUT",
859
-        ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt);
860
-
862
+        ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt, mtr);
863
+      
861 864
     }
862 865
 
863 866
     cmRptPrintf(rpt,"\n");

+ 58
- 2
cmAudDsp.c View File

@@ -19,6 +19,7 @@
19 19
 #include "cmApBuf.h"
20 20
 #include "cmMidi.h"
21 21
 #include "cmMidiPort.h"
22
+#include "cmSerialPort.h"
22 23
 #include "dsp/cmDspValue.h"
23 24
 #include "cmMsgProtocol.h"
24 25
 #include "cmThread.h"
@@ -91,6 +92,12 @@ typedef struct
91 92
   unsigned           msgsPerClientPoll;
92 93
   const cmChar_t*    dfltProgramLabel;
93 94
 
95
+  char*              serialDeviceStr;
96
+  unsigned           serialBaud;
97
+  unsigned           serialCfgFlags;
98
+  unsigned           serialPollPeriodMs;
99
+  cmSeH_t            serialPortH;
100
+
94 101
   cmAdAggDev_t*      aggDevArray;
95 102
   unsigned           aggDevCnt;
96 103
 
@@ -169,6 +176,7 @@ cmAdRC_t _cmAdParseSysJsonTree( cmAd_t* p )
169 176
   cmJsonNode_t*   nrtDevArrNodePtr = NULL;
170 177
   cmJsonNode_t*   afpDevArrNodePtr = NULL;
171 178
   cmJsonNode_t*   audDspNodePtr    = NULL;
179
+  cmJsonNode_t*   serialNodePtr    = NULL;
172 180
   const cmChar_t* errLabelPtr      = NULL;
173 181
   unsigned        i;
174 182
   cmJsRC_t      jsRC = kOkJsRC;
@@ -190,12 +198,28 @@ cmAdRC_t _cmAdParseSysJsonTree( cmAd_t* p )
190 198
         "aggDevArray",        kArrayTId  | kOptArgJsFl, &aggDevArrNodePtr,
191 199
         "nrtDevArray",        kArrayTId  | kOptArgJsFl, &nrtDevArrNodePtr,
192 200
         "afpDevArray",        kArrayTId  | kOptArgJsFl, &afpDevArrNodePtr,
201
+        "serial",             kObjectTId | kOptArgJsFl, &serialNodePtr,
193 202
         NULL )) != kOkJsRC )
194 203
   {
195 204
     rc = _cmAdParseMemberErr(p, jsRC, errLabelPtr, "aud_dsp" );
196 205
     goto errLabel;
197 206
   }
198 207
 
208
+  // parse the serial port cfg
209
+  if( serialNodePtr != NULL )
210
+  {
211
+    if(( jsRC      = cmJsonMemberValues( serialNodePtr, &errLabelPtr, 
212
+          "device",           kStringTId, &p->serialDeviceStr,
213
+          "baud",             kIntTId,    &p->serialBaud,
214
+          "flags",            kIntTId,    &p->serialCfgFlags,
215
+          "pollPeriodMs",     kIntTId,    &p->serialPollPeriodMs,
216
+          NULL )) != kOkJsRC )
217
+    {
218
+      rc = _cmAdParseMemberErr(p, jsRC, errLabelPtr, "serial" );
219
+      goto errLabel;
220
+    }
221
+  }
222
+
199 223
   // parse the aggregate device specifications into p->aggDevArray[].
200 224
   if( aggDevArrNodePtr != NULL && (p->aggDevCnt = cmJsonChildCount(aggDevArrNodePtr)) > 0)
201 225
   {
@@ -382,6 +406,22 @@ cmAdRC_t _cmAdSetup( cmAd_t* p )
382 406
   return rc;
383 407
 }
384 408
 
409
+cmAdRC_t _cmAdCreateSerialPort( cmAd_t* p )
410
+{
411
+  cmAdRC_t rc = kOkAdRC;
412
+  
413
+  if( p->serialDeviceStr != NULL )
414
+  {
415
+    p->serialPortH = cmSeCreate( &p->ctx, &p->serialPortH, p->serialDeviceStr, p->serialBaud, p->serialCfgFlags, NULL, NULL, p->serialPollPeriodMs );
416
+    
417
+    if( !cmSeIsOpen(p->serialPortH) )
418
+    {
419
+      rc = cmErrMsg(&p->err,kSerialDevCreateFailAdRC,"The serial device '%s' creation failed.",cmStringNullGuard(p->serialDeviceStr));
420
+    }
421
+  }
422
+  return rc;
423
+}
424
+
385 425
 cmAdRC_t _cmAdCreateAggDevices( cmAd_t* p )
386 426
 {
387 427
   cmAdRC_t rc = kOkAdRC;
@@ -570,6 +610,15 @@ cmAdRC_t _cmAudDspFree( cmAd_t* p )
570 610
     goto errLabel;
571 611
   }
572 612
 
613
+  if( cmSeIsOpen(p->serialPortH) )
614
+  {    
615
+    if( cmSeDestroy(&p->serialPortH) != kOkSeRC )
616
+    {
617
+      rc = cmErrMsg(&p->err,kSerialPortFailAdRC,"Serial port finalize failed.");
618
+      goto errLabel;      
619
+    }
620
+  }
621
+  
573 622
   if( cmMpIsInitialized() )
574 623
     if( cmMpFinalize() != kOkMpRC )
575 624
     {
@@ -695,6 +744,13 @@ cmAdRC_t cmAudDspAlloc( cmCtx_t* ctx, cmAdH_t* hp, cmMsgSendFuncPtr_t cbFunc, vo
695 744
     goto errLabel;
696 745
   }
697 746
 
747
+  // create the serial port
748
+  if( _cmAdCreateSerialPort(p) != kOkAdRC )
749
+  {
750
+    rc = cmErrMsg(&p->err,kSerialPortFailAdRC,"The MIDI system initialization failed.");
751
+    goto errLabel;
752
+  }
753
+  
698 754
   // initialize the MIDI system
699 755
   if( cmMpInitialize(ctx,NULL,NULL,p->midiPortBufByteCnt,"app") != kOkMpRC )
700 756
   {
@@ -713,7 +769,7 @@ cmAdRC_t cmAudDspAlloc( cmCtx_t* ctx, cmAdH_t* hp, cmMsgSendFuncPtr_t cbFunc, vo
713 769
     goto errLabel;
714 770
 
715 771
   // initialize the DSP system
716
-  if( cmDspSysInitialize(ctx,&p->dsH,p->netH) )
772
+  if( cmDspSysInitialize(ctx,&p->dsH,p->netH,p->serialPortH) )
717 773
   {
718 774
     rc = cmErrMsg(&p->err,kDspSysFailAdRC,"The DSP system initialization failed.");
719 775
     goto errLabel;
@@ -1143,7 +1199,7 @@ cmAdRC_t _cmAudDspLoadAudioSys( cmAd_t* p, unsigned asCfgIdx )
1143 1199
       {
1144 1200
         // ... and allocate additional DSP systems when more than one sub-sys is 
1145 1201
         // defined in the audio system configuration
1146
-        if( cmDspSysInitialize(&p->ctx,&dsH,p->netH) != kOkDspRC )
1202
+        if( cmDspSysInitialize(&p->ctx,&dsH,p->netH,p->serialPortH) != kOkDspRC )
1147 1203
         {
1148 1204
           rc = cmErrMsg(&p->err,kDspSysFailAdRC,"Unable to initialize an additional DSP system.");
1149 1205
           goto errLabel;

+ 2
- 0
cmAudDsp.h View File

@@ -13,6 +13,7 @@ extern "C" {
13 13
     kAudioPortFailAdRC,
14 14
     kAudioSysFailAdRC,
15 15
     kMidiSysFailAdRC,
16
+    kSerialPortFailAdRC,
16 17
     kDspSysFailAdRC,
17 18
     kFileSysFailAdRC,
18 19
     kJsonFailAdRC,
@@ -21,6 +22,7 @@ extern "C" {
21 22
     kNoPgmLoadedAdRC,
22 23
     kInvalidSubSysIdxAdRC,
23 24
     kUnknownMsgTypeAdRC,
25
+    kSerialDevCreateFailAdRC,
24 26
     kAggDevSysFailAdRC,
25 27
     kAggDevCreateFailAdRC,
26 28
     kNrtDevSysFailAdRC,

+ 3
- 1
cmAudioPort.c View File

@@ -738,11 +738,13 @@ int cmApPortTest( bool runFl, cmRpt_t* rpt, int argc, const char* argv[] )
738 738
 
739 739
     // setup the buffer for the output device
740 740
     cmApBufSetup( r.outDevIdx, r.srate, r.framesPerCycle, r.bufCnt, cmApDeviceChannelCount(r.outDevIdx,true), r.framesPerCycle, cmApDeviceChannelCount(r.outDevIdx,false), r.framesPerCycle );
741
-
741
+    
742 742
     // setup the buffer for the input device
743 743
     if( r.inDevIdx != r.outDevIdx )
744 744
       cmApBufSetup( r.inDevIdx, r.srate, r.framesPerCycle, r.bufCnt, cmApDeviceChannelCount(r.inDevIdx,true), r.framesPerCycle, cmApDeviceChannelCount(r.inDevIdx,false), r.framesPerCycle ); 
745 745
 
746
+    cmApBufEnableMeter(  r.inDevIdx, -1, kEnableApFl );
747
+
746 748
     // setup an output device
747 749
     if(cmApDeviceSetup(r.outDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkApRC )
748 750
       cmRptPrintf(rpt,"Out device setup failed.\n");

+ 30
- 0
cmAudioSys.c View File

@@ -15,6 +15,7 @@
15 15
 #include "cmThread.h"
16 16
 #include "cmUdpPort.h"
17 17
 #include "cmUdpNet.h"
18
+#include "cmSerialPort.h"
18 19
 #include "cmAudioSysMsg.h"
19 20
 #include "cmAudioSys.h"
20 21
 #include "cmMidi.h"
@@ -37,6 +38,7 @@ typedef struct
37 38
   cmTsMp1cH_t        htdQueueH; // host-to-dsp thread safe msg queue
38 39
   cmThreadMutexH_t   engMutexH; // thread mutex and condition variable
39 40
   cmUdpNetH_t        netH;
41
+  cmSeH_t            serialPortH; 
40 42
   bool               enableFl;  // application controlled pause flag
41 43
   bool               runFl;     // false during finalization otherwise true
42 44
   bool               statusFl;  // true if regular status notifications should be sent
@@ -507,6 +509,13 @@ void _cmAudioSysMidiCallback( const cmMidiPacket_t* pktArray, unsigned pktCnt )
507 509
 
508 510
 }
509 511
 
512
+void _cmAudioSysSerialPortCallback( void* cbArg, const void* byteA, unsigned byteN )
513
+{
514
+  //_cmAsCfg_t* p (_cmAsCfg_t*)cbArg;
515
+  
516
+  // TODO: handle serial receive
517
+}
518
+
510 519
 cmAsRC_t cmAudioSysAllocate( cmAudioSysH_t* hp, cmRpt_t* rpt, const cmAudioSysCfg_t* cfg )
511 520
 {
512 521
   cmAsRC_t rc;
@@ -832,6 +841,7 @@ cmAsRC_t cmAudioSysInitialize( cmAudioSysH_t h, const cmAudioSysCfg_t* cfg )
832 841
     cp->iMeterArray      = cmMemAllocZ( double, cp->status.iMeterCnt );
833 842
     cp->oMeterArray      = cmMemAllocZ( double, cp->status.oMeterCnt );
834 843
     cp->netH             = cfg->netH;
844
+    cp->serialPortH      = cfg->serialPortH;
835 845
 
836 846
     // create the audio System thread
837 847
     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 )
874 884
         goto errLabel;
875 885
       }
876 886
 
887
+    // install the serial port 
888
+    if( cmSeIsOpen(cp->serialPortH) )
889
+    {
890
+      if( cmSeSetCallback(cp->serialPortH, _cmAudioSysSerialPortCallback, cp ) != kOkSeRC )
891
+      {
892
+        rc = _cmAsError(p,kSerialPortFailAsRC,"Serial port callback installation failed.");
893
+        goto errLabel;        
894
+      }
895
+    }
896
+
877 897
     // setup the sub-system status notification 
878 898
     cp->statusUpdateSmpCnt = floor(cmApBufMeterMs() * cp->ss.args.srate / 1000.0 );
879 899
     cp->statusUpdateSmpIdx = 0;
@@ -886,6 +906,16 @@ cmAsRC_t cmAudioSysInitialize( cmAudioSysH_t h, const cmAudioSysCfg_t* cfg )
886 906
       rc = _cmAsError(p,kThreadErrAsRC,"Thread start failed.");
887 907
       goto errLabel;
888 908
     }
909
+
910
+    if( cmSeIsOpen(cp->serialPortH) )
911
+    {
912
+      if( cmSeStart( cp->serialPortH ) != kOkSeRC )
913
+      {
914
+        rc = _cmAsError(p,kSerialPortFailAsRC,"Serial port start failed.");
915
+        goto errLabel;        
916
+      }
917
+      
918
+    }
889 919
   }
890 920
 
891 921
 

+ 2
- 0
cmAudioSys.h View File

@@ -73,6 +73,7 @@ extern "C" {
73 73
     kBufTooSmallAsRC,
74 74
     kNoMsgWaitingAsRC,
75 75
     kMidiSysFailAsRC,
76
+    kSerialPortFailAsRC,
76 77
     kMsgSerializeFailAsRC,
77 78
     kStateBufFailAsRC,
78 79
     kInvalidArgAsRC,
@@ -197,6 +198,7 @@ extern "C" {
197 198
     cmTsQueueCb_t         clientCbFunc; // Called by  cmAudioSysReceiveMsg() to deliver internally generated msg's to the host. 
198 199
                                         //  Set to NULL if msg's will be directly returned by buffers passed to cmAudioSysReceiveMsg().
199 200
     cmUdpNetH_t           netH;
201
+    cmSeH_t               serialPortH;
200 202
   } cmAudioSysCfg_t;
201 203
 
202 204
   extern cmAudioSysH_t cmAudioSysNullHandle;

+ 6
- 0
cmGlobal.h View File

@@ -91,6 +91,12 @@ extern "C" {
91 91
                                                                //<
92 92
                                                                //< If 'b' == 0 then return 'f' with the bits in 'm' cleared.
93 93
                                                                //< otherwise return 'f' with the bits in 'm' set.
94
+  
95
+// In-place assignment version of the above bit operations
96
+#define cmSetBits(f,m)   ((f) |= (m))                             // Set 'f' with the bits in 'm' set.
97
+#define cmClrBits(f,m)   ((f) &= (~(m)))                          // Set 'f' with the bits in 'm' cleared.
98
+#define cmTogBits(f,m)   ((f)^=(m))                               // Return 'f' with the bits in 'm' toggled.
99
+#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'.
94 100
 
95 101
 
96 102
 #define cmMin(v0,v1) ((v0)<(v1) ? (v0) : (v1)) //< Return the minimum arg.

+ 579
- 0
cmSerialPort.c View File

@@ -0,0 +1,579 @@
1
+#include "cmPrefix.h"
2
+#include "cmGlobal.h"
3
+#include "cmRpt.h"
4
+#include "cmErr.h"
5
+#include "cmCtx.h"
6
+#include "cmMem.h"
7
+#include "cmMallocDebug.h"
8
+#include "cmSerialPort.h"
9
+#include "cmThread.h"
10
+
11
+#include <poll.h>
12
+#include <termios.h>
13
+#include <unistd.h>    // close()
14
+#include <fcntl.h>     // O_RDWR
15
+#include <sys/ioctl.h> // TIOCEXCL
16
+
17
+typedef struct cmSerialPort_str
18
+{
19
+  cmErr_t               _err;
20
+  cmThreadH_t           _thH; 
21
+  const char*           _deviceStr;
22
+  int                   _deviceH;
23
+  unsigned              _baudRate;
24
+  unsigned              _cfgFlags;
25
+  cmSeCallbackFunc_t    _cbFunc;
26
+  void*                 _cbArg;
27
+  struct termios        _ttyAttrs;
28
+  struct pollfd         _pollfd;
29
+  unsigned              _pollPeriodMs;
30
+} cmSerialPort_t;
31
+
32
+cmSerialPort_t* _cmSePtrFromHandle( cmSeH_t h )
33
+{
34
+  cmSerialPort_t* p = (cmSerialPort_t*)h.h;
35
+  assert(p!=NULL);
36
+  return p;
37
+}
38
+
39
+void   _cmSeSetClosedState( cmSerialPort_t* p )
40
+{
41
+  if( p->_deviceStr != NULL )
42
+    cmMemFree((char*)(p->_deviceStr));
43
+     
44
+  p->_deviceH = -1;
45
+  p->_deviceStr = NULL;
46
+  p->_baudRate  = 0;
47
+  p->_cfgFlags  = 0;
48
+  p->_cbFunc    = NULL;
49
+  p->_cbArg     = NULL;
50
+      
51
+}
52
+    
53
+cmSeRC_t _cmSeGetAttributes( cmSerialPort_t* p, struct termios* attr ) 
54
+{
55
+  if( tcgetattr(p->_deviceH, attr) == -1 )
56
+    return cmErrSysMsg(&p->_err,kGetAttrFailSeRC,errno,"Error getting tty attributes from %s.",p->_deviceStr);
57
+
58
+  return kOkSeRC;
59
+}
60
+    
61
+cmSeRC_t _cmSePoll( cmSerialPort_t* p, unsigned timeOutMs )
62
+{
63
+  cmSeRC_t rc = kOkSeRC;
64
+  int sysRC;
65
+
66
+  if((sysRC = poll(&p->_pollfd,1,timeOutMs)) == 0)
67
+    rc = kTimeOutSeRC;
68
+  else
69
+  {
70
+    if( sysRC < 0 )
71
+      rc = cmErrSysMsg(&p->_err,kReadFailSeRC,errno,"Poll failed on serial port.");
72
+  }
73
+  
74
+  return rc;
75
+      
76
+}
77
+
78
+bool _cmSeThreadFunc(void* param)
79
+{
80
+  cmSerialPort_t* p = (cmSerialPort_t*)param;
81
+  cmSeH_t h;
82
+  h.h = p;
83
+  unsigned readN;
84
+  if( cmSeIsOpen(h) )
85
+    cmSeReceiveCbTimeOut(h,p->_pollPeriodMs,&readN);
86
+  
87
+      
88
+  
89
+  return true;
90
+}
91
+
92
+    
93
+cmSeRC_t _cmSeDestroy( cmSerialPort_t* p )
94
+{
95
+  cmSeRC_t rc = kOkSeRC;
96
+
97
+
98
+  // stop the thread first
99
+  if( cmThreadDestroy(&p->_thH) != kOkThRC )
100
+  {
101
+    rc = cmErrMsg(&p->_err,kThreadErrSeRC,"Thread destroy failed.");
102
+    goto errLabel;
103
+  }
104
+  
105
+  // Block until all written output has been sent from the device.
106
+  // Note that this call is simply passed on to the serial device driver.
107
+  // See tcsendbreak(3) ("man 3 tcsendbreak") for details.
108
+  if (tcdrain(p->_deviceH) == -1)
109
+  {
110
+    rc = cmErrSysMsg(&p->_err,kFlushFailSeRC,errno,"Error waiting for serial device '%s' to drain.", p->_deviceStr );
111
+    goto errLabel;
112
+  }
113
+
114
+  // It is good practice to reset a serial port back to the state in
115
+  // which you found it. This is why we saved the original termios struct
116
+  // The constant TCSANOW (defined in termios.h) indicates that
117
+  // the change should take effect immediately.
118
+
119
+  if (tcsetattr(p->_deviceH, TCSANOW, &p->_ttyAttrs) ==  -1)
120
+  {
121
+    rc = cmErrSysMsg(&p->_err,kSetAttrFailSeRC,errno,"Error resetting tty attributes on serial device '%s'.",p->_deviceStr);
122
+    goto errLabel;
123
+  }
124
+	
125
+  if( p->_deviceH != -1 )
126
+  {
127
+    if( close(p->_deviceH ) != 0 )
128
+    {
129
+      rc = cmErrSysMsg(&p->_err,kCloseFailSeRC,errno,"Port close failed on serial dvice '%s'.", p->_deviceStr);
130
+      goto errLabel;
131
+    }
132
+		
133
+    _cmSeSetClosedState(p);
134
+  }
135
+
136
+  cmMemPtrFree(&p);
137
+
138
+ errLabel:
139
+  return rc;      
140
+}
141
+    
142
+
143
+cmSeH_t cmSeCreate( cmCtx_t* ctx, cmSeH_t* hp, const char* deviceStr, unsigned baudRate, unsigned cfgFlags, cmSeCallbackFunc_t cbFunc, void* cbArg, unsigned pollPeriodMs )
144
+{
145
+  cmSeRC_t       rc = kOkSeRC;
146
+  struct termios options;
147
+  cmSeH_t h;
148
+  
149
+  // if the port is already open then close it
150
+  if((rc = cmSeDestroy(hp)) != kOkSeRC )
151
+    return *hp;
152
+
153
+  cmSerialPort_t* p = cmMemAllocZ(cmSerialPort_t,1);
154
+  
155
+  cmErrSetup(&p->_err,&ctx->rpt,"Serial Port");
156
+
157
+  p->_deviceH = -1;
158
+    
159
+	// open the port		
160
+	if( (p->_deviceH = open(deviceStr, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1 )
161
+	{
162
+		rc = cmErrSysMsg(&p->_err,kOpenFailSeRC,errno,"Error opening serial '%s'",cmStringNullGuard(deviceStr));
163
+		goto errLabel;;
164
+	}
165
+
166
+  // Note that open() follows POSIX semantics: multiple open() calls to 
167
+  // the same file will succeed unless the TIOCEXCL ioctl is issued.
168
+  // This will prevent additional opens except by root-owned processes.
169
+  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
170
+  
171
+  if( ioctl(p->_deviceH, TIOCEXCL) == -1 )
172
+  {
173
+    rc = cmErrSysMsg(&p->_err,kResourceNotAvailableSeRC,errno,"The serial device '%s' is already in use.", cmStringNullGuard(deviceStr));
174
+    goto errLabel;
175
+  }
176
+
177
+
178
+  // Now that the device is open, clear the O_NONBLOCK flag so 
179
+  // subsequent I/O will block.
180
+  // See fcntl(2) ("man 2 fcntl") for details.
181
+ 	/*
182
+    if (fcntl(_deviceH, F_SETFL, 0) == -1)
183
+
184
+    {
185
+    _error("Error clearing O_NONBLOCK %s - %s(%d).", pr.devFilePath.c_str(), strerror(errno), errno);
186
+    goto errLabel;
187
+    }
188
+	*/
189
+	
190
+  // Get the current options and save them so we can restore the 
191
+  // default settings later.
192
+  if (tcgetattr(p->_deviceH, &p->_ttyAttrs) == -1)
193
+  {
194
+    rc = cmErrSysMsg(&p->_err,kGetAttrFailSeRC,errno,"Error getting tty attributes from the device '%s'.",deviceStr);
195
+    goto errLabel;
196
+  }
197
+
198
+
199
+  // The serial port attributes such as timeouts and baud rate are set by 
200
+  // modifying the termios structure and then calling tcsetattr to
201
+  // cause the changes to take effect. Note that the
202
+  // changes will not take effect without the tcsetattr() call.
203
+  // See tcsetattr(4) ("man 4 tcsetattr") for details.
204
+  options = p->_ttyAttrs;
205
+
206
+
207
+  // Set raw input (non-canonical) mode, with reads blocking until either 
208
+  // a single character has been received or a 100ms timeout expires.
209
+  // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") 
210
+  // for details.
211
+  cfmakeraw(&options);
212
+  options.c_cc[VMIN] = 1;
213
+  options.c_cc[VTIME] = 1;
214
+
215
+
216
+  // The baud rate, word length, and handshake options can be set as follows:
217
+
218
+ 
219
+	// set baud rate
220
+  cfsetspeed(&options, baudRate);
221
+  
222
+  options.c_cflag |=  CREAD | CLOCAL; // ignore modem controls
223
+
224
+  // set data word size
225
+  cmClrBits(options.c_cflag, CSIZE); // clear the word size bits
226
+  cmEnaBits(options.c_cflag,	CS5,			cmIsFlag(cfgFlags, kDataBits5SeFl));
227
+  cmEnaBits(options.c_cflag,	CS6,			cmIsFlag(cfgFlags, kDataBits6SeFl));
228
+  cmEnaBits(options.c_cflag,	CS7,			cmIsFlag(cfgFlags, kDataBits7SeFl));
229
+  cmEnaBits(options.c_cflag,	CS8,			cmIsFlag(cfgFlags, kDataBits8SeFl));
230
+
231
+  cmClrBits(options.c_cflag, PARENB); // assume no-parity
232
+
233
+  // if the odd or even parity flag is set
234
+  if( cmIsFlag( cfgFlags, kEvenParitySeFl) || cmIsFlag( cfgFlags, kOddParitySeFl ) )
235
+  {
236
+    cmSetBits(options.c_cflag,	PARENB);
237
+    	
238
+    if( cmIsFlag(cfgFlags, kOddParitySeFl ) )
239
+      cmSetBits( options.c_cflag,	PARODD);
240
+  }
241
+
242
+	// set two stop bits    
243
+  cmEnaBits( options.c_cflag, CSTOPB, cmIsFlag(cfgFlags, k2StopBitSeFl));
244
+    
245
+    		    
246
+  // set hardware flow control
247
+  //cmEnaBits(options.c_cflag,		CCTS_OFLOW, 	cmIsFlag(cfgFlags, kCTS_OutFlowCtlFl)); 
248
+	//cmEnaBits(options.c_cflag, 	CRTS_IFLOW, 	cmIsFlag(cfgFlags, kRTS_InFlowCtlFl));
249
+	//cmEnaBits(options.c_cflag, 	CDTR_IFLOW, 	cmIsFlag(cfgFlags, kDTR_InFlowCtlFl));
250
+	//cmEnaBits(options.c_cflag, 	CDSR_OFLOW, 	cmIsFlag(cfgFlags, kDSR_OutFlowCtlFl));
251
+	//cmEnaBits(options.c_cflag, 	CCAR_OFLOW, 	cmIsFlag(cfgFlags, kDCD_OutFlowCtlFl));
252
+    
253
+	cmClrBits(options.c_cflag,CRTSCTS); // turn-off hardware flow control
254
+
255
+	// 7 bit words, enable even parity, CTS out ctl flow, RTS in ctl flow
256
+	// note: set PARODD and PARENB to enable odd parity)
257
+	//options.c_cflag |= (CS7 | PARENB | CCTS_OFLOW | CRTS_IFLOW );
258
+
259
+  // Cause the new options to take effect immediately.
260
+  if (tcsetattr(p->_deviceH, TCSANOW, &options) == -1)
261
+  {
262
+
263
+    rc = cmErrSysMsg(&p->_err,kSetAttrFailSeRC,errno,"Error setting tty attributes on serial device %.", deviceStr);
264
+    goto errLabel;
265
+  }
266
+  
267
+  memset(&p->_pollfd,0,sizeof(p->_pollfd));
268
+  p->_pollfd.fd     = p->_deviceH;
269
+  p->_pollfd.events = POLLIN;
270
+  
271
+  p->_deviceStr    = cmMemAllocStr( deviceStr );
272
+  p->_baudRate     = baudRate;
273
+	p->_cfgFlags     = cfgFlags;
274
+  p->_cbFunc       = cbFunc;
275
+  p->_cbArg        = cbArg;
276
+  p->_pollPeriodMs = pollPeriodMs;
277
+
278
+  // create the listening thread
279
+  if( cmThreadCreate( &p->_thH, _cmSeThreadFunc, p, &ctx->rpt) != kOkThRC )
280
+  {
281
+    rc = cmErrMsg(&p->_err,kThreadErrSeRC,"Thread initialization failed.");
282
+    goto errLabel;
283
+  }
284
+
285
+  if( hp != NULL )
286
+    hp->h = p;
287
+  else
288
+    h.h = p;
289
+  
290
+ errLabel:
291
+  if( rc != kOkSeRC )
292
+  {
293
+    _cmSeDestroy(p);
294
+    h.h = NULL;
295
+	}
296
+  
297
+  return hp != NULL ? *hp : h;
298
+  
299
+}
300
+
301
+cmSeRC_t cmSeDestroy(cmSeH_t* hp )
302
+{
303
+  cmSeRC_t rc = kOkSeRC; 
304
+  
305
+  if( hp==NULL || !cmSeIsOpen(*hp) )
306
+    return kOkSeRC;
307
+
308
+  cmSerialPort_t* p = _cmSePtrFromHandle(*hp);
309
+
310
+  if((rc = _cmSeDestroy(p)) != kOkSeRC )
311
+    return rc;
312
+
313
+  hp->h = NULL;
314
+  
315
+  return rc;
316
+}
317
+
318
+cmSeRC_t  cmSeSetCallback( cmSeH_t h, cmSeCallbackFunc_t cbFunc, void* cbArg  )
319
+{
320
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
321
+  p->_cbFunc  = cbFunc;
322
+  p->_cbArg   = cbArg;
323
+  return kOkSeRC;
324
+}
325
+
326
+cmSeRC_t  cmSeStart( cmSeH_t h )
327
+{
328
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
329
+  
330
+  if( cmThreadPause(p->_thH,0) != kOkThRC )
331
+    return cmErrMsg(&p->_err,kThreadErrSeRC,0,"Thread start failed.");
332
+  
333
+  return kOkSeRC;
334
+}
335
+
336
+
337
+
338
+bool cmSeIsOpen( cmSeH_t h)
339
+{
340
+  if( h.h == NULL )
341
+    return false;
342
+  
343
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
344
+  return p->_deviceH != -1;
345
+}
346
+
347
+cmSeRC_t cmSeSend( cmSeH_t h, const void* byteA, unsigned byteN )
348
+{
349
+  cmSeRC_t        rc = kOkSeRC;
350
+  cmSerialPort_t* p  = _cmSePtrFromHandle(h);
351
+      
352
+  if( !cmSeIsOpen(h)  )
353
+    return cmErrWarnMsg( &p->_err, kResourceNotAvailableSeRC, "An attempt was made to transmit from a closed serial port.");
354
+        
355
+  if( byteN == 0 )
356
+    return rc;
357
+        
358
+  // implement a non blocking write - if less than all the bytes were written then iterate
359
+  unsigned i = 0;
360
+  do
361
+  {
362
+    int n = 0;
363
+    if((n = write( p->_deviceH, ((char*)byteA)+i, byteN-i )) == -1 )
364
+    {
365
+      rc = cmErrSysMsg(&p->_err,kWriteFailSeRC,errno,"Write failed on serial port '%s'.", p->_deviceStr );
366
+      break;
367
+    }
368
+
369
+    i += n;
370
+
371
+      
372
+  }while( i<byteN );
373
+
374
+  return rc;
375
+  
376
+}
377
+
378
+
379
+cmSeRC_t cmSeReceiveCbNb( cmSeH_t h, unsigned* readN_Ref)
380
+{
381
+  cmSeRC_t        rc   = kOkSeRC;
382
+  cmSerialPort_t* p    = _cmSePtrFromHandle(h);
383
+  const unsigned  bufN = 512;
384
+  char            buf[ bufN ];
385
+
386
+  if( readN_Ref != NULL)
387
+    *readN_Ref = 0;
388
+
389
+  if((rc = cmSeReceiveNb(h,buf,bufN,readN_Ref)) == kOkSeRC )
390
+    if( readN_Ref > 0 && p->_cbFunc != NULL )
391
+      p->_cbFunc( p->_cbArg, buf, *readN_Ref );
392
+
393
+  return rc;
394
+  
395
+}
396
+  
397
+cmSeRC_t cmSeReceiveCbTimeOut( cmSeH_t h, unsigned timeOutMs, unsigned* readN_Ref)
398
+{
399
+  cmSeRC_t        rc;
400
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
401
+
402
+  if((rc = _cmSePoll(p,timeOutMs)) == kOkSeRC )
403
+    rc = cmSeReceiveCbNb(h,readN_Ref);
404
+  return rc;
405
+  
406
+}
407
+
408
+cmSeRC_t cmSeReceiveNb( cmSeH_t h, void* buf, unsigned bufN, unsigned* readN_Ref)
409
+{
410
+  cmSeRC_t        rc = kOkSeRC;
411
+  cmSerialPort_t* p  = _cmSePtrFromHandle(h);
412
+
413
+  if( readN_Ref != NULL )
414
+    *readN_Ref = 0;
415
+  
416
+  if( !cmSeIsOpen(h)  )
417
+    return cmErrWarnMsg(&p->_err, kResourceNotAvailableSeRC, "An attempt was made to read from a closed serial port.");
418
+  
419
+  int       n    = 0;
420
+  
421
+  // if attempt to read the port succeeded ...
422
+  if((n =read( p->_deviceH, buf, bufN )) != -1 )
423
+    *readN_Ref = n;
424
+  else
425
+  {
426
+    // ... or failed and it wasn't because the port was empty
427
+    if( errno != EAGAIN)
428
+      rc = cmErrSysMsg(&p->_err,kReadFailSeRC,errno,"An attempt to read the serial port '%s' failed.", p->_deviceStr );
429
+  }
430
+    
431
+  return rc;
432
+}
433
+    
434
+cmSeRC_t cmSeReceive( cmSeH_t h, void* buf, unsigned bufByteN, unsigned timeOutMs, unsigned* readN_Ref )
435
+{
436
+  cmSeRC_t        rc = kOkSeRC;
437
+  cmSerialPort_t* p  = _cmSePtrFromHandle(h);
438
+  
439
+  if((rc = _cmSePoll(p,timeOutMs)) == kOkSeRC )
440
+    rc = cmSeReceiveNb(h,buf,bufByteN,readN_Ref);
441
+  
442
+  return rc;  
443
+}
444
+
445
+const char* cmSeDevice( cmSeH_t h)
446
+{
447
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
448
+  return p->_deviceStr;
449
+}
450
+    
451
+unsigned    cmSeBaudRate( cmSeH_t h)
452
+{
453
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
454
+  return p->_baudRate;
455
+}
456
+
457
+unsigned    cmSeCfgFlags( cmSeH_t h)
458
+{
459
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
460
+  return p->_cfgFlags;
461
+}
462
+
463
+unsigned cmSeReadInBaudRate( cmSeH_t h )
464
+{
465
+	struct termios attr;
466
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
467
+	
468
+	if((_cmSeGetAttributes(p,&attr)) != kOkSeRC )
469
+		return 0;
470
+
471
+	return cfgetispeed(&attr);	
472
+  
473
+}
474
+
475
+unsigned cmSeReadOutBaudRate( cmSeH_t h)
476
+{
477
+	struct termios attr;
478
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
479
+	
480
+	if((_cmSeGetAttributes(p,&attr)) != kOkSeRC )
481
+		return 0;
482
+		
483
+	return cfgetospeed(&attr);	
484
+  
485
+}
486
+
487
+unsigned cmSeReadCfgFlags( cmSeH_t h)
488
+{
489
+	struct termios attr;	
490
+	unsigned result = 0;
491
+  cmSerialPort_t* p = _cmSePtrFromHandle(h);
492
+
493
+	if((_cmSeGetAttributes(p,&attr)) == false )
494
+		return 0;
495
+
496
+	switch( attr.c_cflag & CSIZE )
497
+	{
498
+		case CS5:
499
+			cmSetBits( result, kDataBits5SeFl);
500
+			break;
501
+			
502
+		case CS6:
503
+			cmSetBits( result, kDataBits6SeFl );
504
+			break;
505
+			
506
+		case CS7:
507
+			cmSetBits( result, kDataBits7SeFl);
508
+			break;
509
+			
510
+		case CS8:
511
+			cmSetBits( result, kDataBits8SeFl);
512
+			break;
513
+	}
514
+	
515
+	cmEnaBits( result, k2StopBitSeFl, cmIsFlag(  attr.c_cflag, CSTOPB ));
516
+	cmEnaBits( result, k1StopBitSeFl, !cmIsFlag( attr.c_cflag, CSTOPB ));
517
+
518
+	if( cmIsFlag( attr.c_cflag, PARENB ) )
519
+	{
520
+		cmEnaBits( result, kOddParitySeFl, 	cmIsFlag( attr.c_cflag, PARODD ));
521
+		cmEnaBits( result, kEvenParitySeFl, 	!cmIsFlag( attr.c_cflag, PARODD ));
522
+	}		
523
+	
524
+	return result;
525
+  
526
+}
527
+
528
+
529
+//====================================================================================================
530
+//
531
+//
532
+
533
+
534
+void _cmSePortTestCb( void* arg, const void* byteA, unsigned byteN )
535
+{
536
+  const char* text = (const char*)byteA;
537
+      
538
+  for(unsigned i=0; i<byteN; ++i)
539
+    printf("%c:%i ",text[i],(int)text[i]);
540
+
541
+  if( byteN )
542
+    fflush(stdout);      
543
+}
544
+
545
+cmSeRC_t cmSePortTest(cmCtx_t* ctx)
546
+{
547
+  // Use this test an Arduino running study/serial/arduino_xmt_rcv/main.c  
548
+  cmSeRC_t                  rc             = kOkSeRC;
549
+  const char*               device         = "/dev/ttyACM0";
550
+  unsigned                  baud           = 38400;
551
+  unsigned                  serialCfgFlags = kDefaultCfgSeFlags;
552
+  unsigned                  pollPeriodMs   = 50;
553
+  cmSeH_t                   h;
554
+
555
+  h.h = NULL;
556
+  
557
+  h = cmSeCreate(ctx,&h,device,baud,serialCfgFlags,_cmSePortTestCb,NULL,pollPeriodMs);
558
+
559
+  if( cmSeIsOpen(h) )
560
+    cmSeStart(h);
561
+
562
+  bool quitFl = false;
563
+  printf("q=quit\n");
564
+  while(!quitFl)
565
+  {
566
+    char c = getchar();
567
+    
568
+    if( c == 'q')
569
+      quitFl = true;
570
+    else
571
+      if( '0' <= c && c <= 'z' )
572
+        cmSeSend(h,&c,1);
573
+      
574
+    
575
+  }
576
+
577
+  cmSeDestroy(&h);
578
+  return rc;
579
+}

+ 93
- 0
cmSerialPort.h View File

@@ -0,0 +1,93 @@
1
+#ifndef cmSerialPort_h
2
+#define cmSerialPort_h
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+  typedef unsigned cmSeRC_t;
9
+
10
+  enum
11
+  {
12
+   kOkSeRC = cmOkRC,
13
+   kFlushFailSeRC,
14
+   kSetAttrFailSeRC,
15
+   kCloseFailSeRC,
16
+   kOpenFailSeRC,
17
+   kResourceNotAvailableSeRC,
18
+   kGetAttrFailSeRC,
19
+   kWriteFailSeRC,
20
+   kReadFailSeRC,
21
+   kTimeOutSeRC,
22
+   kThreadErrSeRC
23
+  };
24
+
25
+
26
+  enum
27
+  {
28
+   kDataBits5SeFl 	= 0x0001,
29
+   kDataBits6SeFl 	= 0x0002,
30
+   kDataBits7SeFl 	= 0x0004,
31
+   kDataBits8SeFl 	= 0x0008,
32
+   kDataBitsSeMask	= 0x000f,
33
+   
34
+   k1StopBitSeFl		= 0x0010,
35
+   k2StopBitSeFl 	  = 0x0020,
36
+   
37
+   kEvenParitySeFl	= 0x0040,
38
+   kOddParitySeFl	  = 0x0080,
39
+   kNoParitySeFl		= 0x0000,
40
+
41
+   kDefaultCfgSeFlags = kDataBits8SeFl | k1StopBitSeFl | kNoParitySeFl
42
+  };
43
+
44
+
45
+
46
+  
47
+  typedef void (*cmSeCallbackFunc_t)( void* cbArg, const void* byteA, unsigned byteN );
48
+
49
+  typedef cmHandle_t cmSeH_t;
50
+    
51
+  cmSeH_t   cmSeCreate( cmCtx_t* ctx, cmSeH_t* hp, const char* device, unsigned baudRate, unsigned cfgFlags, cmSeCallbackFunc_t cbFunc, void* cbArg, unsigned pollPeriodMs );
52
+  cmSeRC_t  cmSeDestroy(cmSeH_t* hp );
53
+
54
+  cmSeRC_t  cmSeSetCallback( cmSeH_t h, cmSeCallbackFunc_t cbFunc, void* cbArg  );
55
+  cmSeRC_t  cmSeStart( cmSeH_t h );
56
+
57
+  bool cmSeIsOpen( cmSeH_t h);
58
+    
59
+  cmSeRC_t cmSeSend( cmSeH_t h, const void* byteA, unsigned byteN );
60
+
61
+
62
+  // Make callback to listener with result of read - Non-blocking
63
+  cmSeRC_t cmSeReceiveCbNb( cmSeH_t h, unsigned* readN_Ref);
64
+  
65
+  // Make callback to listener with result of read - Block for up to timeOutMs.
66
+  cmSeRC_t cmSeReceiveCbTimeOut( cmSeH_t h, unsigned timeOutMs, unsigned* readN_Ref); 
67
+
68
+  // Return result of read in buf[bufByteN] - Non-blocking.
69
+  cmSeRC_t cmSeReceiveNb( cmSeH_t h, void* buf, unsigned bufByteN, unsigned* readN_Ref);
70
+    
71
+  // Return result of read in buf[bufByteN] - Block for up to timeOutMs.
72
+  cmSeRC_t cmSeReceive( cmSeH_t h, void* buf, unsigned bufByteN, unsigned timeOutMs, unsigned* readN_Ref );
73
+
74
+  const char* cmSeDevice( cmSeH_t h);
75
+    
76
+  // Get the baud rate and cfgFlags used to initialize the port
77
+  unsigned    cmSeBaudRate( cmSeH_t h);
78
+  unsigned    cmSeCfgFlags( cmSeH_t h);
79
+
80
+  // Get the baud rate and cfg flags by reading the device.
81
+  // Note the the returned buad rate is a system id rather than the actual baud rate,
82
+  // however the cfgFlags are converted to the same kXXXFl defined in this class.
83
+  unsigned cmSeReadInBaudRate( cmSeH_t h );
84
+  unsigned cmSeReadOutBaudRate( cmSeH_t h);
85
+  unsigned cmSeReadCfgFlags( cmSeH_t h);
86
+
87
+  cmSeRC_t cmSePortTest(cmCtx_t* ctx);
88
+
89
+#ifdef __cplusplus
90
+}
91
+#endif
92
+
93
+#endif

+ 2
- 0
dsp/cmDspBuiltIn.c View File

@@ -27,6 +27,7 @@
27 27
 #include "cmThread.h"
28 28
 #include "cmUdpPort.h"
29 29
 #include "cmUdpNet.h"
30
+#include "cmSerialPort.h"
30 31
 #include "cmTime.h"
31 32
 #include "cmAudioSys.h"
32 33
 #include "cmDspSys.h"
@@ -5564,6 +5565,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
5564 5565
   cmActiveMeasClassCons,
5565 5566
   cmAmSyncClassCons,
5566 5567
   cmNanoMapClassCons,
5568
+  cmPicadaeClassCons,
5567 5569
   cmRecdPlayClassCons,
5568 5570
   cmGoertzelClassCons,
5569 5571
   cmSyncRecdClassCons,

+ 3
- 2
dsp/cmDspClass.c View File

@@ -15,6 +15,7 @@
15 15
 #include "cmThread.h"
16 16
 #include "cmUdpPort.h"
17 17
 #include "cmUdpNet.h"
18
+#include "cmSerialPort.h"
18 19
 #include "cmTime.h"
19 20
 #include "cmAudioSys.h"
20 21
 #include "cmProcObj.h"
@@ -128,7 +129,7 @@ void* cmDspInstAllocate(
128 129
     }
129 130
 
130 131
     // determine the space needed for matrices of known size
131
-    if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
132
+    if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn)>0 )
132 133
     {
133 134
       unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );
134 135
       varDataByteCnt += n;
@@ -238,7 +239,7 @@ void* cmDspInstAllocate(
238 239
     }
239 240
 
240 241
     // assign memory to the matrix types of known size
241
-    if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn) )
242
+    if( cmIsFlag(flags,kMtxDsvFl) && (rn*argV[i].cn)>0 )
242 243
     {
243 244
       cmDsvSetMtx(  &ip->varArray[i].value, flags, varDataPtr, rn, argV[i].cn );
244 245
       unsigned n = cmDsvByteCount( flags, rn, argV[i].cn );

+ 1
- 0
dsp/cmDspFx.c View File

@@ -22,6 +22,7 @@
22 22
 #include "cmThread.h" 
23 23
 #include "cmUdpPort.h"
24 24
 #include "cmUdpNet.h"
25
+#include "cmSerialPort.h"
25 26
 #include "cmTime.h"
26 27
 #include "cmAudioSys.h"
27 28
 #include "cmProcObj.h"

+ 130
- 0
dsp/cmDspKr.c View File

@@ -18,6 +18,8 @@
18 18
 #include "cmThread.h"
19 19
 #include "cmUdpPort.h"
20 20
 #include "cmUdpNet.h"
21
+#include "cmSerialPort.h"
22
+
21 23
 //( { file_desc:"'snap' audio effects performance analysis units." kw:[snap]}
22 24
 
23 25
 #include "cmTime.h"
@@ -2803,6 +2805,134 @@ cmDspClass_t* cmNanoMapClassCons( cmDspCtx_t* ctx )
2803 2805
 
2804 2806
 //------------------------------------------------------------------------------------------------------------
2805 2807
 //)
2808
+//( { label:cmDspPicadae file_desc:"Control a MIDI synth." kw:[sunit] }
2809
+
2810
+enum
2811
+{
2812
+  kPgmPcId,
2813
+  kStatusPcId,
2814
+  kD0PcId,
2815
+  kD1PcId,
2816
+  kThruPcId
2817
+};
2818
+
2819
+cmDspClass_t _cmPicadaeDC;
2820
+
2821
+typedef struct
2822
+{
2823
+  cmDspInst_t inst;
2824
+
2825
+} cmDspPicadae_t;
2826
+
2827
+cmDspRC_t _cmDspPicadaeSend( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned st, unsigned d0, unsigned d1 )
2828
+{
2829
+  cmDspSetUInt(ctx,inst,kD1PcId,d1);
2830
+  cmDspSetUInt(ctx,inst,kD0PcId,d0);
2831
+  cmDspSetUInt(ctx,inst,kStatusPcId,st);
2832
+  return kOkDspRC;
2833
+}
2834
+
2835
+void _cmDspPicadaePgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
2836
+{
2837
+  //cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
2838
+
2839
+  unsigned i;
2840
+        
2841
+  for(i=0; i<kMidiChCnt; ++i)
2842
+  {
2843
+    _cmDspPicadaeSend(ctx,inst,kCtlMdId+i,121,0); // reset all controllers
2844
+    _cmDspPicadaeSend(ctx,inst,kCtlMdId+i,123,0); // turn all notes off
2845
+    _cmDspPicadaeSend(ctx,inst,kCtlMdId+i,0,0);   // switch to bank 0
2846
+    _cmDspPicadaeSend(ctx,inst,kPgmMdId+i,pgm,0); // send pgm change
2847
+    cmSleepMs(15);
2848
+  }
2849
+  
2850
+}
2851
+
2852
+cmDspInst_t*  _cmDspPicadaeAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
2853
+{
2854
+  cmDspVarArg_t args[] =
2855
+  {
2856
+    { "pgm",    kPgmPcId,    0,  0,              kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reprogram all channels to this pgm." },
2857
+    { "status", kStatusPcId, 0,  0,  kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI status" },
2858
+    { "d0",     kD0PcId,     0,  0,  kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d0" },
2859
+    { "d1",     kD1PcId,     0,  0,  kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d1" },
2860
+    { "thru",   kThruPcId,   0,  0,              kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Enable pass through."},
2861
+    { NULL, 0, 0, 0, 0 }
2862
+  };
2863
+
2864
+  cmDspPicadae_t* p = cmDspInstAlloc(cmDspPicadae_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
2865
+  
2866
+  cmDspSetDefaultUInt(ctx,&p->inst, kPgmPcId, 0, 0 );
2867
+
2868
+  return &p->inst;
2869
+}
2870
+
2871
+cmDspRC_t _cmDspPicadaeReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2872
+{
2873
+  cmDspRC_t      rc = kOkDspRC;
2874
+
2875
+  cmDspApplyAllDefaults(ctx,inst);
2876
+
2877
+  _cmDspPicadaePgm(ctx,inst,cmDspUInt(inst,kPgmPcId));
2878
+
2879
+  return rc;
2880
+} 
2881
+
2882
+cmDspRC_t _cmDspPicadaeRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2883
+{
2884
+  //cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
2885
+
2886
+  switch( evt->dstVarId )
2887
+  {
2888
+    case kPgmPcId:
2889
+      cmDspSetEvent(ctx,inst,evt);
2890
+      _cmDspPicadaePgm(ctx,inst,cmDspUInt(inst,kPgmPcId));
2891
+      break;
2892
+
2893
+    case kStatusPcId:
2894
+      {
2895
+        unsigned status = cmDsvGetUInt(evt->valuePtr);        
2896
+        unsigned stat_no_ch = status & 0xf0;
2897
+        if( stat_no_ch == kNoteOnMdId || stat_no_ch == kNoteOffMdId || stat_no_ch == kCtlMdId  )
2898
+        {
2899
+          //unsigned d0 = cmDspUInt(inst,kD0PcId);
2900
+          unsigned ch = 0; //d0 % 8;
2901
+          status = (status & 0xf0) + ch;
2902
+          cmDspSetUInt(ctx,inst,kStatusPcId,status);
2903
+        }
2904
+       
2905
+      }
2906
+      break;
2907
+
2908
+
2909
+    default:
2910
+      cmDspSetEvent(ctx,inst,evt);
2911
+      break;
2912
+  }
2913
+
2914
+
2915
+  return kOkDspRC;
2916
+}
2917
+
2918
+cmDspClass_t* cmPicadaeClassCons( cmDspCtx_t* ctx )
2919
+{
2920
+  cmDspClassSetup(&_cmPicadaeDC,ctx,"Picadae",
2921
+    NULL,
2922
+    _cmDspPicadaeAlloc,
2923
+    NULL,
2924
+    _cmDspPicadaeReset,
2925
+    NULL,
2926
+    _cmDspPicadaeRecv,
2927
+    NULL,
2928
+    NULL,
2929
+    "Picadaesynth Mapper");
2930
+
2931
+  return &_cmPicadaeDC;
2932
+}
2933
+
2934
+//------------------------------------------------------------------------------------------------------------
2935
+//)
2806 2936
 //( { label:cmDspRecdPlay file_desc:"Record audio segments from a live perfromance and play them back at a later time" kw:[sunit] }
2807 2937
 
2808 2938
 enum

+ 1
- 0
dsp/cmDspKr.h View File

@@ -17,6 +17,7 @@ extern "C" {
17 17
   struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
18 18
   struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
19 19
   struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
20
+  struct cmDspClass_str* cmPicadaeClassCons( cmDspCtx_t* ctx );
20 21
   struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
21 22
   struct cmDspClass_str* cmGoertzelClassCons( cmDspCtx_t* ctx );
22 23
   struct cmDspClass_str* cmSyncRecdClassCons( cmDspCtx_t* ctx );

+ 1
- 0
dsp/cmDspNet.c View File

@@ -16,6 +16,7 @@
16 16
 #include "cmThread.h"
17 17
 #include "cmUdpPort.h"
18 18
 #include "cmUdpNet.h"
19
+#include "cmSerialPort.h"
19 20
 #include "cmTime.h"
20 21
 #include "cmAudioSys.h"
21 22
 #include "cmProcObj.h"

+ 1
- 0
dsp/cmDspNet.h View File

@@ -72,6 +72,7 @@ extern "C" {
72 72
     cmDspPresetMgr_t    pm;
73 73
     unsigned            nextInstId;
74 74
     unsigned            pgmIdx;
75
+    cmSeH_t             serialPortH;
75 76
 
76 77
 
77 78
     cmUdpNetH_t           netH;          //

+ 1
- 0
dsp/cmDspPgm.c View File

@@ -17,6 +17,7 @@
17 17
 #include "cmThread.h"
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20
+#include "cmSerialPort.h"
20 21
 #include "cmTime.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"

+ 1
- 0
dsp/cmDspPgmKr.c View File

@@ -19,6 +19,7 @@
19 19
 #include "cmThread.h"
20 20
 #include "cmUdpPort.h"
21 21
 #include "cmUdpNet.h"
22
+#include "cmSerialPort.h"
22 23
 #include "cmTime.h"
23 24
 #include "cmAudioSys.h"
24 25
 #include "cmProcObj.h"

+ 1
- 0
dsp/cmDspPgmKrChain.c View File

@@ -18,6 +18,7 @@
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20 20
 #include "cmTime.h"
21
+#include "cmSerialPort.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"
23 24
 #include "cmDspCtx.h"

+ 1
- 0
dsp/cmDspPgmKrChain2.c View File

@@ -17,6 +17,7 @@
17 17
 #include "cmThread.h"
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20
+#include "cmSerialPort.h"
20 21
 #include "cmTime.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"

+ 2
- 1
dsp/cmDspPgmKrTimeLineLite.c View File

@@ -19,6 +19,7 @@
19 19
 #include "cmThread.h"
20 20
 #include "cmUdpPort.h"
21 21
 #include "cmUdpNet.h"
22
+#include "cmSerialPort.h"
22 23
 #include "cmTime.h"
23 24
 #include "cmAudioSys.h"
24 25
 #include "cmProcObj.h"
@@ -61,7 +62,7 @@ cmDspRC_t _cmDspSysPgm_TimeLineLite(cmDspSysH_t h, void** userPtrPtr )
61 62
   cmDspInst_t* ai0 = cmDspSysAllocInst(h,"AudioIn",     NULL,  1, 0);
62 63
   cmDspInst_t* ai1 = cmDspSysAllocInst(h,"AudioIn",     NULL,  1, 1);
63 64
   //cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn",      NULL,  2, "MOTU - Traveler mk3", "MIDI Port");
64
-  cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn",      NULL,  2, "Apple Inc. - IAC Driver", "Bus 1");
65
+  //cmDspInst_t* mip = cmDspSysAllocInst(h,"MidiIn",      NULL,  2, "Apple Inc. - IAC Driver", "Bus 1");
65 66
   
66 67
   cmDspInst_t* tlp  = cmDspSysAllocInst(h,"TimeLine",    "tl",  2, r.tlFn, r.tlPrefixPath );
67 68
   cmDspInst_t* scp  = cmDspSysAllocInst(h,"Score",       "sc",  1, r.scFn );

+ 1
- 0
dsp/cmDspPgmKrTksb.c View File

@@ -17,6 +17,7 @@
17 17
 #include "cmThread.h"
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20
+#include "cmSerialPort.h"
20 21
 #include "cmTime.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"

+ 1
- 0
dsp/cmDspPgmPP.c View File

@@ -17,6 +17,7 @@
17 17
 #include "cmThread.h"
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20
+#include "cmSerialPort.h"
20 21
 #include "cmTime.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"

+ 1
- 0
dsp/cmDspPgmPPMain.c View File

@@ -17,6 +17,7 @@
17 17
 #include "cmThread.h"
18 18
 #include "cmUdpPort.h"
19 19
 #include "cmUdpNet.h"
20
+#include "cmSerialPort.h"
20 21
 #include "cmTime.h"
21 22
 #include "cmAudioSys.h"
22 23
 #include "cmProcObj.h"

+ 13
- 4
dsp/cmDspSys.c View File

@@ -19,6 +19,7 @@
19 19
 #include "cmThread.h"
20 20
 #include "cmUdpPort.h"
21 21
 #include "cmUdpNet.h"
22
+#include "cmSerialPort.h"
22 23
 #include "cmAudioSys.h"
23 24
 #include "cmProcObj.h"
24 25
 #include "cmDspCtx.h"
@@ -165,7 +166,7 @@ cmDspRC_t _cmDspSysFinalize( cmDsp_t* p )
165 166
   return rc;
166 167
 }
167 168
 
168
-cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH )
169
+cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH, cmSeH_t serialPortH )
169 170
 {
170 171
   unsigned        i;
171 172
   cmDspRC_t       rc     = kOkDspRC;
@@ -178,9 +179,10 @@ cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH )
178 179
 
179 180
   cmErrSetup(&p->err,&ctx->rpt,"DSP System");
180 181
   //p->ctx.ctx   = asCtx;
181
-  p->cmCtx     = *ctx;
182
-  p->netH      = netH;
183
-  p->pgmIdx    = cmInvalidIdx;
182
+  p->cmCtx       = *ctx;
183
+  p->netH        = netH;
184
+  p->serialPortH = serialPortH;
185
+  p->pgmIdx      = cmInvalidIdx;
184 186
 
185 187
   // create the DSP class  linked heap
186 188
   if(cmLHeapIsValid( p->lhH = cmLHeapCreate(1024,ctx)) == false)
@@ -1560,6 +1562,13 @@ cmSymTblH_t  cmDspSysSymbolTable( cmDspSysH_t h )
1560 1562
   return p->ctx.stH;  
1561 1563
 }
1562 1564
 
1565
+cmSeH_t      cmDspSysSerialPort( cmDspSysH_t h )
1566
+{
1567
+  cmDsp_t* p = _cmDspHandleToPtr(h);
1568
+  return p->serialPortH;
1569
+}
1570
+
1571
+
1563 1572
 unsigned     cmDspSysRegisterStaticSymbol( cmDspSysH_t h, const cmChar_t* symLabel )
1564 1573
 { return cmSymTblRegisterStaticSymbol( cmDspSysSymbolTable(h), symLabel ); }
1565 1574
 

+ 2
- 1
dsp/cmDspSys.h View File

@@ -23,7 +23,7 @@ extern "C" {
23 23
   //  Control Functions
24 24
   //
25 25
 
26
-  cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH );
26
+  cmDspRC_t cmDspSysInitialize( cmCtx_t* ctx, cmDspSysH_t* hp, cmUdpNetH_t netH, cmSeH_t serialPortH );
27 27
   cmDspRC_t cmDspSysFinalize(  cmDspSysH_t* hp );
28 28
   
29 29
   bool      cmDspSysIsValid(   cmDspSysH_t h );
@@ -156,6 +156,7 @@ extern "C" {
156 156
   double          cmDspSysSampleRate( cmDspSysH_t h );
157 157
   cmJsonH_t       cmDspSysPgmRsrcHandle( cmDspSysH_t h );
158 158
   cmSymTblH_t     cmDspSysSymbolTable( cmDspSysH_t h );
159
+  cmSeH_t         cmDspSysSerialPort( cmDspSysH_t h );
159 160
 
160 161
   unsigned        cmDspSysRegisterStaticSymbol( cmDspSysH_t h, const cmChar_t* symLabel );
161 162
   unsigned        cmDspSysRegisterSymbol( cmDspSysH_t h, const cmChar_t* symLabel );

+ 1
- 0
dsp/cmDspUi.c View File

@@ -19,6 +19,7 @@
19 19
 #include "cmThread.h"
20 20
 #include "cmUdpPort.h"
21 21
 #include "cmUdpNet.h"
22
+#include "cmSerialPort.h"
22 23
 #include "cmTime.h"
23 24
 #include "cmAudioSys.h"
24 25
 

Loading…
Cancel
Save