-
Notifications
You must be signed in to change notification settings - Fork 3
/
mcb_frame.c
161 lines (130 loc) · 3.86 KB
/
mcb_frame.c
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
/**
* @file mcb_frame.c
* @brief This file contains useful functions for framing purpose
*
* @author Firmware department
* @copyright Ingenia Motion Control (c) 2018. All rights reserved.
*/
#include "mcb_frame.h"
#include "mcb_usr.h"
#include <string.h>
/** Frame description
* Word 0 - Header
* Word 1..4 - Config data
* Word 5..N-1 - Cyclic data (optional)
* Word N - CRC
*/
/** Header elements */
typedef union
{
struct
{
/** Segmented message */
uint16_t u1Pending :1;
/** Frame command identification */
uint16_t u3Cmd :3;
/** Address of the Static Data */
uint16_t u12Addr :12;
};
uint16_t u16All;
} THeader;
int32_t Mcb_FrameCreateConfig(Mcb_TFrame* tFrame, uint16_t u16Addr, uint8_t u8Cmd, uint8_t u8Pending,
const void* pCfgBuf, bool bCalcCrc)
{
int32_t i32Err = 0;
while (1)
{
THeader tHeader;
if (tFrame == NULL)
{
i32Err = -1;
break;
}
tHeader.u12Addr = u16Addr;
tHeader.u3Cmd = u8Cmd;
tHeader.u1Pending = u8Pending;
tFrame->u16Buf[MCB_FRM_HEAD_IDX] = tHeader.u16All;
/* Copy config & cyclic buffer (if any) */
if (pCfgBuf != NULL)
{
memcpy(&tFrame->u16Buf[MCB_FRM_CONFIG_IDX], pCfgBuf, (sizeof(tFrame->u16Buf[0]) * MCB_FRM_CONFIG_SZ));
}
else
{
memset(&tFrame->u16Buf[MCB_FRM_CONFIG_IDX], 0, (sizeof(tFrame->u16Buf[0]) * MCB_FRM_CONFIG_SZ));
}
tFrame->u16Sz = MCB_FRM_HEAD_SZ + MCB_FRM_CONFIG_SZ;
if (bCalcCrc != false)
{
/* Compute CRC and add it to buffer */
tFrame->u16Buf[tFrame->u16Sz] = Mcb_IntfComputeCrc(tFrame->u16Buf, tFrame->u16Sz);
tFrame->u16Sz += MCB_FRM_CRC_SZ;
}
break;
}
return i32Err;
}
int32_t Mcb_FrameAppendCyclic(Mcb_TFrame* tFrame, const void* pCyclicBuf, uint16_t u16SzCyclic, bool bCalcCrc)
{
int32_t i32Err = 0;
while (1)
{
if (tFrame == NULL)
{
i32Err = -1;
break;
}
/* Check dynamic buffer size */
if (u16SzCyclic > MCB_FRM_MAX_CYCLIC_SZ)
{
i32Err = -2;
break;
}
/* Copy config & cyclic buffer (if any) */
if (pCyclicBuf != NULL)
{
memcpy(&tFrame->u16Buf[MCB_FRM_CYCLIC_IDX], pCyclicBuf, (sizeof(tFrame->u16Buf[0]) * u16SzCyclic));
}
else
{
memset(&tFrame->u16Buf[MCB_FRM_CYCLIC_IDX], 0, (sizeof(tFrame->u16Buf[0]) * u16SzCyclic));
}
tFrame->u16Sz += u16SzCyclic;
if (bCalcCrc != false)
{
/* Compute CRC and add it to buffer */
tFrame->u16Buf[tFrame->u16Sz] = Mcb_IntfComputeCrc(tFrame->u16Buf, tFrame->u16Sz);
tFrame->u16Sz += MCB_FRM_CRC_SZ;
}
break;
}
return i32Err;
}
bool Mcb_FrameGetSegmented(const Mcb_TFrame* tFrame)
{
THeader tHeader;
tHeader.u16All = tFrame->u16Buf[MCB_FRM_HEAD_IDX];
return (bool)tHeader.u1Pending;
}
uint16_t Mcb_FrameGetAddr(const Mcb_TFrame* tFrame)
{
THeader tHeader;
tHeader.u16All = tFrame->u16Buf[MCB_FRM_HEAD_IDX];
return (uint16_t)tHeader.u12Addr;
}
uint8_t Mcb_FrameGetCmd(const Mcb_TFrame* tFrame)
{
THeader tHeader;
tHeader.u16All = tFrame->u16Buf[MCB_FRM_HEAD_IDX];
return (uint8_t)tHeader.u3Cmd;
}
uint16_t Mcb_FrameGetConfigData(const Mcb_TFrame* tFrame, uint16_t* pu16Buf)
{
memcpy(pu16Buf, &tFrame->u16Buf[MCB_FRM_CONFIG_IDX], (sizeof(tFrame->u16Buf[0]) * MCB_FRM_CONFIG_SZ));
return MCB_FRM_CONFIG_SZ;
}
uint16_t Mcb_FrameGetCyclicData(const Mcb_TFrame* tFrame, uint16_t* pu16Buf, uint16_t u16Size)
{
memcpy(pu16Buf, &tFrame->u16Buf[MCB_FRM_CYCLIC_IDX], (sizeof(tFrame->u16Buf[0]) * u16Size));
return MCB_FRM_CONFIG_SZ;
}