1 /**
2  * CANopen LSS Master/Slave protocol.
3  *
4  * @file        CO_LSS.h
5  * @ingroup     CO_LSS
6  * @author      Martin Wagner
7  * @copyright   2017 - 2020 Neuberger Gebaeudeautomation GmbH
8  *
9  *
10  * This file is part of CANopenNode, an opensource CANopen Stack.
11  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
12  * For more information on CANopen see <http://www.can-cia.org/>.
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  */
26 
27 #ifndef CO_LSS_H
28 #define CO_LSS_H
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * @defgroup CO_LSS LSS
36  * @ingroup CO_CANopen
37  * @{
38  *
39  * CANopen Layer Setting Services protocol
40  *
41  * LSS protocol is according to CiA DSP 305 V3.0.0.
42  *
43  * LSS services and protocols are used to inquire or to change the settings
44  * of three parameters of the physical layer, data link layer, and application
45  * layer on a CANopen device with LSS slave capability by a CANopen device
46  * with LSS master capability via the CAN network.
47  *
48  * The following parameters may be inquired or changed:
49  * - Node-ID of the CANopen device
50  * - Bit timing parameters of the physical layer (bit rate)
51  * - LSS address compliant to the identity object (1018h)
52  *
53  * The connection is established in one of two ways:
54  * - addressing a node by it's 128 bit LSS address. This requires that the
55  *   master already knows the node's LSS address.
56  * - scanning the network for unknown nodes (Fastscan). Using this method,
57  *   unknown devices can be found and configured one by one.
58  *
59  * Be aware that changing the bit rate is a critical step for the network. A
60  * failure will render the network unusable!
61  *
62  * Using this implementation, only master or slave can be included in one
63  * node at a time.
64  *
65  * For CAN identifiers see #CO_Default_CAN_ID_t
66  */
67 
68 #if CO_NO_LSS_CLIENT == 1 || CO_NO_LSS_SERVER == 1
69 
70 /**
71  * LSS protocol command specifiers
72  *
73  * The LSS protocols are executed between the LSS master device and the LSS
74  * slave device(s) to implement the LSS services. Some LSS protocols require
75  * a sequence of CAN messages.
76  *
77  * As identifying method only "LSS fastscan" is supported.
78  */
79 typedef enum {
80     CO_LSS_SWITCH_STATE_GLOBAL      = 0x04U, /**< Switch state global protocol */
81     CO_LSS_SWITCH_STATE_SEL_VENDOR  = 0x40U, /**< Switch state selective protocol - Vendor ID */
82     CO_LSS_SWITCH_STATE_SEL_PRODUCT = 0x41U, /**< Switch state selective protocol - Product code */
83     CO_LSS_SWITCH_STATE_SEL_REV     = 0x42U, /**< Switch state selective protocol - Revision number */
84     CO_LSS_SWITCH_STATE_SEL_SERIAL  = 0x43U, /**< Switch state selective protocol - Serial number */
85     CO_LSS_SWITCH_STATE_SEL         = 0x44U, /**< Switch state selective protocol - Slave response */
86     CO_LSS_CFG_NODE_ID              = 0x11U, /**< Configure node ID protocol */
87     CO_LSS_CFG_BIT_TIMING           = 0x13U, /**< Configure bit timing parameter protocol */
88     CO_LSS_CFG_ACTIVATE_BIT_TIMING  = 0x15U, /**< Activate bit timing parameter protocol */
89     CO_LSS_CFG_STORE                = 0x17U, /**< Store configuration protocol */
90     CO_LSS_IDENT_SLAVE              = 0x4FU, /**< LSS Fastscan response */
91     CO_LSS_IDENT_FASTSCAN           = 0x51U, /**< LSS Fastscan protocol */
92     CO_LSS_INQUIRE_VENDOR           = 0x5AU, /**< Inquire identity vendor-ID protocol */
93     CO_LSS_INQUIRE_PRODUCT          = 0x5BU, /**< Inquire identity product-code protocol */
94     CO_LSS_INQUIRE_REV              = 0x5CU, /**< Inquire identity revision-number protocol */
95     CO_LSS_INQUIRE_SERIAL           = 0x5DU, /**< Inquire identity serial-number protocol */
96     CO_LSS_INQUIRE_NODE_ID          = 0x5EU, /**< Inquire node-ID protocol */
97 } CO_LSS_cs_t;
98 
99 /**
100  * Macro to get service type group from command specifier
101  * @{*/
102 #define CO_LSS_CS_SERVICE_IS_SWITCH_GLOBAL(cs) (cs == CO_LSS_SWITCH_STATE_GLOBAL)
103 #define CO_LSS_CS_SERVICE_IS_SWITCH_STATE_SELECTIVE(cs) (cs >= CO_LSS_SWITCH_STATE_SEL_VENDOR && cs <= CO_LSS_SWITCH_STATE_SEL)
104 #define CO_LSS_CS_SERVICE_IS_CONFIG(cs) (cs >= CO_LSS_CFG_NODE_ID && cs <= CO_LSS_CFG_STORE)
105 #define CO_LSS_CS_SERVICE_IS_INQUIRE(cs) (cs >= CO_LSS_INQUIRE_VENDOR && cs <= CO_LSS_INQUIRE_NODE_ID)
106 #define CO_LSS_CS_SERVICE_IS_IDENT(cs) (cs==CO_LSS_IDENT_SLAVE || cs==CO_LSS_IDENT_FASTSCAN)
107 /**@}*/
108 
109 /**
110  * Error codes for Configure node ID protocol
111  */
112 typedef enum {
113     CO_LSS_CFG_NODE_ID_OK           = 0x00U,/**< Protocol successfully completed */
114     CO_LSS_CFG_NODE_ID_OUT_OF_RANGE = 0x01U,/**< NID out of range */
115     CO_LSS_CFG_NODE_ID_MANUFACTURER = 0xFFU /**< Manufacturer specific error. No further support */
116 } CO_LSS_cfgNodeId_t;
117 
118 /**
119  * Error codes for Configure bit timing parameters protocol
120  */
121 typedef enum {
122     CO_LSS_CFG_BIT_TIMING_OK           = 0x00U,/**< Protocol successfully completed */
123     CO_LSS_CFG_BIT_TIMING_OUT_OF_RANGE = 0x01U,/**< Bit timing / Bit rate not supported */
124     CO_LSS_CFG_BIT_TIMING_MANUFACTURER = 0xFFU /**< Manufacturer specific error. No further support */
125 } CO_LSS_cfgBitTiming_t;
126 
127 /**
128  * Error codes for Store configuration protocol
129  */
130 typedef enum {
131     CO_LSS_CFG_STORE_OK            = 0x00U, /**< Protocol successfully completed */
132     CO_LSS_CFG_STORE_NOT_SUPPORTED = 0x01U, /**< Store configuration not supported */
133     CO_LSS_CFG_STORE_FAILED        = 0x02U, /**< Storage media access error */
134     CO_LSS_CFG_STORE_MANUFACTURER  = 0xFFU  /**< Manufacturer specific error. No further support */
135 } CO_LSS_cfgStore_t;
136 
137 /**
138  * Fastscan BitCheck. BIT0 means all bits are checked for equality by slave.
139  */
140 typedef enum {
141     CO_LSS_FASTSCAN_BIT0    = 0x00U, /**< Least significant bit of IDnumbners bit area to be checked */
142     /* ... */
143     CO_LSS_FASTSCAN_BIT31   = 0x1FU, /**< dito */
144     CO_LSS_FASTSCAN_CONFIRM = 0x80U  /**< All LSS slaves waiting for scan respond and previous scan is reset */
145 } CO_LSS_fastscan_bitcheck;
146 
147 #define CO_LSS_FASTSCAN_BITCHECK_VALID(bit) ((bit>=CO_LSS_FASTSCAN_BIT0 && bit<=CO_LSS_FASTSCAN_BIT31) || bit==CO_LSS_FASTSCAN_CONFIRM)
148 
149 /**
150  * Fastscan LSSsub, LSSnext
151  */
152 typedef enum {
153     CO_LSS_FASTSCAN_VENDOR_ID = 0, /**< Vendor ID */
154     CO_LSS_FASTSCAN_PRODUCT   = 1, /**< Product code */
155     CO_LSS_FASTSCAN_REV       = 2, /**< Revision number */
156     CO_LSS_FASTSCAN_SERIAL    = 3  /**< Serial number */
157 } CO_LSS_fastscan_lss_sub_next;
158 
159 #define CO_LSS_FASTSCAN_LSS_SUB_NEXT_VALID(index) (index>=CO_LSS_FASTSCAN_VENDOR_ID && index<=CO_LSS_FASTSCAN_SERIAL)
160 
161 /**
162  * The LSS address is a 128 bit number, uniquely identifying each node. It
163  * consists of the values in object 0x1018.
164  */
165 typedef union {
166     uint32_t addr[4];
167     struct {
168         uint32_t vendorID;
169         uint32_t productCode;
170         uint32_t revisionNumber;
171         uint32_t serialNumber;
172     } identity;
173 } CO_LSS_address_t;
174 
175 /**
176  * LSS finite state automaton
177  *
178  * The LSS FSA shall provide the following states:
179  * - Initial: Pseudo state, indicating the activation of the FSA.
180  * - LSS waiting: In this state, the LSS slave device waits for requests.
181  * - LSS configuration: In this state variables may be configured in the LSS slave.
182  * - Final: Pseudo state, indicating the deactivation of the FSA.
183  */
184 typedef enum {
185     CO_LSS_STATE_WAITING = 0,                /**< LSS FSA waiting for requests*/
186     CO_LSS_STATE_CONFIGURATION = 1,          /**< LSS FSA waiting for configuration*/
187 } CO_LSS_state_t;
188 
189 /**
190  * Definition of table_index for /CiA301/ bit timing table
191  */
192 typedef enum {
193     CO_LSS_BIT_TIMING_1000 = 0,              /**< 1000kbit/s */
194     CO_LSS_BIT_TIMING_800  = 1,              /**< 800kbit/s */
195     CO_LSS_BIT_TIMING_500  = 2,              /**< 500kbit/s */
196     CO_LSS_BIT_TIMING_250  = 3,              /**< 250kbit/s */
197     CO_LSS_BIT_TIMING_125  = 4,              /**< 125kbit/s */
198     /* reserved            = 5 */
199     CO_LSS_BIT_TIMING_50   = 6,              /**< 50kbit/s */
200     CO_LSS_BIT_TIMING_20   = 7,              /**< 20kbit/s */
201     CO_LSS_BIT_TIMING_10   = 8,              /**< 10kbit/s */
202     CO_LSS_BIT_TIMING_AUTO = 9,              /**< Automatic bit rate detection */
203 } CO_LSS_bitTimingTable_t;
204 
205 /**
206  * Lookup table for conversion between bit timing table and numerical
207  * bit rate
208  */
209 static const uint16_t CO_LSS_bitTimingTableLookup[]  = {
210      1000,
211      800,
212      500,
213      250,
214      125,
215      0,
216      50,
217      20,
218      10,
219      0
220 };
221 
222 /**
223  * Macro to check if index contains valid bit timing
224  */
225 #define CO_LSS_BIT_TIMING_VALID(index) (index != 5 && (index >= CO_LSS_BIT_TIMING_1000 && index <= CO_LSS_BIT_TIMING_AUTO))
226 
227 /**
228  * Invalid node ID triggers node ID assignment
229  */
230 #define CO_LSS_NODE_ID_ASSIGNMENT 0xFFU
231 
232 /**
233  * Macro to check if node id is valid
234  */
235 #define CO_LSS_NODE_ID_VALID(nid) ((nid >= 1 && nid <= 0x7F) || nid == CO_LSS_NODE_ID_ASSIGNMENT)
236 
237 /**
238  * Macro to check if two LSS addresses are equal
239  */
240 #define CO_LSS_ADDRESS_EQUAL(/*CO_LSS_address_t*/ a1, /*CO_LSS_address_t*/ a2) \
241      (a1.identity.productCode == a2.identity.productCode &&         \
242       a1.identity.revisionNumber == a2.identity.revisionNumber &&   \
243       a1.identity.serialNumber == a2.identity.serialNumber &&       \
244       a1.identity.vendorID == a2.identity.vendorID)
245 
246 #endif /* CO_NO_LSS_CLIENT == 1 || CO_NO_LSS_SERVER == 1 */
247 
248 #ifdef __cplusplus
249 }
250 #endif /*__cplusplus*/
251 
252 /** @} */
253 #endif
254