Skip to content
Snippets Groups Projects
Commit 63328ad9 authored by Christian Koernig's avatar Christian Koernig
Browse files

working implementation for UDP and USB connection as well as a basic simulation mode

parent e89c14d3
Branches
Tags
No related merge requests found
Showing
with 24075 additions and 1 deletion
*.pyc
__pycache__
build
AmptekHardwareInterface AmptekHardwareInterface
======================= =======================
Implementation of the DP5 Protocol for communication with Amptek X-Ray detectors Communication interface for Amptek PX5 as a new backend for a Tango Device Server.
This interface will be designed to work with both, USB and UDP connection. It is based on the original AmptekPX5 Tango Device Server.
Current Plan is, to strip the connection-dependent part to seperate comm handlers for USB and UDP and use common code for everything except receiving and sending of the packets.
The Tango Server will the be implemented using python and SWIG. This is based on the much more modern design of Tango device servers in python resulting in a better readability and development. No need for code generators!
Install
-------
Run
python setup.py install
TODOs
------
- propagde the device state properly up to tango
- verify correct error handling
- add comments, docs
#ifndef AmptekConnectionHandler_h
#define AmptekConnectionHandler_h
#include "packet.h"
class AmptekConnectionHandler{
public:
virtual ~AmptekConnectionHandler(){};
virtual Packet sendAndReceive( const Packet& request) = 0;
virtual void ClearCommunicationBuffer() = 0;
};
#endif
\ No newline at end of file
#ifndef AmptekHardwareInterface_h
#define AmptekHardwareInterface_h
#include "types.h"
#include <chrono>
#include "AmptekConnectionHandler.h"
#define STATUS_SIZE 64
#define SPECLEN 8192
enum AmptekState{
NOT_CONNECTED,
ON,
RECORDING,
ERROR
};
class AmptekHardwareInterface{
public:
AmptekHardwareInterface();
~AmptekHardwareInterface();
void connectUSB(int serialNb);
void connectSimulator();
void connectUDP(std::string hostname, int port, double timeout);
//bool readStatus(const byte*, int&, double max_age_ms = -1);
const byte* readSpectrum(double max_age_ms = -1);
const byte* readSpectrumAndStatus(const byte* statusbuffer, double max_age_ms = -1);
bool Enable();
bool Disable();
bool Ping();
bool ClearSpectrum();
bool SetPresetAccumulationTime(double t);
bool SetPresetRealTime(double t);
bool SetPresetCounts(int c);
bool SetTextConfiguration(std::vector<std::string> commands);
bool UpdateStatus() {return updateStatus(-1);};
int FastCount(double max_age_ms = 100);
int SlowCount(double max_age_ms = 100);
double DeadTime(double max_age_ms = 100);
double AccTime(double max_age_ms = 100);
double RealTime(double max_age_ms = 100);
int FirmwareMajor(double max_age_ms = 1000000);
int FirmwareMinor(double max_age_ms = 1000000);
int FirmwareBuild(double max_age_ms = 1000000);
int FpgaMajor(double max_age_ms = 1000000);
int FpgaMinor(double max_age_ms = 1000000);
int SerialNb(double max_age_ms = 1000000);
double HighVoltage(double max_age_ms = 100);
double DetectorTemp(double max_age_ms = 100);
int BoardTemp(double max_age_ms = 100);
bool IsPresetTimeReached(double max_age_ms = 100);
bool IsEnabled(double max_age_ms = 100);
bool IsPresetCountReached(double max_age_ms = 100);
bool IsGated(double max_age_ms = 100);
int FpgaClock(double max_age_ms = 100);
int DeviceType(double max_age_ms = 1000000);
double TecVoltage(double max_age_ms = 100);
int GetSpectrum(unsigned int* spectrum, double max_age_ms = 100);
std::vector<unsigned int> GetSpectrum(double max_age_ms = 100);
std::vector<std::string> GetTextConfiguration(std::vector<std::string> commands);
AmptekState GetState() const {return current_state;};
private:
bool spectrumAgeOk( double max_age_ms ) const;
bool statusAgeOk( double max_age_ms ) const;
bool updateStatus(double max_age_ms );
bool updateSpectrum( double max_age_ms);
void expectAcknowledge(Packet);
byte last_status[STATUS_SIZE];
unsigned int last_spectrum[SPECLEN];
unsigned int spectrum_length = 0;
std::chrono::time_point<std::chrono::system_clock> last_status_update_time;
std::chrono::time_point<std::chrono::system_clock> last_spectrum_update_time;
AmptekState current_state = NOT_CONNECTED;
AmptekConnectionHandler* connection_handler = nullptr;
};
#endif
\ No newline at end of file
#ifndef AmptekSimulatorConnectionHandler_h
#define AmptekSimulatorConnectionHandler_h
#include "AmptekConnectionHandler.h"
#include <thread> // std::thread
#define STATUS_SIZE 64
class AmptekSimulatorConnectionHandler : public AmptekConnectionHandler{
public:
AmptekSimulatorConnectionHandler();
virtual ~AmptekSimulatorConnectionHandler();
virtual Packet sendAndReceive( const Packet& request);
virtual void ClearCommunicationBuffer(){};
private:
void readConfig(char* configs);
void createStatusData(byte* buffer);
void createSpectrumData(byte* buffer);
void enable();
void disable();
void clear();
int speclen = 1024;
unsigned int* spectrum;
uint32_t total_counts;
double acc_time = 0;
bool is_running = true;
bool is_enabled = false;
bool flag_enable = false;
bool flag_disable = false;
double acquisition_time = -1;
std::thread* spectrum_thread;
};
#endif
\ No newline at end of file
#ifndef AmptekUdpConnectionHandler_h
#define AmptekUdpConnectionHandler_h
#include "AmptekConnectionHandler.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <semaphore.h>
#define MAX_UDP_PACKET_SIZE 520
class AmptekUdpConnectionHandler : public AmptekConnectionHandler{
public:
AmptekUdpConnectionHandler(std::string hostname, int port, double timeout);
virtual ~AmptekUdpConnectionHandler();
virtual Packet sendAndReceive( const Packet& request);
virtual void ClearCommunicationBuffer();
private:
int sockfd;
unsigned int addrlength;
struct sockaddr_in server, from;
struct hostent *host;
sem_t mu;
};
#endif
\ No newline at end of file
#ifndef AmptekUsbConnectionHandler_h
#define AmptekUsbConnectionHandler_h
#include "AmptekConnectionHandler.h"
#include "libusb-1.0/libusb.h"
#define MAX_USB_OUT_PACKET_SIZE 520
#define MAX_USB_IN_PACKET_SIZE 32768 //defined by the amptek standard
#define PX5_USB_BULK_IN_ENDPOINT 0x81
#define PX5_USB_BULK_OUT_ENDPOINT 0x02
#define PX5_USB_INTERFACE_NUMBER 0
#define PX5_USB_VENDOR_ID 0x10C4
#define PX5_USB_PRODUCT_ID 0x842A
class AmptekUsbConnectionHandler : public AmptekConnectionHandler{
public:
AmptekUsbConnectionHandler(int serialNb);
virtual ~AmptekUsbConnectionHandler();
virtual Packet sendAndReceive( const Packet& request);
virtual void ClearCommunicationBuffer();
private:
libusb_device_handle* usb_handle = nullptr;
bool isAmptekPX5(libusb_device_descriptor* desc);
bool hasSerialNb(libusb_device_handle* handle, int target_serial_nb);
std::string libusb_errorcode(int error);
void CloseUsbDevice(libusb_device_handle * devh);
byte* input_buffer;
};
#endif
\ No newline at end of file
#ifndef PACKET_H
#define PACKET_H
#include <vector>
#include <string>
#include <sstream>
#include "types.h"
#define MIN_PACKET_LEN 8
using namespace std;
enum Offset
{
SYNC1,
SYNC2,
PID1,
PID2,
LEN_MSB,
LEN_LSB,
DATA
};
enum PID1_TYPE{
PX5_RESPONSE_STATUS = 0x80,
PX5_RESPONSE_SPECTRUM = 0x81,
PX5_RESPONSE_CONFIG = 0x82,
PX5_RESPONSE_COMMTEST = 0x8F,
PX5_ACK = 0xFF,
PX5_REQUEST_CONFIG =0x20
};
enum STATUS_PACKET_TYPES{
PX5_RESPONSE_STATUS_INFO = 0x01,
};
enum SPECTRUM_PACKET_TYPES{
PX5_RESPONSE_SPECTRUM256 = 0x01,
PX5_RESPONSE_SPECTRUM256_STATUS = 0x02,
PX5_RESPONSE_SPECTRUM512 = 0x03,
PX5_RESPONSE_SPECTRUM512_STATUS = 0x04,
PX5_RESPONSE_SPECTRUM1024 = 0x05,
PX5_RESPONSE_SPECTRUM1024_STATUS = 0x06,
PX5_RESPONSE_SPECTRUM2048 = 0x07,
PX5_RESPONSE_SPECTRUM2048_STATUS = 0x08,
PX5_RESPONSE_SPECTRUM4096 = 0x09,
PX5_RESPONSE_SPECTRUM4096_STATUS = 0x0A,
PX5_RESPONSE_SPECTRUM8192 = 0x0B,
PX5_RESPONSE_SPECTRUM8192_STATUS = 0x0C,
};
enum CONFIG_PACKET_TYPES{
PX5_RESPONSE_CONFIG_TEXT = 0x07,
PX5_REQUEST_SET_CONFIG = 0x02,
PX5_REQUEST_GET_CONFIG = 0x03,
};
enum COMMTEST_PACKET_TYPES{
PX5_RESPONSE_COMMETEST_ECHO = 0x7F,
};
enum ACK_PACKET_TYPES{
PX5_ACK_OK = 0x00,
PX5_ACK_SYNC_ERR = 0x01,
PX5_ACK_PID_ERR = 0x02,
PX5_ACK_LEN_ERR = 0x03,
PX5_ACK_CHECKSUM_ERR = 0x04,
PX5_ACK_BADPARAM_ERR = 0x05,
PX5_ACK_BADHEX_ERR = 0x06,
PX5_ACK_BADCMD_ERR = 0x07,
PX5_ACK_FPGA_ERR = 0x08,
PX5_ACK_CP2201_ERR = 0x09,
PX5_ACK_SCOPE_ERR = 0x0A,
PX5_ACK_PC5_ERR = 0x0B,
PX5_ACK_OK_SHARING = 0x0C,
PX5_ACK_BUSY_ERR = 0x0D,
PX5_ACK_I2C_ERR = 0x0E,
PX5_ACK_OK_FPGAADDR = 0x0F,
PX5_ACK_VERSION_ERR = 0x10,
PX5_ACK_CALIB_ERR = 0x11
};
class AmptekException : public std::runtime_error
{
public:
AmptekException(std::string what) : runtime_error(what){}
~AmptekException(){}
};
class Packet: public vector<byte>
{
friend class vector;
public:
Packet();
Packet(unsigned short initSize);
Packet(byte pid1, byte pid2, byte* data, word16 datasize);
word16 dataLength;
void initSync();
void setPid1(byte p1);
void setPid2(byte p2);
word16 calcLen() const;
word16 calcChecksum() const;
void calcAndFillChecksum();
void validateChecksum();
void setData(byte* data, word16 size);
string toString() const;
void fromByteArray(byte* response);
bool isType( word16 );
bool isType( std::vector<word16> );
bool isType( byte, byte );
public:
static const Packet PX5_REQUEST_SPECTRUM;
static const Packet PX5_REQUEST_SPECTRUM_AND_STATUS;
static const Packet PX5_REQUEST_STATUS;
static const Packet PX5_REQUEST_ENABLE;
static const Packet PX5_REQUEST_DISABLE;
static const Packet PX5_REQUEST_CLEAR_SPECTRUM;
static const Packet PX5_REQUEST_SET_CONFIG;
static const Packet PX5_REQUEST_GET_CONFIG;
static const Packet PX5_REQUEST_KEEP_ALIVE_NO_SHARING;
static const Packet gernerateSetConfigurationRequest(std::string text_configuration);
static const Packet gernerateGetConfigurationRequest(std::string text_configuration);
};
#endif
#ifndef TYPES_H
#define TYPES_H
#include <stdio.h>
typedef unsigned char byte; // Byte is a char
typedef unsigned short int word16; // 16-bit word is a short int
typedef signed short int signed_word16; // 16-bit word is a short int
typedef unsigned int word32; // 32-bit word is an int
void charToByte(char* chars, byte* bytes, unsigned int count);
void charToByte(const char* chars, byte* bytes, unsigned int count);
void byteToChar(byte* bytes, char* chars, unsigned int count);
word16 twosComplement(word16 number);
byte lsbyte(word16 number);
byte msbyte(word16 number);
inline word16 mergeBytes(byte msbyte, byte lsbyte)
{
word16 number = msbyte;
// printf("mergeBytes(): msbyte = %d; lsbyte = %d\n", msbyte, lsbyte);
number <<= 8;
// printf("mergeBytes(): number = %d\n", number);
number += lsbyte;
// printf("mergeBytes(): number = %d\n", number);
return number;
}
inline word32 mergeWords(word16 msword, word16 lsword){
word32 number = msword;
// printf("mergeWords(): msword = %d; lsword = %d\n", msword, lsword);
number <<= 16;
// printf("mergeWords(): number = %d\n", number);
number += lsword;
// printf("mergeWords(): number = %d\n", number);
return number;
}
unsigned int mergeBytes(byte msb, byte b, byte lsb);
unsigned int mergeBytes(byte msb, byte mb, byte lb, byte lsb);
#endif
\ No newline at end of file
main.cpp 0 → 100644
#include "AmptekHardwareInterface.h"
#include <iostream>
int main(int argc, char** argv){
std::cout << "Create Interface.." << std::endl;
AmptekHardwareInterface amptek;
std::cout << "Connect via UDP.." << std::endl;
amptek.connectUDP("192.168.0.10", 10001, 3.);
std::cout << "Finished" << std::endl;
}
\ No newline at end of file
%module AmptekHardwareInterface
%{
#define SWIG_FILE_WITH_INIT
#include "AmptekHardwareInterface.h"
%}
%include "numpy.i"
%include "std_string.i"
%init %{
import_array();
%}
%numpy_typemaps(unsigned int , NPY_UINT , int)
%include "stdint.i"
%include "std_vector.i"
%include exception.i
namespace std {
%template(IntVector) vector<int>;
%template(StringVector) vector<std::string>;
%template(DoubleVector) vector<double>;
%template(UIntVector) vector<unsigned int>;
}
%except {
try {
$function
} catch(RangeError) {
SWIG_exception(SWIG_ValueError, "Range Error");
} catch(DivisionByZero) {
SWIG_exception(SWIG_DivisionByZero, "Division by zero");
} catch(OutOfMemory) {
SWIG_exception(SWIG_MemoryError, "Out of memory");
} catch(AmptekException) {
SWIG_exception(SWIG_RuntimeError, "Amptek Error");
} catch(...) {
SWIG_exception(SWIG_RuntimeError,"Unknown exception");
}
}
%include "include/AmptekHardwareInterface.h"
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
sync
pids 0x01 0x1
data of size 0
checksum
twosComplement(): original = 1f1
twosComplement(): pattern = ffff
twosComplement(): complement = fe0f
done
sync
pids 0x02 0x1
data of size 0
checksum
twosComplement(): original = 1f2
twosComplement(): pattern = ffff
twosComplement(): complement = fe0e
done
sync
pids 0x02 0x3
data of size 0
checksum
twosComplement(): original = 1f4
twosComplement(): pattern = ffff
twosComplement(): complement = fe0c
done
sync
pids 0xf0 0x1
data of size 0
checksum
twosComplement(): original = 2e0
twosComplement(): pattern = ffff
twosComplement(): complement = fd20
done
sync
pids 0xf0 0x2
data of size 0
checksum
twosComplement(): original = 2e1
twosComplement(): pattern = ffff
twosComplement(): complement = fd1f
done
sync
pids 0xf0 0x3
data of size 0
checksum
twosComplement(): original = 2e2
twosComplement(): pattern = ffff
twosComplement(): complement = fd1e
done
sync
pids 0xf0 0x21
data of size 0
checksum
twosComplement(): original = 300
twosComplement(): pattern = ffff
twosComplement(): complement = fd00
done
Sent 8 bytes: SYNC1 = f5 SYNC2 = fa
PID1 = f0 PID2 = 21
LEN_MSB = 0 LEN_LSB = 0
CHECKSUM_MSB = fd CHECKSUM_LSB = 0
DATA LENGTH = 0
total response packet data size: 0
in Packet::fromByteArray
dataLength: 0
twosComplement(): original = 2ee
twosComplement(): pattern = ffff
twosComplement(): complement = fd12
Sent 8 bytes: SYNC1 = f5 SYNC2 = fa
PID1 = 2 PID2 = 3
LEN_MSB = 0 LEN_LSB = 0
CHECKSUM_MSB = fe CHECKSUM_LSB = c
DATA LENGTH = 0
total response packet data size: 3136
offset at 520
Ask for 520 bytes
read 520 bytes in step
offset at 1040
Ask for 520 bytes
read 520 bytes in step
offset at 1560
Ask for 520 bytes
read 520 bytes in step
offset at 2080
Ask for 520 bytes
read 520 bytes in step
offset at 2600
Ask for 520 bytes
read 520 bytes in step
offset at 3120
Ask for 24 bytes
read 24 bytes in step
offset at 3144
in Packet::fromByteArray
dataLength: 3136
twosComplement(): original = 8b2
twosComplement(): pattern = ffff
twosComplement(): complement = f74e
3144
ping
True
fnished
This diff is collapsed.
import AmptekHardwareInterface as ahi
amptek = ahi.AmptekHardwareInterface()
#amptek.connectUDP("192.168.1.10", 10001, 1)
amptek.connectUSB(-1)
print("ping")
print( amptek.Ping() )
# print("status")
# dat= amptek.readStatus(-1)
print( "fnished" )
amptek.GetSpectrum()
config_names = ["RESC", "CLCK", "TPEA", "GAIF", "GAIN", "RESL", "TFLA", "TPFA",
"PURE", "RTDE", "MCAS", "MCAC", "SOFF", "AINP", "INOF", "GAIA",
"CUSP", "PDMD", "THSL", "TLLD", "THFA", "DACO", "DACF", "DACF",
"RTDS", "RTDT", "BLRM", "BLRD", "BLRU", "AUO1", "PRET", "PRER",
"PREC", "PRCL", "PRCH", "HVSE", "TECS", "PAPZ", "PAPS", "SCOE",
"SCOT", "SCOG", "MCSL", "MCSH", "MCST", "AUO2", "TPMO", "GPED",
"GPGA", "GPMC", "MCAE", "VOLU", "CON1", "CON2"]
print( "amptek.GetTextConfiguration( config_names )")
configs = amptek.GetTextConfiguration( config_names )
print(configs)
print(amptek.SerialNb())
print("done")
\ No newline at end of file
setup.py 0 → 100644
#! /usr/bin/env python
# System imports
from distutils.core import *
from distutils import sysconfig
# Third-party modules - we depend on numpy for everything
import numpy
import os
# Obtain the numpy include directory. This logic works across numpy versions.
try:
numpy_include = numpy.get_include()
except AttributeError:
numpy_include = numpy.get_numpy_include()
# HexitecIO extension module
_AmptekHardwareInterface = Extension("_AmptekHardwareInterface",
["python/AmptekHardwareInterface.i",] + ["src/" + f for f in os.listdir("src") if os.path.isfile("src/" + f)],
include_dirs = [numpy_include, "include"],
swig_opts=['-c++',"-modern" , "-nomodernargs"],
extra_compile_args = ["-std=c++11", "-g"],
libraries=["usb-1.0"]
)
# NumyTypemapTests setup
setup( name = "AmptekHardwareInterface function",
description = "Implementation of the Amptek DP5 Protocol",
author = "Christian Koernig",
version = "0.1",
ext_modules = [_AmptekHardwareInterface]
)
\ No newline at end of file
This diff is collapsed.
#include "AmptekSimulatorConnectionHandler.h"
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iomanip>
Packet AmptekSimulatorConnectionHandler::sendAndReceive( const Packet& request){
byte pid1 = request.at(PID1);
byte pid2 = request.at(PID2);
Packet p(MIN_PACKET_LEN);
p.initSync();
if (pid1 == Packet::PX5_REQUEST_SPECTRUM.at(PID1)
&& pid2 == Packet::PX5_REQUEST_SPECTRUM.at(PID2))
{
p.setPid1( PX5_RESPONSE_SPECTRUM );
switch (speclen){
case 256:
p.setPid2( PX5_RESPONSE_SPECTRUM256 );
break;
case 512:
p.setPid2( PX5_RESPONSE_SPECTRUM512 );
break;
case 1024:
p.setPid2( PX5_RESPONSE_SPECTRUM1024 );
break;
case 2048:
p.setPid2( PX5_RESPONSE_SPECTRUM2048 );
break;
case 4096:
p.setPid2( PX5_RESPONSE_SPECTRUM4096 );
break;
case 8192:
p.setPid2( PX5_RESPONSE_SPECTRUM8192 );
break;
}
word16 len = 3*speclen;
byte arr[len];
createSpectrumData(arr);
p.resize( MIN_PACKET_LEN + len );
p.setData(arr, len);
}
else if (pid1 == Packet::PX5_REQUEST_SPECTRUM_AND_STATUS.at(PID1)
&& pid2 == Packet::PX5_REQUEST_SPECTRUM_AND_STATUS.at(PID2))
{
p.setPid1( PX5_RESPONSE_SPECTRUM );
switch (speclen){
case 256:
p.setPid2( PX5_RESPONSE_SPECTRUM256_STATUS );
break;
case 512:
p.setPid2( PX5_RESPONSE_SPECTRUM512_STATUS );
break;
case 1024:
p.setPid2( PX5_RESPONSE_SPECTRUM1024_STATUS );
break;
case 2048:
p.setPid2( PX5_RESPONSE_SPECTRUM2048_STATUS );
break;
case 4096:
p.setPid2( PX5_RESPONSE_SPECTRUM4096_STATUS );
break;
case 8192:
p.setPid2( PX5_RESPONSE_SPECTRUM8192_STATUS );
break;
}
word16 len = 3*speclen + STATUS_SIZE;
byte arr[len];
createSpectrumData(arr);
createStatusData(arr + 3*speclen);
p.resize( MIN_PACKET_LEN + len );
p.setData(arr, len);
}
else if (pid1 == Packet::PX5_REQUEST_STATUS.at(PID1)
&& pid2 == Packet::PX5_REQUEST_STATUS.at(PID2))
{
p.setPid1( PX5_RESPONSE_STATUS );
p.setPid2( PX5_RESPONSE_STATUS_INFO );
word16 len = STATUS_SIZE;
byte arr[len];
createStatusData(arr);
p.resize( MIN_PACKET_LEN + len );
p.setData(arr, len);
}
else if (pid1 == 0x20
&& pid2 == 0x03)
{
p.setPid1( PX5_RESPONSE_CONFIG );
p.setPid2( PX5_RESPONSE_CONFIG_TEXT );
std::stringstream configs;
configs << "MCAC=" << std::to_string(speclen) << ";PRET=";
if (acquisition_time > 0){
configs << std::setw(2) << std::fixed << acquisition_time;
} else{
configs << "OFF";
}
string configstring = configs.str();
word16 len = configstring.size();
byte arr[len];
charToByte(configstring.c_str(), arr, len);
p.resize( MIN_PACKET_LEN + len );
p.setData(arr, len);
}
else if( (pid1 == Packet::PX5_REQUEST_ENABLE.at(PID1)
&& pid2 == Packet::PX5_REQUEST_ENABLE.at(PID2)) )
{
enable();
return Packet(PX5_ACK, PX5_ACK_OK, nullptr, 0);
}
else if ( (pid1 == Packet::PX5_REQUEST_DISABLE.at(PID1)
&& pid2 == Packet::PX5_REQUEST_DISABLE.at(PID2)) )
{
disable();
return Packet(PX5_ACK, PX5_ACK_OK, nullptr, 0);
}
else if (pid1 == Packet::PX5_REQUEST_CLEAR_SPECTRUM.at(PID1)
&& pid2 == Packet::PX5_REQUEST_CLEAR_SPECTRUM.at(PID2))
{
clear();
return Packet(PX5_ACK, PX5_ACK_OK, nullptr, 0);
}
else if (pid1 == Packet::PX5_REQUEST_KEEP_ALIVE_NO_SHARING.at(PID1)
&& pid2 == Packet::PX5_REQUEST_KEEP_ALIVE_NO_SHARING.at(PID2))
{
return Packet(PX5_ACK, PX5_ACK_OK, nullptr, 0);
}
else if(pid1 == 0x20 //set Text Config
&& pid2 == 0x02)
{
char configs[ request.dataLength + 1 ];
byteToChar( (byte*)&(request.at(DATA)), configs, request.dataLength );
readConfig(configs);
return Packet(PX5_ACK, PX5_ACK_OK, nullptr, 0);
}
p.calcAndFillChecksum();
return p;
}
AmptekSimulatorConnectionHandler::AmptekSimulatorConnectionHandler(){
spectrum = new unsigned int[speclen];
clear();
spectrum_thread = new std::thread(
[&]{
auto start_time = std::chrono::system_clock::now();
while( is_running ){
if (flag_enable){
is_enabled = true;
start_time = std::chrono::system_clock::now();
flag_enable = false;
}
if (flag_disable){
is_enabled = false;
flag_disable = false;
}
if (is_enabled){
spectrum[ rand() % speclen ]++;
total_counts += 1;
auto now = std::chrono::system_clock::now();
acc_time = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() / 1000.;
if (acquisition_time > 0){
if (acc_time >= acquisition_time){
is_enabled = false;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
}
);
}
AmptekSimulatorConnectionHandler::~AmptekSimulatorConnectionHandler(){
is_running = false;
spectrum_thread->join();
delete[] spectrum;
}
void AmptekSimulatorConnectionHandler::enable(){
flag_enable = true;
}
void AmptekSimulatorConnectionHandler::disable(){
flag_disable = true;
}
void AmptekSimulatorConnectionHandler::clear(){
total_counts = 0;
acc_time = 0;
for (int i = 0; i < speclen; ++i){
spectrum[i] = 0;
}
}
void AmptekSimulatorConnectionHandler::createSpectrumData(byte* buffer){
for (int i = 0; i < speclen; ++i){
buffer[3*i] = spectrum[i] & 0xff;
buffer[3*i + 1] = spectrum[i] >> 8 & 0xff;
buffer[3*i + 2] = spectrum[i] >> 16 & 0xff;
}
}
void AmptekSimulatorConnectionHandler::createStatusData(byte* buffer){
for (int i = 0; i < STATUS_SIZE; ++i){
buffer[i] = 0;
}
//set fast count
buffer[0] = total_counts & 0xff; //lsb
buffer[1] = total_counts >> 8 & 0xff;
buffer[2] = total_counts >> 16 & 0xff;
buffer[3] = total_counts >> 24 & 0xff; //msb
//set slow count
buffer[4] = total_counts & 0xff; //lsb
buffer[5] = total_counts >> 8 & 0xff;
buffer[6] = total_counts >> 16 & 0xff;
buffer[7] = total_counts >> 24 & 0xff; //msb
//acc time
int nticks_0p1 = 10*acc_time;
int nticks_0p001 = 1000*( acc_time - nticks_0p1*0.1 );
buffer[12] = nticks_0p001;
buffer[13] = nticks_0p1 & 0xff;
buffer[14] = nticks_0p1 >> 8 & 0xff;
buffer[15] = nticks_0p1 >> 16 & 0xff;
//real time
nticks_0p001 = 1000* acc_time;
buffer[20] = nticks_0p1 & 0xff;
buffer[21] = nticks_0p1 >> 8 & 0xff;
buffer[22] = nticks_0p1 >> 16 & 0xff;
buffer[23] = nticks_0p1 >> 24 & 0xff;
// is pret reached
if (acquisition_time > 0 && (acc_time - acquisition_time) < 0.0001 && !is_enabled){
buffer[35] |= (1 << 7);
}
if (is_enabled){
buffer[35] |= (1 << 5);
}
}
void AmptekSimulatorConnectionHandler::readConfig(char* configs){
std::string config_name, config_value, configline;
std::stringstream configstream(configs);
while(std::getline(configstream, configline, ';')){
try{
std::stringstream linestream(configline);
std::getline(linestream, config_name,'=');
linestream >> config_value;
if (config_name == "MCAC"){
speclen = std::stoi(config_value);
delete[] spectrum;
spectrum = new unsigned int[speclen];
for(int i = 0; i < speclen; ++i){
spectrum[i] = 0;
}
}else if (config_name == "PRET"){
if (config_value == "OFF"){
acquisition_time = -1;
}else{
acquisition_time = std::stod( config_value );
}
}
else{
std::cout << "Ignored config " << config_name << " with value "<< config_value << std::endl;
}
}catch(...){
std::cerr << "Failed reading config " << configline << std::endl;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment