00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef UBLOX_SERIALIZATION_H
00030 #define UBLOX_SERIALIZATION_H
00031
00032 #include <stdint.h>
00033 #include <boost/call_traits.hpp>
00034 #include <vector>
00035 #include <algorithm>
00036
00037 #include "checksum.h"
00038
00039 namespace ublox {
00040
00041 static const uint8_t DEFAULT_SYNC_A = 0xB5;
00042 static const uint8_t DEFAULT_SYNC_B = 0x62;
00043
00044 template <typename T>
00045 struct Serializer {
00046 static void read(const uint8_t *data, uint32_t count, typename boost::call_traits<T>::reference message);
00047 static uint32_t serializedLength(typename boost::call_traits<T>::param_type message);
00048 static void write(uint8_t *data, uint32_t size, typename boost::call_traits<T>::param_type message);
00049 };
00050
00051 template <typename T>
00052 class Message {
00053 public:
00054 static bool canDecode(uint8_t class_id, uint8_t message_id) {
00055 return std::find(keys_.begin(), keys_.end(), std::make_pair(class_id, message_id)) != keys_.end();
00056 }
00057
00058 static void addKey(uint8_t class_id, uint8_t message_id) {
00059 keys_.push_back(std::make_pair(class_id, message_id));
00060 }
00061
00062 struct StaticKeyInitializer
00063 {
00064 StaticKeyInitializer(uint8_t class_id, uint8_t message_id) { Message<T>::addKey(class_id, message_id); }
00065 };
00066
00067 private:
00068 static std::vector<std::pair<uint8_t,uint8_t> > keys_;
00069 };
00070
00071 struct Options
00072 {
00073 Options() : sync_a(DEFAULT_SYNC_A), sync_b(DEFAULT_SYNC_B) {}
00074 uint8_t sync_a, sync_b;
00075 };
00076
00077 class Reader {
00078 public:
00079 Reader(const uint8_t *data, uint32_t count, const Options &options = Options()) : data_(data), count_(count), found_(false), options_(options) {}
00080
00081 typedef const uint8_t *iterator;
00082
00083 iterator search()
00084 {
00085 if (found_) next();
00086
00087 for( ; count_ > 0; --count_, ++data_) {
00088 if (data_[0] == options_.sync_a && (count_ == 1 || data_[1] == options_.sync_b)) break;
00089 }
00090
00091 return data_;
00092 }
00093
00094 bool found()
00095 {
00096 if (found_) return true;
00097 if (count_ < 6) return false;
00098 if (data_[0] != options_.sync_a || data_[1] != options_.sync_b) return false;
00099 if (count_ < length() + 8) return false;
00100
00101 found_ = true;
00102 return true;
00103 }
00104
00105 iterator next() {
00106 if (found()) {
00107 uint32_t size = length() + 8;
00108 data_ += size; count_ -= size;
00109 }
00110 found_ = false;
00111 return data_;
00112 }
00113
00114 iterator pos() {
00115 return data_;
00116 }
00117
00118 iterator end() {
00119 return data_ + count_;
00120 }
00121
00122 uint8_t classId() { return data_[2]; }
00123 uint8_t messageId() { return data_[3]; }
00124 uint32_t length() { return (data_[5] << 8) + data_[4]; }
00125 const uint8_t *data() { return data_ + 6; }
00126 uint16_t checksum() { return *reinterpret_cast<const uint16_t *>(data_ + 6 + length()); }
00127
00128 template <typename T>
00129 bool read(typename boost::call_traits<T>::reference message, bool search = false)
00130 {
00131 if (search) this->search();
00132 if (!found()) return false;
00133 if (!Message<T>::canDecode(classId(), messageId())) return false;
00134
00135 uint16_t chk;
00136 if (calculateChecksum(data_ + 2, length() + 4, chk) != this->checksum()) {
00137
00138 return false;
00139 }
00140
00141 Serializer<T>::read(data_ + 6, length(), message);
00142 return true;
00143 }
00144
00145 template <typename T> bool hasType()
00146 {
00147 if (!found()) return false;
00148 return Message<T>::canDecode(classId(), messageId());
00149 }
00150
00151 bool isMessage(uint8_t class_id, uint8_t message_id)
00152 {
00153 if (!found()) return false;
00154 return (data_[2] == class_id && data_[3] == message_id);
00155 }
00156
00157 private:
00158 const uint8_t *data_;
00159 uint32_t count_;
00160 bool found_;
00161 Options options_;
00162 };
00163
00164 class Writer
00165 {
00166 public:
00167 Writer(uint8_t *data, uint32_t size, const Options &options = Options()) : data_(data), size_(size), options_(options) {}
00168
00169 typedef uint8_t *iterator;
00170
00171 template <typename T> bool write(const T& message, uint8_t class_id = T::CLASS_ID, uint8_t message_id = T::MESSAGE_ID) {
00172 uint32_t length = Serializer<T>::serializedLength(message);
00173 if (size_ < length + 8) return false;
00174 Serializer<T>::write(data_ + 6, size_ - 6, message);
00175 return write(0, length, class_id, message_id);
00176 }
00177
00178 bool write(const uint8_t* message, uint32_t length, uint8_t class_id, uint8_t message_id) {
00179 if (size_ < length + 8) return false;
00180 uint8_t *start = data_;
00181
00182
00183 *data_++ = options_.sync_a;
00184 *data_++ = options_.sync_b;
00185 *data_++ = class_id;
00186 *data_++ = message_id;
00187 *data_++ = length & 0xFF;
00188 *data_++ = (length >> 8) & 0xFF;
00189 size_ -= 6;
00190
00191
00192 if (message) std::copy(message, message + length, data_);
00193 data_ += length;
00194 size_ -= length;
00195
00196
00197 uint8_t ck_a, ck_b;
00198 calculateChecksum(start + 2, length + 4, ck_a, ck_b);
00199 *data_++ = ck_a;
00200 *data_++ = ck_b;
00201 size_ -= 2;
00202
00203 return true;
00204 }
00205
00206 iterator end() {
00207 return data_;
00208 }
00209
00210 private:
00211 uint8_t *data_;
00212 uint32_t size_;
00213 Options options_;
00214 };
00215
00216 }
00217
00218 #define DECLARE_UBLOX_MESSAGE(class_id, message_id, package, message) \
00219 template class ublox::Serializer<package::message>; \
00220 template class ublox::Message<package::message>; \
00221 namespace package { namespace { \
00222 static const ublox::Message<message>::StaticKeyInitializer static_key_initializer_##message(class_id, message_id); \
00223 } } \
00224
00225
00226 #include "serialization_ros.h"
00227
00228 #endif // UBLOX_SERIALIZATION_H