d40dbc43dcbe0548b580cf1b929e1d3c2a2b0917
[apps/agl-service-can-low-level.git] / src / can-message.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "can-message.hpp"
19
20 #include <cstring>
21
22 #include "low-can-binding.hpp"
23
24 /********************************************************************************
25 *
26 *               CanMessage method implementation
27 *
28 *********************************************************************************/
29
30 can_message_t::can_message_t()
31         : id_{0}, length_{0}, format_{CanMessageFormat::ERROR}, data_{0,0,0,0,0,0,0,0}
32 {}
33
34 uint32_t can_message_t::get_id() const
35 {
36         return id_;
37 }
38
39 int can_message_t::get_format() const
40 {
41         if (format_ != CanMessageFormat::STANDARD || format_ != CanMessageFormat::EXTENDED)
42                 return CanMessageFormat::ERROR;
43         return format_;
44 }
45
46 const uint8_t* can_message_t::get_data() const
47 {
48         return data_;
49 }
50 uint8_t can_message_t::get_length() const
51 {
52         return length_;
53 }
54
55 bool can_message_t::is_correct_to_send()
56 {
57         if (id_ != 0 && length_ != 0 && format_ != CanMessageFormat::ERROR)
58         {
59                 int i;
60                 for(i=0;i<CAN_MESSAGE_SIZE;i++)
61                         if(data_[i] != 0)
62                                 return true;
63         }
64         return false;
65 }
66
67 void can_message_t::set_id(const uint32_t new_id)
68 {
69         switch(format_)
70         {
71                 case CanMessageFormat::STANDARD:
72                         id_ = new_id & CAN_SFF_MASK;
73                         break;
74                 case CanMessageFormat::EXTENDED:
75                         id_ = new_id & CAN_EFF_MASK;
76                         break;
77                 default:
78                         ERROR(binder_interface, "ERROR: Can set id, not a compatible format or format not set prior to set id.");
79                         break;
80         }
81 }
82
83 void can_message_t::set_format(const CanMessageFormat new_format)
84 {
85         if(new_format == CanMessageFormat::STANDARD || new_format == CanMessageFormat::EXTENDED)
86                 format_ = new_format;
87         else
88                 ERROR(binder_interface, "ERROR: Can set format, wrong format chosen");
89 }
90
91 void can_message_t::set_data(const uint8_t new_data)
92 {
93         if ((sizeof(new_data) / sizeof(uint8_t) > CAN_MESSAGE_SIZE))
94                 ERROR(binder_interface, "Can set data, your data array is too big");
95         else
96         {
97                 ::memcpy(&data_, &new_data, sizeof(new_data));
98                 length_ = sizeof(new_data);
99         }
100 }
101
102 void can_message_t::convert_from_canfd_frame(const canfd_frame& frame)
103 {
104         length_ = (frame.len > CAN_MAX_DLEN) ? (uint8_t)CAN_MAX_DLEN : frame.len;
105         length_ = (frame.len > CANFD_MAX_DLEN) ? (uint8_t)CANFD_MAX_DLEN : frame.len;
106
107         if (frame.can_id & CAN_ERR_FLAG)
108         {
109                 id_ = frame.can_id & (CAN_ERR_MASK|CAN_ERR_FLAG);
110                 format_ = CanMessageFormat::ERROR;
111         }
112         else if (frame.can_id & CAN_EFF_FLAG)
113         {
114                 id_ = frame.can_id & CAN_EFF_MASK;
115                 format_ = CanMessageFormat::EXTENDED;
116         }
117         else
118         {
119                 id_ = frame.can_id & CAN_SFF_MASK;
120                 format_ = CanMessageFormat::STANDARD;
121         }
122         DEBUG(binder_interface, "");
123
124         if (sizeof(frame.data) <= sizeof(data_))
125                 ::memcpy(&data_, frame.data, length_);
126         else if (sizeof(frame.data) >= CAN_MAX_DLEN)
127                 ERROR(binder_interface, "can_message_t: canfd_frame data too long to be stored into CanMessage object");
128 }
129
130 canfd_frame can_message_t::convert_to_canfd_frame()
131 {
132         canfd_frame frame;
133
134         if(is_correct_to_send())
135         {
136                 frame.can_id = get_id();
137                 frame.len = get_length();
138                 ::memcpy(frame.data, get_data(), length_);
139         }
140         else
141                 ERROR(binder_interface, "can_message_t not correctly initialized to be sent");
142         
143         return frame;
144 }
145