]> rtime.felk.cvut.cz Git - socketcan-simulink.git/blob - blocks/tlc_c/sfunction_canreceive.tlc
Document myself as author of SocketCAN port of the original RPP library.
[socketcan-simulink.git] / blocks / tlc_c / sfunction_canreceive.tlc
1 %% Copyright (C) 2014 Czech Technical University in Prague
2 %%
3 %% Authors:
4 %%     Michal Horn  <hornmich@fel.cvut.cz>
5 %%     Michal Sojka <sojkam1@fel.cvut.cz>
6 %%     Pavel Pisa <pisa@cmp.felk.cvut.cz> - author of SocketCAN port
7 %%
8 %% Redistribution and use in source and binary forms, with or without
9 %% modification, are permitted provided that the following conditions are
10 %% met:
11 %%
12 %% 1. Redistributions of source code must retain the above copyright
13 %%    notice, this list of conditions and the following disclaimer.
14 %%
15 %% 2. Redistributions in binary form must reproduce the above copyright
16 %%    notice, this list of conditions and the following disclaimer in the
17 %%    documentation and/or other materials provided with the
18 %%    distribution.
19 %%
20 %% 3. Neither the name of the copyright holder nor the names of its
21 %%    contributors may be used to endorse or promote products derived
22 %%    from this software without specific prior written permission.
23 %%
24 %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 %% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 %% HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 %% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 %% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 %% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 %% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 %% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 %% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 %%
36 %% File : sfunction_canreceive.tlc
37 %% Abstract:
38 %%     TLC file for configuring the CAN RX buffer on the TI TMS570LS3137 MCU
39 %%
40 %% References:
41 %%     BlockTypeSetup() : refs/rtw_tlc.pdf p. 277
42 %%     Outputs()        : refs/rtw_tlc.pdf p. 281
43
44
45 %implements sfunction_canreceive "C"
46
47 %include "common.tlc"
48 %include "rpp_can_common.tlc"
49
50 %% Function: BlockTypeSetup ====================================================
51 %function BlockTypeSetup(block, system) void
52     %<RppCommonBlockTypeSetup(block, system)>
53         %<RppCANCommonBlockTypeSetup()>
54 %endfunction
55
56 %% Function: BlockInstanceSetup ================================================
57 %function BlockInstanceSetup(block, system) void
58
59         %assign module_id_par = LibBlockParameterValue(module_id, 0)
60         %assign mailbox_num_par = LibBlockParameterValue(mailbox_id, 0)
61         %assign message_type_par = LibBlockParameterValue(message_type, 0)
62         %assign message_id_par = LibBlockParameterValue(message_id, 0)
63         %assign data_type_par = LibBlockParameterValue(data_type, 0)
64         %assign message_filter_par = LibBlockParameterValue(message_filter, 0)
65         %assign message_mask_par = LibBlockParameterValue(message_mask, 0)
66         %assign mailbox_auto_par = LibBlockParameterValue(mailbox_auto, 0)
67
68     %if message_filter_par == 1
69             %assign mask = 8388607 %% 0x7FFFFF
70     %else
71             %assign mask = message_mask_par
72     %endif
73
74         %% This seems to be the only way to add a record to an array. The
75         %% other way - creating the record with %createrecord and adding
76         %% it later with %addtorecord doesn't work.
77         %addtorecord Rpp.Can.Rx Block { ...
78           HwObj Rpp.Can.Rx.NumBlocks; ...
79           Controller module_id_par; ...
80           MsgObj 0; /% Invalid MsgObj - proper value will be assigned later %/ ...
81           Type message_type_par; ...
82           Id message_id_par; ...
83           Mask mask; ...
84           Name "%<LibGetBlockName(block)>" ...
85         }
86         %assign blockInfo = Rpp.Can.Rx.Block[Rpp.Can.Rx.NumBlocks] /% create alias to the record %/
87         %if %<mailbox_auto_par>==1
88           %<RppPlaceAutomaticMailboxNumber(blockInfo)>
89         %else
90           %<RppPlaceManualMailboxNumber(blockInfo, mailbox_num_par)>
91         %endif
92
93         /% Remember which blockInfo record is associated wit this block %/
94          %addtorecord block RppRxInfo blockInfo
95         %assign Rpp.Can.Rx.NumBlocks = Rpp.Can.Rx.NumBlocks + 1
96 %endfunction
97
98 %% Function: Start =============================================================
99 %function Start(block, system) Output
100
101     %if !SLibCodeGenForSim()
102
103           %if EXISTS(::rpp_can_config_present) == 0
104                 %<LibBlockReportError(block, "CAN buc configuration block not present!")>
105           %endif
106     %endif
107
108
109 %endfunction
110
111 %% Function: Outputs ===========================================================
112 %function Outputs(block, system) Output
113
114   %if !SLibCodeGenForSim()
115         %assign data_type_par = LibBlockParameterValue(data_type, 0)
116         %assign message = LibBlockOutputSignal(1, "", "", 1)
117
118         {
119           struct can_frame sc_frame;
120           int ret;
121           int dlc;
122           int recv_len = -1;
123
124           /* TODO decide what is desired behavior if there are more pendind messages */
125           do {
126             ret = recv(can_rx_handles[%<RppRxInfo.HwObj>], &sc_frame, sizeof(sc_frame), 0);
127             if (ret == -1) {
128               if (errno == EAGAIN)
129                 break;
130               printf("Receiving CAN message failed (%s).\n", "%<RppRxInfo.Name>");
131               break;
132             } else {
133               recv_len = ret;
134             }
135           } while (ret > 0);
136
137           if (recv_len < sizeof(sc_frame)) {
138             if (recv_len >= 0)
139               printf("Receiving CAN message (%s) returns truncated length %d.\n", "%<RppRxInfo.Name>", ret);
140           } else {
141             dlc = sc_frame.can_dlc;
142             if (dlc > 8)
143               dlc = 8;
144             %if %<data_type_par>==4
145                 // CAN_MESSAGE
146                 memset(&%<message>, 0, sizeof(%<message>));
147                 %<message>.Length = dlc;
148                 %<message>.ID = sc_frame.can_id & CAN_EFF_MASK;
149                 %<message>.Extended = sc_frame.can_id & CAN_EFF_FLAG? 1: 0;
150                 int i;
151                 for (i = 0; i < dlc; i++ ) {
152                   %<message>.Data[i] = sc_frame.data[i];
153                   %%printf("%X ", sc_frame.data[i]);
154                 }
155             %elseif %<data_type_par>==3
156                 // uint32
157                 unsigned int msg = (sc_frame.data[0]) |
158                   (sc_frame.data[1]<<8) |
159                   (sc_frame.data[2]<<16) |
160                   (sc_frame.data[3]<<24);
161                 if (dlc < 4)
162                   msg &= 0xffffffff << (8 * dlc);
163                 %<message> = msg;
164                 %%printf("32b: %X ", msg);
165             %elseif %<data_type_par>==2
166                 // uint16
167                 unsigned int msg = (sc_frame.data[0]) |
168                     (sc_frame.data[1]<<8);
169                 if (dlc < 2)
170                   msg &= 0xffffffff << (8 * dlc);
171                 %<message> = msg;
172                 %%printf("16b: %X ", msg);
173             %else
174                 // uint8
175                 unsigned int msg = sc_frame.data[0];
176                 %<message> = msg;
177                 %%printf("8b: %X ", msg);
178             %endif
179             %%printf("\n");
180
181             %% Call a function to process the received message via function-call subsystem
182             %foreach callIdx = NumSFcnSysOutputCalls
183                 %if LibIsEqual(SFcnSystemOutputCall[callIdx].BlockToCall,"unconnected")
184                   %continue
185                 %endif
186                 %% call the downstream system
187                 %<LibBlockExecuteFcnCall(block, callIdx)>\
188             %endforeach
189           }
190         }
191   %endif
192 %endfunction
193
194 %% [EOF]