mirror of
https://github.com/galera951/experiment-automation.git
synced 2024-11-21 13:15:53 +03:00
mv project to lab-helper
This commit is contained in:
parent
1a273370a8
commit
b4e13ad5b4
@ -939,7 +939,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.2"
|
||||
"version": "3.10.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
6
project/.gitignore
vendored
6
project/.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
*test*
|
||||
*tmp*
|
||||
.vscode
|
||||
*.exe
|
||||
*.o
|
||||
main
|
@ -1,2 +0,0 @@
|
||||
- [ ] Автоматическое подключение генератора
|
||||
- [ ] Автоматическая резонансная кривая (данные в файл)
|
File diff suppressed because one or more lines are too long
@ -1,87 +0,0 @@
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "pocketfft_hdronly.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace pocketfft;
|
||||
|
||||
// floating point RNG which is good enough for sinmple demos
|
||||
// Do not use for anything important!
|
||||
inline double simple_drand()
|
||||
{
|
||||
constexpr double norm = 1./RAND_MAX;
|
||||
return rand()*norm;
|
||||
}
|
||||
|
||||
template<typename T> void crand(vector<complex<T>> &v)
|
||||
{
|
||||
for (auto & i:v)
|
||||
i = complex<T>(simple_drand()-0.5, simple_drand()-0.5);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> long double l2err
|
||||
(const vector<T1> &v1, const vector<T2> &v2)
|
||||
{
|
||||
long double sum1=0, sum2=0;
|
||||
for (size_t i=0; i<v1.size(); ++i)
|
||||
{
|
||||
long double dr = v1[i].real()-v2[i].real(),
|
||||
di = v1[i].imag()-v2[i].imag();
|
||||
long double t1 = sqrt(dr*dr+di*di), t2 = abs(v1[i]);
|
||||
sum1 += t1*t1;
|
||||
sum2 += t2*t2;
|
||||
}
|
||||
return sqrt(sum1/sum2);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
for (size_t len=1; len<8192; ++len)
|
||||
{
|
||||
shape_t shape{len};
|
||||
stride_t stridef(shape.size()), strided(shape.size()), stridel(shape.size());
|
||||
size_t tmpf=sizeof(complex<float>),
|
||||
tmpd=sizeof(complex<double>),
|
||||
tmpl=sizeof(complex<long double>);
|
||||
for (int i=shape.size()-1; i>=0; --i)
|
||||
{
|
||||
stridef[i]=tmpf;
|
||||
tmpf*=shape[i];
|
||||
strided[i]=tmpd;
|
||||
tmpd*=shape[i];
|
||||
stridel[i]=tmpl;
|
||||
tmpl*=shape[i];
|
||||
}
|
||||
size_t ndata=1;
|
||||
for (size_t i=0; i<shape.size(); ++i)
|
||||
ndata*=shape[i];
|
||||
|
||||
vector<complex<float>> dataf(ndata);
|
||||
vector<complex<double>> datad(ndata);
|
||||
vector<complex<long double>> datal(ndata);
|
||||
crand(dataf);
|
||||
for (size_t i=0; i<ndata; ++i)
|
||||
{
|
||||
datad[i] = dataf[i];
|
||||
datal[i] = dataf[i];
|
||||
}
|
||||
shape_t axes;
|
||||
for (size_t i=0; i<shape.size(); ++i)
|
||||
axes.push_back(i);
|
||||
auto resl = datal;
|
||||
auto resd = datad;
|
||||
auto resf = dataf;
|
||||
c2c(shape, stridel, stridel, axes, FORWARD,
|
||||
datal.data(), resl.data(), 1.L);
|
||||
c2c(shape, strided, strided, axes, FORWARD,
|
||||
datad.data(), resd.data(), 1.);
|
||||
c2c(shape, stridef, stridef, axes, FORWARD,
|
||||
dataf.data(), resf.data(), 1.f);
|
||||
// c2c(shape, stridel, stridel, axes, POCKETFFT_BACKWARD,
|
||||
// resl.data(), resl.data(), 1.L/ndata);
|
||||
cout << l2err(resl, resf) << endl;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@
|
||||
#include "Generator.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
Generator::Generator() : m_channel("C1")
|
||||
{
|
||||
auto devices_path = files_path("/dev/usbtmc");
|
||||
bool success = false;
|
||||
|
||||
for (auto const &device_path : devices_path)
|
||||
{
|
||||
m_root_path = device_path;
|
||||
std::string response = query("*IDN?");
|
||||
response.erase(0, response.find(',') + 1);
|
||||
response.erase(response.find(','));
|
||||
|
||||
if (response == "AKIP-3409-4")
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
throw std::runtime_error("Generator (AKIP-3409-4) is not available!");
|
||||
}
|
||||
|
||||
void Generator::command(std::string const &comm) const
|
||||
{
|
||||
std::ofstream out;
|
||||
out.open(m_root_path);
|
||||
|
||||
if (!out.is_open())
|
||||
std::cerr << "**ERROR** file is not open to output." << std::endl;
|
||||
else
|
||||
{
|
||||
out << comm;
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Generator::query(std::string const &comm) const
|
||||
{
|
||||
command(comm);
|
||||
|
||||
std::string buffer;
|
||||
std::ifstream in;
|
||||
in.open(m_root_path);
|
||||
|
||||
if (!in.is_open())
|
||||
std::cerr << "**ERROR** file is not open to input." << std::endl;
|
||||
else
|
||||
{
|
||||
std::getline(in, buffer);
|
||||
in.close();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
|
||||
class Generator
|
||||
{
|
||||
public:
|
||||
Generator();
|
||||
|
||||
void command(std::string const &comm) const;
|
||||
std::string query(std::string const &comm) const;
|
||||
|
||||
void set_channel(channels ch)
|
||||
{
|
||||
m_channel = "C" + std::to_string(static_cast<ind_t>(ch));
|
||||
}
|
||||
|
||||
void buzz()
|
||||
{
|
||||
command("BUZZ ON");
|
||||
}
|
||||
|
||||
void set_waveform(std::string waveform)
|
||||
{
|
||||
command(m_channel + ":BSWV WVTP," + waveform);
|
||||
}
|
||||
|
||||
void set_frequency(double frequency)
|
||||
{
|
||||
command(m_channel + ":BSWV FRQ," + std::to_string(frequency));
|
||||
}
|
||||
|
||||
void set_period(double period)
|
||||
{
|
||||
command(m_channel + ":BSWV PERI," + std::to_string(period));
|
||||
}
|
||||
|
||||
void set_amplitude(double amplitude)
|
||||
{
|
||||
command(m_channel + ":BSWV AMP," + std::to_string(amplitude));
|
||||
}
|
||||
|
||||
void set_offset(double offset)
|
||||
{
|
||||
command(m_channel + ":BSWV OFST," + std::to_string(offset));
|
||||
}
|
||||
|
||||
void set_phase(double phase)
|
||||
{
|
||||
command(m_channel + ":BSWV PHSE," + std::to_string(phase));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_root_path;
|
||||
std::string m_channel;
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
CC=g++
|
||||
CFLAGS=-c
|
||||
EXECUTABLE=start
|
||||
|
||||
all: $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): main.o Generator.o Oscilloscope.o
|
||||
$(CC) main.o Generator.o Oscilloscope.o -o main
|
||||
|
||||
main.o: main.cpp
|
||||
$(CC) $(CFLAGS) main.cpp
|
||||
|
||||
Generator.o: Generator.cpp Generator.hpp
|
||||
$(CC) $(CFLAGS) Generator.cpp
|
||||
|
||||
Oscilloscope.o: Oscilloscope.cpp Oscilloscope.hpp
|
||||
$(CC) $(CFLAGS) Oscilloscope.cpp
|
||||
|
||||
clean:
|
||||
rm -f main
|
||||
rm -f *.o
|
||||
|
||||
.PNONY: all clean
|
@ -1,128 +0,0 @@
|
||||
#include "Oscilloscope.hpp"
|
||||
|
||||
Oscilloscope::Oscilloscope(std::string server_ip, port_t server_port) : m_channel("C1")
|
||||
{
|
||||
// setup a socket and connection tools
|
||||
struct hostent *host = gethostbyname(server_ip.c_str());
|
||||
|
||||
sockaddr_in sendSockAddr;
|
||||
bzero((char *)&sendSockAddr, sizeof(sendSockAddr));
|
||||
sendSockAddr.sin_family = AF_INET;
|
||||
sendSockAddr.sin_addr.s_addr =
|
||||
inet_addr(inet_ntoa(*(struct in_addr *)*host->h_addr_list));
|
||||
sendSockAddr.sin_port = htons(server_port);
|
||||
|
||||
m_client_side = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// try to connect...
|
||||
int status = connect(m_client_side,
|
||||
(sockaddr *)&sendSockAddr, sizeof(sendSockAddr));
|
||||
|
||||
if (status < 0)
|
||||
throw std::runtime_error("Error connecting to oscilloscope!");
|
||||
|
||||
std::cout << "Connected to the oscilloscope!" << std::endl;
|
||||
|
||||
char *msg = new char[256];
|
||||
recv(m_client_side, msg, 256, 0);
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
std::string Oscilloscope::request()
|
||||
{
|
||||
size_t msg_size = 256;
|
||||
char buf[msg_size];
|
||||
recv(m_client_side, buf, msg_size, 0);
|
||||
|
||||
return std::string(buf, strlen(buf));
|
||||
}
|
||||
|
||||
size_t Oscilloscope::request(char *buf, size_t msg_size)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
while (bytes_read < msg_size)
|
||||
bytes_read += recv(m_client_side, std::next(buf, bytes_read), msg_size - bytes_read, 0);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
std::string Oscilloscope::query(std::string const &comm)
|
||||
{
|
||||
command(comm);
|
||||
usleep(50000);
|
||||
return request();
|
||||
}
|
||||
|
||||
double Oscilloscope::parser(std::string const &comm, std::string const &to_find, std::string const &units)
|
||||
{
|
||||
std::string response = query(comm);
|
||||
|
||||
ind_t value_ind = response.find(to_find) + to_find.length() + 1;
|
||||
response.erase(0, value_ind - 1);
|
||||
|
||||
ind_t units_ind = response.find(units);
|
||||
response.erase(units_ind);
|
||||
|
||||
return std::stod(response);
|
||||
}
|
||||
|
||||
void Oscilloscope::save_waveform(std::string file_name)
|
||||
{
|
||||
std::size_t const header_size = 23;
|
||||
char *header = new char[header_size];
|
||||
|
||||
command(m_channel + ":WF? DAT2");
|
||||
request(header, header_size);
|
||||
|
||||
// calculate bytes count to read
|
||||
size_t pos = 14; // C1:WF DAT2,#9002800000
|
||||
size_t number = header[13] - '0';
|
||||
|
||||
std::string bytes_count_str = std::string(header, header_size).substr(pos, number);
|
||||
size_t bytes_count = std::stoi(bytes_count_str);
|
||||
|
||||
// request waveform
|
||||
char *wf = new char[bytes_count];
|
||||
request(wf, bytes_count);
|
||||
|
||||
// end values
|
||||
usleep(100000);
|
||||
auto endv = request();
|
||||
|
||||
if ((endv[0] != 10) || (endv[1] != 10) || (endv.length() != 2))
|
||||
std::cerr << "Invalid end values: " << static_cast<int>(endv[0]) << ' ' << static_cast<int>(endv[1]) << std::endl;
|
||||
|
||||
// parse waveform
|
||||
std::ofstream out;
|
||||
out.open(file_name, std::ios_base::trunc | std::ios_base::out);
|
||||
|
||||
out << "voltage,time\n";
|
||||
|
||||
double vdiv = get_vdiv() / 25.0f;
|
||||
double voffset = get_voffset();
|
||||
|
||||
double timebase = get_timebase();
|
||||
double sampling_rate = get_sampling_rate();
|
||||
|
||||
double time_inter = 1.0f / sampling_rate;
|
||||
double const grid = 14; // The grid numbers in horizontal direction
|
||||
|
||||
double time_value = -(timebase * grid / 2.0f);
|
||||
|
||||
std::cout
|
||||
<< "Vdiv: " << vdiv << std::endl
|
||||
<< "Voffset: " << voffset << std::endl
|
||||
<< "Timebase: " << timebase << std::endl
|
||||
<< "Sampling rate: " << sampling_rate << std::endl;
|
||||
|
||||
for (size_t i = 0; i < bytes_count; i++)
|
||||
out << wf[i] * vdiv - voffset << ',' << time_value + time_inter * i << '\n';
|
||||
|
||||
out.close();
|
||||
}
|
||||
|
||||
Oscilloscope::~Oscilloscope()
|
||||
{
|
||||
close(m_client_side);
|
||||
std::cout << "Connection closed" << std::endl;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
class Oscilloscope
|
||||
{
|
||||
public:
|
||||
Oscilloscope(std::string server_ip = "10.11.13.220", port_t server_port = 5024);
|
||||
|
||||
size_t command(std::string const &comm)
|
||||
{
|
||||
return send(m_client_side, comm.c_str(), comm.length(), 0);
|
||||
}
|
||||
|
||||
std::string request();
|
||||
size_t request(char *buf, size_t msg_size);
|
||||
std::string query(std::string const& comm);
|
||||
|
||||
void set_channel(channels ch)
|
||||
{
|
||||
m_channel = "C" + std::to_string(static_cast<ind_t>(ch));
|
||||
}
|
||||
|
||||
double parser(std::string const& comm, std::string const& to_find, std::string const& units);
|
||||
|
||||
double get_vdiv()
|
||||
{
|
||||
return parser(m_channel + ":VDIV?", "VDIV", "V");
|
||||
}
|
||||
|
||||
double get_voffset()
|
||||
{
|
||||
return parser(m_channel + ":OFST?", "OFST", "V");
|
||||
}
|
||||
|
||||
double get_timebase()
|
||||
{
|
||||
return parser("TDIV?", "TDIV", "S");
|
||||
}
|
||||
|
||||
double get_sampling_rate()
|
||||
{
|
||||
return parser("SARA?", "SARA", "Sa/s");
|
||||
}
|
||||
|
||||
void save_waveform(std::string file_name = "waveform.csv");
|
||||
|
||||
~Oscilloscope();
|
||||
|
||||
private:
|
||||
int m_client_side;
|
||||
std::string m_channel;
|
||||
};
|
@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using port_t = std::size_t;
|
||||
using ind_t = std::size_t;
|
||||
|
||||
enum class channels
|
||||
{
|
||||
C1 = 1,
|
||||
C2 = 2
|
||||
};
|
||||
|
||||
std::vector<std::string> files_path(std::string const &path)
|
||||
{
|
||||
size_t file_ind = path.find_last_of('/') + 1;
|
||||
std::string directory = path;
|
||||
directory.erase(file_ind);
|
||||
|
||||
auto directory_iterator = fs::directory_iterator(directory);
|
||||
std::vector<std::string> files_path;
|
||||
|
||||
for (const auto &directory_entry : directory_iterator)
|
||||
{
|
||||
auto filename = std::string(directory_entry.path());
|
||||
std::cout << filename << std::endl;
|
||||
if (!filename.find(path))
|
||||
files_path.push_back(filename);
|
||||
}
|
||||
|
||||
return files_path;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#include "Device.hpp"
|
||||
|
||||
|
||||
Device::Device(std::string path_name) : root_path("/dev/" + path_name)
|
||||
{
|
||||
std::string response = query("*IDN?");
|
||||
response.erase(0, response.find(',') + 1);
|
||||
response.erase(response.find(','));
|
||||
|
||||
name = response;
|
||||
}
|
||||
|
||||
void Device::command(std::string const &comm) const
|
||||
{
|
||||
std::ofstream out;
|
||||
out.open(root_path);
|
||||
|
||||
if (!out.is_open())
|
||||
std::cerr << "**ERROR** file is not open to output." << std::endl;
|
||||
else
|
||||
{
|
||||
out << comm;
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Device::query(std::string const &comm) const
|
||||
{
|
||||
command(comm);
|
||||
|
||||
std::string buffer;
|
||||
std::ifstream in;
|
||||
in.open(root_path);
|
||||
|
||||
if (!in.is_open())
|
||||
std::cerr << "**ERROR** file is not open to input." << std::endl;
|
||||
else
|
||||
{
|
||||
std::getline(in, buffer);
|
||||
in.close();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
#include<fstream>
|
||||
#include<iostream>
|
||||
#include<string>
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(std::string path_name);
|
||||
|
||||
std::string get_name()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void command(std::string const &comm) const;
|
||||
std::string query(std::string const &comm) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "Oscilloscope.hpp"
|
||||
|
||||
class Measurement
|
||||
{
|
||||
public:
|
||||
|
||||
Measurement() = default;
|
||||
|
||||
Measurement(std::string name_) : name(name_) { }
|
||||
|
||||
Measurement(std::string stat_response, bool)
|
||||
{
|
||||
size_t name_start = stat_response.find(" C") + 5;
|
||||
size_t name_end = stat_response.find(":");
|
||||
name = stat_response.substr(name_start, name_end - name_start);
|
||||
}
|
||||
|
||||
// private:
|
||||
std::string name;
|
||||
double mean;
|
||||
double min;
|
||||
double max;
|
||||
double std_dev;
|
||||
double count;
|
||||
};
|
@ -1 +0,0 @@
|
||||
#include "Oscilloscope.hpp"
|
@ -1,113 +0,0 @@
|
||||
#pragma once
|
||||
#include "Device.hpp"
|
||||
#include "Measurement.hpp"
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
|
||||
class Oscilloscope : public Device
|
||||
{
|
||||
public:
|
||||
Oscilloscope(std::string path_name) : Device(path_name), m_channel("C1") {}
|
||||
|
||||
void set_channel(unsigned int channel)
|
||||
{
|
||||
if (channel == 1 || channel == 2)
|
||||
m_channel = "C" + std::to_string(channel);
|
||||
else
|
||||
std::cerr << "Invalid channel" << std::endl;
|
||||
}
|
||||
|
||||
Measurement get_pkpk()
|
||||
{
|
||||
comm_param_custom("PKPK");
|
||||
comm_param_stat(1);
|
||||
|
||||
std::string response = quer_param_value("STAT1");
|
||||
comm_param_stat(0);
|
||||
|
||||
std::cout << response << std::endl;
|
||||
return Measurement(response, 1);
|
||||
}
|
||||
|
||||
void get_waveform()
|
||||
{
|
||||
command(m_channel + ":WF? DAT2");
|
||||
|
||||
usleep(1e7);
|
||||
|
||||
std::ifstream in;
|
||||
std::ofstream out;
|
||||
out.open("out.txt", std::ios_base::trunc | std::ios_base::binary | std::ios_base::out);
|
||||
in.open(root_path, std::ios_base::binary);
|
||||
// in.open(root_path, std::ios_base::binary | std::ios_base::in);
|
||||
|
||||
// if (!in.is_open())
|
||||
// throw std::runtime_error("File is not enable to write!");
|
||||
|
||||
size_t buf_size = 1400026;
|
||||
size_t cur_size = 0;
|
||||
size_t upd = 0;
|
||||
char *buffer = new char [buf_size];
|
||||
|
||||
while (in)
|
||||
{
|
||||
in.get(buffer + cur_size, buf_size);
|
||||
cur_size += in.gcount();
|
||||
if (upd != cur_size)
|
||||
{
|
||||
out.write(buffer + upd, cur_size - upd);
|
||||
std::cout << cur_size << std::endl;
|
||||
upd = cur_size;
|
||||
}
|
||||
}
|
||||
// std::cout << in.gcount() << std::endl;
|
||||
// char response = '0';
|
||||
// while (response != '#')
|
||||
// in >> response;
|
||||
|
||||
// char count_of_integers;
|
||||
// in >> count_of_integers;
|
||||
// size_t coi = count_of_integers - 48;
|
||||
|
||||
// assert(coi == 9);
|
||||
|
||||
// char *count_of_bytes = new char [coi];
|
||||
// for (size_t i = 0; i < coi; i++)
|
||||
// in >> count_of_bytes[i];
|
||||
// size_t cob = std::stoi(count_of_bytes);
|
||||
|
||||
// signed char *data = new signed char [cob];
|
||||
// for (size_t i = 0; i < cob; i++)
|
||||
// in >> data[i];
|
||||
|
||||
// char endl;
|
||||
// in >> endl;
|
||||
// // assert(endl == 10);
|
||||
|
||||
// std::cout << cob << std::endl;
|
||||
// std::cout << data[0] << std::endl;
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void comm_param_custom(std::string param)
|
||||
{
|
||||
command("PACU " + param + "," + m_channel);
|
||||
}
|
||||
|
||||
void comm_param_stat(bool condition)
|
||||
{
|
||||
command("PASTAT " + condition ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
std::string quer_param_value(std::string custom)
|
||||
{
|
||||
return query("PAVA? " + custom);
|
||||
}
|
||||
|
||||
std::string m_channel;
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
#include "Generator.hpp"
|
||||
#include "Oscilloscope.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
template <typename T>
|
||||
void func(T arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
## USB
|
||||
|
||||
1. FTDI
|
||||
2. USBTMC
|
||||
3. BULK
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
gcc gds.c -o gds -g
|
@ -1,473 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <getopt.h>
|
||||
|
||||
// Actually I don't know if oscilloscope tty is freely accessible by conventional users
|
||||
#define SETUID
|
||||
|
||||
#define GDS_BUFFER_LENGTH 1400026
|
||||
|
||||
char gds_buffer[GDS_BUFFER_LENGTH];
|
||||
int gds_buffer_length;
|
||||
|
||||
#define ERR_DEVICE_OPEN -1
|
||||
#define ERR_DEVICE_READ -2
|
||||
#define ERR_INP_FILE_OPEN -3
|
||||
#define ERR_OUT_FILE_OPEN -4
|
||||
#define ERR_INV_CHANNEL -5
|
||||
|
||||
struct record
|
||||
{
|
||||
char *keyword;
|
||||
char *value;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#define GDS_OPT_HELP 'h'
|
||||
#define GDS_OPT_ASCII 'a'
|
||||
#define GDS_OPT_BINARY 'b'
|
||||
#define GDS_OPT_CONVERT 'c'
|
||||
#define GDS_OPT_ACQUIRE 'g'
|
||||
#define GDS_OPT_NO_HDR 'r'
|
||||
#define GDS_OPT_INPUT 'i'
|
||||
#define GDS_OPT_OUTPUT 'o'
|
||||
#define GDS_OPT_DEVICE 'd'
|
||||
#define GDS_OPT_CHANNEL 'n'
|
||||
|
||||
static const struct option gds_long_opt[] =
|
||||
{
|
||||
{"help", no_argument, NULL, GDS_OPT_HELP},
|
||||
{"ascii", no_argument, NULL, GDS_OPT_ASCII},
|
||||
{"binary", no_argument, NULL, GDS_OPT_BINARY},
|
||||
{"convert", no_argument, NULL, GDS_OPT_CONVERT},
|
||||
{"acquire", no_argument, NULL, GDS_OPT_ACQUIRE},
|
||||
{"no-hdr", no_argument, NULL, GDS_OPT_NO_HDR},
|
||||
{"input", required_argument, NULL, GDS_OPT_INPUT},
|
||||
{"output", required_argument, NULL, GDS_OPT_OUTPUT},
|
||||
{"device", required_argument, NULL, GDS_OPT_DEVICE},
|
||||
{"channel", required_argument, NULL, GDS_OPT_CHANNEL},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
static const char* gds_opt_str = "abcghri:o:d:n:";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
double gds_scan_double_key(char *str, struct record *keys, int max_keys)
|
||||
{
|
||||
int curr_key;
|
||||
double result;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (!strcmp(keys[curr_key].keyword, str))
|
||||
{
|
||||
sscanf(keys[curr_key].value, "%lf", &result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_scan_int_key(char *str, struct record *keys, int max_keys)
|
||||
{
|
||||
int curr_key;
|
||||
int result;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (!strcmp(keys[curr_key].keyword, str))
|
||||
{
|
||||
sscanf(keys[curr_key].value, "%d", &result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_acquire(char *dev_file_name, int channel_number)
|
||||
{
|
||||
int dev_fd;
|
||||
int error;
|
||||
#ifdef SETUID
|
||||
int old_uid, old_gid;
|
||||
int uid_changed = 0;
|
||||
#endif // SETUID
|
||||
struct termios old_dev_tio, new_dev_tio;
|
||||
|
||||
fd_set dev_read_fds;
|
||||
struct timeval dev_tv;
|
||||
|
||||
char *dev_cmd_read_request = (channel_number == 1) ? "C1:WF? DAT2\n" : "C2:WF? DAT2\n";
|
||||
|
||||
int dev_data_index = 0;
|
||||
int dev_read_len;
|
||||
|
||||
#ifdef SETUID
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0) // check if we have permissions
|
||||
{
|
||||
old_uid = getuid(); old_gid = getgid();
|
||||
if (setuid(0) || setgid(0))
|
||||
{
|
||||
fprintf(stderr, "**Error**: You have no permissions to access \"%s\"\n"
|
||||
" Setting UID and GID to root failed\n", dev_file_name);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
|
||||
uid_changed = 1;
|
||||
// already root:wheel
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening device \"%s\"\n", dev_file_name);
|
||||
setuid(old_uid); setgid(old_gid);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
}
|
||||
#else // SETUID
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening device \"%s\"\n", dev_file_name);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
#endif // SETUID
|
||||
|
||||
tcgetattr(dev_fd, &old_dev_tio);
|
||||
bzero(&new_dev_tio, sizeof(new_dev_tio));
|
||||
new_dev_tio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
|
||||
new_dev_tio.c_iflag = IGNBRK | IXON | IXOFF;
|
||||
new_dev_tio.c_oflag = 0;
|
||||
new_dev_tio.c_lflag = 0;
|
||||
new_dev_tio.c_cc[VTIME] = 5;
|
||||
new_dev_tio.c_cc[VMIN] = 1;
|
||||
new_dev_tio.c_ispeed = 13;
|
||||
new_dev_tio.c_ospeed = 13;
|
||||
tcflush(dev_fd, TCIFLUSH);
|
||||
tcsetattr(dev_fd, TCSANOW, &new_dev_tio);
|
||||
|
||||
write(dev_fd, dev_cmd_read_request, strlen(dev_cmd_read_request));
|
||||
|
||||
FD_ZERO(&dev_read_fds);
|
||||
FD_SET(dev_fd, &dev_read_fds);
|
||||
|
||||
while (1)
|
||||
{
|
||||
dev_tv.tv_sec = 0;
|
||||
dev_tv.tv_usec = 200000;
|
||||
error = select(dev_fd + 1, &dev_read_fds, NULL, NULL, &dev_tv);
|
||||
switch(error)
|
||||
{
|
||||
case -1:
|
||||
fprintf(stderr, "**Error**: Error reading from device: select() failed with errorcode %d\n", error);
|
||||
close(dev_fd);
|
||||
return ERR_DEVICE_READ;
|
||||
case 0:
|
||||
close(dev_fd);
|
||||
gds_buffer_length = dev_data_index;
|
||||
#ifdef SETUID
|
||||
if (uid_changed) // reset uid/gid to create files belonging to current user but not root
|
||||
{
|
||||
setuid(old_uid);
|
||||
setgid(old_gid);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
default:
|
||||
dev_read_len = read(dev_fd, gds_buffer + dev_data_index, GDS_BUFFER_LENGTH - dev_data_index);
|
||||
dev_data_index += dev_read_len;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_save_binary_file(char *filename)
|
||||
{
|
||||
int out_fd;
|
||||
|
||||
if ((out_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening output file %s\n", filename);
|
||||
return ERR_OUT_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
fchmod(out_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); // set 644 mode
|
||||
write(out_fd, gds_buffer, gds_buffer_length);
|
||||
close(out_fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_read_binary_file(char *filename)
|
||||
{
|
||||
int in_fd;
|
||||
|
||||
if ((in_fd = open(filename, O_RDONLY)) == 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening data file \"%s\"\n", filename);
|
||||
return ERR_INP_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
gds_buffer_length = read(in_fd, gds_buffer, GDS_BUFFER_LENGTH);
|
||||
close(in_fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_save_ascii_file(char *filename, int header_flag)
|
||||
{
|
||||
#define MAX_KEYS 30
|
||||
struct record keys[MAX_KEYS];
|
||||
char *data_ptr;
|
||||
int i, header_length, curr_key, max_keys, max_key_len;
|
||||
double curr_time;
|
||||
FILE *out_file;
|
||||
|
||||
union {
|
||||
short s;
|
||||
char b[2];
|
||||
} short_val;
|
||||
|
||||
int Memory_Length;
|
||||
double Vertical_Scale;
|
||||
double Horizontal_Position;
|
||||
double Sampling_Period;
|
||||
|
||||
if (( out_file = fopen(filename, "wt")) == NULL)
|
||||
{
|
||||
printf("**Error**: Error opening output file \"%s\"\n", filename);
|
||||
return ERR_OUT_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
for(i = 0; i < GDS_BUFFER_LENGTH; i++)
|
||||
{
|
||||
if (gds_buffer[i] == 10)
|
||||
{
|
||||
gds_buffer[i] = 0;
|
||||
header_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (curr_key = 0; curr_key < MAX_KEYS; curr_key++)
|
||||
{
|
||||
keys[curr_key].keyword = NULL;
|
||||
keys[curr_key].value = NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for(curr_key = 0; curr_key < MAX_KEYS; curr_key++)
|
||||
{
|
||||
keys[curr_key].keyword = gds_buffer + i;
|
||||
for( ; ; i++)
|
||||
{
|
||||
if (gds_buffer[i] == 0)
|
||||
{
|
||||
max_keys = curr_key;
|
||||
goto keys_done;
|
||||
}
|
||||
if (gds_buffer[i] == ',')
|
||||
{
|
||||
keys[curr_key].value = gds_buffer + i + 1;
|
||||
gds_buffer[i] = 0;
|
||||
}
|
||||
if (gds_buffer[i] == ';')
|
||||
{
|
||||
keys[curr_key + 1].keyword = gds_buffer + i + 1;
|
||||
gds_buffer[i] = 0;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
keys_done:
|
||||
|
||||
if (header_flag) // put header
|
||||
{
|
||||
max_key_len = 0;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (strlen(keys[curr_key].keyword) > max_key_len)
|
||||
{
|
||||
max_key_len = strlen(keys[curr_key].keyword);
|
||||
}
|
||||
}
|
||||
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
fprintf(out_file, "# \"%s\" ", keys[curr_key].keyword);
|
||||
for (i = 0; i < max_keys - strlen(keys[curr_key].keyword); i++)
|
||||
{
|
||||
fprintf(out_file, " ");
|
||||
}
|
||||
fprintf(out_file, "\"%s\"\n", keys[curr_key].value ? keys[curr_key].value : "");
|
||||
}
|
||||
fprintf(out_file, "\n");
|
||||
}
|
||||
|
||||
Memory_Length = gds_scan_int_key ("Memory Length", keys, max_keys);
|
||||
Vertical_Scale = gds_scan_double_key("Vertical Scale", keys, max_keys);
|
||||
Horizontal_Position = gds_scan_double_key("Horizontal Position", keys, max_keys);
|
||||
Sampling_Period = gds_scan_double_key("Sampling Period", keys, max_keys);
|
||||
|
||||
curr_time = -(double)Memory_Length * Sampling_Period / 2.0 + Horizontal_Position;
|
||||
|
||||
data_ptr = gds_buffer + header_length + 10; // skip #72000000
|
||||
fprintf(out_file, "# Time, s\tReading, raw\tReading, V\n");
|
||||
for (i = 0; i < Memory_Length; i++)
|
||||
{
|
||||
short_val.b[0] = data_ptr[2*i+1];
|
||||
short_val.b[1] = data_ptr[2*i];
|
||||
fprintf(out_file, "%le\t%d\t\t%le\n", curr_time, short_val.s, short_val.s * Vertical_Scale * 10.0 / 256.0);
|
||||
curr_time += Sampling_Period;
|
||||
}
|
||||
|
||||
fclose(out_file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
void usage(void)
|
||||
{
|
||||
#ifdef SETUID
|
||||
#define SETUID_STATE "SETUID"
|
||||
#else // SETUID
|
||||
#define SETUID_STATE
|
||||
#endif // SETUID
|
||||
printf("gds [-abcgh] [-i <filename>] [-o <filename>] [-d <devname>]\n"
|
||||
"GDS-72302 oscilloscope data retrieving program " SETUID_STATE "\n"
|
||||
"(C) S. Ambrozevich <s.ambrozevich@mail.ru>, LPI\n"
|
||||
"v. 0.3 compiled " __DATE__ " " __TIME__ "\n\n"
|
||||
"Options:\n"
|
||||
" -c, --convert - convert previously saved binary data to ASCII form\n"
|
||||
" -g, --acquire - gather data from oscilloscope (default)\n"
|
||||
" -r, --no-hdr - do not store header information in ASCII output\n"
|
||||
" -a, --ascii - generate output in ASCII form\n"
|
||||
" -b, --binary - generate output in binary form (raw data)\n"
|
||||
" -i, --input=file - input file to convert, default = stdin\n"
|
||||
" -o, --output=file - output file to store data, default = stdout\n"
|
||||
" -d, --device=dev - device tty to communicate with, default = /dev/ttyACM0\n"
|
||||
" -n, --channel=n - channel number <1|2> to acquire, default = 2\n"
|
||||
" -h, --help - prints this help\n\n"
|
||||
"NOTE: \"gds -cb\" will only copy input binary stream to output\n");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int errorcode;
|
||||
int ascii_flag = 1;
|
||||
int convert_flag = 0;
|
||||
int header_flag = 1;
|
||||
int input_file_flag = 0;
|
||||
int output_file_flag = 0;
|
||||
int device_file_flag = 0;
|
||||
int channel_number = 2;
|
||||
int opt, opt_ind;
|
||||
|
||||
char *input_file;
|
||||
char *output_file;
|
||||
char *device_file;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, gds_opt_str, gds_long_opt, NULL)) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case GDS_OPT_ASCII:
|
||||
ascii_flag = 1;
|
||||
break;
|
||||
|
||||
case GDS_OPT_BINARY:
|
||||
ascii_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_CONVERT:
|
||||
convert_flag = 1;
|
||||
break;
|
||||
|
||||
case GDS_OPT_ACQUIRE:
|
||||
convert_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_NO_HDR:
|
||||
header_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_DEVICE:
|
||||
device_file_flag = 1;
|
||||
device_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_INPUT:
|
||||
input_file_flag = 1;
|
||||
input_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_OUTPUT:
|
||||
output_file_flag = 1;
|
||||
output_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_CHANNEL:
|
||||
sscanf(optarg, "%d", &channel_number);
|
||||
if ((channel_number < 1) || (channel_number > 2))
|
||||
{
|
||||
fprintf(stderr, "**Error**: Invalid channel number %d\n", channel_number);
|
||||
return ERR_INV_CHANNEL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (convert_flag)
|
||||
{ // convert
|
||||
if (errorcode = gds_read_binary_file(input_file_flag ? input_file : "/dev/stdin") != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
} else
|
||||
{ // read
|
||||
if (errorcode = gds_acquire(device_file_flag ? device_file : "/dev/ttyACM0", channel_number) != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii_flag)
|
||||
{ // write ascii
|
||||
if (errorcode = gds_save_ascii_file(output_file_flag ? output_file : "/dev/stdout", header_flag) != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
} else
|
||||
{ // write binary
|
||||
if (errorcode = gds_save_binary_file(output_file_flag ? output_file : "/dev/stdout") != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
|
||||
# Time, s Reading, raw Reading, V
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
#works only for ascii files with headers
|
||||
#prints every 100th line
|
||||
cat $1 | sed '1,/Waveform/d' | awk '!(NR%100)||(NR==2)'> $2
|
Loading…
Reference in New Issue
Block a user