Explorar el Código

Update to the Python wrapper

Corrected issue with RFFT APIs
Added some features to compute graph

Improved documentation related to RFFT
Changed how Python wrapper is built (to prepare fro future
evolution).
Christophe Favergeon hace 3 años
padre
commit
8b49478b1f
Se han modificado 54 ficheros con 534 adiciones y 2394 borrados
  1. 1 2
      .gitignore
  2. 12 0
      ComputeGraph/README.md
  3. 0 74
      ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h
  4. 0 69
      ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h
  5. 0 69
      ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/AudioConfig.h
  6. 0 26
      ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/RingConfig.h
  7. 0 35
      ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/VideoConfig.h
  8. 0 31
      ComputeGraph/cg/nodes/cpp/StreamingNodes/README.md
  9. 0 278
      ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp
  10. 0 125
      ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h
  11. 0 57
      ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp
  12. 0 58
      ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h
  13. 0 202
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp
  14. 0 292
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c
  15. 0 135
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h
  16. 0 101
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp
  17. 0 232
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.c
  18. 0 124
      ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.h
  19. 0 80
      ComputeGraph/cg/nodes/cpp/StreamingSink.h
  20. 0 88
      ComputeGraph/cg/nodes/cpp/StreamingSource.h
  21. 14 8
      ComputeGraph/cg/src/GenericNodes.h
  22. 1 1
      ComputeGraph/examples/CMakeLists.txt
  23. 3 2
      ComputeGraph/examples/example1/generated/scheduler.cpp
  24. 2 1
      ComputeGraph/examples/example1/generated/scheduler.h
  25. 5 3
      ComputeGraph/examples/example1/graph.py
  26. 1 1
      ComputeGraph/examples/example1/main.cpp
  27. 2 0
      ComputeGraph/examples/example10/AppNodes.h
  28. 67 26
      ComputeGraph/examples/example10/generated/scheduler.cpp
  29. 9 2
      ComputeGraph/examples/example10/graph.py
  30. 29 8
      ComputeGraph/examples/example10/test.dot
  31. BIN
      ComputeGraph/examples/example10/test.pdf
  32. 5 2
      PythonWrapper/.gitignore
  33. 13 0
      PythonWrapper/CMakeLists.txt
  34. 5 0
      PythonWrapper/build/clean.bat
  35. 8 0
      PythonWrapper/build/create.bat
  36. 5 0
      PythonWrapper/build_linux/clean.sh
  37. 11 0
      PythonWrapper/build_linux/create.sh
  38. 4 4
      PythonWrapper/cmsisdsp_pkg/src/cmsisdsp_transform.c
  39. 74 13
      PythonWrapper/examples/debug.py
  40. 1 1
      PythonWrapper/examples/example_1_10.py
  41. 1 1
      PythonWrapper/examples/example_1_9.py
  42. 67 17
      PythonWrapper/examples/testrfft_all.py
  43. 11 2
      PythonWrapper_README.md
  44. 39 32
      README.md
  45. 0 2
      Scripts/git/gen_pack.sh
  46. 0 6
      Source/TransformFunctions/arm_rfft_f32.c
  47. 25 12
      Source/TransformFunctions/arm_rfft_fast_f32.c
  48. 5 7
      Source/TransformFunctions/arm_rfft_q15.c
  49. 6 8
      Source/TransformFunctions/arm_rfft_q31.c
  50. 4 0
      cmsisdsp/cg/scheduler/ccode.py
  51. 41 10
      cmsisdsp/cg/scheduler/description.py
  52. 21 6
      cmsisdsp/cg/scheduler/node.py
  53. 1 1
      cmsisdsp/version.py
  54. 41 140
      setup.py

+ 1 - 2
.gitignore

@@ -1,5 +1,4 @@
 DSP_Lib_TestSuite/build/
-PythonWrapper/build/
 PythonWrapper/cmsisdsp.cp36-win_amd64.pyd
 PythonWrapper/internal.cp36-win_amd64.pyd
 PythonWrapper/*.so
@@ -22,7 +21,6 @@ Output/
 Documentation/html/
 PACK.xsd
 *.uvguix.*
-build
 Documentation/html/*
 Doxygen/history.txt
 Doxygen/dsp.dxy
@@ -30,3 +28,4 @@ __pycache__/
 *.pyd
 .DS_Store
 .swiftpm/
+build/

+ 12 - 0
ComputeGraph/README.md

@@ -235,6 +235,8 @@ Another possibility would be to make the buffer static by redefining the macro `
 
 Optional arguments to pass to the C API of the scheduler function
 
+It can either use a `string` or a list of `string` where an element is an argument of the function (and should be valid `C`).
+
 ##### codeArray (default = True)
 
 When true, the scheduling is defined as an array. Otherwise, a list of function calls is generated.
@@ -305,6 +307,8 @@ In case of dynamic / asynchronous scheduling, the FIFOs may need to be bigger th
 
 For instance, a value of 10 means the FIFO will have their size updated from `oldSize` to `1.1 * oldSize` which is ` (1 + 10%)* oldSize`
 
+If the value is a `float` instead of an `int` it will be used as is. For instance, `1.1` would increase the size by `1.1` and be equivalent to the setting `10` (for 10 percent).
+
 ##### asyncDefaultSkip (default True)
 
 Behavior of a pure function (like CMSIS-DSP) in asynchronous mode. When `True`, the execution is skipped if the function can't be executed. If `False`, an error is raised.
@@ -353,6 +357,14 @@ The `fifoClass` argument allows to choose a specific FIFO class in the generated
 
 Only the `FIFO` class is provided by default. Any new implementation must inherit from `FIFObase<T>`
 
+There is also an option to set the scaling factor when used in asynchronous mode:
+
+```python
+g.connect(odd.o,debug.i,fifoScale=3.0)
+```
+
+When this option is set, it will be used (instead of the global setting). This must be a float.
+
 ## How to build the examples
 
 In folder `ComputeGraph/example/build`, type the `cmake` command:

+ 0 - 74
ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/RingPrivate.h

@@ -1,74 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        RingPrivate.h
- * Description:  Implementation for RTX + Keil MDK
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _RINGPRIVATE_H_
-#define _RINGPRIVATE_H_
-
-/*
-
-Implementation for RTX + Keil MDK Event logger
-
-*/
-
-#include <stddef.h>
-#include "arm_vsi.h"
-#ifdef _RTE_
-#include "RTE_Components.h"
-#endif
-#include CMSIS_device_header
-
-#include "cmsis_os2.h"
-
-#include "SchedEvents.h"
-/*
-
-RTX dependent definition
-
-*/
-#define RING_BEGINCRITICALSECTION()  NVIC_DisableIRQ ((IRQn_Type)config->interruptID); 
-#define RING_ENDCRITICALSECTION() NVIC_EnableIRQ ((IRQn_Type)config->interruptID);
-
-#define RING_WAIT_BUFFER(TIMEOUT) osThreadFlagsWait(1,osFlagsWaitAny,(TIMEOUT))
-#define RING_HASWAITERROR(F) (F < 0)
-
-#define RING_RELEASE_BUFFER(THREADID) osThreadFlagsSet((osThreadId_t)(THREADID),1)
-
-/* Debug trace using Event Recorder */
-#define RING_DBG_USER_RESERVE_BUFFER(ID,CONF) EventRecord2 (Evt_UsrReserve, (ID), (uint32_t)(CONF))
-#define RING_DBG_USER_RELEASE_BUFFER(ID,CONF) EventRecord2 (Evt_UsrRelease, (ID), (uint32_t)(CONF))
-#define RING_DBG_USER_WAIT_BUFFER(ID,CONF) EventRecord2 (Evt_UsrWait, (ID), (uint32_t)(CONF))
-#define RING_DBG_USER_BUFFER_RELEASED(ID,CONF) EventRecord2 (Evt_UsrFree, (ID), (uint32_t)(CONF))
-#define RING_DBG_USER_STATUS(SA,SB,CONF) EventRecord4 (Evt_UsrStatus, config->SA,config->SB,(uint32_t)(CONF),0)
-
-#define RING_DBG_INT_RESERVE_BUFFER(ID,CONF) EventRecord2 (Evt_IntReserve, (ID), (uint32_t)(CONF))
-#define RING_DBG_INT_RELEASE_BUFFER(ID,CONF) EventRecord2 (Evt_IntRelease, (ID), (uint32_t)(CONF))
-#define RING_DBG_INT_RELEASE_USER(CONF) EventRecord2 (Evt_IntReleaseUser, (uint32_t)(CONF), 0)
-#define RING_DBG_INT_STATUS(SA,SB,CONF) EventRecord4 (Evt_IntStatus, config->SA,config->SB,(uint32_t)(CONF),0)
-
-#define RING_DBG_ERROR(ERROR,CONF) EventRecord2 (Evt_Error, (ERROR), (uint32_t)(CONF))
-
-#endif

+ 0 - 69
ComputeGraph/cg/nodes/cpp/StreamingNodes/CMSIS_RTOS/SchedEvents.h

@@ -1,69 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        SchedEvents.h
- * Description:  Definition of the events for the Keil MDK Event logger
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _SCHEDEVT_H
-#define _SCHEDEVT_H
-
-/*
-
-Definition of Event IDs for Keil MDK EventRecorder
-
-*/
-#include "EventRecorder.h"
-
-#define EvtNodes 0x00   
-#define EvtRing_User 0x01     
-#define EvtRing_Int 0x02 
-#define EvtRing_All 0x03 
-
-/* Node events */
-
-#define Evt_Sink         EventID (EventLevelAPI,   EvtNodes, 0x00)
-#define Evt_SinkVal      EventID (EventLevelOp,   EvtNodes, 0x01)
-#define Evt_Source       EventID (EventLevelAPI,   EvtNodes, 0x02)
-
-/* User Ring Events */
-#define Evt_UsrReserve      EventID (EventLevelOp,   EvtRing_User, 0x00)
-#define Evt_UsrRelease      EventID (EventLevelOp,   EvtRing_User, 0x01)
-#define Evt_UsrWait      EventID (EventLevelOp,   EvtRing_User, 0x02)
-#define Evt_UsrFree      EventID (EventLevelOp,   EvtRing_User, 0x03)
-#define Evt_UsrStatus      EventID (EventLevelDetail,   EvtRing_User, 0x04)
-
-
-/* Interrupt Ring Events */
-#define Evt_IntReserve      EventID (EventLevelOp,   EvtRing_Int, 0x00)
-#define Evt_IntRelease      EventID (EventLevelOp,   EvtRing_Int, 0x01)
-#define Evt_IntReleaseUser      EventID (EventLevelOp,   EvtRing_Int, 0x02)
-#define Evt_IntStatus      EventID (EventLevelDetail,   EvtRing_Int, 0x03)
-
-
-/* Other Ring Events */
-#define Evt_Error      EventID (EventLevelError,   EvtRing_All, 0x00)
-
-
-
-#endif

+ 0 - 69
ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/AudioConfig.h

@@ -1,69 +0,0 @@
-#ifndef _AUDIOCONFIG_H_
-#define _AUDIOCONFIG_H_ 
-
-// <<< Use Configuration Wizard in Context Menu >>>
-
-// <e>Audio Configuration for RX
-#ifndef AUDIO_DRV_RX_ENABLED
-#define AUDIO_DRV_RX_ENABLED 1
-#endif
-// <o>Sampling Frequency <8000=>   8000 kHz  <16000=>   16000 kHz
-//                     <44100=>   44100 kHz  <48000=>   48000 kHz
-#ifndef AUDIO_DRV_SAMPLINGFREQUENCY_RX
-#define AUDIO_DRV_SAMPLINGFREQUENCY_RX 16000
-#endif
-
-// <o>Number of samples <256=> 256 <512=> 512 <1024=> 1024 <2048=> 2048  
-// <i> Must be consistent with the settings of the Audio source
-#ifndef AUDIO_DRV_NBSAMPLES_RX
-#define AUDIO_DRV_NBSAMPLES_RX 2048
-#endif
-
-// <o>Number of channels <1=>   Mono <2=>   Stereo
-#ifndef AUDIO_DRV_NBCHANNELS_RX
-#define AUDIO_DRV_NBCHANNELS_RX 1U
-#endif
-
-// <o>Channel encoding <2=>   16 Bits
-#ifndef AUDIO_DRV_CHANNEL_ENCODING_RX
-#define AUDIO_DRV_CHANNEL_ENCODING_RX 2U
-#endif
-
-// </e>
-
-// <e>Audio Configuration for TX
-#ifndef AUDIO_DRV_TX_ENABLED
-#define AUDIO_DRV_TX_ENABLED 1
-#endif
-// <o>Sampling Frequency <8000=>   8000 kHz  <16000=>   16000 kHz
-//                     <44100=>   44100 kHz  <48000=>   48000 kHz
-#ifndef AUDIO_DRV_SAMPLINGFREQUENCY_TX
-#define AUDIO_DRV_SAMPLINGFREQUENCY_TX 16000
-#endif
-
-// <o>Number of samples <256=> 256 <512=> 512 <1024=> 1024 <2048=> 2048  
-// <i> Must be consistent with the settings of the Audio source
-#ifndef AUDIO_DRV_NBSAMPLES_TX
-#define AUDIO_DRV_NBSAMPLES_TX 2048
-#endif
-
-// <o>Number of channels <1=>   Mono <2=>   Stereo
-#ifndef AUDIO_DRV_NBCHANNELS_TX
-#define AUDIO_DRV_NBCHANNELS_TX 1U
-#endif
-
-// <o>Channel encoding <2=>   16 Bits
-#ifndef AUDIO_DRV_CHANNEL_ENCODING_TX
-#define AUDIO_DRV_CHANNEL_ENCODING_TX 2U
-#endif
-
-// </e>
-
-// <q> CGSTATIC_VHT_TX_RX_ORDERING: Force TX RX ordering
-#define CGSTATIC_VHT_TX_RX_ORDERING 0
-
-// <<< end of configuration section >>>
-
-#define CGSTATIC_AUDIO_CONFIG 
-
-#endif

+ 0 - 26
ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/RingConfig.h

@@ -1,26 +0,0 @@
-#ifndef _RINGCONFIG_H_
-#define _RINGCONFIG_H_ 
-
-// <<< Use Configuration Wizard in Context Menu >>>
-
-
-// <h>Ring Buffer Configuration
-// <o>Number of buffers <2=> 2 <4=> 4 <8=> 8 <16=> 16 <32=> 32  
-#ifndef RING_NBBUFS
-#define RING_NBBUFS 4
-#endif
-// </h>
-
-// <<< end of configuration section >>>
-
-#if defined(CGSTATIC_AUDIO_CONFIG)
-#define RING_BUFSIZE_RX (AUDIO_DRV_NBSAMPLES_RX * AUDIO_DRV_NBCHANNELS_RX * AUDIO_DRV_CHANNEL_ENCODING_RX)
-#define RING_BUFSIZE_TX (AUDIO_DRV_NBSAMPLES_TX * AUDIO_DRV_NBCHANNELS_TX * AUDIO_DRV_CHANNEL_ENCODING_TX)
-#endif
-
-#if defined(CGSTATIC_VIDEO_CONFIG)
-#define RING_BUFSIZE_RX (VIDEO_DRV_WIDTH * VIDEO_DRV_HEIGHT * VIDEO_DRV_PIXEL_SIZE)
-#define RING_BUFSIZE_TX 0
-#endif
-
-#endif

+ 0 - 35
ComputeGraph/cg/nodes/cpp/StreamingNodes/Config/VideoConfig.h

@@ -1,35 +0,0 @@
-#ifndef _VIDEOCONFIG_H_
-#define _VIDEOCONFIG_H_ 
-
-// <<< Use Configuration Wizard in Context Menu >>>
-
-// <h>Video Configuration
-// <o>Width in pixels <16-640>
-#ifndef VIDEO_DRV_WIDTH
-#define VIDEO_DRV_WIDTH 32
-#endif
-
-// <o>Height in pixels <16-640>
-#ifndef VIDEO_DRV_HEIGHT
-#define VIDEO_DRV_HEIGHT 32
-#endif
-
-// <o>Pixel size in bytes <1=> 1 <2=> 2
-#ifndef VIDEO_DRV_PIXEL_SIZE
-#define VIDEO_DRV_PIXEL_SIZE 1
-#endif
-
-// <o>Frame rate <10=> 10 <25=> 25 <30=> 30 <60=> 60
-#ifndef VIDEO_DRV_FRAME_RATE
-#define VIDEO_DRV_FRAME_RATE 10
-#endif
-
-// </h>
-
-
-
-// <<< end of configuration section >>>
-
-#define CGSTATIC_VIDEO_CONFIG 
-
-#endif

+ 0 - 31
ComputeGraph/cg/nodes/cpp/StreamingNodes/README.md

@@ -1,31 +0,0 @@
-# Streaming Nodes
-
-This is an example implementation to be used with Arm Virtual Hardware (AVH).
-
-It is requiring headers and source files provided by AVH.
-
-Those files are not needed at all to use the Compute Graph.
-
-Those files are kept because they are used in the AVH-SystemModeling example.
-
-But there are simpler way to interface the compute graph to an audio interrupt.
-
-Those nodes are considered as deprecated. Don't use them.
-
-## RingBuffer
-
-It is a way to connect the compute graph with static flow to an audio source or sink.
-
-The node part is implemented in the AudioSource and AudioSink parts.
-
-
-The main implementation is in `RingBuffer`.
-
-
-To port it to new environments:
-
-- A file RingPrivate.h must be written. It is included by RingBuffer.cpp to customize some part of the implementation 
-- A file managing the audio interrupts must be written an interact with the Ring buffers
-- The file RingConfig.h must be provided to size the buffers
-- Most of the time the Ring buffer will have only 2 buffers and will be a ping-pong buffer.
-

+ 0 - 278
ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.cpp

@@ -1,278 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        RingBuffer.cpp
- * Description:  Implementation of the Ring buffer.
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* 
-
-RTOS dependent definitions must be in RingPrivate.h.
-Without a RingPrivate.h, this code cannot work.
-
- */
-#include "RingPrivate.h"
-#include "RingBuffer.h"
-
-/*
-
-RTOS Integration
-
-*/
-#ifndef RING_BEGINCRITICALSECTION
-#define RING_BEGINCRITICALSECTION() 
-#endif 
-
-#ifndef RING_ENDCRITICALSECTION
-#define RING_ENDCRITICALSECTION() 
-#endif
-
-#ifndef RING_WAIT_BUFFER
-#define RING_WAIT_BUFFER(ID) 0
-#endif
-
-#ifndef RING_RELEASE_BUFFER
-#define RING_RELEASE_BUFFER(THREADID) 
-#endif
-
-#ifndef RING_HASWAITERROR
-#define RING_HASWAITERROR(ERR) 0 
-#endif
-
-/*
-
-Debug integration
-
-*/
-
-#ifndef RING_DBG_USER_RESERVE_BUFFER
-#define RING_DBG_USER_RESERVE_BUFFER(ID,CONF)
-#endif 
-
-#ifndef RING_DBG_USER_RELEASE_BUFFER
-#define RING_DBG_USER_RELEASE_BUFFER(ID,CONF)
-#endif
-
-#ifndef RING_DBG_USER_WAIT_BUFFER
-#define RING_DBG_USER_WAIT_BUFFER(ID,CONF)
-#endif
-
-#ifndef RING_DBG_USER_BUFFER_RELEASED
-#define RING_DBG_USER_BUFFER_RELEASED(ID,CONF)
-#endif
-
-#ifndef RING_DBG_USER_STATUS
-#define RING_DBG_USER_STATUS(SA,SB,CONF)
-#endif
-
-#ifndef RING_DBG_INT_RESERVE_BUFFER
-#define RING_DBG_INT_RESERVE_BUFFER(ID,CONF)
-#endif
-
-#ifndef RING_DBG_INT_RELEASE_BUFFER
-#define RING_DBG_INT_RELEASE_BUFFER(ID,CONF)
-#endif
-
-#ifndef RING_DBG_INT_RELEASE_USER
-#define RING_DBG_INT_RELEASE_USER(CONF)
-#endif
-
-#ifndef RING_DBG_INT_STATUS
-#define RING_DBG_INT_STATUS(SA,SB,CONF) 
-#endif
-
-#ifndef RING_DBG_ERROR
-#define RING_DBG_ERROR(ERROR,CONF)
-#endif
-
-/*
-
-Implementation
-
-*/
-
-#define RING_SET(FIELD,BIT) (config->FIELD) |= (1 << (config->BIT))
-#define RING_CLEAR(FIELD,BIT) (config->FIELD) &= ~(1 << (config->BIT))
-#define RING_TEST(FIELD,BIT) (((config->FIELD) & (1 << (config->BIT))) != 0)
-
-#define RING_INC(ID)                  \
-  config->ID++;                       \
-  if (config->ID == config->nbBuffers)\
-  {                                   \
-     config->ID=0;                    \
-  }
-
-#define RING_BUSY(ID) \
-  (RING_TEST(userBufferStatus,ID) || RING_TEST(intBufferStatus,ID))
-
-
-void ringInit(ring_config_t *config,
-    uint32_t nbBuffers,
-    uint32_t bufferSize,
-    uint8_t *buffer,
-    int interruptID,
-    int timeout)
-{
-  
-  config->buffer=buffer;
-  config->nbBuffers = nbBuffers;
-  config->bufferSize = bufferSize;
-  config->interruptBufferIDStart = 0;
-  config->interruptBufferIDStop = 0;
-  config->userBufferIDStart = 0;
-  config->userBufferIDStop = 0;
-  config->error=kNoError;
-  config->waiting=0;
-  config->timeout=timeout;
-
-  config->interruptID = interruptID;
-  config->userBufferStatus = 0;
-  config->intBufferStatus = 0;
-  
-}
-
-void ringClean(ring_config_t *config)
-{
-}
-
-uint8_t *ringGetBufferAddress(ring_config_t *config,int id)
-{
-  if (id < 0)
-  {
-     return(NULL);
-  }
-  else
-  {
-      return(&config->buffer[id*config->bufferSize]);
-  }
-}
-
-int ringInterruptReserveBuffer(ring_config_t *config)
-{
-   RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
-   if (config->error)
-   {
-     return(-1);
-   }
-
-   /* Try to reserve a buffer */
-   if (RING_BUSY(interruptBufferIDStop))
-   {
-       /* If buffer is already used then kErrorOverflowUnderflow*/
-       config->error=kErrorOverflowUnderflow;
-       RING_DBG_ERROR(config->error,config);
-       return(-1);
-   }
-   else 
-   {
-        RING_DBG_INT_RESERVE_BUFFER(config->interruptBufferIDStop,config);
-        RING_SET(intBufferStatus,interruptBufferIDStop);
-        RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
-        int id=config->interruptBufferIDStop;
-        RING_INC(interruptBufferIDStop);
-        return(id);
-   }
-}
-
-void ringInterruptReleaseBuffer(ring_config_t *config,void *threadId)
-{
-     RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
-     if (config->error)
-     {
-        return;
-     }
-     if (config->interruptBufferIDStart != config->interruptBufferIDStop)
-     {
-         RING_DBG_INT_RELEASE_BUFFER(config->interruptBufferIDStart,config);
-         RING_CLEAR(intBufferStatus,interruptBufferIDStart);
-         /* Send release message in case the thread may be waiting */
-         if (config->interruptBufferIDStart == config->userBufferIDStop)
-         {
-            if (config->waiting)
-            {
-                RING_DBG_INT_RELEASE_USER(config);
-                RING_RELEASE_BUFFER(threadId);
-            }
-         }
-         RING_INC(interruptBufferIDStart);
-     }
-} 
-
-int ringUserReserveBuffer(ring_config_t *config)
-{
-   RING_BEGINCRITICALSECTION();
-   RING_DBG_USER_STATUS(userBufferStatus,intBufferStatus,config);
-   if (config->error)
-   {
-        RING_ENDCRITICALSECTION();
-        return(-1);
-   }
-   /* If buffer is busy we wait*/
-   if (RING_BUSY(userBufferIDStop))
-   {
-            config->waiting=1;
-            RING_DBG_USER_WAIT_BUFFER(config->userBufferIDStop,config);
-            RING_ENDCRITICALSECTION();
-
-            int err = RING_WAIT_BUFFER(config->timeout);
-
-            RING_BEGINCRITICALSECTION();
-            RING_DBG_USER_BUFFER_RELEASED(config->userBufferIDStop,config);
-            if (RING_HASWAITERROR(err))
-            {
-                RING_DBG_ERROR(err,config);
-                config->error=kTimeout; 
-                return(-1);
-            }
-    
-   }
-   
-   RING_DBG_USER_RESERVE_BUFFER(config->userBufferIDStop,config);
-   RING_SET(userBufferStatus,userBufferIDStop);
-   int id=config->userBufferIDStop;
-   RING_INC(userBufferIDStop);
-
-   RING_ENDCRITICALSECTION();
-   
-   return(id);
-}
-
-void ringUserReleaseBuffer(ring_config_t *config)
-{
-     RING_BEGINCRITICALSECTION();
-     RING_DBG_USER_STATUS(userBufferStatus,intBufferStatus,config);
-     if (config->error)
-     {
-        RING_ENDCRITICALSECTION();
-        return;
-     }
-     if (config->userBufferIDStart != config->userBufferIDStop)
-     {
-         RING_DBG_USER_RELEASE_BUFFER(config->userBufferIDStart,config);
-         RING_CLEAR(userBufferStatus,userBufferIDStart);
-         RING_INC(userBufferIDStart);
-     }
-     
-     RING_ENDCRITICALSECTION();
-}

+ 0 - 125
ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingBuffer.h

@@ -1,125 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        RingBuffer.h
- * Description:  Ring buffer to connect the compute graph with static flow to audio sources and sinks
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _RINGBUFFER_H_
-#define _RINGBUFFER_H_
-
-
-#ifdef   __cplusplus
-extern "C"
-{
-#endif
-
-typedef enum {
- kErrorOverflowUnderflow=-1,
- kTimeout=-2,
- kErrorHWOverlowUnderflow=-3,
- kNoError=0
-} ring_error_t;
-
-typedef struct {
-  uint8_t *buffer;
-  uint32_t userBufferStatus;
-  uint32_t intBufferStatus;
-
-  int32_t nbBuffers;
-  uint32_t bufferSize;
-
-  int32_t interruptBufferIDStart;
-  int32_t interruptBufferIDStop;
-  int32_t userBufferIDStart;
-  int32_t userBufferIDStop;
-  int32_t waiting;
-  int timeout;
-  ring_error_t error;
-  int interruptID;
-} ring_config_t;
-
-
-  /**
-   * @brief  Ring buffer initialization
-   * @param[in, out] buf         ring buffer configuration.
-   * @param[in]      nbBuffers   number of buffers (max 32)
-   * @param[in]      bufferSize  size of each buffer in bytes
-   * @param[in]      buffer      array for the buffer storage (bufferSize*nbBuffers)
-   * @param[in]      interruptID interrupt ID
-   * @param[in]      timeout     timeout (meaning is RTOS dependent)
-   * @return  Nothing
-   */
-  void ringInit(ring_config_t *buf,
-    uint32_t nbBuffers,
-    uint32_t bufferSize,
-    uint8_t *buffer,
-    int interruptID,
-    int timeout);
-
-
-
-void ringClean(ring_config_t *buf);
-
-/*
-
-Try to reserve a buffer from a user thread.
-
-*/
-int ringUserReserveBuffer(ring_config_t *buf);
-
-/*
-
-Release a buffer from user htread
-
-*/
-void ringUserReleaseBuffer(ring_config_t *buf);
-
-/*
-
-Reserve a buffer from interrupt
-
-*/
-int ringInterruptReserveBuffer(ring_config_t *buf);
-
-/*
-
-Release a buffer from interrupt 
-
-*/
-void ringInterruptReleaseBuffer(ring_config_t *buf,void *threadId);
-
-/*
-
-Get address of buffer
-
-*/
-
-uint8_t *ringGetBufferAddress(ring_config_t *buf,int id);
-
-
-#ifdef   __cplusplus
-}
-#endif
-
-#endif /* #ifndef _RINGBUFFER_H_*/

+ 0 - 57
ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.cpp

@@ -1,57 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        RingInit.cpp
- * Description:  Initialization of the ring data structure for an audio source
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "arm_math.h"
-#include "RingConfig.h"
-#include "RingInit.h"
-#include "RingBuffer.h"
-
-
-
-
-void initRing(ring_config_t *ringConfigRX,
-    uint8_t *rxBuffer,
-    uint32_t bufSizeRX,
-    int rxInterruptID,
-    ring_config_t *ringConfigTX, 
-    uint8_t *txBuffer,
-    uint32_t bufSizeTX,
-    int txInterruptID,
-    int timeOut)
-{
-  /* Initialization of the ring buffer data structure */
-  if (ringConfigRX != NULL)
-  {
-     ringInit(ringConfigRX,RING_NBBUFS,bufSizeRX,rxBuffer,rxInterruptID,timeOut);
-  }
-
-  if (ringConfigTX != NULL)
-  {
-     ringInit(ringConfigTX,RING_NBBUFS,bufSizeTX,txBuffer,txInterruptID,timeOut);
-  }
-
-}

+ 0 - 58
ComputeGraph/cg/nodes/cpp/StreamingNodes/RingBuffer/RingInit.h

@@ -1,58 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        RingInit.h
- * Description:  API to initialize the ring buffer
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _RINGINIT_H 
-#define _RINGINIT_H
-
-
-
-#include "RingBuffer.h"
-
-#ifdef   __cplusplus
-extern "C"
-{
-#endif
-
-extern ring_config_t ringConfigRX;
-extern ring_config_t ringConfigTX;
-
-void initRing(ring_config_t *ringConfigRX,
-    uint8_t *rxBuffer,
-    uint32_t bufSizeRX,
-    int rxInterruptID,
-    ring_config_t *ringConfigTX, 
-    uint8_t *txBuffer,
-    uint32_t bufSizeTX,
-    int txInterruptID,
-    int timeOut);
-
-#ifdef   __cplusplus
-}
-
-
-#endif
-#endif 

+ 0 - 202
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/AudioInterrupt.cpp

@@ -1,202 +0,0 @@
-#include <stddef.h>
-#include "audio_drv.h"
-#include "arm_vsi.h"
-#ifdef _RTE_
-#include "RTE_Components.h"
-#endif
-#include CMSIS_device_header
-
-#include "cmsis_os2.h"
-
-
-
-#include "RingBuffer.h"
-
-#include "arm_math.h"
-
-#include "SchedEvents.h"
-#include "AudioConfig.h"
-#include "RingConfig.h"
-
-#include "RingInit.h"
-
-extern osThreadId_t gStreamingThreadID;
-
-// Number of bytes read by DMA
-#define AUDIO_BLOCK_SIZE_RX    RING_BUFSIZE_RX
-#define AUDIO_BLOCK_SIZE_TX    RING_BUFSIZE_TX
-
-// Number of DMA blocks
-#define AUDIO_DMA_NB_BLOCKS RING_NBBUFS
-
-
-
-
-#if AUDIO_DRV_RX_ENABLED
-extern ring_config_t ringConfigRX;
-
-#ifdef __FVP_PY
-__attribute__((section(".ARM.__at_0x90000000")))
-#endif
-#if CGSTATIC_VHT_TX_RX_ORDERING
-__ALIGNED(16) static uint8_t dmaRX[AUDIO_BLOCK_SIZE_RX];
-int rxCount=0;
-#endif
-__ALIGNED(16) static uint8_t audio_bufferRX[AUDIO_DMA_NB_BLOCKS*AUDIO_BLOCK_SIZE_RX];
-static uint8_t *reservedBufRX=NULL;
-#endif
-
-#if AUDIO_DRV_TX_ENABLED
-extern ring_config_t ringConfigTX;
-
-#ifdef __FVP_PY
-__attribute__((section(".ARM.__at_0x9FFF0000")))
-#endif
-#if CGSTATIC_VHT_TX_RX_ORDERING
-__ALIGNED(16) static uint8_t dmaTX[AUDIO_BLOCK_SIZE_TX];
-int txCount=0;
-#endif
-__ALIGNED(16) static uint8_t audio_bufferTX[AUDIO_DMA_NB_BLOCKS*AUDIO_BLOCK_SIZE_TX];
-static uint8_t *reservedBufTX=NULL;
-#endif
-
-uint8_t* AudioRXBuffer()
-{
-#if AUDIO_DRV_RX_ENABLED
-  return(audio_bufferRX);
-#else
-    return(NULL);
-#endif
-}
-
-uint8_t* AudioTXBuffer()
-{
-#if AUDIO_DRV_TX_ENABLED
-    return(audio_bufferTX);
-#else
-    return(NULL);
-#endif
-}
-
-static void AudioEvent (uint32_t event) {
-
-#if AUDIO_DRV_RX_ENABLED
-  if (event & AUDIO_DRV_EVENT_RX_DATA) 
-  {
-    
-    #if CGSTATIC_VHT_TX_RX_ORDERING
-      memcpy(reservedBufRX,dmaRX,RING_BUFSIZE_RX);
-      (void)AudioDrv_Control(AUDIO_DRV_CONTROL_RX_DISABLE);
-      (void)AudioDrv_Control(AUDIO_DRV_CONTROL_TX_ENABLE);
-    #endif
-    ringInterruptReleaseBuffer(&ringConfigRX,(void *)gStreamingThreadID);
-    int reservedRX=ringInterruptReserveBuffer(&ringConfigRX);
-    reservedBufRX=ringGetBufferAddress(&ringConfigRX,reservedRX);
-
-  }
-#endif
-
-#if AUDIO_DRV_TX_ENABLED
-  if (event & AUDIO_DRV_EVENT_TX_DATA)
-  {
-    #if CGSTATIC_VHT_TX_RX_ORDERING
-          memcpy(dmaTX,reservedBufTX,RING_BUFSIZE_TX);
-          (void)AudioDrv_Control(AUDIO_DRV_CONTROL_TX_DISABLE);
-          (void)AudioDrv_Control(AUDIO_DRV_CONTROL_RX_ENABLE);
-    #endif
-    ringInterruptReleaseBuffer(&ringConfigTX,(void *)gStreamingThreadID);
-    int reservedTX=ringInterruptReserveBuffer(&ringConfigTX);
-    reservedBufTX=ringGetBufferAddress(&ringConfigTX,reservedTX);
-  }
-#endif
-}
-
-int32_t AudioDrv_Setup(void) {
-  int32_t ret;
-
-  ret = AudioDrv_Initialize(AudioEvent);
-  if (ret != 0) {
-    return ret;
-  }
-
-#if AUDIO_DRV_RX_ENABLED
-
-  ret = AudioDrv_Configure(AUDIO_DRV_INTERFACE_RX,
-                           AUDIO_DRV_NBCHANNELS_RX,  /* single channel */
-                           8U * AUDIO_DRV_CHANNEL_ENCODING_RX, /* 16 sample bits */
-                           static_cast<uint32_t>(AUDIO_DRV_SAMPLINGFREQUENCY_RX));
-  if (ret != 0) {
-    return ret;
-  }
-
-  /* Work because user process not started yet
-  */
-
-  int reservedRX=ringInterruptReserveBuffer(&ringConfigRX);
-  reservedBufRX=ringGetBufferAddress(&ringConfigRX,reservedRX);
-
-#if CGSTATIC_VHT_TX_RX_ORDERING
-  ret = AudioDrv_SetBuf(AUDIO_DRV_INTERFACE_RX,
-                        dmaRX, 1,AUDIO_BLOCK_SIZE_RX);
-#else
-  ret = AudioDrv_SetBuf(AUDIO_DRV_INTERFACE_RX,
-                        audio_bufferRX, AUDIO_DMA_NB_BLOCKS,AUDIO_BLOCK_SIZE_RX);
-#endif
-  if (ret != 0) {
-    return ret;
-  }
-
-#if !CGSTATIC_VHT_TX_RX_ORDERING
-  ret = AudioDrv_Control(AUDIO_DRV_CONTROL_RX_ENABLE);
-  if (ret != 0) {
-    return ret;
-  }
-#endif 
-
-#endif /* AUDIO_DRV_RX_ENABLED */
-
-#if AUDIO_DRV_TX_ENABLED
-  ret = AudioDrv_Configure(AUDIO_DRV_INTERFACE_TX,
-                           AUDIO_DRV_NBCHANNELS_TX,  /* single channel */
-                           8U * AUDIO_DRV_CHANNEL_ENCODING_TX, /* 16 sample bits */
-                           static_cast<uint32_t>(AUDIO_DRV_SAMPLINGFREQUENCY_TX));
-  if (ret != 0) {
-    return ret;
-  }
-
-  /* Work because user process not started yet
-  */
-
-  /* dataflow must be 1 packet ahead of the TX interrupt*/
-  ringUserReserveBuffer(&ringConfigTX);
-  ringUserReleaseBuffer(&ringConfigTX);
-
-  ringUserReserveBuffer(&ringConfigTX);
-  ringUserReleaseBuffer(&ringConfigTX);
-
-  int reservedTX=ringInterruptReserveBuffer(&ringConfigTX);
-  reservedBufTX=ringGetBufferAddress(&ringConfigTX,reservedTX);
-
-#if CGSTATIC_VHT_TX_RX_ORDERING
-  ret = AudioDrv_SetBuf(AUDIO_DRV_INTERFACE_TX,
-                        dmaTX, 1 ,AUDIO_BLOCK_SIZE_TX);
-#else
-  ret = AudioDrv_SetBuf(AUDIO_DRV_INTERFACE_TX,
-                        audio_bufferTX, AUDIO_DMA_NB_BLOCKS,AUDIO_BLOCK_SIZE_TX);
-#endif
-
-  if (ret != 0) {
-    return ret;
-  }
-
-  ret = AudioDrv_Control(AUDIO_DRV_CONTROL_TX_ENABLE);
-  if (ret != 0) {
-    return ret;
-  }
-
-#endif /* AUDIO_DRV_TX_ENABLED */
-
-
-  return 0;
-}
-

+ 0 - 292
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.c

@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- */
-
-#include <stddef.h>
-#include "audio_drv.h"
-#include "arm_vsi.h"
-#ifdef _RTE_
-#include "RTE_Components.h"
-#endif
-#include CMSIS_device_header
-
-/* Audio Peripheral definitions */
-#define AudioO          ARM_VSI1                /* Audio Output access struct */
-#define AudioO_IRQn     ARM_VSI1_IRQn           /* Audio Output Interrupt number */
-#define AudioO_Handler  ARM_VSI1_Handler        /* Audio Output Interrupt handler */
-#define AudioI          ARM_VSI0                /* Audio Input access struct */
-#define AudioI_IRQn     ARM_VSI0_IRQn           /* Audio Input Interrupt number */
-#define AudioI_Handler  ARM_VSI0_Handler        /* Audio Input Interrupt handler */
-
-/* Audio Peripheral registers */
-#define CONTROL         Regs[0] /* Control receiver */
-#define CHANNELS        Regs[1] /* Number of channels */
-#define SAMPLE_BITS     Regs[2] /* Sample number of bits (8..32) */
-#define SAMPLE_RATE     Regs[3] /* Sample rate (samples per second) */
-#define STOP_SIMULATION Regs[4] /* Stop audio simulation */
-
-/* Audio Control register definitions */
-#define CONTROL_ENABLE_Pos      0U                              /* CONTROL: ENABLE Position */
-#define CONTROL_ENABLE_Msk      (1UL << CONTROL_ENABLE_Pos)     /* CONTROL: ENABLE Mask */
-
-/* Driver State */
-static uint8_t Initialized = 0U;
-
-/* Event Callback */
-static AudioDrv_Event_t CB_Event = NULL;
-
-/* Audio Output Interrupt Handler */
-void AudioO_Handler (void) {
-
-  AudioO->IRQ.Clear = 0x00000001U;
-  __DSB();
-  __ISB();
-  if (CB_Event != NULL) {
-    CB_Event(AUDIO_DRV_EVENT_TX_DATA);
-  }
-}
-
-/* Audio Input Interrupt Handler */
-void AudioI_Handler (void) {
-
-  AudioI->IRQ.Clear = 0x00000001U;
-  __DSB();
-  __ISB();
-  if (CB_Event != NULL) {
-    CB_Event(AUDIO_DRV_EVENT_RX_DATA);
-  }
-}
-
-
-
-/* Initialize Audio Interface */
-int32_t AudioDrv_Initialize (AudioDrv_Event_t cb_event) {
-
-  CB_Event = cb_event;
-
-  /* Initialize Audio Output peripheral */
-  AudioO->Timer.Control = 0U;
-  AudioO->DMA.Control   = 0U;
-  AudioO->IRQ.Clear     = 0x00000001U;
-  AudioO->IRQ.Enable    = 0x00000001U;
-  AudioO->CONTROL       = 0U;
-
-  /* Initialize Audio Input peripheral */
-  AudioI->Timer.Control = 0U;
-  AudioI->DMA.Control   = 0U;
-  AudioI->IRQ.Clear     = 0x00000001U;
-  AudioI->IRQ.Enable    = 0x00000001U;
-  AudioI->CONTROL       = 0U;
-
-  /* Enable peripheral interrupts */
-//NVIC_EnableIRQ(AudioO_IRQn);
-  NVIC->ISER[(((uint32_t)AudioO_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)AudioO_IRQn) & 0x1FUL));
-//NVIC_EnableIRQ(AudioI_IRQn);
-  NVIC->ISER[(((uint32_t)AudioI_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)AudioI_IRQn) & 0x1FUL));
-  __DSB();
-  __ISB();
-
-  Initialized = 1U;
-
-  return AUDIO_DRV_OK;
-}
-
-/* De-initialize Audio Interface */
-int32_t AudioDrv_Uninitialize (void) {
-
-  /* Disable peripheral interrupts */
-//NVIC_DisableIRQ(AudioO_IRQn);
-  NVIC->ICER[(((uint32_t)AudioO_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)AudioO_IRQn) & 0x1FUL));
-//NVIC_DisableIRQ(AudioI_IRQn);
-  NVIC->ICER[(((uint32_t)AudioI_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)AudioI_IRQn) & 0x1FUL));
-  __DSB();
-  __ISB();
-
-  /* De-initialize Audio Output peripheral */
-  AudioO->Timer.Control = 0U;
-  AudioO->DMA.Control   = 0U;
-  AudioO->IRQ.Clear     = 0x00000001U;
-  AudioO->IRQ.Enable    = 0x00000000U;
-  AudioO->CONTROL       = 0U;
-
-  /* De-initialize Audio Input peripheral */
-  AudioI->Timer.Control = 0U;
-  AudioI->DMA.Control   = 0U;
-  AudioI->IRQ.Clear     = 0x00000001U;
-  AudioI->IRQ.Enable    = 0x00000000U;
-  AudioI->CONTROL       = 0U;
-
-  Initialized = 0U;
-
-  return AUDIO_DRV_OK;
-}
-
-/* Configure Audio Interface */
-int32_t AudioDrv_Configure (uint32_t interface, uint32_t channels, uint32_t sample_bits, uint32_t sample_rate) {
-  uint32_t format;
-
-  if (Initialized == 0U) {
-    return AUDIO_DRV_ERROR;
-  }
-
-  if ((channels <  1U) ||
-      (channels > 32U) ||
-      (sample_bits <  8U) ||
-      (sample_bits > 32U) ||
-      (sample_rate == 0U)) {
-    return AUDIO_DRV_ERROR_PARAMETER;
-  }
-
-  switch (interface) {
-    case AUDIO_DRV_INTERFACE_TX:
-      if ((AudioO->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-        return AUDIO_DRV_ERROR;
-      }
-      AudioO->CHANNELS    = channels;
-      AudioO->SAMPLE_BITS = sample_bits;
-      AudioO->SAMPLE_RATE = sample_rate;
-      break;
-    case AUDIO_DRV_INTERFACE_RX:
-      if ((AudioI->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-        return AUDIO_DRV_ERROR;
-      }
-      AudioI->CHANNELS    = channels;
-      AudioI->SAMPLE_BITS = sample_bits;
-      AudioI->SAMPLE_RATE = sample_rate;
-      break;
-    default:
-      return AUDIO_DRV_ERROR_PARAMETER;
-  }
-
-  return AUDIO_DRV_OK;
-}
-
-/* Set Audio Interface buffer */
-int32_t AudioDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size) {
-
-  if (Initialized == 0U) {
-    return AUDIO_DRV_ERROR;
-  }
-
-  switch (interface) {
-    case AUDIO_DRV_INTERFACE_TX:
-      if ((AudioO->DMA.Control & ARM_VSI_DMA_Enable_Msk) != 0U) {
-        return AUDIO_DRV_ERROR;
-      }
-      AudioO->DMA.Address   = (uint32_t)buf;
-      AudioO->DMA.BlockNum  = block_num;
-      AudioO->DMA.BlockSize = block_size;
-      break;
-    case AUDIO_DRV_INTERFACE_RX:
-      if ((AudioI->DMA.Control & ARM_VSI_DMA_Enable_Msk) != 0U) {
-        return AUDIO_DRV_ERROR;
-      }
-      AudioI->DMA.Address   = (uint32_t)buf;
-      AudioI->DMA.BlockNum  = block_num;
-      AudioI->DMA.BlockSize = block_size;
-      break;
-    default:
-      return AUDIO_DRV_ERROR_PARAMETER;
-  }
-
-  return AUDIO_DRV_OK;
-}
-
-/* Control Audio Interface */
-int32_t AudioDrv_Control (uint32_t control) {
-  uint32_t sample_size;
-  uint32_t sample_rate;
-  uint32_t block_size;
-
-  if (Initialized == 0U) {
-    return AUDIO_DRV_ERROR;
-  }
-
-  if ((control & AUDIO_DRV_CONTROL_TX_DISABLE) != 0U) {
-    AudioO->Timer.Control = 0U;
-    AudioO->DMA.Control   = 0U;
-    AudioO->CONTROL       = 0U;
-  } else if ((control & AUDIO_DRV_CONTROL_TX_ENABLE) != 0U) {
-    AudioO->CONTROL       = CONTROL_ENABLE_Msk;
-    AudioO->DMA.Control   = ARM_VSI_DMA_Direction_M2P |
-                            ARM_VSI_DMA_Enable_Msk;
-    sample_size = AudioO->CHANNELS * ((AudioO->SAMPLE_BITS + 7U) / 8U);
-    sample_rate = AudioO->SAMPLE_RATE;
-    if ((sample_size == 0U) || (sample_rate == 0U)) {
-      AudioO->Timer.Interval = 0xFFFFFFFFU;
-    } else {
-      block_size = AudioO->DMA.BlockSize;
-      AudioO->Timer.Interval = (1000000U * (block_size / sample_size)) / sample_rate;
-    }
-    AudioO->Timer.Control = ARM_VSI_Timer_Trig_DMA_Msk |
-                            ARM_VSI_Timer_Trig_IRQ_Msk |
-                            ARM_VSI_Timer_Periodic_Msk |
-                            ARM_VSI_Timer_Run_Msk;
-  }
-
-  if ((control & AUDIO_DRV_CONTROL_RX_DISABLE) != 0U) {
-    AudioI->Timer.Control = 0U;
-    AudioI->DMA.Control   = 0U;
-    AudioI->CONTROL       = 0U;
-  } else if ((control & AUDIO_DRV_CONTROL_RX_ENABLE) != 0U) {
-    AudioI->CONTROL       = CONTROL_ENABLE_Msk;
-    AudioI->DMA.Control   = ARM_VSI_DMA_Direction_P2M |
-                            ARM_VSI_DMA_Enable_Msk;
-    sample_size = AudioI->CHANNELS * ((AudioI->SAMPLE_BITS + 7U) / 8U);
-    sample_rate = AudioI->SAMPLE_RATE;
-    if ((sample_size == 0U) || (sample_rate == 0U)) {
-      AudioI->Timer.Interval = 0xFFFFFFFFU;
-    } else {
-      block_size = AudioI->DMA.BlockSize;
-      AudioI->Timer.Interval = (1000000U * (block_size / sample_size)) / sample_rate;
-    }
-    AudioI->Timer.Control = ARM_VSI_Timer_Trig_DMA_Msk |
-                            ARM_VSI_Timer_Trig_IRQ_Msk |
-                            ARM_VSI_Timer_Periodic_Msk |
-                            ARM_VSI_Timer_Run_Msk;
-  }
-
-  return AUDIO_DRV_OK;
-}
-
-/* Get transmitted block count */
-uint32_t AudioDrv_GetTxCount (void) {
-  return (AudioO->Timer.Count);
-}
-
-/* Get received block count */
-uint32_t AudioDrv_GetRxCount (void) {
-  return (AudioI->Timer.Count);
-}
-
-/* Get Audio Interface status */
-AudioDrv_Status_t AudioDrv_GetStatus (void) {
-  AudioDrv_Status_t status;
-  uint32_t sr;
-
-  if ((AudioO->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-    status.tx_active = 1U;
-  } else {
-    status.tx_active = 0U;
-  }
-
-  if ((AudioI->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-    status.rx_active = 1U;
-  } else {
-    status.rx_active = 0U;
-  }
-
-  return (status);
-}
-
-
-void AudioDrv_Stop (void)
-{
-  int32_t ret;
-  ret = AudioDrv_Control(AUDIO_DRV_CONTROL_TX_DISABLE);
-  ret = AudioDrv_Control(AUDIO_DRV_CONTROL_RX_DISABLE);
-  
-  AudioO->STOP_SIMULATION=1;
-  AudioI->STOP_SIMULATION=1;
-  
-}

+ 0 - 135
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/audio/audio_drv.h

@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- */
-
-#ifndef __AUDIO_DRV_H
-#define __AUDIO_DRV_H
-
-#ifdef  __cplusplus
-extern "C"
-{
-#endif
-
-#include <stdint.h>
-
-/* Audio Interface */
-#define AUDIO_DRV_INTERFACE_TX              (1U)  ///< Transmitter
-#define AUDIO_DRV_INTERFACE_RX              (2U)  ///< Receiver
-
-/* Audio Control */
-#define AUDIO_DRV_CONTROL_TX_ENABLE         (1UL << 0)  ///< Enable Transmitter
-#define AUDIO_DRV_CONTROL_RX_ENABLE         (1UL << 1)  ///< Enable Receiver
-#define AUDIO_DRV_CONTROL_TX_DISABLE        (1UL << 2)  ///< Disable Transmitter
-#define AUDIO_DRV_CONTROL_RX_DISABLE        (1UL << 3)  ///< Disable Receiver
-
-/* Audio Event */
-#define AUDIO_DRV_EVENT_TX_DATA             (1UL << 0)  ///< Data block transmitted
-#define AUDIO_DRV_EVENT_RX_DATA             (1UL << 1)  ///< Data block received
-
-/* Return code */
-#define AUDIO_DRV_OK                        (0)  ///< Operation succeeded
-#define AUDIO_DRV_ERROR                     (-1) ///< Unspecified error
-#define AUDIO_DRV_ERROR_BUSY                (-2) ///< Driver is busy
-#define AUDIO_DRV_ERROR_TIMEOUT             (-3) ///< Timeout occurred
-#define AUDIO_DRV_ERROR_UNSUPPORTED         (-4) ///< Operation not supported
-#define AUDIO_DRV_ERROR_PARAMETER           (-5) ///< Parameter error
-
-/**
-\brief Audio Status
-*/
-typedef struct {
-  uint32_t tx_active        :  1;       ///< Transmitter active
-  uint32_t rx_active        :  1;       ///< Receiver active
-  uint32_t reserved         : 30;
-} AudioDrv_Status_t;
-
-/**
-  \fn          AudioDrv_Event_t
-  \brief       Audio Events callback function type: void (*AudioDrv_Event_t) (uint32_t event
-  \param[in]   event events notification mask
-  \return      none
-*/
-typedef void (*AudioDrv_Event_t) (uint32_t event);
-
-uint8_t* AudioRXBuffer();
-uint8_t* AudioTXBuffer();
-extern int32_t AudioDrv_Setup(void);
-
-/**
-  \fn          int32_t AudioDrv_Initialize (AudioDrv_Event_t cb_event)
-  \brief       Initialize Audio Interface.
-  \param[in]   cb_event pointer to \ref AudioDrv_Event_t
-  \return      return code
-*/
-int32_t AudioDrv_Initialize (AudioDrv_Event_t cb_event);
-
-/**
-  \fn          void AudioDrv_Stop (void);
-  \brief       Stop audio simulation.
-  \return      return code
-*/
-void AudioDrv_Stop (void);
-
-/**
-  \fn          int32_t AudioDrv_Uninitialize (void)
-  \brief       De-initialize Audio Interface.
-  \return      return code
-*/
-int32_t AudioDrv_Uninitialize (void);
-
-/**
-  \fn          int32_t AudioDrv_Configure (uint32_t interface, uint32_t channels, uint32_t sample_bits, uint32_t sample_rate)
-  \brief       Configure Audio Interface.
-  \param[in]   interface   audio interface
-  \param[in]   channels    number of channels
-  \param[in]   sample_bits sample number of bits (8..32)
-  \param[in]   sample_rate sample rate (samples per second)
-  \return      return code
-*/
-int32_t AudioDrv_Configure (uint32_t interface, uint32_t channels, uint32_t sample_bits, uint32_t sample_rate);
-
-/**
-  \fn          int32_t AudioDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size)
-  \brief       Set Audio Interface buffer.
-  \param[in]   interface   audio interface
-  \param[in]   buf         pointer to buffer for audio data
-  \param[in]   block_num   number of blocks in buffer (must be 2^n)
-  \param[in]   block_size  block size in number of samples
-  \return      return code
-*/
-int32_t AudioDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size);
-
-/**
-  \fn          int32_t AudioDrv_Control (uint32_t control)
-  \brief       Control Audio Interface.
-  \param[in]   control operation
-  \return      return code
-*/
-int32_t AudioDrv_Control (uint32_t control);
-
-/**
-  \fn          uint32_t AudioDrv_GetTxCount (void)
-  \brief       Get transmitted block count.
-  \return      number of transmitted blocks
-*/
-uint32_t AudioDrv_GetTxCount (void);
-
-/**
-  \fn          uint32_t AudioDrv_GetRxCount (void)
-  \brief       Get received block count.
-  \return      number of received blocks
-*/
-uint32_t AudioDrv_GetRxCount (void);
-
-/**
-  \fn          AudioDrv_Status_t AudioDrv_GetStatus (void)
-  \brief       Get Audio Interface status.
-  \return      \ref AudioDrv_Status_t
-*/
-AudioDrv_Status_t AudioDrv_GetStatus (void);
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif /* __AUDIO_DRV_H */

+ 0 - 101
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/VideoInterrupt.cpp

@@ -1,101 +0,0 @@
-#include <stddef.h>
-#include "video_drv.h"
-#include "arm_vsi.h"
-#ifdef _RTE_
-#include "RTE_Components.h"
-#endif
-#include CMSIS_device_header
-
-#include "cmsis_os2.h"
-
-
-
-#include "RingBuffer.h"
-
-#include "arm_math.h"
-
-#include "SchedEvents.h"
-#include "VideoConfig.h"
-#include "RingConfig.h"
-
-#include "RingInit.h"
-
-extern osThreadId_t gStreamingThreadID;
-
-// Number of bytes read by DMA
-#define VIDEO_BLOCK_SIZE    RING_BUFSIZE_RX
-
-// Number of DMA blocks
-#define VIDEO_DMA_NB_BLOCKS RING_NBBUFS
-
-
-extern int32_t VideoDrv_Setup(void);
-
-
-extern ring_config_t ringConfigRX;
-
-#ifdef __FVP_PY
-__attribute__((section(".ARM.__at_0x90000000")))
-#endif
-__ALIGNED(16) static uint8_t video_bufferRX[VIDEO_DMA_NB_BLOCKS*VIDEO_BLOCK_SIZE];
-static uint8_t *reservedBufRX=NULL;
-
-
-uint8_t* VideoRXBuffer()
-{
-  return(video_bufferRX);
-}
-
-
-static void VideoEvent (uint32_t event) {
-
-  if (event & VIDEO_DRV_EVENT_RX_DATA) 
-  {
-    
-    
-    ringInterruptReleaseBuffer(&ringConfigRX,(void *)gStreamingThreadID);
-    int reservedRX=ringInterruptReserveBuffer(&ringConfigRX);
-    reservedBufRX=ringGetBufferAddress(&ringConfigRX,reservedRX);
-
-  }
-
-}
-
-int32_t VideoDrv_Setup(void) {
-  int32_t ret;
-
-  ret = VideoDrv_Initialize(VideoEvent);
-  if (ret != 0) {
-    return ret;
-  }
-
-
-  ret = VideoDrv_Configure(VIDEO_DRV_INTERFACE_RX,
-                           8U * VIDEO_DRV_PIXEL_SIZE, /* 16 sample bits */
-                           static_cast<uint32_t>(VIDEO_DRV_FRAME_RATE*VIDEO_DRV_WIDTH*VIDEO_DRV_HEIGHT));
-  if (ret != 0) {
-    return ret;
-  }
-
-  /* Work because user process not started yet
-  */
-
-  int reservedRX=ringInterruptReserveBuffer(&ringConfigRX);
-  reservedBufRX=ringGetBufferAddress(&ringConfigRX,reservedRX);
-
-
-  ret = VideoDrv_SetBuf(VIDEO_DRV_INTERFACE_RX,
-                        video_bufferRX, VIDEO_DMA_NB_BLOCKS,VIDEO_BLOCK_SIZE);
-  if (ret != 0) {
-    return ret;
-  }
-
-  ret = VideoDrv_Control(VIDEO_DRV_CONTROL_RX_ENABLE);
-  if (ret != 0) {
-    return ret;
-  }
-
-
-  return 0;
-}
-

+ 0 - 232
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.c

@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- */
-
-#include <stddef.h>
-#include "video_drv.h"
-#include "arm_vsi.h"
-#ifdef _RTE_
-#include "RTE_Components.h"
-#endif
-#include CMSIS_device_header
-
-/* Video Peripheral definitions */
-#define VideoO          ARM_VSI1                /* Video Output access struct */
-#define VideoO_IRQn     ARM_VSI1_IRQn           /* Video Output Interrupt number */
-#define VideoO_Handler  ARM_VSI1_Handler        /* Video Output Interrupt handler */
-#define VideoI          ARM_VSI0                /* Video Input access struct */
-#define VideoI_IRQn     ARM_VSI0_IRQn           /* Video Input Interrupt number */
-#define VideoI_Handler  ARM_VSI0_Handler        /* Video Input Interrupt handler */
-
-/* Video Peripheral registers */
-#define CONTROL         Regs[0] /* Control receiver */
-#define SAMPLE_BITS     Regs[1] /* Sample number of bits (8..32) */
-#define SAMPLE_RATE     Regs[2] /* Sample rate (frame per second) */
-#define STOP_SIMULATION Regs[4] /* Stop audio simulation */
-
-/* Video Control register definitions */
-#define CONTROL_ENABLE_Pos      0U                              /* CONTROL: ENABLE Position */
-#define CONTROL_ENABLE_Msk      (1UL << CONTROL_ENABLE_Pos)     /* CONTROL: ENABLE Mask */
-
-/* Driver State */
-static uint8_t Initialized = 0U;
-
-/* Event Callback */
-static VideoDrv_Event_t CB_Event = NULL;
-
-
-/* Video Input Interrupt Handler */
-void VideoI_Handler (void) {
-
-  VideoI->IRQ.Clear = 0x00000001U;
-  __DSB();
-  __ISB();
-  if (CB_Event != NULL) {
-    CB_Event(VIDEO_DRV_EVENT_RX_DATA);
-  }
-}
-
-
-void VideoO_Handler (void) {
-
-  VideoO->IRQ.Clear = 0x00000001U;
-  __DSB();
-  __ISB();
-}
-
-
-/* Initialize Video Interface */
-int32_t VideoDrv_Initialize (VideoDrv_Event_t cb_event) {
-
-  CB_Event = cb_event;
-
-  /* Initialize Video Output peripheral */
-  VideoO->Timer.Control = 0U;
-  VideoO->DMA.Control   = 0U;
-  VideoO->IRQ.Clear     = 0x00000001U;
-  VideoO->IRQ.Enable    = 0x00000001U;
-  VideoO->CONTROL       = 0U;
-
-  /* Initialize Video Input peripheral */
-  VideoI->Timer.Control = 0U;
-  VideoI->DMA.Control   = 0U;
-  VideoI->IRQ.Clear     = 0x00000001U;
-  VideoI->IRQ.Enable    = 0x00000001U;
-  VideoI->CONTROL       = 0U;
-
-  /* Enable peripheral interrupts */
-  NVIC->ISER[(((uint32_t)VideoI_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)VideoI_IRQn) & 0x1FUL));
-  __DSB();
-  __ISB();
-
-  Initialized = 1U;
-
-  return VIDEO_DRV_OK;
-}
-
-/* De-initialize Video Interface */
-int32_t VideoDrv_Uninitialize (void) {
-
-  /* Disable peripheral interrupts */
-  NVIC->ICER[(((uint32_t)VideoI_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)VideoI_IRQn) & 0x1FUL));
-  __DSB();
-  __ISB();
-
-  /* De-initialize Video Output peripheral */
-  VideoO->Timer.Control = 0U;
-  VideoO->DMA.Control   = 0U;
-  VideoO->IRQ.Clear     = 0x00000001U;
-  VideoO->IRQ.Enable    = 0x00000000U;
-  VideoO->CONTROL       = 0U;
-
-  /* De-initialize Video Input peripheral */
-  VideoI->Timer.Control = 0U;
-  VideoI->DMA.Control   = 0U;
-  VideoI->IRQ.Clear     = 0x00000001U;
-  VideoI->IRQ.Enable    = 0x00000000U;
-  VideoI->CONTROL       = 0U;
-
-  Initialized = 0U;
-
-  return VIDEO_DRV_OK;
-}
-
-/* Configure Video Interface */
-int32_t VideoDrv_Configure (uint32_t interface,  uint32_t pixel_size, uint32_t samplerate) {
-  uint32_t format;
-
-  if (Initialized == 0U) {
-    return VIDEO_DRV_ERROR;
-  }
-
-  if ((pixel_size <  8*1U) ||
-      (pixel_size > 8*2U)) {
-    return VIDEO_DRV_ERROR_PARAMETER;
-  }
-
-  switch (interface) {
-    case VIDEO_DRV_INTERFACE_RX:
-      if ((VideoI->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-        return VIDEO_DRV_ERROR;
-      }
-      VideoI->SAMPLE_BITS = pixel_size;
-      VideoI->SAMPLE_RATE = samplerate;
-      break;
-    default:
-      return VIDEO_DRV_ERROR_PARAMETER;
-  }
-
-  return VIDEO_DRV_OK;
-}
-
-/* Set Video Interface buffer */
-int32_t VideoDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size) {
-
-  if (Initialized == 0U) {
-    return VIDEO_DRV_ERROR;
-  }
-
-  switch (interface) {
-    case VIDEO_DRV_INTERFACE_RX:
-      if ((VideoI->DMA.Control & ARM_VSI_DMA_Enable_Msk) != 0U) {
-        return VIDEO_DRV_ERROR;
-      }
-      VideoI->DMA.Address   = (uint32_t)buf;
-      VideoI->DMA.BlockNum  = block_num;
-      VideoI->DMA.BlockSize = block_size;
-      break;
-    default:
-      return VIDEO_DRV_ERROR_PARAMETER;
-  }
-
-  return VIDEO_DRV_OK;
-}
-
-/* Control Video Interface */
-int32_t VideoDrv_Control (uint32_t control) {
-  uint32_t sample_size;
-  uint32_t sample_rate;
-  uint32_t block_size;
-
-  if (Initialized == 0U) {
-    return VIDEO_DRV_ERROR;
-  }
-
-  
-
-  if ((control & VIDEO_DRV_CONTROL_RX_DISABLE) != 0U) {
-    VideoI->Timer.Control = 0U;
-    VideoI->DMA.Control   = 0U;
-    VideoI->CONTROL       = 0U;
-  } else if ((control & VIDEO_DRV_CONTROL_RX_ENABLE) != 0U) {
-    VideoI->CONTROL       = CONTROL_ENABLE_Msk;
-    VideoI->DMA.Control   = ARM_VSI_DMA_Direction_P2M |
-                            ARM_VSI_DMA_Enable_Msk;
-    sample_size = ((VideoI->SAMPLE_BITS + 7U) / 8U);
-    sample_rate = VideoI->SAMPLE_RATE;
-    if ((sample_size == 0U) || (sample_rate == 0U)) {
-      VideoI->Timer.Interval = 0xFFFFFFFFU;
-    } else {
-      block_size = VideoI->DMA.BlockSize;
-      VideoI->Timer.Interval = (1000000U * (block_size / sample_size)) / sample_rate;
-    }
-    VideoI->Timer.Control = ARM_VSI_Timer_Trig_DMA_Msk |
-                            ARM_VSI_Timer_Trig_IRQ_Msk |
-                            ARM_VSI_Timer_Periodic_Msk |
-                            ARM_VSI_Timer_Run_Msk;
-  }
-
-  return VIDEO_DRV_OK;
-}
-
-/* Get received block count */
-uint32_t VideoDrv_GetRxCount (void) {
-  return (VideoI->Timer.Count);
-}
-
-/* Get Video Interface status */
-VideoDrv_Status_t VideoDrv_GetStatus (void) {
-  VideoDrv_Status_t status;
-  uint32_t sr;
-
-
-  if ((VideoI->CONTROL & CONTROL_ENABLE_Msk) != 0U) {
-    status.rx_active = 1U;
-  } else {
-    status.rx_active = 0U;
-  }
-
-  return (status);
-}
-
-
-void VideoDrv_Stop (void)
-{
-  int32_t ret;
-  ret = VideoDrv_Control(VIDEO_DRV_CONTROL_RX_DISABLE);
-  
-  VideoI->STOP_SIMULATION=1;
-  
-}
-
-

+ 0 - 124
ComputeGraph/cg/nodes/cpp/StreamingNodes/VHT/video/video_drv.h

@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- */
-
-#ifndef __VIDEO_DRV_H
-#define __VIDEO_DRV_H
-
-#ifdef  __cplusplus
-extern "C"
-{
-#endif
-
-#include <stdint.h>
-
-/* Video Interface */
-#define VIDEO_DRV_INTERFACE_RX              (2U)  ///< Receiver
-
-/* Video Control */
-#define VIDEO_DRV_CONTROL_RX_ENABLE         (1UL << 1)  ///< Enable Receiver
-#define VIDEO_DRV_CONTROL_RX_DISABLE        (1UL << 3)  ///< Disable Receiver
-
-/* Video Event */
-#define VIDEO_DRV_EVENT_RX_DATA             (1UL << 1)  ///< Data block received
-
-/* Return code */
-#define VIDEO_DRV_OK                        (0)  ///< Operation succeeded
-#define VIDEO_DRV_ERROR                     (-1) ///< Unspecified error
-#define VIDEO_DRV_ERROR_BUSY                (-2) ///< Driver is busy
-#define VIDEO_DRV_ERROR_TIMEOUT             (-3) ///< Timeout occurred
-#define VIDEO_DRV_ERROR_UNSUPPORTED         (-4) ///< Operation not supported
-#define VIDEO_DRV_ERROR_PARAMETER           (-5) ///< Parameter error
-
-/**
-\brief Video Status
-*/
-typedef struct {
-  uint32_t tx_active        :  1;       ///< Transmitter active
-  uint32_t rx_active        :  1;       ///< Receiver active
-  uint32_t reserved         : 30;
-} VideoDrv_Status_t;
-
-uint8_t* VideoRXBuffer();
-int32_t VideoDrv_Setup(void);
-
-/**
-  \fn          VideoDrv_Event_t
-  \brief       Video Events callback function type: void (*VideoDrv_Event_t) (uint32_t event
-  \param[in]   event events notification mask
-  \return      none
-*/
-typedef void (*VideoDrv_Event_t) (uint32_t event);
-
-/**
-  \fn          int32_t VideoDrv_Initialize (VideoDrv_Event_t cb_event)
-  \brief       Initialize Video Interface.
-  \param[in]   cb_event pointer to \ref VideoDrv_Event_t
-  \return      return code
-*/
-int32_t VideoDrv_Initialize (VideoDrv_Event_t cb_event);
-
-/**
-  \fn          void VideoDrv_Stop (void);
-  \brief       Stop audio simulation.
-  \return      return code
-*/
-void VideoDrv_Stop (void);
-
-
-/**
-  \fn          int32_t VideoDrv_Uninitialize (void)
-  \brief       De-initialize Video Interface.
-  \return      return code
-*/
-int32_t VideoDrv_Uninitialize (void);
-
-/**
-  \fn          int32_t VideoDrv_Configure (uint32_t interface, uint32_t channels, uint32_t sample_bits, uint32_t sample_rate)
-  \brief       Configure Video Interface.
-  \param[in]   interface   audio interface
-  \param[in]   pixel_size size in bytes
-  \param[in]   samplerate samples per second
-  \return      return code
-*/
-int32_t VideoDrv_Configure (uint32_t interface, uint32_t pixel_size,uint32_t samplerate);
-
-/**
-  \fn          int32_t VideoDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size)
-  \brief       Set Video Interface buffer.
-  \param[in]   interface   audio interface
-  \param[in]   buf         pointer to buffer for audio data
-  \param[in]   block_num   number of blocks in buffer (must be 2^n)
-  \param[in]   block_size  block size in number of samples
-  \return      return code
-*/
-int32_t VideoDrv_SetBuf (uint32_t interface, void *buf, uint32_t block_num, uint32_t block_size);
-
-/**
-  \fn          int32_t VideoDrv_Control (uint32_t control)
-  \brief       Control Video Interface.
-  \param[in]   control operation
-  \return      return code
-*/
-int32_t VideoDrv_Control (uint32_t control);
-
-
-/**
-  \fn          uint32_t VideoDrv_GetRxCount (void)
-  \brief       Get received block count.
-  \return      number of received blocks
-*/
-uint32_t VideoDrv_GetRxCount (void);
-
-/**
-  \fn          VideoDrv_Status_t VideoDrv_GetStatus (void)
-  \brief       Get Video Interface status.
-  \return      \ref VideoDrv_Status_t
-*/
-VideoDrv_Status_t VideoDrv_GetStatus (void);
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif /* __VIDEO_DRV_H */

+ 0 - 80
ComputeGraph/cg/nodes/cpp/StreamingSink.h

@@ -1,80 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        StreamingSink.h
- * Description:  Streaming Sink working with the RingBuffer
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _STREAMING_SINK_H_ 
-#define _STREAMING_SINK_H_ 
-
-#include "RingBuffer.h"
-
-/* This is deprecated. Don't use it */
-template<typename IN, int inputSize>
-class StreamingSink: public GenericSink<IN, inputSize>
-{
-public:
-    StreamingSink(FIFOBase<IN> &src,ring_config_t *config):
-    GenericSink<IN,inputSize>(src),mConfig(config){};
-
-    int prepareForRunning() override
-    {
-        if (this->willUnderflow()
-           )
-        {
-           return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution
-        }
-
-        return(0);
-    };
-
-    int run() override
-    {
-        IN *b=this->getReadBuffer();
-
-        int bufID=ringUserReserveBuffer(mConfig);
-        uint8_t *buf=ringGetBufferAddress(mConfig,bufID);
-
-        if (buf != NULL)
-        {
-           /* If a buffer is available we copy the data to the FIFO
-           */
-           memcpy(buf,(void*)b,inputSize*sizeof(IN));
-
-           /* We release the buffer so than it can be used by the interrupt */
-           ringUserReleaseBuffer(mConfig);
-           return(0);
-        }
-        else 
-        {
-            return(mConfig->error);
-        }
-
-        return(0);
-    }
-protected:
-    ring_config_t *mConfig;
-};
-
-#endif /* _STREAMING_SINK_H_ */

+ 0 - 88
ComputeGraph/cg/nodes/cpp/StreamingSource.h

@@ -1,88 +0,0 @@
-/* ----------------------------------------------------------------------
- * Project:      CMSIS DSP Library
- * Title:        StreamingSource.h
- * Description:  Streaming source working with the Ring buffer
- *
- * $Date:        30 July 2021
- * $Revision:    V1.10.0
- *
- * Target Processor: Cortex-M and Cortex-A cores
- * -------------------------------------------------------------------- */
-/*
- * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _STREAMING_SOURCE_H_ 
-#define _STREAMING_SOURCE_H_ 
-
-#include "RingBuffer.h"
-
-/* This is deprecated. Don't use it */
-template<typename OUT,int outputSize>
-class StreamingSource: public GenericSource<OUT,outputSize>
-{
-public:
-    StreamingSource(FIFOBase<OUT> &dst,ring_config_t *config):
-    GenericSource<OUT,outputSize>(dst),mConfig(config){};
-
-    int prepareForRunning() override
-    {
-        if (this->willUnderflow()
-           )
-        {
-           return(CG_SKIP_EXECUTION_ID_CODE); // Skip execution
-        }
-
-        return(0);
-    };
-
-    int run() override
-    {
-        OUT *b=this->getWriteBuffer();
-        /* 
-           Try to reserve a buffer. If no buffer is available, the task running
-           this node will sleep.
-
-           If there is a timeout (configured when the ring buffer was initialized)
-           the function will return a NULL pointer.
-
-        */
-        int bufID=ringUserReserveBuffer(mConfig);
-        uint8_t *buf=ringGetBufferAddress(mConfig,bufID);
-
-
-        if (buf != NULL)
-        {
-           /* If a buffer is available we copy the data to the FIFO
-           */
-           memcpy((void*)b,buf,outputSize*sizeof(OUT));
-
-           /* We release the buffer so than it can be used by the interrupt */
-           ringUserReleaseBuffer(mConfig);
-           return(0);
-        }
-        else 
-        {
-            return(mConfig->error);
-        }
-    };
-
-protected:
-    ring_config_t *mConfig;
-
-
-};
-#endif /* _STREAMING_SOURCE_H_ */

+ 14 - 8
ComputeGraph/cg/src/GenericNodes.h

@@ -65,8 +65,9 @@ class FIFOBase{
 public:
     virtual T* getWriteBuffer(int nb)=0;
     virtual T* getReadBuffer(int nb)=0;
-    virtual bool willUnderflowWith(int nb)=0;
-    virtual bool willOverflowWith(int nb)=0;
+    virtual bool willUnderflowWith(int nb) const = 0;
+    virtual bool willOverflowWith(int nb) const = 0;
+    virtual int nbSamplesInFIFO() const = 0;
 
 };
 
@@ -82,8 +83,9 @@ class FIFO<T,length,0,0>: public FIFOBase<T>
         FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay) {};
 
         /* Not used in synchronous mode */
-        bool willUnderflowWith(int nb) override {return false;};
-        bool willOverflowWith(int nb) override {return false;};
+        bool willUnderflowWith(int nb) const override {return false;};
+        bool willOverflowWith(int nb) const override {return false;};
+        int nbSamplesInFIFO() const override {return 0;};
 
         T * getWriteBuffer(int nb) override
         {
@@ -142,8 +144,10 @@ class FIFO<T,length,1,0>: public FIFOBase<T>
         FIFO(T *buffer,int delay=0):mBuffer(buffer),readPos(0),writePos(delay) {};
         FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay) {};
 
-        bool willUnderflowWith(int nb) override {return false;};
-        bool willOverflowWith(int nb) override {return false;};
+        /* Not used in synchronous mode */
+        bool willUnderflowWith(int nb) const override {return false;};
+        bool willOverflowWith(int nb) const override {return false;};
+        int nbSamplesInFIFO() const override {return 0;};
 
         T * getWriteBuffer(int nb) override
         {
@@ -226,16 +230,18 @@ class FIFO<T,length,0,1>: public FIFOBase<T>
             return(ret);
         }
 
-        bool willUnderflowWith(int nb) override
+        bool willUnderflowWith(int nb) const override
         {
             return((nbSamples - nb)<0);
         }
 
-        bool willOverflowWith(int nb) override
+        bool willOverflowWith(int nb) const override
         {
             return((nbSamples + nb)>length);
         }
 
+        int nbSamplesInFIFO() const override {return nbSamples;};
+
         #ifdef DEBUGSCHED
         void dump()
         {

+ 1 - 1
ComputeGraph/examples/CMakeLists.txt

@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 3.15)
+cmake_minimum_required (VERSION 3.21)
 include(CMakePrintHelpers)
 
 set(Python_FIND_REGISTRY "LAST")

+ 3 - 2
ComputeGraph/examples/example1/generated/scheduler.cpp

@@ -102,7 +102,8 @@ float32_t buf2[BUFFERSIZE2]={0};
 
 
 CG_BEFORE_SCHEDULER_FUNCTION
-uint32_t scheduler(int *error,int someVariable)
+uint32_t scheduler(int *error,const char *testString,
+                              int someVariable)
 {
     int cgStaticError=0;
     uint32_t nbSchedule=0;
@@ -119,7 +120,7 @@ uint32_t scheduler(int *error,int someVariable)
     /* 
     Create node objects
     */
-    ProcessingNode<float32_t,7,float32_t,5> filter(fifo0,fifo1,4,"Test",someVariable);
+    ProcessingNode<float32_t,7,float32_t,5> filter(fifo0,fifo1,4,testString,someVariable);
     Sink<float32_t,5> sink(fifo1);
     Source<float32_t,5> source(fifo0);
 

+ 2 - 1
ComputeGraph/examples/example1/generated/scheduler.h

@@ -16,7 +16,8 @@ extern "C"
 #endif
 
 
-extern uint32_t scheduler(int *error,int someVariable);
+extern uint32_t scheduler(int *error,const char *testString,
+                              int someVariable);
 
 #ifdef   __cplusplus
 }

+ 5 - 3
ComputeGraph/examples/example1/graph.py

@@ -37,8 +37,8 @@ class ProcessingNode(Node):
 floatType=CType(F32)
 src=Source("source",floatType,5)
 b=ProcessingNode("filter",floatType,7,5)
-b.addLiteralArg(4,"Test")
-b.addVariableArg("someVariable")
+b.addLiteralArg(4)
+b.addVariableArg("testString","someVariable")
 sink=Sink("sink",floatType,5)
 
 g = Graph()
@@ -51,7 +51,9 @@ print("Generate graphviz and code")
 
 conf=Configuration()
 conf.debugLimit=1
-conf.cOptionalArgs="int someVariable"
+conf.cOptionalArgs=["const char *testString"
+                   ,"int someVariable"
+                   ]
 #conf.displayFIFOSizes=True
 # Prefix for global FIFO buffers
 #conf.prefix="sched1"

+ 1 - 1
ComputeGraph/examples/example1/main.cpp

@@ -6,6 +6,6 @@ int main(int argc, char const *argv[])
 {
     int error;
     printf("Start\n");
-    uint32_t nbSched=scheduler(&error,1);
+    uint32_t nbSched=scheduler(&error,"Test",1);
     return 0;
 }

+ 2 - 0
ComputeGraph/examples/example10/AppNodes.h

@@ -31,6 +31,8 @@
 #include <iostream>
 #include <cstdio>
 
+#include "NullSink.h"
+
 static int count=0;
 
 template<typename OUT,int outputSize>

+ 67 - 26
ComputeGraph/examples/example10/generated/scheduler.cpp

@@ -78,9 +78,9 @@ CG_AFTER_INCLUDES
 Description of the scheduling. 
 
 */
-static unsigned int schedule[7]=
+static unsigned int schedule[9]=
 { 
-5,6,2,0,1,3,4,
+7,8,2,1,4,0,3,5,6,
 };
 
 CG_BEFORE_FIFO_BUFFERS
@@ -93,8 +93,10 @@ FIFO buffers
 #define FIFOSIZE1 2
 #define FIFOSIZE2 2
 #define FIFOSIZE3 2
-#define FIFOSIZE4 2
+#define FIFOSIZE4 3
 #define FIFOSIZE5 2
+#define FIFOSIZE6 2
+#define FIFOSIZE7 2
 
 #define BUFFERSIZE1 2
 CG_BEFORE_BUFFER
@@ -112,7 +114,7 @@ int16_t buf3[BUFFERSIZE3]={0};
 CG_BEFORE_BUFFER
 int16_t buf4[BUFFERSIZE4]={0};
 
-#define BUFFERSIZE5 2
+#define BUFFERSIZE5 3
 CG_BEFORE_BUFFER
 int16_t buf5[BUFFERSIZE5]={0};
 
@@ -120,6 +122,14 @@ int16_t buf5[BUFFERSIZE5]={0};
 CG_BEFORE_BUFFER
 int16_t buf6[BUFFERSIZE6]={0};
 
+#define BUFFERSIZE7 2
+CG_BEFORE_BUFFER
+int16_t buf7[BUFFERSIZE7]={0};
+
+#define BUFFERSIZE8 2
+CG_BEFORE_BUFFER
+int16_t buf8[BUFFERSIZE8]={0};
+
 
 CG_BEFORE_SCHEDULER_FUNCTION
 uint32_t scheduler(int *error)
@@ -138,17 +148,21 @@ uint32_t scheduler(int *error)
     FIFO<int16_t,FIFOSIZE3,0,1> fifo3(buf4);
     FIFO<int16_t,FIFOSIZE4,0,1> fifo4(buf5);
     FIFO<int16_t,FIFOSIZE5,0,1> fifo5(buf6);
+    FIFO<int16_t,FIFOSIZE6,0,1> fifo6(buf7);
+    FIFO<int16_t,FIFOSIZE7,0,1> fifo7(buf8);
 
     CG_BEFORE_NODE_INIT;
     /* 
     Create node objects
     */
-    Duplicate2<int16_t,1,int16_t,1,int16_t,1> dup0(fifo3,fifo4,fifo5);
-    ProcessingOddEven<int16_t,1,int16_t,1,int16_t,1> proc(fifo0,fifo1,fifo2);
-    SinkAsync<int16_t,1> sinka(fifo4);
-    SinkAsync<int16_t,1> sinkb(fifo5);
-    SourceEven<int16_t,1> sourceEven(fifo1);
-    SourceOdd<int16_t,1> sourceOdd(fifo0);
+    NullSink<int16_t,1> debug(fifo4);
+    Duplicate2<int16_t,1,int16_t,1,int16_t,1> dup0(fifo2,fifo3,fifo4);
+    Duplicate2<int16_t,1,int16_t,1,int16_t,1> dup1(fifo5,fifo6,fifo7);
+    ProcessingOddEven<int16_t,1,int16_t,1,int16_t,1> proc(fifo3,fifo0,fifo1);
+    SinkAsync<int16_t,1> sinka(fifo6);
+    SinkAsync<int16_t,1> sinkb(fifo7);
+    SourceEven<int16_t,1> sourceEven(fifo0);
+    SourceOdd<int16_t,1> sourceOdd(fifo2);
 
     /* Run several schedule iterations */
     CG_BEFORE_SCHEDULE;
@@ -156,7 +170,7 @@ uint32_t scheduler(int *error)
     {
         /* Run a schedule iteration */
         CG_BEFORE_ITERATION;
-        for(unsigned long id=0 ; id < 7; id++)
+        for(unsigned long id=0 ; id < 9; id++)
         {
             CG_BEFORE_NODE_EXECUTION;
 
@@ -167,8 +181,8 @@ uint32_t scheduler(int *error)
                 {
                                         
                     bool canRun=true;
-                    canRun &= !fifo2.willUnderflowWith(1);
-                    canRun &= !fifo3.willOverflowWith(1);
+                    canRun &= !fifo1.willUnderflowWith(1);
+                    canRun &= !fifo5.willOverflowWith(1);
 
                     if (!canRun)
                     {
@@ -183,35 +197,47 @@ uint32_t scheduler(int *error)
 
                 case 1:
                 {
-                    cgStaticError = dup0.prepareForRunning();
+                    cgStaticError = debug.prepareForRunning();
                 }
                 break;
 
                 case 2:
                 {
-                    cgStaticError = proc.prepareForRunning();
+                    cgStaticError = dup0.prepareForRunning();
                 }
                 break;
 
                 case 3:
                 {
-                    cgStaticError = sinka.prepareForRunning();
+                    cgStaticError = dup1.prepareForRunning();
                 }
                 break;
 
                 case 4:
                 {
-                    cgStaticError = sinkb.prepareForRunning();
+                    cgStaticError = proc.prepareForRunning();
                 }
                 break;
 
                 case 5:
                 {
-                    cgStaticError = sourceEven.prepareForRunning();
+                    cgStaticError = sinka.prepareForRunning();
                 }
                 break;
 
                 case 6:
+                {
+                    cgStaticError = sinkb.prepareForRunning();
+                }
+                break;
+
+                case 7:
+                {
+                    cgStaticError = sourceEven.prepareForRunning();
+                }
+                break;
+
+                case 8:
                 {
                     cgStaticError = sourceOdd.prepareForRunning();
                 }
@@ -222,7 +248,10 @@ uint32_t scheduler(int *error)
             }
 
             if (cgStaticError == CG_SKIP_EXECUTION_ID_CODE)
-                continue;
+            { 
+              cgStaticError = 0;
+              continue;
+            }
 
             CHECKERROR;
 
@@ -235,8 +264,8 @@ uint32_t scheduler(int *error)
 
                    int16_t* i0;
                    int16_t* o1;
-                   i0=fifo2.getReadBuffer(1);
-                   o1=fifo3.getWriteBuffer(1);
+                   i0=fifo1.getReadBuffer(1);
+                   o1=fifo5.getWriteBuffer(1);
                    compute(i0,o1,1);
                    cgStaticError = 0;
                   }
@@ -245,35 +274,47 @@ uint32_t scheduler(int *error)
 
                 case 1:
                 {
-                   cgStaticError = dup0.run();
+                   cgStaticError = debug.run();
                 }
                 break;
 
                 case 2:
                 {
-                   cgStaticError = proc.run();
+                   cgStaticError = dup0.run();
                 }
                 break;
 
                 case 3:
                 {
-                   cgStaticError = sinka.run();
+                   cgStaticError = dup1.run();
                 }
                 break;
 
                 case 4:
                 {
-                   cgStaticError = sinkb.run();
+                   cgStaticError = proc.run();
                 }
                 break;
 
                 case 5:
                 {
-                   cgStaticError = sourceEven.run();
+                   cgStaticError = sinka.run();
                 }
                 break;
 
                 case 6:
+                {
+                   cgStaticError = sinkb.run();
+                }
+                break;
+
+                case 7:
+                {
+                   cgStaticError = sourceEven.run();
+                }
+                break;
+
+                case 8:
                 {
                    cgStaticError = sourceOdd.run();
                 }

+ 9 - 2
ComputeGraph/examples/example10/graph.py

@@ -55,6 +55,8 @@ comp=Unary("compute",dataType,1)
 sinka=SinkAsync("sinka",dataType,1)
 sinkb=SinkAsync("sinkb",dataType,1)
 
+debug=NullSink("debug",dataType,1)
+
 g = Graph()
 
 # Option to customize the default class
@@ -67,6 +69,11 @@ g.duplicateNodeClassName = "Duplicate"
 
 g.connect(odd.o,proc.ia)
 g.connect(even.o,proc.ib)
+# Just for checking duplicate nodes
+# with scaling factor are working.
+# In practice, all edge of a duplicate nodes
+# should have same FIFO size
+g.connect(odd.o,debug.i,fifoScale=3.0)
 
 g.connect(proc.o,comp.i)
 g.connect(comp.o,sinka.i)
@@ -95,8 +102,8 @@ conf.asynchronous = True
 # Increase size of synchronous FIFOs by 100%
 # for the asynchronous case (so 2 samples
 # instead of 1 in this example)
-conf.FIFOIncrease = 100 # percent
-
+#conf.FIFOIncrease = 100 # percent
+conf.FIFOIncrease = 2.0
 
 #conf.displayFIFOSizes=True
 # Prefix for global FIFO buffers

+ 29 - 8
ComputeGraph/examples/example10/test.dot

@@ -16,8 +16,17 @@ compute1 [label=<
   </TR>
 </TABLE>>];
 
+debug [label=<
+<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+  <TR>
+    <TD ALIGN="CENTER" PORT="i">debug<BR/>(NullSink)</TD>
+  </TR>
+</TABLE>>];
+
 dup0 [shape=point,label=dup0]
 
+dup1 [shape=point,label=dup1]
+
 
 proc [label=<
 <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
@@ -64,38 +73,50 @@ sourceOdd [label=<
 
 
 
-sourceOdd:i -> proc:ia [label="s16(2)"
+sourceEven:i -> proc:ib [label="s16(2)"
 ,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>
 ,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>]
 
-sourceEven:i -> proc:ib [label="s16(2)"
+proc:o -> compute1:i [label="s16(2)"
 ,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>
 ,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>]
 
-proc:o -> compute1:i [label="s16(2)"
-,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
-</TD></TR></TABLE>>
+sourceOdd:i ->  
+dup0 [label="s16(2)"
+
 ,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>]
 
+ 
+dup0 -> proc:ia [label="s16(2)"
+,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
+</TD></TR></TABLE>>
+]
+
+ 
+dup0 -> debug:i [label="s16(3)"
+,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
+</TD></TR></TABLE>>
+]
+
 compute1:i ->  
-dup0 [label="s16(2)"
+dup1 [label="s16(2)"
 
 ,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>]
 
  
-dup0 -> sinka:i [label="s16(2)"
+dup1 -> sinka:i [label="s16(2)"
 ,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>
 ]
 
  
-dup0 -> sinkb:i [label="s16(2)"
+dup1 -> sinkb:i [label="s16(2)"
 ,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >1</FONT>
 </TD></TR></TABLE>>
 ]

BIN
ComputeGraph/examples/example10/test.pdf


+ 5 - 2
PythonWrapper/.gitignore

@@ -1,4 +1,7 @@
 dist/
-build/
 examples/rec_2.dat
-
+build/bin_dsp    
+build/cmake_install.cmake  
+build/CMakeFiles  
+build/Makefile
+build/CMakeCache.txt       

+ 13 - 0
PythonWrapper/CMakeLists.txt

@@ -0,0 +1,13 @@
+cmake_minimum_required (VERSION 3.6)
+
+# Define the project
+project (pythonwrapper VERSION 0.1)
+
+
+###########
+#
+# CMSIS DSP
+#
+
+add_subdirectory(${CMSISDSP}/Source bin_dsp)
+

+ 5 - 0
PythonWrapper/build/clean.bat

@@ -0,0 +1,5 @@
+DEL /F  CMakeCache.txt
+RMDIR /S /Q CMakeFiles
+DEL /F Makefile
+RMDIR /S /Q bin_dsp
+DEL /F cmake_install.cmake

+ 8 - 0
PythonWrapper/build/create.bat

@@ -0,0 +1,8 @@
+cmake -DHOST=YES ^
+  -DLOOPUNROLL=ON ^
+  -DWRAPPER=YES ^
+  -DCMSISDSP="path to CMSIS-DSP folder" ^
+  -DCMAKE_C_FLAGS_RELEASE="-std=c11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra" ^
+  -DCMAKE_CXX_FLAGS_RELEASE="-fno-rtti -std=c++11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra -Wno-unused-parameter" ^
+  -G "Unix Makefiles" ..
+

+ 5 - 0
PythonWrapper/build_linux/clean.sh

@@ -0,0 +1,5 @@
+rm -f  CMakeCache.txt
+rm -rf CMakeFiles
+rm -f Makefile
+rm -rf bin_dsp
+rm -f cmake_install.cmake

+ 11 - 0
PythonWrapper/build_linux/create.sh

@@ -0,0 +1,11 @@
+cmake -DHOST=YES \
+  -DLOOPUNROLL=ON \
+  -DWRAPPER=YES \
+  -DCMAKE_POSITION_INDEPENDENT_CODE=YES \
+  -DCMSISDSP="path to CMSIS-DSP folder" \
+  -DCMAKE_C_FLAGS_RELEASE="-std=c11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra" \
+  -DCMAKE_CXX_FLAGS_RELEASE="-fno-rtti -std=c++11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra -Wno-unused-parameter" \
+  -G "Unix Makefiles" ..
+
+# For Mac universal lib
+# -arch x86_64 -arch arm64 -mmacosx-version-min=11.0

+ 4 - 4
PythonWrapper/cmsisdsp_pkg/src/cmsisdsp_transform.c

@@ -2291,11 +2291,11 @@ cmsis_arm_rfft_q15(PyObject *obj, PyObject *args)
      inputSize=selfS->instance->fftLenReal;
      if (selfS->instance->ifftFlagR)
      {
-        outputSize = inputSize-2;
+        outputSize = inputSize;
      }
      else
      {
-        outputSize = 2*inputSize+2;
+        outputSize = 2*inputSize;
      }
 
     GETARGUMENT(pSrc,NPY_INT16,int16_t,int16_t);
@@ -2365,11 +2365,11 @@ cmsis_arm_rfft_q31(PyObject *obj, PyObject *args)
      inputSize=selfS->instance->fftLenReal;
      if (selfS->instance->ifftFlagR)
      {
-        outputSize = inputSize-2;
+        outputSize = inputSize;
      }
      else
      {
-        outputSize = 2*inputSize+2;
+        outputSize = 2*inputSize;
      }
   
     GETARGUMENT(pSrc,NPY_INT32,int32_t,int32_t);

+ 74 - 13
PythonWrapper/examples/debug.py

@@ -1,20 +1,81 @@
 import cmsisdsp as dsp
+import cmsisdsp.fixedpoint as f
+
 import numpy as np
 from scipy import signal
+import matplotlib.pyplot as plt
+import scipy.fft
+
+import colorama
+from colorama import init,Fore, Back, Style
+from numpy.testing import assert_allclose
+
+init()
+
+def printTitle(s):
+    print("\n" + Fore.GREEN + Style.BRIGHT +  s + Style.RESET_ALL)
+
+def printSubTitle(s):
+    print("\n" + Style.BRIGHT + s + Style.RESET_ALL)
+
+
+def chop(A, eps = 1e-6):
+    B = np.copy(A)
+    B[np.abs(A) < eps] = 0
+    return B
+
+nb = 32
+signal = np.cos(2 * np.pi * np.arange(nb) / nb)*np.cos(0.2*2 * np.pi * np.arange(nb) / nb)
+
+ref=scipy.fft.rfft(signal)
+invref = scipy.fft.irfft(ref)
+
+print(f"ref length = {len(ref)}")
+print(ref)
+
+# Convert ref to CMSIS-DSP format 
+referenceFloat=np.zeros(2*len(ref))
+print(f"referenceFloat length = {len(referenceFloat)}")
+# Replace complex datatype by real datatype
+referenceFloat[0::2] = np.real(ref)
+referenceFloat[1::2] = np.imag(ref)
+# Copy Nyquist frequency value into first 
+# sample.This is just a storage trick so that the
+# output of the RFFT has same length as input
+# It is legacy behavior that we need to keep
+# for backward compatibility but it is not
+# very pretty
+#referenceFloat[1] = np.real(ref[-1])
+
+rifftQ31=dsp.arm_rfft_instance_q31()
+status=dsp.arm_rfft_init_q31(rifftQ31,nb,1,1)
+# Apply CMSIS-DSP scaling
+referenceQ31 = f.toQ31(referenceFloat / nb) 
+
+resultQ31 = dsp.arm_rfft_q31(rifftQ31,referenceQ31)
+resultF = f.Q31toF32(resultQ31)
+
+print(f"resultF length = {len(resultF)}")
+assert_allclose(invref/nb,resultF,atol=1e-6)
+
+signalQ31 = f.toQ31(signal)
+rfftQ31=dsp.arm_rfft_instance_q31()
+status=dsp.arm_rfft_init_q31(rfftQ31,nb,0,1)
+resultQ31 = dsp.arm_rfft_q31(rfftQ31,signalQ31)
+print(len(resultQ31))
+print(2*nb)
+resultF = f.Q31toF32(resultQ31) * nb
 
-firf32 = dsp.arm_fir_instance_f32()
-dsp.arm_fir_init_f32(firf32,3,[1.,2,3],[0,0,0,0,0,0,0])
-print(firf32.numTaps())
-filtered_x = signal.lfilter([3,2,1.], 1.0, [1,2,3,4,5,1,2,3,4,5])
-print(filtered_x)
-print(dsp.arm_fir_f32(firf32,[1,2,3,4,5]))
-print(dsp.arm_fir_f32(firf32,[1,2,3,4,5]))
+def compareWithConjugatePart(r):
+    res = r[0::2] + 1j * r[1::2]
+    conjPart = res[nb:nb//2:-1].conj()
+    refPart = res[1:nb//2]
+    assert(np.equal(refPart , conjPart).all())
 
-a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]])
-b=np.array([[1.,2,3,4],[5.1,6,7,8],[9.1,10,11,12]])
-#print(a+b)
+compareWithConjugatePart(resultF)
 
-#print("OK")
+res = resultF[0::2] + 1j * resultF[1::2]
+print(res)
 
-v=dsp.arm_mat_add_f32(a,b)
-print(v)
+print(res[0:nb//2+1])
+print(res[0:nb//2+1].shape)

+ 1 - 1
PythonWrapper/examples/example_1_10.py

@@ -6,7 +6,7 @@ import math
 import colorama
 from colorama import init,Fore, Back, Style
 from numpy.testing import assert_allclose
-import matplotlib.pyplot as plt
+#import matplotlib.pyplot as plt
 from scipy import signal
 import scipy.signal.windows as win
 

+ 1 - 1
PythonWrapper/examples/example_1_9.py

@@ -6,7 +6,7 @@ import math
 import colorama
 from colorama import init,Fore, Back, Style
 from numpy.testing import assert_allclose
-import matplotlib.pyplot as plt
+#import matplotlib.pyplot as plt
 from scipy import signal
 
 init()

+ 67 - 17
PythonWrapper/examples/testrfft_all.py

@@ -3,7 +3,7 @@ import cmsisdsp.fixedpoint as f
 
 import numpy as np
 from scipy import signal
-import matplotlib.pyplot as plt
+#import matplotlib.pyplot as plt
 import scipy.fft
 
 import colorama
@@ -24,12 +24,42 @@ def chop(A, eps = 1e-6):
     B[np.abs(A) < eps] = 0
     return B
 
+# For fixed point version, compare that
+# the conjugate part is really the conjugate part
+def compareWithConjugatePart(r):
+    res = r[0::2] + 1j * r[1::2]
+    conjPart = res[nb:nb//2:-1].conj()
+    refPart = res[1:nb//2]
+    assert(np.equal(refPart , conjPart).all())
+
 nb = 32
 signal = np.cos(2 * np.pi * np.arange(nb) / nb)*np.cos(0.2*2 * np.pi * np.arange(nb) / nb)
 
 ref=scipy.fft.rfft(signal)
 invref = scipy.fft.irfft(ref)
 
+assert(len(ref) == (nb // 2) + 1)
+assert(len(invref) == nb)
+
+# Length of arrays for the float implementation
+# of the RFFT (in float so there is a factor 2
+# when the samples are complex)
+
+RFFT_F_IN_LENGTH = nb # real
+RFFT_F_OUT_LENGTH = nb # complex (so nb // 2 complex)
+
+RIFFT_F_IN_LENGTH = nb # complex
+RIFFT_F_OUT_LENGTH = nb # real
+
+# Length of arrays for the fixed point implementation
+# of the RFFT
+RFFT_Q_IN_LENGTH = nb 
+RFFT_Q_OUT_LENGTH = 2*nb 
+
+# Conjugate part ignored
+RIFFT_Q_IN_LENGTH = nb + 2
+RIFFT_Q_OUT_LENGTH = nb
+
 # Convert ref to CMSIS-DSP format 
 referenceFloat=np.zeros(nb)
 # Replace complex datatype by real datatype
@@ -43,6 +73,10 @@ referenceFloat[1::2] = np.imag(ref)[:-1]
 # very pretty
 referenceFloat[1] = np.real(ref[-1])
 
+referenceFixed=np.zeros(2*len(ref))
+referenceFixed[0::2] = np.real(ref)
+referenceFixed[1::2] = np.imag(ref)
+
 printTitle("RFFT FAST F64")
 
 printSubTitle("RFFT")
@@ -51,7 +85,8 @@ printSubTitle("RFFT")
 rfftf64=dsp.arm_rfft_fast_instance_f64()
 status=dsp.arm_rfft_fast_init_f64(rfftf64,nb)
 result = dsp.arm_rfft_fast_f64(rfftf64,signal,0)
-
+assert(len(signal) == RFFT_F_IN_LENGTH)
+assert(len(result) == RFFT_F_OUT_LENGTH)
 
 assert_allclose(referenceFloat,result)
 
@@ -60,6 +95,8 @@ printSubTitle("RIFFT")
 rifftf64=dsp.arm_rfft_fast_instance_f64()
 status=dsp.arm_rfft_fast_init_f64(rifftf64,nb)
 result = dsp.arm_rfft_fast_f64(rifftf64,referenceFloat,1)
+assert(len(referenceFloat) == RIFFT_F_IN_LENGTH)
+assert(len(result) == RIFFT_F_OUT_LENGTH)
 
 assert_allclose(invref,result,atol=1e-15)
 
@@ -71,6 +108,8 @@ printSubTitle("RFFT")
 rfftf32=dsp.arm_rfft_fast_instance_f32()
 status=dsp.arm_rfft_fast_init_f32(rfftf32,nb)
 result = dsp.arm_rfft_fast_f32(rfftf32,signal,0)
+assert(len(signal) == RFFT_F_IN_LENGTH)
+assert(len(result) == RFFT_F_OUT_LENGTH)
 
 
 assert_allclose(referenceFloat,result,rtol=3e-6)
@@ -80,17 +119,12 @@ printSubTitle("RIFFT")
 rifftf32=dsp.arm_rfft_fast_instance_f32()
 status=dsp.arm_rfft_fast_init_f32(rifftf32,nb)
 result = dsp.arm_rfft_fast_f32(rifftf32,referenceFloat,1)
+assert(len(referenceFloat) == RIFFT_F_IN_LENGTH)
+assert(len(result) == RIFFT_F_OUT_LENGTH)
 
 assert_allclose(invref,result,atol=1e-7)
 
 # Fixed point
-# Reference from fixed point arithmetric.
-# The RFFT are not packing the Nyquist frequency
-# real value in sample 0
-referenceFloat=np.zeros(nb+2)
-# Replace complex datatype by real datatype
-referenceFloat[0::2] = np.real(ref)
-referenceFloat[1::2] = np.imag(ref)
 
 printTitle("RFFT Q31")
 
@@ -100,11 +134,17 @@ signalQ31 = f.toQ31(signal)
 rfftQ31=dsp.arm_rfft_instance_q31()
 status=dsp.arm_rfft_init_q31(rfftQ31,nb,0,1)
 resultQ31 = dsp.arm_rfft_q31(rfftQ31,signalQ31)
+assert(len(signalQ31) == RFFT_Q_IN_LENGTH)
+assert(len(resultQ31) == RFFT_Q_OUT_LENGTH)
+compareWithConjugatePart(resultQ31)
+
 # Drop the conjugate part which is not computed by scipy
 resultQ31 = resultQ31[:nb+2]
+assert(len(resultQ31) == RIFFT_Q_IN_LENGTH)
+
 resultF = f.Q31toF32(resultQ31) * nb
 
-assert_allclose(referenceFloat,resultF,rtol=1e-6,atol=1e-6)
+assert_allclose(referenceFixed,resultF,rtol=1e-6,atol=1e-6)
 
 
 printSubTitle("RIFFT")
@@ -112,11 +152,13 @@ printSubTitle("RIFFT")
 rifftQ31=dsp.arm_rfft_instance_q31()
 status=dsp.arm_rfft_init_q31(rifftQ31,nb,1,1)
 # Apply CMSIS-DSP scaling
-referenceQ31 = f.toQ31(referenceFloat / nb) 
-resultQ31 = dsp.arm_rfft_q31(rifftQ31,referenceFloat)
+referenceQ31 = f.toQ31(referenceFixed/ nb) 
+resultQ31 = dsp.arm_rfft_q31(rifftQ31,referenceQ31)
 resultF = f.Q31toF32(resultQ31)
+assert(len(referenceQ31) == RIFFT_Q_IN_LENGTH)
+assert(len(resultQ31) == RIFFT_Q_OUT_LENGTH)
 
-assert_allclose(invref,result,atol=1e-6)
+assert_allclose(invref/nb,resultF,atol=1e-6)
 
 printTitle("RFFT Q15")
 
@@ -126,11 +168,17 @@ signalQ15 = f.toQ15(signal)
 rfftQ15=dsp.arm_rfft_instance_q15()
 status=dsp.arm_rfft_init_q15(rfftQ15,nb,0,1)
 resultQ15 = dsp.arm_rfft_q15(rfftQ15,signalQ15)
+assert(len(signalQ15) == RFFT_Q_IN_LENGTH)
+assert(len(resultQ15) == RFFT_Q_OUT_LENGTH)
+compareWithConjugatePart(resultQ15)
+
 # Drop the conjugate part which is not computed by scipy
 resultQ15 = resultQ15[:nb+2]
+assert(len(resultQ15) == RIFFT_Q_IN_LENGTH)
+
 resultF = f.Q15toF32(resultQ15) * nb
 
-assert_allclose(referenceFloat,resultF,rtol=1e-6,atol=1e-2)
+assert_allclose(referenceFixed,resultF,rtol=1e-6,atol=1e-2)
 
 
 printSubTitle("RIFFT")
@@ -138,9 +186,11 @@ printSubTitle("RIFFT")
 rifftQ15=dsp.arm_rfft_instance_q15()
 status=dsp.arm_rfft_init_q15(rifftQ15,nb,1,1)
 # Apply CMSIS-DSP scaling
-referenceQ15 = f.toQ15(referenceFloat / nb) 
-resultQ15 = dsp.arm_rfft_q15(rifftQ15,referenceFloat)
+referenceQ15 = f.toQ15(referenceFixed / nb) 
+resultQ15 = dsp.arm_rfft_q15(rifftQ15,referenceQ15)
 resultF = f.Q15toF32(resultQ15)
+assert(len(referenceQ15) == RIFFT_Q_IN_LENGTH)
+assert(len(resultQ15) == RIFFT_Q_OUT_LENGTH)
 
-assert_allclose(invref,result,atol=1e-2)
+assert_allclose(invref/nb,resultF,atol=1e-3)
 

+ 11 - 2
PythonWrapper_README.md

@@ -61,13 +61,16 @@ Since the [CMSIS-DSP](https://github.com/ARM-software/CMSIS-DSP) wrapper is usin
     > pip install numpy
 
 Once `NumPy` is installed, you can build the [CMSIS-DSP](https://github.com/ARM-software/CMSIS-DSP) python wrapper. Go to folder `CMSIS/DSP`.
-(In a previous version you had to go to the `PythonWrapper` folder. Now the `setup.py` is inside the DSP folder).
 
 Now, you can install the cmsisdsp package in editable mode:
 
-    > pip install -e "Path To The Folder Containing setup.py"
+    > pip install -e .
 
+Before using this command, you need to rebuild the CMSIS-DSP library which is no more built by the `setup.py` script.
 
+There is a `CMakeLists.txt` in the `PythonWrapper` folder for this. The `build` folders in `PythonWrapper` are giving some examples of the options to use with the `cmake` command to generate the `Makefile` and build the library.
+
+This library is then used by the `setup.py` script to build the Python extension.
 
 ## Running the examples
 
@@ -239,6 +242,12 @@ The wrapper is now containing the compute graph Python scripts and you should re
 
 # Change history
 
+## Version 1.9.6:
+
+* Corrections to the RFFTs APIs
+* More flexibility in the compute graph to specify the additional arguments of the scheduler and nodes
+* Possibility to set the FIFO scaling factor at FIFO level (in asynchronous mode)
+
 ## Version 1.9.5:
 
 Same as 1.9.4 but will work in Google Colab.

+ 39 - 32
README.md

@@ -55,9 +55,7 @@ The Python scripts for the static scheduler generator are part of the CMSIS-DSP
 
 The header files are part of the CMSIS-DSP pack (version 1.10.2 and above).
 
-The audio streaming nodes on top of CMSIS-RTOS2 are not part of the CMSIS-DSP pack but can be found in the repository. They are demo quality only. They can only be used with Arm Virtual Hardware.
-
-The Compute Graph is making it easier to implement a streaming solution : connecting different compute kernels each consuming and producing different amount of data.
+he Compute Graph is making it easier to implement a streaming solution : connecting different compute kernels each consuming and producing different amount of data.
 
 ## Support / Contact
 
@@ -222,6 +220,44 @@ The final executable has no extension in the filename.
 
 Of course, on your fast model or virtual hardware you should use the right configuration file (to enable float, to enable FVP, to enable semihosting if needed for the examples ...)
 
+## Code size
+
+The linker may be able, in some cases, to remove the unused tables (like FFT tables) but:
+
+* It is not a robust solution because it is dependent on how the code is written and the linker is not always able to deduce that some tables are not used
+* It often leads to a coding style where implementation details are visible for the initializations (to help the linker). It thus makes it more difficult to move between different architectures 
+* It often relies on toolchain features which are embedded related but CMSIS-DSP is also used on very high end system where those features may be missing
+
+For all those reasons, compilation options have been introduced to control what's included in the library build. Those options are providing a more complex but more robust and portable solution. 
+
+If no new option is defined, everything will behave as usual and as consequence all tables will be included in the build. There are lot of FFT tables and some are big (F64, 4096 samples for instance).
+
+If `ARM_DSP_CONFIG_TABLES` is defined then the new compilation options will be taken into account.
+
+It is strongly suggested to use the new Python script `cmsisdspconfig.py` to generate the `-D` options to use on the compiler command line.
+
+    pip install streamlit
+    streamlit run cmsisdspconfig.py
+
+If you use `cmake`, it is also easy since high level options are defined and they will select the right compilation options. 
+
+For instance, if you want to use the `arm_rfft_fast_f32` for a 32 sample RFFT, in` fft.cmake` you'll see an option `RFFT_FAST_F32_32`.
+
+If you don't use cmake nor the Python script, you can just look at `fft.cmake` or `interpol.cmake` in `Source` to see which compilation options are needed.
+
+We see, that the following symbols need to be enabled for `RFFT_FAST_F32_32` with 32 samples:
+
+* `ARM_TABLE_TWIDDLECOEF_F32_16 `
+* `ARM_TABLE_BITREVIDX_FLT_16`
+* `ARM_TABLE_TWIDDLECOEF_RFFT_F32_32`
+* `ARM_TABLE_TWIDDLECOEF_F32_16`
+
+In addition to that, `ARM_FFT_ALLOW_TABLES` must also be defined.
+
+This last symbol is required because if no transform functions are included in the build, then by default all flags related to FFT tables are ignored.
+
+
+
 ## Folders and files
 
 The only folders required to build and use CMSIS-DSP Library are:
@@ -280,32 +316,3 @@ And we have a script to make it easier to customize the build:
 * cmsisdspconfig.py:
   * Web browser UI to generate build configurations (temporary until the CMSIS-DSP configuration is reworked to be simpler and more maintainable)
 
-
-## Compilation symbols for tables
-
-Some new compilations symbols have been introduced to avoid including all the tables if they are not needed.
-
-If no new symbol is defined, everything will behave as usual. If `ARM_DSP_CONFIG_TABLES` is defined then the new symbols will be taken into account.
-
-It is strongly suggested to use the new Python script `cmsisdspconfig.py` to generate the -D options to use on the compiler command line.
-
-    pip install streamlit
-    streamlit run cmsisdspconfig.py
-
-If you use `cmake`, it is also easy since high level options are defined and they will select the right compilation symbols. 
-
-For instance, if you want to use the `arm_rfft_fast_f32`, in` fft.cmake` you'll see an option `RFFT_FAST_F32_32`.
-
-If you don't use cmake nor the Python script, you can just look at `fft.cmake` or `interpol.cmake` in `Source` to see which compilation symbols are needed.
-
-We see, for `arm_rfft_fast_f32`, that the following symbols need to be enabled :
-
-* `ARM_TABLE_TWIDDLECOEF_F32_16 `
-* `ARM_TABLE_BITREVIDX_FLT_16`
-* `ARM_TABLE_TWIDDLECOEF_RFFT_F32_32`
-* `ARM_TABLE_TWIDDLECOEF_F32_16`
-
-In addition to that, `ARM_DSP_CONFIG_TABLES` must be enabled and finally `ARM_FFT_ALLOW_TABLES` must also be defined.
-
-This last symbol is required because if no transform functions are included in the build, then by default all flags related to FFT tables are ignored.
-

+ 0 - 2
Scripts/git/gen_pack.sh

@@ -119,8 +119,6 @@ PACK_BASE_FILES="
   ComputeGraph/cg/nodes/cpp/NullSink.h
   ComputeGraph/cg/nodes/cpp/OverlapAndAdd.h
   ComputeGraph/cg/nodes/cpp/SlidingBuffer.h
-  ComputeGraph/cg/nodes/cpp/StreamingSink.h
-  ComputeGraph/cg/nodes/cpp/StreamingSource.h
   ComputeGraph/cg/nodes/cpp/ToComplex.h
   ComputeGraph/cg/nodes/cpp/ToReal.h
   ComputeGraph/cg/nodes/cpp/Unzip.h

+ 0 - 6
Source/TransformFunctions/arm_rfft_f32.c

@@ -86,12 +86,6 @@ void arm_split_rifft_f32(
   @param[out]    pDst points to the output buffer
   @return        none
 
-  @par
-                   For the RIFFT, the source buffer must at least have length 
-                   fftLenReal + 2.
-                   The last two elements must be equal to what would be generated
-                   by the RFFT:
-                     (pSrc[0] - pSrc[1]) and 0.0f
  */
 
 void arm_rfft_f32(

+ 25 - 12
Source/TransformFunctions/arm_rfft_fast_f32.c

@@ -479,9 +479,8 @@ void merge_rfft_f32(
   @par
                    The real sequence is initially treated as if it were complex to perform a CFFT.
                    Later, a processing stage reshapes the data to obtain half of the frequency spectrum
-                   in complex format. Except the first complex number that contains the two real numbers
-                   X[0] and X[N/2] all the data is complex. In other words, the first complex sample
-                   contains two real values packed.
+                   in complex format. 
+
   @par
                    The input for the inverse RFFT should keep the same format as the output of the
                    forward RFFT. A first processing stage pre-process the data to later perform an
@@ -500,16 +499,21 @@ void merge_rfft_f32(
   @par
                    The FFT of a real N-point sequence has even symmetry in the frequency domain. 
                    The second half of the data equals the conjugate of the first half flipped in frequency. 
-                   Looking at the data, we see that we can uniquely represent the FFT using only N/2 complex numbers.
-                   These are packed into the output array in alternating real and imaginary components:
+                   This conjugate part is not computed by the float RFFT. As consequence, the output of 
+                   a N point real FFT should be a N//2 + 1 complex numbers so N + 2 floats.
+  @par
+                   It happens that the first complex of number of the RFFT output is actually
+                   all real. Its real part represents the DC offset.
+                   The value at Nyquist frequency is also real.
+
   @par
-                   X = { real[0], imag[0], real[1], imag[1], real[2], imag[2] ...
-                   real[(N/2)-1], imag[(N/2)-1 }
+                   Those two complex numbers can be encoded with 2 floats rather than using two numbers
+                   with an imaginary part set to zero.
   @par
-                   It happens that the first complex number (real[0], imag[0]) is actually
-                   all real. real[0] represents the DC offset, and imag[0] should be 0.
-                   (real[1], imag[1]) is the fundamental frequency, (real[2], imag[2]) is
-                   the first harmonic and so on.
+                   The implementation is using a trick so that the output buffer can be N float :
+                   the last real is packaged in the imaginary part of the first complex (since
+                   this imaginary part is not used and is zero).
+
   @par
                    The real FFT functions pack the frequency domain data in this fashion.
                    The forward transform outputs the data in this form and the inverse
@@ -519,7 +523,16 @@ void merge_rfft_f32(
                    samples.
   @par           Q15 and Q31
                    The real algorithms are defined in a similar manner and utilize N/2 complex
-                   transforms behind the scenes.
+                   transforms behind the scenes. 
+
+  @par
+                   But warning, contrary to the float version, the fixed point implementation
+                   RFFT is also computing the conjugate part (except for MVE version) so the 
+                   output buffer must be bigger.
+                   Also the fixed point RFFTs are not using any trick to pack the DC and Nyquist
+                   frequency in the same complex number.
+                   The RIFFT is not using the conjugate part but it is still using the Nyquist
+                   frequency value. The details are given in the documentation for the functions.
   @par
                    The complex transforms used internally include scaling to prevent fixed-point
                    overflows.  The overall scaling equals 1/(fftLen/2).

+ 5 - 7
Source/TransformFunctions/arm_rfft_q15.c

@@ -93,15 +93,13 @@ void arm_split_rifft_q15(
 | 8192        | 1.15          | 13.3           | 0                         |
   
   @par
-                   If the input buffer is of length N (fftLenReal), the output buffer must have length 2N + 2
-                   since it is containing the conjugate part. (N/2 + 1 + N/2 complex samples)
+                   If the input buffer is of length N (fftLenReal), the output buffer must have length 2N
+                   since it is containing the conjugate part (except for MVE version where N+2 is enough).
                    The input buffer is modified by this function.
   @par
-                   For the RIFFT, the source buffer must have at least length 
-                   fftLenReal + 2 which is (N/2 + 1 complex samples). It is not using the conjugate part.
-                   The last two elements must be equal to what would be generated
-                   by the RFFT:
-                     (pSrc[0] - pSrc[1]) >> 1 and 0
+                   For the RIFFT, the source buffer must have length N+2 since the Nyquist frequency value
+                   is needed but conjugate part is ignored. 
+                   It is not using the packing trick of the float version.
  */
 
 void arm_rfft_q15(

+ 6 - 8
Source/TransformFunctions/arm_rfft_q31.c

@@ -93,16 +93,14 @@ void arm_split_rifft_q31(
 | 8192        | 1.31          | 13.19          | 0                         |
 
   @par
-                   If the input buffer is of length N (fftLenReal), the output buffer must have length 2N + 2
-                   since it is containing the conjugate part. (N/2 + 1 + N/2 complex samples)
+                   If the input buffer is of length N (fftLenReal), the output buffer must have length 2N
+                   since it is containing the conjugate part (except for MVE version where N+2 is enough).
                    The input buffer is modified by this function.
   @par
-                   For the RIFFT, the source buffer must have at least length 
-                   fftLenReal + 2 which is (N/2 + 1 complex samples). It is not using the conjugate part.
-                   The last two elements must be equal to what would be generated
-                   by the RFFT:
-                     (pSrc[0] - pSrc[1]) >> 1 and 0
-
+                   For the RIFFT, the source buffer must have length N+2 since the Nyquist frequency value
+                   is needed but conjugate part is ignored. 
+                   It is not using the packing trick of the float version.
+                   
  */
 
 void arm_rfft_q31(

+ 4 - 0
cmsisdsp/cg/scheduler/ccode.py

@@ -41,6 +41,10 @@ def gencode(sched,directory,config):
     
     schedDescription=""
 
+    if isinstance(config.cOptionalArgs,list):
+       spc = " " * 30
+       config.cOptionalArgs = f",\n{spc}".join(config.cOptionalArgs)
+
     # Asychronous implies code array and switchCase
     if config.asynchronous:
        config.codeArray = True 

+ 41 - 10
cmsisdsp/cg/scheduler/description.py

@@ -74,7 +74,7 @@ class FifoBuffer:
 
 class FIFODesc:
     """A FIFO connecting two nodes"""
-    def __init__(self,fifoid,fifoClass):
+    def __init__(self,fifoid,fifoClass,fifoScale):
         # The FIFO is in fact just an array
         self.isArray=False 
         # FIFO length
@@ -93,6 +93,7 @@ class FIFODesc:
         # FIFO delay
         self.delay=0
         self.fifoClass = fifoClass
+        self.fifoScale = fifoScale
 
         # Used for liveliness analysis
         # To share buffers between FIFO in memory optimization
@@ -173,6 +174,9 @@ class Graph():
         self._allFIFOs = None 
         self._allBuffers = None
         self._FIFOClasses = {}
+        # In async mode, scaling factor for a given
+        # FIFO to override the global scaling factor
+        self._FIFOScale = {}
         # Topological sorting of nodes
         # computed during topology matrix
         # and used for some scheduling
@@ -224,9 +228,17 @@ class Graph():
 
     def connectDup(self,destination,outputIO,theId):
         if (destination[theId][1]!=0):
-            self.connectWithDelay(outputIO,destination[theId][0],destination[theId][1],dupAllowed=False,fifoClass=destination[theId][2])
+            self.connectWithDelay(outputIO,destination[theId][0],
+                                           destination[theId][1],
+                                           dupAllowed=False,
+                                           fifoClass=destination[theId][2],
+                                           fifoScale=destination[theId][3])
         else:
-            self.connect(outputIO,destination[theId][0],dupAllowed=False,fifoClass=destination[theId][2])
+            self.connect(outputIO,destination[theId][0],
+                                  dupAllowed=False,
+                                  fifoClass=destination[theId][2],
+                                  fifoScale=destination[theId][3]
+                                  )
 
 
 
@@ -289,6 +301,7 @@ class Graph():
                     destinations = []
                     delays = []
 
+
                     self._sortedNodes = None
                     self._sortedEdges = None
                     for f in fifo:
@@ -299,16 +312,19 @@ class Graph():
                         nodeb = f[1]
 
                         fifoClass = self.defaultFIFOClass
+                        fifoScale = 1.0
                         if (nodea,nodeb) in self._FIFOClasses:
                             fifoClass = self._FIFOClasses[(nodea,nodeb)]
 
-                        
+                        if (nodea,nodeb) in self._FIFOScale:
+                            fifoScale = self._FIFOScale[(nodea,nodeb)]
+
                         if (nodea,nodeb) in self._delays:
                            delay = self._delays[(nodea,nodeb)]
                         else:
                            delay = 0
 
-                        destinations.append((nodeb,delay,fifoClass))
+                        destinations.append((nodeb,delay,fifoClass,fifoScale))
 
                         nodea.fifo=None 
                         nodeb.fifo=None
@@ -327,6 +343,8 @@ class Graph():
                         del self._edges[(nodea,nodeb)]
                         if (nodea,nodeb) in self._FIFOClasses:
                             del self._FIFOClasses[(nodea,nodeb)]
+                        if (nodea,nodeb) in self._FIFOScale:
+                            del self._FIFOScale[(nodea,nodeb)]
                         if (nodea,nodeb) in self._delays:
                            del self._delays[(nodea,nodeb)]
 
@@ -351,7 +369,7 @@ class Graph():
 
                
 
-    def connect(self,nodea,nodeb,dupAllowed=True,fifoClass=None):
+    def connect(self,nodea,nodeb,dupAllowed=True,fifoClass=None,fifoScale = 1.0):
         if fifoClass is None:
             fifoClass = self.defaultFIFOClass
         # When connecting to a constant node we do nothing
@@ -374,6 +392,7 @@ class Graph():
                    nodeb.fifo=(nodea,nodeb)
                 self._edges[(nodea,nodeb)]=True
                 self._FIFOClasses[(nodea,nodeb)] = fifoClass
+                self._FIFOScale[(nodea,nodeb)] = fifoScale
                 if not (nodea.owner in self._nodes):
                    self._nodes[nodea.owner]=True
                 if not (nodeb.owner in self._nodes):
@@ -381,14 +400,14 @@ class Graph():
             else:
                 raise IncompatibleIO
 
-    def connectWithDelay(self,nodea,nodeb,delay,dupAllowed=True,fifoClass=None):
+    def connectWithDelay(self,nodea,nodeb,delay,dupAllowed=True,fifoClass=None,fifoScale=1.0):
         if fifoClass is None:
             fifoClass = self.defaultFIFOClass
         # We cannot connect with delay to a constant node
         if (isinstance(nodea,Constant)):
             raise CannotDelayConstantError
         else:
-            self.connect(nodea,nodeb,dupAllowed=dupAllowed,fifoClass=fifoClass)
+            self.connect(nodea,nodeb,dupAllowed=dupAllowed,fifoClass=fifoClass,fifoScale = fifoScale)
             self._delays[(nodea,nodeb)] = delay
     
     def __str__(self):
@@ -406,7 +425,19 @@ class Graph():
         for fifo in allFIFOs:
             edge = self._sortedEdges[fifo.fifoID]
             if config.asynchronous:
-               fifo.length = int(math.ceil(fifoLengths[fifo.fifoID] * (1.0 + 1.0*config.FIFOIncrease/100)))
+               if edge in self._FIFOScale:
+                  fifoScale = self._FIFOScale[edge]
+                  fifo.fifoScale = fifoScale
+               
+               if fifoScale != 1.0:
+                  scale = fifoScale
+               else:
+                 scale = 1.0
+                 if type(config.FIFOIncrease) == float:
+                    scale = config.FIFOIncrease
+                 else:
+                    scale = (1.0 + 1.0*config.FIFOIncrease/100)
+               fifo.length = int(math.ceil(fifoLengths[fifo.fifoID] * scale))
             else:
                fifo.length = fifoLengths[fifo.fifoID]
             src,dst = edge
@@ -866,7 +897,7 @@ class Graph():
         nbFIFOS = t.shape[0]
         allFIFOs = [] 
         for i in range(nbFIFOS):
-            allFIFOs.append(FIFODesc(i,self.defaultFIFOClass))
+            allFIFOs.append(FIFODesc(i,self.defaultFIFOClass,1.0))
 
         # Normalization vector
         # For static scheduling it is

+ 21 - 6
cmsisdsp/cg/scheduler/node.py

@@ -302,19 +302,34 @@ class BaseNode:
         else:
             return(0)
 
+    def _addLiteralItem(self,item):
+        if self.schedArgs:
+            self.schedArgs.append(ArgLiteral(item))
+        else:
+            self.schedArgs=[ArgLiteral(item)]
+
     def addLiteralArg(self,*ls):
         for l in ls:
-            if self.schedArgs:
-                self.schedArgs.append(ArgLiteral(l))
+            if isinstance(l, list):
+                for i in l:
+                    self._addLiteralItem(i)
             else:
-                self.schedArgs=[ArgLiteral(l)]
+                self._addLiteralItem(l)
+
+    def _addVariableItem(self,item):
+        if self.schedArgs:
+            self.schedArgs.append(VarLiteral(item))
+        else:
+            self.schedArgs=[VarLiteral(item)]
 
     def addVariableArg(self,*ls):
         for l in ls:
-            if self.schedArgs:
-                self.schedArgs.append(VarLiteral(l))
+            if isinstance(l, list):
+               for i in l:
+                  self._addVariableItem(i)
             else:
-                self.schedArgs=[VarLiteral(l)]
+              self._addVariableItem(l)
+           
 
     @property
     def isConstantNode(self):

+ 1 - 1
cmsisdsp/version.py

@@ -1,2 +1,2 @@
 # Python wrapper version
-__version__ = "1.9.5"
+__version__ = "1.9.6"

+ 41 - 140
setup.py

@@ -21,135 +21,24 @@ if sys.platform == 'win32':
 else:
   cflags = ["-Wno-attributes","-Wno-unused-function","-Wno-unused-variable","-Wno-implicit-function-declaration","-DCMSISDSP","-D__GNUC_PYTHON__"]
 
-transform = glob.glob(os.path.join(ROOT,"Source","TransformFunctions","*.c"))
-
-# Files are present when creating the source distribution
-# but they are not copied to the source distribution
-# When doing pip install those files are not prevent
-# and it should not fail
-try:
-  transform.remove(os.path.join(ROOT,"Source","TransformFunctions","TransformFunctions.c"))
-  transform.remove(os.path.join(ROOT,"Source","TransformFunctions","TransformFunctionsF16.c"))
-except:
-  pass
-
-support = glob.glob(os.path.join(ROOT,"Source","SupportFunctions","*.c"))
-
-try:
-  support.remove(os.path.join(ROOT,"Source","SupportFunctions","SupportFunctions.c"))
-  support.remove(os.path.join(ROOT,"Source","SupportFunctions","SupportFunctionsF16.c"))
-except:
-  pass
-
-fastmath = glob.glob(os.path.join(ROOT,"Source","FastMathFunctions","*.c"))
-try:
-  fastmath.remove(os.path.join(ROOT,"Source","FastMathFunctions","FastMathFunctions.c"))
-except:
-  pass
-
-filtering = glob.glob(os.path.join(ROOT,"Source","FilteringFunctions","*.c"))
-try:
-  filtering.remove(os.path.join(ROOT,"Source","FilteringFunctions","FilteringFunctions.c"))
-  filtering.remove(os.path.join(ROOT,"Source","FilteringFunctions","FilteringFunctionsF16.c"))
-except:
-  pass
-
-matrix = glob.glob(os.path.join(ROOT,"Source","MatrixFunctions","*.c"))
-try:
-  matrix.remove(os.path.join(ROOT,"Source","MatrixFunctions","MatrixFunctions.c"))
-  matrix.remove(os.path.join(ROOT,"Source","MatrixFunctions","MatrixFunctionsF16.c"))
-except:
-  pass
-
-statistics = glob.glob(os.path.join(ROOT,"Source","StatisticsFunctions","*.c"))
-try:
-  statistics.remove(os.path.join(ROOT,"Source","StatisticsFunctions","StatisticsFunctions.c"))
-  statistics.remove(os.path.join(ROOT,"Source","StatisticsFunctions","StatisticsFunctionsF16.c"))
-except:
-  pass
-
-complexf = glob.glob(os.path.join(ROOT,"Source","ComplexMathFunctions","*.c"))
-try:
-  complexf.remove(os.path.join(ROOT,"Source","ComplexMathFunctions","ComplexMathFunctions.c"))
-  complexf.remove(os.path.join(ROOT,"Source","ComplexMathFunctions","ComplexMathFunctionsF16.c"))
-except:
-  pass
-
-basic = glob.glob(os.path.join(ROOT,"Source","BasicMathFunctions","*.c"))
-try:
-  basic.remove(os.path.join(ROOT,"Source","BasicMathFunctions","BasicMathFunctions.c"))
-  basic.remove(os.path.join(ROOT,"Source","BasicMathFunctions","BasicMathFunctionsF16.c"))
-except:
-  pass
-
-controller = glob.glob(os.path.join(ROOT,"Source","ControllerFunctions","*.c"))
-try:
-  controller.remove(os.path.join(ROOT,"Source","ControllerFunctions","ControllerFunctions.c"))
-except:
-  pass
-
-common = glob.glob(os.path.join(ROOT,"Source","CommonTables","*.c"))
-try:
-  common.remove(os.path.join(ROOT,"Source","CommonTables","CommonTables.c"))
-  common.remove(os.path.join(ROOT,"Source","CommonTables","CommonTablesF16.c"))
-except:
-  pass
-
-interpolation = glob.glob(os.path.join(ROOT,"Source","InterpolationFunctions","*.c"))
-try:
-  interpolation.remove(os.path.join(ROOT,"Source","InterpolationFunctions","InterpolationFunctions.c"))
-  interpolation.remove(os.path.join(ROOT,"Source","InterpolationFunctions","InterpolationFunctionsF16.c"))
-except:
-  pass
-
-quaternion = glob.glob(os.path.join(ROOT,"Source","QuaternionMathFunctions","*.c"))
-try:
-  quaternion.remove(os.path.join(ROOT,"Source","QuaternionMathFunctions","QuaternionMathFunctions.c"))
-except:
-  pass
-
-distance = glob.glob(os.path.join(ROOT,"Source","DistanceFunctions","*.c"))
-try:
-  distance.remove(os.path.join(ROOT,"Source","DistanceFunctions","DistanceFunctions.c"))
-except:
-  pass
-
-bayes = glob.glob(os.path.join(ROOT,"Source","BayesFunctions","*.c"))
-try:
-  bayes.remove(os.path.join(ROOT,"Source","BayesFunctions","BayesFunctions.c"))
-except:
-  pass
-
-svm = glob.glob(os.path.join(ROOT,"Source","SVMFunctions","*.c"))
-try:
-  svm.remove(os.path.join(ROOT,"Source","SVMFunctions","SVMFunctions.c"))
-except:
-  pass
-
-window = glob.glob(os.path.join(ROOT,"Source","WindowFunctions","*.c"))
-try:
-  window.remove(os.path.join(ROOT,"Source","WindowFunctions","WindowFunctions.c"))
-except:
-  pass
-
 # Add dependencies
-transformMod = transform + common + basic + complexf + fastmath + matrix + statistics
-statisticsMod = statistics + common + fastmath + basic
-interpolationMod = interpolation + common
-filteringMod = filtering + common + support + fastmath + basic
-controllerMod = controller + common
-
-matrixMod = matrix + basic
-supportMod = support 
-complexfMod = complexf + fastmath + common + basic
-basicMod = basic
-quaternionMod = quaternion
-fastmathMod = basic + fastmath + common
-distanceMod = distance + common + basic + statistics + fastmath
-bayesMod = bayes + fastmath + common + statistics + basic
-svmMod = svm + fastmath + common + basic
-
-windowMod = window
+transformMod = [] # transform + common + basic + complexf + fastmath + matrix + statistics
+statisticsMod = [] # statistics + common + fastmath + basic
+interpolationMod = [] # interpolation + common
+filteringMod = [] # filtering + common + support + fastmath + basic
+controllerMod = [] # controller + common
+
+matrixMod = [] # matrix + basic
+supportMod = [] # support 
+complexfMod = [] # complexf + fastmath + common + basic
+basicMod = [] # basic
+quaternionMod = [] # quaternion
+fastmathMod = [] # basic + fastmath + common
+distanceMod = [] # distance + common + basic + statistics + fastmath
+bayesMod = [] # bayes + fastmath + common + statistics + basic
+svmMod = [] # svm + fastmath + common + basic
+
+windowMod = [] # window
 
 filteringMod.append(os.path.join("PythonWrapper","cmsisdsp_pkg","src","cmsisdsp_filtering.c"))
 matrixMod.append(os.path.join("PythonWrapper","cmsisdsp_pkg","src","cmsisdsp_matrix.c"))
@@ -209,35 +98,47 @@ window = list(filter(isnotmissing,list(filter(notf16, windowMod))))
 #  print(os.path.basename(l))
 #quit()
 
-def mkModule(name,srcs,funcDir,newCflags=[]):
+def mkModule(name,srcs,funcDir):
   localinc = os.path.join(ROOT,"Source",funcDir)
+  libdir = [os.path.join(ROOT,"PythonWrapper","build","bin_dsp")]
+  lib = ["CMSISDSP"]
+  extraobjs=[]
+  
+  if sys.platform.startswith('linux') or sys.platform.startswith('darwin'):
+    lib = []
+    extraobjs = [os.path.join(ROOT,"PythonWrapper","build_linux","bin_dsp","libCMSISDSP.a")]
+    libdir = []
+ 
   return(Extension(name,
                     sources = (srcs
                               )
                               ,
                     include_dirs =  [localinc] + includes + [numpy.get_include()],
-                    extra_compile_args = cflags + newCflags
+                    extra_compile_args = cflags,
+                    library_dirs = libdir,
+                    libraries=lib,
+                    extra_objects=extraobjs
                               ))
 
 flagsForCommonWithoutFFT=["-DARM_DSP_CONFIG_TABLES", 
     "-DARM_FAST_ALLOW_TABLES", 
     "-DARM_ALL_FAST_TABLES"]
 
-moduleFiltering = mkModule('cmsisdsp_filtering',filtering,"FilteringFunctions",flagsForCommonWithoutFFT)
+moduleFiltering = mkModule('cmsisdsp_filtering',filtering,"FilteringFunctions")
 moduleMatrix = mkModule('cmsisdsp_matrix',matrix,"MatrixFunctions")
 moduleSupport = mkModule('cmsisdsp_support',support,"SupportFunctions")
-moduleStatistics = mkModule('cmsisdsp_statistics',statistics,"StatisticsFunctions",flagsForCommonWithoutFFT)
+moduleStatistics = mkModule('cmsisdsp_statistics',statistics,"StatisticsFunctions")
 moduleComplexf= mkModule('cmsisdsp_complexf',complexf,"ComplexMathFunctions")
 moduleBasic = mkModule('cmsisdsp_basic',basic,"BasicMathFunctions")
-moduleController = mkModule('cmsisdsp_controller',controller,"ControllerFunctions",flagsForCommonWithoutFFT)
+moduleController = mkModule('cmsisdsp_controller',controller,"ControllerFunctions")
 moduleTransform = mkModule('cmsisdsp_transform',transform,"TransformFunctions")
-moduleInterpolation = mkModule('cmsisdsp_interpolation',interpolation,"InterpolationFunctions",flagsForCommonWithoutFFT)
+moduleInterpolation = mkModule('cmsisdsp_interpolation',interpolation,"InterpolationFunctions")
 moduleQuaternion = mkModule('cmsisdsp_quaternion',quaternion,"QuaternionMathFunctions")
-moduleFastmath = mkModule('cmsisdsp_fastmath',fastmath,"FastMathFunctions",flagsForCommonWithoutFFT)
-moduleDistance = mkModule('cmsisdsp_distance',distance,"DistanceFunctions",flagsForCommonWithoutFFT)
-moduleBayes = mkModule('cmsisdsp_bayes',bayes,"BayesFunctions",flagsForCommonWithoutFFT)
-moduleSVM = mkModule('cmsisdsp_svm',svm,"SVMFunctions",flagsForCommonWithoutFFT)
-moduleWindow = mkModule('cmsisdsp_window',window,"WindowFunctions",flagsForCommonWithoutFFT)
+moduleFastmath = mkModule('cmsisdsp_fastmath',fastmath,"FastMathFunctions")
+moduleDistance = mkModule('cmsisdsp_distance',distance,"DistanceFunctions")
+moduleBayes = mkModule('cmsisdsp_bayes',bayes,"BayesFunctions")
+moduleSVM = mkModule('cmsisdsp_svm',svm,"SVMFunctions")
+moduleWindow = mkModule('cmsisdsp_window',window,"WindowFunctions")
 
 
 
@@ -280,7 +181,7 @@ def build():
                         moduleWindow
                         ],
          include_package_data=True,
-         author = 'Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved.',
+         author = 'Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved.',
          author_email = 'christophe.favergeon@arm.com',
          url="https://github.com/ARM-software/CMSIS-DSP",
          python_requires='>=3.6',