SXXXXXXX_PyBusMonitor1553/cpp/GrifoScope/GrifoXLruMonitor/xlru/xlru_manager.cpp
2025-12-17 07:59:30 +01:00

940 lines
21 KiB
C++

/*
* xlru_interface.cpp
*
*/
#include "xlru_manager.h"
#include "xlru_comm.h"
#include "xlru_lcu.h"
#include "xlru_pps.h"
#include "xlru_psm.h"
#include "xlru_message_mng.h"
#include "mrk.h"
#include "mrk_net.h"
#include "bsp_platform.h"
#include "rtlog.h"
#include <string.h>
#include <stdint.h>
#define THREAD_STACK (8*1024)
static const char LID[]="XLRU";
#if 0
struct xlru_if_msg_t
{
};
//typedef int (*xlru_command_message_encoder_t)(unsigned char* buffer, const void* opaque_data);
//extern int xlru_lcu_command_message_encoder(unsigned char* buffer, const void* opaque_data);
//extern int xlru_pps_command_message_encoder(unsigned char* buffer, const void* opaque_data);
//extern int xlru_psm_command_message_encoder(unsigned char* buffer, const void* opaque_data);
struct xlru_lcu_command_t
{
int mode;
};
struct xlru_psm_command_t
{
int mode;
};
struct xlru_pps_command_t
{
int mode;
};
#endif
//-
typedef int (*xlru_command_encoder_t)(unsigned int);
typedef int (*xlru_reply_decoder_t)(unsigned int, const char* msg, unsigned int len);
//static int dummy_command_encoder(unsigned int uid);
static int psm_command_encoder(unsigned int u);
static int lcu_command_encoder(unsigned int u);
static int pps_command_encoder(unsigned int u);
struct xlru_unit_sts_t
{
XLruManager::unit_status_t* public_sts;
#if 0
//TODO: extend with more detail for field messages
unsigned int comm_fail;
unsigned int good_message;
unsigned int fail_message;
unsigned int pending_msg;
#endif
};
enum xlru_units_t { xlru_id_broadcast=0, xlru_id_psm, xlru_id_lcu, xlru_id_pps, xlru_id_number_};
enum { xlru_number_=3};
enum xlru_id_t { DEVICE_PSM=1, DEVICE_PPS=2, DEVICE_LCU=3};
struct xlru_cx_t
{
uint64_t stack[THREAD_STACK/sizeof(uint64_t)];
mrk_thread_t thread;
mrk_mutex_t mutex;
char psm_message[1024];
char pps_message[1024];
char lcu_message[1024];
//xlru_psm_command_t psm_cmd;
//xlru_pps_command_t pps_cmd;
//xlru_lcu_command_t lcu_cmd;
xlru_unit_sts_t sts[xlru_id_number_];
XLruManager::unit_status_t invalid_unit_status;
XLruManager::psm_status_t psm_status;
XLruManager::pps_status_t pps_status;
XLruManager::lcu_status_t lcu_status;
XLruManager::manager_status_t status;
int psm_temperature;
int pps_temperature;
int lcu_temperature;
volatile int pps_cmd;
volatile int pps_unlimited;
volatile int pps_hazard;
};
struct xlru_ovr_t
{
int pps_cmd_ovr;
int pps_unlimited;
int pps_hazard;
};
static volatile xlru_ovr_t autoMonitorable_xlruovr;
static xlru_cx_t xlru_cx;
static int common_reply_decoder(unsigned int, const char* msg, unsigned int len);
struct xlru_unit_map_t
{
const char* name;
unsigned int chid;
unsigned int uid;
const char* cmd_buffer;
xlru_command_encoder_t encoder;
//xlru_reply_decoder_t reply_decoder;
int (*reply_decoder)(const xlru_message_received_t& rx_msg);
const char* sim_reply;
};
#ifdef __MINGW32__
enum { null_ch=0, psm_ch = 0, pps_ch = 0, lcu_ch = 0, ch_num=4 };
#define UDP_START_DELAY -1
#else
enum { null_ch=0, psm_ch = 1, pps_ch = 3, lcu_ch = 3, ch_num=4}; //REP ZynQ PL FPGA UART: Uart 1 = PSM, Uart 3 = PPS, LCU
#define UDP_START_DELAY 5
#endif
static int psm_reply_decoder(const xlru_message_received_t& rx_msg);
static int pps_reply_decoder(const xlru_message_received_t& rx_msg);
static int lcu_reply_decoder(const xlru_message_received_t& rx_msg);
static xlru_unit_map_t xlru_unit_map[xlru_number_]=
{
{"PSM", psm_ch, DEVICE_PSM, xlru_cx.psm_message, psm_command_encoder, psm_reply_decoder, 0},
{"PPS", pps_ch, DEVICE_PPS, xlru_cx.pps_message, pps_command_encoder, pps_reply_decoder, 0},
{"LCU", lcu_ch, DEVICE_LCU, xlru_cx.lcu_message, lcu_command_encoder, lcu_reply_decoder, 0}
};
#if 0
static int dummy_command_encoder(unsigned int u)
{
//xlru_unit_map[u].cmd_buffer="CIAO0\n";
return 0;
}
#endif
static int psm_command_encoder(unsigned int u)
{
xlru_unit_map[u].cmd_buffer=xlru_send_psm_set_message(); //xlru_unit_map[u].cmd_buffer;
return 0;
}
static int lcu_command_encoder(unsigned int u)
{
xlru_unit_map[u].cmd_buffer=xlru_send_lcu_set_message();
return 0;
}
static int pps_command_encoder(unsigned int u)
{
xlru_unit_map[u].cmd_buffer=xlru_send_pps_set_message();
return 0;
}
static void copy_status(XLruManager::unit_basic_status_t& dst, const xlru_unit_status_t& src)
{
dst.unitOk=src.unitOk;
dst.overtempWarning=src.overtempWarning;
dst.overtempHazard=src.overtempHazard;
}
static int psm_reply_decoder(const xlru_message_received_t& rx_msg)
{
if (rx_msg.valid)
{
copy_status(xlru_cx.psm_status.status.basicStatus, xlru_psm::xlru_psm_status.status);
xlru_cx.psm_temperature=xlru_psm::xlru_psm_status.temperature;
return 0;
}
return 1;
}
static int pps_reply_decoder(const xlru_message_received_t& rx_msg)
{
if (rx_msg.valid)
{
copy_status(xlru_cx.pps_status.status.basicStatus, xlru_pps::xlru_pps_status.status);
xlru_cx.pps_temperature=xlru_pps::xlru_pps_status.rx_board_temp;
switch(xlru_pps::xlru_pps_status.mode_status)
{
default:
xlru_cx.pps_status.power_sts=XLruManager::pps_power_err;
xlru_cx.pps_status.power_sts_char='E';
break;
case PPSIdle:
xlru_cx.pps_status.power_sts=XLruManager::pps_power_idle;
xlru_cx.pps_status.power_sts_char='I';
break;
case PPSIBIT:
xlru_cx.pps_status.power_sts=XLruManager::pps_power_idle;
xlru_cx.pps_status.power_sts_char='B';
break;
case PPSStandBy:
xlru_cx.pps_status.power_sts=XLruManager::pps_power_stby;
xlru_cx.pps_status.power_sts_char='S';
break;
case PPSOnGo:
if (xlru_pps::xlru_pps_status.current_limitation_status==PPSCurrentLimitation)
{
xlru_cx.pps_status.power_sts=XLruManager::pps_power_low;
xlru_cx.pps_status.power_sts_char='g';
}
else
{
xlru_cx.pps_status.power_sts=XLruManager::pps_power_full;
xlru_cx.pps_status.power_sts_char='G';
}
break;
}
xlru_cx.pps_status.warning=xlru_pps::xlru_pps_status.warning;
xlru_cx.pps_status.txPower=0;
xlru_cx.pps_status.rxPower=xlru_pps::xlru_pps_status.curr_42v;
return 0;
}
return 1;
}
static int lcu_reply_decoder(const xlru_message_received_t& rx_msg)
{
if (rx_msg.valid)
{
copy_status(xlru_cx.lcu_status.status.basicStatus, xlru_lcu::xlru_lcu_status.status);
return 0;
}
return 1;
}
static int common_reply_decoder(unsigned int pending_unit, const char* msg, unsigned int /*len*/)
{
static xlru_message_received_t message_received;
strncpy(message_received.full_message, msg, sizeof message_received.full_message);
int r=xlru_check_message(&message_received);
if (r)
{
++xlru_cx.status.error_messages;
return -1;
}
unsigned int device_id=message_received.device;
switch(device_id)
{
case DEVICE_PSM:
case DEVICE_PPS:
case DEVICE_LCU:
{
XLruManager::unit_status_t& plrusts=*xlru_cx.sts[device_id].public_sts;
if (message_received.valid)
++plrusts.commStatus.good_messages;
else
++plrusts.commStatus.error_messages;
plrusts.commStatus.reply_pending=0;
plrusts.commStatus.linkUp=true;
plrusts.commStatus.commDeviceOk=true;
xlru_unit_map_t& u=xlru_unit_map[device_id-1];
r=u.reply_decoder(message_received);
//if (r)
// plrusts.basicStatus.unitOk=false;
if (pending_unit!=device_id)
{
++plrusts.commStatus.reply_overlap;
++xlru_cx.status.received_overlapping;
}
break;
}
default:
{
XLruManager::unit_status_t& plrusts=*xlru_cx.sts[0].public_sts;
plrusts.commStatus.reply_pending=0;
++xlru_cx.status.received_invalid_unit;
r=-1;
break;
}
}
return r;
}
static bool receive(unsigned int chid, char* buffer, unsigned int& received_len)
{
const unsigned int max_len=1024;
received_len=0;
xlru_comm_sts_t r=xlru_comm_extract_pending_data(chid, buffer, &received_len, max_len);
if (r==xlru_comm_ok)
{
if (received_len>=max_len)
received_len=max_len-1;
buffer[received_len]=0;
return true;
}
else
{
if (r==xlru_comm_err_overrun)
++xlru_cx.status.overruns;
else
++xlru_cx.status.biterror;
rtlog_printf(LID, rtlog_error, "rx(%d): %d (%s)", chid, r, xlru_comm_error_string(r));
}
return false;
}
static void (*oob_handler)(char c);
class Accumulator
{
public:
enum { MAX_PENDING_SIZE=256 };
char pending_message[MAX_PENDING_SIZE+2];
unsigned int pending_pos;
unsigned int pending_len;
void initialize()
{
pending_pos=0;
pending_len=0;
}
bool accumulate(const char* buffer, unsigned int len)
{
for(unsigned int i=0; i<len; ++i)
{
++xlru_cx.status.received_bytes;
char c=buffer[i];
if ((c=='\n') || (c=='\r'))
{
if (pending_pos>0)
{
pending_message[pending_pos]='\r';
pending_len=pending_pos+1;
pending_message[pending_len+1]=0;
pending_pos=0;
++xlru_cx.status.received_messages;
return true;
}
else
{
++xlru_cx.status.received_oob;
++xlru_cx.status.received_garbage;
if (oob_handler)
oob_handler(c);
continue;
}
}
if (((c<' ') || (c>'}')))// && (c!='\0'))
{
if (pending_pos)
++xlru_cx.status.error_messages;
pending_pos=0;
++xlru_cx.status.received_garbage;
}
else if (c=='!')
{
if (pending_pos>0)
++xlru_cx.status.error_messages;
pending_pos=1;
pending_message[0]=c;
}
else
{
if (pending_pos>0)
{
if (pending_pos>=MAX_PENDING_SIZE) //overflow
{
pending_pos=0;
}
else
{
pending_message[pending_pos]=c;
++pending_pos;
}
}
else
{
++xlru_cx.status.received_oob;
++xlru_cx.status.received_garbage;
if (oob_handler)
oob_handler(c);
}
}
}
return false;
}
};
static Accumulator accumulators[ch_num];
#if 0
#define MAX_PENDING_BUFFER 1024
static char pending_message[MAX_PENDING_BUFFER+2];
static unsigned int pending_pos=0;
static unsigned int pending_len=0;
static bool accumulate(const char* buffer, unsigned int len)
{
for(unsigned int i=0; i<len; ++i)
{
++xlru_cx.status.received_bytes;
char c=buffer[i];
if ((c=='\n') || (c=='\r'))
{
if (pending_pos>0)
{
pending_message[pending_pos]='\r';
pending_len=pending_pos+1;
pending_message[pending_len+1]=0;
pending_pos=0;
++xlru_cx.status.received_messages;
return true;
}
else
{
++xlru_cx.status.received_oob;
++xlru_cx.status.received_garbage;
if (oob_handler)
oob_handler(c);
continue;
}
}
if (((c<' ') || (c>'}')))// && (c!='\0'))
{
if (pending_pos)
++xlru_cx.status.error_messages;
pending_pos=0;
++xlru_cx.status.received_garbage;
}
else if (c=='!')
{
if (pending_pos>0)
++xlru_cx.status.error_messages;
pending_pos=1;
pending_message[0]=c;
}
else
{
if (pending_pos>0)
{
if (pending_pos>=MAX_PENDING_BUFFER) //overflow
{
pending_pos=0;
}
else
{
pending_message[pending_pos]=c;
++pending_pos;
}
}
else
{
++xlru_cx.status.received_oob;
++xlru_cx.status.received_garbage;
if (oob_handler)
oob_handler(c);
}
}
}
return false;
}
#endif
static char oob_data[128];
static volatile unsigned int oob_counter;
static int udp_start_delay=UDP_START_DELAY;
#define PANIC_STRING "PANIC!"
static void xlru_exec()
{
static char buffer[1024];
static mrk_net_udp_socket_t panic_socket;
static char panic_message[32];
const unsigned int panic_port=60000;
const bool panic_enabled=true;
unsigned int unit_scheduler=0;
const unsigned int major_frame_ms=1000; //1second
const unsigned int minor_frame_time_ms=major_frame_ms/xlru_number_;
const unsigned int rx_poll_ms=10;
unsigned int minor_frame_poll_cycles=minor_frame_time_ms/rx_poll_ms;
rtlog_const_message(LID, rtlog_info|rtlog_breaking_news, "XLRU Manager started");
if (bsp_is_evm())
{
for(int i=0; i<xlru_number_; ++i)
xlru_unit_map[i].chid=null_ch;
}
xlru_comm_initialize();
static unsigned int pending_ch=0;
static unsigned int pending_unit=0;
XLruManager::psmFastEnable(true);
XLruManager::psmPowerDown(false);
XLruManager::lcuHeaterOn(false);
XLruManager::lcuExecuteInterruptiveBit(false);
XLruManager::lcuReset(false);
xlru_pps::set_pps_radome_bounce(1); //Limit current by default
xlru_pps::set_pps_hazard_override(0);
xlru_pps::set_pps_operative_cmd(0);
xlru_cx.pps_cmd=0;
xlru_cx.pps_hazard=0;
xlru_cx.pps_unlimited=0;
xlru_unit_map[0].sim_reply="!1n+SGNcwANNNNNNN0E002100330096FF6C300002038901000008000140__47\r";
xlru_unit_map[1].sim_reply="!2a-SBNCwABNNUNUU000021002B0071FF82EE000102081234000208__66\r";
xlru_unit_map[2].sim_reply="!3mTsPI_FH____4610823F00228000808080808080__1E0BFF__0101____F5\r";
mrk_net_udp_socket(&panic_socket, "XLRU-Panic");
mrk_net_udp_bind(&panic_socket, 0, panic_port);
mrk_net_udp_set_capacity(&panic_socket, 1);
unsigned int panic_counter=0;
for(;;)
{
#ifdef __MINGW32__
// mrk_thread_sleep_ms(rx_poll_ms);
minor_frame_poll_cycles=minor_frame_poll_cycles/4;
if (minor_frame_poll_cycles<4)
minor_frame_poll_cycles=4;
#endif
//XLruManager::unit_status_t& plrusts=*xlru_cx.sts[pending_unit].public_sts;
if (panic_enabled)
{
mrk_net_ip_raw_address_t remote_address=0;
unsigned short remote_port=panic_port;
unsigned int received_len=0;
mrk_net_result_t r=mrk_net_udp_receive(&panic_socket, &panic_message, sizeof panic_message, &remote_address, &remote_port, &received_len, 0);
if (r==mrk_net_ok)
{
if (strncmp(PANIC_STRING, panic_message, sizeof(PANIC_STRING))==0)
{
++panic_counter;
rtlog_printf("PANIC", rtlog_error|rtlog_breaking_news, "PANIC %u", panic_counter);
if (panic_counter>1)
{
//XLruManager::psmRecycle(true);
}
}
}
if (panic_counter>1)
{
rtlog_printf("PANIC", rtlog_error|rtlog_breaking_news, "PANIC %u", panic_counter);
++panic_counter;
if (panic_counter>4)
{
rtlog_const_message("PANIC", rtlog_fatal|rtlog_breaking_news, "PANIC! PANIC! PANIC! Trying recycle...");
XLruManager::psmRecycle(true);
}
}
}
if (autoMonitorable_xlruovr.pps_cmd_ovr)
xlru_pps::set_pps_operative_cmd(autoMonitorable_xlruovr.pps_cmd_ovr-1);
else
xlru_pps::set_pps_operative_cmd(xlru_cx.pps_cmd);
if (autoMonitorable_xlruovr.pps_unlimited)
xlru_pps::set_pps_radome_bounce(autoMonitorable_xlruovr.pps_unlimited==1 ? 0 : 1); //Limit current by default
else
xlru_pps::set_pps_radome_bounce(1); //TODO: remove protection -> xlru_cx.pps_unlimited ? 0 : 1); //Limit current by default
if (autoMonitorable_xlruovr.pps_hazard)
xlru_pps::set_pps_hazard_override(1);
else
xlru_pps::set_pps_hazard_override(0);
for(unsigned int poll_cycles=0; poll_cycles<minor_frame_poll_cycles; ++poll_cycles)
{
unsigned int received_len=0;
#ifndef __MINGW32__
mrk_thread_sleep_ms(rx_poll_ms);
#else
mrk_thread_sleep_ms(rx_poll_ms*2);
#endif
if (oob_counter)
{
xlru_comm_raw_transmit(1, oob_data, oob_counter);
oob_counter=0;
}
if (pending_ch<1)
continue;
bool ok=receive(pending_ch, buffer, received_len);
#if 0
if (pending_unit==1)
{
strcpy(buffer, xlru_unit_map[pending_unit-1].sim_reply);
received_len=strlen(buffer);
ok=true;
}
#endif
#if 1
Accumulator* acc=&accumulators[pending_ch];
if ((!ok || (received_len<=0)) && (poll_cycles==0))
{
received_len=0;
ok=xlru_comm_dbg_get_data(buffer, &received_len, sizeof buffer);
acc=&accumulators[0];
}
if (ok && (received_len>0))
{
ok=acc->accumulate(buffer, received_len);
if (ok)
{
const char* current_message=acc->pending_message;
unsigned int current_len=acc->pending_len;
xlru_comm_dbg_add_data(1, current_message, current_len);
//const xlru_unit_map_t& lru=xlru_unit_map[pending_unit];
common_reply_decoder(pending_unit, current_message, current_len);//lru.reply_decoder(pending_unit, current_message, current_len);
}
}
#else
if (ok && (received_len>0))
{
ok=accumulate(buffer, received_len);
//TODO: Decode the message
if (ok)
{
xlru_comm_dbg_add_data(1, pending_message, pending_len);
const char* current_message=pending_message;
unsigned int current_len=pending_len;
//const xlru_unit_map_t& lru=xlru_unit_map[pending_unit];
common_reply_decoder(pending_unit, current_message, current_len);//lru.reply_decoder(pending_unit, current_message, current_len);
//plrusts.commStatus.reply_pending=0;
}
}
#endif
}
//TX frame:
{
if (unit_scheduler==0)
xlru_comm_dbg_flush();
const xlru_unit_map_t& lru=xlru_unit_map[unit_scheduler];
xlru_unit_sts_t& lrusts=xlru_cx.sts[lru.uid];
int r=lru.encoder(unit_scheduler);
xlru_comm_sts_t txres=xlru_comm_ok;
if (lru.chid>=1)
{
if (r==0)
{
if (lrusts.public_sts->commStatus.reply_pending>0)
{
++lrusts.public_sts->commStatus.reply_missed;
if (lrusts.public_sts->commStatus.reply_pending>3)
{
lrusts.public_sts->commStatus.linkUp=false;
lrusts.public_sts->basicStatus.unitOk=false;
}
}
unsigned int len=strlen(lru.cmd_buffer);
//rtlog_printf(LID, rtlog_info|rtlog_breaking_news, "TX: %s", lru.cmd_buffer);
txres=xlru_comm_raw_transmit(lru.chid, lru.cmd_buffer, len);
xlru_comm_dbg_add_data(lru.chid, lru.cmd_buffer, len);
if (lrusts.public_sts->commStatus.reply_pending<1000) //do not let the counter overflow
++lrusts.public_sts->commStatus.reply_pending;
++lrusts.public_sts->commStatus.sent_messages;
++xlru_cx.status.poroduce_messages;
if (txres==0)
++xlru_cx.status.transmitted_bytes+=len;
txres=xlru_comm_ok;
//if (lru.sim_reply)
// xlru_comm_raw_transmit(lru.chid, lru.sim_reply, 0);
}
rtlog_severity_t severity=(r || txres) ? rtlog_error | rtlog_breaking_news : rtlog_info;
rtlog_printf(LID, severity, "tx(%s): %d (%s)", lru.name, txres, xlru_comm_error_string(txres));
}
pending_ch=lru.chid;
pending_unit=lru.uid;
}
++unit_scheduler;
if (unit_scheduler>=xlru_number_)
{
unit_scheduler=0;
if (udp_start_delay>=0)
{
if (udp_start_delay==0)
{
xlru_comm_udp_monitor_enable(true);
}
--udp_start_delay;
}
}
}
}
static void xlru_manager_mex_extension();
//External I/F
static bool manager_started;
void xlru_channel_map(unsigned int psm, unsigned int pps, unsigned int lcu)
{
xlru_unit_map[0].chid=psm;
xlru_unit_map[1].chid=pps;
xlru_unit_map[2].chid=lcu;
if (!manager_started)
XLruManager::start();
}
bool XLruManager::start()
{
xlru_cx.sts[0].public_sts=&xlru_cx.invalid_unit_status;
xlru_cx.sts[1].public_sts=&xlru_cx.psm_status.status;
xlru_cx.sts[2].public_sts=&xlru_cx.pps_status.status;
xlru_cx.sts[3].public_sts=&xlru_cx.lcu_status.status;
if (manager_started)
return true;
manager_started=true;
mrk_mutex_create(&xlru_cx.mutex, "XLRU");
mrk_thread_create(&xlru_cx.thread, "XLRU", xlru_exec, 0, mrk_std_priority_above_normal, sizeof xlru_cx.stack, xlru_cx.stack, 0);
xlru_manager_mex_extension();
return true;
}
XLruManager::manager_status_t& XLruManager::managerStatus()
{
return xlru_cx.status;
}
void XLruManager::emergyEnable(bool enable)
{
psmEmergency(enable);
xlru_cx.pps_hazard=enable ? 1 : 0;
//xlru_pps::set_pps_hazard_override(enable ? 1 : 0);
}
//PSM
XLruManager::psm_status_t& XLruManager::psmStatus()
{
static XLruManager::psm_status_t sts;
mrk_mutex_acquire(&xlru_cx.mutex, mrk_wait_forever);
sts=xlru_cx.psm_status;
mrk_mutex_release(&xlru_cx.mutex);
return sts;
}
float XLruManager::psmTemperature()
{
return xlru_cx.psm_temperature;
}
void XLruManager::psmPowerDown(bool enable)
{
xlru_psm::set_psm_cmd_id(enable ? 0 : 2);
}
void XLruManager::psmRecycle(bool enable)
{
xlru_psm::set_psm_cmd_id(enable ? 1 : 2);
}
void XLruManager::psmEmergency(bool enable)
{
xlru_psm::set_psm_emergency(enable ? 1 : 2);
}
void XLruManager::psmFastEnable(bool enable)
{
xlru_psm::set_psm_fast_cmd(enable ? 0 : 1);
}
//PPS
void XLruManager::ppsPowerOuputEnable(bool enable)
{
xlru_cx.pps_cmd=enable ? 1 : 0; //xlru_pps::set_pps_operative_cmd(enable ? 1 : 0);
}
void XLruManager::ppsPowerLimitationEnable(bool enable)
{
xlru_cx.pps_unlimited=enable ? 0 : 1; //xlru_pps::set_pps_radome_bounce(enable ? 1 : 0);
}
XLruManager::pps_status_t& XLruManager::ppsStatus()
{
static XLruManager::pps_status_t sts;
mrk_mutex_acquire(&xlru_cx.mutex, mrk_wait_forever);
sts=xlru_cx.pps_status;
mrk_mutex_release(&xlru_cx.mutex);
return sts;
}
float XLruManager::ppsTemperature()
{
return xlru_cx.pps_temperature;
}
//LCU:
XLruManager::lcu_status_t& XLruManager::lcuStatus()
{
static XLruManager::lcu_status_t sts;
mrk_mutex_acquire(&xlru_cx.mutex, mrk_wait_forever);
sts=xlru_cx.lcu_status;
mrk_mutex_release(&xlru_cx.mutex);
return sts;
}
float XLruManager::lcuTemperature()
{
return xlru_cx.lcu_temperature;
}
void XLruManager::lcuHeaterOn(bool enable)
{
xlru_lcu::set_lcu_heater(enable);
}
void XLruManager::lcuExecuteInterruptiveBit(bool enable)
{
xlru_lcu::set_lcu_ibit(enable);
}
void XLruManager::lcuReset(bool enable)
{
xlru_lcu::set_lcu_restart(enable);
}
void XLruManager::setOutOfBandDataHandler(void (*handler)(char c))
{
oob_handler=handler;
}
void XLruManager::injectOutofBandData(char c)
{
if (oob_counter>=sizeof(oob_data))
return;
oob_data[oob_counter]=c;
++oob_counter;
}
//
extern void xlru_mex_initialize();
static void xlru_manager_mex_extension()
{
xlru_mex_initialize();
}