Pacific-Design.com

    
Home Index

1. Caltech

2. Comedi Slave

Caltech / Comedi Slave /

/*-----------------------------------------------------------------------------
     California Institute of Technology
     The Andersen Lab, Division of Biology

      Slave: Child process that is forked from broker. This process will 
             read stdin in this case pipe from broker and calculate status 
             and time and write it into share memory circula buffer.  

      Inter-process communications: 
        - Semaphores 
        - Share Memory 
        - Circular Buffer    
               -----------------------------------------
    Begin          : Thu July 31, 2001
    Written        : by Kevin Duraj
    Email          : kevin@vis.caltech.edu
    Collaborator   : Bijan Pesaran

-----------------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/*---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
/*---------------------------------------------------------------------------*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "mysem.h"
#include "myshare.h"
/*---------------------------------------------------------------------------*/
void initialize_share_mem(shared_use_st *a);
void disp_array(shared_use_st *a);
/*---------------------------------------------------------------------------*/
int median(int *circ);
void state_write(int trial, int stat, int time, shared_use_st *a);
int convert_state(int analog_state);
void bubbleSort(int a[], int n);
void open_recording(shared_use_st *a);
void terminate(void);
/*------------------------ Global Variables ---------------------------------*/
int fp;
int fifo_fd;
struct shared_use_st *share;
/*---------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
  /*------ Semaphore Init. Var ---------*/
  int i, j, y, fp1;
  int pause_time;

  /*------ Share Memory Init. Var ------*/
  int data;
  void *shared_memory = (void *) 0;

  /*------- Circular Buffer ------------*/
  unsigned short int *buf;
  int k, m, n, val;

  /*--------- Preprocess Vars. ---------*/
  int state_buffer[HIST];
  int analog_state, digital_state;
  int old_state=0, trial=0, time=0;
  long int data_len = HIST*CH*SS;

  /*--------- File Vars. ---------*/
  char cmd[32];

  /*------- Get Pipe File Name from parent -------------*/
  sscanf(argv[1], "%d", &fifo_fd);

  /*------- Signal alarm -------------*/
  (void) signal(SIGALRM, terminate);


  /*======================= Get semaphore ======================*/
  sem_id = semget((key_t)SHARE_SEM, 1, 0666 | IPC_CREAT);
  if(!set_semaphore()) { printf("Cannot set semaphore!\n"); exit(EXIT_FAILURE); }
  
  /*====================== Get share memory ====================*/
  shm_id = shmget((key_t)SHARE_KEY, sizeof(struct shared_use_st), 0666 | IPC_CREAT);

  /* Check share memory */
  if(shm_id == -1) { fprintf(stderr, "shmget function failed\n"); exit(EXIT_FAILURE); }

  /* Make shared memory accessible by program */
  shared_memory = (struct shared_use_st*)shmat(shm_id,(void *)0, 0);
  if(shared_memory == (void *)-1) { fprintf(stderr, "shmat function failed\n"); }

  /* Make pointer to the share memory */
  share = (struct shared_use_st *)shared_memory;

  /*============== Circular Buffer Init ========================*/
  initialize_share_mem(share);
 
  /*  Allocate memory to load data from pipe */
  buf=malloc(data_len);

  while((k=read(fifo_fd, buf, data_len)) != 0)
  {
        
    /*========================== Critical Section =======================*/
    if(!sem_wait()) { printf("Wait for semaphore Line: %d\n", __LINE__); exit(EXIT_FAILURE); }

    if (share->check!=0) printf("Buffer overrun\n");

    switch(share->file_state)
    {
      case 1: open_recording(share);  share->file_state=2; break;       
      case 2: write(fp, buf, k); break;
      case 3: close(fp); share->file_state = 0; fprintf(stderr,"Closing file\n"); 
                    sprintf(cmd,"chmod 666 %s", share->file_name); 
                    system(cmd); 
            break;
    }
        
    i = 0;  share->time++; time++;

    /* --------------------- Loop over input channels ------------------------------ */
    for (n = 0; n < k/SS; n+=CH)  
    {
      /*---------------------------- Trial State Time ------------------------------- */
      state_buffer[i] = buf[n+STATE_CHANNEL];              /* put state into buffer */
      
      /*------------------ Write eye position first cycle only ---------------------- */
      if(i==0)
      {
            share->eye[0][share->eye_pos] =  buf[n+EYE_CHANNEL_HOR];
            share->eye[1][share->eye_pos] =  buf[n+EYE_CHANNEL_VER];
            share->eye_pos++;
            if(share->eye_pos == EYE_INNER) { share->eye_pos = 0; }
      }
      i++;
      
      /*------------------ Write raw data each cycle -------------------------------- */
      for(y=0; y<RAW_OUTER; y++)
      {
              share->raw[y][share->raw_pos] = buf[n+RAW_CHANNEL_START+y];
      }
      share->raw_pos++;
      if(share->raw_pos == RAW_INNER) { share->raw_pos = 0; }
    }
    /* ============================================================================== */

    analog_state = median(state_buffer);
    digital_state = convert_state(analog_state);
    /* printf("Digital state: %d\n", digital_state); */

    switch(digital_state)
    { /*------------------ transition ----------------------*/
      case 0:  if (old_state != 0)  { state_write(trial,digital_state,time,share); } old_state = 0;  break;
      case 1:  if (old_state != 1)  { state_write(trial,digital_state,time,share); } old_state = 1;  break;
      case 2:  if (old_state != 2)  { state_write(trial,digital_state,time,share); } old_state = 2;  break;
      case 3:  if (old_state != 3)  { state_write(trial,digital_state,time,share); } old_state = 3;  break;
      case 4:  if (old_state != 4)  { state_write(trial,digital_state,time,share); } old_state = 4;  break;
      case 5:  if (old_state != 5)  { state_write(trial,digital_state,time,share); } old_state = 5;  break;
      case 6:  if (old_state != 6)  { state_write(trial,digital_state,time,share); } old_state = 6;  break;
      case 7:  if (old_state != 7)  { state_write(trial,digital_state,time,share); } old_state = 7;  break;
      case 8:  if (old_state != 8)  { state_write(trial,digital_state,time,share); } old_state = 8;  break;
      case 9:  if (old_state != 9)  { state_write(trial,digital_state,time,share); } old_state = 9;  break;
      case 10: if (old_state != 10) { state_write(trial,digital_state,time,share); } old_state = 10; break;
      case 11 ... 19 :
        if (digital_state != old_state)
        {
          trial ++;
          state_write(trial,digital_state,time,share);
        }
      old_state = digital_state;
      break;
    } /*--- end of switch stmt ---*/

  if(!sem_free()) { fprintf(stderr,"Free semaphore Line: %d\n", __LINE__); exit(EXIT_FAILURE); }
  /*===================== End of Critical Section ======================*/

  }  /* ======================== END OF WHILE LOOP ==============================*/

  return EXIT_SUCCESS;
}
//*------------------------------------------------------------*/
/* Record State Values into Circular Buffer */
void state_write(int trial, int stat, int time, shared_use_st *a)
{
  fprintf(stderr,"Trial: %d\tState: %d\tTime: %d\t\n", trial, stat, time);

  a->state[0][a->state_pos] = trial;
  a->state[1][a->state_pos] = stat;
  a->state[2][a->state_pos] = time;
  a->state_pos++;
  if(a->state_pos == STATE_INNER) { a->state_pos=0; }
}
/*------------------------------------------------------------*/
/* converts analog state to digital state */
int convert_state(int analog_state)
{
  float del, offset, m;
  int out = 0;
  float Range = 4096;
  float Cardinality = 64;

  del = Range/Cardinality;
  offset = del/2;

  out = (analog_state-offset)/del;
  return out;
}
/*------------------------------------------------------------*/
/* returns median of state buffer */
int median(int *circ)
{
  int out;

  bubbleSort(circ, HIST);
  out = circ[HIST/2];
  return out;
}
/*------------------------------------------------------------*/
/* It sorts in non-decreasing order the first N positions of A. */
/* It uses the bubble sort method. */
void bubbleSort(int a[], int n)
{
  int lcv;
  int limit = n-1;
  int temp;
  int lastChange;

  while (limit)
  {
    lastChange = 0;
    for (lcv=0;lcv<limit;lcv++)
      /* Notice that the values in positions LIMIT+1 .. N are in
       * their final position, i.e. they are sorted right */
        if (a[lcv]>a[lcv+1]) {
          temp = a[lcv];
          a[lcv] = a[lcv+1];
          a[lcv+1] = temp;
          lastChange = lcv;
        }
    limit = lastChange;
  }
}
/*---------------------------------------------------------------------------*/
void initialize_share_mem(shared_use_st *a)
{
  int i, j;

  a->state_pos = a->eye_pos = a->raw_pos = a->time = a->file_state = a->check = 0;
  for(i=0; i < STATE_OUTER; i++) { for(j=0; j < STATE_INNER; j++) { a->state[i][j] = 0; } }
  for(i=0; i < EYE_OUTER; i++)   { for(j=0; j < EYE_INNER; j++)   { a->eye[i][j]   = 0; } }
  for(i=0; i < RAW_OUTER; i++)   { for(j=0; j < RAW_INNER; j++)   { a->raw[i][j]   = 0; } }

}
/*---------------------------------------------------------------------------*/
void disp_array(shared_use_st *a)
{
  int i, j;
  printf("Circ Buffer Pointer at Position: %d\n", a->state_pos);

  for(i=0; i < STATE_OUTER; i++)
  {
    printf("Array %d: ", i);
    for(j=0; j < STATE_INNER; j++) { printf("%d ", a->state[i][j]); }
    printf("\n");
  }
}
/*---------------------------------------------------------------------------*/
void open_recording(shared_use_st *a)
{
  printf("Start Recording\n", getpid());
  
  if ((fp = open(a->file_name, O_WRONLY | O_CREAT )) == -1)
    fprintf(stderr,"Error opening output file: %s.\n",a->file_name);
}
/*---------------------------------------------------------------------------*/
void terminate(void)
{
  printf("Child received ALARM Signal\n");
  if(fp) {close(fp);   printf("Child closed file\n");}
  close(fifo_fd);
  printf("Child closed pipe\n");
  if (shmdt(share) == -1) 
  { 
    fprintf(stderr, "shmdt function failed\n"); exit(EXIT_FAILURE); 
  }
  printf("Child detached shared memory\n");
  /* if (shmctl(share,IPC_RMID,0) == -1) 
  { 
    fprintf(stderr, "shmctl function failed\n"); exit(EXIT_FAILURE); 
  }
  printf("Child deleted shared memory\n"); */

  kill(getpid(), SIGKILL);
}
/*---------------------------------------------------------------------------*/