|
|
Jump to this file's LXR Page |
|
|
File: [CENS] / emstar / devel / loc / ar / ar_send.c
(download)
/
(as text)
Revision: 1.39, Mon Jul 3 02:48:07 2006 UTC (3 years, 4 months ago) by girod Branch: MAIN CVS Tags: pregeonet, PRE_TOSNIC_FIX, PRE_64BIT, HEAD, CYCLOPS_RELEASE_CANDIDATE_2_0, CYCLOPS_PRERELEASE_STABLE, CENTROUTE_EMSTAR_SOCKETS, AMARSS_JR_DEPLOYMENT_6_05_07 Changes since 1.38: +9 -1 lines several changes for CO trip. * extended range for ranging processing (still not tested) * added support for new arry geom and made it configurable (cmd line/run time) * added support to set sample rate before starting ranging |
/*
*
* Copyright (c) 2005 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <ar.h>
/*
* ar_send
*
* send an acoustic pulse
*/
static
int ar_start_computation(void *data, int interval, g_event_t *ev)
{
ar_state_t *ar = (ar_state_t *)data;
g_event_destroy(ev);
/* trigger the compute thread */
pthread_cond_broadcast(&(ar->chirp_list_cond));
return TIMER_DONE;
}
static
int ar_amp_off(void *data, int interval, g_event_t *ev)
{
#ifndef SIM_ONLY
ar_state_t *ar = (ar_state_t *)data;
ar_amplifier_enable(ar, 0);
#endif
return TIMER_DONE;
}
static
int ar_amp_on(void *data, int interval, g_event_t *ev)
{
#ifndef SIM_ONLY
ar_state_t *ar = (ar_state_t *)data;
ar_amplifier_enable(ar, 1);
#endif
return TIMER_DONE;
}
static
int ar_send_go(void *data, int interval, g_event_t *ev)
{
ar_state_t *ar = (ar_state_t *)data;
int nocomp = ar->next_nocomp;
char *notation = ar->next_note;
ar->next_note = NULL;
int seed = ar->next_seed;
int modulation = ar->next_mod;
/* emit */
ar_emit_current_chirp(ar, 0);
/* turn off amplifier */
g_timer_add(1000, ar_amp_off, ar, NULL, NULL);
/* notify */
range_notify_pkt_t notify = {
chirp_time: {
timebase: {
node: my_node_id,
comp: CPU
},
stamp: ar->last_chirp_time
},
chirp_time_end: {
timebase: {
node: my_node_id,
comp: CPU
},
stamp: ar->last_chirp_time
},
seqno: ar->chirp_seqno,
modulation: modulation,
skip_computation: nocomp,
seed: seed,
chirp_index: ar->send_index
};
ar->send_index++;
if (notation) {
strcpy(notify.notation, notation);
free(notation);
}
ar_record_chirp(ar, my_node_id, ¬ify, 0);
return TIMER_DONE;
}
void ar_reset_chirp(ar_state_t *ar)
{
int chirp_len = CHIRP_CHIPS*MOD_FACTOR;
if (ar->next_chirp) free(ar->next_chirp);
ar->next_chirp = g_new0(int16_t,chirp_len);
ar_pn_generate_chirp(ar->next_chirp, chirp_len, ar->next_seed, ar->next_mod, 1.0);
}
int ar_send_schedule_chirp(ar_state_t *ar, struct timeval *tv, int seed, int delay, int count)
{
if (ar->chirp_refractory) {
/* these things would need to be more sophisticated if we were having more
* than one "master"... multiple scheduled chirps, etc. */
elog(LOG_CRIT, "Not doing triggered chirp because refractory was set!");
goto fail;
}
/* make sure that the codec is running at 48KHz */
printf_to_file(DEV_VXP_STATUS, "rate=48000");
/* configure the chirp */
ar->next_seed = seed;
ar->next_mod = 0;
ar->next_nocomp = 0;
if (ar->next_note) free(ar->next_note);
char buf[20];
sprintf(buf, "%d", my_node_id);
ar->next_note = strdup(buf);
ar_reset_chirp(ar);
struct timeval now;
gettimeofday(&now, NULL);
int msec = misc_tv_offset_neg_msec(tv, &now);
int holdoff = msec + 6000 + count * 1500;
msec += 3000 + delay * 1500;
if (msec < 0) {
elog(LOG_CRIT, "Not doing triggered chirp because msg arrived late");
goto fail;
}
g_event_destroy(ar->amp_at_time);
g_event_destroy(ar->chirp_delay);
g_timer_add(msec, ar_amp_on, ar, NULL, &(ar->amp_at_time));
g_timer_add(msec+1000, ar_send_go, ar, NULL, &(ar->chirp_delay));
g_timer_add(msec+6000, NULL, NULL, NULL, &(ar->chirp_refractory));
g_timer_add(holdoff, ar_start_computation, ar, NULL, &(ar->computation_holdoff));
return 0;
fail:
return -1;
}
int ar_send_trigger(ar_state_t *ar, int seed, int modulation, char *notation, int nocomp)
{
if (ar->chirp_refractory) {
elog(LOG_WARNING, "Chirp requested too soon after last chirp");
return -1;
}
#ifndef SIM_ONLY
/* turn on amplifier via GPIO */
ar_amplifier_enable(ar, 1);
#endif
/* set timer to start chirping */
g_timer_add(1000, ar_send_go, ar, NULL, &ar->chirp_delay);
/* set refractory for five seconds */
g_timer_add(5000, NULL, NULL, NULL, &ar->chirp_refractory);
/* save args */
ar->next_seed = seed;
ar->next_mod = modulation;
ar->next_nocomp = nocomp;
ar->next_note = notation ? strdup(notation) : NULL;
ar_reset_chirp(ar);
return 0;
}
/*
* outputs current orientation seqno
*/
static
int ar_seqno_printable(status_context_t *ctx, buf_t *buf)
{
ar_state_t *ar = (ar_state_t *)sd_data(ctx);
bufprintf(buf, "%d\n", ar->chirp_seqno);
return STATUS_MSG_COMPLETE;
}
static
int ar_index_printable(status_context_t *ctx, buf_t *buf)
{
ar_state_t *ar = (ar_state_t *)sd_data(ctx);
bufprintf(buf, "%04d\n", ar->send_index%10000);
return STATUS_MSG_COMPLETE;
}
/*
* chirp request interface
*/
static
int ar_send_usage(status_context_t *ctx, buf_t *buf)
{
ar_state_t *ar = (ar_state_t *)sd_data(ctx);
bufprintf(buf,
"chirp trigger device\n"
"Usage: \n"
" chirp[=notation]: cause a chirp now\n"
" mod=<modulation-number>: using this modulation\n"
" nocomp: withhold computation (when only collecting data)\n"
" inval: invalidate all range info after moving node\n"
" temp=<degrees-C>: set the current air temperature\n"
" The current temperature is %f degrees C\n"
" rh=<0-100>: set the current relative humdity\n"
" The current RH is %f\n"
" dump=<dump-format-str>: start saving debugging info to this file.\n"
" The format string must have %%s for datafile-type and %%d for index\n"
" Currently the format string is set to '%s'\n"
" nodump: disable saving debug info\n"
" array=<8cm,orig>: re-set the array type\n"
"\n"
"Examples: \n"
" echo chirp > %s\n"
" echo mod=2:chirp=20m-test > %s\n"
" echo inval > %s\n"
" echo dump=format-string > %s\n"
" echo temp=<temperature in C> > %s\n"
" echo rh=<RH (0-100)> > %s\n"
"\n"
"If a notation is supplied, the receiver will attempt to save\n"
"the raw data under that name. \n"
"\n"
"Set via command-line options:\n"
" Control string for raw files: %s\n"
" Control string for details log: %s\n"
"\n"
,
ar->curr_temperature,
ar->curr_RH,
ar->dump_files_ctrl_string,
AR_CHIRP_DEVICE,
AR_CHIRP_DEVICE,
AR_CHIRP_DEVICE,
AR_CHIRP_DEVICE,
AR_CHIRP_DEVICE,
AR_CHIRP_DEVICE,
ar->ar_log_raw,
ar->ar_log_file
);
return STATUS_MSG_COMPLETE;
}
void ar_send_invalidate(ar_state_t *ar)
{
ar->chirp_seqno++;
g_status_dev_notify(ar->seqno_status);
chirp_result_t *result = g_new0(chirp_result_t, 1);
result->entry.source = my_node_id;
result->entry.seqno = ar->chirp_seqno;
ar_update_published(ar, result);
}
static
int ar_send_cmd(status_context_t *ctx, char *command, size_t buf_size)
{
ar_state_t *ar = (ar_state_t *)sd_data(ctx);
int modulation = 0;
char *notation = NULL;
int nocomp = 0;
int chirp = 0;
int retval = buf_size;
int seed = (random() % 999) + 1;
parser_state_t *ps = misc_parse_init(command, MISC_PARSE_COLON_SCHEME);
while (misc_parse_next_kvp(ps) >= 0) {
if (strcmp(ps->key, "inval") == 0) {
ar_send_invalidate(ar);
}
else if (strcmp(ps->key, "array") == 0) {
ar_update_array_spec(ar, ps->value);
}
else if (strcmp(ps->key, "mod") == 0) {
if (ps->value && isdigit(ps->value[0]))
modulation = atoi(ps->value);
else
retval = EVENT_ERROR(EINVAL);
}
else if (strcmp(ps->key, "nocomp") == 0) {
nocomp=1;
}
else if (strcmp(ps->key, "chirp") == 0) {
if (ps->value) notation = strdup(ps->value);
chirp = 1;
}
else if (strcmp(ps->key, "seed") == 0) {
if (ps->value && isdigit(ps->value[0]))
seed = atoi(ps->value);
}
else if (strcmp(ps->key, "dump") == 0) {
ar->dump_files_ctrl_string = strdup(ps->value);
if (strlen(ar->dump_files_ctrl_string) < 1) {
ar->dump_files_ctrl_string = NULL;
retval = EVENT_ERROR(EINVAL);
}
ar->dump_files_ctrl_string[strlen(ar->dump_files_ctrl_string)-1] = 0;
}
else if (strcmp(ps->key, "nodump") == 0) {
if (ar->dump_files_ctrl_string)
free(ar->dump_files_ctrl_string);
ar->dump_files_ctrl_string = NULL;
}
else if (strcmp(ps->key, "temp") == 0) {
if (ps->value && isdigit(ps->value[0])) {
if (1 != sscanf(ps->value, "%f", &(ar->curr_temperature)))
retval = EVENT_ERROR(EINVAL);
}
else
retval = EVENT_ERROR(EINVAL);
}
else if (strcmp(ps->key, "rh") == 0) {
if (ps->value && isdigit(ps->value[0])) {
if (1 != sscanf(ps->value, "%f", &(ar->curr_RH)))
retval = EVENT_ERROR(EINVAL);
}
else
retval = EVENT_ERROR(EINVAL);
}
else
retval = EVENT_ERROR(ENOSYS);
}
if (chirp) {
int status = ar_send_trigger(ar, seed, modulation, notation, nocomp);
if (status < 0)
retval = EVENT_ERROR(EALREADY);
}
//done:
misc_parse_cleanup(ps);
if (notation) free(notation);
return retval;
}
int ar_send_init(ar_state_t *ar)
{
#ifndef SIM_ONLY
/* disable amplifier */
ar_amplifier_enable(ar, 0);
#endif /*SIM_ONLY*/
status_dev_opts_t opts = {
device: {
devname: AR_CHIRP_DEVICE,
device_info: ar
},
printable: ar_send_usage,
write: ar_send_cmd
};
if (g_status_dev(&opts, &(ar->chirp_cmd)) < 0) {
elog(LOG_CRIT, "Failed to create trigger device: %m");
exit(1);
}
status_dev_opts_t opts2 = {
device: {
devname: AR_SEQNO_DEVICE,
device_info: ar
},
printable: ar_seqno_printable
};
if (g_status_dev(&opts2, &(ar->seqno_status)) < 0) {
elog(LOG_CRIT, "Failed to create seqno device: %m");
}
status_dev_opts_t opts3 = {
device: {
devname: AR_INDEX_DEVICE,
device_info: ar
},
printable: ar_index_printable
};
if (g_status_dev(&opts3, &(ar->index_status)) < 0) {
elog(LOG_CRIT, "Failed to create index device: %m");
}
ar->chirp_seqno = random();
ar_send_cmd(ar->chirp_cmd, "inval", 5);
return 0;
}
| CENS CVS Mailing List |
Powered by ViewCVS 0.9.2 |