Beispiel #1
0
		/**
		 * Start the the ADC sampling, unless the external trigger command
		 * is set it will begin sampling as soon as the usbdux device has been
		 * initialized.
		 * The final three arguments are very important to get right
		 * as the recorder thread will use them to determine where to write it's samples and
		 * when it's reached end of the buffer. It doesn't care about the c_buffer class
		 * at all.
		 * @param arg_device name of the comedi device e.g., 'comedi0'
		 * @param arg_sample_rate the rate the usb_dux should sample with in hertz (max=3[Mhz]})
		 * @param arg_start_address the start address of the circle buffer sample should be loading into
		 * @param arg_end_address the end address of the cicle buffer.
		 * @param arg_buffer_size byte size of the buffer.
		 */
		int start_Sampling(char* arg_device, uint32_t arg_sample_rate, 
				char* arg_start_address, char* arg_end_address, int arg_buffer_size){

			_channel_amount = 16;
			_sample_rate = arg_sample_rate;

			unsigned int chanlist[_channel_amount];
			unsigned int convert_arg = 1e9 / _sample_rate;
			int ret;

			comedi_cmd *cmd = (comedi_cmd *) calloc(1, sizeof(comedi_cmd));
			_device = comedi_open(arg_device);


			int buffer = 1048576*40;
			buffer = (buffer * 4096)/4096;

			if(comedi_set_max_buffer_size(_device, 0, buffer) < 0 ){
				printf("Failed to set max buffer size to %i bytes\n", buffer);
				return -1;
			} else printf("Maximum buffer size set to %i bytes\n", comedi_get_max_buffer_size(_device,0));

			if(comedi_set_buffer_size(_device, 0, buffer) < 0){
				printf("Failed to set buffer size to %iBytes\n", buffer);
				return -1;
			} else printf("Buffer size set to %iBytes\n", comedi_get_buffer_size(_device,0));

			if(!_device){
				errx(1, "unable to open device");
				comedi_perror("/dev/comedi0");
				return -1;
			}

			for(int i = 0; i < _channel_amount; i++)	
				chanlist[i] = i;

			comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER);

			if((ret = comedi_get_cmd_generic_timed(_device, 0, cmd, _channel_amount,0)) < 0){
				printf("comedi_get_cmd_generic_timed failed\n");
				return ret;
			}

			cmd->chanlist 	= chanlist;
			cmd->stop_src	= TRIG_NONE;
			cmd->stop_arg	= 0;
			cmd->convert_arg = convert_arg;
		
			//setup the sampling to start from the trigger.
			//cmd->start_src = TRIG_EXT 
			//cmd->start_arg = 1;


			/* call test twice because different things are tested?
			 * if tests are successful run sampling command */
			if((ret = comedi_command_test(_device, cmd)) != 0
					|| (ret = comedi_command_test(_device, cmd)) != 0
					|| (ret = comedi_command(_device, cmd)) < 0){

				fprintf(stderr, "err: %d\n", ret);
				return -1;
			}

			FILE* dux_fp;

			if((dux_fp = fdopen(comedi_fileno(_device), "r")) <= 0)
				comedi_perror("fdopen");

			char* write_address = arg_start_address;
			
			Utility::SNAP_SAMPLE = 0;
			Utility::LAST_SAMPLE = 0;

			uint64_t active_sample = 0;
			uint32_t tmp_block = 0;
			int samples_pr_block = 4096/sizeof(Type);

		
			while((ret = fread(write_address, 1, 4096,dux_fp)) >= 0){

				write_address += 4096;
				tmp_block += 1;

				active_sample += samples_pr_block;
				Utility::LAST_SAMPLE += samples_pr_block;

				if(tmp_block >= Utility::SNAPSHOT_BLOCK_SIZE){
					//printf("signalling serial snapshotter\n");
					tmp_block = 0;
					Utility::SNAP_SAMPLE = active_sample;
					Utility::SNAP_READY = true;
					Utility::CV.notify_one();
				}

				if(write_address == arg_end_address){
					write_address -= arg_buffer_size;
					//printf("resetting to beginning of buffer\n");
				}

				if(_stop == true)
					break;
			}

			if(ret < 0)
				perror("read");

			comedi_cancel(_device, 0);
			return 0;
		}
Beispiel #2
0
void *_laytube_toFile(void *args){

    long unsigned int expansion_size;
    void *pause_after;
    tubeID *pTube;
    rohrStation sendingStation;
    rohrStation receivingStation;

    pTube = (tubeID *) args;


    /* Populate Station Information */
    sendingStation.stationSize = comedi_get_buffer_size(pTube->dev, pTube->subdev);
    receivingStation.stationSize = _file_size(pTube->tail);
    expansion_size = 64 * sysconf(_SC_PAGESIZE); /* Set file expansion size to a mulitple of memory page size */
    if (expansion_size < sendingStation.stationSize){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }

    /* Check for empty file */
    if (receivingStation.stationSize < 1){
        receivingStation.stationSize = expansion_size; /*  Let's make the file one page-size in length */
        ftruncate(pTube->tail, receivingStation.stationSize);
    }

    /* Set up COMEDI ring buffer memory map */
    sendingStation.firstByte = mmap(NULL, sendingStation.stationSize, PROT_READ, MAP_SHARED, pTube->mouth, 0);
    if (sendingStation.firstByte == MAP_FAILED){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }
    sendingStation.address = sendingStation.firstByte;
    sendingStation.lastByte = sendingStation.firstByte + sendingStation.stationSize - 1; /* Last valid byte */

    /* Set up HDD file memory map */
    receivingStation.firstByte = mmap(NULL, receivingStation.stationSize, PROT_WRITE | MAP_HUGETLB, MAP_SHARED, pTube->tail, 0);
    if (receivingStation.firstByte == MAP_FAILED){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }
    receivingStation.address = receivingStation.firstByte;
    receivingStation.lastByte = receivingStation.firstByte + receivingStation.stationSize - 1; /* Last valid byte */


    /* Stations are setup... set status and command flags... */
    pTube->tubeCmd = 0x00;
    pTube->tubeStatus = TUBE_INPLACE; /* <-- un-blocks laytube_toFile to return to calling function */

    /* Core algorithm - This while loop handles the data transfer from ring buffer to disk */
    while( !(pTube->tubeCmd & TUBE_STOP) ){

        /* Check if the storage file is out or about to be out of space */
        if (sendingStation.stationSize >= (receivingStation.lastByte - receivingStation.address) ){
           if (_growStation(&receivingStation, pTube->tail, expansion_size) == -1){
                pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
                pthread_exit(NULL);
           }
        }

        pause_after = sendingStation.firstByte + comedi_get_buffer_contents(pTube->dev, pTube->subdev) - 1;

        if (pause_after < sendingStation.address){
            pTube->bytesMoved = receivingStation.address - receivingStation.firstByte;
            /* comedi_poll(pTube->dev, pTube->subdev)); */
            usleep(10); /* TODO: optimize by setting sleep number to best guess at when data might show up again */
        }
        else if (pause_after < sendingStation.lastByte) /* Confirm COMEDI ring buffer has not aliased */
        {
            do {
                *((CARRIER *)receivingStation.address++) = *((CARRIER *)sendingStation.address++);
            } while(sendingStation.address <= pause_after);
        }
        else if (pause_after >= sendingStation.lastByte) /* COMEDI ring buffer has aliased... copy up to end of ring buffer and reset */
        {
            do {
                *((CARRIER *)receivingStation.address++) = *((CARRIER *)sendingStation.address++);
            } while(sendingStation.address <= sendingStation.lastByte);

            comedi_mark_buffer_read(pTube->dev, pTube->subdev, sendingStation.stationSize); /* Reset the ring buffer mark */
            sendingStation.address = sendingStation.firstByte;
        }
        else
        {
            pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
            pthread_exit(0);
        }
    }

    /* Clean up Stations, truncate file, flush tube */
    expansion_size = receivingStation.address - receivingStation.firstByte; /* 'address' should point to one byte past last byte written */
    ftruncate(pTube->tail, expansion_size);
    fsync(pTube->tail);
    pTube->bytesMoved = expansion_size;

    pTube->tubeStatus = pTube->tubeStatus | TUBE_EXIT;

    pthread_exit(0);
}
Beispiel #3
0
int PLLReferenceGeneration()
 {
    //Initial test function to try out Real time stuff.
    int m, i=0, err, n;
    lsampl_t data_to_card;
    static comedi_t * dev;
    static int OutputFIFOBufferSize;
    static int PLLGenerationBufferSize;
	unsigned int maxdata;
	unsigned int chanlist[16];
	int ret;
    static lsampl_t data[PLLGenerationBufferNPoints]; //this is the buffer used to send data points out
    comedi_cmd cmd;

    dev = comedi_open(device_names[PLLReferenceGenerationChannel.board_number]);

    //Check the size of the output buffer
    OutputFIFOBufferSize = comedi_get_buffer_size(dev, PLLReferenceGenerationChannel.subdevice);
    rt_printk("OutputFIFO Buffer size is %i\n", OutputFIFOBufferSize);

    //Set the actual buffer size that we will be using to half this and the number of data points to one fourth
    //Now configure the output channel using a Comedi instruction
    //BufferSize is initially set to be double the number of PLLGenerationBufferNPoints
    PLLGenerationBufferSize = 2*PLLGenerationBufferNPoints;


	maxdata = comedi_get_maxdata(dev, PLLReferenceGenerationChannel.subdevice, PLLReferenceGenerationChannel.channel);
	rt_printk("PLL Reference channel max data is %i\n", maxdata);

	offset = maxdata / 2;
	amplitude = maxdata - offset;

	memset(&cmd,0,sizeof(cmd));
	cmd.subdev = PLLReferenceGenerationChannel.subdevice;
	cmd.flags = CMDF_WRITE;
	cmd.start_src = TRIG_INT;
	cmd.start_arg = 0;
	cmd.scan_begin_src = TRIG_TIMER;
	cmd.scan_begin_arg = PLLGenMinPulseTime;  //minimum update time for the
	cmd.convert_src = TRIG_NOW;
	cmd.convert_arg = 0;
	cmd.scan_end_src = TRIG_COUNT;
	cmd.scan_end_arg = NCHAN; //only one channel
	cmd.stop_src = TRIG_NONE;
	cmd.stop_arg = 0;

	cmd.chanlist = chanlist;
	cmd.chanlist_len = NCHAN;

	chanlist[0] = CR_PACK(PLLReferenceGenerationChannel.channel, AO_RANGE, AREF_GROUND);

	dds_init(PLLWaveformFrequency, PLLUpdateFrequency);

	err = comedi_command_test(dev, &cmd);
	if (err < 0) {
		comedi_perror("comedi_command_test");
		exit(1);
	}

	err = comedi_command_test(dev, &cmd);
	if (err < 0) {
		comedi_perror("comedi_command_test");
		exit(1);
	}

	if ((err = comedi_command(dev, &cmd)) < 0) {
		comedi_perror("comedi_command");
		exit(1);
	}

	dds_output(data,PLLGenerationBufferNPoints);
	n = PLLGenerationBufferNPoints * sizeof(sampl_t);
	m = write(comedi_fileno(dev), (void *)data, n);
	if(m < 0){
		perror("write");
		exit(1);
	}else if(m < n)
	{
		fprintf(stderr, "failed to preload output buffer with %i bytes, is it too small?\n"
			"See the --write-buffer option of comedi_config\n", n);
		exit(1);
	}

    if(!(PLLRefGen_Task = rt_task_init_schmod(nam2num( "PLLReferenceGeneration" ), // Name
                                        2, // Priority
                                        0, // Stack Size
                                        0, //, // max_msg_size
                                        SCHED_FIFO, // Policy
                                        CPUMAP ))) // cpus_allowed
        {
            printf("ERROR: Cannot initialize pll reference generation task\n");
            exit(1);
        }

    //specify that this is to run on one CPU
    rt_set_runnable_on_cpuid(PLLRefGen_Task, 1);
    //Convert samp_time, which is in nanoseconds, to tick time
    //sampling_interval = nano2count(SAMP_TIME);  //Converts a value from
                                                //nanoseconds to internal count units.
    mlockall(MCL_CURRENT|MCL_FUTURE);
    rt_make_hard_real_time();
    PLLUpdateTime = nano2count(PLLGenerationLoopTime);
    rt_printk("PLL generation update time is %f12 \n",count2nano((float) PLLUpdateTime));
    // Let's make this task periodic..
    expected = rt_get_time() + 100*PLLUpdateTime;



    rt_task_make_periodic(PLLRefGen_Task, expected, PLLUpdateTime); //period in counts
    //rt_task_resume(Sinewaveloop_Task);
    PLLGenerationOn = TRUE;



    // Concurrent function Loop


     //rt_printk("SineWaveAmplitude is is %f \n",SineWaveAmplitude);
     //rt_printk("SineWaveFrequency is %f \n",SineWaveFrequency);
     //rt_printk("sine_loop_running is %d \n",sine_loop_running);
     //rt_printk("SAMP_TIME is %d \n",SAMP_TIME);
     start_time = (float)rt_get_time_ns()/1E9; //in seconds
     old_time = start_time;
     rt_printk("PLLReferenceGenerationChannel board_it is %p \n",PLLReferenceGenerationChannel.board_id);
     rt_printk("PLLReferenceGenerationChannel devicename is %p \n",*(PLLReferenceGenerationChannel.devicename));
     rt_printk("PLLReferenceGenerationChannel boardname is %p \n",*(PLLReferenceGenerationChannel.boardname));
     rt_printk("PLLReferenceGenerationChannel subdevice is %d \n",PLLReferenceGenerationChannel.subdevice);
     rt_printk("PLLReferenceGenerationChannel channel is %d \n",PLLReferenceGenerationChannel.channel);
     OutputValue = 1;
     PLLGenerationBufferSize = comedi_get_buffer_size(dev, PLLReferenceGenerationChannel.subdevice);
     //sine_loop_running = 0;  //set this to 0 for testing
     while(PLLGenerationOn)
     {
        i++; // Count Loops.
        current_time = (float)rt_get_time_ns()/1E9;
        //rt_printk("LOOP %d,-- Period time: %f12 %f12\n",i, current_time - old_time,count2nano((float)sampling_interval)/1E9);
        OutputValue = SineWaveAmplitude*sin(2*PI*SineWaveFrequency*(current_time-start_time));
        //OutputValue = -1*OutputValue;
        //rt_printk("OutputValue is %f12 \n",OutputValue);
        data_to_card = (lsampl_t) nearbyint(((OutputValue - MinOutputVoltage)/OutputRange)*MaxOutputBits);
        //m=rt_comedi_command_data_write(AnalogOutputChannel.board_id, AnalogOutputChannel.subdevice, NCHAN, data_to_card);
        comedi_lock(dev, AnalogOutputChannel.subdevice);
        m=comedi_data_write(dev, AnalogOutputChannel.subdevice, AnalogOutputChannel.channel, AO_RANGE, AREF_DIFF, data_to_card);
        comedi_unlock(dev, AnalogOutputChannel.subdevice);
//        m=comedi_data_write(AnalogOutputChannel.board_id, AnalogOutputChannel.subdevice,
//               AnalogOutputChannel.channel, AO_RANGE, AREF_GROUND, data_to_card);
        //rt_printk("Data_to_card is %d; result from rt_comedi_command_data_write is %d \n",data_to_card, m);
        //rt_printk("LOOP %d,-- AO Out time: %f12 \n",i, (float)rt_get_time_ns()/1E9 - current_time);
        //rt_printk("Data_to_card is %d \n",data_to_card);
        //old_time = current_time;
/*        if (i== 100000)
        {
            sine_loop_running = 0;
            //printf("LOOP -- run: %d %d\n ",keep_on_running,&keep_on_running);
            //printf("RTAI LOOP -- run: %d \n ",i);
            break;
        }
*/
        rt_task_wait_period(); // And waits until the end of the period.

    }
    rt_make_soft_real_time();
    comedi_close(dev);
    rt_task_delete(Sinewaveloop_Task); //Self termination at end.

    pthread_exit(NULL);
    return 0;
 }
Beispiel #4
0
static int openBoard( int board ) {
    MY_BOARD_HARDWARE *pBoardHard = myHardwareBoardList + board;
    MY_BOARD_SOFTWARE *pBoardSoft = mySoftwareBoardList + board;

    fprintf( stderr, "openBoard[%d]\n", board );
    fprintf( stderr, "sizeof(lsampl_t)=%d\n", sizeof(lsampl_t) );
    fprintf( stderr, "sizeof(sampl_t)=%d\n", sizeof(sampl_t) );

    if (pBoardHard == NULL || pBoardSoft == NULL) return 1;

    pBoardHard->p_comediFileHandle = comedi_open( pBoardHard->devicePath );

    if (pBoardHard->p_comediFileHandle == NULL) {
        fprintf( stderr, "comedi_open failed for board[%d] %s\n", board, pBoardHard->devicePath );
        return 1;
    }
    fprintf( stderr, "opened file\n" );
    
    pBoardHard->subDeviceNumber =
    comedi_find_subdevice_by_type(
        pBoardHard->p_comediFileHandle,
        COMEDI_SUBD_AI,
        0
    );
    
    if (pBoardHard->subDeviceNumber < 0) {
        fprintf( stderr, "subDeviceNum < 0 failed for board[%d]\n", board );
        return 1;
    }
    fprintf( stderr, "get subDevice=%d\n", pBoardHard->subDeviceNumber );

    int subDevFlags = comedi_get_subdevice_flags(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );
    if (subDevFlags & SDF_PACKED) {
        fprintf( stderr, "subDevice using bit per channel\n" );
    } else {
        if (subDevFlags & SDF_LSAMPL) {
            pBoardHard->valueIsLsampl_t = 1;
            fprintf( stderr, "subDevice using long word lsampl_t per channel\n" );
        } else {
            fprintf( stderr, "subDevice using word sampl_t per channel\n" );
        }
    }

    pBoardHard->buffer_size_in_byte =
    comedi_get_buffer_size(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );
    fprintf( stderr, "board[%d] hardware buffer size in BYTES=%d\n",
    board, pBoardHard->buffer_size_in_byte );
    if (pBoardHard->buffer_size_in_byte <= 0) {
        fprintf( stderr, "board buffer size faile\n" );
        return 1;
    }

    if (pBoardHard->valueIsLsampl_t) {
        pBoardHard->buffer_size_in_sample = pBoardHard->buffer_size_in_byte / sizeof(lsampl_t);
    } else {
        pBoardHard->buffer_size_in_sample = pBoardHard->buffer_size_in_byte / sizeof(sampl_t);
    }

    pBoardHard->buffer = mmap(
        NULL,
        pBoardHard->buffer_size_in_byte,
        PROT_READ,
        MAP_SHARED,
        comedi_fileno(pBoardHard->p_comediFileHandle),
        0
    );
    if (pBoardHard->buffer == MAP_FAILED) {
        fprintf( stderr, "mmap failed for board[%d]\n", board );
        return 1;
    }

    int numChannel = comedi_get_n_channels(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );
    if (numChannel != pBoardSoft->numberOfActiveAnalogInputs) {
        fprintf( stderr, "number of channel for board[%d] from comedi=%d harccode=%d\n",
        board, numChannel, pBoardSoft->numberOfActiveAnalogInputs );
    }

#ifdef SUPPORT_CHANNEL_SPECIFIC_RANGE
    pBoardHard->maxDataIsChannelSpecific =
    comedi_maxdata_is_chan_specific(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );
    pBoardHard->rangeIsChannelSpecific =
    comedi_maxdata_is_chan_specific(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );
    if (pBoardHard->maxDataIsChannelSpecific) {
        fprintf( stderr, "board[%d] supports different max data per channel\n", board );
    }
    if (pBoardHard->rangeIsChannelSpecific) {
        fprintf( stderr, "board[%d] supports different range per channel\n", board );
    }
#endif

    return 0;
}