940 lines
21 KiB
C++
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();
|
|
}
|
|
|
|
|