DIGILIGHT
main.c
См. документацию.
1 
34 #include <avr/io.h>
35 #include "avr_helper.h"
36 #include <string.h>
37 #include <util/crc16.h>
38 #include <stdlib.h>
39 #include <avr/interrupt.h>
40 #include "spectrum.h"
41 #include "ws2812.h"
42 #include "global.h"
43 #include "control.h"
44 #include "main_effect.h"
45 #include "pixel.h"
46 #include "power_control.h"
47 
48 config_t cfg;
49 
58 static void init_rand(void){
59  uint8_t *ptr = (void*)RAMSTART;
60  uint16_t seed;
61 
62  for(uint16_t i=0; i < RAMEND; i++){
63  seed = _crc16_update(seed, *ptr++);
64  }
65  srand(seed);
66 }
67 
68 #define DELTA_10MS 20000
69 
70 static volatile uint8_t done_wait;
71 
72 ISR(TIMER1_COMPA_vect){
73  OCR1A = TCNT1 + DELTA_10MS;
74  done_wait = 1;
75 }
76 
78 INIT(7){
79  init_rand();
80  // 10 мс таймер
81  TIMSK |= _BV(OCIE1A);
82  OCR1A = DELTA_10MS;
83  TIFR = _BV(OCF1A);
84 
85 #if defined(_DEBUG_)
86  // индикатор ожидания
87  DDR(DEBUG_LED_PORT) |= _BV(DEBUG_LED_PIN0);
88  debug_led_off();
89 #endif
90 }
91 
92 
104 static void synchronize(void){
105  // Флаг прерывания по совпаднию таймера устанавливается каждые 10 мс
106  while(!done_wait){
107  // светим, пока ждем
108  debug_led_on();
109  }
110  debug_led_off();
111  done_wait = 0;
112 }
113 
114 // степень усреднения
115 #define AVE 64
116 
117 typedef struct ave_t{
118  uint8_t buf[AVE];
119  uint8_t cur;
120 }ave_t;
121 
128 static uint8_t average(ave_t *ave, uint8_t v){
129  uint16_t sum=0;
130 
131  ave->buf[ave->cur++] = v;
132  if(ave->cur >= AVE) ave->cur = 0;
133 
134  for(uint8_t i=0; i<AVE; i++)
135  sum += ave->buf[i];
136 
137  return sum / AVE;
138 }
139 
140 // Single Pole Bandpass IIR Filter by DAMIAN PECKETT
141 static float bassFilter(float sample) {
142  static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
143  xv[0] = xv[1]; xv[1] = xv[2];
144  xv[2] = sample / 9.1f;
145  yv[0] = yv[1]; yv[1] = yv[2];
146  yv[2] = (xv[2] - xv[0])
147  + (-0.7960060012f * yv[0]) + (1.7903124146f * yv[1]);
148  return yv[2];
149 }
150 
157 static void beat_detect(signal_t *s){
158  static uint8_t old=0;
159  uint8_t trigger;
160  // выделение инфра-НЧ сигнала
161  int16_t new = bassFilter(s->harmonics[F_DC]);
162 
163  if(new > (300+s->average_vol)) trigger = 1;
164  if(new < -10) trigger = 0;
165 
166  // индикатор ритма только в момент возникновения инфра-НЧ импульса
167  s->beat = !old && trigger;
168  old = trigger;
169 }
170 
173 
174 static uint32_t sum_harmonics(signal_t *s, uint8_t from, uint8_t to){
175  uint32_t result = 0;
176  for(; from <= to; from++){
177  result += s->harmonics[from];
178  }
179  return result;
180 }
181 
182 static uint32_t get_band_power(signal_t *s, uint16_t band){
183  uint32_t result = 0;
184  uint8_t i = 0;
185 
186  for(uint16_t f=1; f; f <<= 1, i++){
187  result += band & f ? s->harmonics[i] : 0;
188  }
189  return result;
190 }
191 
192 static void prepare_samples(signal_t *s){
193  static ave_t v_ave;
194 
195  // считываем гармоники
196  for(uint8_t i=F_DC; i<F_CNT; i++)
197  s->harmonics[i] = get_result_fft(i);
198 
199  // вычисляем громкость
200  //s->peak_volume = lock_input ? 0 : sum_harmonics(s, F_250_HZ, F_3800_HZ) / 6;
201  s->peak_volume = get_band_power(s, BAND_FULL) / 6;
202  s->average_vol = average(&v_ave, s->peak_volume);
203  //s->average_vol = average(&v_ave, s->harmonics[F_DC]);
204 
205  // вычисляем мощность полос
206  s->band[LF] = sum_harmonics(s, F_250_HZ, F_500_HZ);
207  s->band[MF] = sum_harmonics(s, F_750_HZ, F_1500_HZ);
208  s->band[HF] = sum_harmonics(s, F_2800_HZ, F_3800_HZ) + s->harmonics[F_3800_HZ];
209 /*
210  s->band[LF] = get_band_power(s, cfg.band_mask[LF]);
211  s->band[MF] = get_band_power(s, cfg.band_mask[MF]);
212  s->band[HF] = get_band_power(s, cfg.band_mask[HF]);
213 */
214 
215  // вычисление ритма
216  beat_detect(&music);
217 }
218 
219 // блокирующий анализ сигнала флажок
220 uint8_t lock_input = 0;
221 
222 MAIN(){
223  uint8_t nosleep;
224 
225  while(1){
226  power_off();
227  nosleep = 1;
229 
230  do{
231  if(!lock_input){
232  // получение семплов и FFT-разложение
233  sample_and_fft(); // 1 mS (7 mS without DOUBLE_BUFFERED_SAMPLING)
234  // подготовка параметров мелодии
235  prepare_samples(&music); // ~1 mS
236  }
237  // затухание
238  fade(); // < 60 uS
239  // формирование светового эффекта
240  execute_effect(&music);
241  // обновление линейки светодиодов
242  ws2812_show(); // ~1.6 mS
243  // управление
244  do_control(&music); // ~2 uS
245  // автоотключение питания
246  nosleep = !power_timeout(&music);
247  // синхронизация
248  synchronize(); //
249  } while(nosleep);
250  }
251 }
252 
#define DEBUG_LED_PORT
Символ порта индикации текущего состояния (отладка)
Definition: hardware.h:22
void do_control(signal_t *s)
Обработка органов управления
Definition: control.c:254
Гармоника 250 Гц
Definition: global.h:28
Гармоника 2750 Гц
Definition: global.h:38
signal_t music
Параметры мелодии
Definition: main.c:172
void sample_and_fft(void)
Захват семплов и обработка методом FFT.
Definition: spectrum.c:124
volume_t average_vol
средняя громкость
Definition: global.h:74
power_t band[BAND_CNT]
"мощности" полос сигнала
Definition: global.h:75
структура конфигурации устройства
Definition: global.h:84
Общие описания
uint16_t get_result_fft(uint8_t index)
получение запрошенной гармоники FFT.
Definition: spectrum.c:166
Постоянная составляющая (инфранизкие частоты)
Definition: global.h:27
структура параметров звукового сигнала
Definition: global.h:72
Гармоника 3750 Гц
Definition: global.h:42
void fade(void)
Автоматическое изменение яркости всех пикселов
Definition: pixel.c:49
uint16_t harmonics[F_CNT]
амплитуды всех гармоник сигнала
Definition: global.h:77
Гармоника 1500 Гц
Definition: global.h:33
сервисный модуль для реализации эффектов Набор вспомогательных функций для базовых манипуляций над це...
void ws2812_show(void)
обновление ленты светододов
Definition: ws2812.c:45
Описания для модуля реализации спектрального анализа
void reset_power_timeout(void)
сброс таймаута автоотключения питания
Definition: power_control.c:49
Управление питанием
Гармоника 750 Гц
Definition: global.h:30
uint8_t power_timeout(signal_t *s)
проверка таймаута автовыключения питания
Definition: power_control.c:30
#define BAND_FULL
битовые маски частот спектра, учитываемые при расчете уровня сигнала (все, кроме DC) ...
Definition: global.h:64
Общее количество гармоник
Definition: global.h:44
volume_t peak_volume
пиковая громкость
Definition: global.h:73
void power_off(void)
выключение питания
Definition: power_control.c:64
Интерфейс визуальных эффектов
описания урганов управления
uint8_t beat
детектор ритма
Definition: global.h:76
INIT(7)
инициализация периферии
Definition: main.c:78
Гармоника 500 Гц
Definition: global.h:29
void execute_effect(signal_t *s)
Рендеринг эффекта
Definition: main_effect.c:63
аппаратные особенности подключения WS2812.
uint8_t lock_input
Definition: main.c:220