summaryrefslogtreecommitdiffstats
path: root/ucs2-lib/src/ucs_pmp.c
blob: ae333060dee206c6c8816dca4040a9b738de8756 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/*------------------------------------------------------------------------------------------------*/
/* UNICENS V2.1.0-3491                                                                            */
/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG.                              */
/*                                                                                                */
/* This program is free software: you can redistribute it and/or modify                           */
/* it under the terms of the GNU General Public License as published by                           */
/* the Free Software Foundation, either version 2 of the License, or                              */
/* (at your option) any later version.                                                            */
/*                                                                                                */
/* This program is distributed in the hope that it will be useful,                                */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of                                 */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                  */
/* GNU General Public License for more details.                                                   */
/*                                                                                                */
/* You should have received a copy of the GNU General Public License                              */
/* along with this program.  If not, see <http://www.gnu.org/licenses/>.                          */
/*                                                                                                */
/* You may also obtain this software under a propriety license from Microchip.                    */
/* Please contact Microchip for further information.                                              */
/*------------------------------------------------------------------------------------------------*/

/*!
 * \file
 * \brief Implementation of Port Message Protocol
 *
 * \cond UCS_INTERNAL_DOC
 * \addtogroup  G_PMH
 * @{
 */

/*------------------------------------------------------------------------------------------------*/
/* Includes                                                                                       */
/*------------------------------------------------------------------------------------------------*/
#include "ucs_pmp.h"
#include "ucs_misc.h"

/*------------------------------------------------------------------------------------------------*/
/* PMP Indexes                                                                                    */
/*------------------------------------------------------------------------------------------------*/
#define PMP_IDX_PML_H           0U
#define PMP_IDX_PML_L           1U
#define PMP_IDX_PMHL            2U
#define PMP_IDX_FPH             3U
#define PMP_IDX_SID             4U
#define PMP_IDX_EXT_TYPE        5U

/*------------------------------------------------------------------------------------------------*/
/* Masks and shifts for bit fields                                                                */
/*------------------------------------------------------------------------------------------------*/
#define PMP_PMHL_MASK           0x1FU      /* 0b00011111 */
#define PMP_VERSION_MASK        0xE0U      /* 0b11100000 */
#define PMP_VERSION             0x40U      /* Version: "2" */
#define PMP_FPH_TYPE_POS        1U
#define PMP_FPH_TYPE_MASK       0x06U      /* 0b00000110 */
#define PMP_FPH_ID_POS          3U
#define PMP_FPH_ID_MASK         0x38U      /* 0b00111000 */
#define PMP_FPH_DIR_RX          0x01U      /* RX: "1" */
#define PMP_FPH_DIR_MASK        0x01U      /* 0b00000001 */
#define PMP_EXT_TYPE_POS        5U
#define PMP_EXT_TYPE_MASK       0xE0U      /* 0b11100000 */
#define PMP_EXT_CODE_MASK       0x1FU      /* 0b00011111 */

/*------------------------------------------------------------------------------------------------*/
/* PMP Verification                                                                               */
/*------------------------------------------------------------------------------------------------*/
#define PMP_PML_MAX_SIZE_CTRL   69U
#define PMP_PMHL_MIN_SIZE       3U
#define PMP_PMHL_MAX_SIZE       5U

/*------------------------------------------------------------------------------------------------*/
/* Macro like functions                                                                           */
/*------------------------------------------------------------------------------------------------*/
/*! \brief Sets the port message length within a given message header
 *  \param header The message header 
 *  \param length The port message length
 */
void Pmp_SetPml(uint8_t header[], uint8_t length)
{
    header[PMP_IDX_PML_H] = 0U;
    header[PMP_IDX_PML_L] = length;
}

/*! \brief Sets the port message header length within a given message header
 *  \param header The message header 
 *  \param length The port message header length. Valid values: 3..5.
 *                Invalid values will set the PMHL to \c 0.
 */
void Pmp_SetPmhl(uint8_t header[], uint8_t length)
{
    if ((length < PMP_PMHL_MIN_SIZE) || (length > PMP_PMHL_MAX_SIZE))
    {
        length = 0U;
    }

    header[PMP_IDX_PMHL] = length | PMP_VERSION;
}

/*! \brief Sets the FIFO protocol header within a given message header
 *  \param header The message header 
 *  \param id   The FIFO id
 *  \param type The port message type
 */
void Pmp_SetFph(uint8_t header[], Pmp_FifoId_t id, Pmp_MsgType_t type)
{
    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;
}

/*! \brief Sets the field ExtType within a given message header
 *  \param header The message header 
 *  \param type   The command or status type
 *  \param code   The command or status code
 */
void Pmp_SetExtType(uint8_t header[], uint8_t type, uint8_t code)
{
    header[PMP_IDX_EXT_TYPE] = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
}

/*! \brief Sets the sequence id within a given message header
 *  \param header The message header 
 *  \param sid    The sequence id
 */
void Pmp_SetSid(uint8_t header[], uint8_t sid)
{
    header[PMP_IDX_SID] = sid;
}

/*! \brief  Retrieves the port message length of a given port message buffer 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \return The port message length in bytes or 0 if the PML is greater than 255.
 */
uint8_t Pmp_GetPml(uint8_t header[])
{
    uint8_t pml;
    if (header[PMP_IDX_PML_H] != 0U)
    {
        pml = 0U;
    }
    else
    {
        pml = header[PMP_IDX_PML_L];
    }

    return pml;
}

/*! \brief  Retrieves the port message header length of a given port message buffer 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \return The port message header length in bytes
 */
uint8_t Pmp_GetPmhl(uint8_t header[])
{
    return ((uint8_t)(header[PMP_IDX_PMHL] & (uint8_t)PMP_PMHL_MASK));
}

/*! \brief  Retrieves the FIFO number of a given port message buffer 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \return The FIFO number
 */
Pmp_FifoId_t Pmp_GetFifoId(uint8_t header[])
{
    return (Pmp_FifoId_t)(((uint8_t)PMP_FPH_ID_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_ID_POS);
}

/*! \brief  Retrieves the FIFO Type of a given port message buffer 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \return The FIFO type
 */
Pmp_MsgType_t Pmp_GetMsgType(uint8_t header[])
{
    return ((Pmp_MsgType_t)((PMP_FPH_TYPE_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_TYPE_POS));
}

/*! \brief  Retrieves the SequenceID of a given port message buffer 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \return The SequenceID
 */
uint8_t Pmp_GetSid(uint8_t header[])
{
    return ((header)[PMP_IDX_SID]);
}

/*! \brief  Retrieves payload data of a port message
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \param  index   The index of the payload byte starting with '0'
 *  \return The content of a payload data byte
 */
uint8_t Pmp_GetData(uint8_t header[], uint8_t index)
{
    return header[Pmp_GetPmhl(header) + 3U + index];
}

/*! \brief   Retrieves the payload size of the port message
 *  \param   header  Data buffer containing the port message.
 *                   The required size of this buffer is 6 bytes.
 *  \details The function Pmp_VerifyHeader() must be called before
 *           to verify that the port message fields are consistent.
 *  \return  The payload size of a port message
 */
uint8_t Pmp_GetDataSize(uint8_t header[])
{
    return Pmp_GetPml(header) - (Pmp_GetPmhl(header) + 1U);
}

/*! \brief  Checks if header length fields are set to valid values 
 *  \param  header  Data buffer containing the port message.
 *                  The required size of this buffer is 6 bytes.
 *  \param  buf_len Length of the complete port message in bytes
 *  \return Returns \c true if the header was checked successfully,
 *          otherwise \c false.
 */
bool Pmp_VerifyHeader(uint8_t header[], uint8_t buf_len)
{
    uint8_t pml = Pmp_GetPml(header);
    uint8_t pmhl = Pmp_GetPmhl(header);
    bool ok = true;

    ok = ((pmhl >= 3U)&&(pmhl <= 5U))       ? ok : false;
    ok = ((header[PMP_IDX_PMHL] & PMP_VERSION_MASK) == PMP_VERSION) ? ok : false;
    ok = (pml >= (pmhl + 1U))               ? ok : false;
    ok = ((pml + 2U) <= buf_len)            ? ok : false;
    ok = (pml <= PMP_PML_MAX_SIZE_CTRL)     ? ok : false;
    ok = ((header[PMP_IDX_FPH] & PMP_FPH_DIR_MASK) == PMP_FPH_DIR_RX) ? ok : false;

    return ok;
}

/*------------------------------------------------------------------------------------------------*/
/* Implementation                                                                                 */
/*------------------------------------------------------------------------------------------------*/
/*! \brief  Creates a Port Message Header instance 
 *  \param  self  The instance
 */
void Pmh_Ctor(CPmh *self)
{
    MISC_MEM_SET(self, 0, sizeof(*self));
}

/*! \brief  Inserts a port message header of the specified size into a given buffer 
 *  \param  self        Header content to be written to the buffer (source)
 *  \param  data        Data buffer the header shall be written to (target)
 */
void Pmh_BuildHeader(CPmh *self, uint8_t data[])
{
    uint8_t cnt;

    data[PMP_IDX_PML_H]   = 0U;
    data[PMP_IDX_PML_L]   = (uint8_t)self->pml;
    data[PMP_IDX_PMHL]    = (uint8_t)PMP_VERSION | self->pmhl;
    data[PMP_IDX_FPH]     = (uint8_t)PMP_DIR_TX | ((uint8_t)((self->fifo_id) << PMP_FPH_ID_POS)) |
                            ((uint8_t)((self->msg_type) << PMP_FPH_TYPE_POS));

    data[PMP_IDX_SID]     = self->sid;
    data[PMP_IDX_EXT_TYPE]= self->ext_type;

    for (cnt=3U; cnt < self->pmhl; cnt++)
    {
        data[3U + cnt] = 0U;                        /* add stuffing bytes */
    }
}

/*! \brief  Decodes a given data buffer into a provided port message header structure 
 *  \param  self        Header content structure (target)
 *  \param  data        Data buffer containing the port message with a minimum size
 *                      of 6 bytes (source)
 */
void Pmh_DecodeHeader(CPmh *self, uint8_t data[])
{
    self->pml = Pmp_GetPml(data);
    self->pmhl  = data[PMP_IDX_PMHL] & PMP_PMHL_MASK;        /* ignore version */

    self->fifo_id = Pmp_GetFifoId(data);
    self->msg_type = Pmp_GetMsgType(data);
    self->sid   = data[PMP_IDX_SID];
    self->ext_type = data[PMP_IDX_EXT_TYPE];
}

/*! \brief      Setter function for FIFO protocol header which contains several subfields
 *  \details    The "retransmitted" flag is currently not supported (always Tx)
 *  \param      self        Reference to the PM content structure that shall be modified
 *  \param      fifo_id     Id of the PM FIFO
 *  \param      msg_type    PM type
 */
void Pmh_SetFph(CPmh *self, Pmp_FifoId_t fifo_id, Pmp_MsgType_t msg_type)
{
    self->msg_type = msg_type;
    self->fifo_id = fifo_id;
}

/*! \brief  Retrieves the ExtType StatusType
 *  \param  self    The instance
 *  \return Returns The Status Type
 */
Pmp_StatusType_t Pmh_GetExtStatusType(CPmh *self)
{
    return ((Pmp_StatusType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
}

/*! \brief  Retrieves the ExtType StatusCode
 *  \param  self    The instance
 *  \return Returns The Status Code
 */
Pmp_CommandCode_t Pmh_GetExtCommandCode(CPmh *self)
{
    return ((Pmp_CommandCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
}

/*! \brief  Retrieves the ExtType StatusType
 *  \param  self    The instance
 *  \return Returns The Status Type
 */
Pmp_CommandType_t Pmh_GetExtCommandType(CPmh *self)
{
    return ((Pmp_CommandType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
}

/*! \brief  Retrieves the ExtType StatusCode
 *  \param  self    The instance
 *  \return Returns The Status Code
 */
Pmp_StatusCode_t Pmh_GetExtStatusCode(CPmh *self)
{
    return ((Pmp_StatusCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
}

/*! \brief      Sets the ExtType field by passing the values for type and code 
 *  \details    The function is applicable for status and command
 *  \param      self    The Instance
 *  \param      type    The status or command type
 *  \param      code    The status or command code
 */
void Pmh_SetExtType(CPmh *self, uint8_t type, uint8_t code)
{
    self->ext_type = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
}

/*!
 * @}
 * \endcond
 */

/*------------------------------------------------------------------------------------------------*/
/* End of file                                                                                    */
/*------------------------------------------------------------------------------------------------*/