##// END OF EJS Templates
add cgs_status to rc/models.py to program cgs
jrojas -
r416:6c601b3e0196 master
parent child
Show More
@@ -1,1079 +1,1107
1
1
2
2
3 import ast
3 import ast
4 import json
4 import json
5 import requests
5 import requests
6 import numpy as np
6 import numpy as np
7 from base64 import b64encode
7 from base64 import b64encode
8 from struct import pack
8 from struct import pack
9
9
10 from django.db import models
10 from django.db import models
11 from django.urls import reverse
11 from django.urls import reverse
12 from django.core.validators import MinValueValidator, MaxValueValidator
12 from django.core.validators import MinValueValidator, MaxValueValidator
13
13
14 from apps.main.models import Configuration
14 from apps.main.models import Configuration
15 from apps.main.utils import Params
15 from apps.main.utils import Params
16 from devices.rc import api
16 from devices.rc import api
17 from apps.rc.utils import RCFile
17 from apps.rc.utils import RCFile
18
18
19
19
20 LINE_TYPES = (
20 LINE_TYPES = (
21 ('none', 'Not used'),
21 ('none', 'Not used'),
22 ('tr', 'Transmission/reception selector signal'),
22 ('tr', 'Transmission/reception selector signal'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
24 ('codes', 'BPSK modulating signal'),
24 ('codes', 'BPSK modulating signal'),
25 ('windows', 'Sample window signal'),
25 ('windows', 'Sample window signal'),
26 ('sync', 'Synchronizing signal'),
26 ('sync', 'Synchronizing signal'),
27 ('flip', 'IPP related periodic signal'),
27 ('flip', 'IPP related periodic signal'),
28 ('prog_pulses', 'Programmable pulse'),
28 ('prog_pulses', 'Programmable pulse'),
29 ('mix', 'Mixed line'),
29 ('mix', 'Mixed line'),
30 )
30 )
31
31
32
32
33 SAMPLING_REFS = (
33 SAMPLING_REFS = (
34 ('none', 'No Reference'),
34 ('none', 'No Reference'),
35 ('begin_baud', 'Begin of the first baud'),
35 ('begin_baud', 'Begin of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
37 ('sub_baud', 'Middle of the sub-baud')
37 ('sub_baud', 'Middle of the sub-baud')
38 )
38 )
39
39
40 DAT_CMDS = {
40 DAT_CMDS = {
41 # Pulse Design commands
41 # Pulse Design commands
42 'DISABLE' : 0, # Disables pulse generation
42 'DISABLE' : 0, # Disables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
44 'DELAY_START' : 40, # Write delay status to memory
44 'DELAY_START' : 40, # Write delay status to memory
45 'FLIP_START' : 48, # Write flip status to memory
45 'FLIP_START' : 48, # Write flip status to memory
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 'TX_ONE' : 72, # Output '0' in line TX
47 'TX_ONE' : 72, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
49 'SW_ONE' : 104, # Output '0' in line SW
49 'SW_ONE' : 104, # Output '0' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
51 'RESTART': 120, # Restarts CR8 Firmware
51 'RESTART': 120, # Restarts CR8 Firmware
52 'CONTINUE' : 253, # Function Unknown
52 'CONTINUE' : 253, # Function Unknown
53 # Commands available to new controllers
53 # Commands available to new controllers
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.
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 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 'CLOCK_DIVIDER' : 8,
57 'CLOCK_DIVIDER' : 8,
58 }
58 }
59
59
60 MAX_BITS = 8
60 MAX_BITS = 8
61
61
62 # Rotate left: 0b1001 --> 0b0011
62 # Rotate left: 0b1001 --> 0b0011
63 rol = lambda val, r_bits: \
63 rol = lambda val, r_bits: \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66
66
67 # Rotate right: 0b1001 --> 0b1100
67 # Rotate right: 0b1001 --> 0b1100
68 ror = lambda val, r_bits: \
68 ror = lambda val, r_bits: \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71
71
72
72
73 class RCConfiguration(Configuration):
73 class RCConfiguration(Configuration):
74
74
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 total_units = models.PositiveIntegerField(default=0)
86 total_units = models.PositiveIntegerField(default=0)
87 mix = models.BooleanField(default=False)
87 mix = models.BooleanField(default=False)
88
88
89 class Meta:
89 class Meta:
90 db_table = 'rc_configurations'
90 db_table = 'rc_configurations'
91
91
92 def get_absolute_url_plot(self):
92 def get_absolute_url_plot(self):
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94
94
95 @property
95 @property
96 def ipp_unit(self):
96 def ipp_unit(self):
97
97
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99
99
100 @property
100 @property
101 def us2unit(self):
101 def us2unit(self):
102
102
103 return self.clock_in/self.clock_divider
103 return self.clock_in/self.clock_divider
104
104
105 @property
105 @property
106 def km2unit(self):
106 def km2unit(self):
107
107
108 return 20./3*(self.clock_in/self.clock_divider)
108 return 20./3*(self.clock_in/self.clock_divider)
109
109
110 def clone(self, **kwargs):
110 def clone(self, **kwargs):
111
111
112 lines = self.get_lines()
112 lines = self.get_lines()
113 self.pk = None
113 self.pk = None
114 self.id = None
114 self.id = None
115 for attr, value in kwargs.items():
115 for attr, value in kwargs.items():
116 setattr(self, attr, value)
116 setattr(self, attr, value)
117 self.save()
117 self.save()
118
118
119 for line in lines:
119 for line in lines:
120 line.clone(rc_configuration=self)
120 line.clone(rc_configuration=self)
121
121
122 new_lines = self.get_lines()
122 new_lines = self.get_lines()
123 for line in new_lines:
123 for line in new_lines:
124 line_params = json.loads(line.params)
124 line_params = json.loads(line.params)
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 line.params = json.dumps(line_params)
128 line.params = json.dumps(line_params)
129 line.save()
129 line.save()
130
130
131 return self
131 return self
132
132
133 def get_lines(self, **kwargs):
133 def get_lines(self, **kwargs):
134 '''
134 '''
135 Retrieve configuration lines
135 Retrieve configuration lines
136 '''
136 '''
137
137
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139
139
140
140
141 def clean_lines(self):
141 def clean_lines(self):
142 '''
142 '''
143 '''
143 '''
144
144
145 empty_line = RCLineType.objects.get(name='none')
145 empty_line = RCLineType.objects.get(name='none')
146
146
147 for line in self.get_lines():
147 for line in self.get_lines():
148 line.line_type = empty_line
148 line.line_type = empty_line
149 line.params = '{}'
149 line.params = '{}'
150 line.save()
150 line.save()
151
151
152 def dict_to_parms(self, params, id=None):
152 def dict_to_parms(self, params, id=None):
153 '''
153 '''
154 '''
154 '''
155
155
156 if id:
156 if id:
157 data = Params(params).get_conf(id_conf=id)
157 data = Params(params).get_conf(id_conf=id)
158 else:
158 else:
159 data = Params(params).get_conf(dtype='rc')
159 data = Params(params).get_conf(dtype='rc')
160
160
161 #print(data)
161 #print(data)
162 # self.name = data['name']
162 # self.name = data['name']
163 self.ipp = data['ipp']
163 self.ipp = data['ipp']
164 self.ntx = data['ntx']
164 self.ntx = data['ntx']
165 self.clock_in = data['clock_in']
165 self.clock_in = data['clock_in']
166 self.clock_divider = data['clock_divider']
166 self.clock_divider = data['clock_divider']
167 self.clock = data['clock']
167 self.clock = data['clock']
168 self.time_before = data['time_before']
168 self.time_before = data['time_before']
169 self.time_after = data['time_after']
169 self.time_after = data['time_after']
170 self.sync = data['sync']
170 self.sync = data['sync']
171 self.sampling_reference = data['sampling_reference']
171 self.sampling_reference = data['sampling_reference']
172 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.total_units = self.ipp*self.ntx*self.km2unit
173 self.save()
173 self.save()
174 self.clean_lines()
174 self.clean_lines()
175
175
176 #print(params)
176 #print(params)
177
177
178 positions = {'tx':0, 'tr':0}
178 positions = {'tx':0, 'tr':0}
179 for i, id in enumerate(data['lines']):
179 for i, id in enumerate(data['lines']):
180 line_data = params['lines']['byId'][id]
180 line_data = params['lines']['byId'][id]
181 line_type = RCLineType.objects.get(name=line_data['line_type'])
181 line_type = RCLineType.objects.get(name=line_data['line_type'])
182 if line_type.name == 'codes':
182 if line_type.name == 'codes':
183 code = RCLineCode.objects.get(name=line_data['params']['code'])
183 code = RCLineCode.objects.get(name=line_data['params']['code'])
184 line_data['params']['code'] = code.pk
184 line_data['params']['code'] = code.pk
185 if line_type.name == 'tx':
185 if line_type.name == 'tx':
186 position = positions['tx']
186 position = positions['tx']
187 positions['tx'] += 1
187 positions['tx'] += 1
188 elif line_type.name == 'tr':
188 elif line_type.name == 'tr':
189 position = positions['tr']
189 position = positions['tr']
190 positions['tr'] += 1
190 positions['tr'] += 1
191 else:
191 else:
192 position = 0
192 position = 0
193 line, dum = RCLine.objects.update_or_create(
193 line, dum = RCLine.objects.update_or_create(
194 rc_configuration=self,
194 rc_configuration=self,
195 channel=i,
195 channel=i,
196 position=position,
196 position=position,
197 defaults={
197 defaults={
198 'line_type': line_type,
198 'line_type': line_type,
199 'params': json.dumps(line_data['params'])
199 'params': json.dumps(line_data['params'])
200 }
200 }
201 )
201 )
202
202
203 for i, line in enumerate(self.get_lines()):
203 for i, line in enumerate(self.get_lines()):
204 line_params = json.loads(line.params)
204 line_params = json.loads(line.params)
205 if 'TX_ref' in line_params:
205 if 'TX_ref' in line_params:
206 if line_params['TX_ref'] in (0, '0'):
206 if line_params['TX_ref'] in (0, '0'):
207 line_params['TX_ref'] = '0'
207 line_params['TX_ref'] = '0'
208 else:
208 else:
209 ref_id = '{}'.format(line_params['TX_ref'])
209 ref_id = '{}'.format(line_params['TX_ref'])
210 ref_line = params['lines']['byId'][ref_id]
210 ref_line = params['lines']['byId'][ref_id]
211 line_params['TX_ref'] = RCLine.objects.get(
211 line_params['TX_ref'] = RCLine.objects.get(
212 rc_configuration=self,
212 rc_configuration=self,
213 params=json.dumps(ref_line['params'])
213 params=json.dumps(ref_line['params'])
214 ).pk
214 ).pk
215 line.params = json.dumps(line_params)
215 line.params = json.dumps(line_params)
216 print(line.params)
216 print(line.params)
217 line.save()
217 line.save()
218 print("Fin de dict to param")
218 print("Fin de dict to param")
219
219
220 def get_delays(self):
220 def get_delays(self):
221
221
222 pulses = [line.pulses_as_points() for line in self.get_lines()]
222 pulses = [line.pulses_as_points() for line in self.get_lines()]
223 points = [tup for tups in pulses for tup in tups]
223 points = [tup for tups in pulses for tup in tups]
224 points = set([x for tup in points for x in tup])
224 points = set([x for tup in points for x in tup])
225 points = list(points)
225 points = list(points)
226 points.sort()
226 points.sort()
227
227
228 if points[0]!=0:
228 if points[0]!=0:
229 points.insert(0, 0)
229 points.insert(0, 0)
230
230
231 return [points[i+1]-points[i] for i in range(len(points)-1)]
231 return [points[i+1]-points[i] for i in range(len(points)-1)]
232
232
233 def get_pulses(self, binary=True):
233 def get_pulses(self, binary=True):
234
234
235 pulses = [line.pulses_as_points() for line in self.get_lines()]
235 pulses = [line.pulses_as_points() for line in self.get_lines()]
236 tuples = [tup for tups in pulses for tup in tups]
236 tuples = [tup for tups in pulses for tup in tups]
237 points = set([x for tup in tuples for x in tup])
237 points = set([x for tup in tuples for x in tup])
238 points = list(points)
238 points = list(points)
239 points.sort()
239 points.sort()
240 states = []
240 states = []
241 last = [0 for x in pulses]
241 last = [0 for x in pulses]
242 n_pulses = len(pulses)
242 n_pulses = len(pulses)
243 print('len_pulses', n_pulses)
243 print('len_pulses', n_pulses)
244 print('len_points', len(points))
244 print('len_points', len(points))
245 ups_arr = [[] for _ in range(n_pulses)]
245 ups_arr = [[] for _ in range(n_pulses)]
246 dws_arr = [[] for _ in range(n_pulses)]
246 dws_arr = [[] for _ in range(n_pulses)]
247
247
248 for i, tups in enumerate(pulses):
248 for i, tups in enumerate(pulses):
249 ups_arr[i] = [tup[0] for tup in tups if tup!=(0,0)]
249 ups_arr[i] = [tup[0] for tup in tups if tup!=(0,0)]
250 dws_arr[i] = [tup[1] for tup in tups if tup!=(0,0)]
250 dws_arr[i] = [tup[1] for tup in tups if tup!=(0,0)]
251 print('len_points*n_pulses',len(points)*n_pulses)
251 print('len_points*n_pulses',len(points)*n_pulses)
252 #print('ups_arr', ups_arr)
252 #print('ups_arr', ups_arr)
253 #print('dws_arr', dws_arr)
253 #print('dws_arr', dws_arr)
254
254
255 #####################Code for load configuration#########################
255 for x in points:
256 for x in points:
256 dum = []
257 dum = []
257 print('loading', x*100/max(points))
258 print('loading', x*100/max(points))
258
259
259 for i in range(n_pulses):
260 for i in range(n_pulses):
260 if x in ups_arr[i]:
261 if x in ups_arr[i]:
261 dum.append(1)
262 dum.append(1)
262 elif x in dws_arr[i]:
263 elif x in dws_arr[i]:
263 dum.append(0)
264 dum.append(0)
264 else:
265 else:
265 dum.append(last[i])
266 dum.append(last[i])
266 #print(dum)
267 #print(dum)
267 states.append(dum)
268 states.append(dum)
268 last = dum
269 last = dum
270 print("Finish loading")
271 #########################################################################
269
272
270 if binary:
273 if binary:
271 ret = []
274 ret = []
272 for flips in states:
275 for flips in states:
273 flips.reverse()
276 flips.reverse()
274 ret.append(int(''.join([str(x) for x in flips]), 2))
277 ret.append(int(''.join([str(x) for x in flips]), 2))
275 states = ret
278 states = ret
276 #print(states[:-1])
279 #print(states[:-1])
277 #print('len_states',len(states[:-1]))
280 #print('len_states',len(states[:-1]))
278
281
279 return states[:-1]
282 return states[:-1]
280
283
281 def add_cmd(self, cmd):
284 def add_cmd(self, cmd):
282
285
283 if cmd in DAT_CMDS:
286 if cmd in DAT_CMDS:
284 return (255, DAT_CMDS[cmd])
287 return (255, DAT_CMDS[cmd])
285
288
286 def add_data(self, value):
289 def add_data(self, value):
287
290
288 return (254, value-1)
291 return (254, value-1)
289
292
290 def parms_to_binary(self, dat=True):
293 def parms_to_binary(self, dat=True):
291 '''
294 '''
292 Create "dat" stream to be send to CR
295 Create "dat" stream to be send to CR
293 '''
296 '''
294
297
295 data = bytearray()
298 data = bytearray()
296 # create header
299 # create header
297 data.extend(self.add_cmd('DISABLE'))
300 data.extend(self.add_cmd('DISABLE'))
298 data.extend(self.add_cmd('CONTINUE'))
301 data.extend(self.add_cmd('CONTINUE'))
299 data.extend(self.add_cmd('RESTART'))
302 data.extend(self.add_cmd('RESTART'))
300
303
301 if self.control_sw:
304 if self.control_sw:
302 data.extend(self.add_cmd('SW_ONE'))
305 data.extend(self.add_cmd('SW_ONE'))
303 else:
306 else:
304 data.extend(self.add_cmd('SW_ZERO'))
307 data.extend(self.add_cmd('SW_ZERO'))
305
308
306 if self.control_tx:
309 if self.control_tx:
307 data.extend(self.add_cmd('TX_ONE'))
310 data.extend(self.add_cmd('TX_ONE'))
308 else:
311 else:
309 data.extend(self.add_cmd('TX_ZERO'))
312 data.extend(self.add_cmd('TX_ZERO'))
310
313
311 # write divider
314 # write divider
312 data.extend(self.add_cmd('CLOCK_DIVIDER'))
315 data.extend(self.add_cmd('CLOCK_DIVIDER'))
313 data.extend(self.add_data(self.clock_divider))
316 data.extend(self.add_data(self.clock_divider))
314
317
315 # write delays
318 # write delays
316 data.extend(self.add_cmd('DELAY_START'))
319 data.extend(self.add_cmd('DELAY_START'))
317 # first delay is always zero
320 # first delay is always zero
318 data.extend(self.add_data(1))
321 data.extend(self.add_data(1))
319
322
320 delays = self.get_delays()
323 delays = self.get_delays()
321
324
322 for delay in delays:
325 for delay in delays:
323 while delay>252:
326 while delay>252:
324 data.extend(self.add_data(253))
327 data.extend(self.add_data(253))
325 delay -= 253
328 delay -= 253
326 data.extend(self.add_data(int(delay)))
329 data.extend(self.add_data(int(delay)))
327
330
328 # write flips
331 # write flips
329 data.extend(self.add_cmd('FLIP_START'))
332 data.extend(self.add_cmd('FLIP_START'))
330
333
331 states = self.get_pulses(binary=True)
334 states = self.get_pulses(binary=True)
332
335
333
336
334 last = 0
337 last = 0
335 for flip, delay in zip(states, delays):
338 for flip, delay in zip(states, delays):
336 data.extend(self.add_data((flip^last)+1))
339 data.extend(self.add_data((flip^last)+1))
337 last = flip
340 last = flip
338 while delay>252:
341 while delay>252:
339 data.extend(self.add_data(1))
342 data.extend(self.add_data(1))
340 delay -= 253
343 delay -= 253
341
344
342 # write sampling period
345 # write sampling period
343 data.extend(self.add_cmd('SAMPLING_PERIOD'))
346 data.extend(self.add_cmd('SAMPLING_PERIOD'))
344 wins = self.get_lines(line_type__name='windows')
347 wins = self.get_lines(line_type__name='windows')
345 if wins:
348 if wins:
346 win_params = json.loads(wins[0].params)['params']
349 win_params = json.loads(wins[0].params)['params']
347 if win_params:
350 if win_params:
348 dh = int(win_params[0]['resolution']*self.km2unit)
351 dh = int(win_params[0]['resolution']*self.km2unit)
349 else:
352 else:
350 dh = 1
353 dh = 1
351 else:
354 else:
352 dh = 1
355 dh = 1
353 data.extend(self.add_data(dh))
356 data.extend(self.add_data(dh))
354
357
355 # write enable
358 # write enable
356 data.extend(self.add_cmd('ENABLE'))
359 data.extend(self.add_cmd('ENABLE'))
357
360
358 if not dat:
361 if not dat:
359 return data
362 return data
360
363
361 return '\n'.join(['{}'.format(x) for x in data])
364 return '\n'.join(['{}'.format(x) for x in data])
362
365
363 def update_pulses(self):
366 def update_pulses(self):
364 contador = 0
367 contador = 0
365 for line in self.get_lines():
368 for line in self.get_lines():
366 contador=contador+1
369 contador=contador+1
367 print(contador)
370 print(contador)
368 line.update_pulses()
371 line.update_pulses()
369
372
370 def plot_pulses2(self, km=False):
373 def plot_pulses2(self, km=False):
371
374
372 import matplotlib
375 import matplotlib
373 matplotlib.use('Agg')
376 matplotlib.use('Agg')
374 import matplotlib.pyplot as plt
377 import matplotlib.pyplot as plt
375 from bokeh.resources import CDN
378 from bokeh.resources import CDN
376 from bokeh.embed import components
379 from bokeh.embed import components
377 from bokeh.mpl import to_bokeh
380 from bokeh.mpl import to_bokeh
378 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
381 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
379
382
380 lines = self.get_lines()
383 lines = self.get_lines()
381
384
382 N = len(lines)
385 N = len(lines)
383 npoints = self.total_units/self.km2unit if km else self.total_units
386 npoints = self.total_units/self.km2unit if km else self.total_units
384 fig = plt.figure(figsize=(12, 2+N*0.5))
387 fig = plt.figure(figsize=(12, 2+N*0.5))
385 ax = fig.add_subplot(111)
388 ax = fig.add_subplot(111)
386 labels = ['IPP']
389 labels = ['IPP']
387
390
388 for i, line in enumerate(lines):
391 for i, line in enumerate(lines):
389 labels.append(line.get_name(channel=True))
392 labels.append(line.get_name(channel=True))
390 l = ax.plot((0, npoints),(N-i-1, N-i-1))
393 l = ax.plot((0, npoints),(N-i-1, N-i-1))
391 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
394 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
392 ax.broken_barh(points, (N-i-1, 0.5),
395 ax.broken_barh(points, (N-i-1, 0.5),
393 edgecolor=l[0].get_color(), facecolor='none')
396 edgecolor=l[0].get_color(), facecolor='none')
394
397
395 n = 0
398 n = 0
396 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
399 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
397 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
400 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
398 if n%f==0:
401 if n%f==0:
399 ax.text(x, N, '%s' % n, size=10)
402 ax.text(x, N, '%s' % n, size=10)
400 n += 1
403 n += 1
401
404
402 labels.reverse()
405 labels.reverse()
403 ax.set_yticks(range(len(labels)))
406 ax.set_yticks(range(len(labels)))
404 ax.set_yticklabels(labels)
407 ax.set_yticklabels(labels)
405 ax.set_xlabel = 'Units'
408 ax.set_xlabel = 'Units'
406 plot = to_bokeh(fig, use_pandas=False)
409 plot = to_bokeh(fig, use_pandas=False)
407 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
410 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
408 plot.toolbar_location="above"
411 plot.toolbar_location="above"
409
412
410 return components(plot, CDN)
413 return components(plot, CDN)
411
414
412 def plot_pulses(self, km=False):
415 def plot_pulses(self, km=False):
413
416
414 from bokeh.plotting import figure
417 from bokeh.plotting import figure
415 from bokeh.resources import CDN
418 from bokeh.resources import CDN
416 from bokeh.embed import components
419 from bokeh.embed import components
417 from bokeh.models import FixedTicker, PrintfTickFormatter, Label
420 from bokeh.models import FixedTicker, PrintfTickFormatter, Label
418 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
421 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
419 from bokeh.models.sources import ColumnDataSource
422 from bokeh.models.sources import ColumnDataSource
420
423
421 lines = self.get_lines().reverse()
424 lines = self.get_lines().reverse()
422
425
423 N = len(lines)
426 N = len(lines)
424 npoints = self.total_units/self.km2unit if km else self.total_units
427 npoints = self.total_units/self.km2unit if km else self.total_units
425 ipp = self.ipp if km else self.ipp*self.km2unit
428 ipp = self.ipp if km else self.ipp*self.km2unit
426
429
427 hover = HoverTool(tooltips=[("Line", "@name"),
430 hover = HoverTool(tooltips=[("Line", "@name"),
428 ("IPP", "@ipp"),
431 ("IPP", "@ipp"),
429 ("X", "@left")])
432 ("X", "@left")])
430
433
431 tools = [PanTool(dimensions="width"),
434 tools = [PanTool(dimensions="width"),
432 WheelZoomTool(dimensions="width"),
435 WheelZoomTool(dimensions="width"),
433 hover, SaveTool()]
436 hover, SaveTool()]
434
437
435 plot = figure(width=1000,
438 plot = figure(width=1000,
436 height=40+N*50,
439 height=40+N*50,
437 y_range = (0, N),
440 y_range = (0, N),
438 tools=tools,
441 tools=tools,
439 toolbar_location='above',
442 toolbar_location='above',
440 toolbar_sticky=False,)
443 toolbar_sticky=False,)
441
444
442 pulses = [line.pulses_as_points() for line in self.get_lines()]
445 pulses = [line.pulses_as_points() for line in self.get_lines()]
443 tuples = [tup for tups in pulses for tup in tups]
446 tuples = [tup for tups in pulses for tup in tups]
444 points = set([x for tup in tuples for x in tup])
447 points = set([x for tup in tuples for x in tup])
445 capacity_bytes = round((8*(len(points)-1)+12)/2) # se divide entre 2 porque la mitad era solo para direcciones
448 capacity_bytes = round((8*(len(points)-1)+12)/2) # se divide entre 2 porque la mitad era solo para direcciones
446 capacity_percent = (capacity_bytes/2097152)*100
449 capacity_percent = (capacity_bytes/2097152)*100
447 # Add the used memory message
450 # Add the used memory message
448 x_label_memory = Label(x=900, y=-1.5, text='Used memory of '+str(capacity_bytes)+'/2097152 bytes ('+'%.3f'%capacity_percent+'%)', text_align="right", x_units='screen', text_font_size='14pt')
451 x_label_memory = Label(x=900, y=-1.5, text='Used memory of '+str(capacity_bytes)+'/2097152 bytes ('+'%.3f'%capacity_percent+'%)', text_align="right", x_units='screen', text_font_size='14pt')
449 plot.add_layout(x_label_memory, 'below')
452 plot.add_layout(x_label_memory, 'below')
450
453
451 plot.xaxis.axis_label = 'Km' if km else 'Units'
454 plot.xaxis.axis_label = 'Km' if km else 'Units'
452 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
455 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
453 plot.yaxis.axis_label = 'Pulses'
456 plot.yaxis.axis_label = 'Pulses'
454 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
457 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
455 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
458 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
456
459
457 for i, line in enumerate(lines):
460 for i, line in enumerate(lines):
458
461
459 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
462 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
460
463
461 source = ColumnDataSource(data = dict(
464 source = ColumnDataSource(data = dict(
462 bottom = [i for tup in points],
465 bottom = [i for tup in points],
463 top = [i+0.5 for tup in points],
466 top = [i+0.5 for tup in points],
464 left = [tup[0] for tup in points],
467 left = [tup[0] for tup in points],
465 right = [tup[1] for tup in points],
468 right = [tup[1] for tup in points],
466 ipp = [int(tup[0]/ipp) for tup in points],
469 ipp = [int(tup[0]/ipp) for tup in points],
467 name = [line.get_name() for tup in points]
470 name = [line.get_name() for tup in points]
468 ))
471 ))
469
472
470 plot.quad(
473 plot.quad(
471 bottom = 'bottom',
474 bottom = 'bottom',
472 top = 'top',
475 top = 'top',
473 left = 'left',
476 left = 'left',
474 right = 'right',
477 right = 'right',
475 source = source,
478 source = source,
476 fill_alpha = 0,
479 fill_alpha = 0,
477 #line_color = 'blue',
480 #line_color = 'blue',
478 )
481 )
479
482
480 plot.line([0, npoints], [i, i])#, color='blue')
483 plot.line([0, npoints], [i, i])#, color='blue')
481
484
482 return components(plot, CDN)
485 return components(plot, CDN)
483
486
484 def request(self, cmd, method='get', **kwargs):
487 def request(self, cmd, method='get', **kwargs):
485
488
486 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
489 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
487 payload = req.json()
490 payload = req.json()
488
491
489 return payload
492 return payload
490
493
491 def status_device(self):
494 def status_device(self):
492
495
493 try:
496 try:
494 self.device.status = 0
497 self.device.status = 0
495 payload = self.request('status')
498 payload = self.request('status')
496 if payload['status']=='enable':
499 if payload['status']=='enable':
497 self.device.status = 3
500 self.device.status = 3
498 elif payload['status']=='disable':
501 elif payload['status']=='disable':
499 self.device.status = 2
502 self.device.status = 2
500 else:
503 else:
501 self.device.status = 1
504 self.device.status = 1
502 self.device.save()
505 self.device.save()
503 self.message = 'RC status: {}'.format(payload['status'])
506 self.message = 'RC status: {}'.format(payload['status'])
504 return False
507 return False
505 except Exception as e:
508 except Exception as e:
506 if 'No route to host' not in str(e):
509 if 'No route to host' not in str(e):
507 self.device.status = 4
510 self.device.status = 4
508 self.device.save()
511 self.device.save()
509 self.message = 'RC status: {}'.format(str(e))
512 self.message = 'RC status: {}'.format(str(e))
510 return False
513 return False
511
514
512 self.device.save()
515 self.device.save()
513 return True
516 return True
514
517
515 def reset_device(self):
518 def reset_device(self):
516
519
517 try:
520 try:
518 payload = self.request('reset', 'post')
521 payload = self.request('reset', 'post')
519 if payload['reset']=='ok':
522 if payload['reset']=='ok':
520 self.message = 'RC restarted OK'
523 self.message = 'RC restarted OK'
521 self.device.status = 2
524 self.device.status = 2
522 self.device.save()
525 self.device.save()
523 else:
526 else:
524 self.message = 'RC restart fail'
527 self.message = 'RC restart fail'
525 self.device.status = 4
528 self.device.status = 4
526 self.device.save()
529 self.device.save()
527 except Exception as e:
530 except Exception as e:
528 self.message = 'RC reset: {}'.format(str(e))
531 self.message = 'RC reset: {}'.format(str(e))
529 return False
532 return False
530
533
531 return True
534 return True
532
535
533 def stop_device(self):
536 def stop_device(self):
534
537
535 try:
538 try:
536 payload = self.request('stop', 'post')
539 payload = self.request('stop', 'post')
537 self.message = 'RC stop: {}'.format(payload['stop'])
540 self.message = 'RC stop: {}'.format(payload['stop'])
538 if payload['stop']=='ok':
541 if payload['stop']=='ok':
539 self.device.status = 2
542 self.device.status = 2
540 self.device.save()
543 self.device.save()
541 else:
544 else:
542 self.device.status = 4
545 self.device.status = 4
543 self.device.save()
546 self.device.save()
544 return False
547 return False
545 except Exception as e:
548 except Exception as e:
546 if 'No route to host' not in str(e):
549 if 'No route to host' not in str(e):
547 self.device.status = 4
550 self.device.status = 4
548 else:
551 else:
549 self.device.status = 0
552 self.device.status = 0
550 self.message = 'RC stop: {}'.format(str(e))
553 self.message = 'RC stop: {}'.format(str(e))
551 self.device.save()
554 self.device.save()
552 return False
555 return False
553
556
554 return True
557 return True
555
558
556 def start_device(self):
559 def start_device(self):
557
560
558 try:
561 try:
559 payload = self.request('start', 'post')
562 payload = self.request('start', 'post')
560 self.message = 'RC start: {}'.format(payload['start'])
563 self.message = 'RC start: {}'.format(payload['start'])
561 if payload['start']=='ok':
564 if payload['start']=='ok':
562 self.device.status = 3
565 self.device.status = 3
563 self.device.save()
566 self.device.save()
564 else:
567 else:
565 return False
568 return False
566 except Exception as e:
569 except Exception as e:
567 if 'No route to host' not in str(e):
570 if 'No route to host' not in str(e):
568 self.device.status = 4
571 self.device.status = 4
569 else:
572 else:
570 self.device.status = 0
573 self.device.status = 0
571 self.message = 'RC start: {}'.format(str(e))
574 self.message = 'RC start: {}'.format(str(e))
572 self.device.save()
575 self.device.save()
573 return False
576 return False
574
577
575 return True
578 return True
576
579
577 def write_device(self, raw=False):
580 def write_device(self, raw=False):
578 print("write device")
581 print("write device")
582 ##############Comando status a CGS para hacer programacion ############
583 try:
584 self.device.status = 0
585 cgs = self.request('status_cgs')
586 print('CGS status ok') # solo para depurar lo que devuelve CGS
587 except Exception as e:
588 cgs = {'multiplier': 60, 'divider': 10, 'reference_clk': 1} # simulando parametros devueltos por el cgs
589 if 'No route to host' not in str(e):
590 self.device.status = 4
591 self.device.save()
592 self.message = 'CGS status: {}'.format(str(e))
593 print('not cgs status')
594
595 print(cgs)
579
596
580 if not raw:
597 if not raw:
581 clock = RCClock.objects.get(rc_configuration=self)
598 clock = RCClock.objects.get(rc_configuration=self)
599 print('clock_freq', clock.frequency)
600 print('clock_mult', clock.multiplier)
601 print('clock_div', clock.divisor)
602 print('clock_ref', clock.reference)
603 print('cgs', cgs)
582 if clock.mode:
604 if clock.mode:
583 data = {'default': clock.frequency}
605 data = {'default': clock.frequency} # mult=72, div=12
584 else:
606 else:
585 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
607 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
586 payload = self.request('setfreq', 'post', data=json.dumps(data))
608 print('data', data)
587 #if payload['setfreq'] != 'ok':
609 int_cgs_multiplier=int(cgs['multiplier'])
588 if payload['command'] != 'ok':
610 int_cgs_divisor=int(cgs['divider'])
589 #self.message = 'RC write: {}'.format(payload['setfreq'])
611 int_cgs_reference=int(cgs['reference_clk'])
590 self.message = 'RC write: {}'.format(payload['command'])
612 print(cgs['divider'])
613
614 if clock.multiplier != int_cgs_multiplier or clock.divisor != int_cgs_divisor or clock.reference != int_cgs_reference:
615 print("Program CGS...")
616 payload = self.request('setfreq', 'post', data=json.dumps(data))#data=data)#data=json.dumps(data))
617 if payload['command'] != 'ok':
618 self.message = 'RC write: {}'.format(payload['command'])
619 else:
620 self.message = payload['programming']
621 if payload['programming'] == 'fail':
622 self.message = 'RC write: error programming CGS chip'
591 else:
623 else:
592 #self.message = payload['setfreq']
624 print("Not program CGS...")
593 self.message = payload['programming']
594 #if payload['setfreq'] == 'fail':
595 if payload['programming'] == 'fail':
596 self.message = 'RC write: error programming CGS chip'
597
625
598 values = []
626 values = []
599 print('wait delay values...')
627 print('wait delay values...')
600 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
628 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
601 #print('wait zip...')
629 #print('wait zip...')
602 while delay > 65536:
630 while delay > 65536:
603 values.append((pulse, 65535))
631 values.append((pulse, 65535))
604 delay -= 65536
632 delay -= 65536
605 values.append((pulse, delay-1))
633 values.append((pulse, delay-1))
606 data = bytearray()
634 data = bytearray()
607 #reset
635 #reset
608 data.extend((128, 0))
636 data.extend((128, 0))
609 #disable
637 #disable
610 data.extend((129, 0))
638 data.extend((129, 0))
611 #SW switch
639 #SW switch
612 if self.control_sw:
640 if self.control_sw:
613 data.extend((130, 2))
641 data.extend((130, 2))
614 else:
642 else:
615 data.extend((130, 0))
643 data.extend((130, 0))
616 #divider
644 #divider
617 data.extend((131, self.clock_divider-1))
645 data.extend((131, self.clock_divider-1))
618 #enable writing
646 #enable writing
619 data.extend((139, 62))
647 data.extend((139, 62))
620
648
621 last = 0
649 last = 0
622 print('wait data...')
650 print('wait data...')
623 for tup in values:
651 for tup in values:
624 vals = pack('<HH', last^tup[0], tup[1])
652 vals = pack('<HH', last^tup[0], tup[1])
625 last = tup[0]
653 last = tup[0]
626 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
654 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
627
655
628 #enable
656 #enable
629 data.extend((129, 1))
657 data.extend((129, 1))
630 print('len',len(data))
658 print('len',len(data))
631
659
632 if raw:
660 if raw:
633 return b64encode(data)
661 return b64encode(data)
634
662
635 #try:
663 #try:
636 print('requests')
664 print('requests')
637 payload = self.request('stop', 'post')
665 payload = self.request('stop', 'post')
638 payload = self.request('reset', 'post')
666 payload = self.request('reset', 'post')
639 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
667 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
640 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
668 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
641 n = len(data)
669 n = len(data)
642 print('len: ',n)
670 print('len: ',n)
643 x = 0
671 x = 0
644 cnt = 0
672 cnt = 0
645 while x < n:
673 while x < n:
646 print('writing...', cnt)
674 print('writing...', cnt)
647 payload = self.request('write', 'post', data=b64encode(data[x:x+3072]))#(data))#
675 payload = self.request('write', 'post', data=b64encode(data[x:x+16384]))#(data))#
648 x += 3072
676 x += 16384
649 cnt += 1#time.sleep(1)
677 cnt += 1#time.sleep(1)
650 print('writing...', x*100/n)
678 print('writing...', x*100/n)
651
679
652 if payload['write']=='ok':
680 if payload['write']=='ok':
653 self.device.status = 3
681 self.device.status = 3
654 self.device.save()
682 self.device.save()
655 self.message = 'RC configured and started'
683 self.message = 'RC configured and started'
656 else:
684 else:
657 self.device.status = 1
685 self.device.status = 1
658 self.device.save()
686 self.device.save()
659 self.message = 'RC write: {}'.format(payload['write'])
687 self.message = 'RC write: {}'.format(payload['write'])
660 return False
688 return False
661
689
662 #payload = self.request('start', 'post')
690 #payload = self.request('start', 'post')
663
691
664 #except Exception as e:
692 #except Exception as e:
665 # if 'No route to host' not in str(e):
693 # if 'No route to host' not in str(e):
666 # self.device.status = 4
694 # self.device.status = 4
667 # else:
695 # else:
668 # self.device.status = 0
696 # self.device.status = 0
669 # self.message = 'RC write: {}'.format(str(e))
697 # self.message = 'RC write: {}'.format(str(e))
670 # self.device.save()
698 # self.device.save()
671 # return False
699 # return False
672
700
673 return True
701 return True
674
702
675
703
676 def get_absolute_url_import(self):
704 def get_absolute_url_import(self):
677 return reverse('url_import_rc_conf', args=[str(self.id)])
705 return reverse('url_import_rc_conf', args=[str(self.id)])
678
706
679
707
680 class RCLineCode(models.Model):
708 class RCLineCode(models.Model):
681
709
682 name = models.CharField(max_length=40)
710 name = models.CharField(max_length=40)
683 bits_per_code = models.PositiveIntegerField(default=0)
711 bits_per_code = models.PositiveIntegerField(default=0)
684 number_of_codes = models.PositiveIntegerField(default=0)
712 number_of_codes = models.PositiveIntegerField(default=0)
685 codes = models.TextField(blank=True, null=True)
713 codes = models.TextField(blank=True, null=True)
686
714
687 class Meta:
715 class Meta:
688 db_table = 'rc_line_codes'
716 db_table = 'rc_line_codes'
689 ordering = ('name',)
717 ordering = ('name',)
690
718
691 def __str__(self):
719 def __str__(self):
692 return u'%s' % self.name
720 return u'%s' % self.name
693
721
694
722
695 class RCLineType(models.Model):
723 class RCLineType(models.Model):
696
724
697 name = models.CharField(choices=LINE_TYPES, max_length=40)
725 name = models.CharField(choices=LINE_TYPES, max_length=40)
698 description = models.TextField(blank=True, null=True)
726 description = models.TextField(blank=True, null=True)
699 params = models.TextField(default='[]')
727 params = models.TextField(default='[]')
700
728
701 class Meta:
729 class Meta:
702 db_table = 'rc_line_types'
730 db_table = 'rc_line_types'
703
731
704 def __str__(self):
732 def __str__(self):
705 return u'%s - %s' % (self.name.upper(), self.get_name_display())
733 return u'%s - %s' % (self.name.upper(), self.get_name_display())
706
734
707
735
708 class RCLine(models.Model):
736 class RCLine(models.Model):
709
737
710 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
738 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
711 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
739 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
712 channel = models.PositiveIntegerField(default=0)
740 channel = models.PositiveIntegerField(default=0)
713 position = models.PositiveIntegerField(default=0)
741 position = models.PositiveIntegerField(default=0)
714 params = models.TextField(default='{}')
742 params = models.TextField(default='{}')
715 pulses = models.TextField(default='')
743 pulses = models.TextField(default='')
716
744
717 class Meta:
745 class Meta:
718 db_table = 'rc_lines'
746 db_table = 'rc_lines'
719 ordering = ['channel']
747 ordering = ['channel']
720
748
721 def __str__(self):
749 def __str__(self):
722 if self.rc_configuration:
750 if self.rc_configuration:
723 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
751 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
724
752
725 def jsonify(self):
753 def jsonify(self):
726
754
727 data = {}
755 data = {}
728 data['params'] = json.loads(self.params)
756 data['params'] = json.loads(self.params)
729 data['id'] = '{}'.format(self.pk)
757 data['id'] = '{}'.format(self.pk)
730 data['line_type'] = self.line_type.name
758 data['line_type'] = self.line_type.name
731 data['name'] = self.get_name()
759 data['name'] = self.get_name()
732 if data['line_type']=='codes':
760 if data['line_type']=='codes':
733 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
761 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
734
762
735 return data
763 return data
736
764
737
765
738 def clone(self, **kwargs):
766 def clone(self, **kwargs):
739
767
740 self.pk = None
768 self.pk = None
741 self.id = None
769 self.id = None
742
770
743 for attr, value in kwargs.items():
771 for attr, value in kwargs.items():
744 setattr(self, attr, value)
772 setattr(self, attr, value)
745
773
746 self.save()
774 self.save()
747
775
748 return self
776 return self
749
777
750 def get_name(self, channel=False):
778 def get_name(self, channel=False):
751
779
752 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
780 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
753 s = ''
781 s = ''
754
782
755 if self.line_type.name in ('tx',):
783 if self.line_type.name in ('tx',):
756 s = chars[self.position]
784 s = chars[self.position]
757 elif self.line_type.name in ('codes', 'windows', 'tr'):
785 elif self.line_type.name in ('codes', 'windows', 'tr'):
758 if 'TX_ref' in json.loads(self.params):
786 if 'TX_ref' in json.loads(self.params):
759 pk = json.loads(self.params)['TX_ref']
787 pk = json.loads(self.params)['TX_ref']
760 if pk in (0, '0'):
788 if pk in (0, '0'):
761 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
789 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
762 else:
790 else:
763 ref = RCLine.objects.get(pk=pk)
791 ref = RCLine.objects.get(pk=pk)
764 s = chars[ref.position]
792 s = chars[ref.position]
765 s = '({})'.format(s)
793 s = '({})'.format(s)
766
794
767 s = '{}{}'.format(self.line_type.name.upper(), s)
795 s = '{}{}'.format(self.line_type.name.upper(), s)
768
796
769 if channel:
797 if channel:
770 return '{} {}'.format(s, self.channel)
798 return '{} {}'.format(s, self.channel)
771 else:
799 else:
772 return s
800 return s
773
801
774 def get_lines(self, **kwargs):
802 def get_lines(self, **kwargs):
775
803
776 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
804 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
777
805
778 def pulses_as_array(self):
806 def pulses_as_array(self):
779
807
780 y = np.zeros(self.rc_configuration.total_units)
808 y = np.zeros(self.rc_configuration.total_units)
781
809
782 for tup in ast.literal_eval(self.pulses):
810 for tup in ast.literal_eval(self.pulses):
783 y[tup[0]:tup[1]] = 1
811 y[tup[0]:tup[1]] = 1
784
812
785 return y.astype(np.int8)
813 return y.astype(np.int8)
786
814
787 def pulses_as_points(self, km=False):
815 def pulses_as_points(self, km=False):
788
816
789 if km:
817 if km:
790 unit2km = 1/self.rc_configuration.km2unit
818 unit2km = 1/self.rc_configuration.km2unit
791 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
819 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
792 else:
820 else:
793 return ast.literal_eval(self.pulses)
821 return ast.literal_eval(self.pulses)
794
822
795 def get_win_ref(self, params, tx_id, km2unit):
823 def get_win_ref(self, params, tx_id, km2unit):
796
824
797 ref = self.rc_configuration.sampling_reference
825 ref = self.rc_configuration.sampling_reference
798 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
826 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
799
827
800 if codes:
828 if codes:
801 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
829 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
802 else:
830 else:
803 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
831 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
804
832
805 if ref=='first_baud':
833 if ref=='first_baud':
806 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
834 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
807 elif ref=='sub_baud':
835 elif ref=='sub_baud':
808 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
836 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
809 else:
837 else:
810 return 0
838 return 0
811
839
812 def update_pulses(self):
840 def update_pulses(self):
813 '''
841 '''
814 Update pulses field
842 Update pulses field
815 '''
843 '''
816
844
817 km2unit = self.rc_configuration.km2unit
845 km2unit = self.rc_configuration.km2unit
818 us2unit = self.rc_configuration.us2unit
846 us2unit = self.rc_configuration.us2unit
819 ipp = self.rc_configuration.ipp
847 ipp = self.rc_configuration.ipp
820 ntx = int(self.rc_configuration.ntx)
848 ntx = int(self.rc_configuration.ntx)
821 ipp_u = int(ipp*km2unit)
849 ipp_u = int(ipp*km2unit)
822 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
850 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
823 y = []
851 y = []
824
852
825 if self.line_type.name=='tr':
853 if self.line_type.name=='tr':
826 tr_params = json.loads(self.params)
854 tr_params = json.loads(self.params)
827 #print(tr_params)
855 #print(tr_params)
828 #print(tr_params['TX_ref'])
856 #print(tr_params['TX_ref'])
829 if tr_params['TX_ref'] in ('0', 0):
857 if tr_params['TX_ref'] in ('0', 0):
830 txs = self.get_lines(line_type__name='tx')
858 txs = self.get_lines(line_type__name='tx')
831 else:
859 else:
832 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
860 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
833
861
834 for tx in txs:
862 for tx in txs:
835 params = json.loads(tx.params)
863 params = json.loads(tx.params)
836
864
837 if float(params['pulse_width'])==0:
865 if float(params['pulse_width'])==0:
838 continue
866 continue
839 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
867 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
840 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
868 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
841 before = 0
869 before = 0
842 after = int(self.rc_configuration.time_after*us2unit)
870 after = int(self.rc_configuration.time_after*us2unit)
843
871
844 y_tx = self.points(ntx, ipp_u, width,
872 y_tx = self.points(ntx, ipp_u, width,
845 delay=delays,
873 delay=delays,
846 before=before,
874 before=before,
847 after=after,
875 after=after,
848 sync=self.rc_configuration.sync)
876 sync=self.rc_configuration.sync)
849
877
850 ranges = params['range'].split(',')
878 ranges = params['range'].split(',')
851
879
852 if len(ranges)>0 and ranges[0]!='0':
880 if len(ranges)>0 and ranges[0]!='0':
853 y_tx = self.mask_ranges(y_tx, ranges)
881 y_tx = self.mask_ranges(y_tx, ranges)
854
882
855 tr_ranges = tr_params['range'].split(',')
883 tr_ranges = tr_params['range'].split(',')
856
884
857 if len(tr_ranges)>0 and tr_ranges[0]!='0':
885 if len(tr_ranges)>0 and tr_ranges[0]!='0':
858 y_tx = self.mask_ranges(y_tx, tr_ranges)
886 y_tx = self.mask_ranges(y_tx, tr_ranges)
859
887
860 y.extend(y_tx)
888 y.extend(y_tx)
861
889
862 self.pulses = str(y)
890 self.pulses = str(y)
863 y = self.array_to_points(self.pulses_as_array())
891 y = self.array_to_points(self.pulses_as_array())
864
892
865 elif self.line_type.name=='tx':
893 elif self.line_type.name=='tx':
866 params = json.loads(self.params)
894 params = json.loads(self.params)
867 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
895 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
868 width = float(params['pulse_width'])*km2unit
896 width = float(params['pulse_width'])*km2unit
869
897
870 if width>0:
898 if width>0:
871 before = int(self.rc_configuration.time_before*us2unit)
899 before = int(self.rc_configuration.time_before*us2unit)
872 after = 0
900 after = 0
873
901
874 y = self.points(ntx, ipp_u, width,
902 y = self.points(ntx, ipp_u, width,
875 delay=delays,
903 delay=delays,
876 before=before,
904 before=before,
877 after=after,
905 after=after,
878 sync=self.rc_configuration.sync)
906 sync=self.rc_configuration.sync)
879
907
880 ranges = params['range'].split(',')
908 ranges = params['range'].split(',')
881
909
882 if len(ranges)>0 and ranges[0]!='0':
910 if len(ranges)>0 and ranges[0]!='0':
883 y = self.mask_ranges(y, ranges)
911 y = self.mask_ranges(y, ranges)
884
912
885 elif self.line_type.name=='flip':
913 elif self.line_type.name=='flip':
886 n = float(json.loads(self.params)['number_of_flips'])
914 n = float(json.loads(self.params)['number_of_flips'])
887 width = n*ipp*km2unit
915 width = n*ipp*km2unit
888 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
916 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
889
917
890 elif self.line_type.name=='codes':
918 elif self.line_type.name=='codes':
891 params = json.loads(self.params)
919 params = json.loads(self.params)
892 tx = RCLine.objects.get(pk=params['TX_ref'])
920 tx = RCLine.objects.get(pk=params['TX_ref'])
893 tx_params = json.loads(tx.params)
921 tx_params = json.loads(tx.params)
894 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
922 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
895 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
923 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
896 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
924 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
897 codes = [self.array_to_points(code) for code in codes]
925 codes = [self.array_to_points(code) for code in codes]
898 n = len(codes)
926 n = len(codes)
899
927
900 ranges = tx_params['range'].split(',')
928 ranges = tx_params['range'].split(',')
901 if len(ranges)>0 and ranges[0]!='0':
929 if len(ranges)>0 and ranges[0]!='0':
902 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
930 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
903 else:
931 else:
904 dum = tx.pulses_as_points()
932 dum = tx.pulses_as_points()
905
933
906 for i, tup in enumerate(dum):
934 for i, tup in enumerate(dum):
907 if tup==(0,0): continue
935 if tup==(0,0): continue
908 code = codes[i%n]
936 code = codes[i%n]
909 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
937 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
910
938
911 elif self.line_type.name=='sync':
939 elif self.line_type.name=='sync':
912 params = json.loads(self.params)
940 params = json.loads(self.params)
913 n = ipp_u*ntx
941 n = ipp_u*ntx
914 if params['invert'] in ('1', 1):
942 if params['invert'] in ('1', 1):
915 y = [(n-1, n)]
943 y = [(n-1, n)]
916 else:
944 else:
917 y = [(0, 1)]
945 y = [(0, 1)]
918
946
919 elif self.line_type.name=='prog_pulses':
947 elif self.line_type.name=='prog_pulses':
920 params = json.loads(self.params)
948 params = json.loads(self.params)
921 if int(params['periodic'])==0:
949 if int(params['periodic'])==0:
922 nntx = 1
950 nntx = 1
923 nipp = ipp_u*ntx
951 nipp = ipp_u*ntx
924 else:
952 else:
925 nntx = ntx
953 nntx = ntx
926 nipp = ipp_u
954 nipp = ipp_u
927
955
928 if 'params' in params and len(params['params'])>0:
956 if 'params' in params and len(params['params'])>0:
929 for p in params['params']:
957 for p in params['params']:
930 y_pp = self.points(nntx, nipp,
958 y_pp = self.points(nntx, nipp,
931 p['end']-p['begin'],
959 p['end']-p['begin'],
932 before=p['begin'])
960 before=p['begin'])
933
961
934 y.extend(y_pp)
962 y.extend(y_pp)
935
963
936 elif self.line_type.name=='windows':
964 elif self.line_type.name=='windows':
937 params = json.loads(self.params)
965 params = json.loads(self.params)
938 if 'params' in params and len(params['params'])>0:
966 if 'params' in params and len(params['params'])>0:
939 tx = RCLine.objects.get(pk=params['TX_ref'])
967 tx = RCLine.objects.get(pk=params['TX_ref'])
940 tx_params = json.loads(tx.params)
968 tx_params = json.loads(tx.params)
941 ranges = tx_params['range'].split(',')
969 ranges = tx_params['range'].split(',')
942 for p in params['params']:
970 for p in params['params']:
943 y_win = self.points(ntx, ipp_u,
971 y_win = self.points(ntx, ipp_u,
944 p['resolution']*p['number_of_samples']*km2unit,
972 p['resolution']*p['number_of_samples']*km2unit,
945 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
973 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
946 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
974 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
947
975
948
976
949 if len(ranges)>0 and ranges[0]!='0':
977 if len(ranges)>0 and ranges[0]!='0':
950 y_win = self.mask_ranges(y_win, ranges)
978 y_win = self.mask_ranges(y_win, ranges)
951
979
952 y.extend(y_win)
980 y.extend(y_win)
953
981
954 elif self.line_type.name=='mix':
982 elif self.line_type.name=='mix':
955 values = self.rc_configuration.parameters.split('-')
983 values = self.rc_configuration.parameters.split('-')
956 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
984 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
957 modes = [value.split('|')[1] for value in values]
985 modes = [value.split('|')[1] for value in values]
958 ops = [value.split('|')[2] for value in values]
986 ops = [value.split('|')[2] for value in values]
959 delays = [value.split('|')[3] for value in values]
987 delays = [value.split('|')[3] for value in values]
960 masks = [value.split('|')[4] for value in values]
988 masks = [value.split('|')[4] for value in values]
961 print("masks")
989 print("masks")
962 print(masks)
990 print(masks)
963 print('{:8b}'.format(int(masks[0])))
991 print('{:8b}'.format(int(masks[0])))
964 mask = list('{:8b}'.format(int(masks[0])))
992 mask = list('{:8b}'.format(int(masks[0])))
965 print("mask")
993 print("mask")
966 print(mask)
994 print(mask)
967 mask.reverse()
995 mask.reverse()
968 print("mask reverse")
996 print("mask reverse")
969 print(mask)
997 print(mask)
970 if mask[self.channel] in ('0', '', ' '):
998 if mask[self.channel] in ('0', '', ' '):
971 y = np.zeros(confs[0].total_units, dtype=np.int8)
999 y = np.zeros(confs[0].total_units, dtype=np.int8)
972 else:
1000 else:
973 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
1001 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
974
1002
975 for i in range(1, len(values)):
1003 for i in range(1, len(values)):
976 mask = list('{:8b}'.format(int(masks[i])))
1004 mask = list('{:8b}'.format(int(masks[i])))
977 mask.reverse()
1005 mask.reverse()
978
1006
979 if mask[self.channel] in ('0', '', ' '):
1007 if mask[self.channel] in ('0', '', ' '):
980 continue
1008 continue
981 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
1009 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
982 delay = float(delays[i])*km2unit
1010 delay = float(delays[i])*km2unit
983
1011
984 if modes[i]=='P':
1012 if modes[i]=='P':
985 if delay>0:
1013 if delay>0:
986 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
1014 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
987 y_temp = np.empty_like(Y)
1015 y_temp = np.empty_like(Y)
988 y_temp[:delay] = 0
1016 y_temp[:delay] = 0
989 y_temp[delay:] = Y[:-delay]
1017 y_temp[delay:] = Y[:-delay]
990 elif delay+len(Y)>len(y):
1018 elif delay+len(Y)>len(y):
991 y_new = np.zeros(delay+len(Y), dtype=np.int8)
1019 y_new = np.zeros(delay+len(Y), dtype=np.int8)
992 y_new[:len(y)] = y
1020 y_new[:len(y)] = y
993 y = y_new
1021 y = y_new
994 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
1022 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
995 y_temp[-len(Y):] = Y
1023 y_temp[-len(Y):] = Y
996 elif delay+len(Y)==len(y):
1024 elif delay+len(Y)==len(y):
997 y_temp = np.zeros(delay+len(Y))
1025 y_temp = np.zeros(delay+len(Y))
998 y_temp[-len(Y):] = Y
1026 y_temp[-len(Y):] = Y
999 elif delay+len(Y)<len(y):
1027 elif delay+len(Y)<len(y):
1000 y_temp = np.zeros(len(y), dtype=np.int8)
1028 y_temp = np.zeros(len(y), dtype=np.int8)
1001 y_temp[delay:delay+len(Y)] = Y
1029 y_temp[delay:delay+len(Y)] = Y
1002 else:
1030 else:
1003 y_temp = Y.copy()
1031 y_temp = Y.copy()
1004
1032
1005 if ops[i]=='OR':
1033 if ops[i]=='OR':
1006 y = y | y_temp
1034 y = y | y_temp
1007 elif ops[i]=='XOR':
1035 elif ops[i]=='XOR':
1008 y = y ^ y_temp
1036 y = y ^ y_temp
1009 elif ops[i]=='AND':
1037 elif ops[i]=='AND':
1010 y = y & y_temp
1038 y = y & y_temp
1011 elif ops[i]=='NAND':
1039 elif ops[i]=='NAND':
1012 y = y & ~y_temp
1040 y = y & ~y_temp
1013 else:
1041 else:
1014 y = np.concatenate([y, Y])
1042 y = np.concatenate([y, Y])
1015
1043
1016 total = len(y)
1044 total = len(y)
1017 y = self.array_to_points(y)
1045 y = self.array_to_points(y)
1018
1046
1019 else:
1047 else:
1020 y = []
1048 y = []
1021
1049
1022 if self.rc_configuration.total_units != total:
1050 if self.rc_configuration.total_units != total:
1023 self.rc_configuration.total_units = total
1051 self.rc_configuration.total_units = total
1024 self.rc_configuration.save()
1052 self.rc_configuration.save()
1025
1053
1026 self.pulses = str(y)
1054 self.pulses = str(y)
1027 self.save()
1055 self.save()
1028
1056
1029 @staticmethod
1057 @staticmethod
1030 def array_to_points(X):
1058 def array_to_points(X):
1031
1059
1032 if X.size==0:
1060 if X.size==0:
1033 return []
1061 return []
1034
1062
1035 d = X[1:]-X[:-1]
1063 d = X[1:]-X[:-1]
1036
1064
1037 up = np.where(d==1)[0]
1065 up = np.where(d==1)[0]
1038 if X[0]==1:
1066 if X[0]==1:
1039 up = np.concatenate((np.array([-1]), up))
1067 up = np.concatenate((np.array([-1]), up))
1040 up += 1
1068 up += 1
1041
1069
1042 dw = np.where(d==-1)[0]
1070 dw = np.where(d==-1)[0]
1043 if X[-1]==1:
1071 if X[-1]==1:
1044 dw = np.concatenate((dw, np.array([len(X)-1])))
1072 dw = np.concatenate((dw, np.array([len(X)-1])))
1045 dw += 1
1073 dw += 1
1046
1074
1047 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1075 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1048
1076
1049 @staticmethod
1077 @staticmethod
1050 def mask_ranges(Y, ranges):
1078 def mask_ranges(Y, ranges):
1051
1079
1052 y = [(0, 0) for __ in Y]
1080 y = [(0, 0) for __ in Y]
1053
1081
1054 for index in ranges:
1082 for index in ranges:
1055 if '-' in index:
1083 if '-' in index:
1056 args = [int(a) for a in index.split('-')]
1084 args = [int(a) for a in index.split('-')]
1057 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1085 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1058 else:
1086 else:
1059 y[int(index)-1] = Y[int(index)-1]
1087 y[int(index)-1] = Y[int(index)-1]
1060
1088
1061 return y
1089 return y
1062
1090
1063 @staticmethod
1091 @staticmethod
1064 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1092 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1065
1093
1066 delays = len(delay)
1094 delays = len(delay)
1067
1095
1068 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1096 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1069
1097
1070 return Y
1098 return Y
1071
1099
1072 class RCClock(models.Model):
1100 class RCClock(models.Model):
1073
1101
1074 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1102 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1075 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1103 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1076 multiplier = models.PositiveIntegerField(default=60)
1104 multiplier = models.PositiveIntegerField(default=60)
1077 divisor = models.PositiveIntegerField(default=10)
1105 divisor = models.PositiveIntegerField(default=10)
1078 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1106 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1079 frequency = models.FloatField(default=60.0)
1107 frequency = models.FloatField(default=60.0)
General Comments 0
You need to be logged in to leave comments. Login now