(file) Return to ar_send.c CVS log (file) Jump to this file's LXR Page (dir) Up to [CENS] / emstar / devel / loc / ar

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, &notify, 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