diff --git a/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt index 1e2bc0d8..0c4f8b0e 100644 --- a/cfg/InOut/Inp_IPC.txt +++ b/cfg/InOut/Inp_IPC.txt @@ -1,5 +1,5 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> -16 ! Number of Sockets +17 ! Number of Sockets ********************************** RW 0 to 42 ***************************** RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode @@ -171,4 +171,14 @@ fortytwo 4283 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes +"SC" ! Prefix 0 +********************************** NEWSIM IPC ***************************** +TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) +0 ! AC.ID for ACS mode +"NEWSIM.42" ! File name for WRITE or READ +SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) +fortytwo 4251 ! Server Host Name, Port +FALSE ! Allow Blocking (i.e. wait on RX) +FALSE ! Echo to stdout +1 ! Number of TX prefixes "SC" ! Prefix 0 \ No newline at end of file diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index 7a21cddb..5d1aa67b 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -9,6 +9,8 @@ CFE_APP, to, TO_AppMain, TO, CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 80, 16384, 0x0, 0; CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 32768, 0x0, 0; +CFE_APP, newsim, NEWSIM_AppMain, NEWSIM, 72, 8192, 0x0, 0; + ! ! ** The software will not try to parse anything after the first '!' character it sees. ** ! diff --git a/cfg/nos3_defs/tables/to_lab_sub.c b/cfg/nos3_defs/tables/to_lab_sub.c index 9c082dc7..34d519b9 100644 --- a/cfg/nos3_defs/tables/to_lab_sub.c +++ b/cfg/nos3_defs/tables/to_lab_sub.c @@ -64,6 +64,7 @@ #include "generic_star_tracker_msgids.h" #include "syn_msgids.h" +#include "newsim_msgids.h" /* ** Local Structure Declarations @@ -128,7 +129,9 @@ TO_LAB_Subs_t TO_LAB_Subs = {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_HK_TLM_MID),{0,0}, 32}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_DEVICE_TLM_MID),{0,0}, 32}, - {CFE_SB_MSGID_WRAP_VALUE(SYN_HK_TLM_MID), {0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(SYN_HK_TLM_MID), {0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(NEWSIM_HK_TLM_MID), {0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(NEWSIM_DEVICE_TLM_MID), {0,0}, 32}, } }; diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index b670344d..ad35d0a2 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -117,6 +117,8 @@ list(APPEND MISSION_GLOBAL_APPLIST novatel_oem615/fsw sample/fsw syn/fsw + + newsim ) # Create Application Platform Include List diff --git a/cfg/sims/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml index 69461bce..c5192610 100644 --- a/cfg/sims/nos3-simulator.xml +++ b/cfg/sims/nos3-simulator.xml @@ -113,6 +113,32 @@ + + newsim_sim + true + libnewsim_sim.so + + NEWSIM + + command + command + newsim-command + + usart + usart_27 + 27 + + + + NEWSIM_42_PROVIDER + fortytwo + 4251 + 20 + 5 + 0 + + + sample_sim diff --git a/components/newsim/.gitignore b/components/newsim/.gitignore new file mode 100644 index 00000000..cfea098e --- /dev/null +++ b/components/newsim/.gitignore @@ -0,0 +1 @@ +support/build \ No newline at end of file diff --git a/components/newsim/CMakeLists.txt b/components/newsim/CMakeLists.txt new file mode 100644 index 00000000..447e5e32 --- /dev/null +++ b/components/newsim/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.6.4) +project(CFS_NEWSIM_APP C) + +include(../ComponentSettings.cmake) + +include_directories(fsw/public_inc) +include_directories(fsw/mission_inc) +include_directories(fsw/platform_inc) +include_directories(fsw/src) + +include_directories(${hwlib_MISSION_DIR}/fsw/public_inc) + +aux_source_directory(fsw/src APP_SRC_FILES) + +# Create the app module +add_cfe_app(newsim ${APP_SRC_FILES}) diff --git a/components/newsim/LICENSE b/components/newsim/LICENSE new file mode 100644 index 00000000..50a36292 --- /dev/null +++ b/components/newsim/LICENSE @@ -0,0 +1,263 @@ +NASA OPEN SOURCE AGREEMENT VERSION 1.3 + +THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, +REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN +COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT +AS REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT +AGENCY"). THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT +AGENCY, IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT +DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO +USES, REPRODUCES, DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT +SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, +ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN +THIS AGREEMENT. + +Government Agency: NASA +Government Agency Original Software Designation: GSC-17737-1 +Government Agency Original Software Title: + NASA Operational Simulator for Small Satellites +User Registration Requested. Please Visit + https://github.com/nasa/nos3 +Government Agency Point of Contact for Original Software: + John.P.Lucas@nasa.gov + +1. DEFINITIONS + +A. "Contributor" means Government Agency, as the developer of the +Original Software, and any entity that makes a Modification. +B. "Covered Patents" mean patent claims licensable by a Contributor +that are necessarily infringed by the use or sale of its Modification +alone or when combined with the Subject Software. +C. "Display" means the showing of a copy of the Subject Software, +either directly or by means of an image, or any other device. +D. "Distribution" means conveyance or transfer of the Subject +Software, regardless of means, to another. +E. "Larger Work" means computer software that combines Subject +Software, or portions thereof, with software separate from the Subject +Software that is not governed by the terms of this Agreement. +F. "Modification" means any alteration of, including addition to or +deletion from, the substance or structure of either the Original +Software or Subject Software, and includes derivative works, as that +term is defined in the Copyright Statute, 17 USC 101. However, the +act of including Subject Software as part of a Larger Work does not in +and of itself constitute a Modification. +G. "Original Software" means the computer software first released +under this Agreement by Government Agency with Government Agency +designation GSC-17776-1 and entitled Core Flight System Cryptography +Library, including source code, object code and accompanying +documentation, if any. +H. "Recipient" means anyone who acquires the Subject Software under +this Agreement, including all Contributors. +I. "Redistribution" means Distribution of the Subject Software after a +Modification has been made. +J. "Reproduction" means the making of a counterpart, image or copy of +the Subject Software. +K. "Sale" means the exchange of the Subject Software for money or +equivalent value. +L. "Subject Software" means the Original Software, Modifications, or +any respective parts thereof. +M. "Use" means the application or employment of the Subject Software +for any purpose. + +2. GRANT OF RIGHTS + +A. Under Non-Patent Rights: Subject to the terms and conditions of +this Agreement, each Contributor, with respect to its own contribution +to the Subject Software, hereby grants to each Recipient a +non-exclusive, world-wide, royalty-free license to engage in the +following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Modification +5. Redistribution +6. Display + +B. Under Patent Rights: Subject to the terms and conditions of this +Agreement, each Contributor, with respect to its own contribution to +the Subject Software, hereby grants to each Recipient under Covered +Patents a non-exclusive, world-wide, royalty-free license to engage in +the following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Sale +5. Offer for Sale + +C. The rights granted under Paragraph B. also apply to the combination +of a Contributor's Modification and the Subject Software if, at the +time the Modification is added by the Contributor, the addition of +such Modification causes the combination to be covered by the Covered +Patents. It does not apply to any other combinations that include a +Modification. + +D. The rights granted in Paragraphs A. and B. allow the Recipient to +sublicense those same rights. Such sublicense must be under the same +terms and conditions of this Agreement. + +3. OBLIGATIONS OF RECIPIENT + +A. Distribution or Redistribution of the Subject Software must be made +under this Agreement except for additions covered under paragraph 3H. + +1. Whenever a Recipient distributes or redistributes the Subject + Software, a copy of this Agreement must be included with each copy + of the Subject Software; and +2. If Recipient distributes or redistributes the Subject Software in + any form other than source code, Recipient must also make the + source code freely available, and must provide with each copy of + the Subject Software information on how to obtain the source code + in a reasonable manner on or through a medium customarily used for + software exchange. + +B. Each Recipient must ensure that the following copyright notice +appears prominently in the Subject Software: + +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ + +C. Each Contributor must characterize its alteration of the Subject +Software as a Modification and must identify itself as the originator +of its Modification in a manner that reasonably allows subsequent +Recipients to identify the originator of the Modification. In +fulfillment of these requirements, Contributor must include a file +(e.g., a change log file) that describes the alterations made and the +date of the alterations, identifies Contributor as originator of the +alterations, and consents to characterization of the alterations as a +Modification, for example, by including a statement that the +Modification is derived, directly or indirectly, from Original +Software provided by Government Agency. Once consent is granted, it +may not thereafter be revoked. + +D. A Contributor may add its own copyright notice to the Subject +Software. Once a copyright notice has been added to the Subject +Software, a Recipient may not remove it without the express permission +of the Contributor who added the notice. + +E. A Recipient may not make any representation in the Subject Software +or in any promotional, advertising or other material that may be +construed as an endorsement by Government Agency or by any prior +Recipient of any product or service provided by Recipient, or that may +seek to obtain commercial advantage by the fact of Government Agency's +or a prior Recipient's participation in this Agreement. + +F. In an effort to track usage and maintain accurate records of the +Subject Software, each Recipient, upon receipt of the Subject +Software, is requested to register with Government Agency by visiting +the following website: https://github.com/nasa/CryptoLib. Recipient's +name and personal information shall be used for statistical purposes +only. Once a Recipient makes a Modification available, it is requested +that the Recipient inform Government Agency at the web site provided +above how to access the Modification. + +G. Each Contributor represents that that its Modification is believed +to be Contributor's original creation and does not violate any +existing agreements, regulations, statutes or rules, and further that +Contributor has sufficient rights to grant the rights conveyed by this +Agreement. + +H. A Recipient may choose to offer, and to charge a fee for, warranty, +support, indemnity and/or liability obligations to one or more other +Recipients of the Subject Software. A Recipient may do so, however, +only on its own behalf and not on behalf of Government Agency or any +other Recipient. Such a Recipient must make it absolutely clear that +any such warranty, support, indemnity and/or liability obligation is +offered by that Recipient alone. Further, such Recipient agrees to +indemnify Government Agency and every other Recipient for any +liability incurred by them as a result of warranty, support, indemnity +and/or liability offered by such Recipient. + +I. A Recipient may create a Larger Work by combining Subject Software +with separate software not governed by the terms of this agreement and +distribute the Larger Work as a single product. In such case, the +Recipient must make sure Subject Software, or portions thereof, +included in the Larger Work is subject to this Agreement. + +J. Notwithstanding any provisions contained herein, Recipient is +hereby put on notice that export of any goods or technical data from +the United States may require some form of export license from the +U.S. Government. Failure to obtain necessary export licenses may +result in criminal liability under U.S. laws. Government Agency +neither represents that a license shall not be required nor that, if +required, it shall be issued. Nothing granted herein provides any +such export license. + +4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION + +A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY +WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, +INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE +WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM +INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR +FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO +THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, +CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT +OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY +OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. +FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES +REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, +AND DISTRIBUTES IT "AS IS." + +B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS +AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND +SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF +THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, +EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM +PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT +SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED +STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY +PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE +REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL +TERMINATION OF THIS AGREEMENT. + + +5. GENERAL TERMS + +A. Termination: This Agreement and the rights granted hereunder will +terminate automatically if a Recipient fails to comply with these +terms and conditions, and fails to cure such noncompliance within +thirty (30) days of becoming aware of such noncompliance. Upon +termination, a Recipient agrees to immediately cease use and +distribution of the Subject Software. All sublicenses to the Subject +Software properly granted by the breaching Recipient shall survive any +such termination of this Agreement. + +B. Severability: If any provision of this Agreement is invalid or +unenforceable under applicable law, it shall not affect the validity +or enforceability of the remainder of the terms of this Agreement. + +C. Applicable Law: This Agreement shall be subject to United States +federal law only for all purposes, including, but not limited to, +determining the validity of this Agreement, the meaning of its +provisions and the rights, obligations and remedies of the parties. + +D. Entire Understanding: This Agreement constitutes the entire +understanding and agreement of the parties relating to release of the +Subject Software and may not be superseded, modified or amended except +by further written agreement duly executed by the parties. + +E. Binding Authority: By accepting and using the Subject Software +under this Agreement, a Recipient affirms its authority to bind the +Recipient to all terms and conditions of this Agreement and that that +Recipient hereby agrees to all terms and conditions herein. + +F. Point of Contact: Any Recipient contact with Government Agency is +to be directed to the designated representative as follows: + John.P.Lucas@nasa.gov \ No newline at end of file diff --git a/components/newsim/README.md b/components/newsim/README.md new file mode 100644 index 00000000..e43e4eef --- /dev/null +++ b/components/newsim/README.md @@ -0,0 +1,138 @@ +# Newsim - NOS3 Component +This repository contains the NOS3 Newsim Component. +This includes flight software (FSW), ground software (GSW), simulation, and support directories. + +## Component Template +This component template utilizes canned files from the existing [newsim component](https://github.com/nasa-itc/newsim) to generate a new component to do development in. + +Expected utilization: +* Determine the desired component name +* Create a new submodule for the component via GitHub +* Add the submodule to this project + * `git submodule init` + * `git submodule add -f -b main ./components/` +* Generate the new files + * `./generate_template.sh ` + * Note that must be <= 10 characters by default or you'll need to shorten the software bus pipe name after the fact +* The new files should be placed in the submodule + * `..//` +* Commit the new files to the submodule + * `git add * && git add .gitignore` + * `git commit -m "Initial component template based on version 0.0.0"` +* Add new component to flight software (fsw) in the following files: + * `./fsw/nos3_defs/cpu1_cfe_es_startup.scr` + * `./fsw/nos3_defs/targets.cmake` + * `./fsw/nos3_defs/tables/*` +* Add new component to ground software (gsw) in the following files: + * `./gsw/cosmos/config/system/nos3_system.txt` + * `./gsw/cosmos/config/tools/cmd_tlm_server/nos3_cmd_tlm_server.txt` + * `./gsw/scripts/launch.sh` + +## Overview +In addition to being used by the template generator, the newsim component provides an executable example for the user. This newsim component is a UART device that accepts multiple commands, including requests for telemetry and data. +The available FSW is for use in the core Flight System (cFS) while the GSW supports COSMOS. +A NOS3 simulation is available which includes both newsim and 42 data providers. + + +# Device Communications +The protocol, commands, and responses of the component are captured below. + +## Protocol +The protocol in use is UART 115200 8N1. +The device is speak when spoken too. +All communications with the device require / contain a header of 0xDEAD and a trailer of 0xBEEF. + +## Commands +All commands received by the device are echoed back to the sender to confirm receipt. +Should commmands involve a reply, the device immediately sends the reply after the command echo. +Device commands are all formatted in the same manner and are fixed in size: +* uint16, 0xDEAD +* uint8, command identifier + - (0) Get Housekeeping + - (1) Get Newsim + - (2) Set Configuration +* uint32, command payload + - Unused for all but set configuration command +* uint16, 0xBEEF + +## Response +Response formats are as follows: +* Housekeeping + - uint16, 0xDEAD + - uint32, Command Counter + * Increments for each command received + - uint32, Configuration + * Internal configuration number in use by the device + - uint32, Status + * Self reported status of the component where zero is completely healthy and each bit represents different errors + * No means to clear / set status except for a power cycle to the device + - uint16, 0xBEEF +* Newsim + - uint16, 0xDEAD + - uint32, Command Counter + * Increments for each command received + - uint16, Data X + * X component of newsim data + - uint16, Data Y + * X component of newsim data + - uint16, Data Z + * X component of newsim data + - uint16, 0xBEEF + + +# Configuration +The various configuration parameters available for each portion of the component are captured below. + +## FSW +Refer to the file [fsw/platform_inc/newsim_platform_cfg.h](fsw/platform_inc/newsim_platform_cfg.h) for the default +configuration settings, as well as a summary on overriding parameters in mission-specific repositories. + +## Simulation +The default configuration returns data that is X * 0.001, Y * 0.002, and Z * 0.003 the request count after conversions: +``` + + newsim_sim + true + libnewsim_sim.so + + NEWSIM + + command + command + newsim-sim-command-node + + usart + usart_29 + 29 + + + + NEWSIM_PROVIDER + + + +``` + +## 42 +Optionally the 42 data provider can be configured in the `nos3-simulator.xml`: +``` + + NEWSIM_42_PROVIDER + localhost + 4242 + 5 + 5 + 0 + +``` + + +# Documentation +If this newsim application had an ICD and/or test procedure, they would be linked here. + +## Releases +We use [SemVer](http://semver.org/) for versioning. For the versions available, see the tags on this repository. +* v1.0.0 - X/Y/Z + - Updated to be a component repository including FSW, GSW, Sim, and Standalone checkout +* v0.1.0 - 10/9/2021 + - Initial release with version tagging diff --git a/components/newsim/fsw/mission_inc/newsim_perfids.h b/components/newsim/fsw/mission_inc/newsim_perfids.h new file mode 100644 index 00000000..ac98ed5f --- /dev/null +++ b/components/newsim/fsw/mission_inc/newsim_perfids.h @@ -0,0 +1,21 @@ +/******************************************************************************* +** File: +** $Id: newsim_perfids.h $ +** +** Purpose: +** Define NEWSIM Performance IDs +** +** Notes: +** +*************************************************************************/ +#ifndef _NEWSIM_PERFIDS_H_ +#define _NEWSIM_PERFIDS_H_ + +/* +** define any performance id integer for the app - try to not have this +** id conflict with other apps. Performance IDs are used for cFE performance +** metrics. +*/ +#define NEWSIM_PERF_ID 500 + +#endif /* _NEWSIM_PERFIDS_H_ */ diff --git a/components/newsim/fsw/platform_inc/newsim_msgids.h b/components/newsim/fsw/platform_inc/newsim_msgids.h new file mode 100644 index 00000000..22818a96 --- /dev/null +++ b/components/newsim/fsw/platform_inc/newsim_msgids.h @@ -0,0 +1,28 @@ +/************************************************************************ +** File: +** $Id: newsim_msgids.h $ +** +** Purpose: +** Define NEWSIM Message IDs +** +*************************************************************************/ +#ifndef _NEWSIM_MSGIDS_H_ +#define _NEWSIM_MSGIDS_H_ + +/* +** CCSDS V1 Command Message IDs (MID) must be 0x18xx +*/ +#define NEWSIM_CMD_MID 0x17FA /* TODO: Change this for your app */ + +/* +** This MID is for commands telling the app to publish its telemetry message +*/ +#define NEWSIM_REQ_HK_MID 0x17FB /* TODO: Change this for your app */ + +/* +** CCSDS V1 Telemetry Message IDs must be 0x08xx +*/ +#define NEWSIM_HK_TLM_MID 0x07FA /* TODO: Change this for your app */ +#define NEWSIM_DEVICE_TLM_MID 0x07FB /* TODO: Change this for your app */ + +#endif /* _NEWSIM_MSGIDS_H_ */ diff --git a/components/newsim/fsw/platform_inc/newsim_platform_cfg.h b/components/newsim/fsw/platform_inc/newsim_platform_cfg.h new file mode 100644 index 00000000..55e0c6b3 --- /dev/null +++ b/components/newsim/fsw/platform_inc/newsim_platform_cfg.h @@ -0,0 +1,29 @@ +/************************************************************************ +** File: +** $Id: newsim_platform_cfg.h $ +** +** Purpose: +** Define newsim Platform Configuration Parameters +** +** Notes: +** +*************************************************************************/ +#ifndef _NEWSIM_PLATFORM_CFG_H_ +#define _NEWSIM_PLATFORM_CFG_H_ + +/* +** Default NEWSIM Configuration +*/ +#ifndef NEWSIM_CFG + /* Notes: + ** NOS3 uart requires matching handle and bus number + */ + #define NEWSIM_CFG_STRING "usart_27" + #define NEWSIM_CFG_HANDLE 27 + #define NEWSIM_CFG_BAUDRATE_HZ 115200 + #define NEWSIM_CFG_MS_TIMEOUT 50 /* Max 255 */ + /* Note: Debug flag disabled (commented out) by default */ + //#define NEWSIM_CFG_DEBUG +#endif + +#endif /* _NEWSIM_PLATFORM_CFG_H_ */ diff --git a/components/newsim/fsw/src/newsim_app.c b/components/newsim/fsw/src/newsim_app.c new file mode 100644 index 00000000..bc189bcf --- /dev/null +++ b/components/newsim/fsw/src/newsim_app.c @@ -0,0 +1,575 @@ +/******************************************************************************* +** File: newsim_app.c +** +** Purpose: +** This file contains the source code for the NEWSIM application. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include +#include "newsim_app.h" + + +/* +** Global Data +*/ +NEWSIM_AppData_t NEWSIM_AppData; + +/* +** Application entry point and main process loop +*/ +void NEWSIM_AppMain(void) +{ + int32 status = OS_SUCCESS; + + /* + ** Create the first Performance Log entry + */ + CFE_ES_PerfLogEntry(NEWSIM_PERF_ID); + + /* + ** Perform application initialization + */ + status = NEWSIM_AppInit(); + if (status != CFE_SUCCESS) + { + NEWSIM_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; + } + + /* + ** Main loop + */ + while (CFE_ES_RunLoop(&NEWSIM_AppData.RunStatus) == true) + { + /* + ** Performance log exit stamp + */ + CFE_ES_PerfLogExit(NEWSIM_PERF_ID); + + /* + ** Pend on the arrival of the next Software Bus message + ** Note that this is the standard, but timeouts are available + */ + status = CFE_SB_ReceiveBuffer((CFE_SB_Buffer_t **)&NEWSIM_AppData.MsgPtr, NEWSIM_AppData.CmdPipe, CFE_SB_PEND_FOREVER); + + /* + ** Begin performance metrics on anything after this line. This will help to determine + ** where we are spending most of the time during this app execution. + */ + CFE_ES_PerfLogEntry(NEWSIM_PERF_ID); + + /* + ** If the CFE_SB_ReceiveBuffer was successful, then continue to process the command packet + ** If not, then exit the application in error. + ** Note that a SB read error should not always result in an app quitting. + */ + if (status == CFE_SUCCESS) + { + NEWSIM_ProcessCommandPacket(); + } + else + { + CFE_EVS_SendEvent(NEWSIM_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, "NEWSIM: SB Pipe Read Error = %d", (int) status); + NEWSIM_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; + } + } + + /* + ** Disable component, which cleans up the interface, upon exit + */ + NEWSIM_Disable(); + + /* + ** Performance log exit stamp + */ + CFE_ES_PerfLogExit(NEWSIM_PERF_ID); + + /* + ** Exit the application + */ + CFE_ES_ExitApp(NEWSIM_AppData.RunStatus); +} + + +/* +** Initialize application +*/ +int32 NEWSIM_AppInit(void) +{ + int32 status = OS_SUCCESS; + + NEWSIM_AppData.RunStatus = CFE_ES_RunStatus_APP_RUN; + + /* + ** Register the events + */ + status = CFE_EVS_Register(NULL, 0, CFE_EVS_EventFilter_BINARY); /* as default, no filters are used */ + if (status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("NEWSIM: Error registering for event services: 0x%08X\n", (unsigned int) status); + return status; + } + + /* + ** Create the Software Bus command pipe + */ + status = CFE_SB_CreatePipe(&NEWSIM_AppData.CmdPipe, NEWSIM_PIPE_DEPTH, "NEWSIM_CMD_PIPE"); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Creating SB Pipe,RC=0x%08X",(unsigned int) status); + return status; + } + + /* + ** Subscribe to ground commands + */ + status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(NEWSIM_CMD_MID), NEWSIM_AppData.CmdPipe); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_SUB_CMD_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Subscribing to HK Gnd Cmds, MID=0x%04X, RC=0x%08X", + NEWSIM_CMD_MID, (unsigned int) status); + return status; + } + + /* + ** Subscribe to housekeeping (hk) message requests + */ + status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(NEWSIM_REQ_HK_MID), NEWSIM_AppData.CmdPipe); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_SUB_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Subscribing to HK Request, MID=0x%04X, RC=0x%08X", + NEWSIM_REQ_HK_MID, (unsigned int) status); + return status; + } + + /* + ** TODO: Subscribe to any other messages here + */ + + + /* + ** Initialize the published HK message - this HK message will contain the + ** telemetry that has been defined in the NEWSIM_HkTelemetryPkt for this app. + */ + CFE_MSG_Init(CFE_MSG_PTR(NEWSIM_AppData.HkTelemetryPkt.TlmHeader), + CFE_SB_ValueToMsgId(NEWSIM_HK_TLM_MID), + NEWSIM_HK_TLM_LNGTH); + + /* + ** Initialize the device packet message + ** This packet is specific to your application + */ + CFE_MSG_Init(CFE_MSG_PTR(NEWSIM_AppData.DevicePkt.TlmHeader), + CFE_SB_ValueToMsgId(NEWSIM_DEVICE_TLM_MID), + NEWSIM_DEVICE_TLM_LNGTH); + + /* + ** TODO: Initialize any other messages that this app will publish + */ + + + /* + ** Always reset all counters during application initialization + */ + NEWSIM_ResetCounters(); + + /* + ** Initialize application data + ** Note that counters are excluded as they were reset in the previous code block + */ + NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled = NEWSIM_DEVICE_DISABLED; + NEWSIM_AppData.HkTelemetryPkt.DeviceHK.DeviceCounter = 0; + NEWSIM_AppData.HkTelemetryPkt.DeviceHK.DeviceConfig = 0; + NEWSIM_AppData.HkTelemetryPkt.DeviceHK.DeviceStatus = 0; + + /* + ** Send an information event that the app has initialized. + ** This is useful for debugging the loading of individual applications. + */ + status = CFE_EVS_SendEvent(NEWSIM_STARTUP_INF_EID, CFE_EVS_EventType_INFORMATION, + "NEWSIM App Initialized. Version %d.%d.%d.%d", + NEWSIM_MAJOR_VERSION, + NEWSIM_MINOR_VERSION, + NEWSIM_REVISION, + NEWSIM_MISSION_REV); + if (status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("NEWSIM: Error sending initialization event: 0x%08X\n", (unsigned int) status); + } + return status; +} + + +/* +** Process packets received on the NEWSIM command pipe +*/ +void NEWSIM_ProcessCommandPacket(void) +{ + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_GetMsgId(NEWSIM_AppData.MsgPtr, &MsgId); + switch (CFE_SB_MsgIdToValue(MsgId)) + { + /* + ** Ground Commands with command codes fall under the NEWSIM_CMD_MID (Message ID) + */ + case NEWSIM_CMD_MID: + NEWSIM_ProcessGroundCommand(); + break; + + /* + ** All other messages, other than ground commands, add to this case statement. + */ + case NEWSIM_REQ_HK_MID: + NEWSIM_ProcessTelemetryRequest(); + break; + + /* + ** All other invalid messages that this app doesn't recognize, + ** increment the command error counter and log as an error event. + */ + default: + NEWSIM_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(NEWSIM_PROCESS_CMD_ERR_EID,CFE_EVS_EventType_ERROR, "NEWSIM: Invalid command packet, MID = 0x%x", CFE_SB_MsgIdToValue(MsgId)); + break; + } + return; +} + + +/* +** Process ground commands +** TODO: Add additional commands required by the specific component +*/ +void NEWSIM_ProcessGroundCommand(void) +{ + int32 status = OS_SUCCESS; + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t CommandCode = 0; + + /* + ** MsgId is only needed if the command code is not recognized. See default case + */ + CFE_MSG_GetMsgId(NEWSIM_AppData.MsgPtr, &MsgId); + + /* + ** Ground Commands, by definition, have a command code (_CC) associated with them + ** Pull this command code from the message and then process + */ + CFE_MSG_GetFcnCode(NEWSIM_AppData.MsgPtr, &CommandCode); + switch (CommandCode) + { + /* + ** NOOP Command + */ + case NEWSIM_NOOP_CC: + /* + ** First, verify the command length immediately after CC identification + ** Note that VerifyCmdLength handles the command and command error counters + */ + if (NEWSIM_VerifyCmdLength(NEWSIM_AppData.MsgPtr, sizeof(NEWSIM_NoArgs_cmd_t)) == OS_SUCCESS) + { + /* Second, send EVS event on successful receipt ground commands*/ + CFE_EVS_SendEvent(NEWSIM_CMD_NOOP_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: NOOP command received"); + /* Third, do the desired command action if applicable, in the case of NOOP it is no operation */ + } + break; + + /* + ** Reset Counters Command + */ + case NEWSIM_RESET_COUNTERS_CC: + if (NEWSIM_VerifyCmdLength(NEWSIM_AppData.MsgPtr, sizeof(NEWSIM_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_CMD_RESET_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: RESET counters command received"); + NEWSIM_ResetCounters(); + } + break; + + /* + ** Enable Command + */ + case NEWSIM_ENABLE_CC: + if (NEWSIM_VerifyCmdLength(NEWSIM_AppData.MsgPtr, sizeof(NEWSIM_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_CMD_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: Enable command received"); + NEWSIM_Enable(); + } + break; + + /* + ** Disable Command + */ + case NEWSIM_DISABLE_CC: + if (NEWSIM_VerifyCmdLength(NEWSIM_AppData.MsgPtr, sizeof(NEWSIM_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(NEWSIM_CMD_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: Disable command received"); + NEWSIM_Disable(); + } + break; + + /* + ** TODO: Edit and add more command codes as appropriate for the application + ** Set Configuration Command + ** Note that this is an example of a command that has additional arguments + */ + case NEWSIM_CONFIG_CC: + if (NEWSIM_VerifyCmdLength(NEWSIM_AppData.MsgPtr, sizeof(NEWSIM_Config_cmd_t)) == OS_SUCCESS) + { + uint32_t config = ntohl(((NEWSIM_Config_cmd_t*) NEWSIM_AppData.MsgPtr)->DeviceCfg); // command is defined as big-endian... need to convert to host representation + CFE_EVS_SendEvent(NEWSIM_CMD_CONFIG_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: Configuration command received: %u", config); + /* Command device to send HK */ + status = NEWSIM_CommandDevice(&NEWSIM_AppData.NewsimUart, NEWSIM_DEVICE_CFG_CMD, config); + if (status == OS_SUCCESS) + { + NEWSIM_AppData.HkTelemetryPkt.DeviceCount++; + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + } + } + break; + + /* + ** Invalid Command Codes + */ + default: + /* Increment the error counter upon receipt of an invalid command */ + NEWSIM_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(NEWSIM_CMD_ERR_EID, CFE_EVS_EventType_ERROR, + "NEWSIM: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); + break; + } + return; +} + + +/* +** Process Telemetry Request - Triggered in response to a telemetery request +** TODO: Add additional telemetry required by the specific component +*/ +void NEWSIM_ProcessTelemetryRequest(void) +{ + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t CommandCode = 0; + + /* MsgId is only needed if the command code is not recognized. See default case */ + CFE_MSG_GetMsgId(NEWSIM_AppData.MsgPtr, &MsgId); + + /* Pull this command code from the message and then process */ + CFE_MSG_GetFcnCode(NEWSIM_AppData.MsgPtr, &CommandCode); + switch (CommandCode) + { + case NEWSIM_REQ_HK_TLM: + NEWSIM_ReportHousekeeping(); + break; + + case NEWSIM_REQ_DATA_TLM: + NEWSIM_ReportDeviceTelemetry(); + break; + + /* + ** Invalid Command Codes + */ + default: + /* Increment the error counter upon receipt of an invalid command */ + NEWSIM_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(NEWSIM_DEVICE_TLM_ERR_EID, CFE_EVS_EventType_ERROR, + "NEWSIM: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); + break; + } + return; +} + + +/* +** Report Application Housekeeping +*/ +void NEWSIM_ReportHousekeeping(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled == NEWSIM_DEVICE_ENABLED) + { + status = NEWSIM_RequestHK(&NEWSIM_AppData.NewsimUart, (NEWSIM_Device_HK_tlm_t*) &NEWSIM_AppData.HkTelemetryPkt.DeviceHK); + if (status == OS_SUCCESS) + { + NEWSIM_AppData.HkTelemetryPkt.DeviceCount++; + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, + "NEWSIM: Request device HK reported error %d", status); + } + } + /* Intentionally do not report errors if disabled */ + + /* Time stamp and publish housekeeping telemetry */ + CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &NEWSIM_AppData.HkTelemetryPkt); + CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &NEWSIM_AppData.HkTelemetryPkt, true); + return; +} + + +/* +** Collect and Report Device Telemetry +*/ +void NEWSIM_ReportDeviceTelemetry(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled == NEWSIM_DEVICE_ENABLED) + { + status = NEWSIM_RequestData(&NEWSIM_AppData.NewsimUart, (NEWSIM_Device_Data_tlm_t*) &NEWSIM_AppData.DevicePkt.Newsim); + if (status == OS_SUCCESS) + { + NEWSIM_AppData.HkTelemetryPkt.DeviceCount++; + /* Time stamp and publish data telemetry */ + CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &NEWSIM_AppData.DevicePkt); + CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &NEWSIM_AppData.DevicePkt, true); + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_REQ_DATA_ERR_EID, CFE_EVS_EventType_ERROR, + "NEWSIM: Request device data reported error %d", status); + } + } + /* Intentionally do not report errors if disabled */ + return; +} + + +/* +** Reset all global counter variables +*/ +void NEWSIM_ResetCounters(void) +{ + NEWSIM_AppData.HkTelemetryPkt.CommandErrorCount = 0; + NEWSIM_AppData.HkTelemetryPkt.CommandCount = 0; + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount = 0; + NEWSIM_AppData.HkTelemetryPkt.DeviceCount = 0; + return; +} + + +/* +** Enable Component +** TODO: Edit for your specific component implementation +*/ +void NEWSIM_Enable(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is disabled */ + if (NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled == NEWSIM_DEVICE_DISABLED) + { + /* + ** Initialize hardware interface data + ** TODO: Make specific to your application depending on protocol in use + ** Note that other components provide examples for the different protocols available + */ + NEWSIM_AppData.NewsimUart.deviceString = NEWSIM_CFG_STRING; + NEWSIM_AppData.NewsimUart.handle = NEWSIM_CFG_HANDLE; + NEWSIM_AppData.NewsimUart.isOpen = PORT_CLOSED; + NEWSIM_AppData.NewsimUart.baud = NEWSIM_CFG_BAUDRATE_HZ; + NEWSIM_AppData.NewsimUart.access_option = uart_access_flag_RDWR; + + /* Open device specific protocols */ + status = uart_init_port(&NEWSIM_AppData.NewsimUart); + if (status == OS_SUCCESS) + { + NEWSIM_AppData.HkTelemetryPkt.DeviceCount++; + NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled = NEWSIM_DEVICE_ENABLED; + CFE_EVS_SendEvent(NEWSIM_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: Device enabled"); + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_UART_INIT_ERR_EID, CFE_EVS_EventType_ERROR, "NEWSIM: UART port initialization error %d", status); + } + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_ENABLE_ERR_EID, CFE_EVS_EventType_ERROR, "NEWSIM: Device enable failed, already enabled"); + } + return; +} + + +/* +** Disable Component +** TODO: Edit for your specific component implementation +*/ +void NEWSIM_Disable(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled == NEWSIM_DEVICE_ENABLED) + { + /* Open device specific protocols */ + status = uart_close_port(&NEWSIM_AppData.NewsimUart); + if (status == OS_SUCCESS) + { + NEWSIM_AppData.HkTelemetryPkt.DeviceCount++; + NEWSIM_AppData.HkTelemetryPkt.DeviceEnabled = NEWSIM_DEVICE_DISABLED; + CFE_EVS_SendEvent(NEWSIM_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "NEWSIM: Device disabled"); + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_UART_CLOSE_ERR_EID, CFE_EVS_EventType_ERROR, "NEWSIM: UART port close error %d", status); + } + } + else + { + NEWSIM_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(NEWSIM_DISABLE_ERR_EID, CFE_EVS_EventType_ERROR, "NEWSIM: Device disable failed, already disabled"); + } + return; +} + + +/* +** Verify command packet length matches expected +*/ +int32 NEWSIM_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length) +{ + int32 status = OS_SUCCESS; + CFE_SB_MsgId_t msg_id = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t cmd_code = 0; + size_t actual_length = 0; + + CFE_MSG_GetSize(msg, &actual_length); + if (expected_length == actual_length) + { + /* Increment the command counter upon receipt of an invalid command */ + NEWSIM_AppData.HkTelemetryPkt.CommandCount++; + } + else + { + CFE_MSG_GetMsgId(msg, &msg_id); + CFE_MSG_GetFcnCode(msg, &cmd_code); + + CFE_EVS_SendEvent(NEWSIM_LEN_ERR_EID, CFE_EVS_EventType_ERROR, + "Invalid msg length: ID = 0x%X, CC = %d, Len = %ld, Expected = %d", + CFE_SB_MsgIdToValue(msg_id), cmd_code, actual_length, expected_length); + + status = OS_ERROR; + + /* Increment the command error counter upon receipt of an invalid command */ + NEWSIM_AppData.HkTelemetryPkt.CommandErrorCount++; + } + return status; +} diff --git a/components/newsim/fsw/src/newsim_app.h b/components/newsim/fsw/src/newsim_app.h new file mode 100644 index 00000000..04dce92e --- /dev/null +++ b/components/newsim/fsw/src/newsim_app.h @@ -0,0 +1,100 @@ +/******************************************************************************* +** File: newsim_app.h +** +** Purpose: +** This is the main header file for the NEWSIM application. +** +*******************************************************************************/ +#ifndef _NEWSIM_APP_H_ +#define _NEWSIM_APP_H_ + +/* +** Include Files +*/ +#include "cfe.h" +#include "newsim_device.h" +#include "newsim_events.h" +#include "newsim_platform_cfg.h" +#include "newsim_perfids.h" +#include "newsim_msg.h" +#include "newsim_msgids.h" +#include "newsim_version.h" +#include "hwlib.h" + + +/* +** Specified pipe depth - how many messages will be queued in the pipe +*/ +#define NEWSIM_PIPE_DEPTH 32 + + +/* +** Enabled and Disabled Definitions +*/ +#define NEWSIM_DEVICE_DISABLED 0 +#define NEWSIM_DEVICE_ENABLED 1 + + +/* +** NEWSIM global data structure +** The cFE convention is to put all global app data in a single struct. +** This struct is defined in the `newsim_app.h` file with one global instance +** in the `.c` file. +*/ +typedef struct +{ + /* + ** Housekeeping telemetry packet + ** Each app defines its own packet which contains its OWN telemetry + */ + NEWSIM_Hk_tlm_t HkTelemetryPkt; /* NEWSIM Housekeeping Telemetry Packet */ + + /* + ** Operational data - not reported in housekeeping + */ + CFE_MSG_Message_t * MsgPtr; /* Pointer to msg received on software bus */ + CFE_SB_PipeId_t CmdPipe; /* Pipe Id for HK command pipe */ + uint32 RunStatus; /* App run status for controlling the application state */ + + /* + ** Device data + ** TODO: Make specific to your application + */ + NEWSIM_Device_tlm_t DevicePkt; /* Device specific data packet */ + + /* + ** Device protocol + ** TODO: Make specific to your application + */ + uart_info_t NewsimUart; /* Hardware protocol definition */ + +} NEWSIM_AppData_t; + + +/* +** Exported Data +** Extern the global struct in the header for the Unit Test Framework (UTF). +*/ +extern NEWSIM_AppData_t NEWSIM_AppData; /* NEWSIM App Data */ + + +/* +** +** Local function prototypes. +** +** Note: Except for the entry point (NEWSIM_AppMain), these +** functions are not called from any other source module. +*/ +void NEWSIM_AppMain(void); +int32 NEWSIM_AppInit(void); +void NEWSIM_ProcessCommandPacket(void); +void NEWSIM_ProcessGroundCommand(void); +void NEWSIM_ProcessTelemetryRequest(void); +void NEWSIM_ReportHousekeeping(void); +void NEWSIM_ReportDeviceTelemetry(void); +void NEWSIM_ResetCounters(void); +void NEWSIM_Enable(void); +void NEWSIM_Disable(void); +int32 NEWSIM_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length); + +#endif /* _NEWSIM_APP_H_ */ diff --git a/components/newsim/fsw/src/newsim_device.c b/components/newsim/fsw/src/newsim_device.c new file mode 100644 index 00000000..560bcf63 --- /dev/null +++ b/components/newsim/fsw/src/newsim_device.c @@ -0,0 +1,274 @@ +/******************************************************************************* +** File: newsim_device.c +** +** Purpose: +** This file contains the source code for the NEWSIM device. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include "newsim_device.h" + + +/* +** Generic read data from device +*/ +int32_t NEWSIM_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length) +{ + int32_t status = OS_SUCCESS; + int32_t bytes = 0; + int32_t bytes_available = 0; + uint8_t ms_timeout_counter = 0; + + /* Wait until all data received or timeout occurs */ + bytes_available = uart_bytes_available(device); + while((bytes_available < data_length) && (ms_timeout_counter < NEWSIM_CFG_MS_TIMEOUT)) + { + ms_timeout_counter++; + OS_TaskDelay(1); + bytes_available = uart_bytes_available(device); + } + + if (ms_timeout_counter < NEWSIM_CFG_MS_TIMEOUT) + { + /* Limit bytes available */ + if (bytes_available > data_length) + { + bytes_available = data_length; + } + + /* Read data */ + bytes = uart_read_port(device, read_data, bytes_available); + if (bytes != bytes_available) + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_ReadData: Bytes read != to requested! \n"); + #endif + status = OS_ERROR; + } /* uart_read */ + } + else + { + status = OS_ERROR; + } /* ms_timeout_counter */ + + return status; +} + + +/* +** Generic command to device +** Note that confirming the echoed response is specific to this implementation +*/ +int32_t NEWSIM_CommandDevice(uart_info_t* device, uint8_t cmd_code, uint32_t payload) +{ + int32_t status = OS_SUCCESS; + int32_t bytes = 0; + uint8_t write_data[NEWSIM_DEVICE_CMD_SIZE]; + uint8_t read_data[NEWSIM_DEVICE_DATA_SIZE]; + + /* Prepare command */ + write_data[0] = NEWSIM_DEVICE_HDR_0; + write_data[1] = NEWSIM_DEVICE_HDR_1; + write_data[2] = cmd_code; + write_data[3] = payload >> 24; + write_data[4] = payload >> 16; + write_data[5] = payload >> 8; + write_data[6] = payload; + write_data[7] = NEWSIM_DEVICE_TRAILER_0; + write_data[8] = NEWSIM_DEVICE_TRAILER_1; + + /* Flush any prior data */ + status = uart_flush(device); + if (status == UART_SUCCESS) + { + /* Write data */ + bytes = uart_write_port(device, write_data, NEWSIM_DEVICE_CMD_SIZE); + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_CommandDevice[%d] = ", bytes); + for (uint32_t i = 0; i < NEWSIM_DEVICE_CMD_SIZE; i++) + { + OS_printf("%02x", write_data[i]); + } + OS_printf("\n"); + #endif + if (bytes == NEWSIM_DEVICE_CMD_SIZE) + { + status = NEWSIM_ReadData(device, read_data, NEWSIM_DEVICE_CMD_SIZE); + if (status == OS_SUCCESS) + { + /* Confirm echoed response */ + bytes = 0; + while ((bytes < (int32_t) NEWSIM_DEVICE_CMD_SIZE) && (status == OS_SUCCESS)) + { + if (read_data[bytes] != write_data[bytes]) + { + status = OS_ERROR; + } + bytes++; + } + } /* NEWSIM_ReadData */ + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf("NEWSIM_CommandDevice - NEWSIM_ReadData returned %d \n", status); + #endif + } + } + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf("NEWSIM_CommandDevice - uart_write_port returned %d, expected %d \n", bytes, NEWSIM_DEVICE_CMD_SIZE); + #endif + } /* uart_write */ + } /* uart_flush*/ + return status; +} + + +/* +** Request housekeeping command +*/ +int32_t NEWSIM_RequestHK(uart_info_t* device, NEWSIM_Device_HK_tlm_t* data) +{ + int32_t status = OS_SUCCESS; + uint8_t read_data[NEWSIM_DEVICE_HK_SIZE]; + + /* Command device to send HK */ + status = NEWSIM_CommandDevice(device, NEWSIM_DEVICE_REQ_HK_CMD, 0); + if (status == OS_SUCCESS) + { + /* Read HK data */ + status = NEWSIM_ReadData(device, read_data, sizeof(read_data)); + if (status == OS_SUCCESS) + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestHK = "); + for (uint32_t i = 0; i < sizeof(read_data); i++) + { + OS_printf("%02x", read_data[i]); + } + OS_printf("\n"); + #endif + + /* Verify data header and trailer */ + if ((read_data[0] == NEWSIM_DEVICE_HDR_0) && + (read_data[1] == NEWSIM_DEVICE_HDR_1) && + (read_data[14] == NEWSIM_DEVICE_TRAILER_0) && + (read_data[15] == NEWSIM_DEVICE_TRAILER_1) ) + { + data->DeviceCounter = read_data[2] << 24; + data->DeviceCounter |= read_data[3] << 16; + data->DeviceCounter |= read_data[4] << 8; + data->DeviceCounter |= read_data[5]; + + data->DeviceConfig = read_data[6] << 24; + data->DeviceConfig |= read_data[7] << 16; + data->DeviceConfig |= read_data[8] << 8; + data->DeviceConfig |= read_data[9]; + + data->DeviceStatus = read_data[10] << 24; + data->DeviceStatus |= read_data[11] << 16; + data->DeviceStatus |= read_data[12] << 8; + data->DeviceStatus |= read_data[13]; + + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); + OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); + OS_printf(" Config = 0x%08x \n", data->DeviceConfig); + OS_printf(" Status = 0x%08x \n", data->DeviceStatus); + OS_printf(" Trailer = 0x%02x%02x \n", read_data[14], read_data[15]); + #endif + } + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestHK: NEWSIM_ReadData reported error %d \n", status); + #endif + status = OS_ERROR; + } + } /* NEWSIM_ReadData */ + } + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestHK: NEWSIM_CommandDevice reported error %d \n", status); + #endif + } + return status; +} + + +/* +** Request data command +*/ +int32_t NEWSIM_RequestData(uart_info_t* device, NEWSIM_Device_Data_tlm_t* data) +{ + int32_t status = OS_SUCCESS; + uint8_t read_data[NEWSIM_DEVICE_DATA_SIZE]; + + /* Command device to send HK */ + status = NEWSIM_CommandDevice(device, NEWSIM_DEVICE_REQ_DATA_CMD, 0); + if (status == OS_SUCCESS) + { + /* Read HK data */ + status = NEWSIM_ReadData(device, read_data, sizeof(read_data)); + if (status == OS_SUCCESS) + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestData = "); + for (uint32_t i = 0; i < sizeof(read_data); i++) + { + OS_printf("%02x", read_data[i]); + } + OS_printf("\n"); + #endif + + /* Verify data header and trailer */ + if ((read_data[0] == NEWSIM_DEVICE_HDR_0) && + (read_data[1] == NEWSIM_DEVICE_HDR_1) && + (read_data[12] == NEWSIM_DEVICE_TRAILER_0) && + (read_data[13] == NEWSIM_DEVICE_TRAILER_1) ) + { + data->DeviceCounter = read_data[2] << 24; + data->DeviceCounter |= read_data[3] << 16; + data->DeviceCounter |= read_data[4] << 8; + data->DeviceCounter |= read_data[5]; + + data->DeviceDataX = read_data[6] << 8; + data->DeviceDataX |= read_data[7]; + + data->DeviceDataY = read_data[8] << 8; + data->DeviceDataY |= read_data[9]; + + data->DeviceDataZ = read_data[10] << 8; + data->DeviceDataZ |= read_data[11]; + + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); + OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); + OS_printf(" Data X = 0x%04x, %d \n", data->DeviceDataX, data->DeviceDataX); + OS_printf(" Data Y = 0x%04x, %d \n", data->DeviceDataY, data->DeviceDataY); + OS_printf(" Data Z = 0x%04x, %d \n", data->DeviceDataZ, data->DeviceDataZ); + OS_printf(" Trailer = 0x%02x%02x \n", read_data[12], read_data[13]); + #endif + } + } + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestData: Invalid data read! \n"); + #endif + status = OS_ERROR; + } /* NEWSIM_ReadData */ + } + else + { + #ifdef NEWSIM_CFG_DEBUG + OS_printf(" NEWSIM_RequestData: NEWSIM_CommandDevice reported error %d \n", status); + #endif + } + return status; +} diff --git a/components/newsim/fsw/src/newsim_device.h b/components/newsim/fsw/src/newsim_device.h new file mode 100644 index 00000000..8214d802 --- /dev/null +++ b/components/newsim/fsw/src/newsim_device.h @@ -0,0 +1,77 @@ +/******************************************************************************* +** File: newsim_device.h +** +** Purpose: +** This is the header file for the NEWSIM device. +** +*******************************************************************************/ +#ifndef _NEWSIM_DEVICE_H_ +#define _NEWSIM_DEVICE_H_ + +/* +** Required header files. +*/ +#include "device_cfg.h" +#include "hwlib.h" +#include "newsim_platform_cfg.h" + + +/* +** Type definitions +** TODO: Make specific to your application +*/ +#define NEWSIM_DEVICE_HDR 0xDEAD +#define NEWSIM_DEVICE_HDR_0 0xDE +#define NEWSIM_DEVICE_HDR_1 0xAD + +#define NEWSIM_DEVICE_NOOP_CMD 0x00 +#define NEWSIM_DEVICE_REQ_HK_CMD 0x01 +#define NEWSIM_DEVICE_REQ_DATA_CMD 0x02 +#define NEWSIM_DEVICE_CFG_CMD 0x03 + +#define NEWSIM_DEVICE_TRAILER 0xBEEF +#define NEWSIM_DEVICE_TRAILER_0 0xBE +#define NEWSIM_DEVICE_TRAILER_1 0xEF + +#define NEWSIM_DEVICE_HDR_TRL_LEN 4 +#define NEWSIM_DEVICE_CMD_SIZE 9 + +/* +** NEWSIM device housekeeping telemetry definition +*/ +typedef struct +{ + uint32_t DeviceCounter; + uint32_t DeviceConfig; + uint32_t DeviceStatus; + +} __attribute__((packed)) NEWSIM_Device_HK_tlm_t; +#define NEWSIM_DEVICE_HK_LNGTH sizeof ( NEWSIM_Device_HK_tlm_t ) +#define NEWSIM_DEVICE_HK_SIZE NEWSIM_DEVICE_HK_LNGTH + NEWSIM_DEVICE_HDR_TRL_LEN + + +/* +** NEWSIM device data telemetry definition +*/ +typedef struct +{ + uint32_t DeviceCounter; + uint16_t DeviceDataX; + uint16_t DeviceDataY; + uint16_t DeviceDataZ; + +} __attribute__((packed)) NEWSIM_Device_Data_tlm_t; +#define NEWSIM_DEVICE_DATA_LNGTH sizeof ( NEWSIM_Device_Data_tlm_t ) +#define NEWSIM_DEVICE_DATA_SIZE NEWSIM_DEVICE_DATA_LNGTH + NEWSIM_DEVICE_HDR_TRL_LEN + + +/* +** Prototypes +*/ +int32_t NEWSIM_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length); +int32_t NEWSIM_CommandDevice(uart_info_t* device, uint8_t cmd, uint32_t payload); +int32_t NEWSIM_RequestHK(uart_info_t* device, NEWSIM_Device_HK_tlm_t* data); +int32_t NEWSIM_RequestData(uart_info_t* device, NEWSIM_Device_Data_tlm_t* data); + + +#endif /* _NEWSIM_DEVICE_H_ */ diff --git a/components/newsim/fsw/src/newsim_events.h b/components/newsim/fsw/src/newsim_events.h new file mode 100644 index 00000000..4baa6337 --- /dev/null +++ b/components/newsim/fsw/src/newsim_events.h @@ -0,0 +1,47 @@ +/************************************************************************ +** File: +** newsim_events.h +** +** Purpose: +** Define NEWSIM application event IDs +** +*************************************************************************/ + +#ifndef _NEWSIM_EVENTS_H_ +#define _NEWSIM_EVENTS_H_ + +/* Standard app event IDs */ +#define NEWSIM_RESERVED_EID 0 +#define NEWSIM_STARTUP_INF_EID 1 +#define NEWSIM_LEN_ERR_EID 2 +#define NEWSIM_PIPE_ERR_EID 3 +#define NEWSIM_SUB_CMD_ERR_EID 4 +#define NEWSIM_SUB_REQ_HK_ERR_EID 5 +#define NEWSIM_PROCESS_CMD_ERR_EID 6 + +/* Standard command event IDs */ +#define NEWSIM_CMD_ERR_EID 10 +#define NEWSIM_CMD_NOOP_INF_EID 11 +#define NEWSIM_CMD_RESET_INF_EID 12 +#define NEWSIM_CMD_ENABLE_INF_EID 13 +#define NEWSIM_ENABLE_INF_EID 14 +#define NEWSIM_ENABLE_ERR_EID 15 +#define NEWSIM_CMD_DISABLE_INF_EID 16 +#define NEWSIM_DISABLE_INF_EID 17 +#define NEWSIM_DISABLE_ERR_EID 18 + +/* Device specific command event IDs */ +#define NEWSIM_CMD_CONFIG_INF_EID 20 + +/* Standard telemetry event IDs */ +#define NEWSIM_DEVICE_TLM_ERR_EID 30 +#define NEWSIM_REQ_HK_ERR_EID 31 + +/* Device specific telemetry event IDs */ +#define NEWSIM_REQ_DATA_ERR_EID 32 + +/* Hardware protocol event IDs */ +#define NEWSIM_UART_INIT_ERR_EID 40 +#define NEWSIM_UART_CLOSE_ERR_EID 41 + +#endif /* _NEWSIM_EVENTS_H_ */ diff --git a/components/newsim/fsw/src/newsim_msg.h b/components/newsim/fsw/src/newsim_msg.h new file mode 100644 index 00000000..57301c53 --- /dev/null +++ b/components/newsim/fsw/src/newsim_msg.h @@ -0,0 +1,89 @@ +/******************************************************************************* +** File: +** newsim_msg.h +** +** Purpose: +** Define NEWSIM application commands and telemetry messages +** +*******************************************************************************/ +#ifndef _NEWSIM_MSG_H_ +#define _NEWSIM_MSG_H_ + +#include "cfe.h" +#include "newsim_device.h" + + +/* +** Ground Command Codes +** TODO: Add additional commands required by the specific component +*/ +#define NEWSIM_NOOP_CC 0 +#define NEWSIM_RESET_COUNTERS_CC 1 +#define NEWSIM_ENABLE_CC 2 +#define NEWSIM_DISABLE_CC 3 +#define NEWSIM_CONFIG_CC 4 + + +/* +** Telemetry Request Command Codes +** TODO: Add additional commands required by the specific component +*/ +#define NEWSIM_REQ_HK_TLM 0 +#define NEWSIM_REQ_DATA_TLM 1 + + +/* +** Generic "no arguments" command type definition +*/ +typedef struct +{ + /* Every command requires a header used to identify it */ + CFE_MSG_CommandHeader_t CmdHeader; + +} NEWSIM_NoArgs_cmd_t; + + +/* +** NEWSIM write configuration command +*/ +typedef struct +{ + CFE_MSG_CommandHeader_t CmdHeader; + uint32 DeviceCfg; + +} NEWSIM_Config_cmd_t; + + +/* +** NEWSIM device telemetry definition +*/ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TlmHeader; + NEWSIM_Device_Data_tlm_t Newsim; + +} __attribute__((packed)) NEWSIM_Device_tlm_t; +#define NEWSIM_DEVICE_TLM_LNGTH sizeof ( NEWSIM_Device_tlm_t ) + + +/* +** NEWSIM housekeeping type definition +*/ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TlmHeader; + uint8 CommandErrorCount; + uint8 CommandCount; + uint8 DeviceErrorCount; + uint8 DeviceCount; + + /* + ** TODO: Edit and add specific telemetry values to this struct + */ + uint8 DeviceEnabled; + NEWSIM_Device_HK_tlm_t DeviceHK; + +} __attribute__((packed)) NEWSIM_Hk_tlm_t; +#define NEWSIM_HK_TLM_LNGTH sizeof ( NEWSIM_Hk_tlm_t ) + +#endif /* _NEWSIM_MSG_H_ */ diff --git a/components/newsim/fsw/src/newsim_version.h b/components/newsim/fsw/src/newsim_version.h new file mode 100644 index 00000000..d7c34a7d --- /dev/null +++ b/components/newsim/fsw/src/newsim_version.h @@ -0,0 +1,19 @@ +/************************************************************************ +** File: +** $Id: newsim_app_version.h $ +** +** Purpose: +** The Newsim Application header file containing version number +** +*************************************************************************/ + +/* The Newsim Application header file containing version number */ +#ifndef _NEWSIM_VERSION_H_ +#define _NEWSIM_VERSION_H_ + +#define NEWSIM_MAJOR_VERSION 1 +#define NEWSIM_MINOR_VERSION 0 +#define NEWSIM_REVISION 0 +#define NEWSIM_MISSION_REV 0 + +#endif diff --git a/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_CMD.txt b/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_CMD.txt new file mode 100644 index 00000000..862dc813 --- /dev/null +++ b/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_CMD.txt @@ -0,0 +1,49 @@ +COMMAND NEWSIM NEWSIM_NOOP_CC BIG_ENDIAN "Newsim NOOP Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FA "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND NEWSIM NEWSIM_RST_COUNTERS_CC BIG_ENDIAN "Newsim Reset Counters Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FA "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND NEWSIM NEWSIM_ENABLE_CC BIG_ENDIAN "Newsim Enable Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FA "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 2 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND NEWSIM NEWSIM_DISABLE_CC BIG_ENDIAN "Newsim Disable Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FA "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 3 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND NEWSIM NEWSIM_CONFIG_CC BIG_ENDIAN "Newsim Configuration Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FA "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 5 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 4 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + APPEND_PARAMETER DEVICE_CONFIG 32 UINT MIN_UINT32 MAX_UINT32 0 "Device Configuration" + +COMMAND NEWSIM NEWSIM_REQ_HK BIG_ENDIAN "Newsim Request HK Packet Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FB "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND NEWSIM NEWSIM_REQ_DATA BIG_ENDIAN "Newsim Request Data Packet Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x17FB "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" diff --git a/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_TLM.txt b/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_TLM.txt new file mode 100644 index 00000000..6af42d31 --- /dev/null +++ b/components/newsim/gsw/NEWSIM/cmd_tlm/NEWSIM_TLM.txt @@ -0,0 +1,44 @@ +TELEMETRY NEWSIM NEWSIM_HK_TLM LITTLE_ENDIAN "NEWSIM_Hk_tlm_t" + APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x07FA "CCSDS Packet Identification" BIG_ENDIAN + APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN + APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN + APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" + APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" + APPEND_ITEM CCSDS_SPARE 32 UINT "" + APPEND_ITEM CMD_ERR_COUNT 8 UINT "Command Error Count" + APPEND_ITEM CMD_COUNT 8 UINT "Command Count" + APPEND_ITEM DEVICE_ERR_COUNT 8 UINT "Device Command Error Count" + APPEND_ITEM DEVICE_COUNT 8 UINT "Device Command Count" + APPEND_ITEM DEVICE_ENABLED 8 UINT "Device Enable Status" + STATE DISABLED 0 + STATE ENABLED 1 + # NEWSIM_Device_HK_tlm_t + APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" + APPEND_ITEM DEVICE_CONFIG 32 UINT "Reported Device Configuration" + APPEND_ITEM DEVICE_STATUS 32 UINT "Reported Device Status" + +TELEMETRY NEWSIM NEWSIM_DATA_TLM LITTLE_ENDIAN "NEWSIM_Device_tlm_t" + APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x07FB "CCSDS Packet Identification" BIG_ENDIAN + APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN + APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN + APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" + APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" + APPEND_ITEM CCSDS_SPARE 32 UINT "" + # NEWSIM_Device_Data_tlm_t + APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" + APPEND_ITEM RAW_NEWSIM_X 16 UINT "Raw newsim data x component (1-65535)" + APPEND_ITEM RAW_NEWSIM_Y 16 UINT "Raw newsim data y component (1-65535)" + APPEND_ITEM RAW_NEWSIM_Z 16 UINT "Raw newsim data z component (1-65535)" +# APPEND_ITEM PAD 16 UINT "Because the packed struct it came from has a stride address of 32 and cFS does not serialize" + APPEND_ITEM NEWSIM_X 0 DERIVED "Newsim data unit vector x component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_NEWSIM_X") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END + APPEND_ITEM NEWSIM_Y 0 DERIVED "Newsim data unit vector y component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_NEWSIM_Y") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END + APPEND_ITEM NEWSIM_Z 0 DERIVED "Newsim data unit vector z component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_NEWSIM_Z") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END diff --git a/components/newsim/gsw/NEWSIM/target.txt b/components/newsim/gsw/NEWSIM/target.txt new file mode 100644 index 00000000..f942b7ed --- /dev/null +++ b/components/newsim/gsw/NEWSIM/target.txt @@ -0,0 +1,10 @@ +# Ignored Parameters +# IGNORE_PARAMETER parameter_name + +# CCSDS +IGNORE_PARAMETER CCSDS_STREAMID +IGNORE_PARAMETER CCSDS_SEQUENCE +IGNORE_PARAMETER CCSDS_LENGTH +IGNORE_PARAMETER CCSDS_SPARE +IGNORE_PARAMETER CCSDS_FC +IGNORE_PARAMETER CCSDS_CHECKSUM diff --git a/components/newsim/sim/CMakeLists.txt b/components/newsim/sim/CMakeLists.txt new file mode 100644 index 00000000..1134e3b4 --- /dev/null +++ b/components/newsim/sim/CMakeLists.txt @@ -0,0 +1,31 @@ +project(newsim_sim) + +find_package(ITC_Common REQUIRED QUIET COMPONENTS itc_logger) +find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart) + +include_directories(inc + ${sim_common_SOURCE_DIR}/inc + ${ITC_Common_INCLUDE_DIRS} + ${NOSENGINE_INCLUDE_DIRS}) + +set(newsim_sim_src + src/newsim_hardware_model.cpp + src/newsim_42_data_provider.cpp + src/newsim_data_provider.cpp + src/newsim_data_point.cpp +) + +# For Code::Blocks and other IDEs +file(GLOB newsim_sim_inc inc/*.hpp) + +set(newsim_sim_libs + sim_common + ${ITC_Common_LIBRARIES} + ${NOSENGINE_LIBRARIES} +) + +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib") # Pick up .so in install directory + +add_library(newsim_sim SHARED ${newsim_sim_src} ${newsim_sim_inc}) +target_link_libraries(newsim_sim ${newsim_sim_libs}) +install(TARGETS newsim_sim LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) diff --git a/components/newsim/sim/inc/newsim_42_data_provider.hpp b/components/newsim/sim/inc/newsim_42_data_provider.hpp new file mode 100644 index 00000000..232eeab5 --- /dev/null +++ b/components/newsim/sim/inc/newsim_42_data_provider.hpp @@ -0,0 +1,30 @@ +#ifndef NOS3_NEWSIM42DATAPROVIDER_HPP +#define NOS3_NEWSIM42DATAPROVIDER_HPP + +#include +#include +#include +#include + +namespace Nos3 +{ + /* Standard for a 42 data provider */ + class Newsim42DataProvider : public SimData42SocketProvider + { + public: + /* Constructors */ + Newsim42DataProvider(const boost::property_tree::ptree& config); + + /* Accessors */ + boost::shared_ptr get_data_point(void) const; + + private: + /* Disallow these */ + ~Newsim42DataProvider(void) {}; + Newsim42DataProvider& operator=(const Newsim42DataProvider&) {return *this;}; + + int16_t _sc; /* Which spacecraft number to parse out of 42 data */ + }; +} + +#endif diff --git a/components/newsim/sim/inc/newsim_data_point.hpp b/components/newsim/sim/inc/newsim_data_point.hpp new file mode 100644 index 00000000..2c458b0b --- /dev/null +++ b/components/newsim/sim/inc/newsim_data_point.hpp @@ -0,0 +1,47 @@ +#ifndef NOS3_NEWSIMDATAPOINT_HPP +#define NOS3_NEWSIMDATAPOINT_HPP + +#include +#include + +namespace Nos3 +{ + /* Standard for a data point used transfer data between a data provider and a hardware model */ + class NewsimDataPoint : public Sim42DataPoint + { + public: + /* Constructors */ + NewsimDataPoint(double count); + NewsimDataPoint(int16_t spacecraft, const boost::shared_ptr dp); + + /* Accessors */ + /* Provide the hardware model a way to get the specific data out of the data point */ + std::string to_string(void) const; + double get_newsim_data_x(void) const {parse_data_point(); return _newsim_data[0];} + double get_newsim_data_y(void) const {parse_data_point(); return _newsim_data[1];} + double get_newsim_data_z(void) const {parse_data_point(); return _newsim_data[2];} + bool is_newsim_data_valid(void) const {parse_data_point(); return _newsim_data_is_valid;} + + private: + /* Disallow these */ + NewsimDataPoint(void) {}; + NewsimDataPoint(const NewsimDataPoint& sdp) : Sim42DataPoint(sdp) {}; + ~NewsimDataPoint(void) {}; + + // Private mutators + inline void parse_data_point(void) const {if (_not_parsed) do_parsing();} + void do_parsing(void) const; + + mutable Sim42DataPoint _dp; + int16_t _sc; + // mutable below so parsing can be on demand: + mutable bool _42_parsing; + mutable bool _not_parsed; + /* Specific data you need to get from the data provider to the hardware model */ + /* You only get to this data through the accessors above */ + mutable bool _newsim_data_is_valid; + mutable double _newsim_data[3]; + }; +} + +#endif diff --git a/components/newsim/sim/inc/newsim_data_provider.hpp b/components/newsim/sim/inc/newsim_data_provider.hpp new file mode 100644 index 00000000..c7b87ef6 --- /dev/null +++ b/components/newsim/sim/inc/newsim_data_provider.hpp @@ -0,0 +1,29 @@ +#ifndef NOS3_NEWSIMDATAPROVIDER_HPP +#define NOS3_NEWSIMDATAPROVIDER_HPP + +#include +#include +#include +#include + +namespace Nos3 +{ + class NewsimDataProvider : public SimIDataProvider + { + public: + /* Constructors */ + NewsimDataProvider(const boost::property_tree::ptree& config); + + /* Accessors */ + boost::shared_ptr get_data_point(void) const; + + private: + /* Disallow these */ + ~NewsimDataProvider(void) {}; + NewsimDataProvider& operator=(const NewsimDataProvider&) {return *this;}; + + mutable double _request_count; + }; +} + +#endif diff --git a/components/newsim/sim/inc/newsim_hardware_model.hpp b/components/newsim/sim/inc/newsim_hardware_model.hpp new file mode 100644 index 00000000..d4dcedae --- /dev/null +++ b/components/newsim/sim/inc/newsim_hardware_model.hpp @@ -0,0 +1,61 @@ +#ifndef NOS3_NEWSIMHARDWAREMODEL_HPP +#define NOS3_NEWSIMHARDWAREMODEL_HPP + +/* +** Includes +*/ +#include + +#include +#include + +#include +#include /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ + +#include +#include +#include + + +/* +** Defines +*/ +#define NEWSIM_SIM_SUCCESS 0 +#define NEWSIM_SIM_ERROR 1 + + +/* +** Namespace +*/ +namespace Nos3 +{ + /* Standard for a hardware model */ + class NewsimHardwareModel : public SimIHardwareModel + { + public: + /* Constructor and destructor */ + NewsimHardwareModel(const boost::property_tree::ptree& config); + ~NewsimHardwareModel(void); + + private: + /* Private helper methods */ + void create_newsim_hk(std::vector& out_data); + void create_newsim_data(std::vector& out_data); + void uart_read_callback(const uint8_t *buf, size_t len); /* Handle data the hardware receives from its protocol bus */ + void command_callback(NosEngine::Common::Message msg); /* Handle backdoor commands and time tick to the simulator */ + + /* Private data members */ + std::unique_ptr _uart_connection; /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ + std::unique_ptr _time_bus; /* Standard */ + + SimIDataProvider* _newsim_dp; /* Only needed if the sim has a data provider */ + + /* Internal state data */ + std::uint8_t _enabled; + std::uint32_t _count; + std::uint32_t _config; + std::uint32_t _status; + }; +} + +#endif diff --git a/components/newsim/sim/src/newsim_42_data_provider.cpp b/components/newsim/sim/src/newsim_42_data_provider.cpp new file mode 100644 index 00000000..38c54f08 --- /dev/null +++ b/components/newsim/sim/src/newsim_42_data_provider.cpp @@ -0,0 +1,32 @@ +#include + +namespace Nos3 +{ + REGISTER_DATA_PROVIDER(Newsim42DataProvider,"NEWSIM_42_PROVIDER"); + + extern ItcLogger::Logger *sim_logger; + + Newsim42DataProvider::Newsim42DataProvider(const boost::property_tree::ptree& config) : SimData42SocketProvider(config) + { + sim_logger->trace("Newsim42DataProvider::Newsim42DataProvider: Constructor executed"); + + connect_reader_thread_as_42_socket_client( + config.get("simulator.hardware-model.data-provider.hostname", "localhost"), + config.get("simulator.hardware-model.data-provider.port", 4242) ); + + _sc = config.get("simulator.hardware-model.data-provider.spacecraft", 0); + } + + boost::shared_ptr Newsim42DataProvider::get_data_point(void) const + { + sim_logger->trace("Newsim42DataProvider::get_data_point: Executed"); + + /* Get the 42 data */ + const boost::shared_ptr dp42 = boost::dynamic_pointer_cast(SimData42SocketProvider::get_data_point()); + + /* Prepare the specific data */ + SimIDataPoint *dp = new NewsimDataPoint(_sc, dp42); + + return boost::shared_ptr(dp); + } +} diff --git a/components/newsim/sim/src/newsim_data_point.cpp b/components/newsim/sim/src/newsim_data_point.cpp new file mode 100644 index 00000000..f49e55ea --- /dev/null +++ b/components/newsim/sim/src/newsim_data_point.cpp @@ -0,0 +1,87 @@ +#include +#include + +namespace Nos3 +{ + extern ItcLogger::Logger *sim_logger; + + NewsimDataPoint::NewsimDataPoint(double count) + { + sim_logger->trace("NewsimDataPoint::NewsimDataPoint: Defined Constructor executed"); + + /* Do calculations based on provided data */ + _42_parsing = false; + _newsim_data_is_valid = true; + _newsim_data[0] = count * 0.001; + _newsim_data[1] = count * 0.002; + _newsim_data[2] = count * 0.003; + } + + NewsimDataPoint::NewsimDataPoint(int16_t spacecraft, const boost::shared_ptr dp) : _dp(*dp), _sc(spacecraft) + { + sim_logger->trace("NewsimDataPoint::NewsimDataPoint: 42 Constructor executed"); + + /* Initialize data */ + _42_parsing = true; + _newsim_data_is_valid = false; + _newsim_data[0] = _newsim_data[1] = _newsim_data[2] = 0.0; + } + + void NewsimDataPoint::do_parsing(void) const + { + if (_42_parsing) + { + try { + /* + ** Declare 42 telemetry string prefix + ** 42 variables defined in `42/Include/42types.h` + ** 42 data stream defined in `42/Source/IPC/SimWriteToSocket.c` + */ + std::string key; + key.append("SC[").append(std::to_string(_sc)).append("].svb"); // SC[N].svb + + /* Parse 42 telemetry */ + std::string values = _dp.get_value_for_key(key); + + std::vector data; + data.reserve(3); + parse_double_vector(values, data); + + _newsim_data[0] = data[0]; + _newsim_data[1] = data[1]; + _newsim_data[2] = data[2]; + + /* Mark data as valid */ + _newsim_data_is_valid = true; + + _not_parsed = false; + + /* Debug print */ + sim_logger->trace("NewsimDataPoint::NewsimDataPoint: Parsed svb = %f %f %f", _newsim_data[0], _newsim_data[1], _newsim_data[2]); + } catch (const std::exception &e) { + sim_logger->error("NewsimDataPoint::NewsimDataPoint: Error parsing svb. Error=%s", e.what()); + } + } + } + + /* Used for printing a representation of the data point */ + std::string NewsimDataPoint::to_string(void) const + { + sim_logger->trace("NewsimDataPoint::to_string: Executed"); + + std::stringstream ss; + + ss << std::fixed << std::setfill(' '); + ss << "Newsim Data Point: Valid: "; + ss << (_newsim_data_is_valid ? "Valid" : "INVALID"); + ss << std::setprecision(std::numeric_limits::digits10); /* Full double precision */ + ss << " Newsim Data: " + << _newsim_data[0] + << " " + << _newsim_data[1] + << " " + << _newsim_data[2]; + + return ss.str(); + } +} /* namespace Nos3 */ diff --git a/components/newsim/sim/src/newsim_data_provider.cpp b/components/newsim/sim/src/newsim_data_provider.cpp new file mode 100644 index 00000000..5d8c2ac2 --- /dev/null +++ b/components/newsim/sim/src/newsim_data_provider.cpp @@ -0,0 +1,28 @@ +#include + +namespace Nos3 +{ + REGISTER_DATA_PROVIDER(NewsimDataProvider,"NEWSIM_PROVIDER"); + + extern ItcLogger::Logger *sim_logger; + + NewsimDataProvider::NewsimDataProvider(const boost::property_tree::ptree& config) : SimIDataProvider(config) + { + sim_logger->trace("NewsimDataProvider::NewsimDataProvider: Constructor executed"); + _request_count = 0; + } + + boost::shared_ptr NewsimDataProvider::get_data_point(void) const + { + sim_logger->trace("NewsimDataProvider::get_data_point: Executed"); + + /* Prepare the provider data */ + _request_count++; + + /* Request a data point */ + SimIDataPoint *dp = new NewsimDataPoint(_request_count); + + /* Return the data point */ + return boost::shared_ptr(dp); + } +} diff --git a/components/newsim/sim/src/newsim_hardware_model.cpp b/components/newsim/sim/src/newsim_hardware_model.cpp new file mode 100644 index 00000000..e0bdd973 --- /dev/null +++ b/components/newsim/sim/src/newsim_hardware_model.cpp @@ -0,0 +1,326 @@ +#include + +namespace Nos3 +{ + REGISTER_HARDWARE_MODEL(NewsimHardwareModel,"NEWSIM"); + + extern ItcLogger::Logger *sim_logger; + + NewsimHardwareModel::NewsimHardwareModel(const boost::property_tree::ptree& config) : SimIHardwareModel(config), + _enabled(NEWSIM_SIM_SUCCESS), _count(0), _config(0), _status(0) + { + /* Get the NOS engine connection string */ + std::string connection_string = config.get("common.nos-connection-string", "tcp://127.0.0.1:12001"); + sim_logger->info("NewsimHardwareModel::NewsimHardwareModel: NOS Engine connection string: %s.", connection_string.c_str()); + + /* Get a data provider */ + std::string dp_name = config.get("simulator.hardware-model.data-provider.type", "NEWSIM_42_PROVIDER"); + _newsim_dp = SimDataProviderFactory::Instance().Create(dp_name, config); + sim_logger->info("NewsimHardwareModel::NewsimHardwareModel: Data provider %s created.", dp_name.c_str()); + + /* Get on a protocol bus */ + /* Note: Initialized defaults in case value not found in config file */ + std::string bus_name = "usart_27"; + int node_port = 27; + if (config.get_child_optional("simulator.hardware-model.connections")) + { + /* Loop through the connections for hardware model */ + BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("simulator.hardware-model.connections")) + { + /* v.second is the child tree (v.first is the name of the child) */ + if (v.second.get("type", "").compare("usart") == 0) + { + /* Configuration found */ + bus_name = v.second.get("bus-name", bus_name); + node_port = v.second.get("node-port", node_port); + break; + } + } + } + _uart_connection.reset(new NosEngine::Uart::Uart(_hub, config.get("simulator.name", "newsim_sim"), connection_string, bus_name)); + _uart_connection->open(node_port); + sim_logger->info("NewsimHardwareModel::NewsimHardwareModel: Now on UART bus name %s, port %d.", bus_name.c_str(), node_port); + + /* Configure protocol callback */ + _uart_connection->set_read_callback(std::bind(&NewsimHardwareModel::uart_read_callback, this, std::placeholders::_1, std::placeholders::_2)); + + /* Get on the command bus*/ + std::string time_bus_name = "command"; + if (config.get_child_optional("hardware-model.connections")) + { + /* Loop through the connections for the hardware model */ + BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("hardware-model.connections")) + { + /* v.first is the name of the child */ + /* v.second is the child tree */ + if (v.second.get("type", "").compare("time") == 0) // + { + time_bus_name = v.second.get("bus-name", "command"); + /* Found it... don't need to go through any more items*/ + break; + } + } + } + _time_bus.reset(new NosEngine::Client::Bus(_hub, connection_string, time_bus_name)); + sim_logger->info("NewsimHardwareModel::NewsimHardwareModel: Now on time bus named %s.", time_bus_name.c_str()); + + /* Construction complete */ + sim_logger->info("NewsimHardwareModel::NewsimHardwareModel: Construction complete."); + } + + + NewsimHardwareModel::~NewsimHardwareModel(void) + { + /* Close the protocol bus */ + _uart_connection->close(); + + /* Clean up the data provider */ + delete _newsim_dp; + _newsim_dp = nullptr; + + /* The bus will clean up the time node */ + } + + + /* Automagically set up by the base class to be called */ + void NewsimHardwareModel::command_callback(NosEngine::Common::Message msg) + { + /* Get the data out of the message */ + NosEngine::Common::DataBufferOverlay dbf(const_cast(msg.buffer)); + sim_logger->info("NewsimHardwareModel::command_callback: Received command: %s.", dbf.data); + + /* Do something with the data */ + std::string command = dbf.data; + std::string response = "NewsimHardwareModel::command_callback: INVALID COMMAND! (Try HELP)"; + boost::to_upper(command); + if (command.compare("HELP") == 0) + { + response = "NewsimHardwareModel::command_callback: Valid commands are HELP, ENABLE, DISABLE, STATUS=X, or STOP"; + } + else if (command.compare(0,6,"ENABLE") == 0) + { + _enabled = NEWSIM_SIM_SUCCESS; + response = "NewsimHardwareModel::command_callback: Enabled\n"; + } + else if (command.compare(0,7,"DISABLE") == 0) + { + _enabled = NEWSIM_SIM_ERROR; + _count = 0; + _config = 0; + _status = 0; + response = "NewsimHardwareModel::command_callback: Disabled"; + } + else if (command.substr(0,7).compare("STATUS=") == 0) + { + try + { + _status = std::stod(command.substr(7)); + response = "NewsimHardwareModel::command_callback: Status set"; + } + catch (...) + { + response = "NewsimHardwareModel::command_callback: Status invalid"; + } + } + else if (command.compare(0,4,"STOP") == 0) + { + _keep_running = false; + response = "NewsimHardwareModel::command_callback: Stopping"; + } + /* TODO: Add anything additional commands here */ + + /* Send a reply */ + sim_logger->info("NewsimHardwareModel::command_callback: Sending reply: %s", response.c_str()); + _command_node->send_reply_message_async(msg, response.size(), response.c_str()); + } + + + /* Custom function to prepare the Newsim HK telemetry */ + void NewsimHardwareModel::create_newsim_hk(std::vector& out_data) + { + /* Prepare data size */ + out_data.resize(16, 0x00); + + /* Streaming data header - 0xDEAD */ + out_data[0] = 0xDE; + out_data[1] = 0xAD; + + /* Sequence count */ + out_data[2] = (_count >> 24) & 0x000000FF; + out_data[3] = (_count >> 16) & 0x000000FF; + out_data[4] = (_count >> 8) & 0x000000FF; + out_data[5] = _count & 0x000000FF; + + /* Configuration */ + out_data[6] = (_config >> 24) & 0x000000FF; + out_data[7] = (_config >> 16) & 0x000000FF; + out_data[8] = (_config >> 8) & 0x000000FF; + out_data[9] = _config & 0x000000FF; + + /* Device Status */ + out_data[10] = (_status >> 24) & 0x000000FF; + out_data[11] = (_status >> 16) & 0x000000FF; + out_data[12] = (_status >> 8) & 0x000000FF; + out_data[13] = _status & 0x000000FF; + + /* Streaming data trailer - 0xBEEF */ + out_data[14] = 0xBE; + out_data[15] = 0xEF; + } + + + /* Custom function to prepare the Newsim Data */ + void NewsimHardwareModel::create_newsim_data(std::vector& out_data) + { + boost::shared_ptr data_point = boost::dynamic_pointer_cast(_newsim_dp->get_data_point()); + + /* Prepare data size */ + out_data.resize(14, 0x00); + + /* Streaming data header - 0xDEAD */ + out_data[0] = 0xDE; + out_data[1] = 0xAD; + + /* Sequence count */ + out_data[2] = (_count >> 24) & 0x000000FF; + out_data[3] = (_count >> 16) & 0x000000FF; + out_data[4] = (_count >> 8) & 0x000000FF; + out_data[5] = _count & 0x000000FF; + + /* + ** Payload + ** + ** Device is big engian (most significant byte first) + ** Assuming data is valid regardless of dynamic / environmental data + ** Floating poing numbers are extremely problematic + ** (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) + ** Most hardware transmits some type of unsigned integer (e.g. from an ADC), so that's what we've done + ** Scale each of the x, y, z (which are in the range [-1.0, 1.0]) by 32767, + ** and add 32768 so that the result fits in a uint16 + */ + double dx = data_point->get_newsim_data_x(); + double dy = data_point->get_newsim_data_y(); + double dz = data_point->get_newsim_data_z(); + uint16_t x = (uint16_t)(dx*32767.0 + 32768.0); + out_data[6] = (x >> 8) & 0x00FF; + out_data[7] = x & 0x00FF; + uint16_t y = (uint16_t)(dy*32767.0 + 32768.0); + out_data[8] = (y >> 8) & 0x00FF; + out_data[9] = y & 0x00FF; + uint16_t z = (uint16_t)(dz*32767.0 + 32768.0); + out_data[10] = (z >> 8) & 0x00FF; + out_data[11] = z & 0x00FF; + + sim_logger->debug("NewsimHardwareModel::create_newsim_data: data_point=%f, %f, %f, converted values=%u, %u, %u.", dx, dy, dz, x, y, z); + + /* Streaming data trailer - 0xBEEF */ + out_data[12] = 0xBE; + out_data[13] = 0xEF; + } + + + /* Protocol callback */ + void NewsimHardwareModel::uart_read_callback(const uint8_t *buf, size_t len) + { + std::vector out_data; + std::uint8_t valid = NEWSIM_SIM_SUCCESS; + + /* Retrieve data and log in man readable format */ + std::vector in_data(buf, buf + len); + sim_logger->debug("NewsimHardwareModel::uart_read_callback: REQUEST %s", + SimIHardwareModel::uint8_vector_to_hex_string(in_data).c_str()); + + /* Check simulator is enabled */ + if (_enabled != NEWSIM_SIM_SUCCESS) + { + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Newsim sim disabled!"); + valid = NEWSIM_SIM_ERROR; + } + else + { + /* Check if message is incorrect size */ + if (in_data.size() != 9) + { + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Invalid command size of %ld received!", in_data.size()); + valid = NEWSIM_SIM_ERROR; + } + else + { + /* Check header - 0xDEAD */ + if ((in_data[0] != 0xDE) || (in_data[1] !=0xAD)) + { + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Header incorrect!"); + valid = NEWSIM_SIM_ERROR; + } + else + { + /* Check trailer - 0xBEEF */ + if ((in_data[7] != 0xBE) || (in_data[8] !=0xEF)) + { + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Trailer incorrect!"); + valid = NEWSIM_SIM_ERROR; + } + else + { + /* Increment count as valid command format received */ + _count++; + } + } + } + + if (valid == NEWSIM_SIM_SUCCESS) + { + /* Process command */ + switch (in_data[2]) + { + case 0: + /* NOOP */ + sim_logger->debug("NewsimHardwareModel::uart_read_callback: NOOP command received!"); + break; + + case 1: + /* Request HK */ + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Send HK command received!"); + create_newsim_hk(out_data); + break; + + case 2: + /* Request data */ + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Send data command received!"); + create_newsim_data(out_data); + break; + + case 3: + /* Configuration */ + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Configuration command received!"); + _config = in_data[3] << 24; + _config |= in_data[4] << 16; + _config |= in_data[5] << 8; + _config |= in_data[6]; + break; + + default: + /* Unused command code */ + valid = NEWSIM_SIM_ERROR; + sim_logger->debug("NewsimHardwareModel::uart_read_callback: Unused command %d received!", in_data[2]); + break; + } + } + } + + /* Increment count and echo command since format valid */ + if (valid == NEWSIM_SIM_SUCCESS) + { + _count++; + _uart_connection->write(&in_data[0], in_data.size()); + + /* Send response if existing */ + if (out_data.size() > 0) + { + sim_logger->debug("NewsimHardwareModel::uart_read_callback: REPLY %s", + SimIHardwareModel::uint8_vector_to_hex_string(out_data).c_str()); + _uart_connection->write(&out_data[0], out_data.size()); + } + } + } +} diff --git a/components/newsim/support/CMakeLists.txt b/components/newsim/support/CMakeLists.txt new file mode 100644 index 00000000..0c3d3c56 --- /dev/null +++ b/components/newsim/support/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 2.6.4) + +project (newsim_checkout) + +if (NOT DEFINED TGTNAME) + message(FATAL_ERROR "TGTNAME must be defined on the cmake command line (e.g. \"-DTGTNAME=cpu1\")") +endif() + +if(${TGTNAME} STREQUAL cpu1) + SET(CMAKE_C_FLAGS_INIT "-m32" CACHE STRING "C Flags required by platform") + SET(CMAKE_C_FLAGS "-m32" CACHE STRING "C Flags required by platform") +endif() + +include(../../ComponentSettings.cmake) + +if(${TGTNAME} STREQUAL cpu1) + find_path(_ITC_CMAKE_MODULES_ + NAMES FindITC_Common.cmake + PATHS ${ITC_CMAKE_MODULES} + ${ITC_DEV_ROOT}/cmake/modules + $ENV{ITC_DEV_ROOT}/cmake/modules + /usr/local/cmake/modules + /usr/cmake/modules) + if(NOT _ITC_CMAKE_MODULES_) + message(WARNING "Unable to find ITC CMake Modules") + endif() + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${_ITC_CMAKE_MODULES_}) + + find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart can i2c spi) +endif() + +include_directories("./") +include_directories("../fsw/platform_inc") +include_directories("../fsw/src") +include_directories("../../../fsw/apps/hwlib/fsw/public_inc") + +set(newsim_checkout_src + newsim_checkout.c + ../fsw/src/newsim_device.c +) + +if(${TGTNAME} STREQUAL cpu1) + include_directories("../../../fsw/apps/hwlib/sim/inc") + set(newsim_checkout_src + ${newsim_checkout_src} + ../../../fsw/apps/hwlib/sim/src/libuart.c + ../../../fsw/apps/hwlib/sim/src/libcan.c + ../../../fsw/apps/hwlib/sim/src/libi2c.c + ../../../fsw/apps/hwlib/sim/src/libspi.c + ../../../fsw/apps/hwlib/sim/src/nos_link.c + ) + set(newsim_checkout_libs + ${ITC_Common_LIBRARIES} + ${NOSENGINE_LIBRARIES} + ) +endif() +if(${TGTNAME} STREQUAL cpu2) + set(newsim_checkout_src + ${newsim_checkout_src} + ../../../fsw/apps/hwlib/fsw/linux/libuart.c + ) +endif() + +add_executable(newsim_checkout ${newsim_checkout_src}) +target_link_libraries(newsim_checkout ${newsim_checkout_libs}) + +if(${TGTNAME} STREQUAL cpu1) + set_target_properties(newsim_checkout PROPERTIES COMPILE_FLAGS "-m32 -g" LINK_FLAGS "-m32 -g") +endif() diff --git a/components/newsim/support/device_cfg.h b/components/newsim/support/device_cfg.h new file mode 100644 index 00000000..36c8b4f1 --- /dev/null +++ b/components/newsim/support/device_cfg.h @@ -0,0 +1,15 @@ +#ifndef _NEWSIM_CHECKOUT_DEVICE_CFG_H_ +#define _NEWSIM_CHECKOUT_DEVICE_CFG_H_ + +/* +** NEWSIM Checkout Configuration +*/ +#define NEWSIM_CFG +/* Note: NOS3 uart requires matching handle and bus number */ +#define NEWSIM_CFG_STRING "/dev/usart_29" +#define NEWSIM_CFG_HANDLE 29 +#define NEWSIM_CFG_BAUDRATE_HZ 115200 +#define NEWSIM_CFG_MS_TIMEOUT 250 +#define NEWSIM_CFG_DEBUG + +#endif /* _NEWSIM_CHECKOUT_DEVICE_CFG_H_ */ diff --git a/components/newsim/support/newsim_checkout.c b/components/newsim/support/newsim_checkout.c new file mode 100644 index 00000000..eec60be3 --- /dev/null +++ b/components/newsim/support/newsim_checkout.c @@ -0,0 +1,278 @@ +/******************************************************************************* +** File: newsim_checkout.c +** +** Purpose: +** This checkout can be run without cFS and is used to quickly develop and +** test functions required for a specific component. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include "newsim_checkout.h" + + +/* +** Global Variables +*/ +uart_info_t NewsimUart; +NEWSIM_Device_HK_tlm_t NewsimHK; +NEWSIM_Device_Data_tlm_t NewsimData; + +/* +** Component Functions +*/ +void print_help(void) +{ + printf(PROMPT "command [args]\n" + "---------------------------------------------------------------------\n" + "help - Display help \n" + "exit - Exit app \n" + "noop - No operation command to device \n" + " n - ^ \n" + "hk - Request device housekeeping \n" + " h - ^ \n" + "newsim - Request newsim data \n" + " s - ^ \n" + "cfg # - Send configuration # \n" + " c # - ^ \n" + "\n" + ); +} + + +int get_command(const char* str) +{ + int status = CMD_UNKNOWN; + char lcmd[MAX_INPUT_TOKEN_SIZE]; + strncpy(lcmd, str, MAX_INPUT_TOKEN_SIZE); + + /* Convert command to lower case */ + to_lower(lcmd); + + if(strcmp(lcmd, "help") == 0) + { + status = CMD_HELP; + } + else if(strcmp(lcmd, "exit") == 0) + { + status = CMD_EXIT; + } + else if(strcmp(lcmd, "noop") == 0) + { + status = CMD_NOOP; + } + else if(strcmp(lcmd, "n") == 0) + { + status = CMD_NOOP; + } + else if(strcmp(lcmd, "hk") == 0) + { + status = CMD_HK; + } + else if(strcmp(lcmd, "h") == 0) + { + status = CMD_HK; + } + else if(strcmp(lcmd, "newsim") == 0) + { + status = CMD_NEWSIM; + } + else if(strcmp(lcmd, "s") == 0) + { + status = CMD_NEWSIM; + } + else if(strcmp(lcmd, "cfg") == 0) + { + status = CMD_CFG; + } + else if(strcmp(lcmd, "c") == 0) + { + status = CMD_CFG; + } + return status; +} + + +int process_command(int cc, int num_tokens, char tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]) +{ + int32_t status = OS_SUCCESS; + int32_t exit_status = OS_SUCCESS; + uint32_t config; + + /* Process command */ + switch(cc) + { + case CMD_HELP: + print_help(); + break; + + case CMD_EXIT: + exit_status = OS_ERROR; + break; + + case CMD_NOOP: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = NEWSIM_CommandDevice(&NewsimUart, NEWSIM_DEVICE_NOOP_CMD, 0); + if (status == OS_SUCCESS) + { + OS_printf("NOOP command success\n"); + } + else + { + OS_printf("NOOP command failed!\n"); + } + } + break; + + case CMD_HK: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = NEWSIM_RequestHK(&NewsimUart, &NewsimHK); + if (status == OS_SUCCESS) + { + OS_printf("NEWSIM_RequestHK command success\n"); + } + else + { + OS_printf("NEWSIM_RequestHK command failed!\n"); + } + } + break; + + case CMD_NEWSIM: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = NEWSIM_RequestData(&NewsimUart, &NewsimData); + if (status == OS_SUCCESS) + { + OS_printf("NEWSIM_RequestData command success\n"); + } + else + { + OS_printf("NEWSIM_RequestData command failed!\n"); + } + } + break; + + case CMD_CFG: + if (check_number_arguments(num_tokens, 1) == OS_SUCCESS) + { + config = atoi(tokens[0]); + status = NEWSIM_CommandDevice(&NewsimUart, NEWSIM_DEVICE_CFG_CMD, config); + if (status == OS_SUCCESS) + { + OS_printf("Configuration command success with value %u\n", config); + } + else + { + OS_printf("Configuration command failed!\n"); + } + } + break; + + default: + OS_printf("Invalid command format, type 'help' for more info\n"); + break; + } + return exit_status; +} + + +int main(int argc, char *argv[]) +{ + int status = OS_SUCCESS; + char input_buf[MAX_INPUT_BUF]; + char input_tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]; + int num_input_tokens; + int cmd; + char* token_ptr; + uint8_t run_status = OS_SUCCESS; + + /* Open device specific protocols */ + NewsimUart.deviceString = NEWSIM_CFG_STRING; + NewsimUart.handle = NEWSIM_CFG_HANDLE; + NewsimUart.isOpen = PORT_CLOSED; + NewsimUart.baud = NEWSIM_CFG_BAUDRATE_HZ; + status = uart_init_port(&NewsimUart); + if (status == OS_SUCCESS) + { + printf("UART device %s configured with baudrate %d \n", NewsimUart.deviceString, NewsimUart.baud); + } + else + { + printf("UART device %s failed to initialize! \n", NewsimUart.deviceString); + run_status = OS_ERROR; + } + + /* Main loop */ + print_help(); + while(run_status == OS_SUCCESS) + { + num_input_tokens = -1; + cmd = CMD_UNKNOWN; + + /* Read user input */ + printf(PROMPT); + fgets(input_buf, MAX_INPUT_BUF, stdin); + + /* Tokenize line buffer */ + token_ptr = strtok(input_buf, " \t\n"); + while((num_input_tokens < MAX_INPUT_TOKENS) && (token_ptr != NULL)) + { + if(num_input_tokens == -1) + { + /* First token is command */ + cmd = get_command(token_ptr); + } + else + { + strncpy(input_tokens[num_input_tokens], token_ptr, MAX_INPUT_TOKEN_SIZE); + } + token_ptr = strtok(NULL, " \t\n"); + num_input_tokens++; + } + + /* Process command if valid */ + if(num_input_tokens >= 0) + { + /* Process command */ + run_status = process_command(cmd, num_input_tokens, input_tokens); + } + } + + // Close the device + uart_close_port(&NewsimUart); + + OS_printf("Cleanly exiting newsim application...\n\n"); + return 1; +} + + +/* +** Generic Functions +*/ +int check_number_arguments(int actual, int expected) +{ + int status = OS_SUCCESS; + if (actual != expected) + { + status = OS_ERROR; + OS_printf("Invalid command format, type 'help' for more info\n"); + } + return status; +} + +void to_lower(char* str) +{ + char* ptr = str; + while(*ptr) + { + *ptr = tolower((unsigned char) *ptr); + ptr++; + } + return; +} + diff --git a/components/newsim/support/newsim_checkout.h b/components/newsim/support/newsim_checkout.h new file mode 100644 index 00000000..2c2a44d2 --- /dev/null +++ b/components/newsim/support/newsim_checkout.h @@ -0,0 +1,68 @@ +/******************************************************************************* +** File: newsim_checkout.h +** +** Purpose: +** This is the header file for the NEWSIM checkout. +** +*******************************************************************************/ +#ifndef _NEWSIM_CHECKOUT_H_ +#define _NEWSIM_CHECKOUT_H_ + +/* +** Includes +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hwlib.h" +#include "device_cfg.h" +#include "newsim_device.h" + + +/* +** Standard Defines +*/ +#define PROMPT "newsim> " +#define MAX_INPUT_BUF 512 +#define MAX_INPUT_TOKENS 64 +#define MAX_INPUT_TOKEN_SIZE 50 +#define TELEM_BUF_LEN 8 + + +/* +** Command Defines +*/ +#define CMD_UNKNOWN -1 +#define CMD_HELP 0 +#define CMD_EXIT 1 +#define CMD_NOOP 2 +#define CMD_HK 3 +#define CMD_NEWSIM 4 +#define CMD_CFG 5 + + +/* +** Prototypes +*/ +void print_help(void); +int get_command(const char* str); +int main(int argc, char *argv[]); + + +/* +** Generic Prototypes +*/ +int check_number_arguments(int actual, int expected); +void to_lower(char* str); + + +#endif /* _NEWSIM_CHECKOUT_H_ */ diff --git a/gsw/cosmos b/gsw/cosmos index 50c889a4..b0611353 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 50c889a4f6ad21bd0dbc6e32254252a435e57770 +Subproject commit b06113537d0eb38ac20281b35d9f4360f6e81275 diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 5d1caec7..1a776c0d 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -130,6 +130,9 @@ do gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + + gnome-terminal --tab --title=$SC_NUM" - Newsim Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_newsim_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE newsim_sim + echo "" done