/* * DspRIS.cpp * * WARNING: ALL section (code, data, rodata, bss, ...) shall be allocated onto a dedicated memory area, reserved at link time * It shall work as a "static DLL": the Rsi Code shall not alter in any way the operative code, even in term of linker time memory allocation. * In other word, the operative CSC shall link also without DspRis and its binary image shall be equal on an executable linker with the RisDsp * * The target memory shall have 3 partition: * -the operative, spread around without constrains except it cannot use the RIS reserved partitions * -Fixed RIS I/F partition: I/F between operative CSC and RIS CSC, * -Fixed RIS CSC partition: all RIS section * * The operative partition of an executable linked without RIS shall be equal to an executable linked with the RIS * */ #include "dsp_ris_internals_.h" #include "sfp_dsp_ris.h" #include "gc_math.h" #include "mrk_plus.h" #include "mrk_net.h" #include "rtlog.h" #include "mex_hobbit_register.h" #include "mex.h" #include #include #include #define LOGID "RIS" #define MAX_PACKET_SIZE (10*1024) /*provision for jumbo buffer*/ struct ris_dsp_message_header_t { uint32_t begin_marker[2]; //=="RIS0>>>>" uint16_t version; uint16_t type; uint32_t cmd; char data[1024]; }; #define RIS_MARKER0 0x30534952 /*"RIS0"*/ #define RIS_MARKER1 0x3E3E3E3E /*">>>>"*/ enum dsp_ris_features_flags_t { dsp_ris_feat_sim_none, dsp_ris_feat_sim_lcu, dsp_ris_feat_sim_pps, dsp_ris_feat_sim_aesa, dsp_ris_feat_sim_simple_map }; struct dsp_ris_tgt_cmd_t { int id; uint32_t data_mask; float ground_range; float baro_altitude; float nav_azimuth; float ground_speed; float vertical_speed; float turn_rate; float turn_time; float spare[4]; }; struct dsp_ris_cmd_packet_t { uint32_t features_enable; dsp_ris_tgt_cmd_t tgt_cmd[16]; }; static_assert((sizeof(SFP_RIS::status_payload_t) { public: explicit DspRisAgent() { mrk_mutex_create(&mutex, "RisAgent"); } mrk_mutex_t mutex; int active; int connected; int eth_if; mrk_net_ip_port_t server_port; mrk_net_udp_socket_t ris_socket; mrk_net_ip_raw_address_t client_ip; mrk_net_ip_port_t client_port; unsigned int rcv_datagram; unsigned int rcv_script; SFP_RIS::status_message_t stsmsg; SFP_RIS::script_message_t cmdmsg; unsigned int raw_packet[MAX_PACKET_SIZE/(sizeof(unsigned int))]; void go() { create("RIS", mrk_std_priority_below_normal, 0); } void mrk_exec() override { mex_hobbit_register_instance("riscom", *this); eth_if=0; server_port=60001; mrk_net_udp_socket(&ris_socket, "Ris"); #ifdef __MINGW32__ mrk_net_udp_bind(&ris_socket, mrk_net_str2ip("127.0.0.1"), server_port); #else mrk_net_udp_bind_if(&ris_socket, eth_if, server_port); #endif client_ip=mrk_net_myip_address_broadcast(eth_if); client_port=server_port+1; unsigned int timeout=5000; //mrk_wait_forever; active=1; memset(&stsmsg, 0, sizeof stsmsg); memset(&cmdmsg, 0, sizeof cmdmsg); sfp_frag_header_initialize(stsmsg.header, SFP::frag_sync_marker_sender, SFP::src_rdr, SFP::flow_id_ris_sts); //sfp_frag_header_payload_init(stsmsg.header, 'R', sizeof fh, uint8_t record_type, unsigned int payload_leader_size, unsigned int payload_body_size); { stsmsg.header.frag_tag=SFP::frag_single; stsmsg.header.payload_total_size=sizeof stsmsg.payload; stsmsg.header.payload_size=sizeof stsmsg.payload; stsmsg.header.frag_total=1; stsmsg.header.record_type=SFP::flow_id_ris_sts; } sfp_data_tag_initialize(stsmsg.payload.scenario_tag, sfp_data_tag('R', 'S'), 0, sizeof stsmsg.payload.scenario); sfp_data_tag_initialize(stsmsg.payload.target_tag, sfp_data_tag('R', 'T'), 0, sizeof stsmsg.payload.tgt); auto script_tag=sfp_data_tag('C', 'S'); rtlog_printf("RIS", rtlog_report|rtlog_breaking_news, "RIS COM Active I/F %d, port %u", eth_if, server_port); for(;;) { mrk_thread_sleep_ms(10); unsigned int received_len=0; mrk_net_result_t r=mrk_net_udp_receive(&ris_socket, raw_packet, sizeof raw_packet, &client_ip, &client_port, &received_len, 0); if (r==mrk_net_ok) { ++rcv_datagram; connected=1; bool valid=received_len>(sizeof cmdmsg.header); memcpy(&cmdmsg, raw_packet, sizeof cmdmsg); valid&= (cmdmsg.payload.script_tag.type_validity) && (cmdmsg.payload.script_tag.tag==script_tag); if (valid) { ++rcv_script; if (cmdmsg.payload.script_tag.size<((sizeof cmdmsg.payload.script)-1)) { cmdmsg.payload.script[cmdmsg.payload.script_tag.size]=0; mex_script_asynch_exec(reinterpret_cast(cmdmsg.payload.script), 0); } } } ++stsmsg.header.transaction_id; ++stsmsg.header.record_counter; mrk_net_udp_send(&ris_socket, &stsmsg, sizeof stsmsg, client_ip, client_port, 0); } } }; #ifdef _TMS320C6X #define ATTR_NO_INIT __attribute__((section(".far:ris_noinit_"))) #else #define ATTR_NO_INIT #endif struct dsp_ris_static_noinit_data_t { uint64_t align; unsigned int active[2]; mrk_mutex_t tgtMutex; char risAgentImage[sizeof(DspRisAgent)]; DspRisAgent* risAgent; volatile DspRisAgent* risAgentVolatile; }; static dsp_ris_static_noinit_data_t dsp_ris_static_noinit_data ATTR_NO_INIT; bool DspRigTgtMutexAcquire(bool please_wait) { mrk_tick_t tm=please_wait ? mrk_wait_forever : 0; mrk_sts_t r=mrk_mutex_acquire(&dsp_ris_static_noinit_data.tgtMutex, tm); return r==mrk_ok; } void DspRigTgtMutexRelease() { mrk_mutex_release(&dsp_ris_static_noinit_data.tgtMutex); } static void DspRisMexInstall(); #include "mex.h" void DspRisInstall() { bool activated=(dsp_ris_static_noinit_data.active[0]==0x12345678) && (dsp_ris_static_noinit_data.active[1]==0x87654321); if (activated) return; rtlog_const_message(LOGID, rtlog_breaking_news|rtlog_report, "RIS: Activating..."); memset(&dsp_ris_tgt_db, 0, sizeof dsp_ris_tgt_db); #ifdef __MINGW32__ dsp_ris_tgt_db.agr.enable=1; #endif for(int i=0; igo(); mex_set_prompt("DSP-RIS"); } #include "idd_nav_types.h" static void DspRisSfpUpdateScenario(unsigned int timetag, const iddtypes::inu_data_t& inu) { if (!dsp_ris_static_noinit_data.risAgent) return; DspRisAgent& ra=*dsp_ris_static_noinit_data.risAgent; ra.stsmsg.payload.scenario.timetag=timetag; ra.stsmsg.payload.scenario.platform_azimuth=inu.own_ship_attitude.vector.platform_azimuth; ra.stsmsg.payload.scenario.vx=inu.own_ship_velocity.vector.x; ra.stsmsg.payload.scenario.vy=inu.own_ship_velocity.vector.y; ra.stsmsg.payload.scenario.vz=inu.own_ship_velocity.vector.z; ra.stsmsg.payload.scenario.baro_altitude=inu.inertial_altitude.data; ra.stsmsg.payload.scenario.latitude=inu.geo_pos.latitude; ra.stsmsg.payload.scenario.longitude=inu.geo_pos.longitude; ra.stsmsg.payload.scenario.true_heading=inu.own_ship_attitude.true_heading; //Targets for(int i=0; ige.general_settings.antenna.position.navaz_rad; ra.stsmsg.payload.scenario.ant_nav_el=hdrptr->ge.general_settings.antenna.position.navel_rad; } //MEx monitor #include "mex_rtg_io.h" #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif static void nl() { mex_putchar('\n'); } static int eth_n; static int eth_stat_refresh; static int eth_msg_stat; static int eth_msg_period; static const mex_cmd_param_descriptor_t eth_show_table[] = { { "ethif", "Ethernet I/F", 0, ð_n, &mex_mt_int}, { "r", "refresh", mex_cmd_qualifier, ð_stat_refresh }, { "m", "message stat", mex_cmd_qualifier, ð_msg_stat }, { "p", "show exact period", mex_cmd_qualifier, ð_msg_period }, #if 0 { "r", "relative timetags", mex_cmd_qualifier, &drs.param_relative_timetag }, { "a", "abs time", mex_cmd_qualifier, &drs.param_abs_time }, { "rev", "reverse (oldest first)", mex_cmd_qualifier, &drs.reverse }, { "t", "hide timetag (default)", mex_cmd_qualifier, &drs.tt_hide }, { "b", "show local batch", mex_cmd_qualifier, &drs.lb }, { "g", "show global batch", mex_cmd_qualifier, &drs.gb }, #endif { 0 } }; static unsigned period_round(unsigned int period, char& rounded) { rounded=' '; if (period<1) return period; if (period>9999) { rounded='>'; return 9999; } if (eth_msg_period) return period; unsigned int p10=period/10; p10=p10*10; int p_remainder=period-(p10); if (p_remainder>=8) { rounded='~'; period=10+p10; } else if (p_remainder==1) { rounded='~'; period=p10; } return period; } static mex_res_t Cmd_ShowEth() { int eth_id=1; int eth_mask=1<connected ? "CONNECTED " : "NOT CONNECTED"); //mrk_net_stat_t eth_stat=*mrk_net_stat(ra->eth_if, 0); mex_printf(" DSP Server: %u received: %u (%u datagrams)\n", ra->server_port, ra->rcv_script, ra->rcv_datagram); unsigned int ccip=ra->client_ip; mex_printf(" CC Client : %u.%u.%u.%u::%u\n", ccip & 0x0FF, (ccip>>8) & 0x0FF, (ccip>>16) & 0x0FF, (ccip>>24) & 0x0FF, ra->client_port); if (show_msg) continue; } while (mex_page_loop_end(0, 0) != mex_page_event_quit); nl(); return mex_ok; } static int sleep_time; static mex_res_t Cmd_Sleep() { mrk_thread_sleep_ms(sleep_time); return mex_ok; } static const mex_cmd_param_descriptor_t sleep_table[] = { { "time", "sleep time(ms)", mex_cmd_required, &sleep_time, &mex_mt_uint }, { 0 } }; static const mex_cmd_descriptor_t cmd_sleep = { "sleep", "script sleep", (mex_cmd_handler_t) Cmd_Sleep, sleep_table}; static const mex_cmd_descriptor_t cmd_eth = { "rissts", "Show RIS status", (mex_cmd_handler_t) Cmd_ShowEth, eth_show_table}; extern const mex_cmd_descriptor_t cmd_msg; extern const mex_cmd_descriptor_t cmd_msg_res; extern const mex_cmd_descriptor_t cmd_scenario; extern const mex_cmd_descriptor_t cmd_tgtinit; extern const mex_cmd_descriptor_t cmd_tgtset; extern const mex_cmd_descriptor_t cmd_tgtturn; extern const mex_cmd_descriptor_t cmd_pause; extern const mex_cmd_descriptor_t cmd_continue; extern const mex_cmd_descriptor_t cmd_tgtreset; extern const mex_cmd_descriptor_t cmd_aclatch; extern const mex_cmd_descriptor_t cmd_acunlatch; extern const mex_cmd_descriptor_t cmd_tgtrng; extern const mex_cmd_descriptor_t cmd_tgtaz; extern const mex_cmd_descriptor_t cmd_tgthead; extern const mex_cmd_descriptor_t cmd_tgtspeed; extern const mex_cmd_descriptor_t cmd_tgtalt; extern const mex_cmd_descriptor_t cmd_tgtmap; extern const mex_cmd_descriptor_t cmd_bite_reset; extern const mex_cmd_descriptor_t cmd_bite_set; extern const mex_cmd_descriptor_t cmd_bite_clear; extern const mex_mt_struct_t mex_mt_ris_tgtovr; static const mex_mt_object_t ris_str[] = { MEX_HOTCMD_REF("sts", &cmd_eth), MEX_HOTCMD_REF("sleep", &cmd_sleep), MEX_HOTCMD_REF("tgtinit", &cmd_tgtinit), MEX_HOTCMD_REF("tgtset", &cmd_tgtset), MEX_HOTCMD_REF("tgtturn", &cmd_tgtturn), #if 0 //MEX_HOTCMD_REF("message", &cmd_msg), //MEX_HOTCMD_REF("scenario", &cmd_scenario), //MEX_HOTCMD_REF("tgtinit", &cmd_tgtinit), //MEX_HOTCMD_REF("tgtset", &cmd_tgtset), //MEX_HOTCMD_REF("tgtreset", &cmd_tgtreset), MEX_HOTCMD_REF("tgtrng", &cmd_tgtrng), MEX_HOTCMD_REF("tgtaz", &cmd_tgtaz), MEX_HOTCMD_REF("tgtvel", &cmd_tgtspeed), MEX_HOTCMD_REF("tgtalt", &cmd_tgtalt), MEX_HOTCMD_REF("tgthead", &cmd_tgthead), MEX_HOTCMD_REF("tgtmap", &cmd_tgtmap), MEX_HOTCMD_REF("aclatch", &cmd_aclatch), MEX_HOTCMD_REF("acunlatch", &cmd_acunlatch), MEX_HOTCMD_REF("pause", &cmd_pause), MEX_HOTCMD_REF("continue", &cmd_continue), MEX_HOTCMD_REF("recorder", &cmd_recorder), MEX_HOTCMD_REF("wow", &cmd_wow), MEX_HOTCMD_REF("biterest", &cmd_bite_reset), MEX_HOTCMD_REF("biteset", &cmd_bite_set), MEX_HOTCMD_REF("biteclear", &cmd_bite_clear), { 0, "ovr", &MEX_MT_CAST(mex_mt_ris_tgtovr), 0 }, { 0, "dbgdeclutter", &mex_mt_uint, &cmp_dbg_display_hide_ }, #ifdef MCD_UDPFMT MEX_CMD_REF("udp1553fmt", &cmd_udp1553fmt), #endif //MEX_CMD_REF("restart", &cmd_restart), MEX_CMD_REF("_showreserved", &cmd_msg_res), #endif { 0 } }; const mex_mt_struct_t mex_mt_ris = { { "ris", 0, &mex_mt_struct_methods }, ris_str }; static mex_mt_object_t ris_obj={ 0, "ris", &MEX_MT_CAST(mex_mt_ris), 0 }; static void DspRisMexInstall() { static mex_cmd_server_t ris_srv; mex_object_register(mex_object_root(), &ris_obj); mex_add_command_server(&ris_srv, &ris_obj, "Radar Interface Simulator Commands"); //mex_set_user_mode(-1, "ris."); mex_hobbit_register_instance("riscom", dsp_ris_static_noinit_data.risAgent); } bool DspRisIsActive() { bool activated=(dsp_ris_static_noinit_data.active[0]==0x12345678) && (dsp_ris_static_noinit_data.active[1]==0x87654321); return activated; } void DspRisProcessEnvironment(unsigned int timetag, const iddtypes::inu_data_t* inu) { static unsigned int previous_time; unsigned int dt=timetag-previous_time; previous_time=timetag; DspRisSfpUpdateScenario(timetag, *inu); float delta_time=dt*64.0E-6; if ((delta_time<0) || (delta_time>5)) return; DspRisTgtUpdate(*inu, delta_time); }