telemetry

Dependents:   Everything Sequential_Timing FixedPWM FixedPWMWill

packet.cpp

Committer:
vsutardja
Date:
2016-03-18
Revision:
0:aca5a32d2759

File content as of revision 0:aca5a32d2759:

/**
 * Transmit and receive packet interfaces
 */

#include "telemetry.h"

namespace telemetry {

namespace internal {
  template<> void pkt_write<uint8_t>(TransmitPacket& interface, uint8_t data) {
    interface.write_uint8(data);
  }
  template<> void pkt_write<uint16_t>(TransmitPacket& interface, uint16_t data) {
    interface.write_uint16(data);
  }
  template<> void pkt_write<uint32_t>(TransmitPacket& interface, uint32_t data) {
    interface.write_uint32(data);
  }
  template<> void pkt_write<float>(TransmitPacket& interface, float data) {
    interface.write_float(data);
  }

  template<> uint8_t buf_read<uint8_t>(ReceivePacketBuffer& buffer) {
    return buffer.read_float();
  }
  template<> uint16_t buf_read<uint16_t>(ReceivePacketBuffer& buffer) {
    return buffer.read_uint16();
  }
  template<> uint32_t buf_read<uint32_t>(ReceivePacketBuffer& buffer) {
    return buffer.read_uint32();
  }
  template<> float buf_read<float>(ReceivePacketBuffer& buffer) {
    return buffer.read_float();
  }
}

FixedLengthTransmitPacket::FixedLengthTransmitPacket(HalInterface& hal,
    size_t length) :
        hal(hal),
        length(length),
        count(0) {
  for (int i=0; i<protocol::SOF_LENGTH; i++) {
    hal.transmit_byte(protocol::SOF_SEQ[i]);
  }

  hal.transmit_byte((length >> 8) & 0xff);
  hal.transmit_byte((length >> 0) & 0xff);

  valid = true;
}

void FixedLengthTransmitPacket::write_byte(uint8_t data) {
  if (!valid) {
    hal.do_error("Writing to invalid packet");
    return;
  } else if (count + 1 > length) {
    hal.do_error("Writing over packet length");
    return;
  }
  hal.transmit_byte(data);
#if SOF_LENGTH > 2
#error "Byte stuffing algorithm does not work for SOF_LENGTH > 2"
#endif
  if (data == protocol::SOF_SEQ[0]) {
    hal.transmit_byte(protocol::SOF_SEQ0_STUFF);
  }
  count++;
}

void FixedLengthTransmitPacket::write_uint8(uint8_t data) {
  write_byte(data);
}

void FixedLengthTransmitPacket::write_uint16(uint16_t data) {
  write_byte((data >> 8) & 0xff);
  write_byte((data >> 0) & 0xff);
}

void FixedLengthTransmitPacket::write_uint32(uint32_t data) {
  write_byte((data >> 24) & 0xff);
  write_byte((data >> 16) & 0xff);
  write_byte((data >> 8) & 0xff);
  write_byte((data >> 0) & 0xff);
}

void FixedLengthTransmitPacket::write_float(float data) {
  // TODO: THIS IS ENDIANNESS DEPENDENT, ABSTRACT INTO HAL?
  uint8_t *float_array = (uint8_t*) &data;
  write_byte(float_array[3]);
  write_byte(float_array[2]);
  write_byte(float_array[1]);
  write_byte(float_array[0]);
}

void FixedLengthTransmitPacket::finish() {
  if (!valid) {
    hal.do_error("Finish invalid packet");
    return;
  } else if (count != length) {
    hal.do_error("TX packet under length");
    return;
  }

  // TODO: add CRC check here
}

ReceivePacketBuffer::ReceivePacketBuffer(HalInterface& hal) :
    hal(hal) {
  new_packet();
}

void ReceivePacketBuffer::new_packet() {
  packet_length = 0;
  read_loc = 0;
}

void ReceivePacketBuffer::add_byte(uint8_t byte) {
  if (packet_length >= MAX_RECEIVE_PACKET_LENGTH) {
    hal.do_error("RX packet over length");
    return;
  }

  data[packet_length] = byte;
  packet_length++;
}

uint8_t ReceivePacketBuffer::read_uint8() {
  if (read_loc + 1 > packet_length) {
    hal.do_error("Read uint8 over length");
    return 0;
  }
  read_loc += 1;
  return data[read_loc - 1];
}

uint16_t ReceivePacketBuffer::read_uint16() {
  if (read_loc + 2 > packet_length) {
    hal.do_error("Read uint16 over length");
    return 0;
  }
  read_loc += 2;
  return ((uint16_t)data[read_loc - 2] << 8)
       | ((uint16_t)data[read_loc - 1] << 0);
}

uint32_t ReceivePacketBuffer::read_uint32() {
  if (read_loc + 4 > packet_length) {
    hal.do_error("Read uint32 over length");
    return 0;
  }
  read_loc += 4;
  return ((uint32_t)data[read_loc - 4] << 24)
       | ((uint32_t)data[read_loc - 3] << 16)
       | ((uint32_t)data[read_loc - 2] << 8)
       | ((uint32_t)data[read_loc - 1] << 0);
}

float ReceivePacketBuffer::read_float() {
  if (read_loc + 4 > packet_length) {
    hal.do_error("Read float over length");
    return 0;
  }
  read_loc += 4;
  float out = 0;
  uint8_t* out_array = (uint8_t*)&out;
  out_array[0] = data[read_loc - 1];
  out_array[1] = data[read_loc - 2];
  out_array[2] = data[read_loc - 3];
  out_array[3] = data[read_loc - 4];
  return out;
}

}