// C++ code Copyright (C) David R. Evans G4AMJ/NQ0I #ifndef EDRH #define EDRH #include #include // edr classes #define HIGHEST_HIGH_BAND_CHANNEL 130 #define LONGEST_RECORD_LENGTH 3860 const int N_PRA_MODES = 7; class edr_file; // Miscellaneous routines which do not require an edr_record object inline boolean high_band(int ch) { return (ch <= HIGHEST_HIGH_BAND_CHANNEL); } inline boolean low_band(int ch) { return !high_band(ch); } // **************************** edr_record *************************** extern const int edr_duration(const int); class bdr_record; class edr_record : public data_record { friend class science_edr_record; friend class edr_file; friend class const_edr_file; protected: // certain functions are always available, not all of which are // accessible to the outside world. (NB "reveal" is misleading here) reveal(int, _hour, ((_record[24] << 8) + _record[25])); reveal(int, _second, ((_record[26] << 8) + _record[27])); public: // default constructor edr_record(void); // copy constructor edr_record(const edr_record&); // A note; I have experimented with several ways to try to use both // edr_record and bdr_record objects consistently within a program. // I can find no way (even deriving from a common base) that is not // an rather gross kludge. The leanest mechanism is simply to provide // for casting from bdr_record to edr_record. This is also a kludge, // if only because the polarisation information is lost in the process, // but at least all the kludges are pretty much confined to the casting // process, rather than being spread throughout the application program. edr_record(const bdr_record&); virtual ~edr_record(void) { } void operator=(const bdr_record&); void operator=(const edr_record &); inline byte record(const int n) const { return datum(n); } // input void operator=(edr_file&); // output int write(edr_file&); // several functions work for all (non-unknown) types of edr record // because there is a common "standard" header. // year reveal(int, year, _record[30]); // day (Jan 1 == 1); Page C-2 of 618-306 demonstrates that their "hour // of the year" is actually "hour of year + 24". That is, _hour() can // never return a value less than 24. (And if we believe that....) reveal(int, day, _hour() / 24); reveal(int, hour, _hour() % 24); reveal(int, minute, _second() / 60); reveal(int, second, _second() % 60); reveal(int, sc_mode, _record[6]); reveal(byte, sc, 2 - (_record[3] & 1)); // type of the record -- this can be handy virtual edr_record_type record_type(void) const; // name of record type char* record_type_name(void) const; // return an individual byte inline byte datum(const int n) const { return _record[n]; } reveal(const char *, sc_mode_name, _sc_mode_name[sc_mode()]); // some useful virtual functions virtual inline int n_sweeps(void) const { return 1; } inline const int duration(void) const { return edr_duration(sc_mode()); } }; // derived classes // *************************** science_edr_record ******************** extern n_statuses_per_edr(const int); class science_edr_record : public edr_record { public: science_edr_record(const edr_record&); science_edr_record(const science_edr_record&); inline science_edr_record(void) : edr_record() { } ~science_edr_record(void) { } void operator=(const edr_record&); inline edr_record_type record_type(void) const { return science; } // there are lots of special science-only functions. For almost all of // these, things go awry once we enter VIM, as there is no longer any // real correspondence between status words and sweeps. Therefore, if // we are in VIM, then reasonable defaults are returned without regard // to status words. int n_sweeps(void) const; // return rhcupper of a sweep [1--8] int rhcupper(const int s) const; // return ad from lower of a sweep [1--8] int ad_from_lower(const int s) const; // return pra_submode of a sweep [1--8] int pra_submode(const int s) const; // return name of pra submode in a sweep const char* pra_submode_name(const int s) const; // return pra_mode of a sweep [1--8] int pra_mode(const int s) const; // datum(sweep [1--8], channel [1--200]) int datum(const int s, const int c) const; // return status of a sweep [1--8] int status(const int s) const; // return por counter for a sweep [1--8] int por_counter(const int s = 1) const; // return total attenuation [1--8] (in dB) int attenuation(const int s = 1) const; // return the eight bits of subheader frequency information [1--8] int frequency(const int s) const; // return a complete scan -- passed address must be able to hold it! void scan(int* d, const int s = 1) const; // how long is a scan (in octets) int scan_octets(void) const; // return mode command (from sub header) inline int mode_command(void) const { return ((_record[240] << 8) + _record[241]); } // return configuration_command (from sub header) inline int configuration_command(void) const { return ((_record[242] << 8) + _record[243]); } // which channel number is lowest with real data? int min_valid_channel_nr(void) const; // which channel number is highest with real data? int max_valid_channel_nr(void) const; // through which physical channel did a datum signal pass? int channel(const int sweep, const int channel) const; // was the command to toggle channels? Can't use status word because // that is overwritten by the POR counter inline int configuration_channel_toggle_disable(void) const { return ((configuration_command() & 0x0800) >> 11); } // what is the polarisation of a datum? int polarisation(const int s, const int c) const; // duration of a scan, in seconds int sweep_duration(void) const; // is this a VIM mode edr? inline boolean vim(void) const { return ((sc_mode() == cr5a) || (sc_mode() == uv5a)); } // frequency of a given GS-8 scan (times 10) uint32 fixlo_frequency(const int n) const; // number of statuses inline int n_statuses(void) const { return n_statuses_per_edr(sc_mode()); } // is a particular sweep fixlo? inline boolean fixlo(const int s) const { return ((pra_submode(s) == fixlol) || (pra_submode(s) == fixloh)); } }; // ******************** engineering_edr_record ************* class engineering_edr_record : public edr_record { public: inline edr_record_type record_type(void) const { return engineering; } }; // ******************** decom_edr_record ************* class decom_edr_record : public edr_record { public: inline edr_record_type record_type(void) const { return decom; } }; // ******************** unknown_edr_record ************* class unknown_edr_record : public edr_record { public: inline edr_record_type record_type(void) const { return unknown; } }; // ************************ edr_file **************************** class edr_file : public data_file { friend class edr_record; enum { decom_map_length = 716 } ; protected: boolean previously_open; // big_array record_posn; BIG_ARRAY(uint32) record_posn; static int record_size[N_SC_MODES]; int32 _get_file_size(void); virtual int _read(byte* record_buffer); int _write(const byte* record_buffer); void _initialise_static(void); public: edr_file(FILE*); edr_file(DREstring filename, const char* mode = "rb" ); virtual ~edr_file(void); boolean magic_number_OK(void); virtual void read(GMDR&, const int rec_nr = -1); virtual void read(edr_record&, const int rec_nr = -1); virtual int32 seek(const int rec_nr); // wrt 0 virtual uint32 size(void); }; // **************************** const_edr_file ******************** // edr class with constant-length records class const_edr_file : public edr_file { int record_length; int _read(byte* record_buffer); public: const_edr_file(FILE*, const int rec_size = 1872); const_edr_file(DREstring& filename, const char* mode = "rb", const int rec_size = 1872); int32 seek(const int rec_nr); // wrt 0 uint32 size(void); void read(GMDR&, const int rec_nr = -1); void read(edr_record&, const int rec_nr = -1); }; #endif