Exemple #1
0
//
// Retrieve a recors from disk and check it's CRC
//
void dvb_config_retrieve_from_disk( sys_config *cfg )
{
    FILE *fp;
    SysConfigRecord rd;
    int success = -1;

    dvb_config_create();

    if((fp=fopen(dvb_config_get_path("datvexpress.cfg"),"r")) > 0)
    {
        size_t size = fread( &rd, 1, sizeof(SysConfigRecord), fp );
        if( size == sizeof(SysConfigRecord))
        {
            // Check the CRC to make sure it is valid
            unsigned long crc = dvb_crc32_calc((unsigned char*)&rd.cfg, sizeof(sys_config));
            if( crc == rd.crc.crc )
            {
                memcpy( cfg, &rd.cfg, sizeof(sys_config));
                success = 0;
            }
        }
        //cfg->dvbs2_fmt.constellation = M_QPSK;
        //cfg->dvb_mode         = MODE_DVBS;
        fclose(fp);
    }
    if( success != 0 )
    {
        loggerf("Using default Settings");
        dvb_default_configuration( cfg );
        dvb_config_save_to_disk( cfg );
    }
}
Exemple #2
0
int
serOpenDev ( serDevT* dev )
{
#ifdef ENABLE_TIMEPPS
	pps_params_t	ppsparams;
	int		ppsmode;
#endif

	dev->fd = open ( dev->dev, O_RDONLY|O_NOCTTY );

	switch ( dev->mode )
	{
#ifdef ENABLE_TIMEPPS
	case SERPORT_MODE_TIMEPPS:
		if ( time_pps_create ( dev->fd, &dev->ppshandle ) == -1 )
			return -1;

		if ( time_pps_getparams ( dev->ppshandle, &ppsparams ) == -1 )
			return -1;

		ppsparams.mode |= PPS_TSFMT_TSPEC | PPS_CAPTUREBOTH;

		if ( time_pps_setparams ( dev->ppshandle, &ppsparams ) == -1 )
			return -1;

		if ( time_pps_getcap ( dev->ppshandle, &ppsmode ) == -1 )
			return -1;

		//NOTE: these should probably be error cases, but the code is still experimental and
		//the PPS support I've used also seems to have problems
		if ( ! (ppsmode | PPS_CAPTUREASSERT) )
			loggerf ( LOGGER_NOTE, "Warning: PPS_CAPTUREASSERT not supported\n" );
		if ( ! (ppsmode | PPS_CAPTURECLEAR) )
			loggerf ( LOGGER_NOTE, "Warning: PPS_CAPTURECLEAR not supported\n" );

//!!! no point using this - too many problems
//1. linux doesn't report PPS_CANWAIT, but can
//2. FreeBSD does report PPS_CANWAIT, but can't
//(unless its me reading the docs backwards?)
//		if ( ! (ppsmode | PPS_CANWAIT) )
//			loggerf ( LOGGER_NOTE, "Warning: PPS_CANWAIT not supported (linux lies)\n" );

#endif
	}

	return dev->fd;
}
Exemple #3
0
int
wwvbDecode ( clkInfoT* clock, time_f minstart )
{
	struct tm	dectime;
	time_t		dectimet;

	wwvbDump ( clock );

	if ( !DATA_OK(1) )
		return -1;

	memset ( &dectime, 0, sizeof(dectime) );

	dectime.tm_year = wwvbGetBCD ( clock, 44, 10 ) + CENTURY - 1900;
	dectime.tm_mon = 1;
	dectime.tm_mday = wwvbGetBCD ( clock, 22, 12 );
	dectime.tm_hour = wwvbGetBCD ( clock, 12, 7 );
	dectime.tm_min = wwvbGetBCD ( clock, 1, 8 );
	dectime.tm_sec = 0;
	dectime.tm_isdst = 0;	//time is always UTC... (although there are bits for summer time)

	//NOTE: decoding this depends on a mktime() which will normalize day numbers correctly

	if ( (dectime.tm_mday < 1) || (dectime.tm_mday > 366) )
		return -1;
	if ( dectime.tm_hour > 23 )
		return -1;
	if ( dectime.tm_min > 60 )
		return -1;

	loggerf ( LOGGER_DEBUG, "WWVB time: %04d-%03d %02d:%02d %s%s\n", dectime.tm_year+1900, dectime.tm_mday, dectime.tm_hour, dectime.tm_min, GET(55)?" leap year":"", GET(56)?" leap second soon":"" );

//	setenv ( "TZ", "", 1 );
//
//	dectimet = mktime ( &dectime );
	dectimet = UTCtime ( &dectime );
	if ( dectimet == (time_t)(-1) )
		return -1;

	clock->pctime = minstart;
	clock->radiotime = dectimet + clock->fudgeoffset;
	clock->radioleap = GET(56) ? LEAP_ADDSECOND : LEAP_NOWARNING;

	clock->secondssincetime = 0;

	return 0;
}
Exemple #4
0
int
serStoreDevStatusLines ( serDevT* dev, int lines, time_f timef )
{

	time_f diff = timef - dev->eventtime;
	if (diff < 0.05) {
		loggerf ( LOGGER_DEBUG, "serStoreDevStatusLines: pulse too short %f, filtering!\n", diff);
		return 0;
	}
	if ( lines != dev->curlines )
	{
		dev->prevlines = dev->curlines;
		dev->curlines = lines;
		dev->eventtime = timef;

		return 1;
	}

	return 0;
}
Exemple #5
0
void
wwvbDump ( clkInfoT* clock )
{
	int	i;

	loggerf ( LOGGER_TRACE, "WWVB : " );
	for ( i=0; i<60; i+=5 )
		loggerf ( LOGGER_TRACE, "|%-4d", i );
	loggerf ( LOGGER_TRACE, "\n" );

	loggerf ( LOGGER_TRACE, "WWVB : " );
	for ( i=0; i<60; i++ )
		loggerf ( LOGGER_TRACE, "%c", DATA_OK(i)?(GET(i)?'1':'.'):' ' );
	loggerf ( LOGGER_TRACE, "\n" );
}
Exemple #6
0
void dvb_config_save_to_disk(sys_config *cfg)
{
    FILE *fp;
    SysConfigRecord record;

    dvb_config_create();

    if((fp=fopen(dvb_config_get_path("datvexpress.cfg"),"w"))>0)
    {
        // Create a CRC of the data and sve it along with the data
        record.crc.crc  = dvb_crc32_calc((unsigned char*)cfg, sizeof(sys_config));
        // Copy the cfg into the disk record structure
        memcpy( &record.cfg, cfg, sizeof(sys_config));
        // Save
        fwrite(&record,sizeof(SysConfigRecord), 1, fp );
        fclose(fp);
    }
    else
    {
        loggerf("Cannot save configuration file (check owner)");
    }
}
Exemple #7
0
void
shmStore ( shmTimeT* volatile shm, time_f radioclock, time_f localrecv, time_f time_err, int leap )
{
	struct timeval radioclocktv,localrecvtv;

	loggerf ( LOGGER_DEBUG, "shm: storing time "TIMEF_FORMAT" local "TIMEF_FORMAT" err "TIMEF_FORMAT" leap %d\n", radioclock, localrecv, time_err, leap );

	time_f2timeval ( radioclock, &radioclocktv );
	time_f2timeval ( localrecv, &localrecvtv );

	shm->valid = 0;

	shm->mode = 1;
	shm->count++;
	shm->clockTimeStampSec = radioclocktv.tv_sec;
	shm->clockTimeStampUSec = radioclocktv.tv_usec;
	shm->receiveTimeStampSec = localrecvtv.tv_sec;
	shm->receiveTimeStampUSec = localrecvtv.tv_usec;
	shm->leap = leap;
	shm->precision = log(time_err)/log(2);
	shm->count++;

	shm->valid = 1;
}
Exemple #8
0
serLineT*
serAddLine ( char* dev, int line, int mode )
{
	char		fulldev[64];
	serDevT*	serdev;
	serLineT*	serline;

	//allow for either full paths or /dev relative paths...
	if ( dev[0] == '/' )
	{
		if ( strlen(dev) >= 64 )
		{
			loggerf ( LOGGER_NOTE, "serAddLine(): dev too long\n" );
			return NULL;
		}
		strcpy ( fulldev, dev );
	}
	else
	{
		strcpy ( fulldev, "/dev/" );
		if ( strlen(dev)+strlen(fulldev) >= 64 )
		{
			loggerf ( LOGGER_NOTE, "serAddLine(): dev too long\n" );
			return NULL;
		}
		strcat ( fulldev, dev );
	}

	//make sure only one line bit is set...
	if ( line & (line-1) )
	{
		loggerf ( LOGGER_NOTE, "serAddLine(): more than one line bit set\n" );
		return NULL;
	}

	//try and find an existing device in the list...
	serdev = serDevHead;
	while ( serdev != NULL )
	{
		if ( strcmp ( serdev->dev, fulldev ) == 0 )
			break;
		serdev = serdev->next;
	}
	if ( serdev == NULL )
	{
		//no existing device - create a new one..
		serdev = safe_mallocz ( sizeof(serDevT) );
		serdev->next = serDevHead;
		serDevHead = serdev;

		strcpy ( serdev->dev, fulldev );
		serdev->mode = mode;
		serdev->modemlines = 0;
		serdev->fd = -1;
	}

	//make sure we're using it in the same mode...
	if ( serdev->mode != mode )
	{
		loggerf ( LOGGER_NOTE, "serAddLine(): cannot add line for same device with different mode\n" );
		return NULL;
	}


	//make sure we're not already monitoring this line...
	if ( serdev->modemlines & line )
	{
		loggerf ( LOGGER_NOTE, "serAddLine(): cannot add modem status line more than once\n" );
		return NULL;
	}

	//ok - we've got a valid device/line/mode combo...

	serdev->modemlines |= line;

	//create a new line entry...
	serline = safe_mallocz ( sizeof(serLineT) );
	serline->next = serLineHead;
	serLineHead = serline;

	serline->dev = serdev;
	serline->line = line;

	return serline;

}
Exemple #9
0
int
serWaitForSerialChange ( serDevT* dev )
{
	struct timeval tv;
	time_f	timef;
	int	i,ret;
#ifdef ENABLE_TIMEPPS
	struct timespec timeout;
	pps_info_t	ppsinfo;
	int		ppslines;
#endif
#ifdef ENABLE_GPIO
	struct pollfd  pollfds[1];
#endif

	if ( dev->modemlines == 0 )
		return -1;

	switch ( dev->mode )
	{
	case SERPORT_MODE_POLL:

		for ( i=0; i<10*1000; i++ )
		{
			gettimeofday ( &tv, NULL );
			timeval2time_f ( &tv, timef );
			ret = serGetDevStatusLines ( dev, timef );
			if ( ret < 0 )
				return -1;
			if ( ret == 1 )
				return 0;

			usleep ( 1000 );
		}

		//timeout
		return -1;
		break;

#ifdef ENABLE_GPIO
	case SERPORT_MODE_GPIO:
		pollfds[0].fd = dev->fd;
		pollfds[0].events = POLLERR;

		i = poll(pollfds, 1, 10000); /* timeout 10 seconds */
		if (i != 1 && !(pollfds[0].revents & POLLERR) )
			return -1;

		gettimeofday ( &tv, NULL );
		timeval2time_f ( &tv, timef );

		if ( serGetDevStatusLines ( dev, timef ) < 0 )
			return -1;

		return 0;
		break;
#endif


#ifdef ENABLE_TIOCMIWAIT
	case SERPORT_MODE_IWAIT:
		signal ( SIGALRM, sigalrm );
		alarm ( 10 );

		if ( ioctl ( dev->fd, TIOCMIWAIT, dev->modemlines) != 0 )
			return -1;
		gettimeofday ( &tv, NULL );
		timeval2time_f ( &tv, timef );

		signal ( SIGALRM, SIG_DFL );
		alarm ( 0 );

		if ( serGetDevStatusLines ( dev, timef ) < 0 )
			return -1;

		return 0;
		break;
#endif

#ifdef ENABLE_TIMEPPS
	case SERPORT_MODE_TIMEPPS:
		timeout.tv_sec = 0;
		timeout.tv_nsec = 0;

		for ( i=0; i<10*100; i++ )
		{
			if ( time_pps_fetch ( dev->ppshandle, PPS_TSFMT_TSPEC, &ppsinfo, &timeout ) == -1 )
			{
				loggerf ( LOGGER_NOTE, "ppsfetch failed: %d\n", errno );
				return -1;
			}

			if ( ppsinfo.assert_sequence != dev->ppslastassert )
			{
				timespec2time_f ( &ppsinfo.assert_timestamp, timef );
				ppslines = TIOCM_CD;	//NOTE: assuming that pps support is on the DCD line
				dev->ppslastassert = ppsinfo.assert_sequence;

				if ( serStoreDevStatusLines ( dev, ppslines, timef ) < 0 )
					return -1;
				return 0;
			}
			else if ( ppsinfo.clear_sequence != dev->ppslastclear )
			{
				timespec2time_f ( &ppsinfo.clear_timestamp, timef );
				ppslines = 0;
				dev->ppslastclear = ppsinfo.clear_sequence;

				if ( serStoreDevStatusLines ( dev, ppslines, timef ) < 0 )
					return -1;
				return 0;
			}

			usleep ( 10000 );
		}

		return -1;
		break;
#endif

	}

	loggerf ( LOGGER_NOTE, "Error: serWaitForSerialChange(): mode not supported\n" );

	//unknown serial port mode !!
	return -1;

}
//
// Set up both the audio and video capturing on the card
//
void an_configure_capture_card( void )
{
    struct v4l2_cropcap cropcap;
    struct v4l2_crop    crop;
    struct v4l2_format  fmt;
    sys_config info;
    int input;
    u32 pix_fmt;

    dvb_config_get( &info );

    CLEAR(cropcap);
    CLEAR(crop);
    CLEAR(fmt);

    m_width  = PAL_WIDTH_CAPTURE;
    m_height = PAL_HEIGHT_CAPTURE;

    // Set the cropping, ignore any errors
    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (ioctl(m_i_fd, VIDIOC_CROPCAP, &cropcap)==0) {
            crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            crop.c    = cropcap.defrect; /* reset to default */

            ioctl(m_i_fd, VIDIOC_S_CROP, &crop);
    }
    //
    // Analogue Video capture
    //
    pix_fmt = V4L2_PIX_FMT_YUV420;
    m_sws   = NULL;

    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width       = m_width;
    fmt.fmt.pix.height      = m_height;
    fmt.fmt.pix.pixelformat = pix_fmt;
    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;

    if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0)
    {
        an_set_image_size( AV_PIX_FMT_YUV420P );
    }
    else
    {
        pix_fmt = V4L2_PIX_FMT_YUYV; // capture format
        fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.width       = m_width;
        fmt.fmt.pix.height      = m_height;
        fmt.fmt.pix.pixelformat = pix_fmt;
        fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
        if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0)
        {
            // Format conversion will be required
            m_sws = sws_getContext( m_width, m_height, AV_PIX_FMT_YUYV422,
                                    m_width, m_height, AV_PIX_FMT_YUV420P,
                                    SWS_BICUBIC, NULL,NULL, NULL);
            an_set_image_size( AV_PIX_FMT_YUYV422 );
        }
        else
        {
            logger("CAP ANALOGUE FORMAT NOT SUPPORTED");
        }
    }

    if(ioctl(m_i_fd, VIDIOC_G_FMT, &fmt)<0 )
        logger("can't get format");

    //	input = V4L2_INPUT_TYPE_CAMERA;
    input = info.video_capture_device_input;

    if( ioctl( m_i_fd, VIDIOC_S_INPUT, &input) < 0 )
    {
        loggerf("CAP Error VIDIOC_S_INPUT %d",input);
    }

/*
    v4l2_streamparm parm;
    memset(&parm,0,sizeof(v4l2_streamparm));
    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    parm.parm.capture.capturemode = 0;
    parm.parm.capture.readbuffers = 0;

    if( ioctl( m_i_fd, VIDIOC_S_PARM, &parm) < 0 )
    {
        loggerf("CAP Error VIDIOC_S_PARM");
    }
*/
    info.video_bitrate = calculate_video_bitrate();

    //
    // Analogue sound capture
    //
    snd_pcm_hw_params_t *hw_params;

    if(snd_pcm_open(&m_audio_handle, "pulse", SND_PCM_STREAM_CAPTURE, 0)< 0 )
    {
        loggerf("Unable to open sound device");
        return;
    }
    unsigned int rate = 48000;
    int r;
    r = snd_pcm_hw_params_malloc(&hw_params);
    r = snd_pcm_hw_params_any(m_audio_handle, hw_params);
    r = snd_pcm_hw_params_set_access(m_audio_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    r = snd_pcm_hw_params_set_format(m_audio_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    r = snd_pcm_hw_params_set_rate_near(m_audio_handle, hw_params, &rate, 0);
    r = snd_pcm_hw_params_set_channels(m_audio_handle, hw_params, 2);
    r = snd_pcm_hw_params(m_audio_handle, hw_params);
    snd_pcm_hw_params_free(hw_params);
    r = snd_pcm_prepare(m_audio_handle);

    an_init_codecs();
    m_capturing = true;
    an_setup_video_capturing( m_i_fd );
    an_setup_audio_capturing();
}
//
// Initilaise all the software codecs
//
int an_init_codecs( void )
{
    sys_config info;

    av_register_all();
    avfilter_register_all();
    dvb_config_get( &info );

    av_init_packet(&m_avpkt[ENVC]);

    m_avpkt[ENVC].data = NULL;
    m_avpkt[ENVC].size = 0;

    // 25 frames per sec, every 40 ms
    m_video_timestamp_delta = ((0.04*27000000.0)/300.0);
    // New audio packet sent every 24 ms
    m_audio_timestamp_delta = ((0.024*27000000.0)/300.0);

    AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MPEG2VIDEO);
    if(codec != NULL)
    {
        m_pC[ENVC]                     = avcodec_alloc_context3(codec);
        m_pC[ENVC]->bit_rate           = info.video_bitrate;
        m_pC[ENVC]->bit_rate_tolerance = info.video_bitrate/10;
        m_pC[ENVC]->width              = m_width;
        m_pC[ENVC]->height             = m_height;
        m_pC[ENVC]->gop_size           = 12;
        m_pC[ENVC]->max_b_frames       = 0;
        m_pC[ENVC]->me_method          = 5;
        m_pC[ENVC]->pix_fmt            = AV_PIX_FMT_YUV420P;
        m_pC[ENVC]->time_base          = (AVRational){1,25};
        m_pC[ENVC]->ticks_per_frame    = 2;// MPEG2 & 4
        m_pC[ENVC]->profile            = FF_PROFILE_MPEG2_MAIN;
        m_pC[ENVC]->thread_count       = 1;

        if(avcodec_open2(m_pC[ENVC], codec, NULL)<0)
        {
            loggerf("Unable to open MPEG2 Codec");
            return -1;
        }
    }
    else
    {
        loggerf("MPEG2 Codec not found");
        return -1;
    }
    //
    // Audio
    //
    av_init_packet( &m_avpkt[ENAC] );
    //
    // Must be set to 48000, 2 chan
    //
    // Size in bytes 2 channels, 16 bits 1/25 sec
    codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
    if( codec != NULL )
    {
        m_pC[ENAC] = avcodec_alloc_context3(codec);
        m_pC[ENAC]->bit_rate            = info.audio_bitrate;
        m_pC[ENAC]->bit_rate_tolerance  = 0;
        m_pC[ENAC]->bits_per_raw_sample = 16;
        m_pC[ENAC]->sample_rate         = 48000;
        m_pC[ENAC]->channels            = 2;
        m_pC[ENAC]->sample_fmt          = AV_SAMPLE_FMT_S16;
        m_pC[ENAC]->channel_layout      = AV_CH_LAYOUT_STEREO;
        m_pC[ENAC]->thread_count        = 1;

        if(avcodec_open2(m_pC[ENAC], codec, NULL)<0 )
        {
            loggerf("Unable to open MPEG1 codec");
            return -1;
        }
        // 16 bit samples & stereo so multiply by 4
        m_sound_capture_buf_size = m_pC[ENAC]->frame_size*4;
        an_set_audio_size();
    }
    return 0;
}
//
// Start capturing using streaming
//
void an_start_streaming_capture(int fd)
{
    struct v4l2_requestbuffers req;

    CLEAR(req);

    req.count = 4;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

    if (ioctl(fd, VIDIOC_REQBUFS, &req)<0)
    {
        loggerf("CAP does not support MM");
        return;
    }

    if (req.count < 2)
    {
        loggerf("CAP not enough MM buffers");
        return;
    }

    m_buffers = (struct buffer*)calloc(req.count, sizeof(*m_buffers));

    if (!m_buffers)
    {
        loggerf("Not enough buffer memory");
        return;
    }

    for (m_n_buffers = 0; m_n_buffers < req.count; ++m_n_buffers)
    {
        struct v4l2_buffer buf;

        CLEAR(buf);

        buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index  = m_n_buffers;

        if ( ioctl(fd, VIDIOC_QUERYBUF, &buf)<0)
        {
            return;
        }

        m_buffers[m_n_buffers].length = buf.length;
        m_buffers[m_n_buffers].start =
        mmap(NULL /* start anywhere */,
        buf.length,
        PROT_READ | PROT_WRITE /* required */,
        MAP_SHARED /* recommended */,
        fd, buf.m.offset);

        if (MAP_FAILED == m_buffers[m_n_buffers].start) return;
    }
    //
    // Start the capturing
    //
    for (unsigned int i = 0; i < m_n_buffers; ++i)
    {
        struct v4l2_buffer buf;

        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;

        if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) return;
    }
    v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd, VIDIOC_STREAMON, &type)<0) return;

    pthread_create( &an_thread[0], NULL, an_video_mmap_capturing_thread, NULL );
}