| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- API
- ===
- .. highlight:: python
- The idea is to follow as closely as possible the CMSIS-DSP API to ease the migration to the final implementation on a board.
- First you need to import the module::
- import cmsisdsp as dsp
- If you use numpy::
- import numpy as np
- If you use scipy signal processing functions::
- from scipy import signal
- Standard APIs
- *************
- .. code-block:: C
-
- void arm_add_f32(
- const float32_t * pSrcA,
- const float32_t * pSrcB,
- float32_t * pDst,
- uint32_t blockSize);
- .. py:function:: dsp.arm_add_f32(pSrcA,pSrcB)
- Return a list of random ingredients as strings.
- :param pSrcA: array.
- :type pSrcA: NumPy array
- :param pSrcB: array.
- :type pSrcB: NumPy array
- :return: array.
- :rtype: NumPy array
- Example::
- import cmsisdsp as dsp
- r = dsp.arm_add_f32([1.,2,3],[4.,5,7])
- You can use a CMSIS-DSP function with numpy arrays: ::
- r = dsp.arm_add_f32(np.array([1.,2,3]),np.array([4.,5,7]))
- The result of a CMSIS-DSP function will always be a numpy array whatever the arguments were (numpy array or list).
- Functions with instance arguments
- *********************************
- When the CMSIS-DSP function is requiring an instance data structure, it is just a bit more complex to use it:
- First you need to create this instance::
- import cmsisdsp as dsp
- firf32 = dsp.arm_fir_instance_f32()
- .. code-block:: C
- void arm_fir_init_f32(
- arm_fir_instance_f32 * S,
- uint16_t numTaps,
- const float32_t * pCoeffs,
- float32_t * pState,
- uint32_t blockSize);
- .. py:function:: dsp.arm_fir_init_f32(S,numTaps,pCoeffs,pState)
- Return a list of random ingredients as strings.
- :param S: f32 instance.
- :type S: int
- :param pCoeffs: array.
- :type pCoeffs: NumPy array
- :param pState: array.
- :type pState: NumPy array
- :return: array.
- :rtype: NumPy array
- Example of use::
- dsp.arm_fir_init_f32(firf32,3,[1.,2,3],[0,0,0,0,0,0,0])
- The third argument in this function is the state. Since all arguments (except the instance ones) are read-only in this Python API, this state will never be changed ! It is just used to communicate the length of the state array which must be allocated by the init function. This argument is required because it is present in the CMSIS-DSP API and in the final C implementation you'll need to allocate a state array with the right dimension.
- Since the goal is to be as close as possible to the C API, the API is forcing the use of this argument.
- The only change compared to the C API is that the size variables (like blockSize for filter) are computed automatically from the other arguments. This choice was made to make it a bit easier the use of numpy array with the API.
- Now, you can check that the instance was initialized correctly::
- .. code-block:: python
- print(firf32.numTaps())
- The filter can then be called:
- .. code-block:: C
- void arm_fir_f32(
- const arm_fir_instance_f32 * S,
- const float32_t * pSrc,
- float32_t * pDst,
- uint32_t blockSize);
- .. py:function:: dsp.arm_fir_f32(S,pSrc)
- Return a list of random ingredients as strings.
- :param S: f32 instance.
- :type S: int
- :param pSrc: array of input samples.
- :type pSrc: NumPy array
- :return: array.
- :rtype: NumPy array
- Then, you can filter with CMSIS-DSP::
- print(dsp.arm_fir_f32(firf32,[1,2,3,4,5]))
- The size of this signal should be blockSize. blockSize was inferred from the size of the state array : numTaps + blockSize - 1 according to CMSIS-DSP. So here the signal must have 5 samples.
- If you want to filter more than 5 samples, then you can just call the function again. The state variable inside firf32 will ensure that it works like in the CMSIS-DSP C code::
- print(dsp.arm_fir_f32(firf32,[6,7,8,9,10]))
- If you want to compare with scipy it is easy but warning : coefficients for the filter are in opposite order in scipy ::
- filtered_x = signal.lfilter([3,2,1.], 1.0, [1,2,3,4,5,6,7,8,9,10])
- print(filtered_x)
- FFT
- ***
- The CMSIS-DSP cfft is requiring complex signals with a specific layout in memory.
- To remain as close as possible to the C API, we are not using complex numbers in the wrapper. So a complex signal must be converted into a real one. A function like the bewlo one can be used::
- def imToReal1D(a):
- ar=np.zeros(np.array(a.shape) * 2)
- ar[0::2]=a.real
- ar[1::2]=a.imag
- return(ar)
- In the same way, the return array from the CMSIS-DSP FFT will not be containing complex Python scalars. It must be converted back with a function like::
- def realToIm1D(ar):
- return(ar[0::2] + 1j * ar[1::2])
- Then, the utilisation of the API si very similar to what was done for the FIR example:
- Then, you create the FFT instance with::
- cfftf32=dsp.arm_cfft_instance_f32()
- You initialize the instance with the init function ::
- status=dsp.arm_cfft_init_f32(cfftf32, nb)
- print(status)
- You convert the complex signal to the format expected by the wrapper::
- signalR = imToReal1D(signal)
- You compute the FFT of the signal with::
- resultR = dsp.arm_cfft_f32(cfftf32,signalR,0,1)
- You convert back to a complex format to compare with scipy::
- resultI = realToIm1D(resultR)
- print(resultI)
- Matrix
- ******
- For matrix, the instance variables are masked by the Python API. We decided that for matrix only there was no use for having the CMSIS-DSP instance visibles since they contain the same information as the numpy array (samples and dimension).
- So to use a CMSIS-DSP matrix function, it is very simple::
- a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]])
- b=np.array([[1.,2,3],[5.1,6,7],[9.1,10,11],[5,8,4]])
- Numpy result as reference::
- print(np.dot(a , b))
- CMSIS-DSP result::
- v=dsp.arm_mat_mult_f32(a,b)
- print(v)
- In a real C code, a pointer to a data structure for the result v would have to be passed as argument of the function.
- The C API is:
- .. code-block:: C
- arm_status arm_mat_mult_f32(
- const arm_matrix_instance_f32 * pSrcA,
- const arm_matrix_instance_f32 * pSrcB,
- arm_matrix_instance_f32 * pDst);
- The Python API is:
- .. py:function:: dsp.arm_mat_mult_f32(pSrcA,pSrcB)
- Return the matrix product pSrcA * pSrcB
- :param pSrcA: array of input samples.
- :type pSrcA: NumPy array
- :param pSrcB: array of input samples.
- :type pSrcB: NumPy array
- :return: the matrix product.
- :rtype: NumPy array
|