OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [tools/] [src/] [librlink/] [RlinkPacketBuf.cpp] - Blame information for rev 40

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 20 wfjm
// $Id: RlinkPacketBuf.cpp 509 2013-04-21 20:46:20Z mueller $
2 10 wfjm
//
3 18 wfjm
// Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 10 wfjm
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 20 wfjm
// 2013-04-21   509   1.0.4  add SndAttn() method
17 19 wfjm
// 2013-02-03   481   1.0.3  use Rexception
18
// 2013-01-13   474   1.0.2  add PollAttn() method
19 18 wfjm
// 2013-01-04   469   1.0.1  SndOob(): Add filler 0 to ensure escape state
20 10 wfjm
// 2011-04-02   375   1.0    Initial version
21
// 2011-03-05   366   0.1    First draft
22
// ---------------------------------------------------------------------------
23
 
24
/*!
25
  \file
26 20 wfjm
  \version $Id: RlinkPacketBuf.cpp 509 2013-04-21 20:46:20Z mueller $
27 10 wfjm
  \brief   Implemenation of class RlinkPacketBuf.
28
 */
29
 
30
#include <sys/time.h>
31
 
32
// debug
33
#include <iostream>
34
 
35
#include "RlinkPacketBuf.hpp"
36
 
37
#include "librtools/RosFill.hpp"
38
#include "librtools/RosPrintf.hpp"
39
#include "librtools/RosPrintBvi.hpp"
40 19 wfjm
#include "librtools/Rexception.hpp"
41 10 wfjm
 
42
using namespace std;
43
 
44
/*!
45
  \class Retro::RlinkPacketBuf
46
  \brief FIXME_docs
47
*/
48
 
49 19 wfjm
// all method definitions in namespace Retro
50
namespace Retro {
51
 
52 10 wfjm
//------------------------------------------+-----------------------------------
53
// constants definitions
54
 
55
const uint32_t RlinkPacketBuf::kFlagSopSeen;
56
const uint32_t RlinkPacketBuf::kFlagEopSeen;
57
const uint32_t RlinkPacketBuf::kFlagNakSeen;
58
const uint32_t RlinkPacketBuf::kFlagAttnSeen;
59
const uint32_t RlinkPacketBuf::kFlagTout;
60
const uint32_t RlinkPacketBuf::kFlagDatDrop;
61
const uint32_t RlinkPacketBuf::kFlagDatMiss;
62
 
63
const uint8_t RlinkPacketBuf::kCPREF;
64
const uint8_t RlinkPacketBuf::kNCOMM;
65
const uint8_t RlinkPacketBuf::kCommaIdle;
66
const uint8_t RlinkPacketBuf::kCommaSop;
67
const uint8_t RlinkPacketBuf::kCommaEop;
68
const uint8_t RlinkPacketBuf::kCommaNak;
69
const uint8_t RlinkPacketBuf::kCommaAttn;
70
const uint8_t RlinkPacketBuf::kSymEsc;
71
 
72
//------------------------------------------+-----------------------------------
73
//! Default constructor
74
 
75
RlinkPacketBuf::RlinkPacketBuf()
76
  : fPktBuf(),
77
    fRawBuf(),
78
    fRawBufSize(0),
79
    fCrc(),
80
    fFlags(0),
81
    fNdone(0),
82
    fNesc(0),
83
    fNattn(0),
84
    fNidle(0),
85
    fNdrop(0)
86
{}
87
 
88
//------------------------------------------+-----------------------------------
89
//! Destructor
90
 
91
RlinkPacketBuf::~RlinkPacketBuf()
92
{}
93
 
94
//------------------------------------------+-----------------------------------
95
//! FIXME_docs
96
 
97
void RlinkPacketBuf::Init()
98
{
99
  fPktBuf.clear();
100
  fRawBufSize = 0;
101
  fCrc.Clear();
102
  fFlags = 0;
103
  fNdone = 0;
104
  fNesc  = 0;
105
  fNattn = 0;
106
  fNidle = 0;
107
  fNdrop = 0;
108
 
109
  return;
110
}
111
 
112
//------------------------------------------+-----------------------------------
113
//! FIXME_docs
114
 
115
bool RlinkPacketBuf::SndPacket(RlinkPort* port, RerrMsg& emsg)
116
{
117
  fRawBuf.reserve(2*fPktBuf.size()+2);        // max. size of raw data
118
  fRawBuf.clear();
119
 
120
  fRawBuf.push_back(kCommaSop);
121
 
122
  size_t   ni = fPktBuf.size();
123
  uint8_t* pi = fPktBuf.data();
124
  for (size_t i=0; i<ni; i++) {
125
    uint8_t c = *pi++;
126
    if (c == kSymEsc || (c >= kCPREF && c <= kCPREF+kNCOMM)) {
127
      fRawBuf.push_back(kSymEsc);
128
      fRawBuf.push_back(((~kCPREF) & 0xf0) | (c & 0x0f));
129
      fNesc += 1;
130
    } else {
131
      fRawBuf.push_back(c);
132
    }
133
  }
134
 
135
  fRawBuf.push_back(kCommaEop);
136
 
137
  return SndRaw(port, emsg);
138
 
139
}
140
 
141
//------------------------------------------+-----------------------------------
142
//! FIXME_docs
143
 
144
bool RlinkPacketBuf::RcvPacket(RlinkPort* port, size_t nrcv, float timeout,
145
                               RerrMsg& emsg)
146
{
147
  fPktBuf.clear();
148
 
149
  bool   escseen = false;                   // in esc
150
  bool   sopseen = false;                   // sop seen
151
  bool   eopseen = false;                   // eop seen
152
  bool   nakseen = false;                   // nak seen
153
 
154
  while (!(eopseen|nakseen)) {              // try till eop or nak received
155
    size_t   nread = nrcv - fPktBuf.size();
156
    // FIXME_code: if the 'enough data' handling below correct ?
157 19 wfjm
    if (nread < 0)  return true;
158
 
159 10 wfjm
    if (!sopseen) nread += 1;
160
    if (!eopseen) nread += 1;
161
 
162
    size_t sizeold = fRawBufSize;
163
    int irc = RcvRaw(port, nread, timeout, emsg);
164
 
165
    if (irc <= 0) {
166
      if (irc == RlinkPort::kTout) {
167
        SetFlagBit(kFlagTout);
168
        return true;
169
      } else {
170
        return false;
171
      }
172
    }
173
 
174
    uint8_t* pi = fRawBuf.data()+sizeold;
175
    for (int i=0; i<irc; i++) {
176
      uint8_t c = *pi++;
177
      if (escseen) {
178
        escseen = false;
179
        if (sopseen && !(nakseen || eopseen)) {
180
          fPktBuf.push_back((kCPREF & 0xf0) | (c & 0x0f));
181
        }
182
      } else if (c == kCommaSop) {
183
        if (!eopseen) {
184
          SetFlagBit(kFlagSopSeen);
185
          sopseen  = true;
186
        } else {
187
          // FIXME_code: handle multiple sop
188
        }
189
      } else if (c == kCommaEop) {
190
        SetFlagBit(kFlagEopSeen);
191
        eopseen  = true;
192
      } else if (c == kCommaNak) {
193
        SetFlagBit(kFlagNakSeen);
194
        nakseen  = true;
195
      } else if (c == kCommaAttn) {
196
        SetFlagBit(kFlagAttnSeen);
197
        fNattn += 1;
198
      } else if (c == kCommaIdle) {
199
        fNidle += 1;
200
      } else if (c == kSymEsc) {
201
        fNesc += 1;
202
        escseen = true;
203
      } else {
204
        if (sopseen && !(nakseen || eopseen)) {
205
          fPktBuf.push_back(c);
206
        } else {
207
          fNdrop += 1;
208
        }
209
      }
210 19 wfjm
    } // for (int i=0; i<irc; i++)
211 10 wfjm
 
212 19 wfjm
  } // while (!(eopseen|nakseen))
213
 
214 10 wfjm
  return true;
215
}
216
 
217
//------------------------------------------+-----------------------------------
218
//! FIXME_docs
219
 
220
double RlinkPacketBuf::WaitAttn(RlinkPort* port, double timeout, RerrMsg& emsg)
221
{
222
  if (timeout <= 0.)
223 19 wfjm
    throw Rexception("RlinkPacketBuf::WaitAttn()", "Bad args: timeout <= 0.");
224 10 wfjm
 
225
  struct timeval tval;
226
  gettimeofday(&tval, 0);
227
  double tbeg  = double(tval.tv_sec) + 1.e-6*double(tval.tv_usec);
228
  double trest = timeout;
229
 
230
  Init();
231
 
232
  while (trest > 0.) {
233
    size_t sizeold = fRawBufSize;
234
    int irc = RcvRaw(port, 1, trest, emsg);
235
 
236
    if (irc <= 0) {
237
      if (irc == RlinkPort::kTout) {
238
        SetFlagBit(kFlagTout);
239
        return -1.;
240
      } else {
241
        return -2.;
242
      }
243
    }
244
 
245
    gettimeofday(&tval, 0);
246
    double tend  = double(tval.tv_sec) + 1.e-6*double(tval.tv_usec);
247
    trest -= (tend-tbeg);
248
 
249
    uint8_t c = fRawBuf[sizeold];
250
 
251
    if (c == kCommaAttn) {
252
      fNattn += 1;
253
      SetFlagBit(kFlagAttnSeen);
254
      break;
255
    } else if (c == kCommaIdle) {
256
      fNidle += 1;
257
    } else {
258
      fNdrop += 1;
259
    }
260
 
261
    tbeg   = tend;
262
  }
263
 
264
  return timeout - trest;
265
}
266
 
267
//------------------------------------------+-----------------------------------
268
//! FIXME_docs
269
 
270 19 wfjm
int RlinkPacketBuf::PollAttn(RlinkPort* port, RerrMsg& emsg)
271
{
272
  Init();
273
 
274
  int irc = RcvRaw(port, 128, 0., emsg);
275
 
276
  if (irc <= 0) {
277
    if (irc == RlinkPort::kTout) {
278
      SetFlagBit(kFlagTout);
279
      return 0;
280
    } else {
281
      return -2;
282
    }
283
  }
284
 
285
  for (size_t i=0; i<(size_t)irc; i++) {
286
    uint8_t c = fRawBuf[i];
287
    if (c == kCommaAttn) {
288
      fNattn += 1;
289
      SetFlagBit(kFlagAttnSeen);
290
      break;
291
    } else if (c == kCommaIdle) {
292
      fNidle += 1;
293
    } else {
294
      fNdrop += 1;
295
    }
296
  }
297
 
298
  return fNattn;
299
}
300
 
301
//------------------------------------------+-----------------------------------
302
//! FIXME_docs
303
 
304 10 wfjm
bool RlinkPacketBuf::SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
305
                            RerrMsg& emsg)
306
{
307
  Init();
308
 
309
  fRawBuf.clear();
310
  fRawBuf.push_back(kSymEsc);                       // ESC
311
  fRawBuf.push_back(kSymEsc);                       // ESC
312
  fRawBuf.push_back((uint8_t)addr);                 // ADDR 
313
  fRawBuf.push_back((uint8_t)(data & 0x00ff));      // DL
314
  fRawBuf.push_back((uint8_t)((data>>8) & 0x00ff)); // DH
315 18 wfjm
  // write a filler char (just 0) to ensure that the 8b->9b stage in the
316
  // receiver (byte2cdata) is always out if the escape state...
317
  fRawBuf.push_back(0);                             // filler
318 10 wfjm
 
319
  return SndRaw(port, emsg);
320
}
321
 
322
//------------------------------------------+-----------------------------------
323
//! FIXME_docs
324
 
325
bool RlinkPacketBuf::SndKeep(RlinkPort* port, RerrMsg& emsg)
326
{
327
  Init();
328
 
329
  fRawBuf.clear();
330 20 wfjm
  fRawBuf.push_back(kSymEsc);               // ESC
331
  fRawBuf.push_back(kSymEsc);               // ESC
332 10 wfjm
 
333
  return SndRaw(port, emsg);
334
}
335
 
336
//------------------------------------------+-----------------------------------
337
//! FIXME_docs
338
 
339 20 wfjm
bool RlinkPacketBuf::SndAttn(RlinkPort* port, RerrMsg& emsg)
340
{
341
  Init();
342
 
343
  fRawBuf.clear();
344
  fRawBuf.push_back(kCommaAttn);            // Attn
345
 
346
  return SndRaw(port, emsg);
347
}
348
 
349
//------------------------------------------+-----------------------------------
350
//! FIXME_docs
351
 
352 10 wfjm
void RlinkPacketBuf::Dump(std::ostream& os, int ind, const char* text) const
353
{
354
  RosFill bl(ind);
355
  os << bl << (text?text:"--") << "RlinkPacketBuf @ " << this << endl;
356
  os << bl << "  fCrc:          " << RosPrintBvi(fCrc.Crc(), 0) << endl;
357
  os << bl << "  fFlags:        " << RosPrintBvi(fFlags, 0) << endl;
358
  os << bl << "  fNdone:        " << RosPrintf(fNdone,"d",4) << endl;
359
  os << bl << "  fNesc:         " << RosPrintf(fNesc,"d",4) << endl;
360
  os << bl << "  fNattn:        " << RosPrintf(fNattn,"d",4) << endl;
361
  os << bl << "  fNidle:        " << RosPrintf(fNidle,"d",4) << endl;
362
  os << bl << "  fNdrop:        " << RosPrintf(fNdrop,"d",4) << endl;
363
 
364
  os << bl << "  fPktBuf(size): " << RosPrintf(fPktBuf.size(),"d",4);
365
  size_t ncol  = max(1, (80-ind-4-6)/(2+1));
366
  for (size_t i=0; i< fPktBuf.size(); i++) {
367
    if (i%ncol == 0) os << "\n" << bl << "    " << RosPrintf(i,"d",4) << ": ";
368
    os << RosPrintBvi(fPktBuf[i],16) << " ";
369
  }
370
  os << endl;
371
 
372
  os << bl << "  fRawBuf(size): " << RosPrintf(fRawBufSize,"d",4);
373
  for (size_t i=0; i< fRawBufSize; i++) {
374
    if (i%ncol == 0) os << "\n" << bl << "    " << RosPrintf(i,"d",4) << ": ";
375
    os << RosPrintBvi(fRawBuf[i],16) << " ";
376
  }
377
  os << endl;
378
 
379
  return;
380
}
381
 
382
//------------------------------------------+-----------------------------------
383
//! FIXME_docs
384
 
385
bool RlinkPacketBuf::SndRaw(RlinkPort* port, RerrMsg& emsg)
386
{
387
  if (port==0 || !port->IsOpen())
388 19 wfjm
    throw Rexception("RlinkPacketBuf::SndRaw()", "Bad state: port not open");
389 10 wfjm
 
390
  fRawBufSize = fRawBuf.size();
391
  int irc = port->Write(fRawBuf.data(), fRawBuf.size(), emsg);
392
  if (irc < 0) return false;
393
  if ((size_t)irc != fRawBuf.size()) {
394
    emsg.Init("RlinkPacketBuf::SndRaw()", "failed to write all data");
395
    return false;
396
  }
397
 
398
  return true;
399
}
400
 
401
//------------------------------------------+-----------------------------------
402
//! FIXME_docs
403
 
404
int RlinkPacketBuf::RcvRaw(RlinkPort* port, size_t size, float timeout,
405
                           RerrMsg& emsg)
406
{
407
  if (port==0 || !port->IsOpen())
408 19 wfjm
    throw Rexception("RlinkPacketBuf::RcvRaw()", "Bad state: port not open");
409 10 wfjm
 
410
  if (fRawBuf.size() < fRawBufSize+size) fRawBuf.resize(fRawBufSize+size);
411
  int irc = port->Read(fRawBuf.data()+fRawBufSize, size, timeout, emsg);
412
  if (irc == RlinkPort::kEof) {
413
    emsg.Init("RlinkPacketBuf::RcvRaw()", "eof on read");
414
  }
415
 
416
  if (irc > 0) {
417
    fRawBufSize += irc;
418
  }
419
 
420
  return irc;
421
}
422
 
423 19 wfjm
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.