#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include "drv.h"

#define AD_BUFFER_SIZE  	8192	// 512 * 16
#define CHANNEL_NUM		32
#define AD_LEVEL_DISP_VAL	30000
#define DEVICE_NAME		"/dev/kt"

static int   ad_data[AD_BUFFER_SIZE];
static int main_end_flag;

void sigint_action(int signum, siginfo_t *info, void *ctx)
{
    main_end_flag = 1;
}

void level_display( char *str, int ch, int val )
{
    int i;

    i = sprintf( str, "[%d] ", ch );
    str += i;
    for( i = 1 ; i < 11 ; i++ )
    {
        if( val > ( AD_LEVEL_DISP_VAL * i )) *str++ = '#';
        else *str++ = ' ';
    }
    *str++ = ' ';
    *str++ = '\0';
}

int main(int argc, char **argv)
{
    struct sigaction sa_sigint;
    
    int fd;
    int stat;
    
    int    ret_val;
    struct timeval time_out;
    fd_set rfds, wfds;
    
    int rbyte;
    int wbyte;
    
    char str[64];

    int i, j, rdcnt, smpl, crlf, board_num, ch_num;
    int wave[CHANNEL_NUM], peek[CHANNEL_NUM];
    CAPTURE_CHANNELS_t  capture_info[5];

    ch_num = 16;

    if(argc == 2)
        ch_num = atoi( argv[1] );

    /* device open */
    fd = open( DEVICE_NAME, O_RDWR, 0666 );
    if( fd < 0 )
    {
        printf( "%s open error.\n", DEVICE_NAME );
        return -1;
    }
    
    /* Get AD Board Num */
    stat = ioctl( fd, FIO_GET_BOARD_NUM, &board_num );
    if( stat < 0 )
    {
        printf("ioctl error! (%d)\n", stat);
        close ( fd );
        return -1;
    }
    if(ch_num > board_num * 8) ch_num = board_num * 8;
    printf("Board num = %d\n", board_num);
    printf("Channel num = %d\n", ch_num);

    /* AD Channel Select */
    for(i = 0 ; i < 4 ; i++)
    {
        capture_info[i].board_no = i;
        capture_info[i].channels = 0xFF;
        if(ch_num < (i + 1) * 8)
        {
            switch(ch_num % 8)
            {
                case 0: capture_info[i].channels = 0x00; break;
                case 1: capture_info[i].channels = 0x01; break;
                case 2: capture_info[i].channels = 0x03; break;
                case 3: capture_info[i].channels = 0x07; break;
                case 4: capture_info[i].channels = 0x0F; break;
                case 5: capture_info[i].channels = 0x1F; break;
                case 6: capture_info[i].channels = 0x3F; break;
                case 7: capture_info[i].channels = 0x7F; break;
                default: break;
            }
        }
        stat = ioctl( fd, FIO_SET_CAPTURE_CHANNELS, &capture_info[i] );
        if( stat < 0 )
        {
            printf("ioctl error! (%d)\n", stat);
            close ( fd );
            return -1;
        }
    }

    /* AD Channel Select Check */
    for(i = 0 ; i < 4 ; i++)
    {
        capture_info[4].board_no = capture_info[i].board_no;
        capture_info[4].channels = 0x00;
        stat = ioctl( fd, FIO_GET_CAPTURE_CHANNELS, &capture_info[4] );
        if( stat < 0 )
        {
            printf("ioctl error! (%d)\n", stat);
            close ( fd );
            return -1;
        }
        if(capture_info[i].channels != capture_info[4].channels)
        {
            printf("capture channel error!\n");
            printf("capture_info.board_no = %d\n", capture_info[i].board_no);
            printf("set capture_info.channels = %d\n", capture_info[i].channels);
            printf("get capture_info.channels = %d\n", capture_info[4].channels);
            close ( fd );
            return -1;
        }
    }

    /* AD Start */
    stat = ioctl( fd, FIO_AD_START );
    if( stat < 0 )
    {
	printf("ioctl error! (%d)\n", stat);
	close ( fd );
	return -1;
    }
    
    memset(&sa_sigint, 0, sizeof(sa_sigint));
    sa_sigint.sa_sigaction = sigint_action;
    sa_sigint.sa_flags = SA_RESTART | SA_SIGINFO;
    
    if (sigaction(SIGINT, &sa_sigint, NULL) < 0)
        printf("sigaction error.\n");

    /* variable initialize */
    for( i = 0 ; i < CHANNEL_NUM ; i++ )
    {
        wave[i] = 0;
        peek[i] = 0;
    }
    rdcnt = 0;

    while(!main_end_flag)
    {
        do
        {
            FD_ZERO(&rfds);
            FD_ZERO(&wfds);
            FD_SET(fd, &rfds);
            FD_SET(fd, &wfds);
            
            time_out.tv_sec  = 0;
            time_out.tv_usec = 10 * 1000;
            ret_val = select(fd+1, &rfds, &wfds, NULL, &time_out);
        }while(ret_val == 0);
        
        if(ret_val < 0)
        {
            printf("ret_val = %d\n", ret_val);
            main_end_flag = 1;
            break;
        }

        /* データ取得処理 */
        if(FD_ISSET(fd, &rfds))
        {
            rbyte = read(fd, &ad_data[0], sizeof(ad_data));
            smpl = rbyte / sizeof(int) / ch_num;
            for( i = 0 ; i < smpl ; i++ )
            {
                for( j = 0 ; j < ch_num ; j++ )
                {
                    wave[j] = ad_data[i * ch_num + j];
                    if( abs(wave[j]) > abs(peek[j]) )
                        peek[j] = abs(wave[j]);
                }
                rdcnt++;
                if(( rdcnt % 1000 ) == 0 )
                {
                    crlf = 0;
                    for( j = 0 ; j < ch_num ; j++ )
                    {
                        if( peek[j] )
                        {
                            level_display( str, j + 1, peek[j] );
                            printf( "%s", str );
                            peek[j] = 0;
                            crlf++;
                        }
                    }
                    if( crlf )
                        printf("\n");
                }
            }
        }
    }

    fflush( stdout );
    
    /* AD Stop */
    stat = ioctl(fd, FIO_AD_STOP);
    if(stat < 0)
    {
	printf("ioctl error! (%d)\n", stat);
    }

    close(fd);
    
    return 0;
}

/* EOF */

