testrfft_all.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import cmsisdsp as dsp
  2. import cmsisdsp.fixedpoint as f
  3. import numpy as np
  4. from scipy import signal
  5. import matplotlib.pyplot as plt
  6. import scipy.fft
  7. import colorama
  8. from colorama import init,Fore, Back, Style
  9. from numpy.testing import assert_allclose
  10. init()
  11. def printTitle(s):
  12. print("\n" + Fore.GREEN + Style.BRIGHT + s + Style.RESET_ALL)
  13. def printSubTitle(s):
  14. print("\n" + Style.BRIGHT + s + Style.RESET_ALL)
  15. def chop(A, eps = 1e-6):
  16. B = np.copy(A)
  17. B[np.abs(A) < eps] = 0
  18. return B
  19. nb = 32
  20. signal = np.cos(2 * np.pi * np.arange(nb) / nb)*np.cos(0.2*2 * np.pi * np.arange(nb) / nb)
  21. ref=scipy.fft.rfft(signal)
  22. invref = scipy.fft.irfft(ref)
  23. # Convert ref to CMSIS-DSP format
  24. referenceFloat=np.zeros(nb)
  25. # Replace complex datatype by real datatype
  26. referenceFloat[0::2] = np.real(ref)[:-1]
  27. referenceFloat[1::2] = np.imag(ref)[:-1]
  28. # Copy Nyquist frequency value into first
  29. # sample.This is just a storage trick so that the
  30. # output of the RFFT has same length as input
  31. # It is legacy behavior that we need to keep
  32. # for backward compatibility but it is not
  33. # very pretty
  34. referenceFloat[1] = np.real(ref[-1])
  35. printTitle("RFFT FAST F64")
  36. printSubTitle("RFFT")
  37. rfftf64=dsp.arm_rfft_fast_instance_f64()
  38. status=dsp.arm_rfft_fast_init_f64(rfftf64,nb)
  39. result = dsp.arm_rfft_fast_f64(rfftf64,signal,0)
  40. assert_allclose(referenceFloat,result)
  41. printSubTitle("RIFFT")
  42. rifftf64=dsp.arm_rfft_fast_instance_f64()
  43. status=dsp.arm_rfft_fast_init_f64(rifftf64,nb)
  44. result = dsp.arm_rfft_fast_f64(rifftf64,referenceFloat,1)
  45. assert_allclose(invref,result,atol=1e-15)
  46. printTitle("RFFT FAST F32")
  47. printSubTitle("RFFT")
  48. rfftf32=dsp.arm_rfft_fast_instance_f32()
  49. status=dsp.arm_rfft_fast_init_f32(rfftf32,nb)
  50. result = dsp.arm_rfft_fast_f32(rfftf32,signal,0)
  51. assert_allclose(referenceFloat,result,rtol=3e-6)
  52. printSubTitle("RIFFT")
  53. rifftf32=dsp.arm_rfft_fast_instance_f32()
  54. status=dsp.arm_rfft_fast_init_f32(rifftf32,nb)
  55. result = dsp.arm_rfft_fast_f32(rifftf32,referenceFloat,1)
  56. assert_allclose(invref,result,atol=1e-7)
  57. # Fixed point
  58. # Reference from fixed point arithmetric.
  59. # The RFFT are not packing the Nyquist frequency
  60. # real value in sample 0
  61. referenceFloat=np.zeros(nb+2)
  62. # Replace complex datatype by real datatype
  63. referenceFloat[0::2] = np.real(ref)
  64. referenceFloat[1::2] = np.imag(ref)
  65. printTitle("RFFT Q31")
  66. printSubTitle("RFFT")
  67. signalQ31 = f.toQ31(signal)
  68. rfftQ31=dsp.arm_rfft_instance_q31()
  69. status=dsp.arm_rfft_init_q31(rfftQ31,nb,0,1)
  70. resultQ31 = dsp.arm_rfft_q31(rfftQ31,signalQ31)
  71. # Drop the conjugate part which is not computed by scipy
  72. resultQ31 = resultQ31[:nb+2]
  73. resultF = f.Q31toF32(resultQ31) * nb
  74. assert_allclose(referenceFloat,resultF,rtol=1e-6,atol=1e-6)
  75. printSubTitle("RIFFT")
  76. rifftQ31=dsp.arm_rfft_instance_q31()
  77. status=dsp.arm_rfft_init_q31(rifftQ31,nb,1,1)
  78. # Apply CMSIS-DSP scaling
  79. referenceQ31 = f.toQ31(referenceFloat / nb)
  80. resultQ31 = dsp.arm_rfft_q31(rifftQ31,referenceFloat)
  81. resultF = f.Q31toF32(resultQ31)
  82. assert_allclose(invref,result,atol=1e-6)
  83. printTitle("RFFT Q15")
  84. printSubTitle("RFFT")
  85. signalQ15 = f.toQ15(signal)
  86. rfftQ15=dsp.arm_rfft_instance_q15()
  87. status=dsp.arm_rfft_init_q15(rfftQ15,nb,0,1)
  88. resultQ15 = dsp.arm_rfft_q15(rfftQ15,signalQ15)
  89. # Drop the conjugate part which is not computed by scipy
  90. resultQ15 = resultQ15[:nb+2]
  91. resultF = f.Q15toF32(resultQ15) * nb
  92. assert_allclose(referenceFloat,resultF,rtol=1e-6,atol=1e-2)
  93. printSubTitle("RIFFT")
  94. rifftQ15=dsp.arm_rfft_instance_q15()
  95. status=dsp.arm_rfft_init_q15(rifftQ15,nb,1,1)
  96. # Apply CMSIS-DSP scaling
  97. referenceQ15 = f.toQ15(referenceFloat / nb)
  98. resultQ15 = dsp.arm_rfft_q15(rifftQ15,referenceFloat)
  99. resultF = f.Q15toF32(resultQ15)
  100. assert_allclose(invref,result,atol=1e-2)