COSA
An Object-Oriented Platform for Arduino Programming
VWI_Transmitter.cpp
Go to the documentation of this file.
1 
23 #include "VWI.hh"
24 #include <util/crc16.h>
25 
26 int
27 VWI::Transmitter::send(uint8_t dest, uint8_t port, const iovec_t* vec)
28 {
29  // Santiy check the io vector
30  if (UNLIKELY(vec == NULL)) return (EINVAL);
31 
32  // Check that the message is not too large
33  size_t len = iovec_size(vec);
34  if (UNLIKELY(len > PAYLOAD_MAX)) return (EMSGSIZE);
35 
36  uint8_t *tp = m_buffer + m_codec->PREAMBLE_MAX;
37  uint16_t crc = 0xffff;
38 
39  // Wait for transmitter to become available. Might be transmitting
40  while (m_enabled) yield();
41 
42  // Encode the message total length = length(1)+header(4)+payload(len)+crc(2)
43  uint8_t count = 1 + sizeof(header_t) + len + 2;
44  crc = _crc_ccitt_update(crc, count);
45  *tp++ = m_codec->encode4(count >> 4);
46  *tp++ = m_codec->encode4(count);
47 
48  // Encode the message header
49  header_t header;
50  header.network = s_rf->m_addr.network;
51  header.src = s_rf->m_addr.device;
52  header.dest = dest;
53  header.port = port;
54  uint8_t* bp = (uint8_t*) &header;
55  for (uint8_t i = 0; i < sizeof(header); i++) {
56  uint8_t data = *bp++;
57  crc = _crc_ccitt_update(crc, data);
58  *tp++ = m_codec->encode4(data >> 4);
59  *tp++ = m_codec->encode4(data);
60  }
61 
62  // Encode the message into symbols. Each byte is converted into
63  // 2 symbols, high nybble first, low nybble second
64  for (const iovec_t* vp = vec; vp->buf != NULL; vp++) {
65  uint8_t *bp = (uint8_t*) vp->buf;
66  for (uint8_t i = 0; i < vp->size; i++) {
67  uint8_t data = *bp++;
68  crc = _crc_ccitt_update(crc, data);
69  *tp++ = m_codec->encode4(data >> 4);
70  *tp++ = m_codec->encode4(data);
71  }
72  }
73 
74  // Append the FCS, 16 bits before encoding (4 symbols after
75  // encoding) Caution: VWI expects the _ones_complement_ of the CCITT
76  // CRC-16 as the FCS VWI sends FCS as low byte then hi byte
77  crc = ~crc;
78  *tp++ = m_codec->encode4(crc >> 4);
79  *tp++ = m_codec->encode4(crc);
80  *tp++ = m_codec->encode4(crc >> 12);
81  *tp++ = m_codec->encode4(crc >> 8);
82 
83  // Total number of symbols to send
84  m_length = m_codec->PREAMBLE_MAX + (count * 2);
85 
86  // Start the low level interrupt handler sending symbols
87  begin();
88  return (len);
89 }
90 
91 int
92 VWI::Transmitter::send(uint8_t dest, uint8_t port, const void* buf, size_t len)
93 {
94  if (UNLIKELY(len > PAYLOAD_MAX)) return (EMSGSIZE);
95  iovec_t vec[2];
96  iovec_t* vp = vec;
97  iovec_arg(vp, buf, len);
98  iovec_end(vp);
99  return (send(dest, port, vec));
100 }
#define EINVAL
Definition: Errno.h:49
#define NULL
Definition: Types.h:101
#define EMSGSIZE
Definition: Errno.h:117
virtual uint8_t encode4(uint8_t nibble)=0
static const uint8_t PAYLOAD_MAX
Definition: VWI.hh:158
Definition: Types.h:391
uint8_t dest
Destination device address.
Definition: VWI.hh:148
uint8_t src
Source device address.
Definition: VWI.hh:149
void(* yield)()
void * buf
Buffer pointer.
Definition: Types.h:392
uint8_t port
Port or message type.
Definition: VWI.hh:150
void begin()
Definition: VWI.hh:354
const uint8_t PREAMBLE_MAX
Definition: VWI.hh:85
int16_t network
Network address.
Definition: VWI.hh:147
int send(uint8_t dest, uint8_t port, const iovec_t *vec)
#define UNLIKELY(x)
Definition: Types.h:153
void iovec_arg(iovec_t *&vp, const void *buf, size_t size)
Definition: Types.h:430
void iovec_end(iovec_t *&vp)
Definition: Types.h:449
size_t iovec_size(const iovec_t *vec)
Definition: Types.h:407