##// END OF EJS Templates
Actualizacion de la app RC a python3 y django 2, antes del merge con cambios
gonzalesluisfrancisco -
r341:cb29d2ed7f9e merge
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,463
1 {% extends "dev_conf_edit.html" %}
2 {% load bootstrap4 %}
3 {% load static %}
4 {% load main_tags %}
5
6 {% block dds_rest%}
7
8 {% bootstrap_field form.template layout='horizontal' size='medium' %}
9 {% bootstrap_field form.device layout='horizontal' size='medium' %}
10 {% bootstrap_field form.label layout='horizontal' size='medium' %}
11 {% bootstrap_field form.experiment layout='horizontal' size='medium' %}
12
13 {% bootstrap_field form.clock layout='horizontal' size='medium' %}
14 {% bootstrap_field form.multiplier layout='horizontal' size='medium' %}
15
16 <div style="display: flex; justify-content: flex-end">
17 <div class="form-check">
18 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_fA" value="" >Mostrar Decimal</label>
19 </div>
20 </div>
21 {% bootstrap_field form.frequencyA_Mhz layout='horizontal' size='medium' %}
22 <div id='id_row_fAbin'>
23 {% bootstrap_field form.frequencyA layout='horizontal' size='medium' %}
24 <div style="display: flex; justify-content: flex-end">
25 <small type="text" id="id_aux_fAbin" class="form-text text-muted">1000 0000 </small>
26 </div>
27 <br>
28 </div>
29
30 <div style="display: flex; justify-content: flex-end">
31 <div class="form-check">
32 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_fB" value="" >Mostrar Decimal</label>
33 </div>
34 </div>
35 {% bootstrap_field form.frequencyB_Mhz layout='horizontal' size='medium' %}
36 <div id='id_row_fBbin'>
37 {% bootstrap_field form.frequencyB layout='horizontal' size='medium' %}
38 <div style="display: flex; justify-content: flex-end">
39 <small type="text" id="id_aux_fBbin" class="form-text text-muted">1000 0000 </small>
40 </div>
41 <br>
42 </div>
43
44 <div style="display: flex; justify-content: flex-end">
45 <div class="form-check">
46 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_df" value="" >Mostrar Decimal</label>
47 </div>
48 </div>
49 {% bootstrap_field form.delta_frequency_Mhz layout='horizontal' size='medium' %}
50 <div id='id_row_dfbin'>
51 {% bootstrap_field form.delta_frequency layout='horizontal' size='medium' %}
52 <div style="display: flex; justify-content: flex-end">
53 <small type="text" id="id_aux_deltabin" class="form-text text-muted">1000 0000 </small>
54 </div>
55 <br>
56 </div>
57
58 <div style="display: flex; justify-content: flex-end">
59 <div class="form-check">
60 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_ramp" value="" >Mostrar Decimal</label>
61 </div>
62 </div>
63 <div class="form-group row">
64 <label class="col-md-3 col-form-label" for="id_ramp_rate_clock_us">Ramp rate clock(us)</label>
65 <div class="col-md-9">
66 <input type="number" name="ramp_rate_clock_us" step="1e-16" class="form-control" placeHolder="Ramp rate clock(us)" title id="id_ramp_rate_clock_us">
67 </div>
68 </div>
69 <div id='id_row_rampbin'>
70 {% bootstrap_field form.ramp_rate_clock_Mhz layout='horizontal' size='medium' %}
71 {% bootstrap_field form.ramp_rate_clock layout='horizontal' size='medium' %}
72 <div style="display: flex; justify-content: flex-end">
73 <small type="text" id="id_aux_rampbin" class="form-text text-muted">1000 0000 </small>
74 </div>
75 <br>
76 </div>
77
78 <div style="display: flex; justify-content: flex-end">
79 <div class="form-check">
80 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_phaseA" value="" >Mostrar Decimal</label>
81 </div>
82 </div>
83 {% bootstrap_field form.phaseA_degrees layout='horizontal' size='medium' %}
84 <div id='id_row_phaseA'>
85 <div style="display: flex; justify-content: flex-end">
86 <small type="text" id="id_aux_phaseAdec" class="form-text text-muted">9282 </small>
87 </div>
88 <div style="display: flex; justify-content: flex-end">
89 <small type="text" id="id_aux_phaseAbin" class="form-text text-muted">1000 0000 </small>
90 </div>
91 <br>
92 </div>
93
94 <div style="display: flex; justify-content: flex-end">
95 <div class="form-check">
96 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_phaseB" value="" >Mostrar Decimal</label>
97 </div>
98 </div>
99 {% bootstrap_field form.phaseB_degrees layout='horizontal' size='medium' %}
100 <div id='id_row_phaseB'>
101 <div style="display: flex; justify-content: flex-end">
102 <small type="text" id="id_aux_phaseBdec" class="form-text text-muted">9876 </small>
103 </div>
104 <div style="display: flex; justify-content: flex-end">
105 <small type="text" id="id_aux_phaseBbin" class="form-text text-muted">1000 0000 </small>
106 </div>
107 <br>
108 </div>
109
110 {% bootstrap_field form.modulation layout='horizontal' size='medium' %}
111 {% bootstrap_field form.amplitude_enabled layout='horizontal' size='medium' %}
112
113 {% bootstrap_field form.amplitudeI layout='horizontal' size='medium' %}
114 {% bootstrap_field form.amplitudeQ layout='horizontal' size='medium' %}
115
116
117 {% endblock %}
118
119 {% block extra-js%}
120 <script src="{% static 'js/dds_conversion.js' %}"></script>
121 <script type="text/javascript">
122 $("#id_row_fAbin").hide();
123 $("#id_chkbin_fA").on('change', function() {
124 hidefA();
125 });
126
127 $("#id_row_fBbin").hide();
128 $("#id_chkbin_fB").on('change', function() {
129 hidefB();
130 });
131
132 $("#id_row_dfbin").hide();
133 $("#id_chkbin_df").on('change', function() {
134 hidedf();
135 });
136
137 $("#id_row_rampbin").hide();
138 $("#id_chkbin_ramp").on('change', function() {
139 hideramp();
140 });
141
142 $("#id_row_phaseA").hide();
143 $("#id_chkbin_phaseA").on('change', function() {
144 hidephaseA();
145 });
146
147 $("#id_row_phaseB").hide();
148 $("#id_chkbin_phaseB").on('change', function() {
149 hidephaseB();
150 });
151
152 $("#id_clock").on('change', function() {
153 updateFrequencies();
154 });
155
156 $("#id_multiplier").on('change', function() {
157 updateFrequencies();
158 });
159
160 $("#id_frequencyA_Mhz").on('change', function() {
161 updateBinaryFrequencies();
162 });
163
164 $("#id_frequencyA").on('change', function() {
165 updateFrequencies();
166 });
167
168 $("#id_frequencyB_Mhz").on('change', function() {
169 updateBinaryFrequencies();
170 });
171
172 $("#id_frequencyB").on('change', function() {
173 updateFrequencies();
174 });
175
176 $("#id_delta_frequency").on('change', function() {
177 updateFrequencyDelta();
178 });
179
180 $("#id_delta_frequency_Mhz").on('change', function() {
181 updateBinaryFrequencyDelta();
182 });
183
184 $("#id_ramp_rate_clock").on('change', function() {
185 updateFrequencyRamp();
186 });
187
188 $("#id_ramp_rate_clock_us").on('change', function() {
189 updateFrequencyMhzRamp();
190 });
191
192 $("#id_ramp_rate_clock_Mhz").on('change', function() {
193 updateBinaryFrequencyRamp();
194 });
195
196 $("#id_phaseA_degrees").on('change', function() {
197 updatephaseAbindec();
198 });
199
200 $("#id_phaseB_degrees").on('change', function() {
201 updatephaseBbindec();
202 });
203
204 function updateBinaryFrequencies() {
205
206 var clock = $("#id_clock").val();
207 var multiplier = $("#id_multiplier").val();
208 var freq = $("#id_frequencyA_Mhz").val();
209 var freq_mod = $("#id_frequencyB_Mhz").val();
210
211 var mclock = clock*multiplier;
212
213 var freq_bin = freq2Binary(mclock, freq);
214 var freq_mod_bin = freq2Binary(mclock, freq_mod);
215
216 $("#id_frequencyA").val(freq_bin);
217 $("#id_frequencyB").val(freq_mod_bin);
218
219 freq = binary2Freq(mclock, freq_bin);
220 freq_mod = binary2Freq(mclock, freq_mod_bin);
221
222 $("#id_frequencyA_Mhz").val(freq);
223 $("#id_frequencyB_Mhz").val(freq_mod);
224
225 }
226
227 function updateFrequencies() {
228 console.log("Ingreso a updateFrequencies");
229 var clock = $("#id_clock").val();
230 var multiplier = $("#id_multiplier").val();
231 var freq_bin = $("#id_frequencyA").val();
232 var freq_mod_bin = $("#id_frequencyB").val();
233 var freqdelta_bin = $("#id_delta_frequency").val();
234 var freqramp_bin = $("#id_ramp_rate_clock").val();
235
236 var mclock = clock*multiplier;
237
238 var freq = binary2Freq(mclock, freq_bin);
239 var freq_mod = binary2Freq(mclock, freq_mod_bin);
240 var freqdelta = binary2FreqDelta(mclock, freqdelta_bin);
241 var freq_ramp = binary2Ramp(mclock, freqramp_bin);
242
243 $("#id_frequencyA_Mhz").val(freq);
244 $("#id_frequencyB_Mhz").val(freq_mod);
245 $("#id_delta_frequency_Mhz").val(freqdelta);
246 $("#id_ramp_rate_clock_Mhz").val(freq_ramp);
247 }
248
249 function updateFrequencyDelta() {
250 console.log("Ingreso a updateFrequencyDelta");
251 var clock = $("#id_clock").val();
252 var multiplier = $("#id_multiplier").val();
253 var freq_bin = $("#id_delta_frequency").val();
254
255 var mclock = clock*multiplier;
256
257 var freq = binary2FreqDelta(mclock, freq_bin);
258 console.log(freq);
259 $("#id_delta_frequency_Mhz").val(freq);
260 }
261
262 function updateBinaryFrequencyDelta() {
263 console.log("Ingreso a updateBInaryFrequencyDelta");
264 var clock = $("#id_clock").val();
265 var multiplier = $("#id_multiplier").val();
266 var freq = $("#id_delta_frequency_Mhz").val();
267 console.log(clock);
268 console.log(multiplier);
269 console.log(freq);
270
271 var mclock = clock*multiplier;
272 console.log(mclock);
273
274 var freq_bin = freqDelta2Binary(mclock, freq);
275
276 console.log(freq_bin);
277 $("#id_delta_frequency").val(freq_bin);
278
279 document.getElementById("id_aux_deltabin").innerHTML = numToString(parseInt(freq_bin, 10), 2, 48).match(/.{1,4}/g).join(' ');
280 }
281
282 function updateFrequencyRamp() {
283 console.log("Ingreso a updateFrequencyRamp");
284 var clock = $("#id_clock").val();
285 var multiplier = $("#id_multiplier").val();
286 var freq_bin = $("#id_ramp_rate_clock").val();
287
288 var mclock = clock*multiplier;
289
290 var freq = binary2Ramp(mclock, freq_bin);
291 console.log(freq);
292 $("#id_ramp_rate_clock_Mhz").val(freq);
293 }
294
295 function updateBinaryFrequencyRamp() {
296 console.log("Ingreso a updateBInaryFrequencyRamp");
297 var clock = $("#id_clock").val();
298 var multiplier = $("#id_multiplier").val();
299 var freq = $("#id_ramp_rate_clock_Mhz").val();
300
301 var mclock = clock*multiplier;
302
303 var freq_bin = freqRamp2Binary(mclock, freq);
304 console.log(freq_bin);
305 $("#id_ramp_rate_clock").val(freq_bin);
306 }
307
308 function updateFrequencyMhzRamp() {
309 console.log("Ingreso a updateFrequencyMhzRamp");
310 var step_us = $("#id_ramp_rate_clock_us").val();
311
312 var freq = us2Ramp(step_us);
313 console.log(freq);
314 $("#id_ramp_rate_clock_Mhz").val(freq);
315 updateBinaryFrequencyRamp();
316 }
317
318 function hidefA() {
319 var checkbox = $("#id_chkbin_fA");
320 var freq_bin = $("#id_row_fAbin");
321 var val_freq = $("#id_frequencyA");
322
323 console.log("Ingreso a hidefA");
324 if (checkbox.is(':checked')) {
325 freq_bin.show();
326 console.log(val_freq.val());
327 document.getElementById("id_aux_fAbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
328 }
329 else{
330 freq_bin.hide();
331 }
332 }
333
334 function hidefB() {
335 var checkbox = $("#id_chkbin_fB");
336 var freq_bin = $("#id_row_fBbin");
337 var val_freq = $("#id_frequencyB");
338
339 console.log("Ingreso a hidefB");
340 if (checkbox.is(':checked')) {
341 freq_bin.show();
342 console.log(val_freq.val());
343 document.getElementById("id_aux_fBbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
344 }
345 else{
346 freq_bin.hide();
347 }
348 }
349
350 function hidedf() {
351 var checkbox = $("#id_chkbin_df");
352 var freq_bin = $("#id_row_dfbin");
353 var val_freq = $("#id_delta_frequency");
354
355 console.log("Ingreso a hidedf");
356 if (checkbox.is(':checked')) {
357 freq_bin.show();
358 console.log(val_freq.val());
359 document.getElementById("id_aux_deltabin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
360 }
361 else{
362 freq_bin.hide();
363 }
364 }
365
366 function hideramp() {
367 var checkbox = $("#id_chkbin_ramp");
368 var freq_bin = $("#id_row_rampbin");
369 var val_freq = $("#id_ramp_rate_clock");
370
371 console.log("Ingreso a hideramp");
372 if (checkbox.is(':checked')) {
373 freq_bin.show();
374 console.log(val_freq.val());
375 document.getElementById("id_aux_rampbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 20).match(/.{1,4}/g).join(' ');
376 }
377 else{
378 freq_bin.hide();
379 }
380 }
381
382 function hidephaseA() {
383 var checkbox = $("#id_chkbin_phaseA");
384 var freq_bin = $("#id_row_phaseA");
385 var phase_degree = $("#id_phaseA_degrees");
386
387 console.log("Ingreso a hidephaseA");
388 if (checkbox.is(':checked')) {
389 freq_bin.show();
390 console.log(phase_degree.val());
391 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
392 console.log(phase_degree_dec);
393 document.getElementById("id_aux_phaseAdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
394 document.getElementById("id_aux_phaseAbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
395
396 }
397 else{
398 freq_bin.hide();
399 }
400 }
401
402 function hidephaseB() {
403 var checkbox = $("#id_chkbin_phaseB");
404 var freq_bin = $("#id_row_phaseB");
405 var phase_degree = $("#id_phaseB_degrees");
406
407 console.log("Ingreso a hidephaseB");
408 if (checkbox.is(':checked')) {
409 freq_bin.show();
410 console.log(phase_degree.val());
411 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
412 console.log(phase_degree_dec);
413 document.getElementById("id_aux_phaseBdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
414 document.getElementById("id_aux_phaseBbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
415
416 }
417 else{
418 freq_bin.hide();
419 }
420 }
421
422 function updatephaseAbindec() {
423 var freq_bin = $("#id_row_phaseA");
424 var phase_degree = $("#id_phaseA_degrees");
425
426 console.log("Ingreso a cupdatephaseAbindec");
427 console.log(phase_degree.val());
428 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
429 console.log(phase_degree_dec);
430 document.getElementById("id_aux_phaseAdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
431 document.getElementById("id_aux_phaseAbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
432
433 }
434
435 function updatephaseBbindec() {
436 var freq_bin = $("#id_row_phaseB");
437 var phase_degree = $("#id_phaseB_degrees");
438
439 console.log("Ingreso a cupdatephaseBbindec");
440 console.log(phase_degree.val());
441 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
442 console.log(phase_degree_dec);
443 document.getElementById("id_aux_phaseBdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
444 document.getElementById("id_aux_phaseBbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
445
446 }
447
448 function padStart(string, length, char) {
449 return length > 0 ?
450 padStart(char + string, --length, char) :
451 string;
452 }
453
454 function numToString(num, radix, length = num.length) {
455 const numString = num.toString(radix);
456 return numString.length === length ?
457 numString :
458 padStart(numString, length - numString.length, "0")
459 }
460
461 console.log(numToString(parseInt("37529996894754", 10), 2, 48));
462 </script>
463 {% endblock %} No newline at end of file
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,12 +1,12
1 1 REDIS_HOST=radarsys-redis
2 2 REDIS_PORT=6379
3 3 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
4 4 POSTGRES_PORT_5432_TCP_PORT=5432
5 5 DB_NAME=radarsys
6 6 DB_USER=docker
7 7 DB_PASSWORD=docker
8 8 PGDATA=/var/lib/postgresql/data
9 9 LC_ALL=C.UTF-8
10 10 TZ=America/Lima
11 DOCKER_DATA=/Volumes/dockers/radarsys/
11 DOCKER_DATA=/data/dockers/radarsys/
12 12 LOCAL_IP=192.168.1.128
@@ -1,1005 +1,1005
1 1 from django.db import models
2 2 from apps.main.models import Configuration , User
3 3 from django.urls import reverse
4 4 from celery.execute import send_task
5 5 from datetime import datetime
6 6 import ast
7 7 import socket
8 8 import json
9 9 import requests
10 10 import struct
11 11 import os, sys, time
12 12
13 13 antenna_default = json.dumps({
14 14 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
15 15 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
16 16 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
17 17 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
18 18 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
19 19 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
20 20 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
21 21 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
22 22 ]
23 23 ,
24 24 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
25 25 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
26 26 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
27 27 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
28 28 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
29 29 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
30 30 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
31 31 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
32 32 })
33 33
34 34
35 35 tx_default = json.dumps({
36 36 "up": [[1,1,1,1,0,0,0,0],
37 37 [1,1,1,1,0,0,0,0],
38 38 [1,1,1,1,0,0,0,0],
39 39 [1,1,1,1,0,0,0,0],
40 40 [0,0,0,0,1,1,1,1],
41 41 [0,0,0,0,1,1,1,1],
42 42 [0,0,0,0,1,1,1,1],
43 43 [0,0,0,0,1,1,1,1]],
44 44
45 45 "down": [[1,1,1,1,0,0,0,0],
46 46 [1,1,1,1,0,0,0,0],
47 47 [1,1,1,1,0,0,0,0],
48 48 [1,1,1,1,0,0,0,0],
49 49 [0,0,0,0,1,1,1,1],
50 50 [0,0,0,0,1,1,1,1],
51 51 [0,0,0,0,1,1,1,1],
52 52 [0,0,0,0,1,1,1,1]],
53 53 })
54 54
55 55 rx_default = json.dumps({
56 56 "up": [[1,1,1,1,0,0,0,0],
57 57 [1,1,1,1,0,0,0,0],
58 58 [1,1,1,1,0,0,0,0],
59 59 [1,1,1,1,0,0,0,0],
60 60 [0,0,0,0,1,1,1,1],
61 61 [0,0,0,0,1,1,1,1],
62 62 [0,0,0,0,1,1,1,1],
63 63 [0,0,0,0,1,1,1,1]],
64 64
65 65 "down": [[1,1,1,1,0,0,0,0],
66 66 [1,1,1,1,0,0,0,0],
67 67 [1,1,1,1,0,0,0,0],
68 68 [1,1,1,1,0,0,0,0],
69 69 [0,0,0,0,1,1,1,1],
70 70 [0,0,0,0,1,1,1,1],
71 71 [0,0,0,0,1,1,1,1],
72 72 [0,0,0,0,1,1,1,1]],
73 73 })
74 74
75 75 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
76 76 default_messages = {}
77 77
78 78 for i in range(1,65):
79 79 default_messages[str(i)] = "Module "+str(i)
80 80
81 81
82 82 ues_default = json.dumps({
83 83 "up": [0.533333,0.00000,1.06667,0.00000],
84 84 "down": [0.533333,0.00000,1.06667,0.00000]
85 85 })
86 86
87 87 onlyrx_default = json.dumps({
88 88 "up": False,
89 89 "down": False
90 90 })
91 91
92 92 def up_convertion(cadena):
93 93 valores = []
94 94 for c in cadena:
95 95 if c == 1.0: valores=valores+['000']
96 96 if c == 2.0: valores=valores+['001']
97 97 if c == 3.0: valores=valores+['010']
98 98 if c == 0.0: valores=valores+['011']
99 99 if c == 0.5: valores=valores+['100']
100 100 if c == 1.5: valores=valores+['101']
101 101 if c == 2.5: valores=valores+['110']
102 102 if c == 3.5: valores=valores+['111']
103 103
104 104 return valores
105 105
106 106 def up_conv_bits(value):
107 107
108 108 if value == 1.0: bits="000"
109 109 if value == 2.0: bits="001"
110 110 if value == 3.0: bits="010"
111 111 if value == 0.0: bits="011"
112 112 if value == 0.5: bits="100"
113 113 if value == 1.5: bits="101"
114 114 if value == 2.5: bits="110"
115 115 if value == 3.5: bits="111"
116 116
117 117 return bits
118 118
119 119 def down_convertion(cadena):
120 120 valores = []
121 121 for c in cadena:
122 122 if c == 1.0: valores=valores+['000']
123 123 if c == 2.0: valores=valores+['001']
124 124 if c == 3.0: valores=valores+['010']
125 125 if c == 0.0: valores=valores+['011']
126 126 if c == 0.5: valores=valores+['100']
127 127 if c == 1.5: valores=valores+['101']
128 128 if c == 2.5: valores=valores+['110']
129 129 if c == 3.5: valores=valores+['111']
130 130
131 131 return valores
132 132
133 133 def down_conv_bits(value):
134 134
135 135 if value == 1.0: bits="000"
136 136 if value == 2.0: bits="001"
137 137 if value == 3.0: bits="010"
138 138 if value == 0.0: bits="011"
139 139 if value == 0.5: bits="100"
140 140 if value == 1.5: bits="101"
141 141 if value == 2.5: bits="110"
142 142 if value == 3.5: bits="111"
143 143
144 144 return bits
145 145
146 146 def up_conv_value(bits):
147 147
148 148 if bits == "000": value=1.0
149 149 if bits == "001": value=2.0
150 150 if bits == "010": value=3.0
151 151 if bits == "011": value=0.0
152 152 if bits == "100": value=0.5
153 153 if bits == "101": value=1.5
154 154 if bits == "110": value=2.5
155 155 if bits == "111": value=3.5
156 156
157 157 return value
158 158
159 159 def down_conv_value(bits):
160 160
161 161 if bits == "000": value=1.0
162 162 if bits == "001": value=2.0
163 163 if bits == "010": value=3.0
164 164 if bits == "011": value=0.0
165 165 if bits == "100": value=0.5
166 166 if bits == "101": value=1.5
167 167 if bits == "110": value=2.5
168 168 if bits == "111": value=3.5
169 169
170 170 return value
171 171
172 172 def ip2position(module_number):
173 173 j=0
174 174 i=0
175 175 for x in range(0,module_number-1):
176 176 j=j+1
177 177 if j==8:
178 178 i=i+1
179 179 j=0
180 180
181 181 pos = [i,j]
182 182 return pos
183 183
184 184
185 185 def fromBinary2Char(binary_string):
186 186 number = int(binary_string, 2)
187 187 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
188 188 number = number + 33
189 189 char = chr(number)
190 190 return char
191 191
192 192 def fromChar2Binary(char):
193 193 number = ord(char) - 33
194 194 #Minus 33 to get the real value
195 195 bits = bin(number)[2:]
196 196 #To ensure we have a string with 6bits
197 197 if len(bits) < 6:
198 198 bits = bits.zfill(6)
199 199 return bits
200 200
201 201 OPERATION_MODES = (
202 202 (0, 'Manual'),
203 203 (1, 'Automatic'),
204 204 )
205 205
206 206 class ABSConfiguration(Configuration):
207 207 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
208 208 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=status_default)
209 209 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
210 210 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
211 211 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
212 212
213 213 class Meta:
214 214 db_table = 'abs_configurations'
215 215
216 216 def get_absolute_url_plot(self):
217 217 return reverse('url_plot_abs_patterns', args=[str(self.id)])
218 218
219 219
220 220 def parms_to_dict(self):
221 221
222 222 parameters = {}
223 223
224 224 parameters['device_id'] = self.device.id
225 225 parameters['label'] = self.label
226 226 parameters['device_type'] = self.device.device_type.name
227 227 parameters['beams'] = {}
228 228
229 229 beams = ABSBeam.objects.filter(abs_conf=self)
230 230 b=1
231 231 for beam in beams:
232 232 #absbeam = ABSBeam.objects.get(pk=beams[beam])
233 233 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
234 234 b+=1
235 235
236 236 return parameters
237 237
238 238
239 239 def dict_to_parms(self, parameters):
240 240
241 241 self.label = parameters['label']
242 242
243 243 absbeams = ABSBeam.objects.filter(abs_conf=self)
244 244 beams = parameters['beams']
245 245
246 246 if absbeams:
247 247 beams_number = len(beams)
248 248 absbeams_number = len(absbeams)
249 249 if beams_number==absbeams_number:
250 250 i = 1
251 251 for absbeam in absbeams:
252 252 absbeam.dict_to_parms(beams['beam'+str(i)])
253 253 i = i+1
254 254 elif beams_number > absbeams_number:
255 255 i = 1
256 256 for absbeam in absbeams:
257 257 absbeam.dict_to_parms(beams['beam'+str(i)])
258 258 i=i+1
259 259 for x in range(i,beams_number+1):
260 260 new_beam = ABSBeam(
261 261 name =beams['beam'+str(i)]['name'],
262 262 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
263 263 abs_conf = self,
264 264 tx =json.dumps(beams['beam'+str(i)]['tx']),
265 265 rx =json.dumps(beams['beam'+str(i)]['rx']),
266 266 ues =json.dumps(beams['beam'+str(i)]['ues']),
267 267 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
268 268 )
269 269 new_beam.save()
270 270 i=i+1
271 271 else: #beams_number < absbeams_number:
272 272 i = 1
273 273 for absbeam in absbeams:
274 274 if i <= beams_number:
275 275 absbeam.dict_to_parms(beams['beam'+str(i)])
276 276 i=i+1
277 277 else:
278 278 absbeam.delete()
279 279 else:
280 280 for beam in beams:
281 281 new_beam = ABSBeam(
282 282 name =beams[beam]['name'],
283 283 antenna =json.dumps(beams[beam]['antenna']),
284 284 abs_conf = self,
285 285 tx =json.dumps(beams[beam]['tx']),
286 286 rx =json.dumps(beams[beam]['rx']),
287 287 ues =json.dumps(beams[beam]['ues']),
288 288 only_rx =json.dumps(beams[beam]['only_rx'])
289 289 )
290 290 new_beam.save()
291 291
292 292
293 293
294 294 def update_from_file(self, parameters):
295 295
296 296 self.dict_to_parms(parameters)
297 297 self.save()
298 298
299 299
300 300 def get_beams(self, **kwargs):
301 301 '''
302 302 This function returns ABS Configuration beams
303 303 '''
304 304 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
305 305
306 306 def clone(self, **kwargs):
307 307
308 308 beams = self.get_beams()
309 309 self.pk = None
310 310 self.id = None
311 311 for attr, value in kwargs.items():
312 312 setattr(self, attr, value)
313 313 self.save()
314 314
315 315 for beam in beams:
316 316 beam.clone(abs_conf=self)
317 317
318 318 #-----For Active Beam-----
319 319 new_beams = ABSBeam.objects.filter(abs_conf=self)
320 320 self.active_beam = new_beams[0].id
321 321 self.save()
322 322 #-----For Active Beam-----
323 323 #-----For Device Status---
324 324 self.device.status = 3
325 325 self.device.save()
326 326 #-----For Device Status---
327 327
328 328 return self
329 329
330 330
331 331 def start_device(self):
332 332
333 333 if self.device.status == 3:
334 334
335 335 try:
336 336 #self.write_device()
337 337 send_task('task_change_beam', [self.id],)
338 338 self.message = 'ABS running'
339 339
340 340 except Exception as e:
341 341 self.message = str(e)
342 342 return False
343 343
344 344 return True
345 345
346 346 else:
347 347 self.message = 'Please, select Write ABS Device first.'
348 348 return False
349 349
350 350
351 351 def stop_device(self):
352 352
353 353 self.device.status = 2
354 354 self.device.save()
355 355 self.message = 'ABS has been stopped.'
356 356 self.save()
357 357
358 358 return True
359 359
360 360
361 361 def write_device(self):
362 362
363 363 """
364 364 This function sends the beams list to every abs module.
365 365 It needs 'module_conf' function
366 366 """
367 367 print("Write")
368 beams = ABSBeam.objects.filter(abs_conf=self)
368 beams = ABSBeam.objects.filter(abs_conf=self)
369 369 nbeams = len(beams)
370 370
371 371 # Se manda a cero RC para poder realizar cambio de beam
372 372 if self.experiment is None:
373 373 confs = []
374 374 else:
375 375 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
376 376 confdds = ''
377 377 confjars = ''
378 378 confrc = ''
379 379 #TO STOP DEVICES: DDS-JARS-RC
380 380 for i in range(0,len(confs)):
381 381 if i==0:
382 382 for conf in confs:
383 383 if conf.device.device_type.name == 'dds':
384 384 confdds = conf
385 385 confdds.stop_device()
386 386 break
387 387 if i==1:
388 388 for conf in confs:
389 389 if conf.device.device_type.name == 'jars':
390 390 confjars = conf
391 391 confjars.stop_device()
392 392 break
393 393 if i==2:
394 394 for conf in confs:
395 395 if conf.device.device_type.name == 'rc':
396 396 confrc = conf
397 397 confrc.stop_device()
398 398 break
399 399
400 400 '''
401 401 if self.connected_modules() == 0 :
402 402 print("No encuentra modulos")
403 403 self.message = "No ABS Module detected."
404 404 return False
405 405 '''
406 406 #-------------Write each abs module-----------
407 407
408 408 if beams:
409 409 block_id = 0
410 410 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
411 411 for i, status in enumerate(self.module_status):
412 412 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
413 413 status = ['0'] * 64
414 414 n = 0
415 415 print("Llega una antes entrar a multicast")
416 416 sock = self.send_multicast(message)
417 417
418 418 while True:
419 419 #for i in range(32):
420 420 try:
421 421 data, address = sock.recvfrom(1024)
422 422 print (address, data)
423 423
424 424 if data == '1':
425 425 status[int(address[0][10:])-1] = '3'
426 426 elif data == '0':
427 427 status[int(address[0][10:])-1] = '1'
428 428 except socket.timeout:
429 429 print('Timeout')
430 430 break
431 431 except Exception as e:
432 432 print ('Error {}'.format(e))
433 433 n += 1
434 434 sock.close()
435 435 else:
436 436 self.message = "ABS Configuration does not have beams"
437 437 print('No beams')
438 438 #Start DDS-RC-JARS
439 439 if confdds:
440 440 confdds.start_device()
441 441 if confrc:
442 442 #print confrc
443 443 confrc.start_device()
444 444 if confjars:
445 445 confjars.start_device()
446 446 return False
447 447
448 448 if n == 64:
449 449 self.message = "Could not write ABS Modules"
450 450 self.device.status = 0
451 451 self.module_status = ''.join(status)
452 452 self.save()
453 453 print('Could not write ABS')
454 454 #Start DDS-RC-JARS
455 455 if confdds:
456 456 confdds.start_device()
457 457 if confrc:
458 458 #print confrc
459 459 confrc.start_device()
460 460 if confjars:
461 461 confjars.start_device()
462 462 return False
463 463 else:
464 464 self.message = "ABS Beams List have been sent to ABS Modules"
465 465 print('ABS beams list sent')
466 466 self.active_beam = beams[0].pk
467 467
468 468 #Start DDS-RC-JARS
469 469 if confdds:
470 470 confdds.start_device()
471 471 if confrc:
472 472 #print confrc
473 473 confrc.start_device()
474 474 if confjars:
475 475 confjars.start_device()
476 476
477 477 print('Inicia intento de salvar device.status')
478 478 self.device.status = 3
479 479 self.module_status = ''.join(status)
480 480 self.save()
481 481 print('Estatus salvado')
482 conf_active = ABSActive.objects.get_or_create(pk=1)
482 conf_active, __ = ABSActive.objects.get_or_create(pk=1)
483 483 conf_active.conf = self
484 484 conf_active.save()
485 485 return True
486 486
487 487
488 488 def read_module(self, module):
489 489
490 490 """
491 491 Read out-bits (up-down) of 1 abs module NOT for Configuration
492 492 """
493 493
494 494 ip_address = self.device.ip_address
495 495 ip_address = ip_address.split('.')
496 496 module_seq = (ip_address[0],ip_address[1],ip_address[2])
497 497 dot = '.'
498 498 module_ip = dot.join(module_seq)+'.'+str(module)
499 499 module_port = self.device.port_address
500 500 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
501 501
502 502 module_status = json.loads(self.module_status)
503 503 print(read_route)
504 504
505 505 module_bits = ''
506 506
507 507 try:
508 508 r_read = requests.get(read_route, timeout=0.5)
509 509 answer = r_read.json()
510 510 module_bits = answer['allbits']
511 511 except:
512 512 return {}
513 513
514 514 return module_bits
515 515
516 516 def read_device(self):
517 517
518 518 parms = {}
519 519 # Reads active modules.
520 520 module_status = json.loads(self.module_status)
521 521 total = 0
522 522 for status in module_status:
523 523 if module_status[status] != 0:
524 524 module_bits = self.read_module(int(status))
525 525 bits={}
526 526 if module_bits:
527 527 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
528 528 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
529 529 parms[str(status)] = bits
530 530
531 531 total +=1
532 532
533 533 if total==0:
534 534 self.message = "No ABS Module detected. Please select 'Status'."
535 535 return False
536 536
537 537
538 538
539 539 self.message = "ABS Modules have been read"
540 540 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
541 541 return parms
542 542
543 543
544 544 def connected_modules(self):
545 545 """
546 546 This function returns the number of connected abs-modules without updating.
547 547 """
548 548 num = 0
549 549 print(self.module_status)
550 550 for i, status in enumerate(self.module_status):
551 551 if status != '0':
552 552 num += 1
553 553 #print('status {}:{}'.format(i+1, status))
554 554 return num
555 555
556 556 def send_multicast(self, message):
557 557 #print("Send multicast")
558 558 multicast_group = ('224.3.29.71', 10000)
559 559 # Create the datagram socket
560 560 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
561 561 sock.settimeout(1)
562 562 local_ip = os.environ.get('LOCAL_IP', '192.168.2.128')
563 563 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
564 564 sock.sendto(message.encode(), multicast_group)
565 565 print('Sending ' + message)
566 566 return sock
567 567
568 568 def status_device(self):
569 569 """
570 570 This function returns the status of all abs-modules as one.
571 571 If at least one module is connected, its answer is "1"
572 572 """
573 573 print ('Status device')
574 574 print (self.active_beam)
575 575 beams = ABSBeam.objects.filter(abs_conf=self)
576 576 #print beams[self.active_beam-1].module_6bits(0)
577 577 active = ABSActive.objects.get(pk=1)
578 578 if active.conf != self:
579 579 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
580 580 self.message += "\n"
581 581 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
582 582
583 583 return False
584 584
585 585 sock = self.send_multicast('MNTR')
586 586
587 587 n = 0
588 588 status = ['0'] * 64
589 589
590 590 while True:
591 591 #for i in range(32):
592 592 #if True:
593 593 try:
594 594 print("Recibiendo")
595 595 address = None
596 596 data, address = sock.recvfrom(2)
597 597 print (address, data)
598 598 print("!!!!")
599 599 data = data.decode()
600 600 aux_mon = "1"
601 601 aux_expected = aux_mon
602 602 if(len(data)==2):
603 603 print ("data[1]: ")
604 604 print (data[1])
605 605 aux_mon = fromChar2Binary(data[1])
606 606 print (aux_mon)
607 607 aux_i = (str(address[0]).split('.'))[3]
608 608 print (aux_i)
609 609 print ('Active beam')
610 610 beam_active = ABSBeam.objects.get(pk=self.active_beam)
611 611 print (beam_active)
612 612 aux_expected = beam_active.module_6bits(int(aux_i)-1)
613 613 print (aux_expected)
614 614
615 615 print ("data[0]: ")
616 616 print (data[0])
617 617
618 618 if data[0] == '1':
619 619 status[int(address[0][10:])-1] = '3'
620 620 if aux_mon == aux_expected:
621 621 print ('Es igual')
622 622 else:
623 623 print ('Es diferente')
624 624 status[int(address[0][10:])-1] = '2'
625 625
626 626 elif data[0] == '0':
627 627 status[int(address[0][10:])-1] = '1'
628 628 n += 1
629 629 print('Module: {} connected'.format(address))
630 630 except socket.timeout:
631 631 print('Timeout')
632 632 break
633 633 except:
634 634 print('Module: {} error'.format(address))
635 635 pass
636 636
637 637 sock.close()
638 638
639 639 if n > 0:
640 640 self.message = 'ABS modules Status have been updated.'
641 641 self.device.status = 1
642 642 else:
643 643 self.device.status = 0
644 644 self.message = 'No ABS module is connected.'
645 645 self.module_status = ''.join(status)
646 646 self.save()
647 647
648 648 return self.device.status
649 649
650 650
651 651 def send_beam(self, beam_pos):
652 652 """
653 653 This function connects to a multicast group and sends the beam number
654 654 to all abs modules.
655 655 """
656 656 print ('Send beam')
657 657 print (self.active_beam)
658 658 beams = ABSBeam.objects.filter(abs_conf=self)
659 659 #print beams[self.active_beam-1].module_6bits(0)
660 660 active = ABSActive.objects.get(pk=1)
661 661 if active.conf != self:
662 662 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
663 663 self.message += "\n"
664 664 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
665 665
666 666 return False
667 667
668 668 # Se manda a cero RC para poder realizar cambio de beam
669 669 if self.experiment is None:
670 670 confs = []
671 671 else:
672 672 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
673 673 confdds = ''
674 674 confjars = ''
675 675 confrc = ''
676 676 #TO STOP DEVICES: DDS-JARS-RC
677 677 for i in range(0,len(confs)):
678 678 if i==0:
679 679 for conf in confs:
680 680 if conf.device.device_type.name == 'dds':
681 681 confdds = conf
682 682 confdds.stop_device()
683 683 break
684 684 if i==1:
685 685 for conf in confs:
686 686 if conf.device.device_type.name == 'jars':
687 687 confjars = conf
688 688 confjars.stop_device()
689 689 break
690 690 if i==2:
691 691 for conf in confs:
692 692 if conf.device.device_type.name == 'rc':
693 693 confrc = conf
694 694 confrc.stop_device()
695 695 break
696 696 if beam_pos > 0:
697 697 beam_pos = beam_pos - 1
698 698 else:
699 699 beam_pos = 0
700 700
701 701 #El indice del apunte debe ser menor que el numero total de apuntes
702 702 #El servidor tcp en el embebido comienza a contar desde 0
703 703 status = ['0'] * 64
704 704 message = 'CHGB{}'.format(beam_pos)
705 705 sock = self.send_multicast(message)
706 706 while True:
707 707 #for i in range(32):
708 708 try:
709 709 data, address = sock.recvfrom(1024)
710 710 print (address, data)
711 711 data = data.decode()
712 712 if data == '1':
713 713 status[int(address[0][10:])-1] = '3'
714 714 elif data == '0':
715 715 status[int(address[0][10:])-1] = '1'
716 716 except socket.timeout:
717 717 print('Timeout')
718 718 break
719 719 except Exception as e:
720 720 print ('Error {}'.format(e))
721 721 pass
722 722
723 723 sock.close()
724 724
725 725 #Start DDS-RC-JARS
726 726 if confdds:
727 727 confdds.start_device()
728 728 if confrc:
729 729 #print confrc
730 730 confrc.start_device()
731 731 if confjars:
732 732 confjars.start_device()
733 733
734 734 self.message = "ABS Beam has been changed"
735 735 self.module_status = ''.join(status)
736 736 self.save()
737 737 return True
738 738
739 739
740 740 def get_absolute_url_import(self):
741 741 return reverse('url_import_abs_conf', args=[str(self.id)])
742 742
743 743 class ABSActive(models.Model):
744 744 conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration', on_delete=models.CASCADE)
745 745
746 746 class Meta:
747 747 db_table = 'abs_absactive'
748 748
749 749 class ABSBeam(models.Model):
750 750
751 751 name = models.CharField(max_length=60, default='Beam')
752 752 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
753 753 abs_conf = models.ForeignKey('ABSConfiguration', null=True,
754 754 verbose_name='ABS Configuration', on_delete=models.CASCADE)
755 755 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
756 756 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
757 757 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
758 758 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
759 759 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
760 760 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
761 761
762 762 class Meta:
763 763 db_table = 'abs_beams'
764 764
765 765 def __unicode__(self):
766 766 return u'%s' % (self.name)
767 767
768 768 def parms_to_dict(self):
769 769
770 770 parameters = {}
771 771 parameters['name'] = self.name
772 772 parameters['antenna'] = ast.literal_eval(self.antenna)
773 773 parameters['abs_conf'] = self.abs_conf.name
774 774 parameters['tx'] = ast.literal_eval(self.tx)
775 775 parameters['rx'] = ast.literal_eval(self.rx)
776 776 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
777 777 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
778 778 parameters['ues'] = ast.literal_eval(self.ues)
779 779 parameters['only_rx'] = json.loads(self.only_rx)
780 780
781 781 return parameters
782 782
783 783 def dict_to_parms(self, parameters):
784 784
785 785 self.name = parameters['name']
786 786 self.antenna = json.dumps(parameters['antenna'])
787 787 #self.abs_conf = parameters['abs_conf']
788 788 self.tx = json.dumps(parameters['tx'])
789 789 self.rx = json.dumps(parameters['rx'])
790 790 #self.s_time = parameters['s_time']
791 791 #self.e_time = parameters['e_time']
792 792 self.ues = json.dumps(parameters['ues'])
793 793 self.only_rx = json.dumps(parameters['only_rx'])
794 794 self.save()
795 795
796 796
797 797 def clone(self, **kwargs):
798 798
799 799 self.pk = None
800 800 self.id = None
801 801 for attr, value in kwargs.items():
802 802 setattr(self, attr, value)
803 803
804 804 self.save()
805 805
806 806 return self
807 807
808 808
809 809 def module_6bits(self, module):
810 810 """
811 811 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
812 812 """
813 813 module += 1
814 814 if module > 64:
815 815 beam_bits = ""
816 816 return beam_bits
817 817
818 818 data = ast.literal_eval(self.antenna)
819 819 up_data = data['antenna_up']
820 820 down_data = data['antenna_down']
821 821
822 822 pos = ip2position(module)
823 823 up_value = up_data[pos[0]][pos[1]]
824 824 down_value = down_data[pos[0]][pos[1]]
825 825
826 826 up_bits = up_conv_bits(up_value)
827 827 down_bits = down_conv_bits(down_value)
828 828 beam_bits = up_bits+down_bits
829 829
830 830 return beam_bits
831 831
832 832
833 833 @property
834 834 def get_upvalues(self):
835 835 """
836 836 This function reads antenna pattern and show the up-value of one abs module
837 837 """
838 838
839 839 data = ast.literal_eval(self.antenna)
840 840 up_data = data['antenna_up']
841 841
842 842 up_values = []
843 843 for data in up_data:
844 844 for i in range(0,8):
845 845 up_values.append(data[i])
846 846
847 847 return up_values
848 848
849 849 @property
850 850 def antenna_upvalues(self):
851 851 """
852 852 This function reads antenna pattern and show the up - values of one abs beam
853 853 in a particular order
854 854 """
855 855 data = ast.literal_eval(self.antenna)
856 856 up_data = data['antenna_up']
857 857
858 858 return up_data
859 859
860 860 @property
861 861 def antenna_downvalues(self):
862 862 """
863 863 This function reads antenna pattern and show the down - values of one abs beam
864 864 in a particular order
865 865 """
866 866 data = ast.literal_eval(self.antenna)
867 867 down_data = data['antenna_down']
868 868
869 869 return down_data
870 870
871 871 @property
872 872 def get_downvalues(self):
873 873 """
874 874 This function reads antenna pattern and show the down-value of one abs module
875 875 """
876 876
877 877 data = ast.literal_eval(self.antenna)
878 878 down_data = data['antenna_down']
879 879
880 880 down_values = []
881 881 for data in down_data:
882 882 for i in range(0,8):
883 883 down_values.append(data[i])
884 884
885 885 return down_values
886 886
887 887 @property
888 888 def get_up_ues(self):
889 889 """
890 890 This function shows the up-ues-value of one beam
891 891 """
892 892 data = ast.literal_eval(self.ues)
893 893 up_ues = data['up']
894 894
895 895 return up_ues
896 896
897 897 @property
898 898 def get_down_ues(self):
899 899 """
900 900 This function shows the down-ues-value of one beam
901 901 """
902 902 data = ast.literal_eval(self.ues)
903 903 down_ues = data['down']
904 904
905 905 return down_ues
906 906
907 907 @property
908 908 def get_up_onlyrx(self):
909 909 """
910 910 This function shows the up-onlyrx-value of one beam
911 911 """
912 912 data = json.loads(self.only_rx)
913 913 up_onlyrx = data['up']
914 914
915 915 return up_onlyrx
916 916
917 917 @property
918 918 def get_down_onlyrx(self):
919 919 """
920 920 This function shows the down-onlyrx-value of one beam
921 921 """
922 922 data = json.loads(self.only_rx)
923 923 down_onlyrx = data['down']
924 924
925 925 return down_onlyrx
926 926
927 927 @property
928 928 def get_tx(self):
929 929 """
930 930 This function shows the tx-values of one beam
931 931 """
932 932 data = json.loads(self.tx)
933 933
934 934 return data
935 935
936 936 @property
937 937 def get_uptx(self):
938 938 """
939 939 This function shows the up-tx-values of one beam
940 940 """
941 941 data = json.loads(self.tx)
942 942 up_data = data['up']
943 943
944 944 up_values = []
945 945 for data in up_data:
946 946 for i in range(0,8):
947 947 up_values.append(data[i])
948 948
949 949 return up_values
950 950
951 951 @property
952 952 def get_downtx(self):
953 953 """
954 954 This function shows the down-tx-values of one beam
955 955 """
956 956 data = json.loads(self.tx)
957 957 down_data = data['down']
958 958
959 959 down_values = []
960 960 for data in down_data:
961 961 for i in range(0,8):
962 962 down_values.append(data[i])
963 963
964 964 return down_values
965 965
966 966
967 967
968 968 @property
969 969 def get_rx(self):
970 970 """
971 971 This function shows the rx-values of one beam
972 972 """
973 973 data = json.loads(self.rx)
974 974
975 975 return data
976 976
977 977 @property
978 978 def get_uprx(self):
979 979 """
980 980 This function shows the up-rx-values of one beam
981 981 """
982 982 data = json.loads(self.rx)
983 983 up_data = data['up']
984 984
985 985 up_values = []
986 986 for data in up_data:
987 987 for i in range(0,8):
988 988 up_values.append(data[i])
989 989
990 990 return up_values
991 991
992 992 @property
993 993 def get_downrx(self):
994 994 """
995 995 This function shows the down-rx-values of one beam
996 996 """
997 997 data = json.loads(self.rx)
998 998 down_data = data['down']
999 999
1000 1000 down_values = []
1001 1001 for data in down_data:
1002 1002 for i in range(0,8):
1003 1003 down_values.append(data[i])
1004 1004
1005 1005 return down_values
@@ -1,274 +1,305
1 1 import ast
2 2 import json
3 3 import requests
4 4 import numpy as np
5 5 from base64 import b64encode
6 6 from struct import pack
7 7
8 8 from django.urls import reverse
9 9 from django.db import models
10 10 from apps.main.models import Configuration
11 11 from apps.main.utils import Params
12 12 # Create your models here.
13 13
14 14 from django.core.validators import MinValueValidator, MaxValueValidator
15 15 from django.core.exceptions import ValidationError
16 16
17 17 from devices.dds_rest import api, data
18 18
19 19 ENABLE_TYPE = (
20 20 (False, 'Disabled'),
21 21 (True, 'Enabled'),
22 22 )
23 23 MOD_TYPES = (
24 24 (0, 'Single Tone'),
25 25 (1, 'FSK'),
26 26 (2, 'Ramped FSK'),
27 27 (3, 'Chirp'),
28 28 (4, 'BPSK'),
29 29 )
30 30
31 31 class DDSRestConfiguration(Configuration):
32 32
33 33 DDS_NBITS = 48
34 34
35 35 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
36 36 multiplier = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=4)
37 37
38 38 frequencyA_Mhz = models.DecimalField(verbose_name='Frequency A (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
39 39 frequencyA = models.BigIntegerField(verbose_name='Frequency A (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
40 40
41 41 frequencyB_Mhz = models.DecimalField(verbose_name='Frequency B (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
42 42 frequencyB = models.BigIntegerField(verbose_name='Frequency B (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
43 43
44 44 delta_frequency_Mhz = models.DecimalField(verbose_name='Delta frequency (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
45 45 delta_frequency = models.BigIntegerField(verbose_name='Delta frequency (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
46 46
47 47 update_clock_Mhz = models.DecimalField(verbose_name='Update clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
48 48 update_clock = models.BigIntegerField(verbose_name='Update clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**32-1)], blank=True, null=True)
49 49
50 50 ramp_rate_clock_Mhz = models.DecimalField(verbose_name='Ramp rate clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
51 51 ramp_rate_clock = models.BigIntegerField(verbose_name='Ramp rate clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**18-1)], blank=True, null=True)
52 52
53 53 phaseA_degrees = models.FloatField(verbose_name='Phase A (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], default=0)
54 54
55 55 phaseB_degrees = models.FloatField(verbose_name='Phase B (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], blank=True, null=True)
56 56
57 57 modulation = models.PositiveIntegerField(verbose_name='Modulation Type', choices = MOD_TYPES, default = 0)
58 58
59 59 amplitude_enabled = models.BooleanField(verbose_name='Amplitude Control', choices=ENABLE_TYPE, default=False)
60 60
61 61 amplitudeI = models.PositiveIntegerField(verbose_name='Amplitude CH1',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
62 62 amplitudeQ = models.PositiveIntegerField(verbose_name='Amplitude CH2',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
63 63
64 64
65 65 def get_nbits(self):
66 66
67 67 return self.DDS_NBITS
68 68
69 69 def clean(self):
70 70
71 71 if self.modulation in [1,2,3]:
72 72 if self.frequencyB is None or self.frequencyB_Mhz is None:
73 73 raise ValidationError({
74 74 'frequencyB': 'Frequency modulation has to be defined when FSK or Chirp modulation is selected'
75 75 })
76 76
77 77 if self.modulation in [4,]:
78 78 if self.phaseB_degrees is None:
79 79 raise ValidationError({
80 80 'phaseB': 'Phase modulation has to be defined when BPSK modulation is selected'
81 81 })
82 82
83 83 self.frequencyA_Mhz = data.binary_to_freq(self.frequencyA, self.clock*self.multiplier)
84 84 self.frequencyB_Mhz = data.binary_to_freq(self.frequencyB, self.clock*self.multiplier)
85 85
86 86 def verify_frequencies(self):
87 87
88 88 return True
89 89
90 90 def parms_to_text(self):
91 91
92 92 my_dict = self.parms_to_dict()['configurations']['byId'][str(self.id)]
93 93
94 94 text = data.dict_to_text(my_dict)
95 95
96 96 return text
97 97
98 98 def status_device(self):
99 99 print("Status ")
100 100 try:
101 101 self.device.status = 0
102 102 payload = self.request('status')
103 103 if payload['status']=='generating RF':
104 104 self.device.status = 3
105 105 elif payload['status']=='no generating RF':
106 106 self.device.status = 2
107 107 else:
108 108 self.device.status = 1
109 109 self.device.save()
110 110 self.message = 'DDS REST status: {}'.format(payload['status'])
111 111 return False
112 112 except Exception as e:
113 113 if 'No route to host' not in str(e):
114 114 self.device.status = 4
115 115 self.device.save()
116 116 self.message = 'DDS REST status: {}'.format(str(e))
117 117 return False
118 118
119 119 self.device.save()
120 120 return True
121 121
122 122 def reset_device(self):
123 123
124 answer = api.reset(ip = self.device.ip_address,
125 port = self.device.port_address)
126
127 if answer[0] != "1":
128 self.message = 'DDS - {}'.format(answer[2:])
129 return 0
124 try:
125 payload = self.request('reset', 'post')
126 if payload['reset']=='ok':
127 self.message = 'DDS REST restarted OK'
128 self.device.status = 2
129 self.device.save()
130 else:
131 self.message = 'DDS REST restart fail'
132 self.device.status = 4
133 self.device.save()
134 except Exception as e:
135 self.message = 'DDS REST reset: {}'.format(str(e))
136 return False
130 137
131 self.message = 'DDS - {}'.format(answer[2:])
132 return 1
138 return True
133 139
134 140 def stop_device(self):
135 141
136 142 try:
137 answer = api.disable_rf(ip = self.device.ip_address,
138 port = self.device.port_address)
139
140 return self.status_device()
141
143 payload = self.request('stop', 'post',data=json.dumps({'_rf_enable':0}))
144 self.message = 'DDS REST: {}'.format(payload['stop'])
145 if payload['stop']=='ok':
146 self.device.status = 2
147 self.device.save()
148 else:
149 self.device.status = 4
150 self.device.save()
151 return False
142 152 except Exception as e:
143 self.message = str(e)
153 if 'No route to host' not in str(e):
154 self.device.status = 4
155 else:
156 self.device.status = 0
157 self.message = 'DDS REST stop: {}'.format(str(e))
158 self.device.save()
144 159 return False
145 160
161 return True
162
146 163 def start_device(self):
147 164
148 165 try:
149 answer = api.enable_rf(ip = self.device.ip_address,
150 port = self.device.port_address)
151
152 return self.status_device()
153
166 payload = self.request('start', 'post',data=json.dumps({'_rf_enable':1}))
167 self.message = 'DDS REST start: {}'.format(payload['start'])
168 if payload['start']=='ok':
169 self.device.status = 3
170 self.device.save()
171 else:
172 self.device.status = 2
173 self.device.save()
174 return False
154 175 except Exception as e:
155 self.message = str(e)
176 if 'No route to host' not in str(e):
177 self.device.status = 4
178 else:
179 self.device.status = 0
180 self.message = 'DDS REST start: {}'.format(str(e))
181 self.device.save()
156 182 return False
157 183
184 return True
185
158 186 def read_device(self):
159 187
160 parms = api.read_config(ip = self.device.ip_address,
161 port = self.device.port_address)
188 parms = self.request('read')
189 print(parms)
162 190 if not parms:
163 self.message = "Could not read DDS parameters from this device"
191 self.message = "Could not read DDS REST parameters from this device"
164 192 return parms
165 193
166 194 self.message = ""
167 195 return parms
168 196
169 197 def arma_control(self,l_clock,l_multiplier,l_modulation):
170 198 sysclock = l_clock*l_multiplier
171 199 pll_range = 0
172 200 if(sysclock>=200):
173 201 pll_range = 1
174 202 l_control = ((l_modulation<<9)+(pll_range<<22)+(l_multiplier<<16)).to_bytes(4,'little')
175 203 return l_control
176 204
177 205 def conv_phase(self,l_phase):
178 206
179 207 l_phase_2B = int((l_phase*(2**14)/360)).to_bytes(2,'little')
180 208 return l_phase_2B
181 209
182 210 def arma_data_write(self):
183 211 #clock = RCClock.objects.get(rc_configuration=self)
184 212 clock = self.clock
185 213 print(clock)
186 214 multiplier = self.multiplier
187 215 print(multiplier)
188 216 frequencyA_Mhz = self.frequencyA_Mhz
189 217 print(frequencyA_Mhz)
190 218 frequencyA = self.frequencyA
191 219 print(frequencyA)
192 220 frequencyB_Mhz = self.frequencyB_Mhz
193 221 print(frequencyB_Mhz)
194 222 frequencyB = self.frequencyB
195 223 print(frequencyB)
196 224 phaseA_degrees = self.phaseA_degrees or 0
197 225 print(phaseA_degrees)
198 226 phaseB_degrees = self.phaseB_degrees or 0
199 227 print(phaseB_degrees)
200 228 modulation = self.modulation or 0
201 229 print(modulation)
202 230 amplitude_enabled = self.amplitude_enabled or 0
203 231 print(amplitude_enabled)
204 232 amplitudeI = self.amplitudeI or 0
205 233 print(amplitudeI)
206 234 amplitudeQ = self.amplitudeQ or 0
207 235 print(amplitudeQ)
208 236 delta_frequency = self.delta_frequency or 0
209 237 print(delta_frequency)
210 238 update_clock = self.update_clock or 0
211 239 print(update_clock)
212 240 ramp_rate_clock = self.ramp_rate_clock or 0
213 241 print(ramp_rate_clock)
214
242 osrr = 0
243 qdac = 0
215 244 control = self.arma_control(clock,multiplier,modulation)
216 245 phase1 = self.conv_phase(phaseA_degrees)
217 246 phase2 = self.conv_phase(phaseB_degrees)
218 247
219 248 cadena_json = {'clock': (b64encode(pack('<f',clock))).decode("UTF-8"),\
220 249 'multiplier': (b64encode(pack('<B',multiplier))).decode("UTF-8"),\
221 250 'frequencyA': (b64encode((frequencyA).to_bytes(6,'little'))).decode("UTF-8"),\
222 251 'frequencyB': (b64encode((frequencyB).to_bytes(6,'little'))).decode("UTF-8"),\
223 252 'delta_frequency': (b64encode((delta_frequency).to_bytes(6,'little'))).decode("UTF-8"),\
224 253 'update_clock': (b64encode((update_clock).to_bytes(4,'little'))).decode("UTF-8"),\
225 254 'ramp_rate_clock': (b64encode((ramp_rate_clock).to_bytes(3,'little'))).decode("UTF-8"),\
226 255 'control': (b64encode(control)).decode("UTF-8"),\
227 256 'amplitudeI': (b64encode((amplitudeI).to_bytes(2,'little'))).decode("UTF-8"),\
228 257 'amplitudeQ': (b64encode((amplitudeQ).to_bytes(2,'little'))).decode("UTF-8"),\
229 258 '_phase1': (b64encode((phase1))).decode("UTF-8"),\
230 '_phase2': (b64encode((phase2))).decode("UTF-8")
259 '_phase2': (b64encode((phase2))).decode("UTF-8"),\
260 'osrr': (b64encode((osrr).to_bytes(1,'little'))).decode("UTF-8"),\
261 'qdac': (b64encode((qdac).to_bytes(2,'little'))).decode("UTF-8")
231 262 }
232 263 return cadena_json
233 264
234 265 def write_device(self, raw=False):
235 266 print("Ingreso a write")
236 267 try:
237 268
238 269 if not raw:
239 270 data = self.arma_data_write()
240 271 print(data)
241 272 payload = self.request('write', 'post', data=json.dumps(data))
242 273 print(payload)
243 274 if payload['write'] == 'ok':
244 275 self.device.status = 3
245 276 self.device.save()
246 277 self.message = 'DDS Rest write configured and started'
247 278 else:
248 279 self.message = payload['programming']
249 280 if payload['programming'] == 'fail':
250 281 self.message = 'DDS Rest write: error programming DDS chip'
251 282 if raw:
252 283 return b64encode(data)
253 284
254 285
255 286 except Exception as e:
256 287 if 'No route to host' not in str(e):
257 288 self.device.status = 4
258 289 else:
259 290 self.device.status = 0
260 291 self.message = 'DDS Rest write: {}'.format(str(e))
261 292 self.device.save()
262 293 return False
263 294
264 295 return True
265 296
266 297 def request(self, cmd, method='get', **kwargs):
267 298 print("Ingreso a request")
268 299 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
269 300 payload = req.json()
270 301
271 302 return payload
272 303
273 304 class Meta:
274 305 db_table = 'ddsrest_configurations'
@@ -1,463 +1,576
1 1 {% extends "dev_conf_edit.html" %}
2 2 {% load bootstrap4 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5
6 6 {% block dds_rest%}
7 7
8 8 {% bootstrap_field form.template layout='horizontal' size='medium' %}
9 9 {% bootstrap_field form.device layout='horizontal' size='medium' %}
10 10 {% bootstrap_field form.label layout='horizontal' size='medium' %}
11 11 {% bootstrap_field form.experiment layout='horizontal' size='medium' %}
12 12
13 13 {% bootstrap_field form.clock layout='horizontal' size='medium' %}
14 14 {% bootstrap_field form.multiplier layout='horizontal' size='medium' %}
15 15
16 16 <div style="display: flex; justify-content: flex-end">
17 17 <div class="form-check">
18 18 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_fA" value="" >Mostrar Decimal</label>
19 19 </div>
20 20 </div>
21 21 {% bootstrap_field form.frequencyA_Mhz layout='horizontal' size='medium' %}
22 22 <div id='id_row_fAbin'>
23 23 {% bootstrap_field form.frequencyA layout='horizontal' size='medium' %}
24 24 <div style="display: flex; justify-content: flex-end">
25 25 <small type="text" id="id_aux_fAbin" class="form-text text-muted">1000 0000 </small>
26 26 </div>
27 27 <br>
28 28 </div>
29 29
30 30 <div style="display: flex; justify-content: flex-end">
31 31 <div class="form-check">
32 32 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_fB" value="" >Mostrar Decimal</label>
33 33 </div>
34 34 </div>
35 35 {% bootstrap_field form.frequencyB_Mhz layout='horizontal' size='medium' %}
36 36 <div id='id_row_fBbin'>
37 37 {% bootstrap_field form.frequencyB layout='horizontal' size='medium' %}
38 38 <div style="display: flex; justify-content: flex-end">
39 39 <small type="text" id="id_aux_fBbin" class="form-text text-muted">1000 0000 </small>
40 40 </div>
41 41 <br>
42 42 </div>
43 43
44 44 <div style="display: flex; justify-content: flex-end">
45 45 <div class="form-check">
46 46 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_df" value="" >Mostrar Decimal</label>
47 47 </div>
48 48 </div>
49 49 {% bootstrap_field form.delta_frequency_Mhz layout='horizontal' size='medium' %}
50 50 <div id='id_row_dfbin'>
51 51 {% bootstrap_field form.delta_frequency layout='horizontal' size='medium' %}
52 52 <div style="display: flex; justify-content: flex-end">
53 53 <small type="text" id="id_aux_deltabin" class="form-text text-muted">1000 0000 </small>
54 54 </div>
55 55 <br>
56 56 </div>
57 57
58 58 <div style="display: flex; justify-content: flex-end">
59 59 <div class="form-check">
60 60 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_ramp" value="" >Mostrar Decimal</label>
61 61 </div>
62 62 </div>
63 63 <div class="form-group row">
64 64 <label class="col-md-3 col-form-label" for="id_ramp_rate_clock_us">Ramp rate clock(us)</label>
65 65 <div class="col-md-9">
66 66 <input type="number" name="ramp_rate_clock_us" step="1e-16" class="form-control" placeHolder="Ramp rate clock(us)" title id="id_ramp_rate_clock_us">
67 67 </div>
68 68 </div>
69 69 <div id='id_row_rampbin'>
70 70 {% bootstrap_field form.ramp_rate_clock_Mhz layout='horizontal' size='medium' %}
71 71 {% bootstrap_field form.ramp_rate_clock layout='horizontal' size='medium' %}
72 72 <div style="display: flex; justify-content: flex-end">
73 73 <small type="text" id="id_aux_rampbin" class="form-text text-muted">1000 0000 </small>
74 74 </div>
75 75 <br>
76 76 </div>
77 77
78 78 <div style="display: flex; justify-content: flex-end">
79 79 <div class="form-check">
80 80 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_phaseA" value="" >Mostrar Decimal</label>
81 81 </div>
82 82 </div>
83 83 {% bootstrap_field form.phaseA_degrees layout='horizontal' size='medium' %}
84 84 <div id='id_row_phaseA'>
85 85 <div style="display: flex; justify-content: flex-end">
86 86 <small type="text" id="id_aux_phaseAdec" class="form-text text-muted">9282 </small>
87 87 </div>
88 88 <div style="display: flex; justify-content: flex-end">
89 89 <small type="text" id="id_aux_phaseAbin" class="form-text text-muted">1000 0000 </small>
90 90 </div>
91 91 <br>
92 92 </div>
93 93
94 94 <div style="display: flex; justify-content: flex-end">
95 95 <div class="form-check">
96 96 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_phaseB" value="" >Mostrar Decimal</label>
97 97 </div>
98 98 </div>
99 99 {% bootstrap_field form.phaseB_degrees layout='horizontal' size='medium' %}
100 100 <div id='id_row_phaseB'>
101 101 <div style="display: flex; justify-content: flex-end">
102 102 <small type="text" id="id_aux_phaseBdec" class="form-text text-muted">9876 </small>
103 103 </div>
104 104 <div style="display: flex; justify-content: flex-end">
105 105 <small type="text" id="id_aux_phaseBbin" class="form-text text-muted">1000 0000 </small>
106 106 </div>
107 107 <br>
108 108 </div>
109 109
110 110 {% bootstrap_field form.modulation layout='horizontal' size='medium' %}
111 111 {% bootstrap_field form.amplitude_enabled layout='horizontal' size='medium' %}
112 112
113 <div style="display: flex; justify-content: flex-end">
114 <div class="form-check">
115 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_amplitudeI" value="" >Mostrar Decimal</label>
116 </div>
117 </div>
113 118 {% bootstrap_field form.amplitudeI layout='horizontal' size='medium' %}
119 <div id='id_row_amplitudeI'>
120 <div style="display: flex; justify-content: flex-end">
121 <small type="text" id="id_aux_amplitudeIdec" class="form-text text-muted">35 </small>
122 </div>
123 <div style="display: flex; justify-content: flex-end">
124 <small type="text" id="id_aux_amplitudeIbin" class="form-text text-muted">0000 0000 0010 </small>
125 </div>
126 <br>
127 </div>
128
129 <div style="display: flex; justify-content: flex-end">
130 <div class="form-check">
131 <label class="form-check-label" ><input type="checkbox" class="form-check-input" id="id_chkbin_amplitudeQ" value="" >Mostrar Decimal</label>
132 </div>
133 </div>
114 134 {% bootstrap_field form.amplitudeQ layout='horizontal' size='medium' %}
135 <div id='id_row_amplitudeQ'>
136 <div style="display: flex; justify-content: flex-end">
137 <small type="text" id="id_aux_amplitudeQdec" class="form-text text-muted">40 </small>
138 </div>
139 <div style="display: flex; justify-content: flex-end">
140 <small type="text" id="id_aux_amplitudeQbin" class="form-text text-muted">0000 1010 1000 </small>
141 </div>
142 <br>
143 </div>
115 144
116 145
117 146 {% endblock %}
118 147
119 148 {% block extra-js%}
120 149 <script src="{% static 'js/dds_conversion.js' %}"></script>
121 150 <script type="text/javascript">
122 151 $("#id_row_fAbin").hide();
123 152 $("#id_chkbin_fA").on('change', function() {
124 153 hidefA();
125 154 });
126 155
127 156 $("#id_row_fBbin").hide();
128 157 $("#id_chkbin_fB").on('change', function() {
129 158 hidefB();
130 159 });
131 160
132 161 $("#id_row_dfbin").hide();
133 162 $("#id_chkbin_df").on('change', function() {
134 163 hidedf();
135 164 });
136 165
137 166 $("#id_row_rampbin").hide();
138 167 $("#id_chkbin_ramp").on('change', function() {
139 168 hideramp();
140 169 });
141 170
142 171 $("#id_row_phaseA").hide();
143 172 $("#id_chkbin_phaseA").on('change', function() {
144 173 hidephaseA();
145 174 });
146 175
147 176 $("#id_row_phaseB").hide();
148 177 $("#id_chkbin_phaseB").on('change', function() {
149 178 hidephaseB();
150 179 });
180
181 $("#id_row_amplitudeI").hide();
182 $("#id_chkbin_amplitudeI").on('change', function() {
183 hideamplitudeI();
184 });
185
186 $("#id_row_amplitudeQ").hide();
187 $("#id_chkbin_amplitudeQ").on('change', function() {
188 hideamplitudeQ();
189 });
151 190
152 191 $("#id_clock").on('change', function() {
153 192 updateFrequencies();
154 193 });
155 194
156 195 $("#id_multiplier").on('change', function() {
157 196 updateFrequencies();
158 197 });
159 198
160 199 $("#id_frequencyA_Mhz").on('change', function() {
161 200 updateBinaryFrequencies();
162 201 });
163 202
164 203 $("#id_frequencyA").on('change', function() {
165 204 updateFrequencies();
166 205 });
167 206
168 207 $("#id_frequencyB_Mhz").on('change', function() {
169 208 updateBinaryFrequencies();
170 209 });
171 210
172 211 $("#id_frequencyB").on('change', function() {
173 212 updateFrequencies();
174 213 });
175 214
176 215 $("#id_delta_frequency").on('change', function() {
177 216 updateFrequencyDelta();
178 217 });
179 218
180 219 $("#id_delta_frequency_Mhz").on('change', function() {
181 220 updateBinaryFrequencyDelta();
182 221 });
183 222
184 223 $("#id_ramp_rate_clock").on('change', function() {
185 224 updateFrequencyRamp();
186 225 });
187 226
188 227 $("#id_ramp_rate_clock_us").on('change', function() {
189 228 updateFrequencyMhzRamp();
190 229 });
191 230
192 231 $("#id_ramp_rate_clock_Mhz").on('change', function() {
193 232 updateBinaryFrequencyRamp();
194 233 });
195 234
196 235 $("#id_phaseA_degrees").on('change', function() {
197 236 updatephaseAbindec();
198 237 });
199 238
200 239 $("#id_phaseB_degrees").on('change', function() {
201 240 updatephaseBbindec();
202 241 });
203 242
243 $("#id_amplitudeI").on('change', function() {
244 updateamplitudeIindec();
245 });
246
247 $("#id_amplitudeQ").on('change', function() {
248 updateamplitudeQindec();
249 });
250
204 251 function updateBinaryFrequencies() {
205 252
206 253 var clock = $("#id_clock").val();
207 254 var multiplier = $("#id_multiplier").val();
208 255 var freq = $("#id_frequencyA_Mhz").val();
209 256 var freq_mod = $("#id_frequencyB_Mhz").val();
210 257
211 258 var mclock = clock*multiplier;
212 259
213 260 var freq_bin = freq2Binary(mclock, freq);
214 261 var freq_mod_bin = freq2Binary(mclock, freq_mod);
215 262
216 263 $("#id_frequencyA").val(freq_bin);
217 264 $("#id_frequencyB").val(freq_mod_bin);
218 265
219 266 freq = binary2Freq(mclock, freq_bin);
220 267 freq_mod = binary2Freq(mclock, freq_mod_bin);
221 268
222 269 $("#id_frequencyA_Mhz").val(freq);
223 270 $("#id_frequencyB_Mhz").val(freq_mod);
224 271
225 272 }
226 273
227 274 function updateFrequencies() {
228 275 console.log("Ingreso a updateFrequencies");
229 276 var clock = $("#id_clock").val();
230 277 var multiplier = $("#id_multiplier").val();
231 278 var freq_bin = $("#id_frequencyA").val();
232 279 var freq_mod_bin = $("#id_frequencyB").val();
233 280 var freqdelta_bin = $("#id_delta_frequency").val();
234 281 var freqramp_bin = $("#id_ramp_rate_clock").val();
235 282
236 283 var mclock = clock*multiplier;
237 284
238 285 var freq = binary2Freq(mclock, freq_bin);
239 286 var freq_mod = binary2Freq(mclock, freq_mod_bin);
240 287 var freqdelta = binary2FreqDelta(mclock, freqdelta_bin);
241 288 var freq_ramp = binary2Ramp(mclock, freqramp_bin);
242 289
243 290 $("#id_frequencyA_Mhz").val(freq);
244 291 $("#id_frequencyB_Mhz").val(freq_mod);
245 292 $("#id_delta_frequency_Mhz").val(freqdelta);
246 293 $("#id_ramp_rate_clock_Mhz").val(freq_ramp);
247 294 }
248 295
249 296 function updateFrequencyDelta() {
250 297 console.log("Ingreso a updateFrequencyDelta");
251 298 var clock = $("#id_clock").val();
252 299 var multiplier = $("#id_multiplier").val();
253 300 var freq_bin = $("#id_delta_frequency").val();
254 301
255 302 var mclock = clock*multiplier;
256 303
257 304 var freq = binary2FreqDelta(mclock, freq_bin);
258 305 console.log(freq);
259 306 $("#id_delta_frequency_Mhz").val(freq);
260 307 }
261 308
262 309 function updateBinaryFrequencyDelta() {
263 310 console.log("Ingreso a updateBInaryFrequencyDelta");
264 311 var clock = $("#id_clock").val();
265 312 var multiplier = $("#id_multiplier").val();
266 313 var freq = $("#id_delta_frequency_Mhz").val();
267 314 console.log(clock);
268 315 console.log(multiplier);
269 316 console.log(freq);
270 317
271 318 var mclock = clock*multiplier;
272 319 console.log(mclock);
273 320
274 321 var freq_bin = freqDelta2Binary(mclock, freq);
275 322
276 323 console.log(freq_bin);
277 324 $("#id_delta_frequency").val(freq_bin);
278 325
279 326 document.getElementById("id_aux_deltabin").innerHTML = numToString(parseInt(freq_bin, 10), 2, 48).match(/.{1,4}/g).join(' ');
280 327 }
281 328
282 329 function updateFrequencyRamp() {
283 330 console.log("Ingreso a updateFrequencyRamp");
284 331 var clock = $("#id_clock").val();
285 332 var multiplier = $("#id_multiplier").val();
286 333 var freq_bin = $("#id_ramp_rate_clock").val();
287 334
288 335 var mclock = clock*multiplier;
289 336
290 337 var freq = binary2Ramp(mclock, freq_bin);
291 338 console.log(freq);
292 339 $("#id_ramp_rate_clock_Mhz").val(freq);
293 340 }
294 341
295 342 function updateBinaryFrequencyRamp() {
296 343 console.log("Ingreso a updateBInaryFrequencyRamp");
297 344 var clock = $("#id_clock").val();
298 345 var multiplier = $("#id_multiplier").val();
299 346 var freq = $("#id_ramp_rate_clock_Mhz").val();
300 347
301 348 var mclock = clock*multiplier;
302 349
303 350 var freq_bin = freqRamp2Binary(mclock, freq);
304 351 console.log(freq_bin);
305 352 $("#id_ramp_rate_clock").val(freq_bin);
306 353 }
307 354
308 355 function updateFrequencyMhzRamp() {
309 356 console.log("Ingreso a updateFrequencyMhzRamp");
310 357 var step_us = $("#id_ramp_rate_clock_us").val();
311 358
312 359 var freq = us2Ramp(step_us);
313 360 console.log(freq);
314 361 $("#id_ramp_rate_clock_Mhz").val(freq);
315 362 updateBinaryFrequencyRamp();
316 363 }
317 364
318 365 function hidefA() {
319 366 var checkbox = $("#id_chkbin_fA");
320 367 var freq_bin = $("#id_row_fAbin");
321 368 var val_freq = $("#id_frequencyA");
322 369
323 370 console.log("Ingreso a hidefA");
324 371 if (checkbox.is(':checked')) {
325 372 freq_bin.show();
326 373 console.log(val_freq.val());
327 374 document.getElementById("id_aux_fAbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
328 375 }
329 376 else{
330 377 freq_bin.hide();
331 378 }
332 379 }
333 380
334 381 function hidefB() {
335 382 var checkbox = $("#id_chkbin_fB");
336 383 var freq_bin = $("#id_row_fBbin");
337 384 var val_freq = $("#id_frequencyB");
338 385
339 386 console.log("Ingreso a hidefB");
340 387 if (checkbox.is(':checked')) {
341 388 freq_bin.show();
342 389 console.log(val_freq.val());
343 390 document.getElementById("id_aux_fBbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
344 391 }
345 392 else{
346 393 freq_bin.hide();
347 394 }
348 395 }
349 396
350 397 function hidedf() {
351 398 var checkbox = $("#id_chkbin_df");
352 399 var freq_bin = $("#id_row_dfbin");
353 400 var val_freq = $("#id_delta_frequency");
354 401
355 402 console.log("Ingreso a hidedf");
356 403 if (checkbox.is(':checked')) {
357 404 freq_bin.show();
358 405 console.log(val_freq.val());
359 406 document.getElementById("id_aux_deltabin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 48).match(/.{1,4}/g).join(' ');
360 407 }
361 408 else{
362 409 freq_bin.hide();
363 410 }
364 411 }
365 412
366 413 function hideramp() {
367 414 var checkbox = $("#id_chkbin_ramp");
368 415 var freq_bin = $("#id_row_rampbin");
369 416 var val_freq = $("#id_ramp_rate_clock");
370 417
371 418 console.log("Ingreso a hideramp");
372 419 if (checkbox.is(':checked')) {
373 420 freq_bin.show();
374 421 console.log(val_freq.val());
375 422 document.getElementById("id_aux_rampbin").innerHTML = numToString(parseInt(val_freq.val(), 10), 2, 20).match(/.{1,4}/g).join(' ');
376 423 }
377 424 else{
378 425 freq_bin.hide();
379 426 }
380 427 }
381 428
382 429 function hidephaseA() {
383 430 var checkbox = $("#id_chkbin_phaseA");
384 431 var freq_bin = $("#id_row_phaseA");
385 432 var phase_degree = $("#id_phaseA_degrees");
386 433
387 434 console.log("Ingreso a hidephaseA");
388 435 if (checkbox.is(':checked')) {
389 436 freq_bin.show();
390 437 console.log(phase_degree.val());
391 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
438 var phase_degree_dec = parseInt(phase_degree.val()*((2**14-1)/360.0),10);
392 439 console.log(phase_degree_dec);
393 440 document.getElementById("id_aux_phaseAdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
394 441 document.getElementById("id_aux_phaseAbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
395 442
396 443 }
397 444 else{
398 445 freq_bin.hide();
399 446 }
400 447 }
401 448
402 449 function hidephaseB() {
403 450 var checkbox = $("#id_chkbin_phaseB");
404 451 var freq_bin = $("#id_row_phaseB");
405 452 var phase_degree = $("#id_phaseB_degrees");
406 453
407 454 console.log("Ingreso a hidephaseB");
408 455 if (checkbox.is(':checked')) {
409 456 freq_bin.show();
410 457 console.log(phase_degree.val());
411 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
458 var phase_degree_dec = parseInt(phase_degree.val()*((2**14-1)/360.0),10);
412 459 console.log(phase_degree_dec);
413 460 document.getElementById("id_aux_phaseBdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
414 461 document.getElementById("id_aux_phaseBbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
415 462
416 463 }
417 464 else{
418 465 freq_bin.hide();
419 466 }
420 467 }
421 468
469 function hideamplitudeI() {
470 var checkbox = $("#id_chkbin_amplitudeI");
471 var freq_bin = $("#id_row_amplitudeI");
472 var phase_degree = $("#id_amplitudeI");
473
474 console.log("Ingreso a hideamplitudeI");
475 if (checkbox.is(':checked')) {
476 freq_bin.show();
477 console.log(phase_degree.val());
478 var phase_degree_dec = parseInt(phase_degree.val()*((2**12-1)/100.0),10);
479 console.log(phase_degree_dec);
480 document.getElementById("id_aux_amplitudeIdec").innerHTML = numToString(phase_degree_dec, 10, 4).match(/.{1,4}/g).join(' ');
481 document.getElementById("id_aux_amplitudeIbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 12).match(/.{1,4}/g).join(' ');
482
483 }
484 else{
485 freq_bin.hide();
486 }
487 }
488
489 function hideamplitudeQ() {
490 var checkbox = $("#id_chkbin_amplitudeQ");
491 var freq_bin = $("#id_row_amplitudeQ");
492 var phase_degree = $("#id_amplitudeQ");
493
494 console.log("Ingreso a hideamplitudeQ");
495 if (checkbox.is(':checked')) {
496 freq_bin.show();
497 console.log(phase_degree.val());
498 var phase_degree_dec = parseInt(phase_degree.val()*((2**12-1)/100.0),10);
499 console.log(phase_degree_dec);
500 document.getElementById("id_aux_amplitudeQdec").innerHTML = numToString(phase_degree_dec, 10, 4).match(/.{1,4}/g).join(' ');
501 document.getElementById("id_aux_amplitudeQbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 12).match(/.{1,4}/g).join(' ');
502
503 }
504 else{
505 freq_bin.hide();
506 }
507 }
508
422 509 function updatephaseAbindec() {
423 510 var freq_bin = $("#id_row_phaseA");
424 511 var phase_degree = $("#id_phaseA_degrees");
425 512
426 console.log("Ingreso a cupdatephaseAbindec");
513 console.log("Ingreso a updatephaseAbindec");
427 514 console.log(phase_degree.val());
428 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
515 var phase_degree_dec = parseInt(phase_degree.val()*((2**14-1)/360.0),10);
429 516 console.log(phase_degree_dec);
430 517 document.getElementById("id_aux_phaseAdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
431 518 document.getElementById("id_aux_phaseAbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
432 519
433 520 }
434 521
435 522 function updatephaseBbindec() {
436 523 var freq_bin = $("#id_row_phaseB");
437 524 var phase_degree = $("#id_phaseB_degrees");
438 525
439 console.log("Ingreso a cupdatephaseBbindec");
526 console.log("Ingreso a updatephaseBbindec");
440 527 console.log(phase_degree.val());
441 var phase_degree_dec = parseInt(phase_degree.val()*((2**14)/360.0),10);
528 var phase_degree_dec = parseInt(phase_degree.val()*((2**14-1)/360.0),10);
442 529 console.log(phase_degree_dec);
443 530 document.getElementById("id_aux_phaseBdec").innerHTML = numToString(phase_degree_dec, 10, 5).match(/.{1,4}/g).join(' ');
444 531 document.getElementById("id_aux_phaseBbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 14).match(/.{1,4}/g).join(' ');
445 532
446 533 }
447 534
535 // Para ingresar amplitud CH1 como porcentaje y devuelve en decimal y binario
536 function updateamplitudeIindec() {
537 var freq_bin = $("#id_row_amplitudeI");
538 var phase_degree = $("#id_amplitudeI");
539
540 console.log("Ingreso a updateamplitudeIindec");
541 console.log(phase_degree.val());
542 var phase_degree_dec = parseInt(phase_degree.val()*((2**12-1)/100.0),10);
543 console.log(phase_degree_dec);
544 document.getElementById("id_aux_amplitudeIdec").innerHTML = numToString(phase_degree_dec, 10, 4).match(/.{1,4}/g).join(' ');
545 document.getElementById("id_aux_amplitudeIbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 12).match(/.{1,4}/g).join(' ');
546 }
547
548 // Para ingresar amplitud CH1 como porcentaje y devuelve en decimal y binario
549 function updateamplitudeQindec() {
550 var freq_bin = $("#id_row_amplitudeQ");
551 var phase_degree = $("#id_amplitudeQ");
552
553 console.log("Ingreso a updateamplitudeQindec");
554 console.log(phase_degree.val());
555 var phase_degree_dec = parseInt(phase_degree.val()*((2**12-1)/100.0),10);
556 console.log(phase_degree_dec);
557 document.getElementById("id_aux_amplitudeQdec").innerHTML = numToString(phase_degree_dec, 10, 4).match(/.{1,4}/g).join(' ');
558 document.getElementById("id_aux_amplitudeQbin").innerHTML = numToString(parseInt(phase_degree_dec, 10), 2, 12).match(/.{1,4}/g).join(' ');
559 }
560
448 561 function padStart(string, length, char) {
449 562 return length > 0 ?
450 563 padStart(char + string, --length, char) :
451 564 string;
452 565 }
453 566
454 567 function numToString(num, radix, length = num.length) {
455 568 const numString = num.toString(radix);
456 569 return numString.length === length ?
457 570 numString :
458 571 padStart(numString, length - numString.length, "0")
459 572 }
460 573
461 574 console.log(numToString(parseInt("37529996894754", 10), 2, 48));
462 575 </script>
463 576 {% endblock %} No newline at end of file
@@ -1,130 +1,138
1 1 [
2 2 {
3 3 "fields": {
4 4 "name": "JRO",
5 5 "description": ""
6 6 },
7 7 "model": "main.location",
8 8 "pk": 1
9 9 },
10 10 {
11 11 "fields": {
12 12 "name": "JASMET",
13 13 "description": ""
14 14 },
15 15 "model": "main.location",
16 16 "pk": 2
17 17 },
18 18 {
19 19 "fields": {
20 20 "name": "SOUSY",
21 21 "description": ""
22 22 },
23 23 "model": "main.location",
24 24 "pk": 3
25 25 },
26 26 {
27 27 "fields": {
28 28 "name": "JULIA",
29 29 "description": ""
30 30 },
31 31 "model": "main.location",
32 32 "pk": 4
33 33 },
34 34 {
35 35 "fields": {
36 36 "name": "CLAIRE",
37 37 "description": ""
38 38 },
39 39 "model": "main.location",
40 40 "pk": 5
41 41 },
42 42 {
43 43 "fields": {
44 44 "name": "IDI",
45 45 "description": ""
46 46 },
47 47 "model": "main.location",
48 48 "pk": 6
49 49 },
50 50 {
51 51 "fields": {
52 52 "name": "rc",
53 53 "description": ""
54 54 },
55 55 "model": "main.devicetype",
56 56 "pk": 1
57 57 },
58 58 {
59 59 "fields": {
60 60 "name": "dds",
61 61 "description": ""
62 62 },
63 63 "model": "main.devicetype",
64 64 "pk": 2
65 65 },
66 66 {
67 67 "fields": {
68 68 "name": "cgs",
69 69 "description": ""
70 70 },
71 71 "model": "main.devicetype",
72 72 "pk": 3
73 73 },
74 74 {
75 75 "fields": {
76 76 "name": "jars",
77 77 "description": ""
78 78 },
79 79 "model": "main.devicetype",
80 80 "pk": 4
81 81 },
82 82 {
83 83 "fields": {
84 84 "name": "abs",
85 85 "description": ""
86 86 },
87 87 "model": "main.devicetype",
88 88 "pk": 5
89 89 },
90 90 {
91 91 "fields": {
92 "name": "dds_rest",
93 "description": ""
94 },
95 "model": "main.devicetype",
96 "pk": 6
97 },
98 {
99 "fields": {
92 100 "name": "Operator"
93 101 },
94 102 "model": "auth.group",
95 103 "pk": 1
96 104 },
97 105 {
98 106 "fields": {
99 107 "name": "Developer"
100 108 },
101 109 "model": "auth.group",
102 110 "pk": 2
103 111 },
104 112 {
105 113 "fields": {
106 114 "password": "pbkdf2_sha256$24000$6RRL7xETgdgN$ORRPhrITZKzTTZHCm8T+Er6ght415kYKeU7QP3rry5M=",
107 115 "last_login": null,
108 116 "is_superuser": true,
109 117 "username": "admin",
110 118 "first_name": "Administrador",
111 119 "last_name": "IDI",
112 120 "email": "admin@admin.com",
113 121 "is_staff": true,
114 122 "is_active": true,
115 123 "date_joined": "2017-01-12T16:10:24.383",
116 124 "groups": [],
117 125 "user_permissions": []
118 126 },
119 127 "model": "auth.user",
120 128 "pk": 1
121 129 },
122 130 {
123 131 "fields": {
124 132 "user": 1,
125 133 "theme": "spacelab"
126 134 },
127 135 "model": "main.profile",
128 136 "pk": 1
129 137 }
130 138 ]
@@ -1,142 +1,219
1 1
2 2 :root{
3 3 --primary: #0200AE;
4 4 --dark-primary: #000080;
5 5 --light-primary: rgb(0, 0, 179, .7);
6 6 --secondary: #6F6F6F;
7 7 --tertiary: #0099FF;
8 8 --color-txt: #333;
9 9 --bg-main: rgba(80, 80, 80, .8);
10 10 --bg-invert: rgba(0, 0, 0, .2);
11 11 --bg-sections: #f9f9f9;
12 12 --bd-sections: 1px solid #D9D9D9;
13 13 --fs-nav: .875em;
14 14 --fs-trail: .87rem;
15 15 --hover-nav: rgba(0, 0, 0, 0.3);
16 16 --fg-nav: #2068A0;
17 17 --bs-nav: rgba(43, 43, 43, .4);
18 18 --bs-input: rgba(0, 113, 184, 0.5);
19 19 --bd-input: rgba(56, 181, 230, 0.75);
20 20 --bd-item: 1px solid #C9C9C9;
21 21 --bx-shadow: 0 2px 5px 0 var(--bs-nav);
22 22 }
23 23
24 24 body {
25 25 color: #444;
26 26 font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
27 27 font-size: 14px;
28 28 }
29 29
30 30 main {
31 31 min-width: 100%;
32 32 min-height: 400px;
33 33 }
34 34
35 35 a:link { -webkit-tap-highlight-color: var(--tertiary); }
36 36
37 37 .titulo {
38 38 color: #898989;
39 39 font-size: 2rem;
40 40 font-family: 'Dosis', Arial, Verdana, serif;
41 41 }
42 42
43 43 .titulo:after {
44 44 display: flex;
45 45 width: 60px;
46 46 border-bottom: 3px solid #48C7EC;
47 47 content: '';
48 48 padding-top: .5rem;
49 49 margin: 0;
50 50 }
51 51
52 52 #sidebar a {
53 53 color: gray;
54 54 padding: 0.1rem;
55 55 }
56 56
57 57 #sidebar h5 {
58 58 color:#333;
59 59 }
60 60
61 61 .text-blue {
62 62 color: #003A8E;
63 63 }
64 64
65 65 .text-skyblue {
66 66 color: #00addc;
67 67 }
68 68
69 69 .nopadding {
70 70 padding: 0px !important;
71 71 }
72 72
73 73 .nomargin {
74 74 margin: 0px !important;
75 75 }
76 76
77 77 .legend {
78 78 list-style: none;
79 79 padding-left: 1rem;
80 80 padding-top: 1rem;
81 81 }
82 82
83 83 .legend span {
84 84 padding-left: 1em;
85 85 }
86 86
87 87 #loader {
88 88 margin-top: 40px;
89 89 color: var(--tertiary);
90 90 }
91 91
92 92 #plot {
93 93 margin-top: 2em;
94 94 margin-bottom: 2em;
95 95 }
96 96
97 97 /* Change Buttons Bootstrap */
98 98 .btn-primary {
99 99 color: #fff;
100 100 background-color: #00addc !important;
101 101 border-color: #00addc !important;
102 102 }
103 103
104 104 .btn-primary:hover {
105 105 color: #fff;
106 106 background-color: #23527c !important;
107 107 border-color: #23527c !important;
108 108 }
109 109
110 110 .card-text {
111 111 font-size: 0.8rem;
112 112 }
113 113
114 114 .tools-date {
115 115 font-size: 0.8rem;
116 116 }
117 117
118 /*------------------------------------------------*/
119
120 .panel {
121 margin-bottom: 20px;
122 background-color: #fafafa;
123 border: 1px solid transparent;
124 border-radius: 4px;
125 -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
126 box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
127 }
128 .panel-body {
129 padding: 15px;
130 }
131 .panel-heading {
132 padding: 10px 15px;
133 border-bottom: 1px solid transparent;
134 border-top-left-radius: 3px;
135 border-top-right-radius: 3px;
136 }
137
138 .panel-title {
139 margin-top: 0;
140 margin-bottom: 0;
141
142
143 }
144
145 .panel-footer {
146 padding: 10px 15px;
147 background-color: #fafafa;
148 border-top: 1px solid #fafafa;
149 border-bottom-right-radius: 3px;
150 border-bottom-left-radius: 3px;
151 }
152
153 .panel-group {
154 margin-bottom: 20px;
155 }
156 .panel-group .panel {
157 margin-bottom: 0;
158 border-radius: 4px;
159 }
160 .panel-group .panel + .panel {
161 margin-top: 5px;
162 }
163 .panel-group .panel-heading {
164 border-bottom: 0;
165 }
166 .panel-group .panel-heading + .panel-collapse > .panel-body,
167
168 .panel-group .panel-footer {
169 border-top: 0;
170 }
171 .panel-group .panel-footer + .panel-collapse .panel-body {
172 border-bottom: 1px solid #fafafa;
173 }
174 .panel-default {
175 border-color: #fafafa;
176 }
177 .panel-default > .panel-heading {
178
179 background-color: #fafafa;
180 border-color: #fafafa;
181 }
182 .panel-default > .panel-heading + .panel-collapse > .panel-body {
183 border-top-color: #fafafa;
184 }
185 .panel-default > .panel-heading .badge {
186 color: #fafafa;
187 background-color: #fafafa;
188 }
189 .panel-default > .panel-footer + .panel-collapse > .panel-body {
190 border-bottom-color: #fafafa;
191 }
192
193
118 194 /* cards */
119 195
120 196 @media (min-width: 480px) {
121 197 .card-columns {
122 198 column-count: 2;
123 199 }
124 200 }
125 201
126 202 @media (min-width: 768px) {
127 203 .card-columns {
128 204 column-count: 3;
129 205 }
130 206 }
131 207
132 208 @media (min-width: 1180px) {
133 209 .card-columns {
134 210 column-count: 4;
135 211 }
136 212 }
137 213
138 214 @media (min-width: 1380px) {
139 215 .card-columns {
140 216 column-count: 5;
141 217 }
142 } No newline at end of file
218 }
219
@@ -1,129 +1,130
1 1 <!DOCTYPE html>
2 2 {% load static %}
3 3 {% load bootstrap4 %}
4 4 <html lang="en">
5 5 <head>
6 6 <meta charset="utf-8">
7 7 <title>{% block title %}Jicamarca Integrated Radar System:::::{% endblock %}</title>
8 8 <meta name="description" content="">
9 9 <meta name="author" content="">
10 10 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
11 11 {# bootstrap_css #}
12 12
13 13 <link href="{% static 'css/fontawesome.css' %}" rel="stylesheet">
14 14 <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
15 15 <link href="{% static 'css/style.css' %}" rel="stylesheet">
16 16 <link href="{% static 'css/header.css' %}" rel="stylesheet">
17 17 <link href="{% static 'css/footer.css' %}" rel="stylesheet">
18 18 <link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" />
19 19
20 20
21 21 <!--link href="{% static '' %}css/bootstrap-{{theme}}.min.css" media="all" rel="stylesheet"-->
22 22 <!-- <link href="{% static 'css/bootcards-desktop.min.css' %}" media="all" rel="stylesheet"> -->
23 23 <link href="{% static 'css/font-awesome.min.css' %}" media="all" rel="stylesheet"-->
24 24 <!--link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"-->
25 25
26 26 <!-- Bootcards CSS for iOS: >
27 27 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-ios.min.css"-->
28 28
29 29 <!-- Bootcards CSS for Android: >
30 30 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-android.min.css"-->
31 31
32 32 <!-- Bootcards CSS for desktop: >
33 33 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-desktop.min.css"-->
34 34
35 35 <style type="text/css">
36 36 .logo {padding-top: 5px; height: 50px}
37 37 .clickable-row {cursor: pointer;}
38 38 .col-no-padding { padding-left:0;}
39 39 .gi-2x{font-size: 2em;}
40 40 .gi-3x{font-size: 3em;}
41 41 .gi-4x{font-size: 4em;}
42 42 .gi-5x{font-size: 5em;}
43 43 </style>
44 <script src="{% static 'js/jquery.min.js' %}"></script>
44 45 {% block extra-head %}{% endblock %}
45 46 </head>
46 47
47 48 <body>
48 49
49 50 {% include "header_igp.html" %}
50 51
51 52 <div style="clear: both;"></div>
52 53
53 54 <div class="container">
54 55 <div id="page" class="row" style="min-height:600px">
55 56
56 57 {% if no_sidebar %}
57 58 <div class="col-md-0 hidden-xs hidden-sm" role="complementary"></div>
58 59
59 60 {% else %}
60 61 <div class="col-md-3 hidden-xs hidden-sm" role="complementary">
61 62 <br><br>
62 63 <div id="sidebar">
63 64 {% block sidebar%}
64 65 {% include "sidebar_devices.html" %}
65 66 {% endblock %}
66 67 </div>
67 68 </div>
68 69 {% endif %}
69 70
70 71
71 72 {% if no_sidebar %}
72 73 <div class="col-md-12 col-xs-12" role="main">
73 74 {% else %}
74 75 <div class="col-md-9 col-xs-12" role="main">
75 76 {% endif %}
76 77
77 78 <div class="page-header">
78 79 <h1>{% block content-title %}{% endblock %} <small>{% block content-suptitle %}{% endblock %}</small></h1>
79 80 </div>
80 81 {% block messages %}
81 82 {% if messages %}
82 83 {% for message in messages %}
83 84 <div class="alert alert-{% if message.tags %}{% if 'error' in message.tags %}danger{% else %}{{ message.tags }}{% endif %}{% else %}info{% endif %} alert-dismissible" role="alert">
84 85 <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
85 86 <strong>{{message.tags|title}}!</strong> {{ message }}
86 87 </div>
87 88 {% endfor %}
88 89 {% endif %}
89 90 {% endblock %}
90 91
91 92 {% block content %}
92 93 {% endblock %}
93 94
94 95 </div>
95 96
96 97
97 98 </div><!--/row-->
98 99 </div> <!-- container -->
99 100
100 101 {% include "footer_igp.html" %}
101 102
102 103
103 104
104 105 <!-- This part put block modal which is used to change parameters of my plot -->
105 106 {% block modal %}{% endblock modal %}
106 107 {% block debug %}<div class="row">{{debug}}</div>{% endblock debug %}
107 108 <!-- Optional JavaScript -->
108 109 <!-- jQuery first, then Popper.js, then Bootstrap JS -->
109 110 {# % bootstrap_javascript jquery='slim' % #}
110 111 <script src="{% static 'js/jquery-3.3.1.slim.min.js' %}"></script>
111 112 <script src="{% static 'js/popper.min.js' %}"></script>
112 113 <script src="{% static 'js/moment.min.js' %}"></script>
113 114 <script src="{% static 'js/bootstrap.min.js' %}"></script>
114 115 <script src="{% static 'js/plotly-latest.min.js' %}"></script>
115 116
116 117 <!-- Here we put the script from the type of plot that we recibe -->
117 118 <script>
118 119 $("#menu-toggle").click(function (e) {
119 120 e.preventDefault();
120 121 $("#wrapper").toggleClass("toggled");
121 122 });
122 123 </script>
123 124 {% block extra-js %}
124 125 {% endblock%}
125 126
126 127
127 128
128 129 </body>
129 130 </html>
@@ -1,418 +1,427
1 1 import os
2 2 import json
3 3
4 4 from django import forms
5 5 from django.utils.safestring import mark_safe
6 6 from apps.main.models import Device
7 7 from apps.main.forms import add_empty_choice
8 8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
9 9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
10 10
11 11 def create_choices_from_model(model, conf_id, all_choice=False):
12 12
13 13 if model=='RCLine':
14 14 instance = RCConfiguration.objects.get(pk=conf_id)
15 15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
16 16 if all_choice:
17 17 choices = add_empty_choice(choices, label='All')
18 18 else:
19 19 instance = globals()[model]
20 20 choices = instance.objects.all().values_list('pk', 'name')
21 21
22 22 return choices
23 23
24 24
25 25 class ExtFileField(forms.FileField):
26 26 """
27 27 Same as forms.FileField, but you can specify a file extension whitelist.
28 28
29 29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
30 30 >>>
31 31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
32 32 >>>
33 33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
34 34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
35 35 >>>
36 36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
37 37 Traceback (most recent call last):
38 38 ...
39 39 ValidationError: [u'Not allowed filetype!']
40 40 """
41 41 def __init__(self, *args, **kwargs):
42 42 extensions = kwargs.pop("extensions")
43 43 self.extensions = [i.lower() for i in extensions]
44 44
45 45 super(ExtFileField, self).__init__(*args, **kwargs)
46 46
47 47 def clean(self, *args, **kwargs):
48 48 data = super(ExtFileField, self).clean(*args, **kwargs)
49 49 filename = data.name
50 50 ext = os.path.splitext(filename)[1]
51 51 ext = ext.lower()
52 52 if ext not in self.extensions:
53 53 raise forms.ValidationError('Not allowed file type: %s' % ext)
54 54
55 55
56 56 class RCConfigurationForm(forms.ModelForm):
57 57
58 58 def __init__(self, *args, **kwargs):
59 59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
60 60
61 61 instance = getattr(self, 'instance', None)
62 62
63 63 if instance and instance.pk:
64 64
65 65 devices = Device.objects.filter(device_type__name='rc')
66 66 if instance.experiment:
67 67 self.fields['experiment'].widget.attrs['read_only'] = True
68 68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
69 69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
70 70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
71 71 self.fields['clock'].widget.attrs['readonly'] = True
72 72
73 73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
74 74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
75 75
76 76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
77 77 self.fields['experiment'].widget.attrs['readonly'] = True
78 78
79 79 class Meta:
80 80 model = RCConfiguration
81 81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix', 'author', 'hash', 'clock_in')
82 82
83 83 def clean(self):
84 84 form_data = super(RCConfigurationForm, self).clean()
85 85
86 86 if 'clock_divider' in form_data:
87 87 if form_data['clock_divider']<1:
88 88 self.add_error('clock_divider', 'Invalid Value')
89 89 #else:
90 90 # if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
91 91 # self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
92 92
93 93 return form_data
94 94
95 95 def save(self, *args, **kwargs):
96 96 conf = super(RCConfigurationForm, self).save(*args, **kwargs)
97 97 clk = RCClock.objects.filter(rc_configuration=conf).first()
98 98 if clk:
99 99 conf.clock_in = clk.frequency
100 100 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
101 101 conf.save()
102 102 return conf
103 103
104 104
105 105 class RCMixConfigurationForm(forms.Form):
106 106
107 107 clock_in = forms.CharField(widget=forms.HiddenInput())
108 108 clock_divider = forms.CharField(widget=forms.HiddenInput())
109 109 name = forms.CharField()
110 110 experiment = forms.ChoiceField()
111 111 mode = forms.ChoiceField(widget=forms.RadioSelect(),
112 112 choices=[(0, 'Parallel'), (1, 'Sequence')],
113 113 initial=0)
114 114 operation = forms.ChoiceField(widget=forms.RadioSelect(),
115 115 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
116 116 initial=1)
117 117 delay = forms.CharField()
118 118 mask = forms.MultipleChoiceField(
119 119 choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8'),
120 120 (8, 'L9'),(9, 'L10'),(10, 'L11'),(11, 'L12'),(12, 'L13'),(13, 'L14'),(14, 'L15'),(15, 'L16')],
121 121 widget=HCheckboxSelectMultiple())
122 122 result = forms.CharField(required=False,
123 123 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
124 124
125 125 def __init__(self, *args, **kwargs):
126 126 confs = kwargs.pop('confs', [])
127 127 if confs:
128 128 km2unit = confs[0].km2unit
129 129 clock_in = confs[0].clock_in
130 130 clock_divider = confs[0].clock_divider
131 131 else:
132 132 km2unit = clock_in = clock_divider = 0
133 133 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
134 134 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
135 135 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
136 136 self.fields['clock_in'].initial = clock_in
137 137 self.fields['clock_divider'].initial = clock_divider
138 138
139 139
140 140 class RCLineForm(forms.ModelForm):
141 141
142 142 def __init__(self, *args, **kwargs):
143 143 self.extra_fields = kwargs.pop('extra_fields', [])
144 144 super(RCLineForm, self).__init__(*args, **kwargs)
145 145
146 146 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
147 147 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
148 148
149 149 if 'code_id' in kwargs['initial']:
150 150 model_initial = kwargs['initial']['code_id']
151 151 else:
152 152 model_initial = 0
153 153
154 154 params = json.loads(line_type.params)
155 155
156 156 for label, value in self.extra_fields.items():
157 157 if label=='params':
158 158 continue
159 159
160 160 if 'model' in params[label]:
161 161 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
162 162 kwargs['initial']['rc_configuration']),
163 163 initial=model_initial)
164 164
165 165
166 166 else:
167 167 if label=='codes' and 'code_id' in kwargs['initial']:
168 168 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
169 169 else:
170 170 self.fields[label] = forms.CharField(initial=value['value'])
171 171
172 172 if label=='codes':
173 173 self.fields[label].widget = CodesWidget()
174 174
175 175 if self.data:
176 176 line_type = RCLineType.objects.get(pk=self.data['line_type'])
177 177
178 178 if 'code_id' in self.data:
179 179 model_initial = self.data['code_id']
180 180 else:
181 181 model_initial = 0
182 182
183 183 params = json.loads(line_type.params)
184 184
185 185 for label, value in self.extra_fields.items():
186 186 if label=='params':
187 187 continue
188 188
189 189 if 'model' in params[label]:
190 190 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
191 191 self.data['rc_configuration']),
192 192 initial=model_initial)
193 193
194 194
195 195 else:
196 196 if label=='codes' and 'code' in self.data:
197 197 self.fields[label] = forms.CharField(initial=self.data['codes'])
198 198 else:
199 199 self.fields[label] = forms.CharField(initial=self.data[label])
200 200
201 201 if label=='codes':
202 202 self.fields[label].widget = CodesWidget()
203 203
204 204
205 205 class Meta:
206 206 model = RCLine
207 207 fields = ('rc_configuration', 'line_type', 'channel')
208 208 widgets = {
209 209 'channel': forms.HiddenInput(),
210 210 }
211 211
212 212
213 213 def clean(self):
214 214
215 215 form_data = self.cleaned_data
216 216 if 'code' in self.data and self.data['TX_ref']=="0":
217 217 self.add_error('TX_ref', 'Choose a valid TX reference')
218 218
219 219 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
220 220 self.add_error('line_type', 'Invalid Line type')
221 221
222 222 return form_data
223 223
224 224
225 225 def save(self):
226 226 line = super(RCLineForm, self).save()
227 227
228 228 #auto add channel
229 229 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
230 230
231 231 #auto add position for TX, TR & CODE
232 232 if line.line_type.name in ('tx', ):
233 233 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
234 234
235 235 #save extra fields in params
236 236 params = {}
237 237 for label, value in self.extra_fields.items():
238 238 if label=='params':
239 239 params['params'] = []
240 240 elif label=='codes':
241 241 params[label] = [s for s in self.data[label].split('\r\n') if s]
242 242 else:
243 243 params[label] = self.data[label]
244 244 line.params = json.dumps(params)
245 245 line.save()
246 246 return
247 247
248 248
249 249 class RCLineViewForm(forms.Form):
250 250
251 251 def __init__(self, *args, **kwargs):
252 252
253 253 extra_fields = kwargs.pop('extra_fields')
254 254 line = kwargs.pop('line')
255 255 subform = kwargs.pop('subform', False)
256 256 super(RCLineViewForm, self).__init__(*args, **kwargs)
257 257
258 258 if subform:
259 259 params = json.loads(line.line_type.params)['params']
260 260 else:
261 261 params = json.loads(line.line_type.params)
262 262
263 263 for label, value in extra_fields.items():
264 264
265 265 if label=='params':
266 266 continue
267 267 if 'ref' in label:
268 268 if value in (0, '0'):
269 269 value = 'All'
270 270 else:
271 271 value = RCLine.objects.get(pk=value).get_name()
272 272 elif label=='code':
273 273 value = RCLineCode.objects.get(pk=value).name
274 274
275 275 self.fields[label] = forms.CharField(initial=value)
276 276
277 277 if 'widget' in params[label]:
278 278 km2unit = line.rc_configuration.km2unit
279 279 if params[label]['widget']=='km':
280 280 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
281 281 elif params[label]['widget']=='unit':
282 282 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
283 283 elif params[label]['widget']=='dc':
284 284 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
285 285 elif params[label]['widget']=='codes':
286 286 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
287 287 else:
288 288 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
289 289
290 290
291 291 class RCLineEditForm(forms.ModelForm):
292 292
293 293 def __init__(self, *args, **kwargs):
294 print("RCLineEditForm")
294 295
295 296 extra_fields = kwargs.pop('extra_fields', [])
296 297 conf = kwargs.pop('conf', False)
297 298 line = kwargs.pop('line')
298 299 subform = kwargs.pop('subform', False)
299 300
300 301 super(RCLineEditForm, self).__init__(*args, **kwargs)
301 302
302 303 if subform is not False:
303 304 params = json.loads(line.line_type.params)['params']
304 305 count = subform
305 306 else:
306 307 params = json.loads(line.line_type.params)
307 308 count = -1
308 309
309 310 for label, value in extra_fields.items():
310 311
311 312 if label in ('params',):
312 313 continue
313 314 if 'help' in params[label]:
314 315 help_text = params[label]['help']
315 316 else:
316 317 help_text = ''
317 318
318 319 if 'model' in params[label]:
319 320 if line.line_type.name=='tr':
320 321 all_choice = True
321 322 else:
322 323 all_choice = False
323 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
324 #print("'name':'%s|%s|%s'" % (count, line.id, label))
325 aux_name = '%s|%s|%s' % (count, line.id, label)
326 print(aux_name)
327 print(label)
328
329 self.fields[aux_name] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
324 330 initial=value,
325 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
331 label=label,
332 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}), #No trabaja con attrs esta versión de django 2.0 hacia adelante
333 #widget=forms.Select(attrs={'name':'HOLA'}), #No trabaja con attrs esta versión de django 2.0 hacia adelante
326 334 help_text=help_text)
327 335
328 336 else:
329 337 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
330 338
331 339 if label in ('code', ):
332 340 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
333 341
334 342 elif 'widget' in params[label]:
335 343 km2unit = line.rc_configuration.km2unit
336 344 if params[label]['widget']=='km':
337 345 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
338 346 elif params[label]['widget']=='unit':
339 347 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
340 348 elif params[label]['widget']=='dc':
341 349 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
342 350 elif params[label]['widget']=='codes':
343 351 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
344 352 else:
345 353 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
346 354
347 355
348 356 class Meta:
349 357 model = RCLine
350 358 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
351 359
352 360
353 361 class RCSubLineEditForm(forms.Form):
354 362
355 363 def __init__(self, *args, **kwargs):
364 print("RCSubLineEditForm")
356 365 extra_fields = kwargs.pop('extra_fields')
357 366 count = kwargs.pop('count')
358 367 line = kwargs.pop('line')
359 368 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
360 369 for label, value in extra_fields.items():
361 370 self.fields[label] = forms.CharField(initial=value,
362 371 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
363
372
364 373
365 374 class RCImportForm(forms.Form):
366 375
367 376 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
368 377
369 378
370 379 class RCLineCodesForm(forms.ModelForm):
371 380
372 381 def __init__(self, *args, **kwargs):
373 382 super(RCLineCodesForm, self).__init__(*args, **kwargs)
374 383
375 384 if 'initial' in kwargs:
376 385 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
377 386 initial=kwargs['initial']['code'])
378 387 if 'instance' in kwargs:
379 388 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
380 389 initial=kwargs['instance'].pk)
381 390
382 391 self.fields['codes'].widget = CodesWidget()
383 392
384 393
385 394 class Meta:
386 395 model = RCLineCode
387 396 exclude = ('name',)
388 397
389 398 class RCClockForm(forms.ModelForm):
390 399
391 400 def __init__(self, *args, **kwargs):
392 401 super(RCClockForm, self).__init__(*args, **kwargs)
393 402
394 403 instance = getattr(self, 'instance', None)
395 404
396 405 if instance is not None and instance.mode:
397 406 self.fields['multiplier'].widget.attrs['readonly'] = True
398 407 self.fields['divisor'].widget.attrs['readonly'] = True
399 408 self.fields['reference'].widget.attrs['readonly'] = True
400 409
401 410
402 411 class Meta:
403 412 model = RCClock
404 413 exclude = ('rc_configuration',)
405 414
406 415 def clean(self):
407 416
408 417 form_data = self.cleaned_data
409 418
410 419 if form_data['mode'] is True and float(form_data['frequency']) not in (60., 55.):
411 420 self.add_error('frequency', 'Only 60 and 55 are valid values in auto mode')
412 421 elif form_data['mode'] is False:
413 422 if form_data['reference']==0 and not 24<=form_data['multiplier']<=36:
414 423 self.add_error('multiplier', 'For 25MHz, valid values are between 24 and 36')
415 424 elif form_data['reference']==1 and not 60<=form_data['multiplier']<=90:
416 425 self.add_error('multiplier', 'For 10MHz, valid values are between 60 and 90')
417 426
418 427 return form_data No newline at end of file
@@ -1,1027 +1,1032
1 1
2 2
3 3 import ast
4 4 import json
5 5 import requests
6 6 import numpy as np
7 7 from base64 import b64encode
8 8 from struct import pack
9 9
10 10 from django.db import models
11 11 from django.urls import reverse
12 12 from django.core.validators import MinValueValidator, MaxValueValidator
13 13
14 14 from apps.main.models import Configuration
15 15 from apps.main.utils import Params
16 16 from devices.rc import api
17 17 from apps.rc.utils import RCFile
18 18
19 19
20 20 LINE_TYPES = (
21 21 ('none', 'Not used'),
22 22 ('tr', 'Transmission/reception selector signal'),
23 23 ('tx', 'A modulating signal (Transmission pulse)'),
24 24 ('codes', 'BPSK modulating signal'),
25 25 ('windows', 'Sample window signal'),
26 26 ('sync', 'Synchronizing signal'),
27 27 ('flip', 'IPP related periodic signal'),
28 28 ('prog_pulses', 'Programmable pulse'),
29 29 ('mix', 'Mixed line'),
30 30 )
31 31
32 32
33 33 SAMPLING_REFS = (
34 34 ('none', 'No Reference'),
35 35 ('begin_baud', 'Begin of the first baud'),
36 36 ('first_baud', 'Middle of the first baud'),
37 37 ('sub_baud', 'Middle of the sub-baud')
38 38 )
39 39
40 40 DAT_CMDS = {
41 41 # Pulse Design commands
42 42 'DISABLE' : 0, # Disables pulse generation
43 43 'ENABLE' : 24, # Enables pulse generation
44 44 'DELAY_START' : 40, # Write delay status to memory
45 45 'FLIP_START' : 48, # Write flip status to memory
46 46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 47 'TX_ONE' : 72, # Output '0' in line TX
48 48 'TX_ZERO' : 88, # Output '0' in line TX
49 49 'SW_ONE' : 104, # Output '0' in line SW
50 50 'SW_ZERO' : 112, # Output '1' in line SW
51 51 'RESTART': 120, # Restarts CR8 Firmware
52 52 'CONTINUE' : 253, # Function Unknown
53 53 # Commands available to new controllers
54 54 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
55 55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 57 'CLOCK_DIVIDER' : 8,
58 58 }
59 59
60 60 MAX_BITS = 8
61 61
62 62 # Rotate left: 0b1001 --> 0b0011
63 63 rol = lambda val, r_bits: \
64 64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66 66
67 67 # Rotate right: 0b1001 --> 0b1100
68 68 ror = lambda val, r_bits: \
69 69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71 71
72 72
73 73 class RCConfiguration(Configuration):
74 74
75 75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 86 total_units = models.PositiveIntegerField(default=0)
87 87 mix = models.BooleanField(default=False)
88 88
89 89 class Meta:
90 90 db_table = 'rc_configurations'
91 91
92 92 def get_absolute_url_plot(self):
93 93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94 94
95 95 @property
96 96 def ipp_unit(self):
97 97
98 98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99 99
100 100 @property
101 101 def us2unit(self):
102 102
103 103 return self.clock_in/self.clock_divider
104 104
105 105 @property
106 106 def km2unit(self):
107 107
108 108 return 20./3*(self.clock_in/self.clock_divider)
109 109
110 110 def clone(self, **kwargs):
111 111
112 112 lines = self.get_lines()
113 113 self.pk = None
114 114 self.id = None
115 115 for attr, value in kwargs.items():
116 116 setattr(self, attr, value)
117 117 self.save()
118 118
119 119 for line in lines:
120 120 line.clone(rc_configuration=self)
121 121
122 122 new_lines = self.get_lines()
123 123 for line in new_lines:
124 124 line_params = json.loads(line.params)
125 125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 128 line.params = json.dumps(line_params)
129 129 line.save()
130 130
131 131 return self
132 132
133 133 def get_lines(self, **kwargs):
134 134 '''
135 135 Retrieve configuration lines
136 136 '''
137 137
138 138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139 139
140 140
141 141 def clean_lines(self):
142 142 '''
143 143 '''
144 144
145 145 empty_line = RCLineType.objects.get(name='none')
146 146
147 147 for line in self.get_lines():
148 148 line.line_type = empty_line
149 149 line.params = '{}'
150 150 line.save()
151 151
152 152 def dict_to_parms(self, params, id=None):
153 153 '''
154 154 '''
155 155
156 156 if id:
157 157 data = Params(params).get_conf(id_conf=id)
158 158 else:
159 159 data = Params(params).get_conf(dtype='rc')
160 160
161 #print(data)
161 162 # self.name = data['name']
162 163 self.ipp = data['ipp']
163 164 self.ntx = data['ntx']
164 165 self.clock_in = data['clock_in']
165 166 self.clock_divider = data['clock_divider']
166 167 self.clock = data['clock']
167 168 self.time_before = data['time_before']
168 169 self.time_after = data['time_after']
169 170 self.sync = data['sync']
170 171 self.sampling_reference = data['sampling_reference']
171 172 self.total_units = self.ipp*self.ntx*self.km2unit
172 173 self.save()
173 174 self.clean_lines()
174 175
176 #print(params)
177
175 178 positions = {'tx':0, 'tr':0}
176 179 for i, id in enumerate(data['lines']):
177 180 line_data = params['lines']['byId'][id]
178 181 line_type = RCLineType.objects.get(name=line_data['line_type'])
179 182 if line_type.name == 'codes':
180 183 code = RCLineCode.objects.get(name=line_data['params']['code'])
181 184 line_data['params']['code'] = code.pk
182 185 if line_type.name == 'tx':
183 186 position = positions['tx']
184 187 positions['tx'] += 1
185 188 elif line_type.name == 'tr':
186 189 position = positions['tr']
187 190 positions['tr'] += 1
188 191 else:
189 192 position = 0
190 193 line, dum = RCLine.objects.update_or_create(
191 194 rc_configuration=self,
192 195 channel=i,
193 196 position=position,
194 197 defaults={
195 198 'line_type': line_type,
196 199 'params': json.dumps(line_data['params'])
197 200 }
198 201 )
199 202
200 203 for i, line in enumerate(self.get_lines()):
201 204 line_params = json.loads(line.params)
202 205 if 'TX_ref' in line_params:
203 206 if line_params['TX_ref'] in (0, '0'):
204 207 line_params['TX_ref'] = '0'
205 208 else:
206 209 ref_id = '{}'.format(line_params['TX_ref'])
207 210 ref_line = params['lines']['byId'][ref_id]
208 211 line_params['TX_ref'] = RCLine.objects.get(
209 212 rc_configuration=self,
210 213 params=json.dumps(ref_line['params'])
211 214 ).pk
212 215 line.params = json.dumps(line_params)
216 print(line.params)
213 217 line.save()
214
218 print("Fin de dict to param")
215 219
216 220 def get_delays(self):
217 221
218 222 pulses = [line.pulses_as_points() for line in self.get_lines()]
219 223 points = [tup for tups in pulses for tup in tups]
220 224 points = set([x for tup in points for x in tup])
221 225 points = list(points)
222 226 points.sort()
223 227
224 228 if points[0]!=0:
225 229 points.insert(0, 0)
226 230
227 231 return [points[i+1]-points[i] for i in range(len(points)-1)]
228 232
229 233
230 234 def get_pulses(self, binary=True):
231 235
232 236 pulses = [line.pulses_as_points() for line in self.get_lines()]
233 237 tuples = [tup for tups in pulses for tup in tups]
234 238 points = set([x for tup in tuples for x in tup])
235 239 points = list(points)
236 240 points.sort()
237 241 states = []
238 242 last = [0 for x in pulses]
239 243
240 244 for x in points:
241 245 dum = []
242 246 for i, tups in enumerate(pulses):
243 247 ups = [tup[0] for tup in tups if tup!=(0,0)]
244 248 dws = [tup[1] for tup in tups if tup!=(0,0)]
245 249 if x in ups:
246 250 dum.append(1)
247 251 elif x in dws:
248 252 dum.append(0)
249 253 else:
250 254 dum.append(last[i])
251 255 states.append(dum)
252 256 last = dum
253 257
254 258 if binary:
255 259 ret = []
256 260 for flips in states:
257 261 flips.reverse()
258 262 ret.append(int(''.join([str(x) for x in flips]), 2))
259 263 states = ret
260 264
261 265 return states[:-1]
262 266
263 267 def add_cmd(self, cmd):
264 268
265 269 if cmd in DAT_CMDS:
266 270 return (255, DAT_CMDS[cmd])
267 271
268 272 def add_data(self, value):
269 273
270 274 return (254, value-1)
271 275
272 276 def parms_to_binary(self, dat=True):
273 277 '''
274 278 Create "dat" stream to be send to CR
275 279 '''
276 280
277 281 data = bytearray()
278 282 # create header
279 283 data.extend(self.add_cmd('DISABLE'))
280 284 data.extend(self.add_cmd('CONTINUE'))
281 285 data.extend(self.add_cmd('RESTART'))
282 286
283 287 if self.control_sw:
284 288 data.extend(self.add_cmd('SW_ONE'))
285 289 else:
286 290 data.extend(self.add_cmd('SW_ZERO'))
287 291
288 292 if self.control_tx:
289 293 data.extend(self.add_cmd('TX_ONE'))
290 294 else:
291 295 data.extend(self.add_cmd('TX_ZERO'))
292 296
293 297 # write divider
294 298 data.extend(self.add_cmd('CLOCK_DIVIDER'))
295 299 data.extend(self.add_data(self.clock_divider))
296 300
297 301 # write delays
298 302 data.extend(self.add_cmd('DELAY_START'))
299 303 # first delay is always zero
300 304 data.extend(self.add_data(1))
301 305
302 306 delays = self.get_delays()
303 307
304 308 for delay in delays:
305 309 while delay>252:
306 310 data.extend(self.add_data(253))
307 311 delay -= 253
308 312 data.extend(self.add_data(int(delay)))
309 313
310 314 # write flips
311 315 data.extend(self.add_cmd('FLIP_START'))
312 316
313 317 states = self.get_pulses(binary=True)
314 318
315 319
316 320 last = 0
317 321 for flip, delay in zip(states, delays):
318 322 data.extend(self.add_data((flip^last)+1))
319 323 last = flip
320 324 while delay>252:
321 325 data.extend(self.add_data(1))
322 326 delay -= 253
323 327
324 328 # write sampling period
325 329 data.extend(self.add_cmd('SAMPLING_PERIOD'))
326 330 wins = self.get_lines(line_type__name='windows')
327 331 if wins:
328 332 win_params = json.loads(wins[0].params)['params']
329 333 if win_params:
330 334 dh = int(win_params[0]['resolution']*self.km2unit)
331 335 else:
332 336 dh = 1
333 337 else:
334 338 dh = 1
335 339 data.extend(self.add_data(dh))
336 340
337 341 # write enable
338 342 data.extend(self.add_cmd('ENABLE'))
339 343
340 344 if not dat:
341 345 return data
342 346
343 347 return '\n'.join(['{}'.format(x) for x in data])
344 348
345 349 def update_pulses(self):
346 350
347 351 for line in self.get_lines():
348 352 line.update_pulses()
349 353
350 354 def plot_pulses2(self, km=False):
351 355
352 356 import matplotlib
353 357 matplotlib.use('Agg')
354 358 import matplotlib.pyplot as plt
355 359 from bokeh.resources import CDN
356 360 from bokeh.embed import components
357 361 from bokeh.mpl import to_bokeh
358 362 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
359 363
360 364 lines = self.get_lines()
361 365
362 366 N = len(lines)
363 367 npoints = self.total_units/self.km2unit if km else self.total_units
364 368 fig = plt.figure(figsize=(12, 2+N*0.5))
365 369 ax = fig.add_subplot(111)
366 370 labels = ['IPP']
367 371
368 372 for i, line in enumerate(lines):
369 373 labels.append(line.get_name(channel=True))
370 374 l = ax.plot((0, npoints),(N-i-1, N-i-1))
371 375 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
372 376 ax.broken_barh(points, (N-i-1, 0.5),
373 377 edgecolor=l[0].get_color(), facecolor='none')
374 378
375 379 n = 0
376 380 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
377 381 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
378 382 if n%f==0:
379 383 ax.text(x, N, '%s' % n, size=10)
380 384 n += 1
381 385
382 386 labels.reverse()
383 387 ax.set_yticks(range(len(labels)))
384 388 ax.set_yticklabels(labels)
385 389 ax.set_xlabel = 'Units'
386 390 plot = to_bokeh(fig, use_pandas=False)
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
391 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
388 392 plot.toolbar_location="above"
389 393
390 394 return components(plot, CDN)
391 395
392 396 def plot_pulses(self, km=False):
393 397
394 398 from bokeh.plotting import figure
395 399 from bokeh.resources import CDN
396 400 from bokeh.embed import components
397 401 from bokeh.models import FixedTicker, PrintfTickFormatter
398 402 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 403 from bokeh.models.sources import ColumnDataSource
400 404
401 405 lines = self.get_lines().reverse()
402 406
403 407 N = len(lines)
404 408 npoints = self.total_units/self.km2unit if km else self.total_units
405 409 ipp = self.ipp if km else self.ipp*self.km2unit
406 410
407 411 hover = HoverTool(tooltips=[("Line", "@name"),
408 412 ("IPP", "@ipp"),
409 413 ("X", "@left")])
410 414
411 tools = [PanTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
415 tools = [PanTool(dimensions="width"),
416 WheelZoomTool(dimensions="width"),
413 417 hover, SaveTool()]
414 418
415 419 plot = figure(width=1000,
416 420 height=40+N*50,
417 421 y_range = (0, N),
418 422 tools=tools,
419 423 toolbar_location='above',
420 424 toolbar_sticky=False,)
421 425
422 426 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 427 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 428 plot.yaxis.axis_label = 'Pulses'
425 429 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 430 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427 431
428 432 for i, line in enumerate(lines):
429 433
430 434 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431 435
432 436 source = ColumnDataSource(data = dict(
433 437 bottom = [i for tup in points],
434 438 top = [i+0.5 for tup in points],
435 439 left = [tup[0] for tup in points],
436 440 right = [tup[1] for tup in points],
437 441 ipp = [int(tup[0]/ipp) for tup in points],
438 442 name = [line.get_name() for tup in points]
439 443 ))
440 444
441 445 plot.quad(
442 446 bottom = 'bottom',
443 447 top = 'top',
444 448 left = 'left',
445 449 right = 'right',
446 450 source = source,
447 451 fill_alpha = 0,
448 452 #line_color = 'blue',
449 453 )
450 454
451 455 plot.line([0, npoints], [i, i])#, color='blue')
452 456
453 457 return components(plot, CDN)
454 458
455 459 def request(self, cmd, method='get', **kwargs):
456 460
457 461 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 462 payload = req.json()
459 463
460 464 return payload
461 465
462 466 def status_device(self):
463 467
464 468 try:
465 469 self.device.status = 0
466 470 payload = self.request('status')
467 471 if payload['status']=='enable':
468 472 self.device.status = 3
469 473 elif payload['status']=='disable':
470 474 self.device.status = 2
471 475 else:
472 476 self.device.status = 1
473 477 self.device.save()
474 478 self.message = 'RC status: {}'.format(payload['status'])
475 479 return False
476 480 except Exception as e:
477 481 if 'No route to host' not in str(e):
478 482 self.device.status = 4
479 483 self.device.save()
480 484 self.message = 'RC status: {}'.format(str(e))
481 485 return False
482 486
483 487 self.device.save()
484 488 return True
485 489
486 490 def reset_device(self):
487 491
488 492 try:
489 493 payload = self.request('reset', 'post')
490 494 if payload['reset']=='ok':
491 495 self.message = 'RC restarted OK'
492 496 self.device.status = 2
493 497 self.device.save()
494 498 else:
495 499 self.message = 'RC restart fail'
496 500 self.device.status = 4
497 501 self.device.save()
498 502 except Exception as e:
499 503 self.message = 'RC reset: {}'.format(str(e))
500 504 return False
501 505
502 506 return True
503 507
504 508 def stop_device(self):
505 509
506 510 try:
507 511 payload = self.request('stop', 'post')
508 512 self.message = 'RC stop: {}'.format(payload['stop'])
509 513 if payload['stop']=='ok':
510 514 self.device.status = 2
511 515 self.device.save()
512 516 else:
513 517 self.device.status = 4
514 518 self.device.save()
515 519 return False
516 520 except Exception as e:
517 521 if 'No route to host' not in str(e):
518 522 self.device.status = 4
519 523 else:
520 524 self.device.status = 0
521 525 self.message = 'RC stop: {}'.format(str(e))
522 526 self.device.save()
523 527 return False
524 528
525 529 return True
526 530
527 531 def start_device(self):
528 532
529 533 try:
530 534 payload = self.request('start', 'post')
531 535 self.message = 'RC start: {}'.format(payload['start'])
532 536 if payload['start']=='ok':
533 537 self.device.status = 3
534 538 self.device.save()
535 539 else:
536 540 return False
537 541 except Exception as e:
538 542 if 'No route to host' not in str(e):
539 543 self.device.status = 4
540 544 else:
541 545 self.device.status = 0
542 546 self.message = 'RC start: {}'.format(str(e))
543 547 self.device.save()
544 548 return False
545 549
546 550 return True
547 551
548 552 def write_device(self, raw=False):
549 553
550 554 if not raw:
551 555 clock = RCClock.objects.get(rc_configuration=self)
552 556 if clock.mode:
553 557 data = {'default': clock.frequency}
554 558 else:
555 559 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
556 560 payload = self.request('setfreq', 'post', data=json.dumps(data))
557 561 if payload['command'] != 'ok':
558 562 self.message = 'RC write: {}'.format(payload['command'])
559 563 else:
560 564 self.message = payload['programming']
561 565 if payload['programming'] == 'fail':
562 566 self.message = 'RC write: error programming CGS chip'
563 567
564 568 values = []
565 569 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
566 570 while delay>65536:
567 571 values.append((pulse, 65535))
568 572 delay -= 65536
569 573 values.append((pulse, delay-1))
570 574 data = bytearray()
571 575 #reset
572 576 data.extend((128, 0))
573 577 #disable
574 578 data.extend((129, 0))
575 579 #SW switch
576 580 if self.control_sw:
577 581 data.extend((130, 2))
578 582 else:
579 583 data.extend((130, 0))
580 584 #divider
581 585 data.extend((131, self.clock_divider-1))
582 586 #enable writing
583 587 data.extend((139, 62))
584 588
585 589 last = 0
586 590 for tup in values:
587 591 vals = pack('<HH', last^tup[0], tup[1])
588 592 last = tup[0]
589 593 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
590 594
591 595 #enable
592 596 data.extend((129, 1))
593 597
594 598 if raw:
595 599 return b64encode(data)
596 600
597 601 try:
598 602 payload = self.request('stop', 'post')
599 603 payload = self.request('reset', 'post')
600 604 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
601 605 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
602 606 n = len(data)
603 607 x = 0
604 608 #while x < n:
605 609 payload = self.request('write', 'post', data=b64encode(data))
606 610 # x += 1024
607 611
608 612 if payload['write']=='ok':
609 613 self.device.status = 3
610 614 self.device.save()
611 615 self.message = 'RC configured and started'
612 616 else:
613 617 self.device.status = 1
614 618 self.device.save()
615 619 self.message = 'RC write: {}'.format(payload['write'])
616 620 return False
617 621
618 622 #payload = self.request('start', 'post')
619 623
620 624 except Exception as e:
621 625 if 'No route to host' not in str(e):
622 626 self.device.status = 4
623 627 else:
624 628 self.device.status = 0
625 629 self.message = 'RC write: {}'.format(str(e))
626 630 self.device.save()
627 631 return False
628 632
629 633 return True
630 634
631 635
632 636 def get_absolute_url_import(self):
633 637 return reverse('url_import_rc_conf', args=[str(self.id)])
634 638
635 639
636 640 class RCLineCode(models.Model):
637 641
638 642 name = models.CharField(max_length=40)
639 643 bits_per_code = models.PositiveIntegerField(default=0)
640 644 number_of_codes = models.PositiveIntegerField(default=0)
641 645 codes = models.TextField(blank=True, null=True)
642 646
643 647 class Meta:
644 648 db_table = 'rc_line_codes'
645 649 ordering = ('name',)
646 650
647 651 def __str__(self):
648 652 return u'%s' % self.name
649 653
650 654
651 655 class RCLineType(models.Model):
652 656
653 657 name = models.CharField(choices=LINE_TYPES, max_length=40)
654 658 description = models.TextField(blank=True, null=True)
655 659 params = models.TextField(default='[]')
656 660
657 661 class Meta:
658 662 db_table = 'rc_line_types'
659 663
660 664 def __str__(self):
661 665 return u'%s - %s' % (self.name.upper(), self.get_name_display())
662 666
663 667
664 668 class RCLine(models.Model):
665 669
666 670 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
667 671 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
668 672 channel = models.PositiveIntegerField(default=0)
669 673 position = models.PositiveIntegerField(default=0)
670 674 params = models.TextField(default='{}')
671 675 pulses = models.TextField(default='')
672 676
673 677 class Meta:
674 678 db_table = 'rc_lines'
675 679 ordering = ['channel']
676 680
677 681 def __str__(self):
678 682 if self.rc_configuration:
679 683 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
680 684
681 685 def jsonify(self):
682 686
683 687 data = {}
684 688 data['params'] = json.loads(self.params)
685 689 data['id'] = '{}'.format(self.pk)
686 690 data['line_type'] = self.line_type.name
687 691 data['name'] = self.get_name()
688 692 if data['line_type']=='codes':
689 693 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
690 694
691 695 return data
692 696
693 697
694 698 def clone(self, **kwargs):
695 699
696 700 self.pk = None
697 701 self.id = None
698 702
699 703 for attr, value in kwargs.items():
700 704 setattr(self, attr, value)
701 705
702 706 self.save()
703 707
704 708 return self
705 709
706 710 def get_name(self, channel=False):
707 711
708 712 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
709 713 s = ''
710 714
711 715 if self.line_type.name in ('tx',):
712 716 s = chars[self.position]
713 717 elif self.line_type.name in ('codes', 'windows', 'tr'):
714 718 if 'TX_ref' in json.loads(self.params):
715 719 pk = json.loads(self.params)['TX_ref']
716 720 if pk in (0, '0'):
717 721 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
718 722 else:
719 723 ref = RCLine.objects.get(pk=pk)
720 724 s = chars[ref.position]
721 725 s = '({})'.format(s)
722 726
723 727 s = '{}{}'.format(self.line_type.name.upper(), s)
724 728
725 729 if channel:
726 730 return '{} {}'.format(s, self.channel)
727 731 else:
728 732 return s
729 733
730 734 def get_lines(self, **kwargs):
731 735
732 736 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
733 737
734 738 def pulses_as_array(self):
735 739
736 740 y = np.zeros(self.rc_configuration.total_units)
737 741
738 742 for tup in ast.literal_eval(self.pulses):
739 743 y[tup[0]:tup[1]] = 1
740 744
741 745 return y.astype(np.int8)
742 746
743 747 def pulses_as_points(self, km=False):
744 748
745 749 if km:
746 750 unit2km = 1/self.rc_configuration.km2unit
747 751 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
748 752 else:
749 753 return ast.literal_eval(self.pulses)
750 754
751 755 def get_win_ref(self, params, tx_id, km2unit):
752 756
753 757 ref = self.rc_configuration.sampling_reference
754 758 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
755 759
756 760 if codes:
757 761 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
758 762 else:
759 763 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
760 764
761 765 if ref=='first_baud':
762 766 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
763 767 elif ref=='sub_baud':
764 768 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
765 769 else:
766 770 return 0
767 771
768 772 def update_pulses(self):
769 773 '''
770 774 Update pulses field
771 775 '''
772 776
773 777 km2unit = self.rc_configuration.km2unit
774 778 us2unit = self.rc_configuration.us2unit
775 779 ipp = self.rc_configuration.ipp
776 780 ntx = int(self.rc_configuration.ntx)
777 781 ipp_u = int(ipp*km2unit)
778 782 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
779 783 y = []
780
784
781 785 if self.line_type.name=='tr':
782 786 tr_params = json.loads(self.params)
783
787 #print(tr_params)
788 #print(tr_params['TX_ref'])
784 789 if tr_params['TX_ref'] in ('0', 0):
785 790 txs = self.get_lines(line_type__name='tx')
786 791 else:
787 792 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
788 793
789 794 for tx in txs:
790 795 params = json.loads(tx.params)
791 796
792 797 if float(params['pulse_width'])==0:
793 798 continue
794 799 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
795 800 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
796 801 before = 0
797 802 after = int(self.rc_configuration.time_after*us2unit)
798 803
799 804 y_tx = self.points(ntx, ipp_u, width,
800 805 delay=delays,
801 806 before=before,
802 807 after=after,
803 808 sync=self.rc_configuration.sync)
804 809
805 810 ranges = params['range'].split(',')
806 811
807 812 if len(ranges)>0 and ranges[0]!='0':
808 813 y_tx = self.mask_ranges(y_tx, ranges)
809 814
810 815 tr_ranges = tr_params['range'].split(',')
811 816
812 817 if len(tr_ranges)>0 and tr_ranges[0]!='0':
813 818 y_tx = self.mask_ranges(y_tx, tr_ranges)
814 819
815 820 y.extend(y_tx)
816 821
817 822 self.pulses = str(y)
818 823 y = self.array_to_points(self.pulses_as_array())
819 824
820 825 elif self.line_type.name=='tx':
821 826 params = json.loads(self.params)
822 827 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
823 828 width = float(params['pulse_width'])*km2unit
824 829
825 830 if width>0:
826 831 before = int(self.rc_configuration.time_before*us2unit)
827 832 after = 0
828 833
829 834 y = self.points(ntx, ipp_u, width,
830 835 delay=delays,
831 836 before=before,
832 837 after=after,
833 838 sync=self.rc_configuration.sync)
834 839
835 840 ranges = params['range'].split(',')
836 841
837 842 if len(ranges)>0 and ranges[0]!='0':
838 843 y = self.mask_ranges(y, ranges)
839 844
840 845 elif self.line_type.name=='flip':
841 846 n = float(json.loads(self.params)['number_of_flips'])
842 847 width = n*ipp*km2unit
843 848 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
844 849
845 850 elif self.line_type.name=='codes':
846 851 params = json.loads(self.params)
847 852 tx = RCLine.objects.get(pk=params['TX_ref'])
848 853 tx_params = json.loads(tx.params)
849 854 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
850 855 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
851 856 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
852 857 codes = [self.array_to_points(code) for code in codes]
853 858 n = len(codes)
854 859
855 860 ranges = tx_params['range'].split(',')
856 861 if len(ranges)>0 and ranges[0]!='0':
857 862 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
858 863 else:
859 864 dum = tx.pulses_as_points()
860 865
861 866 for i, tup in enumerate(dum):
862 867 if tup==(0,0): continue
863 868 code = codes[i%n]
864 869 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
865 870
866 871 elif self.line_type.name=='sync':
867 872 params = json.loads(self.params)
868 873 n = ipp_u*ntx
869 874 if params['invert'] in ('1', 1):
870 875 y = [(n-1, n)]
871 876 else:
872 877 y = [(0, 1)]
873 878
874 879 elif self.line_type.name=='prog_pulses':
875 880 params = json.loads(self.params)
876 881 if int(params['periodic'])==0:
877 882 nntx = 1
878 883 nipp = ipp_u*ntx
879 884 else:
880 885 nntx = ntx
881 886 nipp = ipp_u
882 887
883 888 if 'params' in params and len(params['params'])>0:
884 889 for p in params['params']:
885 890 y_pp = self.points(nntx, nipp,
886 891 p['end']-p['begin'],
887 892 before=p['begin'])
888 893
889 894 y.extend(y_pp)
890 895
891 896 elif self.line_type.name=='windows':
892 897 params = json.loads(self.params)
893 898 if 'params' in params and len(params['params'])>0:
894 899 tx = RCLine.objects.get(pk=params['TX_ref'])
895 900 tx_params = json.loads(tx.params)
896 901 ranges = tx_params['range'].split(',')
897 902 for p in params['params']:
898 903 y_win = self.points(ntx, ipp_u,
899 904 p['resolution']*p['number_of_samples']*km2unit,
900 905 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
901 906 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
902 907
903 908
904 909 if len(ranges)>0 and ranges[0]!='0':
905 910 y_win = self.mask_ranges(y_win, ranges)
906 911
907 912 y.extend(y_win)
908 913
909 914 elif self.line_type.name=='mix':
910 915 values = self.rc_configuration.parameters.split('-')
911 916 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
912 917 modes = [value.split('|')[1] for value in values]
913 918 ops = [value.split('|')[2] for value in values]
914 919 delays = [value.split('|')[3] for value in values]
915 920 masks = [value.split('|')[4] for value in values]
916 921 mask = list('{:8b}'.format(int(masks[0])))
917 922 mask.reverse()
918 923 if mask[self.channel] in ('0', '', ' '):
919 924 y = np.zeros(confs[0].total_units, dtype=np.int8)
920 925 else:
921 926 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
922 927
923 928 for i in range(1, len(values)):
924 929 mask = list('{:8b}'.format(int(masks[i])))
925 930 mask.reverse()
926 931
927 932 if mask[self.channel] in ('0', '', ' '):
928 933 continue
929 934 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
930 935 delay = float(delays[i])*km2unit
931 936
932 937 if modes[i]=='P':
933 938 if delay>0:
934 939 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
935 940 y_temp = np.empty_like(Y)
936 941 y_temp[:delay] = 0
937 942 y_temp[delay:] = Y[:-delay]
938 943 elif delay+len(Y)>len(y):
939 944 y_new = np.zeros(delay+len(Y), dtype=np.int8)
940 945 y_new[:len(y)] = y
941 946 y = y_new
942 947 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
943 948 y_temp[-len(Y):] = Y
944 949 elif delay+len(Y)==len(y):
945 950 y_temp = np.zeros(delay+len(Y))
946 951 y_temp[-len(Y):] = Y
947 952 elif delay+len(Y)<len(y):
948 953 y_temp = np.zeros(len(y), dtype=np.int8)
949 954 y_temp[delay:delay+len(Y)] = Y
950 955 else:
951 956 y_temp = Y.copy()
952 957
953 958 if ops[i]=='OR':
954 959 y = y | y_temp
955 960 elif ops[i]=='XOR':
956 961 y = y ^ y_temp
957 962 elif ops[i]=='AND':
958 963 y = y & y_temp
959 964 elif ops[i]=='NAND':
960 965 y = y & ~y_temp
961 966 else:
962 967 y = np.concatenate([y, Y])
963 968
964 969 total = len(y)
965 970 y = self.array_to_points(y)
966 971
967 972 else:
968 973 y = []
969 974
970 975 if self.rc_configuration.total_units != total:
971 976 self.rc_configuration.total_units = total
972 977 self.rc_configuration.save()
973 978
974 979 self.pulses = str(y)
975 980 self.save()
976 981
977 982 @staticmethod
978 983 def array_to_points(X):
979 984
980 985 if X.size==0:
981 986 return []
982 987
983 988 d = X[1:]-X[:-1]
984 989
985 990 up = np.where(d==1)[0]
986 991 if X[0]==1:
987 992 up = np.concatenate((np.array([-1]), up))
988 993 up += 1
989 994
990 995 dw = np.where(d==-1)[0]
991 996 if X[-1]==1:
992 997 dw = np.concatenate((dw, np.array([len(X)-1])))
993 998 dw += 1
994 999
995 1000 return [(tup[0], tup[1]) for tup in zip(up, dw)]
996 1001
997 1002 @staticmethod
998 1003 def mask_ranges(Y, ranges):
999 1004
1000 1005 y = [(0, 0) for __ in Y]
1001 1006
1002 1007 for index in ranges:
1003 1008 if '-' in index:
1004 1009 args = [int(a) for a in index.split('-')]
1005 1010 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1006 1011 else:
1007 1012 y[int(index)-1] = Y[int(index)-1]
1008 1013
1009 1014 return y
1010 1015
1011 1016 @staticmethod
1012 1017 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1013 1018
1014 1019 delays = len(delay)
1015 1020
1016 1021 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1017 1022
1018 1023 return Y
1019 1024
1020 1025 class RCClock(models.Model):
1021 1026
1022 1027 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1023 1028 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1024 1029 multiplier = models.PositiveIntegerField(default=60)
1025 1030 divisor = models.PositiveIntegerField(default=10)
1026 1031 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1027 1032 frequency = models.FloatField(default=60.0) No newline at end of file
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now