Kestrel Interface
Loading...
Searching...
No Matches
kest_param_update.c
Go to the documentation of this file.
1#include "kest_int.h"
2
3#ifndef PRINTLINES_ALLOWED
4#define PRINTLINES_ALLOWED 0
5#endif
6
7static const char *FNAME = "kest_param_update.c";
8
9#ifdef KEST_USE_FREERTOS
10#define UPDATE_QUEUE_LENGTH 64
11
12static kest_parameter_update update_queue[UPDATE_QUEUE_LENGTH];
13static int n_waiting = 0;
14static int update_queue_head = 0;
15static int update_queue_tail = 0;
16
18static int n_updates = 0;
19
20#define UPDATE_RATE_HZ 500
21#define UPDATE_PERIOD_MS (1000.0f / (float)UPDATE_RATE_HZ)
22
23static const int update_period_ticks = (pdMS_TO_TICKS((int)UPDATE_PERIOD_MS) == 0) ? 1 : pdMS_TO_TICKS((int)UPDATE_PERIOD_MS);
24
25int queue_initd = 0;
26QueueHandle_t update_rtos_queue;
27
28void remove_param_update(int index)
29{
30 for (int i = index; i + 1 < n_updates; i++)
31 update_array[i] = update_array[i+1];
32
33 n_updates--;
34}
35
36int add_param_update(kest_parameter_update up)
37{
38 for (int i = 0; i < n_updates; i++)
39 {
40 if (update_queue[i].id.profile_id == up.id.profile_id
41 && update_queue[i].id.effect_id == up.id.effect_id
42 && update_queue[i].id.parameter_id == up.id.parameter_id)
43 {
44 update_array[i].target = up.target;
45 }
46 }
47
48 if (n_updates + 1 >= MAX_CONCURRENT_PARAM_UPDATES)
50
51 update_array[n_updates++] = up;
52
53 return NO_ERROR;
54}
55
56void print_parameter_update(kest_parameter_update up)
57{
58 KEST_PRINTF("%d.%d.%d -> %s%.03f\n", up.id.profile_id, up.id.effect_id, up.id.parameter_id, (up.target >= 0) ? " " : "", up.target);
59}
60
61void kest_param_update_task(void *arg)
62{
63 update_rtos_queue = xQueueCreate(16, sizeof(kest_parameter_update));
64 queue_initd = 1;
65
66 TickType_t last_wake = xTaskGetTickCount();
67
69 kest_effect *effect;
70 kest_parameter *param;
71
72 float diff;
73 int enqueue;
74 int send;
75 int commit;
76 int k;
77
78 while (1)
79 {
80 while ((update_queue_tail + 1) % UPDATE_QUEUE_LENGTH != update_queue_head && xQueueReceive(update_rtos_queue, &current, 0) == pdPASS)
81 {
82 //print_parameter_update(current);
83
84 enqueue = 1;
85 for (int i = 0; i < n_updates; i++)
86 {
87 //print_parameter_update(current);
88 if (update_array[i].id.profile_id == current.id.profile_id
89 && update_array[i].id.effect_id == current.id.effect_id
90 && update_array[i].id.parameter_id == current.id.parameter_id)
91 {
92 update_array[i].target = current.target;
93 enqueue = 0;
94 break;
95 }
96 }
97
98 if (!enqueue)
99 continue;
100
101 for (int j = update_queue_head; j != update_queue_tail; j = (j + 1) % UPDATE_QUEUE_LENGTH)
102 {
103 //print_parameter_update(update_queue[j]);
104
105 if (update_queue[j].id.profile_id == current.id.profile_id
106 && update_queue[j].id.effect_id == current.id.effect_id
107 && update_queue[j].id.parameter_id == current.id.parameter_id)
108 {
109 update_queue[j].target = current.target;
110 enqueue = 0;
111 break;
112 }
113 }
114
115 if (enqueue)
116 {
117 update_queue[update_queue_tail] = current;
118 update_queue_tail = (update_queue_tail + 1) % UPDATE_QUEUE_LENGTH;
119 }
120 }
121
122 while (update_queue_tail != update_queue_head && n_updates < MAX_CONCURRENT_PARAM_UPDATES)
123 {
124 update_array[n_updates++] = update_queue[update_queue_head];
125 update_queue_head = (update_queue_head + 1) % UPDATE_QUEUE_LENGTH;
126 //print_parameter_update(update_array[n_updates - 1]);
127 }
128
129
130 commit = 0;
131
132 for (int i = 0; i < n_updates; i++)
133 {
134 current = update_array[i];
135 //print_parameter_update(current);
136
137 if (cxt_get_parameter_and_effect_by_id(&global_cxt, update_array[i].id, &update_array[i].p, &update_array[i].t) != NO_ERROR)
138 {
139 remove_param_update(i);
140 i--;
141 continue;
142 }
143
144 param = update_array[i].p;
145
146 if (!param)
147 {
148 remove_param_update(i);
149 i--;
150 continue;
151 }
152
153 if (update_array[i].id.profile_id != CONTEXT_PROFILE_ID)
154 {
155 update_array[i].send = (update_array[i].t != NULL);
156
157 if (update_array[i].send)
158 {
159 for (int j = 0; j < i && update_array[i].send; j++)
160 {
161 if (update_array[j].t == update_array[i].t)
162 update_array[i].send = 0;
163 }
164
165 if (!(update_array[i].send && update_array[i].t && xSemaphoreTake(update_array[i].t->mutex, 0) == pdTRUE))
166 update_array[i].send = 0;
167 }
168 }
169
170 diff = update_array[i].target - param->value;
171
172 if (param->scale == PARAMETER_SCALE_LINEAR)
173 {
174 if (diff > UPDATE_PERIOD_MS * param->max_velocity)
175 diff = UPDATE_PERIOD_MS * param->max_velocity;
176
177 if (diff < -UPDATE_PERIOD_MS * param->max_velocity)
178 diff = -UPDATE_PERIOD_MS * param->max_velocity;
179 }
180 else if (param->scale == PARAMETER_SCALE_LOGARITHMIC)
181 {
182 if (diff > UPDATE_PERIOD_MS * param->max_velocity * param->value)
183 diff = UPDATE_PERIOD_MS * param->max_velocity * param->value;
184
185 if (diff < -UPDATE_PERIOD_MS * param->max_velocity * param->value)
186 diff = -UPDATE_PERIOD_MS * param->max_velocity * param->value;
187 }
188 //kest_printf("Move parameter %s (%d.%d.%d) by %f from %f to %f, with target %f\n", param->name, param->id.profile_id, param->id.effect_id, param->id.parameter_id,
189 // diff, param->value, param->value + diff, update_array[i].target);
190
191 param->value = param->value + diff;
192
193 if (update_array[i].id.profile_id == CONTEXT_PROFILE_ID)
194 {
195 update_array[i].send = 0;
196 if (param == &global_cxt.input_gain)
197 {
199 }
200 else if (param == &global_cxt.output_gain)
201 {
203 }
204 }
205 else
206 {
207 commit = 1;
208 }
209
210 }
211
212 for (int i = 0; i < n_updates; i++)
213 {
214 if (update_array[i].t && update_array[i].send)
215 {
216 if (global_cxt.active_profile && global_cxt.active_profile->id == update_array[i].id.profile_id)
217 kest_effect_update_fpga_registers(update_array[i].t);
218 xSemaphoreGive(update_array[i].t->mutex);
219 }
220 }
221
222 for (int i = 0; i < n_updates; i++)
223 {
224 if (!update_array[i].p)
225 {
226 remove_param_update(i);
227 i--;
228 continue;
229 }
230
231 if (update_array[i].p->value == update_array[i].target)
232 {
233 //kest_printf("Removing update %d from queue for reason: value %.03f equals target %.03f\n", i, update_array[i].p->value, update_array[i].target);
234 if (update_array[i].p->id.profile_id == CONTEXT_PROFILE_ID)
236
237 queue_representation_list_update(update_array[i].p->reps);
238
239 remove_param_update(i);
240 i--;
241 continue;
242 }
243 }
244
245 if (commit)
246 {
248 }
249
250 xTaskDelayUntil(&last_wake, update_period_ticks);
251 }
252}
253
254int kest_parameter_trigger_update(kest_parameter *param, float target)
255{
256 KEST_PRINTF("kest_parameter_trigger_update, param = %p, target = %f\n", param, target);
257 if (!param)
258 return ERR_NULL_PTR;
259
260 KEST_PRINTF("Parameter %s, ID %d.%d.%d. Current value: %f. Update target: %f. Max velocity: %f\n",
261 param->name, param->id.profile_id, param->id.effect_id, param->id.parameter_id,
262 param->value, target, param->max_velocity);
263
265 up.id = param->id;
266 up.target = target;
267
268 while (!queue_initd);
269
270 if (xQueueSend(update_rtos_queue, &up, pdMS_TO_TICKS(1)) != pdPASS)
272
273 return NO_ERROR;
274}
275#else
277{
278 KEST_PRINTF("kest_parameter_trigger_update, param = %p, target = %f\n", param, target);
279 if (!param)
280 return ERR_NULL_PTR;
281
282 param->value = target;
283
284 return NO_ERROR;
285}
286#endif
int cxt_get_parameter_and_effect_by_id(kest_context *cxt, kest_parameter_id id, kest_parameter **pp, kest_effect **tp)
int kest_cxt_queue_save_state(kest_context *cxt)
#define CONTEXT_PROFILE_ID
Definition kest_context.h:6
int kest_effect_update_fpga_registers(kest_effect *effect)
#define NO_ERROR
#define ERR_CURRENTLY_EXHAUSTED
#define ERR_NULL_PTR
int kest_fpga_queue_input_gain_set(float gain_db)
int kest_fpga_queue_register_commit()
int kest_fpga_queue_output_gain_set(float gain_db)
kest_context global_cxt
Definition kest_int.c:12
int kest_parameter_trigger_update(kest_parameter *param, float target)
#define MAX_CONCURRENT_PARAM_UPDATES
void kest_param_update_task(void *arg)
#define PARAMETER_SCALE_LINEAR
#define PARAMETER_SCALE_LOGARITHMIC
#define KEST_PRINTF(...)
Definition kest_printf.h:10
int queue_representation_list_update(kest_representation_pll *reps)
kest_parameter_id id
const char * name
kest_parameter_id id