SourceForge VA Linux Systems
Copyright © 2000 Paul Sheer - Click here for copying permissions       Source by FTP

next up previous contents index
Next: Data Graphing Application Up: Rute Users Tutorial and Previous: Corporate Frequently Asked Questions   Contents   Index

ADC Server Daemon

Add comments here 
port.h header:

 
 
 
 
5 
 
 
 
 
10 
 
 
 
 
15 
 
 
 
 
20 
 
 
 
 
25 
 
 
 
 
30 
 
 
 
 
35 
 
 
 
 
40 
 
 
 
 
45 
 
 
 
 
50 
 
 
 
 
55 
 
 
 
 
60 
 
 
 
 
65 
 
 
 
 
70 
 
 
 
 
75 
 
 
 
 
80 
 
 
 
 
85 
 
 
 
 
90 
 
 
 
 
95 
 
 
 
 
100 
 
 
 
 
105 
 
 
 
 
110 
 
 
 
 
115 
 
 
 
 
120 
 
 
 
 
125 
 
/* this comes from svgalib */

#ifdef __alpha__

#include <asm/io.h>

static __inline__ void port_out (int value, int port)
{
    _outb (value, port);
}

static __inline__ void port_outw (int value, int port)
{
    _outw (value, port);
}

static __inline__ int port_in (int port)
{
    return _inb (port);
}

static __inline__ int port_inw (int port)
{
    return _inw (port);
}

#undef inb
#undef inw
#undef outb
#undef outw

extern unsigned long vga_readb (unsigned long base, unsigned long off);
extern unsigned long vga_readw (unsigned long base, unsigned long off);
extern void vga_writeb (unsigned char b, unsigned long base, unsigned long off);
extern void vga_writew (unsigned short b, unsigned long base, unsigned long off);

#define gr_readb(off)     (vga_readb((unsigned long)SM, (off)))
#define gr_readw(off)     (vga_readw((unsigned long)SM, (off)))

#if defined(CONFIG_ALPHA_JENSEN)
#define gr_readl(off)     (vga_readl((unsigned long)SM, (off)))
#else
#define gr_readl(off)     (*(((unsigned int*)GM)+(off)))
#endif

#define gr_writeb(v,off)        (vga_writeb((v), (unsigned long)SM, (off)))
#define gr_writew(v,off)        (vga_writew((v), (unsigned long)SM, (off)))

#if defined(CONFIG_ALPHA_JENSEN)
#define gr_writel(v,off)        (vga_writel((v), (unsigned long)SM, (off)))
#else
#define gr_writel(v,off)        (*(((unsigned int*)GM)+(off)) = (v))
#endif

#else

static __inline__ void port_out (int value, int port)
{
    __asm__ volatile ("outb %0,%1"
             ::"a" ((unsigned char) value), "d" ((unsigned short) port));
}

static __inline__ void port_outw (int value, int port)
{
    __asm__ volatile ("outw %0,%1"
            ::"a" ((unsigned short) value), "d" ((unsigned short) port));
}

static __inline__ void port_outl (int value, int port)
{
    __asm__ volatile ("outl %0,%1"
             ::"a" ((unsigned long) value), "d" ((unsigned short) port));
}

static __inline__ int port_in (int port)
{
    unsigned char value;
    __asm__ volatile ("inb %1,%0"
                     :"=a" (value)
                     :"d" ((unsigned short) port));
    return value;
}

static __inline__ int port_inw (int port)
{
    unsigned short value;
    __asm__ volatile ("inw %1,%0"
                     :"=a" (value)
                     :"d" ((unsigned short) port));
    return value;
}

static __inline__ int port_inl (int port)
{
    unsigned int value;
    __asm__ volatile ("inl %1,%0":
                     "=a" (value):
                     "d" ((unsigned short) port));
    return value;
}

#define gr_readb(off)     (((volatile unsigned char *)GM)[(off)])
#define gr_readw(off)     (*(volatile unsigned short*)((GM)+(off)))
#define gr_readl(off)     (*(volatile unsigned long*)((GM)+(off)))
#define gr_writeb(v,off)        (GM[(off)] = (v))
#define gr_writew(v,off)        (*(unsigned short*)((GM)+(off)) = (v))
#define gr_writel(v,off)        (*(unsigned long*)((GM)+(off)) = (v))


#endif

/* Note that the arguments of outb/w are reversed compared with the */
/* kernel sources. The XFree86 drivers also use this format. */
#undef inb
#undef inw
#undef inl
#undef outb
#undef outw
#undef outl

#define inb port_in
#define inw port_inw
#define inl port_inl
#define outb(port, value) port_out(value, port)
#define outw(port, value) port_outw(value, port)
#define outl(port, value) port_outl(value, port)









Main source file:

 
 
 
 
5 
 
 
 
 
10 
 
 
 
 
15 
 
 
 
 
20 
 
 
 
 
25 
 
 
 
 
30 
 
 
 
 
35 
 
 
 
 
40 
 
 
 
 
45 
 
 
 
 
50 
 
 
 
 
55 
 
 
 
 
60 
 
 
 
 
65 
 
 
 
 
70 
 
 
 
 
75 
 
 
 
 
80 
 
 
 
 
85 
 
 
 
 
90 
 
 
 
 
95 
 
 
 
 
100 
 
 
 
 
105 
 
 
 
 
110 
 
 
 
 
115 
 
 
 
 
120 
 
 
 
 
125 
 
 
 
 
130 
 
 
 
 
135 
 
 
 
 
140 
 
 
 
 
145 
 
 
 
 
150 
 
 
 
 
155 
 
 
 
 
160 
 
 
 
 
165 
 
 
 
 
170 
 
 
 
 
175 
 
 
 
 
180 
 
 
 
 
185 
 
 
 
 
190 
 
 
 
 
195 
 
 
 
 
200 
 
 
 
 
205 
 
 
 
 
210 
 
 
 
 
215 
 
 
 
 
220 
 
 
 
 
225 
 
 
 
 
230 
 
 
 
 
235 
 
 
 
 
240 
 
 
 
 
245 
 
 
 
 
250 
 
 
 
 
255 
 
 
 
 
260 
 
 
 
 
265 
 
 
 
 
270 
 
 
 
 
275 
 
 
 
 
280 
 
 
 
 
285 
 
 
 
 
290 
 
 
 
 
295 
 
 
 
 
300 
 
 
 
 
305 
 
 
 
 
310 
 
 
 
 
315 
 
 
 
 
320 
 
 
 
 
325 
 
 
 
 
330 
 
 
 
 
335 
 
 
 
 
340 
 
 
 
 
345 
 
 
 
 
350 
 
 
 
 
355 
 
 
 
 
360 
 
 
 
 
365 
 
 
 
 
370 
 
 
 
 
375 
 
 
 
 
380 
 
 
 
 
385 
 
 
 
 
390 
 
 
 
/* little program to allow any program on the network to read the ADC */

/* to use, just telnet to the port and enter:
 *    x, y
 * 
 * where x is the channel, and y is the number of samples over which
 * you would like an average. It returns the time in seconds
 * since the socket was opened.
 * 
 * Entering
 *    reset
 * resets the time to zero.
 * 
 * Entering
 *    close
 * 
 * closes the socket.
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/io.h>         /* for glibc */
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/time.h>
#include <errno.h>

#include "sample.h"
#include "port.h"

void milli_sleep (long milliseconds)
{
    struct timeval tv;
    tv.tv_sec = milliseconds / 1000;
    tv.tv_usec = (milliseconds % 1000) * 1000;
    select (0, 0, 0, 0, &tv);
}

void pc30_init (PC30 * p, int base_address)
{
    struct timeval tv;

#ifdef __alpha__
    if (ioperm (0x0000, 0x10000, 1)) {
        printf ("sample: Cannot get I/O permissions.\n");
        exit (1);
    }
#else
    if (iopl (3)) {
        printf ("sample: Cannot get I/O permissions.\n");
        exit (1);
    }
#endif

    memset (p, 0, sizeof (PC30));
    p->base_address = base_address;

    port_out (0x92, PC30_ADMDE (p));
    port_out (0x34, PC30_TMRCTR (p));
    port_out (0x74, PC30_TMRCTR (p));
    port_out (0xB6, PC30_TMRCTR (p));
    port_out (0x02, PC30_ADCCR (p));
    port_out (0, PC30_DIOCNTRL (p));
    port_out (0, PC30_GMEM (p, 0));
    port_out (0, PC30_GMEM (p, 1));
    port_out (0, PC30_GMEM (p, 2));
    port_out (0, PC30_GMEM (p, 3));

    tv.tv_sec = 0;
    tv.tv_usec = 100;
    select (0, 0, 0, 0, &tv);

    port_in (PC30_ADDATL (p));
    port_in (PC30_ADDSR (p));
}

void pc30_clear (PC30 * p)
{
    struct timeval tv;

//    port_out (PC30_ADMDE (p), 0x92);
    port_out (PC30_ADCCR (p), 0x02);

    port_in (PC30_ADDATL (p));
    port_in (PC30_ADDSR (p));

/* sleep 100 microseconds sec */
    tv.tv_sec = 0;
    tv.tv_usec = 100;
    select (0, 0, 0, 0, &tv);

    port_in (PC30_ADDATL (p));
    port_in (PC30_ADDSR (p));
}

void pc30_set_gain (PC30 * p, int channel, int gain)
{
    int reg, shift, val;
    reg = channel & 0x3;
    shift = (channel >> 2) << 1;
    val = port_in (PC30_GMEM (p, reg));
    val = (val & (0xFFFF ^ (3 << shift))) | ((gain & 3) << shift);
    port_out (val, PC30_GMEM (p, reg));
}

int pc30_getsample (PC30 * p, int channel)
{
    int r;

#if 0
/* this just seems to be a waiste of milliseconds (we initialised already): */
    pc30_clear (p);
    pc30_set_gain (p, channel, p->gain[channel]);
#endif

    port_out (PC30_STBC | (channel << 4), PC30_ADCCR (p));
    port_out (PC30_STBC | PC30_SSTB | (channel << 4), PC30_ADCCR (p));
    port_out (PC30_STBC | (channel << 4), PC30_ADCCR (p));

    while (!(port_in (PC30_ADDSR (p)) & PC30_ADDONE));

    r = port_in (PC30_ADDATL (p));
    r |= port_in (PC30_ADDSR (p)) << 8;
    return (r & 0x0FFF) - (0x0FFF / 2);
}

double pc30_getsample_ave (PC30 * p, int channel, int n)
{
    double ave = 0.0;
    int i;
    for (i = 0; i < n; i++)
        ave += (double) pc30_getsample (p, channel);
    return (double) ave / (double) n;
}

#define MAX_SOCKETS         64
#define MAX_SOCKET_RESULT       32
#define NUM_CHANNELS       8
#define LISTEN_PORT         1928

struct client_adc {
    int socket;
    double time;
    char result[MAX_SOCKET_RESULT];
} adc_socket[MAX_SOCKETS];


static void fatal_error (char *fmt, ...)
{
    va_list ap;
    va_start (ap, fmt);
    fprintf (stderr, "sampled: aborting: ");
    vfprintf (stderr, fmt, ap);
    fprintf (stderr, "\n");
    if (errno)
        fprintf (stderr, "[%s]\n", sys_errlist[errno]);
    va_end (ap);
    exit (1);
}

void usage (void)
{
    printf ("Usage:\n\tsample [-v] [-p <port>] [-h]\n\n");
    printf ("-h   help\n");
    printf ("-v   verbose (-v -v for greater verbosity)\n");
    printf ("-d   run as daemon\n");
    printf ("-p   set listen port\n\n");
    printf ("See sample.c for more help.\n\n");
    exit (0);
}

double gettime (void)
{
    struct timeval tv;
    gettimeofday (&tv, 0);
    return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
}

int main (int argc, char **argv)
{
    int a;
    int verbose = 0;
    int sock, port = LISTEN_PORT;
    PC30 p;
    struct sockaddr_in server_address;
    struct hostent *hp;
    char hostname[255];
    int yes = 1;

    errno = 0;

    for (a = 1; a < argc; a++) {
        if (!strcmp (argv[a], "-v")) {
            verbose++;
            continue;
        }
        if (!strcmp (argv[a], "-d")) {
            if (fork ())
               exit (0);
            if (fork ())
               exit (0);
            continue;
        }
        if (!strcmp (argv[a], "-h")) {
            usage ();
            continue;
        }
        if (!strcmp (argv[a], "-p")) {
            if (argv[++a])
               port = atoi (argv[a]);
            else
               fatal_error ("error on command line: try\n\tsample -h");
            continue;
        }
        fatal_error ("error on command line: try\n\tsample -h");
    }

    pc30_init (&p, 0x700);

    if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
        fatal_error ("socket() failed");

    if (verbose)
        printf ("sock = %d\n", sock);

    /* Use this to debug: */
    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
                   (char *) &yes, sizeof (yes)) < 0)
        fatal_error ("setsockopt() failed");

    gethostname (hostname, 255);
    if (!(hp = gethostbyname (hostname)))
        fatal_error ("gethostbyname() failed");

    memset ((char *) &server_address, 0, sizeof (server_address));

    server_address.sin_family = hp->h_addrtype;
    server_address.sin_addr.s_addr = INADDR_ANY;
    server_address.sin_port = htons (port);

    if (verbose)
        printf ("listen port is %d\n", port);

    if (bind (sock, (struct sockaddr *) &server_address,
              sizeof (server_address)) < 0)
        fatal_error ("bind() failed");

    listen (sock, 5);

    for (a = 0; a < MAX_SOCKETS; a++) {
        adc_socket[a].socket = 0;
        adc_socket[a].result[0] = '\0';
    }

    signal (SIGPIPE, SIG_IGN);

    for (;;) {
        int i;
        fd_set writing, reading;
        int last_sock = 0;

        FD_ZERO (&writing);
        FD_ZERO (&reading);
        FD_SET (sock, &reading);
        if (sock > last_sock)
            last_sock = sock;
        for (i = 0; i < MAX_SOCKETS; i++) {
            if (adc_socket[i].socket) {
               FD_SET (adc_socket[i].socket, &reading);
               if (adc_socket[i].result[0])
                   FD_SET (adc_socket[i].socket, &writing);
               if (adc_socket[i].socket > last_sock)
                   last_sock = adc_socket[i].socket;
            }
        }

        if (verbose > 1)
            printf ("select (%d,...)\n", last_sock + 1);
        if (select (last_sock + 1, &reading, &writing, 0, 0) == -1)
            fatal_error ("select() return -1");

        if (FD_ISSET (sock, &reading)) {
            struct sockaddr_in client_address;
            unsigned int l = sizeof (client_address);
            if (verbose > 1)
               printf ("FD_ISSET (sock = %d, &reading)\n", sock);
            for (i = 0; i < MAX_SOCKETS && adc_socket[i].socket; i++);
            if (i == MAX_SOCKETS)
               fatal_error ("MAX_SOCKETS reached");
            if (verbose > 1)
               printf ("accepting:\n");
            adc_socket[i].socket =
               accept (sock, (struct sockaddr *) &client_address, &l);
            adc_socket[i].result[0] = '\0';
            adc_socket[i].time = gettime ();
            if (verbose > 1)
               printf ("%d = accept (sock = %d,...)\n",
                     adc_socket[i].socket, sock);
        }
        for (i = 0; i < MAX_SOCKETS; i++) {
            if (FD_ISSET (adc_socket[i].socket, &reading)) {
               int l;
               char buf[1024] = "";
               if (verbose > 1)
                   printf ("FD_ISSET (%d, &reading)\n",
                         adc_socket[i].socket);
               l = read (adc_socket[i].socket, buf, 1024);
               if (verbose > 1)
                   printf ("%d = read (%d, ...)\n", l,
                         adc_socket[i].socket);
               if (l <= 0) {
                   if (verbose)
                     printf ("read error, closing socket %d\n",
                          adc_socket[i].socket);
                   close (adc_socket[i].socket);
                   adc_socket[i].socket = 0;
                   adc_socket[i].result[0] = '\0';
                   continue;
               }
               if (!strncmp (buf, "close", 5)) {
                   if (verbose)
                     printf ("recieved \"close\", closing socket %d\n",
                          adc_socket[i].socket);
                   close (adc_socket[i].socket);
                   adc_socket[i].socket = 0;
                   adc_socket[i].result[0] = '\0';
                   continue;
               }
               if (!strncmp (buf, "reset", 5)) {
                   adc_socket[i].time = gettime ();
                   continue;
               }
               if (verbose)
                   printf ("got command: \"%.50s\", from socket %d\n",
                         buf, adc_socket[i].socket);
               {
                   char *q;
                   int channel, samples = 0;
                   channel = atoi (buf);
                   q = (char *) strchr (buf, ',');
                   if (q)
                     while (strchr (", \t", *q))
                         q++;
                   if (q)
                     samples = atoi (q);
                   if (!samples || channel < 0 || channel >= NUM_CHANNELS) {
                     if (verbose)
                         printf
                          ("bad command: \"%.50s\", closing socket %d\n",
                           buf, adc_socket[i].socket);
                     close (adc_socket[i].socket);
                     adc_socket[i].socket = 0;
                     adc_socket[i].result[0] = '\0';
                     continue;
                   }
                   sprintf (adc_socket[i].result, "%.3f, %.3f\n",
                          gettime () - adc_socket[i].time,
                          pc30_getsample_ave (&p, channel, atoi (q)));
               }
            }
        }
        for (i = 0; i < MAX_SOCKETS; i++) {
            if (FD_ISSET (adc_socket[i].socket, &writing)) {
               int l;
               if (verbose > 1)
                   printf ("FD_ISSET (%d, &writing)\n",
                         adc_socket[i].socket);
               l =
                   write (adc_socket[i].socket, adc_socket[i].result,
                        strlen (adc_socket[i].result));
               if (verbose > 1)
                   printf ("%d = write (%d, ...)\n", l,
                         adc_socket[i].socket);
               if (l != strlen (adc_socket[i].result)) {
                   if (verbose)
                     printf ("write error, closing socket %d\n",
                          adc_socket[i].socket);
                   close (adc_socket[i].socket);
                   adc_socket[i].socket = 0;
                   adc_socket[i].result[0] = '\0';
               }
               adc_socket[i].result[0] = '\0';
            }
        }
    }
    return 0;
}



Paul Sheer 2000-10-07