Real-Time Signal Analysis & Real-Time Linux: Part 1 & 2
by Matt Sherer

Listing One

struct command {
   int signal_hz;
   int noise_hz;
   int sample_hz;
   } ;
static pthread_t signal_gen_t;
static pthread_t sampler_t;
static int sampled_fd;
static int signal_fd;
static int control_to_rtl_fd;
static int control_from_rtl_fd;

int init_module(void) {
   pthread_attr_t attr;
   struct rtl_sigaction sigact_r;
   struct rtl_sigaction sigact_w;

   mkfifo("/pure_signal",0777);
   signal_fd = open("/pure_signal", O_RDWR|O_NONBLOCK);
   ftruncate(signal_fd, sizeof(int)*10);

   mkfifo("/sampled_signal",0777);
   sampled_fd = open("/sampled_signal", O_RDWR|O_NONBLOCK);
   ftruncate(sampled_fd, sizeof(int)*10);

   mkfifo("/control_to_rtl", 0777);
   control_to_rtl_fd = open("/control_to_rtl", O_RDWR|O_NONBLOCK);
   ftruncate(control_to_rtl_fd, sizeof(struct command));
   sigact_r.sa_sigaction = control_to_rtl_handler;
   sigact_r.sa_fd = control_to_rtl_fd;
   sigact_r.sa_flags = RTL_SA_WRONLY|RTL_SA_SIGINFO;
   rtl_sigaction(RTL_SIGPOLL, &sigact_r, NULL);

   mkfifo("/control_from_rtl", 0777);
   control_from_rtl_fd = open("/control_from_rtl", O_RDWR|O_NONBLOCK);
   ftruncate(control_from_rtl_fd, sizeof(struct command));
   sigact_w.sa_sigaction = control_from_rtl_handler;
   sigact_w.sa_fd = control_from_rtl_fd;
   sigact_w.sa_flags = RTL_SA_RDONLY|RTL_SA_SIGINFO;
   rtl_sigaction(RTL_SIGPOLL, &sigact_w, NULL);

   pthread_attr_init(&attr);
   pthread_attr_setfp_np(&attr,1);
   pthread_create(&signal gen_t, &attr, signal_gen, 0);
   pthread_create(&sampler_t, &attr, sampler, 0);
   return 0;


Listing Two

void *signal_gen(void *arg) {
#define THREAD_PERIOD 5000000
#define SAMPLE_FRACTION 1000000000/THREAD_PERIOD
struct timespec next;
   float x1 = 0;
   float x2 = 1.5;
   float incr1;
   float incr2;
   float cur1;
   float cur2;
   int icur;
   clock_gettime(CLOCK_REALTIME, &next);
      while (1) {
         timespec_add_ns(&next, THREAD_PERIOD);
         clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
         incr1 = 2*PI / (SAMPLE_FRACTION / signal_hz);
         x1 += incr1;
         cur1 = (float)sin(x1);
         incr2 = 2*PI / (SAMPLE_FRACTION / noise_hz);
         x2 += incr2;
         cur2 = (float)sin(x2);
         cur signal = cur1 + (0.5*cur2);
         icur = (int)(cur_signal * 10000);
         icur = htonl(icur);
         write(signal_fd,&icur,sizeof(int));
      }
   return 0;
}


Listing Three

void control_from_rtl_handler(int_sig, rtl_siginfo_t *siginfo, void *v) {
      int_ret;
      struct command com;
      com.signal_hz = htonl(signal_hz);
      com.noise_hz = htonl(noise_hz);
      com.sample_hz = htonl(sample_hz);
      ret = write(siginfo ->rtl_si_fd, &com, sizeof(struct command));
}
static int count = 0;
static unsigned char readdata[sizeof(struct command)];
static char *ptr = readdata;
void control_to_rtl_handler(int_sig, rtl_siginfo_t *siginfo, void *v) {
      int ret;
      struct command com;
      ret = read(siginfo ->rtl_si_fd, ptr, sizeof(unsigned char));
      count += ret;
      ptr += ret;
         if (count >= sizeof(struct command)) {
            memcpy(&com, readdata, sizeof(struct command));
               signal_hz = ntohl(com.signal_hz);
               noise_hz = ntohl(com.noise_hz);
               sample_hz = ntohl(com.sample_hz);
               count = 0; ptr = readdata;
   }
}


Listing Four

void cleanup_module(void) {
   pthread_cancel(signal_gen_t);
   pthread_join(signal_gen_t, NULL);
   pthread_cancel(sampler_t);
   pthread_join(sampler_t, NULL);
   close(signal_fd);
   unlink("/pure_signal");
   close(sampled_fd);
   unlink("/sampled_signal");
   close(control_to_rtl_fd);
   unlink("/control_to_rtl");
   close(control_from_rtl_fd);
   unlink("/control_from_rtl");
}


Listing Five

class SignalCommand {
   private int signal_hz;
   private int noise_hz;
   private int sample_hz;
   private DataInputStream dis;
   private DataOutputStream dos;
   private String write_fifo, read_fifo;
   public SignalCommand(String write_fifo, String read_fifo) {
      this.write fifo = write_fifo;
      this.read fifo = read_fifo;
      try {
         dis = new DataInputStream(
               new FileInputStream(read_fifo));
        dos = new DataOutputStream(
              new FileOutputStream(write_fifo));
      } catch (Exception e) {
               System.out.println("Could not open FIFO: " + e);
      }
   }
   public void setSignalHz(int signal_hz) {
      this.signal_hz = signal_hz;
   }
   public void setNoiseHz(int noise_hz) {
      this.noise_hz = noise_hz;
   }
   public void setSampleHz(int sample_hz) {
      this.sample_hz = sample_hz;
   }
   public int getSignalHz() { return this.signal_hz; }
   public int getNoiseHz() { return this.noise_hz; }
   public int getSampleHz() { return this.sample_hz; }
   public void receiveCommand() {
      try {
        signal_hz = dis.readInt();
        noise_hz = dis.readInt();
        sample_hz = dis.readInt();
      } catch (Exception e) {
         System.out.println("Error reading commands: " + e);
      }
   }
   public void sendCommand() {
      Process proc;
      try {
         dos.writeInt(signal_hz);
         dos.writeInt(noise_hz); 50
         dos.writeInt(sample_hz);
      } catch (Exception e) {
         System.out.println("Error writing commands: " + e);
      }
   }
}


Listing Six

class Reader extends Thread
{
   DataInputStream dis;
   XYSeries series;
   JLabel lab;
   public Reader(String device, XYSeries series, JLabel lab) {
      this.series = series;
      this.lab = lab;
      try {
         dis = new DataInputStream(
               new FileInputStream(device));
      } catch (Exception e) {
         System.out.println("Failed open: " + e);
      }
   }
final static int area_len = 200;
public void run() { int i = 0;
   int count = 0;
   int newval = 0;
   int zerval = 0;
   for (i = 0; i < area_len; i++) {
      series.add(i,0);
   }
   while (true) {
      try {
         i = dis.readInt()/100;
      } catch (Exception e) {
         System.out.println("Failed: " + e);
      }
      try {
         count++;
         newval = count % area_len;
         zerval = newval - (int)(area len * .95);
         if (zerval < 0)
            zerval = area len + zerval;
         series.update(newval, new Integer(i));
         series.update(zerval, new Integer(0));
         lab.setText((new Date()).toString());
     } catch (Exception ee) {
     }
   }
 }
}


Listing Seven

#include <rtl.h>
#include <time.h>
#include <unistd.h>
#include <rtl_fifo.h>
#include <pthread.h>
#include <math.h>
#include <sys/mman.h>
#include <ck_module.h>
#include <FSMCL_core.h> 

RTLINUX_MODULE(A_D_CKIT);
static pthread_t signal_gen_t;
static pthread_t sampler_t;
static pthread_t filter_t;

static int sampled_fd;
static int signal_fd;
static float cur_signal;
static float cur_signal_filtered;
#define PI 3.14159

static CK_entity_control_group;
static CK_entity_signal_hz;
static CK_entity_noise_hz;
static CK_entity_sample_hz;
static CK_entity_filter_hz;
static FSMCL_Rolloff_entity_rolloff_filter; 

Listing Eight

void *filter(void *arg) { 
   int iperiod;
   int ifilter_hz;
   struct timespec next;
   float fsample;
   float period;
   clock_gettime(CLOCK REALTIME, &next);
   while (1) { 
      ifilter_hz = CK_scalar_get_int(&filter_hz); 
      iperiod = (int)(1000000000/ifilter_hz);
      timespec_add_ns(&next, iperiod);
      clock_nanosleep(CLOCK REALTIME, TIMER ABSTIME,&next, NULL);
      fsample = cur_signal;
      period = 1.0 / ifilter_hz;
      FSMCL Rolloff(&fsample, &period, &rolloff filter);
      cur_signal_filtered = fsample;
   }
   return 0;
}

Listing Nine
void *sampler(void *arg) { 
   struct timespec next;
   float sample;
   int isample;
   int iperiod, isample_hz;
   clock_gettime(CLOCK_REALTIME, &next);
   while (1) { 
      isample_hz = CK_scalar_get_int(&sample_hz);
      iperiod = (int)(1000000000/isample_hz); 
      timespec_add_ns(&next, iperiod);
      clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
      sample = cur_signal_filtered;
      isample = (int)(sample * 10000);
      isample = htonl(isample);
      write(sampled_fd,&isample,sizeof(int));
   }
   return 0;
}

Listing Ten

pthread_attr_t_attr;

mkfifo("/pure_signal",0777);
signal_fd = open("/pure_signal", O RDWR | O NONBLOCK);
ftruncate(signal_fd, sizeof(int)*10);

mkfifo("/sampled_signal",0777);
sampled_fd = open("/sampled_signal", O RDWR | O NONBLOCK);
ftruncate(sampled_fd, sizeof(int)*10);

CK_entity_init(&control_group, CK_GROUP, "JavaControl", 
                          "Control Group for Java interaction", NULL);
CK_scalar_int_init(&signal_hz, "SignalHz", 
                          "Core Signal Frequency",&control_group, 0, 100, 1);
CK_scalar_int_init(&noise_hz, "NoiseHz", "Noise Signal 
                           Frequency",  &control_group, 0, 100, 8);
CK_scalar_int_init(&sample_hz, "SampleHz", "Rate of Sampling 
                           Thread", &control_group, 0, 100, 10);
CK_scalar_int_init(&filter_hz, "FilterHz", "Rate of Filter 
                           Thread", &control_group, 0, 1000, 100); 
FSMCL_Rolloff_init(&rolloff_filter,"LowPassFilter", "Low Pass Filter", NULL);
CK_scalar_init_float_val(&rolloff_filter.Wn, 0, 200, 100);
CK_entity_set_suggested_representation(&rolloff_filter.Wn,"%.2f");
pthread_attr_init(&attr);
pthread_attr_setfp_np(&attr,1);
pthread_create(&filter_t, &attr, filter, 0);
pthread_create(&signal_gen_t, &attr, signal_gen, 0); 
pthread_create(&sampler_t, &attr, sampler, 0);

Listing Eleven
pthread_cancel(signal_gen_t);
pthread_join(signal_gen_t, NULL);
pthread_cancel(filter_t);
pthread_join(filter_t, NULL);
pthread_cancel(sampler_t);
pthread_join(sampler_t, NULL);
close(signal_fd); 
unlink("/pure_signal");
close(sampled_fd);
unlink("/sampled_signal");
FSMCL_Rolloff_destroy(&rolloff_filter);
CK_entity_destroy(&control_group);

Listing Twelve 
Label_corner_freq_label;
JTextField corner_freq_text;
   private void setLabels() { 
   signal_hz_label.setText("Signal Hz: " + sc.getSignalHz());
   noise_hz_label.setText("Noise Hz: " + sc.getNoiseHz());
   sample_hz_label.setText("Sample Hz: " + sc.getSampleHz());
   corner_freq_text.setText(""+sc.getCornerFreq());
   signal_hz_slider.setValue(sc.getSignalHz());
   noise_hz_slider.setValue(sc.getNoiseHz()); 
   sample_hz_slider.setValue(sc.getSampleHz());
   corner_freq_text.setText(""+sc.getCornerFreq());
}

Listing Thirteen
public void sendCommand() { 
   Process proc;
   try { 
      proc = r.exec("ck_hrt_op -s " + sample hz + 
                                     " -vp JavaControl/SampleHz");
      proc.waitFor();
      proc = r.exec("ck_hrt_op -s " + noise hz + " -vp JavaControl/NoiseHz");
      proc.waitFor();
      proc = r.exec("ck_hrt_op -s " + signal hz + " -vp JavaControl/SignalHz");
      proc.waitFor();
      proc = r.exec("ck_hrt_op -s " + filter hz + " -vp JavaControl/FilterHz");
      proc.waitFor();
      proc = r.exec("ck_hrt_op -s " + corner freq + " -vp LowPassFilter/Wn");
      proc.waitFor();
   } catch (Exception e) { 
            System.out.println("Error setting variables: " + e); 
   } 
}


Listing Fourteen
static int sampled_fd, matlab_sampled_fd;
static int signal_fd, matlab_signal_fd;
void *signal gen(void *arg) { 
   /* ... */

   write(signal_fd,&icur,sizeof(int));
   write(matlab_signal_fd,&icur,sizeof(int));
}
void *sampler(void *arg) {
   /* ... */
   write(sampled_fd,&isample,sizeof(int));
   write(matlab_sampled_fd,&isample,sizeof(int));
}

Listing Fifteen
int init_module(void) { 
   /* . . . */
   mkfifo("/pure_matlab_signal",0777);
   matlab_signal_fd = open("/pure_matlab_signal", O_RDWR | O_NONBLOCK);
   ftruncate(matlab_signal_fd, sizeof(int)*10);
   
   mkfifo("/sampled_matlab_signal",0777);
   matlab sampled_fd = open("/sampled_matlab_signal", O_RDWR | O_NONBLOCK);
   ftruncate(matlab_sampled_fd, sizeof(int)*10);
   /* ... */ 
}
void cleanup_module(void) { 
   /* ... */
   close(matlab_signal_fd);
   unlink("/pure_matlab_signal");
   close(matlab_sampled_fd);
   unlink("/sampled_matlab_signal");
   /* ... */ 
}


Listing Sixteen

clear all; clf; close all;
r = java.lang.Runtime.getRuntime;
fp = java.io.FileInputStream('/pure_matlab_signal');
dis_pure = java.io.DataInputStream(fp);
fs = java.io.FileInputStream('/sampled_matlab_signal');
dis_sample = java.io.DataInputStream(fs);
samp_size = input('Number of samples: ');

% prime the fifos
for ii=1:10
   g=dis_sample.readInt;
   g=dis_pure.readInt;
end
p = r.exec('ck_hrt_op -gvp JavaControl/SampleHz');
pause(1); 20
is = p.getInputStream;
samp_read = [ ];
num = is.available;

for ii=1:num
   samp_read = [samp_read read(is)];
end
close(is);
samp_freq = str2double(char(samp_read));

for ii=1:samp_size
   samp(ii) = dis_sample.readInt;
end

for ii=1:samp_size
   pure(ii) = dis_pure.readInt;
end
figure(1);
periodogram(samp, [ ], 512, samp_freq); 
xlabel('Sampled signal, Frequency (Hz)');
figure(2);
periodogram(pure, [ ], 512, 200);
xlabel('Pure signal, Frequency (Hz)');
dis_sample.close;
dis_pure.close;







1


