~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/devel/loc/ar/ar_send.c


  1 /*
  2  *
  3  * Copyright (c) 2005 The Regents of the University of California.  All 
  4  * rights reserved.
  5  *
  6  * Redistribution and use in source and binary forms, with or without
  7  * modification, are permitted provided that the following conditions
  8  * are met:
  9  *
 10  * - Redistributions of source code must retain the above copyright
 11  *   notice, this list of conditions and the following disclaimer.
 12  *
 13  * - Neither the name of the University nor the names of its
 14  *   contributors may be used to endorse or promote products derived
 15  *   from this software without specific prior written permission.
 16  *
 17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 20  * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  *
 29  */
 30 
 31 #include <ar.h>
 32 
 33 /*
 34  * ar_send
 35  *
 36  * send an acoustic pulse
 37  */
 38 
 39 
 40 static 
 41 int ar_start_computation(void *data, int interval, g_event_t *ev)
 42 {
 43   ar_state_t *ar = (ar_state_t *)data;
 44   g_event_destroy(ev);
 45 
 46   /* trigger the compute thread */
 47   pthread_cond_broadcast(&(ar->chirp_list_cond));
 48 
 49   return TIMER_DONE;
 50 }
 51 
 52 
 53 static 
 54 int ar_amp_off(void *data, int interval, g_event_t *ev)
 55 {
 56 #ifndef SIM_ONLY
 57   ar_state_t *ar = (ar_state_t *)data;
 58   ar_amplifier_enable(ar, 0);
 59 #endif
 60   return TIMER_DONE;
 61 }
 62 
 63 
 64 static 
 65 int ar_amp_on(void *data, int interval, g_event_t *ev)
 66 {
 67 #ifndef SIM_ONLY
 68   ar_state_t *ar = (ar_state_t *)data;
 69   ar_amplifier_enable(ar, 1);
 70 #endif
 71   return TIMER_DONE;
 72 }
 73 
 74 
 75 static
 76 int ar_send_go(void *data, int interval, g_event_t *ev)
 77 {
 78   ar_state_t *ar = (ar_state_t *)data;
 79   int nocomp = ar->next_nocomp;
 80   char *notation = ar->next_note;
 81   ar->next_note = NULL;
 82   int seed = ar->next_seed;
 83   int modulation = ar->next_mod;
 84 
 85   /* emit */
 86   ar_emit_current_chirp(ar, 0);
 87   
 88   /* turn off amplifier */
 89   g_timer_add(1000, ar_amp_off, ar, NULL, NULL);
 90 
 91   /* notify */
 92   range_notify_pkt_t notify = {
 93     chirp_time: {
 94       timebase: {
 95         node: my_node_id,
 96         comp: CPU
 97       },
 98       stamp: ar->last_chirp_time
 99     },
100     chirp_time_end: {
101       timebase: {
102         node: my_node_id,
103         comp: CPU
104       },
105       stamp: ar->last_chirp_time
106     },
107     seqno: ar->chirp_seqno,
108     modulation: modulation,
109     skip_computation: nocomp,
110     seed: seed,
111     chirp_index: ar->send_index
112   };
113   ar->send_index++;
114   if (notation) {
115     strcpy(notify.notation, notation);
116     free(notation);
117   }
118   ar_record_chirp(ar, my_node_id, &notify, 0);
119   
120   return TIMER_DONE;
121 }
122 
123 
124 void ar_reset_chirp(ar_state_t *ar)
125 {
126   int chirp_len = CHIRP_CHIPS*MOD_FACTOR;
127   if (ar->next_chirp) free(ar->next_chirp);
128   ar->next_chirp = g_new0(int16_t,chirp_len);
129   ar_pn_generate_chirp(ar->next_chirp, chirp_len, ar->next_seed, ar->next_mod, 1.0);
130 }
131   
132 
133 int ar_send_schedule_chirp(ar_state_t *ar, struct timeval *tv, int seed, int delay, int count)
134 {
135   if (ar->chirp_refractory) {
136     /* these things would need to be more sophisticated if we were having more
137      * than one "master"... multiple scheduled chirps, etc. */
138     elog(LOG_CRIT, "Not doing triggered chirp because refractory was set!");
139     goto fail;
140   }
141 
142   /* make sure that the codec is running at 48KHz */
143   printf_to_file(DEV_VXP_STATUS, "rate=48000");
144 
145   /* configure the chirp */
146   ar->next_seed = seed;
147   ar->next_mod = 0;
148   ar->next_nocomp = 0;
149   if (ar->next_note) free(ar->next_note);
150   char buf[20];
151   sprintf(buf, "%d", my_node_id);
152   ar->next_note = strdup(buf);
153   ar_reset_chirp(ar);
154 
155   struct timeval now;
156   gettimeofday(&now, NULL);
157   int msec = misc_tv_offset_neg_msec(tv, &now);
158   int holdoff = msec + 6000 + count * 1500;
159   
160   msec += 3000 + delay * 1500;
161   if (msec < 0) {
162     elog(LOG_CRIT, "Not doing triggered chirp because msg arrived late");
163     goto fail;
164   }
165   
166   g_event_destroy(ar->amp_at_time);
167   g_event_destroy(ar->chirp_delay);
168   g_timer_add(msec, ar_amp_on, ar, NULL, &(ar->amp_at_time));
169   g_timer_add(msec+1000, ar_send_go, ar, NULL, &(ar->chirp_delay));
170   g_timer_add(msec+6000, NULL, NULL, NULL, &(ar->chirp_refractory));
171   g_timer_add(holdoff, ar_start_computation, ar, NULL, &(ar->computation_holdoff));
172   return 0;
173 
174  fail:
175   return -1;
176 }
177 
178 
179 
180 int ar_send_trigger(ar_state_t *ar, int seed, int modulation, char *notation, int nocomp)
181 {
182   if (ar->chirp_refractory) {
183     elog(LOG_WARNING, "Chirp requested too soon after last chirp");
184     return -1;
185   }
186 
187 #ifndef SIM_ONLY
188   /* turn on amplifier via GPIO */
189   ar_amplifier_enable(ar, 1);
190 #endif
191 
192   /* set timer to start chirping */
193   g_timer_add(1000, ar_send_go, ar, NULL, &ar->chirp_delay);
194 
195   /* set refractory for five seconds */
196   g_timer_add(5000, NULL, NULL, NULL, &ar->chirp_refractory);
197 
198   /* save args */
199   ar->next_seed = seed;
200   ar->next_mod = modulation;
201   ar->next_nocomp = nocomp;
202   ar->next_note = notation ? strdup(notation) : NULL;
203   ar_reset_chirp(ar);
204 
205   return 0;
206 }
207 
208 
209 /*
210  *  outputs current orientation seqno
211  */
212 
213 static
214 int ar_seqno_printable(status_context_t *ctx, buf_t *buf)
215 {
216   ar_state_t *ar = (ar_state_t *)sd_data(ctx);
217   bufprintf(buf, "%d\n", ar->chirp_seqno);
218   return STATUS_MSG_COMPLETE;
219 }
220 
221 static
222 int ar_index_printable(status_context_t *ctx, buf_t *buf)
223 {
224   ar_state_t *ar = (ar_state_t *)sd_data(ctx);
225   bufprintf(buf, "%04d\n", ar->send_index%10000);
226   return STATUS_MSG_COMPLETE;
227 }
228 
229 /* 
230  * chirp request interface 
231  */
232 
233 static
234 int ar_send_usage(status_context_t *ctx, buf_t *buf)
235 {
236   ar_state_t *ar = (ar_state_t *)sd_data(ctx);
237 
238   bufprintf(buf, 
239             "chirp trigger device\n"
240             "Usage: \n"
241             "       chirp[=notation]: cause a chirp now\n"
242             "       mod=<modulation-number>: using this modulation\n"
243             "       nocomp: withhold computation (when only collecting data)\n"
244             "       inval:  invalidate all range info after moving node\n"
245             "       temp=<degrees-C>:  set the current air temperature\n"
246             "           The current temperature is %f degrees C\n"
247             "       rh=<0-100>:  set the current relative humdity\n"
248             "           The current RH is %f\n"
249             "       dump=<dump-format-str>: start saving debugging info to this file.\n"
250             "           The format string must have %%s for datafile-type and %%d for index\n"
251             "           Currently the format string is set to '%s'\n"
252             "       nodump:  disable saving debug info\n"
253             "       array=<8cm,orig>:  re-set the array type\n"
254             "\n"
255             "Examples: \n"
256             "       echo chirp > %s\n"
257             "       echo mod=2:chirp=20m-test > %s\n"
258             "       echo inval > %s\n"
259             "       echo dump=format-string > %s\n"
260             "       echo temp=<temperature in C> > %s\n"
261             "       echo rh=<RH (0-100)> > %s\n"
262             "\n"
263             "If a notation is supplied, the receiver will attempt to save\n"
264             "the raw data under that name.  \n"
265             "\n"
266             "Set via command-line options:\n"
267             "  Control string for raw files:   %s\n"
268             "  Control string for details log: %s\n"
269             "\n"
270 
271             ,
272             ar->curr_temperature,
273             ar->curr_RH,
274             ar->dump_files_ctrl_string,
275             AR_CHIRP_DEVICE,
276             AR_CHIRP_DEVICE,
277             AR_CHIRP_DEVICE,
278             AR_CHIRP_DEVICE,
279             AR_CHIRP_DEVICE,
280             AR_CHIRP_DEVICE,
281             ar->ar_log_raw,
282             ar->ar_log_file
283             );
284   return STATUS_MSG_COMPLETE;
285 }
286 
287 
288 void ar_send_invalidate(ar_state_t *ar)
289 {
290   ar->chirp_seqno++;
291   g_status_dev_notify(ar->seqno_status);
292   chirp_result_t *result = g_new0(chirp_result_t, 1);
293   result->entry.source = my_node_id;
294   result->entry.seqno = ar->chirp_seqno;
295   ar_update_published(ar, result);
296 }
297 
298 
299 static
300 int ar_send_cmd(status_context_t *ctx, char *command, size_t buf_size)
301 {
302   ar_state_t *ar = (ar_state_t *)sd_data(ctx);
303   int modulation = 0;
304   char *notation = NULL;
305   int nocomp = 0; 
306   int chirp = 0;
307   int retval = buf_size;
308   int seed = (random() % 999) + 1;
309 
310   parser_state_t *ps = misc_parse_init(command, MISC_PARSE_COLON_SCHEME);
311   while (misc_parse_next_kvp(ps) >= 0) {
312 
313     if (strcmp(ps->key, "inval") == 0) {
314       ar_send_invalidate(ar);
315     }
316 
317     else if (strcmp(ps->key, "array") == 0) {
318       ar_update_array_spec(ar, ps->value);
319     }
320     
321     else if (strcmp(ps->key, "mod") == 0) {    
322       if (ps->value && isdigit(ps->value[0])) 
323         modulation = atoi(ps->value);
324       else 
325         retval = EVENT_ERROR(EINVAL);
326     }
327 
328     else if (strcmp(ps->key, "nocomp") == 0) {    
329       nocomp=1;
330     }
331       
332     else if (strcmp(ps->key, "chirp") == 0) {
333       if (ps->value) notation = strdup(ps->value);
334       chirp = 1;
335     }
336 
337     else if (strcmp(ps->key, "seed") == 0) {
338       if (ps->value && isdigit(ps->value[0])) 
339         seed = atoi(ps->value);
340     }
341 
342     else if (strcmp(ps->key, "dump") == 0) {
343       ar->dump_files_ctrl_string = strdup(ps->value);
344       if (strlen(ar->dump_files_ctrl_string) < 1) {
345         ar->dump_files_ctrl_string = NULL;
346         retval = EVENT_ERROR(EINVAL);
347       }
348       ar->dump_files_ctrl_string[strlen(ar->dump_files_ctrl_string)-1] = 0;
349     }
350     
351     else if (strcmp(ps->key, "nodump") == 0) {
352       if (ar->dump_files_ctrl_string) 
353         free(ar->dump_files_ctrl_string);
354       ar->dump_files_ctrl_string = NULL;
355     }
356     
357     else if (strcmp(ps->key, "temp") == 0) {
358       if (ps->value && isdigit(ps->value[0])) {
359         if (1 != sscanf(ps->value, "%f", &(ar->curr_temperature)))
360           retval = EVENT_ERROR(EINVAL);
361       }
362       else
363         retval = EVENT_ERROR(EINVAL);
364     }
365     
366     else if (strcmp(ps->key, "rh") == 0) {
367       if (ps->value && isdigit(ps->value[0])) {
368         if (1 != sscanf(ps->value, "%f", &(ar->curr_RH)))
369           retval = EVENT_ERROR(EINVAL);
370       }
371       else
372         retval = EVENT_ERROR(EINVAL);
373     }
374     
375     else 
376       retval = EVENT_ERROR(ENOSYS);
377   }
378   
379   if (chirp) {
380     int status = ar_send_trigger(ar, seed, modulation, notation, nocomp);
381     if (status < 0)
382       retval = EVENT_ERROR(EALREADY);
383   }
384   
385   //done:
386   misc_parse_cleanup(ps);
387   if (notation) free(notation);
388   return retval;
389 }
390 
391 
392 int ar_send_init(ar_state_t *ar)
393 {
394 #ifndef SIM_ONLY
395   /* disable amplifier */
396   ar_amplifier_enable(ar, 0);
397 #endif /*SIM_ONLY*/
398 
399   status_dev_opts_t opts = {
400     device: {
401       devname: AR_CHIRP_DEVICE,
402       device_info: ar
403     },
404     printable: ar_send_usage,
405     write: ar_send_cmd
406   };
407 
408   if (g_status_dev(&opts, &(ar->chirp_cmd)) < 0) {
409     elog(LOG_CRIT, "Failed to create trigger device: %m");
410     exit(1);
411   }
412 
413   status_dev_opts_t opts2 = {
414     device: {
415       devname: AR_SEQNO_DEVICE,
416       device_info: ar
417     },
418     printable: ar_seqno_printable
419   };
420 
421   if (g_status_dev(&opts2, &(ar->seqno_status)) < 0) {
422     elog(LOG_CRIT, "Failed to create seqno device: %m");
423   }
424 
425   status_dev_opts_t opts3 = {
426     device: {
427       devname: AR_INDEX_DEVICE,
428       device_info: ar
429     },
430     printable: ar_index_printable
431   };
432 
433   if (g_status_dev(&opts3, &(ar->index_status)) < 0) {
434     elog(LOG_CRIT, "Failed to create index device: %m");
435   }
436 
437   ar->chirp_seqno = random();
438   ar_send_cmd(ar->chirp_cmd, "inval", 5);
439 
440   return 0;
441 }
442 
443 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.