parameters.cpp 4.08 KB
Newer Older
1
/**
2 3 4
 * @file parameters.cpp
 * @brief Provides interface to global camera parameters
 * @copyright Copyright (C) 2017 Elphel Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * @author AUTHOR <EMAIL>
 *
 * @par License:
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

22 23 24 25 26 27 28
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
29 30 31 32
#include <iostream>
#include <sstream>
#include <string>
#include <elphel/x393_devices.h>
33

34 35
#include "parameters.h"
//#include "streamer.h"
36 37 38

using namespace std;

39 40
//#undef PARAMETERS_DEBUG
#define PARAMETERS_DEBUG
41 42 43 44 45 46 47

#ifdef PARAMETERS_DEBUG
	#define D(a) a
#else
	#define D(a)
#endif

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
//Parameters *Parameters::_parameters = NULL;
static const char *ctl_file_names[] = {
		DEV393_PATH(DEV393_FRAMEPARS0), DEV393_PATH(DEV393_FRAMEPARS1),
		DEV393_PATH(DEV393_FRAMEPARS2), DEV393_PATH(DEV393_FRAMEPARS3)
};

Parameters::Parameters(int port) {
	string err_msg;

	if ((port >= 0) && (port < SENSOR_PORTS)) {
		sensor_port = port;
	} else {
		string port_str = static_cast<ostringstream &>((ostringstream() << dec << port)).str();
		err_msg = "port number specified is invalid: " + port_str;
		throw invalid_argument(err_msg);
	}

	fd_fparmsall = open(ctl_file_names[sensor_port], O_RDWR);
	if (fd_fparmsall < 0) {
		err_msg = "can not open " + *ctl_file_names[sensor_port];
		throw std::runtime_error(err_msg);
	}
	frameParsAll = (struct framepars_all_t *) mmap(0,
			sizeof(struct framepars_all_t), PROT_READ | PROT_WRITE, MAP_SHARED,
			fd_fparmsall, 0);
	if ((int) frameParsAll == -1) {
		frameParsAll = NULL;
		err_msg = "Error in mmap " + *ctl_file_names[sensor_port];
		throw std::invalid_argument(err_msg);
	}
78 79 80 81 82
	framePars = frameParsAll->framePars;
	globalPars = frameParsAll->globalPars;
}

Parameters::~Parameters(void) {
83 84 85 86 87
	if (frameParsAll != NULL) {
		munmap(frameParsAll, sizeof(struct framepars_all_t));
		frameParsAll = NULL;
	}
	if (fd_fparmsall > 0)
88 89 90 91 92 93 94 95 96 97
		close(fd_fparmsall);
}

/**
 * @brief Read either G_* parameter (these are 'regular' values defined by number) or P_* parameter
 *         (it can be read for up to 6 frames ahead, but current interface only allows to read last/current value)
 * @param GPNumber parameter number (as defined in c313a.h), G_* parameters have numbers above FRAMEPAR_GLOBALS, P_* - below)
 * @return parameter value
 */
unsigned long Parameters::getGPValue(unsigned long GPNumber) {
98 99
	return (GPNumber >= FRAMEPAR_GLOBALS) ? GLOBALPARS_SNGL(GPNumber) :
			framePars[GLOBALPARS_SNGL(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber];
100 101 102 103 104 105 106 107
}

/**
 * @brief Set value of the specified global (G_*) parameter
 * @param GNumber - parameter number (as defined in c313a.h)
 * @param value  - value to set
 */
void Parameters::setGValue(unsigned long GNumber, unsigned long value) {
108
	GLOBALPARS_SNGL(GNumber) = value;
109 110 111
}

unsigned long Parameters::getFrameValue(unsigned long FPNumber) {
112
	return framePars[GLOBALPARS_SNGL(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[FPNumber];
113 114 115 116 117 118 119 120 121
}

bool Parameters::daemon_enabled(void) {
	return((getFrameValue(P_DAEMON_EN) & (1 << DAEMON_BIT_STREAMER)) != 0);
}

void Parameters::setPValue(unsigned long *val_array, int count) {
	this->write(val_array, sizeof(unsigned long) * count);
}
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137

/**
 * @brief Get current FPGA time
 * @return   Time value in \e timeval structure
 */
struct timeval Parameters::get_fpga_time(void)
{
	struct timeval tv;
	unsigned long write_data[] = {FRAMEPARS_GETFPGATIME, 0};

	write(write_data, sizeof(unsigned long) * 2);
	tv.tv_sec = getGPValue(G_SECONDS);
	tv.tv_usec = getGPValue(G_MICROSECONDS);

	return tv;
}