]> rtime.felk.cvut.cz Git - jenkicar/rpp-simulink.git/blob - rpp/blocks/sfunction_cantransmit.c
53325ed5e176d51e55b2fa5a1491d0bbf0eda6d2
[jenkicar/rpp-simulink.git] / rpp / blocks / sfunction_cantransmit.c
1 /* Copyright (C) 2013-2014 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn <hornmich@fel.cvut.cz>
5  *
6  * This document contains proprietary information belonging to Czech
7  * Technical University in Prague. Passing on and copying of this
8  * document, and communication of its contents is not permitted
9  * without prior written authorization.
10  *
11  * File : sfunction_cantransmit.c
12  * Abstract:
13  *     C-MEX S-function block for RPP CAN bus transmit message.
14  *
15  * References:
16  *     header.c
17  *     trailer.c
18  *
19  * Compile with:
20  *     mex(['-I' matlabroot '/toolbox/shared/can/src/scanutil'], ['-I' matlabroot '/toolbox/rtw/targets/common/can/datatypes'],  'sfunction_cantransmit.c', [matlabroot '/toolbox/rtw/targets/common/can/datatypes/sfun_can_util.c'], [matlabroot '/toolbox/rtw/targets/common/can/datatypes/can_msg.c'])
21  */
22
23 /*
24 %YAML 1.2
25 ---
26 Name: CAN Transmit
27 Category: CAN
28 Header: rpp/can.h
29 Mnemonic: CANT
30
31 Inputs:
32   - { name: "Msg", type: "dynamically" }
33
34 Outputs:
35
36 Parameters:
37   - { name: "Module",                   type: "Choice", range: "CAN1, CAN2, CAN3"   }
38   - { name: "Frame type",               type: "Choice", range: "Standard, Extended" }
39   - { name: "Message ID",               type: "uint16"                              }
40   - { name: "Automatic mailbox number", type: "bool"                                }
41   - { name: "Mailbox number",           type: "int8",   range: "[1–64]"             }
42
43 # Description and Help is in Markdown mark-up
44 Description: |
45
46   Transmit a CAN message.
47
48   Expects a uint8, uint16, uint32 or CAN\_MESSAGE object as an input. Use
49   CAN Pack to create the CAN\_MESSAGE object.
50
51   Matlab expression can be used as Message ID and Mailbox number.
52
53   Uncheck *Automatic mailbox number*, if user defined mailbox number is
54   needed.
55
56 Help: |
57
58   This block allows to send a message to the CAN bus. It can be
59   configured for any of the CAN ports (modules) CAN1, CAN2 or CAN3.
60
61   The message data are read from `Msg` input port. The data type is
62   decided automatically from the input, but it is restricted to uint8,
63   uint16, uint32 and CAN\_MESSAGE. The CAN\_MESSAGE object can be
64   created by the `CAN Pack` block.
65
66   The message sent by the block will have an ID assigned according to
67   the number in the *Message ID* parameter. The block supports both
68   types of message IDs: Standard (11b) and Extended (29b). If
69   CAN\_MESSAGE is used as input type, the message ID stored in
70   CAN\_MESSAGE object is ignored and the ID from the parameter of this
71   block is used instead.
72
73   The mailbox number can be assigned automatically or manually. Automatic mailbox
74   numbers are generated in ascending order from 0 to 31. Every mailbox must have a unique
75   number. It is possible to mix blocks with automatically and manually
76   assigned mailboxes. If the manually assigned mailbox number would
77   collide with the automatic one then the automatically generated
78   block will get assigned a next higher non-colliding ID.
79   The mailbox numbers are shared between CAN Transmit and CAN Receive
80   blocks with the same CAN port (module) parameter.
81
82   In order to use this block, there must be a `CAN Configure` block in the model.
83
84 Status:
85   Tested:
86     - Transmission of the message with configured ID
87     - Automatic generation of mailboxes numbers in combination with
88       manual specification in other blocks. Colliding mailbox numbers
89       are correctly handled.
90     - Input message data type recognition
91     - When unsupported data type is connected to the Msg input port, Simulink generates a reasonable error message
92   Untested:
93     - Handling of error states on CAN bus
94   Not working:
95     - External mode - throwing syntax error during compilation
96
97 RPP API functions used:
98     - rpp_can_write()
99
100 Relevant demos:
101     - cantransmit
102     - can_demo
103 ...
104 */
105
106
107 #define S_FUNCTION_NAME sfunction_cantransmit
108 #include "header.c"
109 #include <stdio.h>
110 #include "sfun_can_util.h"
111
112 #define MSG_TYPE_STANDART_MAX   2048
113 #define MSG_TYPE_EXTENDED_MAX   536870912
114 #define MAILBOX_ID_MIN                  1
115 #define MAILBOX_MAX_CNT                 64
116
117 #define PARAM_NAME_MODULE_ID    "module_id"
118 #define PARAM_NAME_MAILBOX_ID   "mailbox_id"
119 #define PARAM_NAME_MESSAGE_TYPE "message_type"
120 #define PARAM_NAME_MESSAGE_ID   "message_id"
121 #define PARAM_NAME_MAILBOX_AUTO "mailbox_auto"
122
123 /** Identifier of the input */
124 enum input {
125         IN_MSG,
126         IN_COUNT
127 };
128
129 /** Identifiers of the block parameters */
130 enum params{
131         PARAM_MODULE_ID,
132         PARAM_MAILBOX_ID,
133         PARAM_MSG_TYPE,
134         PARAM_MSG_ID,
135         PARAM_MAILBOX_AUTO,
136         PARAM_COUNT
137 };
138
139 enum message_id_type {
140         MSG_ID_STANDART,
141         MSG_ID_EXTENDED,
142         MSG_ID_MIXED
143 };
144
145
146 static void mdlInitializeSizes(SimStruct *S)
147 {
148
149         CAN_Common_MdlInitSizes(S);
150
151         if (!rppSetNumParams(S, PARAM_COUNT)) {
152                 return;
153         }
154
155         /*
156          * Configure input ports: 1
157          *      - Message to be sent
158          */
159         if (!ssSetNumInputPorts(S, IN_COUNT)) {
160                 return;
161         }
162
163         rppAddInputPort(S, IN_MSG, DYNAMICALLY_TYPED);
164
165         /* No output ports */
166         if (!ssSetNumOutputPorts(S, 0)) {
167                 return;
168         }
169
170         /* Set standard options for this block */
171         rppSetStandardOptions(S);
172 }
173
174 #if defined(MATLAB_MEX_FILE)
175 #define MDL_SET_INPUT_PORT_DATA_TYPE
176 void mdlSetInputPortDataType(SimStruct *S, int_T port, DTypeId type)
177 {
178         if (port == IN_MSG) {
179                 if (type == SS_UINT8 ||
180                     type == SS_UINT16 ||
181                     type == SS_UINT32 ||
182                     /* CAN pack seems to use this data type, but it is
183                      * not registered in sfun_can_util.c. Strange. */
184                     type == ssGetDataTypeId(S, "CAN_MESSAGE") ||
185                     type == ssGetDataTypeId(S, SL_CAN_STANDARD_FRAME_DTYPE_NAME) ||
186                     type == ssGetDataTypeId(S, SL_CAN_EXTENDED_FRAME_DTYPE_NAME))
187                         ssSetInputPortDataType(S, port, type);
188                 else {
189                         char msg[300];
190                         sprintf(msg, "Unsupported data type '%s' on Msg input port.",
191                                  ssGetDataTypeName(S, type));
192                         ssSetErrorStatus(S, msg);
193                 }
194         }
195 }
196 #endif
197
198 #ifdef MATLAB_MEX_FILE
199 #define MDL_CHECK_PARAMETERS
200
201 static void mdlCheckParameters(SimStruct *S){
202         int min = 0;
203         int max = 0;
204         /* Check the parameter mailbox id */
205         if ((int_T)mxGetPr(ssGetSFcnParam(S, PARAM_MAILBOX_AUTO))[0] == 0) {
206                 if (!rppValidParamRange(S, PARAM_MAILBOX_ID, MAILBOX_ID_MIN, MAILBOX_ID_MIN + MAILBOX_MAX_CNT)) {
207                         return;
208                 }
209         }
210
211         if ((int_T)mxGetPr(ssGetSFcnParam(S, PARAM_MSG_TYPE))[0] == MSG_ID_STANDART) {
212                 max = MSG_TYPE_STANDART_MAX;
213         }
214         else {
215                 max = MSG_TYPE_EXTENDED_MAX;
216         }
217
218         /* Check the parameter message id */
219         if (!rppValidParamRange(S, PARAM_MSG_ID, min, max)) {
220                 return;
221         }
222 }
223 #endif
224
225
226 #ifdef MATLAB_MEX_FILE
227 #define MDL_SET_WORK_WIDTHS
228 static void mdlSetWorkWidths(SimStruct *S){
229
230         if (!ssSetNumRunTimeParams(S, PARAM_COUNT)) {
231                 return;
232         }
233
234         ssRegDlgParamAsRunTimeParam(S, PARAM_MODULE_ID,  PARAM_MODULE_ID, PARAM_NAME_MODULE_ID, SS_UINT8);
235         ssRegDlgParamAsRunTimeParam(S, PARAM_MAILBOX_ID,  PARAM_MAILBOX_ID, PARAM_NAME_MAILBOX_ID, SS_INT8);
236         ssRegDlgParamAsRunTimeParam(S, PARAM_MSG_TYPE,  PARAM_MSG_TYPE, PARAM_NAME_MESSAGE_TYPE, SS_UINT16);   
237         ssRegDlgParamAsRunTimeParam(S, PARAM_MSG_ID,  PARAM_MSG_ID, PARAM_NAME_MESSAGE_ID, SS_UINT32); 
238         ssRegDlgParamAsRunTimeParam(S, PARAM_MAILBOX_AUTO,  PARAM_MAILBOX_AUTO, PARAM_NAME_MAILBOX_AUTO, SS_BOOLEAN);     
239 }
240 #endif
241
242 #define COMMON_MDLINITIALIZESAMPLETIMES_INHERIT
243 #define UNUSED_MDLOUTPUTS
244 #define UNUSED_MDLTERMINATE
245 #include "trailer.c"