KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mcf2.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 true;
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  return (uint32_t) (state->buf.end - state->buf.cur) - _MCF_HDR_LEN ;
123 }
124 
125 
126 uint32_t mcfEncodeFreeNext(MCFState * state)
127 {
128  // nothing written yet. Just return whatever is available.
129  if (state->buf.cur == state->buf.start) {
130  return (uint32_t)( state->buf.end - state->buf.start ) - ( _MCF_MSGHDR_LEN + _MCF_HDR_LEN );
131  }
132  return mcfEncodeFree(state) + state->msg.cntLength + _MCF_HDR_LEN;
133 }
134 
135 static void mcfEncodeEntry(MCFState * state)
136 {
137  uint16_t t;
138  state->msg.timestamp = _mcfTimeStamp();
139  mcfWriteU16(state, state->msg.timestamp - state->tsOffset);
140  t = ( state->msg.clazz << _MCF_CLASS_SHIFT ) & _MCF_CLASS_MASK;
141  t |= ( state->msg.typ << _MCF_TYPE_SHIFT) & _MCF_TYPE_MASK;
142  mcfWriteU16(state, t);
143  t = (state->msg.cntLength << _MCF_LEN_SHIFT) & _MCF_LEN_MASK;
144  t |= ( state->msg.identifier << _MCF_ID_SHIFT) & _MCF_ID_MASK;
145  mcfWriteU16(state, t);
146  state->buf.cur += state->msg.cntLength;
147  state->msgCount += 1;
148  state->msgCur += 1;
149 }
150 
151 bool mcfEncodeBuffer(MCFState * state, DataBuffer * db)
152 {
153  uint32_t len = dbLength(db);
154  if (len >= mcfEncodeFree(state)) {
155  //printf("Error: free=%d, len=%d\n", mcfEncodeFree(state), len);
156  return errSet(ERROR(E_OUTOFMEMORY));
157  }
158  memcpy(state->msg.cntPtr, db->start, len);
159  state->msg.cntLength = len;
160 
161  return true;
162 }
163 
164 bool mcfEncodeNext(MCFState * state)
165 {
166  if (state->buf.cur == state->buf.start) mcfInitEncode(state);
167  else mcfEncodeEntry(state);
168 
169  state->msg.cntPtr = state->buf.cur + _MCF_MSGHDR_LEN;
170 
171  return true;
172 }
173 
174 uint32_t mcfEncodeFinish(MCFState * state)
175 {
176  if (state->buf.cur == state->buf.start) return 0;
177  mcfEncodeEntry(state);
178  uint32_t len = state->buf.cur - state->buf.start;
179  state->buf.cur = state->buf.start;
180  mcfWriteU32(state, state->tsOffset);
181  mcfWriteU16(state, state->msgCount - 1);
182  return len;
183 }
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