#include <rtl.h>
#include <pthread.h>
#include <rtl_fifo.h>

/* Periodischer RT-Thread. Zaehlt bei jedem Aufruf hoch und gibt */
/* den Zaehlerstand in /dev/rtf1 aus. Lesen: "cat /dev/rtf1" */
/* Periode ist ber /dev/rtf2 aenderbar: echo nnnn > /dev/rtf2 */
/* nnnn [ms] muss eine vierstellige Zahl sein (fuehrende Nullen!) */
/* Statusinfos bei geaenderter Periode etc. im Syslog */
/* Benoetigt zum Kompilieren ein installiertes RTLinux */
/* ACHTUNG: Kann bei Fehlern den ganzen Rechner crashen! */

pthread_t thread;
int count = 0;   /* zaehlt die Aufrufe des periodischen Threads */
int period = 50; /* ms; make_periodic_np() erwartet Nanosekunden */

void *my_thread(void *arg)
{
  int err;
  char buf[5] = "000\n\0";   /* fuer Ein- und Ausgabe */
  /* Thread periodisch machen und Periode ins Syslog ausgeben */
  pthread_make_periodic_np(pthread_self(), gethrtime(), period*1000000);
  rtl_printf("I'm here, waking up each %d ms\n", period);
  while (1)
  {
    count++;
    if (count>999) count=0;    /* groesser geht nicht ... */
    if (4 == (err=rtf_get(2, buf, 4)))
    {      /* neue Periode aus /dev/rtf2 gelesen */
      period=0;
      if (buf[0]>='0' && buf[0]<='9') period += 1000 * (buf[0]-48);
      if (buf[1]>='0' && buf[1]<='9') period += 100 * (buf[1]-48);
      if (buf[2]>='0' && buf[2]<='9') period += 10 * (buf[2]-48);
      if (buf[3]>='0' && buf[3]<='9') period += buf[3]-48;
      if (period)   /* gueltig */
      { /* von vorne zaehlen, Periode aendern und ins Syslog */
        count=0;
        pthread_make_periodic_np(pthread_self(), gethrtime(), 
         period*1000000);
        rtl_printf("period changed to %d ms\n", period);
      }
      else rtl_printf("read %s: invalid\n", buf);
    }
    pthread_wait_np();  /* warten, bis wir dran sind */
    buf[0] = count/100 + 48;   /* Zaehler als String basteln ... */
    buf[1] = (count%100)/10 + 48;
    buf[2] = count%10 + 48;
    buf[3] = '\n';
    if (4 != (err=rtf_put(1, buf, 4)))   /* ... und ausgeben */
     rtl_printf("rtf_put(): error %1d (count=%03d)\n", err, count);
  }
  return 0;
}  /* my_thread() */

int init_module(void) 
{
  rtf_destroy(1);   /* FIFOs sicherheitshalber erst wegraeumen */
  rtf_destroy(2);
  if (rtf_create(1, 4096) < 0)  /* nach /dev/rtf1 schreiben */
  {
    rtl_printf("can't create FIFO 1\n"); return -1;
  }
  if (rtf_create(2, 4096) < 0)  /* von /dev/rtf2 lesen */
  {
    rtl_printf("can't create FIFO 2\n"); return -1;
  }
  return pthread_create(&thread, NULL, my_thread, 0); /* der Thread */
}  /* init_module() */

void cleanup_module(void)
{
  rtf_destroy(1);              /* FIFOs aufraeumen */
  rtf_destroy(2);
  pthread_delete_np (thread);  /* Thread aufraeumen */
}  /* cleanup_module() */

