afsk_demodulator.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * afsk_demodulator.c
  3. *
  4. * Created on: Sep 10, 2019
  5. * Author: curiousmuch
  6. */
  7. #include "stdio.h"
  8. #include "stdint.h"
  9. #include "math.h"
  10. #include "afsk_demodulator.h"
  11. /* Public Variables */
  12. int8_t window[WINDOW_SIZE]; // sliding window
  13. float coeff0 = 0, coeff1 = 0; // goerztel coefficients
  14. float lpf_coef0[5], lpf_coef1[5]; // lpf coefficients
  15. float lpf_delay0[2], lpf_delay1[2]; // lpf delay line
  16. int raw_bit = 0; // afsk demodulator result
  17. /* Private Functions */
  18. void goertzel_init(float freq0, float freq1, float *coeff0, float *coeff1)
  19. {
  20. float normalizedfreq;
  21. // calculate coeff0
  22. normalizedfreq = freq0 / SAMPLEFREQUENCY;
  23. *coeff0 = (float) 2*cos(2*M_PI*normalizedfreq);
  24. // calculate coeff1
  25. normalizedfreq = freq1 / SAMPLEFREQUENCY;
  26. *coeff1 = (float) 2*cos(2*M_PI*normalizedfreq);
  27. }
  28. float goertzel_filter(int8_t samples[], float coeff, unsigned int N)
  29. {
  30. float s_prev = 0.0;
  31. float s_prev2 = 0.0;
  32. float power, s;
  33. unsigned int i;
  34. for (i=0; i<N; i++) {
  35. s = samples[i] + coeff * s_prev - s_prev2;
  36. s_prev2 = s_prev;
  37. s_prev = s;
  38. }
  39. power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2;
  40. return power;
  41. }
  42. void window_init(void)
  43. {
  44. // TODO: setup dynamic allocation
  45. for(unsigned int i=0;i<WINDOW_SIZE;i++)
  46. {
  47. window[i] = 0;
  48. }
  49. }
  50. void window_add(int8_t sample)
  51. {
  52. for(uint32_t i=0;i<(WINDOW_SIZE-1);i++)
  53. {
  54. window[(WINDOW_SIZE-1)-i] = window[(WINDOW_SIZE-2)-i];
  55. }
  56. window[0] = sample;
  57. }
  58. int8_t* window_get(void)
  59. {
  60. return window;
  61. }
  62. unsigned int window_get_size(void)
  63. {
  64. return sizeof(window);
  65. }
  66. void dsps_biquad_gen_lpf_f32(float *coeffs, float f, float qFactor)
  67. {
  68. if (qFactor <= 0.0001) {
  69. qFactor = 0.0001;
  70. }
  71. float Fs = 1;
  72. float w0 = 2 * M_PI * f / Fs;
  73. float c = cosf(w0);
  74. float s = sinf(w0);
  75. float alpha = s / (2 * qFactor);
  76. float b0 = (1 - c) / 2;
  77. float b1 = 1 - c;
  78. float b2 = b0;
  79. float a0 = 1 + alpha;
  80. float a1 = -2 * c;
  81. float a2 = 1 - alpha;
  82. coeffs[0] = b0 / a0;
  83. coeffs[1] = b1 / a0;
  84. coeffs[2] = b2 / a0;
  85. coeffs[3] = a1 / a0;
  86. coeffs[4] = a2 / a0;
  87. return;
  88. }
  89. void dsps_biquad_f32_ansi(const float *input, float *output, int len, float *coef, float *w)
  90. {
  91. for (int i = 0 ; i < len ; i++) {
  92. float d0 = input[i] - coef[3] * w[0] - coef[4] * w[1];
  93. output[i] = coef[0] * d0 + coef[1] * w[0] + coef[2] * w[1];
  94. w[1] = w[0];
  95. w[0] = d0;
  96. }
  97. return;
  98. }
  99. void lpf_init(void)
  100. {
  101. // generate filter coef
  102. dsps_biquad_gen_lpf_f32(lpf_coef0, 0.10, 0.54119610);
  103. dsps_biquad_gen_lpf_f32(lpf_coef1, 0.10, 1.3065630);
  104. // setup delay line and lpf_input window
  105. int i;
  106. for(i=0;i<2;i++)
  107. {
  108. lpf_delay0[i] = 0;
  109. lpf_delay1[i] = 0;
  110. }
  111. }
  112. float lpf_baseband(float input)
  113. {
  114. float output, temp;
  115. dsps_biquad_f32_ansi(&input, &temp, 1, lpf_coef0, lpf_delay0);
  116. dsps_biquad_f32_ansi(&temp, &output, 1, lpf_coef1, lpf_delay1);
  117. return output;
  118. }
  119. /* Public Functions */
  120. void afsk_demod_init(uint32_t sample_rate, uint32_t symbol0_freq, uint32_t symbol1_freq)
  121. {
  122. goertzel_init(symbol0_freq, symbol1_freq, &coeff0, &coeff1);
  123. window_init();
  124. lpf_init();
  125. }
  126. #define THRESHOLD 5
  127. uint8_t afsk_demod_add_sample(int8_t sample)
  128. {
  129. float E_s0, E_s1, lpf_output;
  130. window_add(sample);
  131. E_s0 = goertzel_filter(window, coeff0, WINDOW_SIZE);
  132. E_s1 = goertzel_filter(window, coeff1, WINDOW_SIZE);
  133. lpf_output = lpf_baseband((E_s0 - E_s1));
  134. if (lpf_output > THRESHOLD)
  135. {
  136. raw_bit = 1;
  137. //enable_debug_IO(DEBUG_2);
  138. }
  139. else if (lpf_output < THRESHOLD)
  140. {
  141. raw_bit = 0;
  142. //disable_debug_IO(DEBUG_2);
  143. }
  144. return raw_bit; // if not above threshold keep old state.
  145. }