DIGILIGHT
sparkler_effect.c
См. документацию.
1 
20 #include <avr/io.h>
21 #include "../avr_helper.h"
22 #include <stdlib.h>
23 #include <avr/eeprom.h>
24 #include "../color_transform.h"
25 #include "../global.h"
26 #include "../pixel.h"
27 #include "../main_effect.h"
28 #include <string.h>
33 static void _effect(signal_t *s);
34 static void _stop(void);
35 static void _start(void);
36 static void _save(void);
37 static preset_result_t _preset(int8_t d);
38 
39 // Название эффекта, не более 16 знаков
40 static __flash const char _name[] = "SPARKLER";
41 // Описание эффекта. Можно не менять, можно для оптимизации заменить
42 // отсутствующие функции на NULL
43 static flash_effect_t effect_def = {
44  .name = _name,
45  .start = _start, // может быть NULL
46  .work = _effect, // это значение не может быть NULL!
47  .preset = _preset // может быть NULL
48 };
49 
50 // количество одновременно летящих огней, не более
51 #define LIGHT_LIVE_CNT 10
52 
53 typedef struct{
54  uint8_t pix; //< номер пиксела
55  uint8_t color_id; //< цвет огонька
56  uint8_t live; //< время жизни
57  uint8_t speed; //< скорость полёта
58  uint8_t div; //< счетчик скорости
59 } light_t;
60 
61 typedef struct{
62  uint8_t live; //< текущее количество огней
63  uint8_t h;
64  light_t lights[LIGHT_LIVE_CNT]; //< массив огней
65  uint16_t prev_peak[F_CNT]; //< массив предыдущего уровня
66 } static_parameter_t;
67 
68 static static_parameter_t par;
69 
70 static static_parameter_t *param=&par;
71 
72 INIT(7){
73  // регистрация эффекта - правильно указать тип эффекта!
74  register_effect(FOREGROUND_EFFECT, &effect_def);
75 }
76 
77 
78 #define MIN_SPEED 5
79 
80 static uint8_t get_speed(uint16_t ha){
81  uint8_t result = MIN_SPEED;
82  while(ha && result){
83  result--;
84  ha >>= 1;
85  }
86  return result + 1;
87 }
88 
89 // главная функция эффекта - вызывается 100 раз в секунду для рендеринга
90 static void _effect(signal_t *s){
91  // прежде всего - обеспечиваем полет огней
92  for(uint8_t i=0; i<LIGHT_LIVE_CNT; i++){
93  // для каждого живого огонька
94  if(param->lights[i].live){
95  // если яркость упала до 0 - тоже убиваем огонь
96  if(pixels[param->lights[i].pix].bright == 0){
97  param->live--;
98  continue;
99  }
100  //*/
101  // если скорость позволяет
102  if(!--param->lights[i].div){
103  // обновляем делитель скорости
104  param->lights[i].div = param->lights[i].speed;
105 
106  // уменьшаем время жизни
107  param->lights[i].live--;
108 
109  if(++param->lights[i].pix >= PIXEL_CNT){
110  // если улетели за пределы
111  param->lights[i].live = 0;
112  }
113  }
114  // если истекло - уменьшаем общий счетчик огней
115  if(param->lights[i].live == 0) param->live--;
116  }
117  }
118  if(1){
119  // теперь анализ пиков и добавление новых огней
120  int16_t delta;
121 
122  delta = s->harmonics[param->h] - param->prev_peak[param->h];
123  if(delta > 50){
124  param->prev_peak[param->h] = s->harmonics[param->h];
125  // ищем свободный огонь в массиве
126  uint8_t n;
127  for(n=0; n<LIGHT_LIVE_CNT; n++){
128  if(param->lights[n].live == 0){
129  // нашли, его номер n
130  param->lights[n].speed = get_speed(s->harmonics[param->h] / 10);
131  param->lights[n].speed++; // чтобы не было 0
132  param->lights[n].live = rand() % PIXEL_CNT;
133  param->lights[n].color_id = param->h-1;
134  param->lights[n].div = param->lights[n].speed;
135  param->lights[n].pix = 0;
136  if(param->lights[n].live) param->live++;
137  break;
138  }
139  }
140  }
141  // уменьшаем порог
142  if(param->prev_peak[param->h] >= 5) param->prev_peak[param->h] -= 5;
143 
144  param->h += 2;
145  if(param->h >= F_CNT) param->h = 1;
146  if(param->prev_peak[param->h] >= 5) param->prev_peak[param->h] >>= 1;
147  }
148  // теперь рисуем все огни
149 
150  off_all_pixels();
151  for(uint8_t i=0; i<LIGHT_LIVE_CNT; i++){
152  if(param->lights[i].live){
153  set_fix_color(param->lights[i].pix, param->lights[i].color_id);
154  bright_ctrl(param->lights[i].pix, 255, 10);
155  }
156  }
157 }
158 
159 // начало эффекта - вызывается после того, как завершился другой эффект и
160 // в том случае, если функция _preset вернула значение, отличное от PRESET_NOTHING
161 static void _start(void){
162  memset(param, 0, sizeof(static_parameter_t));
163  param->h = 1;
164 }
165 
166 // смена пресета эффекта - вызывается в произвольные моменты
167 static preset_result_t _preset(int8_t d){
168  return PRESET_NOTHING;
169 }
170 
void bright_ctrl(uint8_t id, uint8_t bright, int8_t delta)
Управление яркостью
Definition: pixel.c:95
void off_all_pixels(void)
Выключение всех пикселов
Definition: pixel.c:162
нет пресетов
Definition: main_effect.h:58
const __flash effect_t flash_effect_t
тип описания эффекта, размещенного во FLASH.
Definition: main_effect.h:79
структура параметров звукового сигнала
Definition: global.h:72
uint16_t harmonics[F_CNT]
амплитуды всех гармоник сигнала
Definition: global.h:77
preset_result_t
результат функции смены пресета
Definition: main_effect.h:56
#define PIXEL_CNT
Общее количество пикселов
Definition: pixel.h:27
#define FOREGROUND_EFFECT
основной эффект
Definition: main_effect.h:50
Общее количество гармоник
Definition: global.h:44
pixel_t pixels[MAX_TOTAL_PIX]
Массив пикселей предельного размера
Definition: pixel.c:22
void register_effect(uint8_t toe, flash_effect_t *eff)
Регистрация эффекта в списках
Definition: main_effect.c:41
void set_fix_color(uint8_t pos, uint8_t fix_cid)
Пиксел одного из фиксированных цветов
Definition: pixel.c:124
uint8_t bright
яркость пиксела
Definition: pixel.h:37