#ifndef __CATCAM_PROCESSOR_H__ #define __CATCAM_PROCESSOR_H__ #ifdef __TI_COMPILER_VERSION__ #include #ifdef _BIG_ENDIAN #define IS_LITTLE_ENDIAN 0 #else #define IS_LITTLE_ENDIAN 1 #endif #else #include #include #endif #include "util/fifo.h" #ifndef IS_LITTLE_ENDIAN #define IS_LITTLE_ENDIAN 1 #endif #include "util/endian.h" #define PAGE_SIZE 32 template class Packet_Observer : public FIFO{ public: Packet_Observer(const unsigned int &buffer_size) : FIFO(buffer_size){ } virtual ~Packet_Observer(){} virtual bool ready() const = 0; virtual bool validate() const = 0; virtual bool seek_next() = 0; virtual bool require_more() const {return false;} virtual unsigned int current_packet_size() const = 0; }; template class A_Packet_Observer : public Packet_Observer<>{ public: static const unsigned int a_packet_size = PAGE_SIZE - 1; A_Packet_Observer(const unsigned int &buffer_size) : Packet_Observer<>(buffer_size){ } ~A_Packet_Observer(){} bool ready() const { return (Packet_Observer<>::stored() >= a_packet_size); } bool validate() const { return true; } bool seek_next(){ if(Packet_Observer<>::stored() < a_packet_size){return false;} Packet_Observer<>::skip(a_packet_size); return true; } unsigned int fetch_ITOW_ms() const { char buf[4]; this->inspect(buf, sizeof(buf), 0); return le_char4_2_num(*buf); } FloatType fetch_ITOW() const { return (FloatType)1E-3 * fetch_ITOW_ms(); } unsigned int current_packet_size() const { return PAGE_SIZE; } struct values_t { struct xyz_t { int x, y, z; } values[9]; }; values_t fetch_values() const { values_t result; { char buf[3]; for(int i = 0; i < 9; i++){ this->inspect(buf, 3, 4 + (3 * i)); result.values[i].x = buf[0]; result.values[i].y = buf[1]; result.values[i].z = buf[2]; } } return result; } }; template class I_Packet_Observer : public Packet_Observer<>{ protected: mutable unsigned int already_checked; const unsigned int continuous_pages; public: using Packet_Observer<>::stored; unsigned int current_packet_size() const { return already_checked; } unsigned int fetch_data_length() const { char buf[4]; this->inspect(buf, sizeof(buf), already_checked + 6); return le_char4_2_num(*buf); } I_Packet_Observer( const unsigned int &buffer_size, const unsigned int &_continuous_pages = 7) : Packet_Observer<>(buffer_size), already_checked(0), continuous_pages(_continuous_pages){ } ~I_Packet_Observer(){} bool ready() const { int _stored(stored()); //std::cerr << already_checked << "," << _stored << std::endl; if(already_checked < _stored){ switch((*this)[already_checked]){ case 'C': already_checked += (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages); break; case 'F': case 'H': default: return true; } } return false; } bool validate() const { return (((*this)[already_checked] == 'F') && (fetch_data_length() < (already_checked + (PAGE_SIZE - 1)))); } bool seek_next(){ if(ready()){ Packet_Observer<>::skip(current_packet_size()); already_checked = 0; } for(int _stored(stored()); _stored > 0; ){ unsigned int skip_length(0); switch((*this)[0]){ case 'H': already_checked = (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages); return true; case 'C': case 'F': default: skip_length = (PAGE_SIZE - 1); break; } Packet_Observer<>::skip(skip_length); _stored -= skip_length; } return false; } bool require_more() const { return (already_checked > 0) && (already_checked > stored()); } unsigned int fetch_ITOW_ms() const { char buf[4]; this->inspect(buf, sizeof(buf), 2); return le_char4_2_num(*buf); } FloatType fetch_ITOW() const { return (FloatType)1E-3 * fetch_ITOW_ms(); } unsigned int fetch_data(char *buf, unsigned int buf_length) const { if(!validate()){return 0;} unsigned int length(fetch_data_length()); if(length > buf_length){return 0;} int index(6); // 先頭ページ { unsigned int read_length( (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages) - 6); this->inspect(buf, read_length, index); buf += read_length; buf_length -= read_length; // 次に続く"IC"の'C'の分で+1してある index = (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages) + 1; } // それ以降 { unsigned int read_length( (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages) - 1); while(index < already_checked){ this->inspect(buf, read_length, index); buf += read_length; buf_length -= read_length; index += (PAGE_SIZE - 1) + (PAGE_SIZE * continuous_pages); read_length = (read_length > buf_length) ? buf_length : read_length; } } return length; } }; template class G_Packet_Observer : public Packet_Observer<>{ public: unsigned int current_packet_size() const { char buf[2]; this->inspect(buf, 2, 4); return min_macro( le_char2_2_num(*buf) + 8, (this->capacity / 2) ); } protected: bool valid_header() const { if(Packet_Observer<>::stored() < 2){ return false; } return ((((unsigned char)((*this)[0])) == 0xB5) && (((unsigned char)((*this)[1])) == 0x62)); } bool valid_size() const { int _stored(Packet_Observer<>::stored()); if(_stored < 6) return false; if(current_packet_size() > _stored) return false; return true; } bool valid_parity() const { int ck_a(0), ck_b(0), packet_size(current_packet_size()); for(int index(2); index < (packet_size - 2); index++){ ck_a += (unsigned char)(*this)[index]; ck_b += ck_a; } ck_a &= 0xFF; ck_b &= 0xFF; return ((((unsigned char)((*this)[packet_size - 2])) == ck_a) && (((unsigned char)((*this)[packet_size - 1])) == ck_b)); } public: G_Packet_Observer(const unsigned int &buffer_size) : Packet_Observer<>(buffer_size){ } ~G_Packet_Observer(){} bool ready() const { if(!valid_header()) return false; if(!valid_size()) return false; return true; } bool validate() const { return valid_parity(); } bool seek_next(){ if(ready()){ if(validate()){Packet_Observer<>::skip(current_packet_size());} else{Packet_Observer<>::skip(1);} } int _stored(Packet_Observer<>::stored()); while(_stored > 0){ if((unsigned char)((*this)[0]) == 0xB5){ if(_stored > 1){ if((unsigned char)((*this)[1]) == 0x62){return true;} else{_stored--; Packet_Observer<>::skip(1);} }else{break;} } _stored--; Packet_Observer<>::skip(1); } return false; } struct packet_type_t { const char &mclass; const char ∣ bool equals(const char klass, const char id) const { return ((mclass == klass) && (mid == id)); } packet_type_t(const char &klass, const char &id) : mclass(klass), mid(id) {} ~packet_type_t(){} }; packet_type_t packet_type() const { return packet_type_t((*this)[2], (*this)[3]); } unsigned int fetch_ITOW_ms() const { char buf[4]; this->inspect(buf, 4, 6); return le_char4_2_num(*buf); } FloatType fetch_ITOW() const { return (FloatType)1E-3 * fetch_ITOW_ms(); } unsigned short fetch_WN() const { char buf[2]; this->inspect(buf, 2, 10); return le_char2_2_num(*buf); } struct position_t { FloatType longitude, latitude, altitude; position_t(FloatType longi, FloatType lati, FloatType alti) : longitude(longi), latitude(lati), altitude(alti) {}; }; position_t fetch_position() const { //if(!packet_type().equals(0x01, 0x02)){} char buf1[4], buf2[4], buf3[4]; this->inspect(buf1, 4, 6 + 4); this->inspect(buf2, 4, 6 + 8); this->inspect(buf3, 4, 6 + 12); return position_t( (FloatType)1E-7 * le_char4_2_num(*buf1), (FloatType)1E-7 * le_char4_2_num(*buf2), (FloatType)1E-3 * le_char4_2_num(*buf3) ); } struct position_acc_t { FloatType horizontal, vertical; position_acc_t(FloatType h_acc, FloatType v_acc) : horizontal(h_acc), vertical(v_acc) {}; }; position_acc_t fetch_position_acc() const { //if(!packet_type().equals(0x01, 0x02)){} char buf1[4], buf2[4]; this->inspect(buf1, 4, 6 + 20); this->inspect(buf2, 4, 6 + 24); return position_acc_t( (FloatType)1E-3 * le_char4_2_num(*buf1), (FloatType)1E-3 * le_char4_2_num(*buf2) ); } struct velocity_t { FloatType north, east, down; velocity_t(FloatType v_n, FloatType v_e, FloatType v_d) : north(v_n), east(v_e), down(v_d) {}; }; velocity_t fetch_velocity() const { //if(!packet_type().equals(0x01, 0x12)){} char buf1[4], buf2[4], buf3[4]; this->inspect(buf1, 4, 6 + 4); this->inspect(buf2, 4, 6 + 8); this->inspect(buf3, 4, 6 + 12); return velocity_t( (FloatType)1E-2 * le_char4_2_num(*buf1), (FloatType)1E-2 * le_char4_2_num(*buf2), (FloatType)1E-2 * le_char4_2_num(*buf3) ); } struct velocity_acc_t { FloatType acc; velocity_acc_t(FloatType v_acc) : acc(v_acc) {}; }; velocity_acc_t fetch_velocity_acc() const { //if(!packet_type().equals(0x01, 0x12)){} char buf[4]; this->inspect(buf, 4, 6 + 28); return velocity_acc_t( (FloatType)1E-2 * le_char4_2_num(*buf) ); } struct svinfo_t { unsigned int channel_num; unsigned int svid; unsigned int flags; unsigned int quality_indicator; int signal_strength; int elevation; int azimuth; int pseudo_residual; svinfo_t(){} svinfo_t( unsigned int chn, unsigned int _svid, unsigned int _flags, unsigned int qi, int cno, int elev, int azim, int prres) : channel_num(chn), svid(_svid), flags(_flags), quality_indicator(qi), signal_strength(cno), elevation(elev), azimuth(azim), pseudo_residual(prres) {}; }; svinfo_t fetch_svinfo(unsigned int chn) const { //if(!packet_type().equals(0x01, 0x30)){} char buf[12]; this->inspect(buf, sizeof(buf), 6 + 8 + (chn * sizeof(buf))); return svinfo_t( (unsigned char)(*buf), (unsigned char)(*(buf + 1)), (unsigned char)(*(buf + 2)), (unsigned char)(*(buf + 3)), (unsigned char)(*(buf + 4)), (*(buf + 5)), le_char2_2_num(*(buf + 6)), le_char4_2_num(*(buf + 8))); } struct raw_measurement_t { FloatType carrier_phase, pseudo_range, doppler; unsigned int sv_number; int quarity, signal_strength; unsigned int lock_indicator; raw_measurement_t(){} raw_measurement_t( FloatType cp, FloatType pr, FloatType dopp, unsigned int sv_num, int q, int signal, unsigned int lock ) : carrier_phase(cp), pseudo_range(pr), doppler(dopp), sv_number(sv_num), quarity(q), signal_strength(signal), lock_indicator(lock) {}; }; raw_measurement_t fetch_raw(unsigned int index) const { //if(!packet_type().equals(0x02, 0x10)){} char buf[24]; this->inspect(buf, 24, 6 + 8 + (index * 24)); return raw_measurement_t( (FloatType)le_char8_2_num(*buf), (FloatType)le_char8_2_num(*(buf + 8)), (FloatType)le_char4_2_num(*(buf + 16)), (unsigned char)(*(buf + 20)), (*(buf + 21)), (*(buf + 22)), (unsigned char)(*(buf + 23)) ); } struct ephemeris_t { unsigned int sv_number; bool valid; // Subframe 1 unsigned int wn, ura, sv_health, iodc, t_oc; FloatType t_gd, a_f2, a_f1, a_f0; // Subframe 2 unsigned int iode, t_oe; FloatType c_rs, delta_n, m_0, c_uc, e, c_us, root_a; bool fit; // Subframe 3 FloatType c_ic, omega_0, c_is, i_0, c_rc, omega, omega_0_dot, i_0_dot; ephemeris_t() : valid(false) {} }; ephemeris_t fetch_ephemeris() const { //if(!packet_type().equals(0x02, 0x31)){} ephemeris_t ephemeris; { char buf[4]; this->inspect(buf, 4, 6); // SVID ephemeris.sv_number = le_char4_2_num(*buf); } if((this->current_packet_size() > (8 + 8))){ ephemeris.valid = true; unsigned char buf[32]; #define get_subframe(n) (this->inspect((char *)buf, 32, 6 + 8 + n * 32)) #define bits2uchar(index) buf[(((index / 30) - 2) * 4) + (2 - ((index % 30) / 8))] #define bits2char(index) (char)(bits2uchar(index)) #define bits2uchar_align(index, length) \ ((bits2uchar(index) \ & ((0xFF << (8 - length)) >> ((index % 30) % 8)) ) \ >> (8 - (length + (index % 30) % 8))) #define bytes2ushort(a, b) \ ((((unsigned short)a) << 8) | b) #define bytes2short(a, b) \ (short)(bytes2ushort(a, b)) #define bytes2uint(a, b, c, d) \ ((((((((unsigned int)a) << 8) | b) << 8) | c) << 8) | d) #define bytes2int(a, b, c, d) \ (int)(bytes2uint(a, b, c, d)) #define GPS_PI 3.1415926535898 #define DIV_POWER_2(n) (1.0 / (1 << ((n <= 30) ? (n) : 30)) / (1 << ((n <= 30) ? 0 : (n - 30)))) get_subframe(0); // Subframe 1 ephemeris.wn = (((unsigned short)bits2uchar(60)) << 2) | bits2uchar_align(68, 2); ephemeris.ura = bits2uchar_align(72, 4); ephemeris.sv_health = bits2uchar_align(76, 6); ephemeris.iodc = (((unsigned short)bits2uchar_align(82, 2)) << 2) | bits2uchar(210); ephemeris.t_gd = (FloatType)bits2char(196) * DIV_POWER_2(31); ephemeris.t_oc = bytes2ushort(bits2uchar(218), bits2uchar(226)) << 4; ephemeris.a_f2 = (FloatType)bits2char(240) * DIV_POWER_2(55); ephemeris.a_f1 = (FloatType)bytes2short(bits2uchar(248), bits2uchar(256)) * DIV_POWER_2(43); ephemeris.a_f0 = (FloatType)((((((int)bits2char(270)) << 8) | bits2uchar(278)) << 6) | (bits2uchar(286) >> 2)) * DIV_POWER_2(31); get_subframe(1); // Subframe 2 ephemeris.iode = bits2uchar(60); ephemeris.c_rs = (FloatType)bytes2short(bits2uchar(68), bits2uchar(76)) * DIV_POWER_2(5); ephemeris.delta_n = (FloatType)bytes2short(bits2uchar(90), bits2uchar(98)) * DIV_POWER_2(43) * GPS_PI; ephemeris.m_0 = (FloatType)bytes2int(bits2uchar(106), bits2uchar(120), bits2uchar(128), bits2uchar(136)) * DIV_POWER_2(31) * GPS_PI; ephemeris.c_uc = (FloatType)bytes2short(bits2uchar(150), bits2uchar(158)) * DIV_POWER_2(29); ephemeris.e = (FloatType)bytes2uint(bits2uchar(166), bits2uchar(180), bits2uchar(188), bits2uchar(196)) * DIV_POWER_2(33); ephemeris.c_us = (FloatType)bytes2short(bits2uchar(210), bits2uchar(218)) * DIV_POWER_2(29); ephemeris.root_a = (FloatType)bytes2uint(bits2uchar(226), bits2uchar(240), bits2uchar(248), bits2uchar(256)) * DIV_POWER_2(19); ephemeris.t_oe = bytes2ushort(bits2uchar(270), bits2uchar(278)) << 4; ephemeris.fit = (bits2uchar_align(286, 1) & 0x01); /* cout << hex; cout << setw(2) << setfill('0') << (unsigned int)bits2uchar(106) << "," << setw(2) << setfill('0') << (unsigned int)bits2uchar(120) << "," << setw(2) << setfill('0') << (unsigned int)bits2uchar(128) << "," << setw(2) << setfill('0') << (unsigned int)bits2uchar(136) << endl; cout << ephemeris.m_0 << endl; cout << dec; */ get_subframe(2); // Subframe 3 ephemeris.c_ic = (FloatType)bytes2short(bits2uchar(60), bits2uchar(68)) * DIV_POWER_2(29); ephemeris.omega_0 = (FloatType)bytes2int(bits2uchar(76), bits2uchar(90), bits2uchar(98), bits2uchar(106)) * DIV_POWER_2(31) * GPS_PI; ephemeris.c_is = (FloatType)bytes2short(bits2uchar(120), bits2uchar(128)) * DIV_POWER_2(29); ephemeris.i_0 = (FloatType)bytes2int(bits2uchar(136), bits2uchar(150), bits2uchar(158), bits2uchar(166)) * DIV_POWER_2(31) * GPS_PI; ephemeris.c_rc = (FloatType)bytes2short(bits2uchar(180), bits2uchar(188)) * DIV_POWER_2(5); ephemeris.omega = (FloatType)bytes2int(bits2uchar(196), bits2uchar(210), bits2uchar(218), bits2uchar(226)) * DIV_POWER_2(31) * GPS_PI; ephemeris.omega_0_dot = (FloatType)bytes2int((bits2uchar(240) & 0x80 ? 0xFF : 0), bits2uchar(240), bits2uchar(248), bits2uchar(256)) * DIV_POWER_2(43) * GPS_PI; ephemeris.i_0_dot = (FloatType)(short)((((unsigned short)bits2uchar(278)) << 6) | bits2uchar_align(286, 6) | (bits2uchar(278) & 0x80 ? 0xC000 : 0x0000)) * DIV_POWER_2(43) * GPS_PI; /* cout << hex; cout << setw(2) << setfill('0') << (unsigned int)bits2uchar(278) << "," << setw(2) << setfill('0') << (unsigned int)bits2uchar(286) << endl; cout << dec; */ #undef DIV_POWER_2 #undef GPS_PI #undef bytes2ushort #undef bytes2short #undef bytes2uint #undef bytes2int #undef bits2uchar_align #undef bits2char #undef bits2uchar #undef get_subframe } return ephemeris; } struct health_utc_iono_t { struct { bool healthy[32]; bool valid; } health; struct { FloatType a1, a0; unsigned int tot, wnt, ls, wnf, dn, lsf, spare; bool valid; } utc; struct { FloatType klob_a0, klob_a1, klob_a2, klob_a3, klob_b0, klob_b1, klob_b2, klob_b3; bool valid; } iono; health_utc_iono_t(){ health.valid = false; utc.valid = false; iono.valid = false; } }; health_utc_iono_t fetch_health_utc_iono() const { //if(!packet_type().equals(0x0b, 0x02)){} health_utc_iono_t health_utc_iono; { // Valid flag char buf; this->inspect(&buf, 1, 74); health_utc_iono.health.valid = (buf & 0x01); health_utc_iono.utc.valid = (buf & 0x02); health_utc_iono.iono.valid = (buf & 0x04); } if(health_utc_iono.health.valid){ // Health char buf[4]; this->inspect(buf, 4, 6); unsigned int mask(le_char4_2_num(*(buf))); for(int i(0), j(1); i < 32; i++, j<<=1){ health_utc_iono.health.healthy[i] = (mask & j); } } if(health_utc_iono.utc.valid){ // UTC char buf[32]; this->inspect(buf, 32, 10); health_utc_iono.utc.a1 = (FloatType)le_char8_2_num(*buf); health_utc_iono.utc.a0 = (FloatType)le_char8_2_num(*(buf + 8)); health_utc_iono.utc.tot = le_char4_2_num(*(buf + 16)); health_utc_iono.utc.wnt = le_char2_2_num(*(buf + 20)); health_utc_iono.utc.ls = le_char2_2_num(*(buf + 22)); health_utc_iono.utc.wnf = le_char2_2_num(*(buf + 24)); health_utc_iono.utc.dn = le_char2_2_num(*(buf + 26)); health_utc_iono.utc.lsf = le_char2_2_num(*(buf + 28)); health_utc_iono.utc.spare = le_char2_2_num(*(buf + 30)); } if(health_utc_iono.iono.valid){ // iono char buf[32]; this->inspect(buf, 32, 42); health_utc_iono.iono.klob_a0 = (FloatType)le_char4_2_num(*buf); health_utc_iono.iono.klob_a1 = (FloatType)le_char4_2_num(*(buf + 4)); health_utc_iono.iono.klob_a2 = (FloatType)le_char4_2_num(*(buf + 8)); health_utc_iono.iono.klob_a3 = (FloatType)le_char4_2_num(*(buf + 12)); health_utc_iono.iono.klob_b0 = (FloatType)le_char4_2_num(*(buf + 16)); health_utc_iono.iono.klob_b1 = (FloatType)le_char4_2_num(*(buf + 20)); health_utc_iono.iono.klob_b2 = (FloatType)le_char4_2_num(*(buf + 24)); health_utc_iono.iono.klob_b3 = (FloatType)le_char4_2_num(*(buf + 28)); } return health_utc_iono; } }; template class AbstractCatCAMProcessor{ protected: template void process_packet( char *buffer, int read_count, Observer &observer, bool &previous_seek_next, void (*handler)(const Observer &)){ observer.write(buffer + 1, read_count - 1); if(!previous_seek_next){ previous_seek_next = observer.seek_next(); } while(previous_seek_next && observer.ready()){ handler(observer); previous_seek_next = observer.seek_next(); } } template void process_packet( char *buffer, int read_count, Observer &observer, bool &previous_seek_next, Callback &handler){ observer.write(buffer + 1, read_count - 1); if(!previous_seek_next){ previous_seek_next = observer.seek_next(); } while(previous_seek_next && observer.ready()){ handler(observer); previous_seek_next = observer.seek_next(); } } }; template class CatCAMProcessor : public AbstractCatCAMProcessor { #define assign_observer(type) \ public: \ typedef type ## _Packet_Observer type ## _Observer_t; \ protected: \ type ## _Observer_t observer_ ## type; \ void (*packet_handler_ ## type)(const type ## _Observer_t &); \ bool previous_seek_next_ ## type assign_observer(A); assign_observer(G); assign_observer(I); #undef assign_observer Packet_Observer<> *require_more_observer; protected: int process_count; typedef AbstractCatCAMProcessor super_t; public: #define assign_initializer(type, buf_size) \ observer_ ## type(buf_size), \ packet_handler_ ## type(NULL), \ previous_seek_next_ ## type(observer_ ## type.ready()) CatCAMProcessor(const int &observer_buffer_size = PAGE_SIZE * 32) : assign_initializer(A, observer_buffer_size), assign_initializer(G, observer_buffer_size), assign_initializer(I, observer_buffer_size * 10000), require_more_observer(NULL), process_count(0) { } #undef assign_initializer virtual ~CatCAMProcessor(){} #define assign_setter(type, mark) \ void set_ ## mark ## _handler(void (*handler)(const type ## _Observer_t &)){ \ packet_handler_ ## type = handler; \ } assign_setter(A, a); assign_setter(G, g); assign_setter(I, i); #undef assign_setter public: virtual void process(char *buffer, int read_count){ if(require_more_observer){ require_more_observer->write(buffer, read_count); if(!require_more_observer->require_more()){ require_more_observer = NULL; } return; } switch(buffer[0]){ #define assign_case(type, header) \ case header : { \ if(packet_handler_ ## type){ \ super_t::process_packet( \ buffer, read_count, \ observer_ ## type, previous_seek_next_ ## type, packet_handler_ ## type); \ if(observer_ ## type.require_more()){ \ require_more_observer = &observer_ ## type; \ } \ } \ break; \ } assign_case(A, 'A'); assign_case(G, 'G'); assign_case(I, 'I'); #undef assign_case } } }; #endif /* __CATCAM_PROCESSOR_H__ */