KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mcf.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  *
4  * Copyright 2013 KM3NeT Collaboration
5  *
6  * All Rights Reserved.
7  *
8  * mcf.c
9  *
10  * Created on: 4 jun. 2013
11  * Author: Vincent van Beveren
12  */
13 #include "net/mcf.h"
14 
15 #include <string.h>
16 #include <stdio.h>
17 
18 #include "errorcode.h"
19 #include "kernel/err.h"
20 
21 
22 #include "util/macro.h"
23 
24 #define _MCF_TYPE_MASK 0x0FFF
25 #define _MCF_TYPE_SHIFT 0
26 #define _MCF_CLASS_MASK 0xF000
27 #define _MCF_CLASS_SHIFT 12
28 #define _MCF_LEN_MASK 0xFFC0
29 #define _MCF_LEN_SHIFT 6
30 #define _MCF_ID_MASK 0x003F
31 #define _MCF_ID_SHIFT 0
32 
33 
34 #define _MCF_MSGHDR_LEN 6
35 #define _MCF_HDR_LEN 6
36 
37 static uint32_t mcfReadU32(MCFState * state)
38 {
39  uint32_t t;
40  dbReadU32(&state->buf, &t);
41  return t;
42 }
43 
44 static uint16_t mcfReadU16(MCFState * state)
45 {
46  uint16_t t;
47 
48  dbReadU16(&state->buf, &t);
49  return t;
50 }
51 
52 static void mcfWriteU16(MCFState * state, uint16_t v)
53 {
54  dbWriteU16(&state->buf, v);
55 }
56 
57 static void mcfWriteU32(MCFState * state, uint32_t v)
58 {
59  dbWriteU32(&state->buf, v);
60 }
61 
62 
63 void mcfInitState(MCFState * state, uint8_t * bufPtr, uint32_t bufLen)
64 {
65  state->buf.cur = bufPtr;
66  state->buf.start = bufPtr;
67  state->buf.end = bufPtr + bufLen;
68  state->buf.error = 0;
69 
70  state->tsOffset = 0;
71  state->msgCount = 0;
72  state->msgCur = 0;
73 
74 }
75 
76 static void initDecode(MCFState * state)
77 {
78  state->tsOffset = mcfReadU32(state);
79  state->msgCount = ( mcfReadU16(state) & 0x00FF ) + 1;
80 }
81 
82 bool mcfDecodeNext(MCFState * state)
83 {
84  uint16_t t;
85  if (state->buf.cur == state->buf.start) initDecode(state);
86  else {
87  state->buf.cur += state->msg.cntLength;
88  state->msgCur++;
89  }
90 
91 
92  if (state->msgCur >= state->msgCount) return false;
93 /* printf("mcfDecodeNext(): current message: %d, message count: %d\n",
94  state->msgCur, state->msgCount);*/
95 
96  state->msg.timestamp = state->tsOffset + mcfReadU16(state);
97  t = mcfReadU16(state);
98 
99  state->msg.clazz = ( t & _MCF_CLASS_MASK ) >> _MCF_CLASS_SHIFT;
100  state->msg.typ = ( t & _MCF_TYPE_MASK ) >> _MCF_TYPE_SHIFT;
101  t = mcfReadU16(state);
102  state->msg.cntLength = ( t & _MCF_LEN_MASK ) >> _MCF_LEN_SHIFT;
103  state->msg.identifier = ( t & _MCF_ID_MASK ) >> _MCF_ID_SHIFT;
104  state->msg.cntPtr = state->buf.cur;
105  return state->buf.error == 0;
106 }
107 
108 static void mcfInitEncode(MCFState * state)
109 {
110  state->tsOffset = _mcfTimeStamp();
111  state->msgCount = 0;
112  state->msgCur = 0;
113  state->buf.cur += _MCF_HDR_LEN; // jump over header, we'll fill it in at the end.
114 }
115 
116 uint32_t mcfEncodeFree(MCFState * state)
117 {
118  // There is no current message, return 0
119  if (state->buf.cur == state->buf.start) {
120  return 0;
121  }
122  // FIX 2019-03-21: if the buffer is almost full, this could return a negative number.
123  int free = (state->buf.end - state->buf.cur) - _MCF_HDR_LEN;
124  return (uint32_t)(free < 0 ? 0 : free);
125 }
126 
127 
128 uint32_t mcfEncodeFreeNext(MCFState * state)
129 {
130  // nothing written yet. Just return whatever is available.
131  if (state->buf.cur == state->buf.start) {
132  return (uint32_t)( state->buf.end - state->buf.start ) - ( _MCF_MSGHDR_LEN + _MCF_HDR_LEN );
133  }
134 
135  // FIX 2019-03-21a: previous message added to the bytes free!
136  // FIX 2019-03-21b: again, if the buffer almost full this could be negative!
137  int free = mcfEncodeFree(state) - state->msg.cntLength - _MCF_HDR_LEN;
138  return (uint32_t)(free < 0 ? 0 : free);
139 }
140 
141 static void mcfEncodeEntry(MCFState * state)
142 {
143  uint16_t t;
144  state->msg.timestamp = _mcfTimeStamp();
145  mcfWriteU16(state, state->msg.timestamp - state->tsOffset);
146  t = ( state->msg.clazz << _MCF_CLASS_SHIFT ) & _MCF_CLASS_MASK;
147  t |= ( state->msg.typ << _MCF_TYPE_SHIFT) & _MCF_TYPE_MASK;
148  mcfWriteU16(state, t);
149  t = (state->msg.cntLength << _MCF_LEN_SHIFT) & _MCF_LEN_MASK;
150  t |= ( state->msg.identifier << _MCF_ID_SHIFT) & _MCF_ID_MASK;
151  mcfWriteU16(state, t);
152  state->buf.cur += state->msg.cntLength;
153  state->msgCount += 1;
154  state->msgCur += 1;
155 }
156 
158 {
159  uint32_t len = dbLength(db);
160  if (len >= mcfEncodeFree(state)) {
161  //printf("Error: free=%d, len=%d\n", mcfEncodeFree(state), len);
162  return errSet(ERROR(E_OUTOFMEMORY));
163  }
164  memcpy(state->msg.cntPtr, db->start, len);
165  state->msg.cntLength = len;
166 
167  return state->buf.error == 0;
168 }
169 
170 bool mcfEncodeNext(MCFState * state)
171 {
172  if (state->buf.cur == state->buf.start) mcfInitEncode(state);
173  else mcfEncodeEntry(state);
174 
175  state->msg.cntPtr = state->buf.cur + _MCF_MSGHDR_LEN;
176 
177  return state->buf.error == 0;
178 }
179 
180 uint32_t mcfEncodeFinish(MCFState * state)
181 {
182  if (state->buf.cur == state->buf.start) return 0;
183  mcfEncodeEntry(state);
184  uint32_t len = state->buf.cur - state->buf.start;
185  state->buf.cur = state->buf.start;
186  mcfWriteU32(state, state->tsOffset);
187  mcfWriteU16(state, state->msgCount - 1);
188  return len;
189 }
uint32_t mcfEncodeFinish(MCFState *state)
Call this after encoding to complete the MCF packet.
Definition: mcf.c:180
uint32_t _mcfTimeStamp()
Dependency function.
Definition: network.c:90
Message Container Format formatter / parser.
uint32_t mcfEncodeFree()
Returns the number of bytes available for content in the current message.
bool dbReadU16(DataBuffer *buf, uint16_t *u)
Reads a unsigned short (16 bits unsigned) integer.
Definition: databuffer.c:186
uint8_t * end
End Pointer.
Definition: databuffer.h:48
bool mcfEncodeBuffer(MCFState *state, DataBuffer *db)
Encodes the content of a databuffer into the container.
Definition: mcf.c:157
uint8_t * start
Start Pointer.
Definition: databuffer.h:47
bool mcfEncodeNext(MCFState *state)
Creates a new encoding entry.
Definition: mcf.c:170
Defines a DataBuffer structure.
Definition: databuffer.h:45
static uint32_t dbLength(DataBuffer *buf)
Returns the lenght of the current buffer.
Definition: databuffer.h:83
int error
Last error.
Definition: databuffer.h:50
Manages the global system error.
uint32_t mcfEncodeFreeNext()
Returns the number of bytes available for content in the NEXT message.
#define E_OUTOFMEMORY
Generic error: There is no more memory.
Definition: errorcode.h:107
This module is responsible for distributing error codes.
bool dbReadU32(DataBuffer *buf, uint32_t *u)
Reads an 32 bits unsigned integer.
Definition: databuffer.c:219
void mcfInitState(MCFState *state, uint8_t *bufPtr, uint32_t bufLen)
Initializes the decoding or encoding of a Message Container Formatted message.
Definition: mcf.c:63
Definition: mcf.h:104
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
Provides common macros.
bool mcfDecodeNext(MCFState *state)
Decodes the next message.
Definition: mcf.c:82
uint8_t * cur
Current Pointer.
Definition: databuffer.h:49
bool dbWriteU32(DataBuffer *buf, uint32_t u)
Writes an 32 bits unsigned integer.
Definition: databuffer.c:200
bool dbWriteU16(DataBuffer *buf, uint16_t u)
Writes a unsigned short (16 bits unsigned) integer.
Definition: databuffer.c:162