Updated GDB ini file to load binding symbols directly from SDK
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_pmp.c
1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491                                                                            */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG.                              */
4 /*                                                                                                */
5 /* This program is free software: you can redistribute it and/or modify                           */
6 /* it under the terms of the GNU General Public License as published by                           */
7 /* the Free Software Foundation, either version 2 of the License, or                              */
8 /* (at your option) any later version.                                                            */
9 /*                                                                                                */
10 /* This program is distributed in the hope that it will be useful,                                */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of                                 */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                  */
13 /* GNU General Public License for more details.                                                   */
14 /*                                                                                                */
15 /* You should have received a copy of the GNU General Public License                              */
16 /* along with this program.  If not, see <http://www.gnu.org/licenses/>.                          */
17 /*                                                                                                */
18 /* You may also obtain this software under a propriety license from Microchip.                    */
19 /* Please contact Microchip for further information.                                              */
20 /*------------------------------------------------------------------------------------------------*/
21
22 /*!
23  * \file
24  * \brief Implementation of Port Message Protocol
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup  G_PMH
28  * @{
29  */
30
31 /*------------------------------------------------------------------------------------------------*/
32 /* Includes                                                                                       */
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_pmp.h"
35 #include "ucs_misc.h"
36
37 /*------------------------------------------------------------------------------------------------*/
38 /* PMP Indexes                                                                                    */
39 /*------------------------------------------------------------------------------------------------*/
40 #define PMP_IDX_PML_H           0U
41 #define PMP_IDX_PML_L           1U
42 #define PMP_IDX_PMHL            2U
43 #define PMP_IDX_FPH             3U
44 #define PMP_IDX_SID             4U
45 #define PMP_IDX_EXT_TYPE        5U
46
47 /*------------------------------------------------------------------------------------------------*/
48 /* Masks and shifts for bit fields                                                                */
49 /*------------------------------------------------------------------------------------------------*/
50 #define PMP_PMHL_MASK           0x1FU      /* 0b00011111 */
51 #define PMP_VERSION_MASK        0xE0U      /* 0b11100000 */
52 #define PMP_VERSION             0x40U      /* Version: "2" */
53 #define PMP_FPH_TYPE_POS        1U
54 #define PMP_FPH_TYPE_MASK       0x06U      /* 0b00000110 */
55 #define PMP_FPH_ID_POS          3U
56 #define PMP_FPH_ID_MASK         0x38U      /* 0b00111000 */
57 #define PMP_FPH_DIR_RX          0x01U      /* RX: "1" */
58 #define PMP_FPH_DIR_MASK        0x01U      /* 0b00000001 */
59 #define PMP_EXT_TYPE_POS        5U
60 #define PMP_EXT_TYPE_MASK       0xE0U      /* 0b11100000 */
61 #define PMP_EXT_CODE_MASK       0x1FU      /* 0b00011111 */
62
63 /*------------------------------------------------------------------------------------------------*/
64 /* PMP Verification                                                                               */
65 /*------------------------------------------------------------------------------------------------*/
66 #define PMP_PML_MAX_SIZE_CTRL   69U
67 #define PMP_PMHL_MIN_SIZE       3U
68 #define PMP_PMHL_MAX_SIZE       5U
69
70 /*------------------------------------------------------------------------------------------------*/
71 /* Macro like functions                                                                           */
72 /*------------------------------------------------------------------------------------------------*/
73 /*! \brief Sets the port message length within a given message header
74  *  \param header The message header 
75  *  \param length The port message length
76  */
77 void Pmp_SetPml(uint8_t header[], uint8_t length)
78 {
79     header[PMP_IDX_PML_H] = 0U;
80     header[PMP_IDX_PML_L] = length;
81 }
82
83 /*! \brief Sets the port message header length within a given message header
84  *  \param header The message header 
85  *  \param length The port message header length. Valid values: 3..5.
86  *                Invalid values will set the PMHL to \c 0.
87  */
88 void Pmp_SetPmhl(uint8_t header[], uint8_t length)
89 {
90     if ((length < PMP_PMHL_MIN_SIZE) || (length > PMP_PMHL_MAX_SIZE))
91     {
92         length = 0U;
93     }
94
95     header[PMP_IDX_PMHL] = length | PMP_VERSION;
96 }
97
98 /*! \brief Sets the FIFO protocol header within a given message header
99  *  \param header The message header 
100  *  \param id   The FIFO id
101  *  \param type The port message type
102  */
103 void Pmp_SetFph(uint8_t header[], Pmp_FifoId_t id, Pmp_MsgType_t type)
104 {
105     header[PMP_IDX_FPH] = (uint8_t)((uint8_t)type << PMP_FPH_TYPE_POS) | (uint8_t)((uint8_t)id << PMP_FPH_ID_POS) | (uint8_t)PMP_DIR_TX;
106 }
107
108 /*! \brief Sets the field ExtType within a given message header
109  *  \param header The message header 
110  *  \param type   The command or status type
111  *  \param code   The command or status code
112  */
113 void Pmp_SetExtType(uint8_t header[], uint8_t type, uint8_t code)
114 {
115     header[PMP_IDX_EXT_TYPE] = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
116 }
117
118 /*! \brief Sets the sequence id within a given message header
119  *  \param header The message header 
120  *  \param sid    The sequence id
121  */
122 void Pmp_SetSid(uint8_t header[], uint8_t sid)
123 {
124     header[PMP_IDX_SID] = sid;
125 }
126
127 /*! \brief  Retrieves the port message length of a given port message buffer 
128  *  \param  header  Data buffer containing the port message.
129  *                  The required size of this buffer is 6 bytes.
130  *  \return The port message length in bytes or 0 if the PML is greater than 255.
131  */
132 uint8_t Pmp_GetPml(uint8_t header[])
133 {
134     uint8_t pml;
135     if (header[PMP_IDX_PML_H] != 0U)
136     {
137         pml = 0U;
138     }
139     else
140     {
141         pml = header[PMP_IDX_PML_L];
142     }
143
144     return pml;
145 }
146
147 /*! \brief  Retrieves the port message header length of a given port message buffer 
148  *  \param  header  Data buffer containing the port message.
149  *                  The required size of this buffer is 6 bytes.
150  *  \return The port message header length in bytes
151  */
152 uint8_t Pmp_GetPmhl(uint8_t header[])
153 {
154     return ((uint8_t)(header[PMP_IDX_PMHL] & (uint8_t)PMP_PMHL_MASK));
155 }
156
157 /*! \brief  Retrieves the FIFO number of a given port message buffer 
158  *  \param  header  Data buffer containing the port message.
159  *                  The required size of this buffer is 6 bytes.
160  *  \return The FIFO number
161  */
162 Pmp_FifoId_t Pmp_GetFifoId(uint8_t header[])
163 {
164     return (Pmp_FifoId_t)(((uint8_t)PMP_FPH_ID_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_ID_POS);
165 }
166
167 /*! \brief  Retrieves the FIFO Type of a given port message buffer 
168  *  \param  header  Data buffer containing the port message.
169  *                  The required size of this buffer is 6 bytes.
170  *  \return The FIFO type
171  */
172 Pmp_MsgType_t Pmp_GetMsgType(uint8_t header[])
173 {
174     return ((Pmp_MsgType_t)((PMP_FPH_TYPE_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_TYPE_POS));
175 }
176
177 /*! \brief  Retrieves the SequenceID of a given port message buffer 
178  *  \param  header  Data buffer containing the port message.
179  *                  The required size of this buffer is 6 bytes.
180  *  \return The SequenceID
181  */
182 uint8_t Pmp_GetSid(uint8_t header[])
183 {
184     return ((header)[PMP_IDX_SID]);
185 }
186
187 /*! \brief  Retrieves payload data of a port message
188  *  \param  header  Data buffer containing the port message.
189  *                  The required size of this buffer is 6 bytes.
190  *  \param  index   The index of the payload byte starting with '0'
191  *  \return The content of a payload data byte
192  */
193 uint8_t Pmp_GetData(uint8_t header[], uint8_t index)
194 {
195     return header[Pmp_GetPmhl(header) + 3U + index];
196 }
197
198 /*! \brief   Retrieves the payload size of the port message
199  *  \param   header  Data buffer containing the port message.
200  *                   The required size of this buffer is 6 bytes.
201  *  \details The function Pmp_VerifyHeader() must be called before
202  *           to verify that the port message fields are consistent.
203  *  \return  The payload size of a port message
204  */
205 uint8_t Pmp_GetDataSize(uint8_t header[])
206 {
207     return Pmp_GetPml(header) - (Pmp_GetPmhl(header) + 1U);
208 }
209
210 /*! \brief  Checks if header length fields are set to valid values 
211  *  \param  header  Data buffer containing the port message.
212  *                  The required size of this buffer is 6 bytes.
213  *  \param  buf_len Length of the complete port message in bytes
214  *  \return Returns \c true if the header was checked successfully,
215  *          otherwise \c false.
216  */
217 bool Pmp_VerifyHeader(uint8_t header[], uint8_t buf_len)
218 {
219     uint8_t pml = Pmp_GetPml(header);
220     uint8_t pmhl = Pmp_GetPmhl(header);
221     bool ok = true;
222
223     ok = ((pmhl >= 3U)&&(pmhl <= 5U))       ? ok : false;
224     ok = ((header[PMP_IDX_PMHL] & PMP_VERSION_MASK) == PMP_VERSION) ? ok : false;
225     ok = (pml >= (pmhl + 1U))               ? ok : false;
226     ok = ((pml + 2U) <= buf_len)            ? ok : false;
227     ok = (pml <= PMP_PML_MAX_SIZE_CTRL)     ? ok : false;
228     ok = ((header[PMP_IDX_FPH] & PMP_FPH_DIR_MASK) == PMP_FPH_DIR_RX) ? ok : false;
229
230     return ok;
231 }
232
233 /*------------------------------------------------------------------------------------------------*/
234 /* Implementation                                                                                 */
235 /*------------------------------------------------------------------------------------------------*/
236 /*! \brief  Creates a Port Message Header instance 
237  *  \param  self  The instance
238  */
239 void Pmh_Ctor(CPmh *self)
240 {
241     MISC_MEM_SET(self, 0, sizeof(*self));
242 }
243
244 /*! \brief  Inserts a port message header of the specified size into a given buffer 
245  *  \param  self        Header content to be written to the buffer (source)
246  *  \param  data        Data buffer the header shall be written to (target)
247  */
248 void Pmh_BuildHeader(CPmh *self, uint8_t data[])
249 {
250     uint8_t cnt;
251
252     data[PMP_IDX_PML_H]   = 0U;
253     data[PMP_IDX_PML_L]   = (uint8_t)self->pml;
254     data[PMP_IDX_PMHL]    = (uint8_t)PMP_VERSION | self->pmhl;
255     data[PMP_IDX_FPH]     = (uint8_t)PMP_DIR_TX | ((uint8_t)((self->fifo_id) << PMP_FPH_ID_POS)) |
256                             ((uint8_t)((self->msg_type) << PMP_FPH_TYPE_POS));
257
258     data[PMP_IDX_SID]     = self->sid;
259     data[PMP_IDX_EXT_TYPE]= self->ext_type;
260
261     for (cnt=3U; cnt < self->pmhl; cnt++)
262     {
263         data[3U + cnt] = 0U;                        /* add stuffing bytes */
264     }
265 }
266
267 /*! \brief  Decodes a given data buffer into a provided port message header structure 
268  *  \param  self        Header content structure (target)
269  *  \param  data        Data buffer containing the port message with a minimum size
270  *                      of 6 bytes (source)
271  */
272 void Pmh_DecodeHeader(CPmh *self, uint8_t data[])
273 {
274     self->pml = Pmp_GetPml(data);
275     self->pmhl  = data[PMP_IDX_PMHL] & PMP_PMHL_MASK;        /* ignore version */
276
277     self->fifo_id = Pmp_GetFifoId(data);
278     self->msg_type = Pmp_GetMsgType(data);
279     self->sid   = data[PMP_IDX_SID];
280     self->ext_type = data[PMP_IDX_EXT_TYPE];
281 }
282
283 /*! \brief      Setter function for FIFO protocol header which contains several subfields
284  *  \details    The "retransmitted" flag is currently not supported (always Tx)
285  *  \param      self        Reference to the PM content structure that shall be modified
286  *  \param      fifo_id     Id of the PM FIFO
287  *  \param      msg_type    PM type
288  */
289 void Pmh_SetFph(CPmh *self, Pmp_FifoId_t fifo_id, Pmp_MsgType_t msg_type)
290 {
291     self->msg_type = msg_type;
292     self->fifo_id = fifo_id;
293 }
294
295 /*! \brief  Retrieves the ExtType StatusType
296  *  \param  self    The instance
297  *  \return Returns The Status Type
298  */
299 Pmp_StatusType_t Pmh_GetExtStatusType(CPmh *self)
300 {
301     return ((Pmp_StatusType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
302 }
303
304 /*! \brief  Retrieves the ExtType StatusCode
305  *  \param  self    The instance
306  *  \return Returns The Status Code
307  */
308 Pmp_CommandCode_t Pmh_GetExtCommandCode(CPmh *self)
309 {
310     return ((Pmp_CommandCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
311 }
312
313 /*! \brief  Retrieves the ExtType StatusType
314  *  \param  self    The instance
315  *  \return Returns The Status Type
316  */
317 Pmp_CommandType_t Pmh_GetExtCommandType(CPmh *self)
318 {
319     return ((Pmp_CommandType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
320 }
321
322 /*! \brief  Retrieves the ExtType StatusCode
323  *  \param  self    The instance
324  *  \return Returns The Status Code
325  */
326 Pmp_StatusCode_t Pmh_GetExtStatusCode(CPmh *self)
327 {
328     return ((Pmp_StatusCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
329 }
330
331 /*! \brief      Sets the ExtType field by passing the values for type and code 
332  *  \details    The function is applicable for status and command
333  *  \param      self    The Instance
334  *  \param      type    The status or command type
335  *  \param      code    The status or command code
336  */
337 void Pmh_SetExtType(CPmh *self, uint8_t type, uint8_t code)
338 {
339     self->ext_type = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
340 }
341
342 /*!
343  * @}
344  * \endcond
345  */
346
347 /*------------------------------------------------------------------------------------------------*/
348 /* End of file                                                                                    */
349 /*------------------------------------------------------------------------------------------------*/
350