DIGILIGHT
spectrum.c
См. документацию.
1 
24 #include <avr/io.h>
25 #include "avr_helper.h"
26 #include <avr/pgmspace.h>
27 #include <avr/interrupt.h>
28 #include <stdlib.h>
29 #include <avr/eeprom.h>
30 #include "hardware.h"
31 #include "fft32.h"
32 #include "spectrum.h"
33 #include "global.h"
34 
35 #if defined(DOUBLE_BUFFERED_SAMPLING)
36 #define FFT_BUFFER_SIZE (FFT_N * 2L)
37 #else
38 #define FFT_BUFFER_SIZE FFT_N
39 #endif
40 
42 static complex_t buffer_fft_a[FFT_BUFFER_SIZE];
43 #if defined(DOUBLE_BUFFERED_SAMPLING)
44 static complex_t *buffer_fft_b = buffer_fft_a + FFT_N;//[FFT_N];
47 static complex_t *buf_out = buffer_fft_a + FFT_N;//buffer_fft_b;
48 #endif
49 static complex_t *buf_in = buffer_fft_a;
51 
58 void* get_reserved_memory(uint16_t *size){
59  if(!lock_input) return NULL;
60  if(*size > (FFT_BUFFER_SIZE*sizeof(complex_t)))
61  *size = (FFT_BUFFER_SIZE*sizeof(complex_t));
62  return buffer_fft_a;
63 }
64 
66 static __flash const int16_t *window_ptr = tbl32_window;
68 static volatile uint8_t adc_count;
69 
70 #if defined(_FFT_DEBUG_)
71 int16_t real_offset;
72 #endif
73 
78 ISR(ADC_vect){
79 #if defined(_FFT_DEBUG_)
80  real_offset = ADC;
81 #endif
82  int16_t v = ADC - cfg.dc_offset;
83 
84  v = fmuls_f(v, *window_ptr);
85 
86  buf_in->r = v; // заносим его в массив БПФ
87  buf_in->i = v;
88 
89  window_ptr++;
90  buf_in++; // сдвигаем указатель на следующий элемент
91  // т.к. запуск АЦП по событию возможен только если флаг соответствующего события
92  // сброшен принудительно ДО НАСТУПЛЕНИЯ СОБЫТИЯ, сбрасываем флаг компаратора таймера
93  TIFR = _BV(OCF0);
94  // работаем до тех пор, пока не соберем заданное количество семлов
95  if(!--adc_count){
96  TCCR0 = 0; // остановить таймер, когда буфер заполнен
97  }
98 }
99 
106 INIT(7){
107  DDR(ADC_PORT) &= ~_BV(ADC_PIN);
108 
109  SFIOR = _BV(ADTS1) | _BV(ADTS0);
110 
111  ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADATE) | ADC_DIV_32;
112  //ADMUX = _BV(ADLAR) | ADC_REF_INT_WITH_ECAP; // встроенный AREF
113  ADMUX = _BV(ADLAR) | ADC_REF_AVCC; // особенность схемы "плавающее" смещение
114  OCR0 = 250;
115 
116  sei();
117 }
118 
124 void sample_and_fft(void){
125  static uint8_t buf_id;
126 
127 #if defined(DOUBLE_BUFFERED_SAMPLING)
128 
129  while(TCCR0); // ждем, пока он не остановится
130 
131  // меняем буферы местами
132  if(buf_id){
133  buf_in = buffer_fft_b;
134  buf_out = buffer_fft_a;
135  } else {
136  buf_in = buffer_fft_a;
137  buf_out = buffer_fft_b;
138  }
139 #else
140  buf_in = buffer_fft_a;
141 #endif
142 
143  buf_id = !buf_id;
144 
145  adc_count = FFT_N;
146  window_ptr = tbl32_window;
147  TCNT0 = 0;
148 
149  TCCR0 = _BV(WGM01) | TIMER_CLK_DIV_8; // запускаем 0-й таймер
150 
151 #if !defined(DOUBLE_BUFFERED_SAMPLING)
152  while(TCCR0); // ждем, пока он не остановится
153  // обсчитываем только что полученный буфер, пока другой заполняется семплами
154  fft32_execute(buffer_fft_a); // выполняем БПФ над данными
155 #else
156  // обсчитываем только что полученный буфер, пока другой заполняется семплами
157  fft32_execute(buf_out); // выполняем БПФ над данными
158 #endif
159 }
160 
166 uint16_t get_result_fft(uint8_t index){
167  uint16_t ix;
168  __flash const int16_t *revers = tbl32_bitrev;
169 
170  revers += index; // вычисляем указатель на индекс ПЕРЕСТАНОВКИ
171  ix = *revers; // считываем индекс
172  return (
173 #if defined(DOUBLE_BUFFERED_SAMPLING)
174  // возвращаем из массива БПФ значение по индексу перестановки
175  fsqrt(buf_out[ix].r,buf_out[ix].i)
176 #else
177  fsqrt(buffer_fft_a[ix].r,buffer_fft_a[ix].i)
178 #endif
179  // но перед этим младшие (шумные) биты отбрасываются и амплитуда уменьшается
180  // путем сдвига
181  & 0xFFC0)>> 1;
182 }
183 
#define ADC_PIN
номер пина порта АЦП для входного сигнала
Definition: hardware.h:19
void sample_and_fft(void)
Захват семплов и обработка методом FFT.
Definition: spectrum.c:124
uint8_t lock_input
Definition: main.c:220
Общие описания
uint16_t get_result_fft(uint8_t index)
получение запрошенной гармоники FFT.
Definition: spectrum.c:166
ISR(ADC_vect)
Definition: spectrum.c:78
Описания для модуля реализации спектрального анализа
Аппаратно-зависимые определения
#define DOUBLE_BUFFERED_SAMPLING
Definition: spectrum.h:22
#define ADC_PORT
символ порта АЦП
Definition: hardware.h:17
void * get_reserved_memory(uint16_t *size)
запрос резервной памяти
Definition: spectrum.c:58
INIT(7)
Definition: spectrum.c:106