diff --git a/DGIdGateway/APRSWriter.cpp b/DGIdGateway/APRSWriter.cpp new file mode 100644 index 0000000..ae9e7cb --- /dev/null +++ b/DGIdGateway/APRSWriter.cpp @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2010-2014,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "APRSWriter.h" +#include "YSFDefines.h" +#include "Log.h" + +#include +#include +#include +#include + +CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix, bool debug) : +m_idTimer(1000U), +m_callsign(callsign), +m_debug(debug), +m_txFrequency(0U), +m_rxFrequency(0U), +m_latitude(0.0F), +m_longitude(0.0F), +m_height(0), +m_desc(), +m_suffix(suffix), +m_aprsAddress(), +m_aprsPort(port), +m_aprsSocket() +#if defined(USE_GPSD) +,m_gpsdEnabled(false), +m_gpsdAddress(), +m_gpsdPort(), +m_gpsdData() +#endif +{ + assert(!callsign.empty()); + assert(!address.empty()); + assert(port > 0U); + + if (!rptSuffix.empty()) { + m_callsign.append("-"); + m_callsign.append(rptSuffix.substr(0U, 1U)); + } + + m_aprsAddress = CUDPSocket::lookup(address); +} + +CAPRSWriter::~CAPRSWriter() +{ +} + +void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc) +{ + m_txFrequency = txFrequency; + m_rxFrequency = rxFrequency; + m_desc = desc; +} + +void CAPRSWriter::setStaticLocation(float latitude, float longitude, int height) +{ + m_latitude = latitude; + m_longitude = longitude; + m_height = height; +} + +void CAPRSWriter::setGPSDLocation(const std::string& address, const std::string& port) +{ +#if defined(USE_GPSD) + assert(!address.empty()); + assert(!port.empty()); + + m_gpsdEnabled = true; + m_gpsdAddress = address; + m_gpsdPort = port; +#endif +} + +bool CAPRSWriter::open() +{ +#if defined(USE_GPSD) + if (m_gpsdEnabled) { + int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData); + if (ret != 0) { + LogError("Error when opening access to gpsd - %d - %s", errno, ::gps_errstr(errno)); + return false; + } + + ::gps_stream(&m_gpsdData, WATCH_ENABLE | WATCH_JSON, NULL); + + LogMessage("Connected to GPSD"); + } +#endif + bool ret = m_aprsSocket.open(); + if (!ret) + return false; + + LogMessage("Opened connection to the APRS Gateway"); + + m_idTimer.setTimeout(60U); + m_idTimer.start(); + + return true; +} + +void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned char radio, float fLatitude, float fLongitude) +{ + assert(source != NULL); + assert(type != NULL); + + char callsign[15U]; + ::memcpy(callsign, source, YSF_CALLSIGN_LENGTH); + callsign[YSF_CALLSIGN_LENGTH] = 0x00U; + + size_t n = ::strspn(callsign, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + callsign[n] = 0x00U; + + if (!m_suffix.empty()) { + ::strcat(callsign, "-"); + ::strcat(callsign, m_suffix.substr(0U, 1U).c_str()); + } + + double tempLat = ::fabs(fLatitude); + double tempLong = ::fabs(fLongitude); + + double latitude = ::floor(tempLat); + double longitude = ::floor(tempLong); + + latitude = (tempLat - latitude) * 60.0 + latitude * 100.0; + longitude = (tempLong - longitude) * 60.0 + longitude * 100.0; + + char lat[20U]; + ::sprintf(lat, "%07.2lf", latitude); + + char lon[20U]; + ::sprintf(lon, "%08.2lf", longitude); + + char symbol; + switch (radio) { + case 0x24U: + case 0x28U: + case 0x30U: + symbol = '['; + break; + case 0x25U: + case 0x29U: + symbol = '>'; + break; + case 0x26U: + symbol = 'r'; + break; + default: + symbol = '-'; + break; + } + + char output[300U]; + ::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM\r\n", + callsign, m_callsign.c_str(), + lat, (fLatitude < 0.0F) ? 'S' : 'N', + lon, (fLongitude < 0.0F) ? 'W' : 'E', + symbol, type); + + if (m_debug) + LogDebug("APRS ==> %s", output); + + m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort); +} + +void CAPRSWriter::clock(unsigned int ms) +{ + m_idTimer.clock(ms); + +#if defined(USE_GPSD) + if (m_gpsdEnabled) { + if (m_idTimer.hasExpired()) { + sendIdFrameMobile(); + m_idTimer.start(); + } + + } else { +#endif + if (m_idTimer.hasExpired()) { + sendIdFrameFixed(); + m_idTimer.setTimeout(20U * 60U); + m_idTimer.start(); + } +#if defined(USE_GPSD) + } +#endif +} + +void CAPRSWriter::close() +{ + m_aprsSocket.close(); + +#if defined(USE_GPSD) + if (m_gpsdEnabled) { + ::gps_stream(&m_gpsdData, WATCH_DISABLE, NULL); + ::gps_close(&m_gpsdData); + } +#endif +} + +void CAPRSWriter::sendIdFrameFixed() +{ + // Default values aren't passed on + if (m_latitude == 0.0F && m_longitude == 0.0F) + return; + + char desc[200U]; + if (m_txFrequency != 0U) { + float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F; + ::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz%s%s", + (long double)(m_txFrequency) / 1000000.0F, + offset < 0.0F ? '-' : '+', + ::fabs(offset), m_desc.empty() ? "" : ", ", m_desc.c_str()); + } else { + ::sprintf(desc, "MMDVM Voice%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str()); + } + + const char* band = "4m"; + if (m_txFrequency >= 1200000000U) + band = "1.2"; + else if (m_txFrequency >= 420000000U) + band = "440"; + else if (m_txFrequency >= 144000000U) + band = "2m"; + else if (m_txFrequency >= 50000000U) + band = "6m"; + else if (m_txFrequency >= 28000000U) + band = "10m"; + + double tempLat = ::fabs(m_latitude); + double tempLong = ::fabs(m_longitude); + + double latitude = ::floor(tempLat); + double longitude = ::floor(tempLong); + + latitude = (tempLat - latitude) * 60.0 + latitude * 100.0; + longitude = (tempLong - longitude) * 60.0 + longitude * 100.0; + + char lat[20U]; + ::sprintf(lat, "%07.2lf", latitude); + + char lon[20U]; + ::sprintf(lon, "%08.2lf", longitude); + + std::string server = m_callsign; + size_t pos = server.find_first_of('-'); + if (pos == std::string::npos) + server.append("-S"); + else + server.append("S"); + + char output[500U]; + ::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n", + m_callsign.c_str(), server.c_str(), + lat, (m_latitude < 0.0F) ? 'S' : 'N', + lon, (m_longitude < 0.0F) ? 'W' : 'E', + float(m_height) * 3.28F, band, desc); + + if (m_debug) + LogDebug("APRS ==> %s", output); + + m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort); +} + +#if defined(USE_GPSD) +void CAPRSWriter::sendIdFrameMobile() +{ + if (!::gps_waiting(&m_gpsdData, 0)) + return; + +#if GPSD_API_MAJOR_VERSION >= 7 + if (::gps_read(&m_gpsdData, NULL, 0) <= 0) + return; +#else + if (::gps_read(&m_gpsdData) <= 0) + return; +#endif + + + if (m_gpsdData.status != STATUS_FIX) + return; + + bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET; + bool altitudeSet = (m_gpsdData.set & ALTITUDE_SET) == ALTITUDE_SET; + bool velocitySet = (m_gpsdData.set & SPEED_SET) == SPEED_SET; + bool bearingSet = (m_gpsdData.set & TRACK_SET) == TRACK_SET; + + if (!latlonSet) + return; + + float rawLatitude = float(m_gpsdData.fix.latitude); + float rawLongitude = float(m_gpsdData.fix.longitude); +#if GPSD_API_MAJOR_VERSION >= 9 + float rawAltitude = float(m_gpsdData.fix.altMSL); +#else + float rawAltitude = float(m_gpsdData.fix.altitude); +#endif + float rawVelocity = float(m_gpsdData.fix.speed); + float rawBearing = float(m_gpsdData.fix.track); + + char desc[200U]; + if (m_txFrequency != 0U) { + float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F; + ::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz%s%s", + (long double)(m_txFrequency) / 1000000.0F, + offset < 0.0F ? '-' : '+', + ::fabs(offset), m_desc.empty() ? "" : ", ", m_desc.c_str()); + } else { + ::sprintf(desc, "MMDVM Voice%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str()); + } + + const char* band = "4m"; + if (m_txFrequency >= 1200000000U) + band = "1.2"; + else if (m_txFrequency >= 420000000U) + band = "440"; + else if (m_txFrequency >= 144000000U) + band = "2m"; + else if (m_txFrequency >= 50000000U) + band = "6m"; + else if (m_txFrequency >= 28000000U) + band = "10m"; + + double tempLat = ::fabs(rawLatitude); + double tempLong = ::fabs(rawLongitude); + + double latitude = ::floor(tempLat); + double longitude = ::floor(tempLong); + + latitude = (tempLat - latitude) * 60.0 + latitude * 100.0; + longitude = (tempLong - longitude) * 60.0 + longitude * 100.0; + + char lat[20U]; + ::sprintf(lat, "%07.2lf", latitude); + + char lon[20U]; + ::sprintf(lon, "%08.2lf", longitude); + + std::string server = m_callsign; + size_t pos = server.find_first_of('-'); + if (pos == std::string::npos) + server.append("-S"); + else + server.append("S"); + + char output[500U]; + ::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&", + m_callsign.c_str(), server.c_str(), + lat, (rawLatitude < 0.0F) ? 'S' : 'N', + lon, (rawLongitude < 0.0F) ? 'W' : 'E'); + + if (bearingSet && velocitySet) + ::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F); + + if (altitudeSet) + ::sprintf(output + ::strlen(output), "/A=%06.0f", float(rawAltitude) * 3.28F); + + ::sprintf(output + ::strlen(output), "%s %s\r\n", band, desc); + + if (m_debug) + LogDebug("APRS ==> %s", output); + + m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort); +} +#endif diff --git a/DGIdGateway/APRSWriter.h b/DGIdGateway/APRSWriter.h new file mode 100644 index 0000000..f014b20 --- /dev/null +++ b/DGIdGateway/APRSWriter.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010,2011,2012,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef APRSWriter_H +#define APRSWriter_H + +#include "UDPSocket.h" +#include "Timer.h" + +#include + +#if !defined(_WIN32) && !defined(_WIN64) +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(USE_GPSD) +#include +#endif +#else +#include +#endif + +class CAPRSWriter { +public: + CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix, bool debug); + ~CAPRSWriter(); + + bool open(); + + void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc); + + void setStaticLocation(float latitude, float longitude, int height); + + void setGPSDLocation(const std::string& address, const std::string& port); + + void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude); + + void clock(unsigned int ms); + + void close(); + +private: + CTimer m_idTimer; + std::string m_callsign; + bool m_debug; + unsigned int m_txFrequency; + unsigned int m_rxFrequency; + float m_latitude; + float m_longitude; + int m_height; + std::string m_desc; + std::string m_suffix; + in_addr m_aprsAddress; + unsigned int m_aprsPort; + CUDPSocket m_aprsSocket; +#if defined(USE_GPSD) + bool m_gpsdEnabled; + std::string m_gpsdAddress; + std::string m_gpsdPort; + struct gps_data_t m_gpsdData; +#endif + + void sendIdFrameFixed(); + void sendIdFrameMobile(); +}; + +#endif diff --git a/DGIdGateway/CRC.cpp b/DGIdGateway/CRC.cpp new file mode 100644 index 0000000..f2c3cbc --- /dev/null +++ b/DGIdGateway/CRC.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "CRC.h" + +#include "Utils.h" +#include "Log.h" + +#include +#include +#include +#include + +const uint16_t CCITT16_TABLE2[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; + + +void CCRC::addCCITT16(unsigned char *in, unsigned int length) +{ + assert(in != NULL); + assert(length > 2U); + + union { + uint16_t crc16; + uint8_t crc8[2U]; + }; + + crc16 = 0U; + + for (unsigned i = 0U; i < (length - 2U); i++) + crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; + + crc16 = ~crc16; + + in[length - 1U] = crc8[0U]; + in[length - 2U] = crc8[1U]; +} + +bool CCRC::checkCCITT16(const unsigned char *in, unsigned int length) +{ + assert(in != NULL); + assert(length > 2U); + + union { + uint16_t crc16; + uint8_t crc8[2U]; + }; + + crc16 = 0U; + + for (unsigned i = 0U; i < (length - 2U); i++) + crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; + + crc16 = ~crc16; + + return crc8[0U] == in[length - 1U] && crc8[1U] == in[length - 2U]; +} + +unsigned char CCRC::addCRC(const unsigned char* in, unsigned int length) +{ + assert(in != NULL); + + unsigned char crc = 0U; + + for (unsigned int i = 0U; i < length; i++) + crc += in[i]; + + return crc; +} \ No newline at end of file diff --git a/DGIdGateway/CRC.h b/DGIdGateway/CRC.h new file mode 100644 index 0000000..20482c8 --- /dev/null +++ b/DGIdGateway/CRC.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(CRC_H) +#define CRC_H + +class CCRC +{ +public: + static void addCCITT16(unsigned char* in, unsigned int length); + static bool checkCCITT16(const unsigned char* in, unsigned int length); + + static unsigned char addCRC(const unsigned char* in, unsigned int length); +}; + +#endif diff --git a/DGIdGateway/Conf.cpp b/DGIdGateway/Conf.cpp new file mode 100644 index 0000000..dffd9a1 --- /dev/null +++ b/DGIdGateway/Conf.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Conf.h" +#include "Log.h" + +#include +#include +#include +#include +#include + +const int BUFFER_SIZE = 500; + +enum SECTION { + SECTION_NONE, + SECTION_GENERAL, + SECTION_INFO, + SECTION_LOG, + SECTION_APRS, + SECTION_YSF_NETWORK, + SECTION_FCS_NETWORK, + SECTION_DGID, + SECTION_GPSD +}; + +CConf::CConf(const std::string& file) : +m_file(file), +m_callsign(), +m_suffix(), +m_id(0U), +m_rptAddress(), +m_rptPort(0U), +m_myAddress(), +m_myPort(0U), +m_rfHangTime(60U), +m_netHangTime(60U), +m_debug(false), +m_daemon(false), +m_rxFrequency(0U), +m_txFrequency(0U), +m_power(0U), +m_latitude(0.0F), +m_longitude(0.0F), +m_height(0), +m_name(), +m_description(), +m_logDisplayLevel(0U), +m_logFileLevel(0U), +m_logFilePath(), +m_logFileRoot(), +m_aprsEnabled(false), +m_aprsAddress(), +m_aprsPort(0U), +m_aprsSuffix(), +m_aprsDescription(), +m_ysfNetHosts(), +m_ysfRFHangTime(60U), +m_ysfNetHangTime(60U), +m_ysfNetDebug(false), +m_fcsRFHangTime(60U), +m_fcsNetHangTime(60U), +m_fcsNetDebug(false), +m_dgIdData(), +m_gpsdEnabled(false), +m_gpsdAddress(), +m_gpsdPort() +{ +} + +CConf::~CConf() +{ +} + +bool CConf::read() +{ + FILE* fp = ::fopen(m_file.c_str(), "rt"); + if (fp == NULL) { + ::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str()); + return false; + } + + SECTION section = SECTION_NONE; + + DGIdData* dgIdData = NULL; + + char buffer[BUFFER_SIZE]; + while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) { + if (buffer[0U] == '#') + continue; + + if (buffer[0U] == '[') { + if (::strncmp(buffer, "[General]", 9U) == 0) + section = SECTION_GENERAL; + else if (::strncmp(buffer, "[Info]", 6U) == 0) + section = SECTION_INFO; + else if (::strncmp(buffer, "[Log]", 5U) == 0) + section = SECTION_LOG; + else if (::strncmp(buffer, "[APRS]", 6U) == 0) + section = SECTION_APRS; + else if (::strncmp(buffer, "[YSF Network]", 13U) == 0) + section = SECTION_YSF_NETWORK; + else if (::strncmp(buffer, "[FCS Network]", 13U) == 0) + section = SECTION_FCS_NETWORK; + else if (::strncmp(buffer, "[DGId=", 6U) == 0) { + section = SECTION_DGID; + dgIdData = new DGIdData; + dgIdData->m_dgId = (unsigned int)::atoi(buffer + 6U); + m_dgIdData.push_back(dgIdData); + } else if (::strncmp(buffer, "[GPSD]", 6U) == 0) + section = SECTION_GPSD; + else + section = SECTION_NONE; + + continue; + } + + char* key = ::strtok(buffer, " \t=\r\n"); + if (key == NULL) + continue; + + char* value = ::strtok(NULL, "\r\n"); + if (section == SECTION_GENERAL) { + if (::strcmp(key, "Callsign") == 0) { + // Convert the callsign to upper case + for (unsigned int i = 0U; value[i] != 0; i++) + value[i] = ::toupper(value[i]); + m_callsign = value; + } else if (::strcmp(key, "Suffix") == 0) { + // Convert the callsign to upper case + for (unsigned int i = 0U; value[i] != 0; i++) + value[i] = ::toupper(value[i]); + m_suffix = value; + } else if (::strcmp(key, "Id") == 0) + m_id = (unsigned int)::atoi(value); + else if (::strcmp(key, "RptAddress") == 0) + m_rptAddress = value; + else if (::strcmp(key, "RptPort") == 0) + m_rptPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "LocalAddress") == 0) + m_myAddress = value; + else if (::strcmp(key, "LocalPort") == 0) + m_myPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "RFHangTime") == 0) + m_ysfRFHangTime = m_fcsRFHangTime = m_rfHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "NetHangTime") == 0) + m_ysfNetHangTime = m_fcsNetHangTime = m_netHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "Debug") == 0) + m_debug = ::atoi(value) == 1; + else if (::strcmp(key, "Daemon") == 0) + m_daemon = ::atoi(value) == 1; + } else if (section == SECTION_INFO) { + if (::strcmp(key, "TXFrequency") == 0) + m_txFrequency = (unsigned int)::atoi(value); + else if (::strcmp(key, "RXFrequency") == 0) + m_rxFrequency = (unsigned int)::atoi(value); + else if (::strcmp(key, "Power") == 0) + m_power = (unsigned int)::atoi(value); + else if (::strcmp(key, "Latitude") == 0) + m_latitude = float(::atof(value)); + else if (::strcmp(key, "Longitude") == 0) + m_longitude = float(::atof(value)); + else if (::strcmp(key, "Height") == 0) + m_height = ::atoi(value); + else if (::strcmp(key, "Name") == 0) + m_name = value; + else if (::strcmp(key, "Description") == 0) + m_description = value; + } else if (section == SECTION_LOG) { + if (::strcmp(key, "FilePath") == 0) + m_logFilePath = value; + else if (::strcmp(key, "FileRoot") == 0) + m_logFileRoot = value; + else if (::strcmp(key, "FileLevel") == 0) + m_logFileLevel = (unsigned int)::atoi(value); + else if (::strcmp(key, "DisplayLevel") == 0) + m_logDisplayLevel = (unsigned int)::atoi(value); + } else if (section == SECTION_APRS) { + if (::strcmp(key, "Enable") == 0) + m_aprsEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) + m_aprsAddress = value; + else if (::strcmp(key, "Port") == 0) + m_aprsPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "Suffix") == 0) + m_aprsSuffix = value; + else if (::strcmp(key, "Description") == 0) + m_aprsDescription = value; + } else if (section == SECTION_YSF_NETWORK) { + if (::strcmp(key, "Hosts") == 0) + m_ysfNetHosts = value; + else if (::strcmp(key, "RFHangTime") == 0) + m_ysfRFHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "NetHangTime") == 0) + m_ysfNetHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "Debug") == 0) + m_ysfNetDebug = ::atoi(value) == 1; + } else if (section == SECTION_FCS_NETWORK) { + if (::strcmp(key, "RFHangTime") == 0) + m_fcsRFHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "NetHangTime") == 0) + m_fcsNetHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "Debug") == 0) + m_fcsNetDebug = ::atoi(value) == 1; + } else if (section == SECTION_DGID) { + assert(dgIdData != NULL); + if (::strcmp(key, "Type") == 0) { + dgIdData->m_type = value; + dgIdData->m_static = false; + if (::strcmp(value, "YSF") == 0) { + dgIdData->m_rfHangTime = m_ysfRFHangTime; + dgIdData->m_netHangTime = m_ysfNetHangTime; + dgIdData->m_debug = m_ysfNetDebug; + } else if (::strcmp(value, "FCS") == 0) { + dgIdData->m_rfHangTime = m_fcsRFHangTime; + dgIdData->m_netHangTime = m_fcsNetHangTime; + dgIdData->m_debug = m_fcsNetDebug; + } else { + dgIdData->m_rfHangTime = m_rfHangTime; + dgIdData->m_netHangTime = m_netHangTime; + dgIdData->m_debug = false; + } + } else if (::strcmp(key, "RFHangTime") == 0) + dgIdData->m_rfHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "NetHangTime") == 0) + dgIdData->m_netHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "Static") == 0) + dgIdData->m_static = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) + dgIdData->m_address = value; + else if (::strcmp(key, "Name") == 0) + dgIdData->m_name = value; + else if (::strcmp(key, "Port") == 0) + dgIdData->m_port = (unsigned int)::atoi(value); + else if (::strcmp(key, "Local") == 0) + dgIdData->m_local = (unsigned int)::atoi(value); + else if (::strcmp(key, "Destination") == 0) { + char* p1 = ::strtok(value, ","); + char* p2 = ::strtok(NULL, "\r\n"); + IMRSDestination* dest = new IMRSDestination; + dest->m_dgId = (unsigned int)::atoi(p1); + dest->m_address = p2; + dgIdData->m_destinations.push_back(dest); + } else if (::strcmp(key, "Debug") == 0) + dgIdData->m_debug = ::atoi(value) == 1; + } else if (section == SECTION_GPSD) { + if (::strcmp(key, "Enable") == 0) + m_gpsdEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) + m_gpsdAddress = value; + else if (::strcmp(key, "Port") == 0) + m_gpsdPort = value; + } + } + + ::fclose(fp); + + return true; +} + +std::string CConf::getCallsign() const +{ + return m_callsign; +} + +std::string CConf::getSuffix() const +{ + return m_suffix; +} + +unsigned int CConf::getId() const +{ + return m_id; +} + +std::string CConf::getRptAddress() const +{ + return m_rptAddress; +} + +unsigned int CConf::getRptPort() const +{ + return m_rptPort; +} + +std::string CConf::getMyAddress() const +{ + return m_myAddress; +} + +unsigned int CConf::getMyPort() const +{ + return m_myPort; +} + +bool CConf::getDebug() const +{ + return m_debug; +} + +bool CConf::getDaemon() const +{ + return m_daemon; +} + +unsigned int CConf::getRxFrequency() const +{ + return m_rxFrequency; +} + +unsigned int CConf::getTxFrequency() const +{ + return m_txFrequency; +} + +unsigned int CConf::getPower() const +{ + return m_power; +} + +float CConf::getLatitude() const +{ + return m_latitude; +} + +float CConf::getLongitude() const +{ + return m_longitude; +} + +int CConf::getHeight() const +{ + return m_height; +} + +std::string CConf::getName() const +{ + return m_name; +} + +std::string CConf::getDescription() const +{ + return m_description; +} + +unsigned int CConf::getLogDisplayLevel() const +{ + return m_logDisplayLevel; +} + +unsigned int CConf::getLogFileLevel() const +{ + return m_logFileLevel; +} + +std::string CConf::getLogFilePath() const +{ + return m_logFilePath; +} + +std::string CConf::getLogFileRoot() const +{ + return m_logFileRoot; +} + +bool CConf::getAPRSEnabled() const +{ + return m_aprsEnabled; +} + +std::string CConf::getAPRSAddress() const +{ + return m_aprsAddress; +} + +unsigned int CConf::getAPRSPort() const +{ + return m_aprsPort; +} + +std::string CConf::getAPRSSuffix() const +{ + return m_aprsSuffix; +} + +std::string CConf::getAPRSDescription() const +{ + return m_aprsDescription; +} + +std::string CConf::getYSFNetHosts() const +{ + return m_ysfNetHosts; +} + +std::vector CConf::getDGIdData() const +{ + return m_dgIdData; +} + +bool CConf::getGPSDEnabled() const +{ + return m_gpsdEnabled; +} + +std::string CConf::getGPSDAddress() const +{ + return m_gpsdAddress; +} + +std::string CConf::getGPSDPort() const +{ + return m_gpsdPort; +} + diff --git a/DGIdGateway/Conf.h b/DGIdGateway/Conf.h new file mode 100644 index 0000000..cdbb88c --- /dev/null +++ b/DGIdGateway/Conf.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(CONF_H) +#define CONF_H + +#include +#include + +struct IMRSDestination { + std::string m_address; + unsigned int m_dgId; +}; + +struct DGIdData { + unsigned int m_dgId; + std::string m_type; + bool m_static; + std::string m_name; + std::string m_address; + unsigned int m_port; + unsigned int m_local; + std::vector m_destinations; + unsigned int m_rfHangTime; + unsigned int m_netHangTime; + bool m_debug; +}; + +class CConf +{ +public: + CConf(const std::string& file); + ~CConf(); + + bool read(); + + // The General section + std::string getCallsign() const; + std::string getSuffix() const; + unsigned int getId() const; + std::string getRptAddress() const; + unsigned int getRptPort() const; + std::string getMyAddress() const; + unsigned int getMyPort() const; + bool getDebug() const; + bool getDaemon() const; + + // The Info section + unsigned int getRxFrequency() const; + unsigned int getTxFrequency() const; + unsigned int getPower() const; + float getLatitude() const; + float getLongitude() const; + int getHeight() const; + std::string getName() const; + std::string getDescription() const; + + // The Log section + unsigned int getLogDisplayLevel() const; + unsigned int getLogFileLevel() const; + std::string getLogFilePath() const; + std::string getLogFileRoot() const; + + // The APRS section + bool getAPRSEnabled() const; + std::string getAPRSAddress() const; + unsigned int getAPRSPort() const; + std::string getAPRSSuffix() const; + std::string getAPRSDescription() const; + + // The YSF Network section + std::string getYSFNetHosts() const; + + // The DG-ID Section + std::vector getDGIdData() const; + + // The GPSD section + bool getGPSDEnabled() const; + std::string getGPSDAddress() const; + std::string getGPSDPort() const; + +private: + std::string m_file; + std::string m_callsign; + std::string m_suffix; + unsigned int m_id; + std::string m_rptAddress; + unsigned int m_rptPort; + std::string m_myAddress; + unsigned int m_myPort; + unsigned int m_rfHangTime; + unsigned int m_netHangTime; + bool m_debug; + bool m_daemon; + + unsigned int m_rxFrequency; + unsigned int m_txFrequency; + unsigned int m_power; + float m_latitude; + float m_longitude; + int m_height; + std::string m_name; + std::string m_description; + + unsigned int m_logDisplayLevel; + unsigned int m_logFileLevel; + std::string m_logFilePath; + std::string m_logFileRoot; + + bool m_aprsEnabled; + std::string m_aprsAddress; + unsigned int m_aprsPort; + std::string m_aprsSuffix; + std::string m_aprsDescription; + + std::string m_ysfNetHosts; + unsigned int m_ysfRFHangTime; + unsigned int m_ysfNetHangTime; + bool m_ysfNetDebug; + + unsigned int m_fcsRFHangTime; + unsigned int m_fcsNetHangTime; + bool m_fcsNetDebug; + + std::vector m_dgIdData; + + bool m_gpsdEnabled; + std::string m_gpsdAddress; + std::string m_gpsdPort; +}; + +#endif diff --git a/DGIdGateway/DGIdGateway.cpp b/DGIdGateway/DGIdGateway.cpp new file mode 100644 index 0000000..bec6cf6 --- /dev/null +++ b/DGIdGateway/DGIdGateway.cpp @@ -0,0 +1,556 @@ +/* +* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "YSFReflectors.h" +#include "DGIdGateway.h" +#include "DGIdNetwork.h" +#include "YSFNetwork.h" +#include "FCSNetwork.h" +#include "UDPSocket.h" +#include "StopWatch.h" +#include "Version.h" +#include "YSFFICH.h" +#include "Thread.h" +#include "Timer.h" +#include "Utils.h" +#include "Log.h" + +#if defined(_WIN32) || defined(_WIN64) +#include +#else +#include +#include +#include +#include +#include +#endif + +#if defined(_WIN32) || defined(_WIN64) +const char* DEFAULT_INI_FILE = "DGIdGateway.ini"; +#else +const char* DEFAULT_INI_FILE = "/etc/DGIdGateway.ini"; +#endif + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + const char* iniFile = DEFAULT_INI_FILE; + if (argc > 1) { + for (int currentArg = 1; currentArg < argc; ++currentArg) { + std::string arg = argv[currentArg]; + if ((arg == "-v") || (arg == "--version")) { + ::fprintf(stdout, "DGIdGateway version %s\n", VERSION); + return 0; + } else if (arg.substr(0, 1) == "-") { + ::fprintf(stderr, "Usage: DGIdGateway [-v|--version] [filename]\n"); + return 1; + } else { + iniFile = argv[currentArg]; + } + } + } + + CDGIdGateway* gateway = new CDGIdGateway(std::string(iniFile)); + + int ret = gateway->run(); + + delete gateway; + + return ret; +} + +CDGIdGateway::CDGIdGateway(const std::string& configFile) : +m_callsign(), +m_suffix(), +m_conf(configFile), +m_writer(NULL), +m_gps(NULL) +{ +} + +CDGIdGateway::~CDGIdGateway() +{ +} + +int CDGIdGateway::run() +{ + bool ret = m_conf.read(); + if (!ret) { + ::fprintf(stderr, "DGIdGateway: cannot read the .ini file\n"); + return 1; + } + + setlocale(LC_ALL, "C"); + +#if !defined(_WIN32) && !defined(_WIN64) + bool m_daemon = m_conf.getDaemon(); + if (m_daemon) { + // Create new process + pid_t pid = ::fork(); + if (pid == -1) { + ::fprintf(stderr, "Couldn't fork() , exiting\n"); + return -1; + } + else if (pid != 0) { + exit(EXIT_SUCCESS); + } + + // Create new session and process group + if (::setsid() == -1) { + ::fprintf(stderr, "Couldn't setsid(), exiting\n"); + return -1; + } + + // Set the working directory to the root directory + if (::chdir("/") == -1) { + ::fprintf(stderr, "Couldn't cd /, exiting\n"); + return -1; + } + + // If we are currently root... + if (getuid() == 0) { + struct passwd* user = ::getpwnam("mmdvm"); + if (user == NULL) { + ::fprintf(stderr, "Could not get the mmdvm user, exiting\n"); + return -1; + } + + uid_t mmdvm_uid = user->pw_uid; + gid_t mmdvm_gid = user->pw_gid; + + // Set user and group ID's to mmdvm:mmdvm + if (setgid(mmdvm_gid) != 0) { + ::fprintf(stderr, "Could not set mmdvm GID, exiting\n"); + return -1; + } + + if (setuid(mmdvm_uid) != 0) { + ::fprintf(stderr, "Could not set mmdvm UID, exiting\n"); + return -1; + } + + // Double check it worked (AKA Paranoia) + if (setuid(0) != -1) { + ::fprintf(stderr, "It's possible to regain root - something is wrong!, exiting\n"); + return -1; + } + } + } +#endif + + ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel()); + if (!ret) { + ::fprintf(stderr, "DGIdGateway: unable to open the log file\n"); + return 1; + } + +#if !defined(_WIN32) && !defined(_WIN64) + if (m_daemon) { + ::close(STDIN_FILENO); + ::close(STDOUT_FILENO); + ::close(STDERR_FILENO); + } +#endif + + m_callsign = m_conf.getCallsign(); + m_suffix = m_conf.getSuffix(); + + bool debug = m_conf.getDebug(); + in_addr rptAddress = CUDPSocket::lookup(m_conf.getRptAddress()); + unsigned int rptPort = m_conf.getRptPort(); + std::string myAddress = m_conf.getMyAddress(); + unsigned int myPort = m_conf.getMyPort(); + + CYSFNetwork rptNetwork(myAddress, myPort, m_callsign, debug); + rptNetwork.setDestination("MMDVM", rptAddress, rptPort); + + ret = rptNetwork.open(); + if (!ret) { + ::LogError("Cannot open the repeater network port"); + ::LogFinalise(); + return 1; + } + + std::string fileName = m_conf.getYSFNetHosts(); + + CYSFReflectors* reflectors = new CYSFReflectors(fileName); + reflectors->load(); + + unsigned int currentDGId = 0U; + + CDGIdNetwork* dgIdNetwork[100U]; + for (unsigned int i = 0U; i < 100U; i++) + dgIdNetwork[i] = NULL; + + std::vector dgIdData = m_conf.getDGIdData(); + for (std::vector::const_iterator it = dgIdData.begin(); it != dgIdData.end(); ++it) { + unsigned int dgid = (*it)->m_dgId; + std::string type = (*it)->m_type; + bool statc = (*it)->m_static; + unsigned int rfHangTime = (*it)->m_rfHangTime; + unsigned int netHangTime = (*it)->m_netHangTime; + bool debug = (*it)->m_debug; + + if (type == "FCS") { + std::string name = (*it)->m_name; + unsigned int local = (*it)->m_local; + unsigned int txFrequency = m_conf.getTxFrequency(); + unsigned int rxFrequency = m_conf.getRxFrequency(); + std::string locator = calculateLocator(); + unsigned int id = m_conf.getId(); + + dgIdNetwork[dgid] = new CFCSNetwork(name, local, m_callsign, rxFrequency, txFrequency, locator, id, debug); + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } else if (type == "YSF") { + std::string name = (*it)->m_name; + unsigned int local = (*it)->m_local; + + CYSFReflector* reflector = reflectors->findByName(name); + if (reflector != NULL) { + CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug); + ysf->setDestination(reflector->m_name, reflector->m_address, reflector->m_port); + + dgIdNetwork[dgid] = ysf; + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } +/* + } else if (type == "IMRS") { + dgIdNetwork[dgid] = new CIMRSNetwork; + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; +*/ + } else if (type == "Parrot") { + in_addr address = CUDPSocket::lookup((*it)->m_address); + unsigned int port = (*it)->m_port; + unsigned int local = (*it)->m_local; + + if (address.s_addr != INADDR_NONE) { + CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug); + ysf->setDestination("PARROT", address, port); + + dgIdNetwork[dgid] = ysf; + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } + } else if (type == "YSF2DMR") { + in_addr address = CUDPSocket::lookup((*it)->m_address); + unsigned int port = (*it)->m_port; + unsigned int local = (*it)->m_local; + + if (address.s_addr != INADDR_NONE) { + CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug); + ysf->setDestination("YSF2DMR", address, port); + + dgIdNetwork[dgid] = ysf; + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } + } else if (type == "YSF2NXDN") { + in_addr address = CUDPSocket::lookup((*it)->m_address); + unsigned int port = (*it)->m_port; + unsigned int local = (*it)->m_local; + + if (address.s_addr != INADDR_NONE) { + CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug); + ysf->setDestination("YSF2NXDN", address, port); + + dgIdNetwork[dgid] = ysf; + dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } + } else if (type == "YSF2P25") { + in_addr address = CUDPSocket::lookup((*it)->m_address); + unsigned int port = (*it)->m_port; + unsigned int local = (*it)->m_local; + + if (address.s_addr != INADDR_NONE) { + CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug); + ysf->setDestination("YSF2P25", address, port); + + dgIdNetwork[dgid] = ysf; + dgIdNetwork[dgid]->m_modes = YSF_DT_VOICE_FR_MODE; + dgIdNetwork[dgid]->m_static = statc; + dgIdNetwork[dgid]->m_rfHangTime = rfHangTime; + dgIdNetwork[dgid]->m_netHangTime = netHangTime; + } + } + + if (dgIdNetwork[dgid] != NULL) { + LogDebug("Loaded DG-ID %u", dgid); + bool ret = dgIdNetwork[dgid]->open(); + if (!ret) { + delete dgIdNetwork[dgid]; + dgIdNetwork[dgid] = NULL; + } + if (dgIdNetwork[dgid] != NULL && dgIdNetwork[dgid]->m_static) { + dgIdNetwork[dgid]->link(); + dgIdNetwork[dgid]->link(); + dgIdNetwork[dgid]->link(); + } + } + } + + createGPS(); + + CTimer inactivityTimer(1000U); + + CStopWatch stopWatch; + stopWatch.start(); + + LogMessage("Starting DGIdGateway-%s", VERSION); + + for (;;) { + unsigned char buffer[200U]; + memset(buffer, 0U, 200U); + + if (rptNetwork.read(0U, buffer) > 0U) { + if (::memcmp(buffer + 0U, "YSFD", 4U) == 0) { + CYSFFICH fich; + bool valid = fich.decode(buffer + 35U); + if (valid) { + unsigned char fi = fich.getFI(); + unsigned char dt = fich.getDT(); + unsigned char fn = fich.getFN(); + unsigned char ft = fich.getFT(); + unsigned char dgId = fich.getDGId(); + + if (dgId != 0U && dgId != currentDGId) { + if (dgIdNetwork[currentDGId] != NULL && !dgIdNetwork[currentDGId]->m_static) { + dgIdNetwork[currentDGId]->unlink(); + dgIdNetwork[currentDGId]->unlink(); + dgIdNetwork[currentDGId]->unlink(); + } + + if (dgIdNetwork[dgId] != NULL && !dgIdNetwork[dgId]->m_static) { + dgIdNetwork[dgId]->link(); + dgIdNetwork[dgId]->link(); + dgIdNetwork[dgId]->link(); + } + + LogDebug("DG-ID set to %u via RF", dgId); + currentDGId = dgId; + } + + if (m_gps != NULL) + m_gps->data(buffer + 14U, buffer + 35U, fi, dt, fn, ft); + + if (currentDGId != 0U && dgIdNetwork[currentDGId] != NULL) { + // Only allow the wanted modes through + if ((dgIdNetwork[currentDGId]->m_modes & dt) != 0U) { + dgIdNetwork[currentDGId]->write(currentDGId, buffer); + inactivityTimer.setTimeout(dgIdNetwork[currentDGId]->m_rfHangTime); + inactivityTimer.start(); + } + } + } + + if ((buffer[34U] & 0x01U) == 0x01U) { + if (m_gps != NULL) + m_gps->reset(); + } + } + } + + for (unsigned int i = 1U; i < 100U; i++) { + if (dgIdNetwork[i] != NULL) { + unsigned int len = dgIdNetwork[i]->read(i, buffer); + if (len > 0U && (i == currentDGId || currentDGId == 0U)) { + if (::memcmp(buffer + 0U, "YSFD", 4U) == 0) { + CYSFFICH fich; + bool valid = fich.decode(buffer + 35U); + if (valid) { + fich.setDGId(i); + fich.encode(buffer + 35U); + + rptNetwork.write(0U, buffer); + inactivityTimer.setTimeout(dgIdNetwork[i]->m_netHangTime); + inactivityTimer.start(); + + if (currentDGId == 0U) { + LogDebug("DG-ID set to %u via Network", i); + currentDGId = i; + } + } + } + } + } + } + + unsigned int ms = stopWatch.elapsed(); + stopWatch.start(); + + rptNetwork.clock(ms); + for (unsigned int i = 0U; i < 100U; i++) { + if (dgIdNetwork[i] != NULL) + dgIdNetwork[i]->clock(ms); + } + if (m_writer != NULL) + m_writer->clock(ms); + + inactivityTimer.clock(ms); + if (inactivityTimer.isRunning() && inactivityTimer.hasExpired()) { + if (dgIdNetwork[currentDGId] != NULL && !dgIdNetwork[currentDGId]->m_static) { + dgIdNetwork[currentDGId]->unlink(); + dgIdNetwork[currentDGId]->unlink(); + dgIdNetwork[currentDGId]->unlink(); + } + } + LogDebug("DG-ID set to 0 via timeout"); + + currentDGId = 0U; + inactivityTimer.stop(); + } + + if (ms < 5U) + CThread::sleep(5U); + } + + rptNetwork.close(); + + if (m_gps != NULL) { + m_writer->close(); + delete m_writer; + delete m_gps; + } + + for (unsigned int i = 1U; i < 100U; i++) { + if (dgIdNetwork[i] != NULL) { + dgIdNetwork[i]->unlink(); + dgIdNetwork[i]->unlink(); + dgIdNetwork[i]->unlink(); + dgIdNetwork[i]->close(); + delete dgIdNetwork[i]; + } + } + + ::LogFinalise(); + + return 0; +} + +void CDGIdGateway::createGPS() +{ + if (!m_conf.getAPRSEnabled()) + return; + + std::string address = m_conf.getAPRSAddress(); + unsigned int port = m_conf.getAPRSPort(); + std::string suffix = m_conf.getAPRSSuffix(); + bool debug = m_conf.getDebug(); + + m_writer = new CAPRSWriter(m_callsign, m_suffix, address, port, suffix, debug); + + unsigned int txFrequency = m_conf.getTxFrequency(); + unsigned int rxFrequency = m_conf.getRxFrequency(); + std::string desc = m_conf.getAPRSDescription(); + + m_writer->setInfo(txFrequency, rxFrequency, desc); + + bool enabled = m_conf.getGPSDEnabled(); + if (enabled) { + std::string address = m_conf.getGPSDAddress(); + std::string port = m_conf.getGPSDPort(); + + m_writer->setGPSDLocation(address, port); + } else { + float latitude = m_conf.getLatitude(); + float longitude = m_conf.getLongitude(); + int height = m_conf.getHeight(); + + m_writer->setStaticLocation(latitude, longitude, height); + } + + bool ret = m_writer->open(); + if (!ret) { + delete m_writer; + m_writer = NULL; + return; + } + + m_gps = new CGPS(m_writer); +} + +std::string CDGIdGateway::calculateLocator() +{ + std::string locator; + + float latitude = m_conf.getLatitude(); + float longitude = m_conf.getLongitude(); + + if (latitude < -90.0F || latitude > 90.0F) + return "AA00AA"; + + if (longitude < -360.0F || longitude > 360.0F) + return "AA00AA"; + + latitude += 90.0F; + + if (longitude > 180.0F) + longitude -= 360.0F; + + if (longitude < -180.0F) + longitude += 360.0F; + + longitude += 180.0F; + + float lon = ::floor(longitude / 20.0F); + float lat = ::floor(latitude / 10.0F); + + locator += 'A' + (unsigned int)lon; + locator += 'A' + (unsigned int)lat; + + longitude -= lon * 20.0F; + latitude -= lat * 10.0F; + + lon = ::floor(longitude / 2.0F); + lat = ::floor(latitude / 1.0F); + + locator += '0' + (unsigned int)lon; + locator += '0' + (unsigned int)lat; + + longitude -= lon * 2.0F; + latitude -= lat * 1.0F; + + lon = ::floor(longitude / (2.0F / 24.0F)); + lat = ::floor(latitude / (1.0F / 24.0F)); + + locator += 'A' + (unsigned int)lon; + locator += 'A' + (unsigned int)lat; + + return locator; +} + diff --git a/DGIdGateway/DGIdGateway.filters b/DGIdGateway/DGIdGateway.filters new file mode 100644 index 0000000..92a65c0 --- /dev/null +++ b/DGIdGateway/DGIdGateway.filters @@ -0,0 +1,152 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/DGIdGateway/DGIdGateway.h b/DGIdGateway/DGIdGateway.h new file mode 100644 index 0000000..8edc124 --- /dev/null +++ b/DGIdGateway/DGIdGateway.h @@ -0,0 +1,47 @@ +/* +* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(DGIdGateway_H) +#define DGIdGateway_H + +#include "APRSWriter.h" +#include "Conf.h" +#include "GPS.h" + +#include + +class CDGIdGateway +{ +public: + CDGIdGateway(const std::string& configFile); + ~CDGIdGateway(); + + int run(); + +private: + std::string m_callsign; + std::string m_suffix; + CConf m_conf; + CAPRSWriter* m_writer; + CGPS* m_gps; + + std::string calculateLocator(); + void createGPS(); +}; + +#endif diff --git a/DGIdGateway/DGIdGateway.ini b/DGIdGateway/DGIdGateway.ini new file mode 100644 index 0000000..40e0cb4 --- /dev/null +++ b/DGIdGateway/DGIdGateway.ini @@ -0,0 +1,138 @@ +[General] +Callsign=G9BF +Suffix=RPT +# Suffix=ND +Id=1234567 +RptAddress=127.0.0.1 +RptPort=3200 +LocalAddress=127.0.0.1 +LocalPort=4200 +RFHangTime=120 +NetHangTime=120 +Debug=0 +Daemon=0 + +[Info] +RXFrequency=430475000 +TXFrequency=439475000 +Power=1 +Latitude=0.0 +Longitude=0.0 +Height=0 +Name=Nowhere +Description=Multi-Mode Repeater + +[Log] +# Logging levels, 0=No logging +DisplayLevel=1 +FileLevel=1 +FilePath=. +FileRoot=DGIdGateway + +[APRS] +Enable=0 +Address=127.0.0.1 +Port=8673 +Description=APRS Description +Suffix=Y + +[YSF Network] +Hosts=./YSFHosts.txt +RFHangTime=120 +NetHangTime=60 +Debug=0 + +[FCS Network] +RFHangTime=120 +NetHangTime=60 +Debug=0 + +[DGId=1] +# YSF Local Parrot +Type=Parrot +Static=1 +Address=127.0.0.1 +Port=42012 +Local=42013 +RFHangTime=30 +NetHangTime=30 +Debug=0 + +[DGId=10] +# Local YSF2DMR TG23590 +Type=YSF2DMR +Static=1 +Address=127.0.0.1 +Port=42014 +Local=42015 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=11] +# Local YSF2DMR TG23510 +Type=YSF2DMR +Static=1 +Address=127.0.0.1 +Port=42016 +Local=42017 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=20] +# Local YSF2NXDN TG65000 +Type=YSF2NXDN +Static=1 +Address=127.0.0.1 +Port=42018 +Local=42019 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=30] +# Local YSF2P25 TG10200 +Type=YSF2P25 +Static=1 +Address=127.0.0.1 +Port=42020 +Local=42021 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=40] +# YSF Reflector CQ-UK +Type=YSF +Static=0 +Name=0-0-CQ-UK-ROOM +Local=42023 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=50] +# FCS Reflector FCS001-01 +Type=FCS +Static=0 +Name=FCS00101 +Local=42025 +#RFHangTime=120 +#NetHangTime=60 +Debug=0 + +[DGId=100] +# Local IMRS System Fusion Network +Type=IMRS +Destination=100,44.131.4.1 +Destination=75,44.131.4.2 +#RFHangTime=120 +#NetHangTime=60 +Debug=1 + +[GPSD] +Enable=0 +Address=127.0.0.1 +Port=2947 + diff --git a/DGIdGateway/DGIdGateway.vcxproj b/DGIdGateway/DGIdGateway.vcxproj new file mode 100644 index 0000000..f7567da --- /dev/null +++ b/DGIdGateway/DGIdGateway.vcxproj @@ -0,0 +1,200 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {4F82857B-D2CC-48DC-91A8-6275BDD3081B} + Win32Proj + YSFGateway + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DGIdGateway/DGIdNetwork.cpp b/DGIdGateway/DGIdNetwork.cpp new file mode 100644 index 0000000..83a786f --- /dev/null +++ b/DGIdGateway/DGIdNetwork.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "DGIdNetwork.h" + + +CDGIdNetwork::~CDGIdNetwork() +{ +} + diff --git a/DGIdGateway/DGIdNetwork.h b/DGIdGateway/DGIdNetwork.h new file mode 100644 index 0000000..f553d31 --- /dev/null +++ b/DGIdGateway/DGIdNetwork.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef DGIdNetwork_H +#define DGIdNetwork_H + + +class CDGIdNetwork { +public: + virtual ~CDGIdNetwork() = 0; + + virtual bool open() = 0; + + virtual void link() = 0; + + virtual void write(unsigned int dgId, const unsigned char* data) = 0; + + virtual unsigned int read(unsigned int dgid, unsigned char* data) = 0; + + virtual void clock(unsigned int ms) = 0; + + virtual void unlink() = 0; + + virtual void close() = 0; + + // Allowed modes + unsigned char m_modes; + + bool m_static; + + unsigned int m_rfHangTime; + unsigned int m_netHangTime; + +private: +}; + +#endif diff --git a/DGIdGateway/FCSNetwork.cpp b/DGIdGateway/FCSNetwork.cpp new file mode 100644 index 0000000..559ec29 --- /dev/null +++ b/DGIdGateway/FCSNetwork.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2009-2014,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "YSFDefines.h" +#include "FCSNetwork.h" +#include "Utils.h" +#include "Log.h" + +#include +#include +#include + +const char* FCS_VERSION = "MMDVM"; + +const unsigned int BUFFER_LENGTH = 200U; + +CFCSNetwork::CFCSNetwork(const std::string& reflector, unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug) : +m_socket(port), +m_debug(debug), +m_address(), +m_ping(NULL), +m_info(NULL), +m_reflector(reflector), +m_print(), +m_buffer(1000U, "FCS Network Buffer"), +m_n(0U), +m_pingTimer(1000U, 0U, 800U), +m_resetTimer(1000U, 1U), +m_state(FCS_UNLINKED) +{ + m_info = new unsigned char[100U]; + ::sprintf((char*)m_info, "%9u%9u%-6.6s%-12.12s%7u", rxFrequency, txFrequency, locator.c_str(), FCS_VERSION, id); + ::memset(m_info + 43U, ' ', 57U); + + m_ping = new unsigned char[25U]; + ::memcpy(m_ping + 0U, "PING", 4U); + ::memset(m_ping + 4U, ' ', 6U); + ::memcpy(m_ping + 4U, callsign.c_str(), callsign.size()); + ::memset(m_ping + 10U, 0x00U, 15U); + ::memcpy(m_ping + 10U, reflector.c_str(), 8U); +} + +CFCSNetwork::~CFCSNetwork() +{ + delete[] m_info; + delete[] m_ping; +} + +bool CFCSNetwork::open() +{ + LogMessage("Resolving FCS00x addresses"); + + m_addresses["FCS001"] = CUDPSocket::lookup("fcs001.xreflector.net"); + m_addresses["FCS002"] = CUDPSocket::lookup("fcs002.xreflector.net"); + m_addresses["FCS003"] = CUDPSocket::lookup("fcs003.xreflector.net"); + m_addresses["FCS004"] = CUDPSocket::lookup("fcs004.xreflector.net"); + m_addresses["FCS005"] = CUDPSocket::lookup("fcs005.xreflector.net"); + m_addresses["FCS222"] = CUDPSocket::lookup("fcs222.xreflector.net"); + m_addresses["FCS224"] = CUDPSocket::lookup("fcs224.xreflector.net"); + m_addresses["FCS232"] = CUDPSocket::lookup("fcs232.xreflector.net"); + + LogMessage("Opening FCS network connection"); + + return m_socket.open(); +} + +void CFCSNetwork::write(const unsigned char* data) +{ + assert(data != NULL); + + if (m_state != FCS_LINKED) + return; + + unsigned char buffer[130U]; + ::memset(buffer + 0U, ' ', 130U); + ::memcpy(buffer + 0U, data + 35U, 120U); + ::memcpy(buffer + 121U, m_reflector.c_str(), 8U); + + if (m_debug) + CUtils::dump(1U, "FCS Network Data Sent", buffer, 130U); + + m_socket.write(buffer, 130U, m_address, FCS_PORT); +} + +void CFCSNetwork::link() +{ + if (m_state != FCS_LINKED) { + std::string name = m_reflector.substr(0U, 6U); + if (m_addresses.count(name) == 0U) { + LogError("Unknown FCS reflector - %s", name.c_str()); + return; + } + + m_address = m_addresses[name]; + if (m_address.s_addr == INADDR_NONE) { + LogError("FCS reflector %s has no address", name.c_str()); + return; + } + } + + m_print = m_reflector.substr(0U, 6U) + "-" + m_reflector.substr(6U); + + m_state = FCS_LINKING; + + m_pingTimer.start(); + + writePing(); + + return true; +} + +void CFCSNetwork::unlink() +{ + if (m_state != FCS_LINKED) + return; + + m_socket.write((unsigned char*)"CLOSE ", 11U, m_address, FCS_PORT); +} + +void CFCSNetwork::clock(unsigned int ms) +{ + m_pingTimer.clock(ms); + if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) { + writePing(); + m_pingTimer.start(); + } + + m_resetTimer.clock(ms); + if (m_resetTimer.isRunning() && m_resetTimer.hasExpired()) { + m_n = 0U; + m_resetTimer.stop(); + } + + unsigned char buffer[BUFFER_LENGTH]; + + in_addr address; + unsigned int port; + int length = m_socket.read(buffer, BUFFER_LENGTH, address, port); + if (length <= 0) + return; + + if (m_state == FCS_UNLINKED) + return; + + if (address.s_addr != m_address.s_addr || port != FCS_PORT) + return; + + if (m_debug) + CUtils::dump(1U, "FCS Network Data Received", buffer, length); + + if (length == 7) { + if (m_state == FCS_LINKING) + LogMessage("Linked to %s", m_print.c_str()); + m_state = FCS_LINKED; + writeInfo(); + } + + if (length == 10 && m_state == FCS_LINKING) { + LogMessage("Linked to %s", m_print.c_str()); + m_state = FCS_LINKED; + writeInfo(); + } + + if (length == 7 || length == 10 || length == 130) { + unsigned char len = length; + m_buffer.addData(&len, 1U); + m_buffer.addData(buffer, len); + } +} + +unsigned int CFCSNetwork::read(unsigned char* data) +{ + assert(data != NULL); + + if (m_buffer.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_buffer.getData(&len, 1U); + + // Pass pings up to the gateway to reset the lost timer. + if (len != 130U) { + m_buffer.getData(data, len); + + ::memset(data + 0U, ' ', 14U); + ::memcpy(data + 0U, "YSFP", 4U); + ::memcpy(data + 4U, m_print.c_str(), 8U); + + return 14U; + } + + m_resetTimer.start(); + + unsigned char buffer[130U]; + m_buffer.getData(buffer, len); + + ::memset(data + 0U, ' ', 35U); + ::memcpy(data + 0U, "YSFD", 4U); + ::memcpy(data + 35U, buffer, 120U); + + // Put the reflector name as the via callsign. + ::memcpy(data + 4U, m_print.c_str(), 9U); + + data[34U] = m_n; + m_n += 2U; + + return 155U; +} + +void CFCSNetwork::close() +{ + m_socket.close(); + + LogMessage("Closing FCS network connection"); +} + +void CFCSNetwork::writeInfo() +{ + if (m_state != FCS_LINKED) + return; + + if (m_debug) + CUtils::dump(1U, "FCS Network Data Sent", m_info, 100U); + + m_socket.write(m_info, 100U, m_address, FCS_PORT); +} + +void CFCSNetwork::writePing() +{ + if (m_state == FCS_UNLINKED) + return; + + if (m_debug) + CUtils::dump(1U, "FCS Network Data Sent", m_ping, 25U); + + m_socket.write(m_ping, 25U, m_address, FCS_PORT); +} diff --git a/DGIdGateway/FCSNetwork.h b/DGIdGateway/FCSNetwork.h new file mode 100644 index 0000000..9cb61d1 --- /dev/null +++ b/DGIdGateway/FCSNetwork.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2014,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef FCSNetwork_H +#define FCSNetwork_H + +#include "DGIdNetwork.h" +#include "YSFDefines.h" +#include "UDPSocket.h" +#include "RingBuffer.h" +#include "Timer.h" + +#include +#include +#include + +enum FCS_STATE { + FCS_UNLINKED, + FCS_LINKING, + FCS_LINKED +}; + +class CFCSNetwork : public CDGIdNetwork { +public: + CFCSNetwork(const std::string& reflector, unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug); + virtual ~CFCSNetwork(); + + virtual bool open(); + + virtual void link(); + + virtual void write(unsigned int dgId, const unsigned char* data); + + virtual unsigned int read(unsigned int dgId, unsigned char* data); + + virtual void clock(unsigned int ms); + + virtual void unlink(); + + virtual void close(); + +private: + CUDPSocket m_socket; + bool m_debug; + in_addr m_address; + unsigned char* m_ping; + unsigned char* m_info; + std::string m_reflector; + std::string m_print; + CRingBuffer m_buffer; + std::map m_addresses; + unsigned char m_n; + CTimer m_pingTimer; + CTimer m_resetTimer; + FCS_STATE m_state; + + void writeInfo(); + void writePing(); +}; + +#endif diff --git a/DGIdGateway/FCSRooms.txt b/DGIdGateway/FCSRooms.txt new file mode 100644 index 0000000..aa95e0d --- /dev/null +++ b/DGIdGateway/FCSRooms.txt @@ -0,0 +1,678 @@ +# FCS_Hosts.txt downloaded from http://www.pistar.uk/downloads/FCS_Hosts.txt +# Sourced from PiStar.UK Update Server +# File created at Tuesday 8th of May 2018 01:20:49 AM BST +FCS00100;Repeater;FCS001 - Repeater;;; +FCS00101;Deutschland;FCS001 - Deutschland;;; +FCS00102;World Wide ;FCS001 - World Wide ;;; +FCS00103;Switzerland;FCS001 - Switzerland;;; +FCS00104;Denmark;FCS001 - Denmark;;; +FCS00105;Great Britain;FCS001 - Great Britain;;; +FCS00106;United States of America;FCS001 - United States of America;;; +FCS00107;Netherlands;FCS001 - Netherlands;;; +FCS00108;South korea;FCS001 - South korea;;; +FCS00109;Austria;FCS001 - Austria;;; +FCS00110;Sweden;FCS001 - Sweden;;; +FCS00111;Belgium;FCS001 - Belgium;;; +FCS00112;Portugal;FCS001 - Portugal;;; +FCS00113;Norway;FCS001 - Norway;;; +FCS00114;Australia;FCS001 - Australia;;; +FCS00115;Test System;FCS001 - Test System;;; +FCS00116;Brazil;FCS001 - Brazil;;; +FCS00117;Canada;FCS001 - Canada;;; +FCS00118;Spain;FCS001 - Spain;;; +FCS00119;Czech;FCS001 - Czech;;; +FCS00120;Slovakia;FCS001 - Slovakia;;; +FCS00121;Japan;FCS001 - Japan;;; +FCS00122;THAILAND;FCS001 - THAILAND;;; +FCS00123;Bulgaria;FCS001 - Bulgaria;;; +FCS00124; United States of America2;FCS001 - United States of America2;;; +FCS00125;Hungary;FCS001 - Hungary;;; +FCS00126;Polen;FCS001 - Polen;;; +FCS00127;Italy2;FCS001 - Italy2;;; +FCS00128;Australia;FCS001 - Australia;;; +FCS00129;Canada;FCS001 - Canada;;; +FCS00130;Iwate001jp-net;FCS001 - Iwate001jp-net;;; +FCS00131;Hessen;FCS001 - Hessen;;; +FCS00132;Luxembourg;FCS001 - Luxembourg;;; +FCS00133;Franc;FCS001 - Franc;;; +FCS00134;Greece;FCS001 - Greece;;; +FCS00135;Mecklenburg-Vorpommern;FCS001 - Mecklenburg-Vorpommern;;; +FCS00136;Sendai;FCS001 - Sendai;;; +FCS00139;China;FCS001 - China;;; +FCS00140;Spain2;FCS001 - Spain2;;; +FCS00141;HB9DR;FCS001 - HB9DR;;; +FCS00142;Repeater Schweiz;FCS001 - Repeater Schweiz;;; +FCS00143;GL/GR Room Schweiz;FCS001 - GL/GR Room Schweiz;;; +FCS00144;Zuerich/Schweiz;FCS001 - Zuerich/Schweiz;;; +FCS00146;DL-NORDWEST;FCS001 - DL-NORDWEST;;; +FCS00147;Kurpfalz;FCS001 - Kurpfalz;;; +FCS00150;Canada;FCS001 - Canada;;; +FCS00156;Elbe-Weser;FCS001 - Elbe-Weser;;; +FCS00160;CATALUNYA;FCS001 - CATALUNYA;;; +FCS00166;Nord-Ostsee-Link;FCS001 - Nord-Ostsee-Link;;; +FCS00167;Baden-Pfalz;FCS001 - Baden-Pfalz;;; +FCS00169;Italy;FCS001 - Italy;;; +FCS00170;SoCal Link Society;FCS001 - SoCal Link Society;;; +FCS00171;ARGENTINA LINK;FCS001 - ARGENTINA LINK;;; +FCS00173;phillipines;FCS001 - phillipines;;; +FCS00180;Schleswig-Holstein;FCS001 - Schleswig-Holstein;;; +FCS00186;GAUCHOS DEL SUR;FCS001 - GAUCHOS DEL SUR;;; +FCS00187;Rhein-Main / Wetterau;FCS001 - Rhein-Main / Wetterau;;; +FCS00188;TIROLER OBERLAND;FCS001 - TIROLER OBERLAND;;; +FCS00189;OE9/Vorarlberg;FCS001 - OE9/Vorarlberg;;; +FCS00192;Dongle User OE;FCS001 - Dongle User OE;;; +FCS00198;C4FM OE8;FCS001 - C4FM OE8;;; +FCS00199;ECHO;FCS001 - ECHO;;; +FCS00200;TALK USA1;FCS002 - TALK USA1;;; +FCS00201;TALK USA2;FCS002 - TALK USA2;;; +FCS00202;Alabama;FCS002 - Alabama;;; +FCS00203;Alaska;FCS002 - Alaska;;; +FCS00204;Arizona;FCS002 - Arizona;;; +FCS00205;Arkansas;FCS002 - Arkansas;;; +FCS00206;California;FCS002 - California;;; +FCS00207;Colorado;FCS002 - Colorado;;; +FCS00208;Connecticut;FCS002 - Connecticut;;; +FCS00209;Delaware;FCS002 - Delaware;;; +FCS00210;Florida;FCS002 - Florida;;; +FCS00211;Georgia;FCS002 - Georgia;;; +FCS00212;Hawaii;FCS002 - Hawaii;;; +FCS00213;Idaho;FCS002 - Idaho;;; +FCS00214;Illinois;FCS002 - Illinois;;; +FCS00215;Indiana;FCS002 - Indiana;;; +FCS00216;Iowa;FCS002 - Iowa;;; +FCS00217;Kansas;FCS002 - Kansas;;; +FCS00218;Louisiana;FCS002 - Louisiana;;; +FCS00219;Maine;FCS002 - Maine;;; +FCS00220;Maryland;FCS002 - Maryland;;; +FCS00221;Massachusetts;FCS002 - Massachusetts;;; +FCS00222;Michigan;FCS002 - Michigan;;; +FCS00223;Minnesota;FCS002 - Minnesota;;; +FCS00224;Mississippi;FCS002 - Mississippi;;; +FCS00225;Missouri;FCS002 - Missouri;;; +FCS00226;Montana;FCS002 - Montana;;; +FCS00227;Nebraska;FCS002 - Nebraska;;; +FCS00228;Nevada;FCS002 - Nevada;;; +FCS00229;New Hampshire;FCS002 - New Hampshire;;; +FCS00230;New Jersey;FCS002 - New Jersey;;; +FCS00231;New Mexico;FCS002 - New Mexico;;; +FCS00232;New York;FCS002 - New York;;; +FCS00233;North Carolina;FCS002 - North Carolina;;; +FCS00234;North Dakota;FCS002 - North Dakota;;; +FCS00235;Ohio;FCS002 - Ohio;;; +FCS00236;Oklahoma;FCS002 - Oklahoma;;; +FCS00237;Oregon;FCS002 - Oregon;;; +FCS00238;Pennsylvania;FCS002 - Pennsylvania;;; +FCS00239;Rhode Island;FCS002 - Rhode Island;;; +FCS00240;South Carolina;FCS002 - South Carolina;;; +FCS00241;South Dakota;FCS002 - South Dakota;;; +FCS00242;Tennessee;FCS002 - Tennessee;;; +FCS00243;Texas;FCS002 - Texas;;; +FCS00244;Utah;FCS002 - Utah;;; +FCS00245;Vermont;FCS002 - Vermont;;; +FCS00246;Virginia;FCS002 - Virginia;;; +FCS00247;Washington;FCS002 - Washington;;; +FCS00248;West Virginia;FCS002 - West Virginia;;; +FCS00249;Wisconsin;FCS002 - Wisconsin;;; +FCS00250;Wyoming;FCS002 - Wyoming;;; +FCS00251;AREC;FCS002 - AREC;;; +FCS00253;Puerto Rico;FCS002 - Puerto Rico;;; +FCS00255;Central Alabama;FCS002 - Central Alabama;;; +FCS00256;Northeast Florida;FCS002 - Northeast Florida;;; +FCS00259;Public Safety ARG;FCS002 - Public Safety ARG;;; +FCS00260;AB2BH-AZ;FCS002 - AB2BH-AZ;;; +FCS00261;Belfast;FCS002 - Belfast;;; +FCS00269;Illinois Link;FCS002 - Illinois Link;;; +FCS00270;SoCal Link Society;FCS002 - SoCal Link Society;;; +FCS00271;SoCal Link Society;FCS002 - SoCal Link Society;;; +FCS00275;Wires-X Spain;FCS002 - Wires-X Spain;;; +FCS00280;Canada english;FCS002 - Canada english;;; +FCS00281;Canada francais;FCS002 - Canada francais;;; +FCS00284;NJ-NY RGNL;FCS002 - NJ-NY RGNL;;; +FCS00285;America-Ragchew (Wires-X);FCS002 - America-Ragchew (Wires-X);;; +FCS00288;KK4GAF;FCS002 - KK4GAF;;; +FCS00290;America Link WIRES-X;FCS002 - America Link WIRES-X;;; +FCS00291;CQ-UK WIRES-X;FCS002 - CQ-UK WIRES-X;;; +FCS00298;Software Test;FCS002 - Software Test;;; +FCS00299;ECHO;FCS002 - ECHO;;; +FCS00300;Group SYSOP chat ROOM;FCS003 - Group SYSOP chat ROOM;;; +FCS00301;FUSION-CANADA-FR;FCS003 - FUSION-CANADA-FR;;; +FCS00302;FUSION-QUEBEC-EN;FCS003 - FUSION-QUEBEC-EN;;; +FCS00303;Newfoundland and Labrador;FCS003 - Newfoundland and Labrador;;; +FCS00304;PEI;FCS003 - PEI;;; +FCS00305;New Brunswick;FCS003 - New Brunswick;;; +FCS00306;Ontario;FCS003 - Ontario;;; +FCS00307;Manitoba;FCS003 - Manitoba;;; +FCS00308;Saskatchewan;FCS003 - Saskatchewan;;; +FCS00309;Alberta;FCS003 - Alberta;;; +FCS00310;British Columbia;FCS003 - British Columbia;;; +FCS00311;Yukon / NWT / Nunavut;FCS003 - Yukon / NWT / Nunavut;;; +FCS00312;New England USA-East;FCS003 - New England USA-East;;; +FCS00314;NILECOMM;FCS003 - NILECOMM;;; +FCS00315;PA-Fl Link Society;FCS003 - PA-Fl Link Society;;; +FCS00316;San Diego;FCS003 - San Diego;;; +FCS00317;VA7GH Test Room;FCS003 - VA7GH Test Room;;; +FCS00318;ALOHA-HAWAII Wires-X;FCS003 - ALOHA-HAWAII Wires-X;;; +FCS00320;Irish Group;FCS003 - Irish Group;;; +FCS00321;CARS Nevada;FCS003 - CARS Nevada;;; +FCS00325;D.A.R.N.;FCS003 - D.A.R.N.;;; +FCS00328;SouthEast Mississippi;FCS003 - SouthEast Mississippi;;; +FCS00330;TeXaS-I35;FCS003 - TeXaS-I35;;; +FCS00333;Carolina Link;FCS003 - Carolina Link;;; +FCS00334;TEXAS - NEXUS;FCS003 - TEXAS - NEXUS;;; +FCS00335;Ohio NET;FCS003 - Ohio NET;;; +FCS00346;SAT-DRC;FCS003 - SAT-DRC;;; +FCS00350;LEO-ARC;FCS003 - LEO-ARC;;; +FCS00355;WINSCONSIN LINK;FCS003 - WINSCONSIN LINK;;; +FCS00358;Alabama Link;FCS003 - Alabama Link;;; +FCS00369;Midwest Hub;FCS003 - Midwest Hub;;; +FCS00370;SoCal Link Network;FCS003 - SoCal Link Network;;; +FCS00371;SoCal Link Society Café;FCS003 - SoCal Link Society Café;;; +FCS00372;ND6C-OpenSPOT Network;FCS003 - ND6C-OpenSPOT Network;;; +FCS00373;PINOYHAMS;FCS003 - PINOYHAMS;;; +FCS00376;Montivilliers C4FM / F4ETA;FCS003 - Montivilliers C4FM / F4ETA;;; +FCS00377;WXCTAC;FCS003 - WXCTAC;;; +FCS00385;Haïti System Fusion - HH2MJF;FCS003 - Haïti System Fusion - HH2MJF;;; +FCS00390;America Link Wires-X;FCS003 - America Link Wires-X;;; +FCS00397;DV4Home Test ROOM;FCS003 - DV4Home Test ROOM;;; +FCS00398;DV4mini Test ROOM;FCS003 - DV4mini Test ROOM;;; +FCS00399;ECHO;FCS003 - ECHO;;; +FCS00400;La-Espanola;FCS004 - La-Espanola;;; +FCS00401;EA-DISTRITO-1;FCS004 - EA-DISTRITO-1;;; +FCS00402;EA-DISTRITO-2;FCS004 - EA-DISTRITO-2;;; +FCS00403;EA-DISTRITO-3;FCS004 - EA-DISTRITO-3;;; +FCS00404;EA-DISTRITO-4;FCS004 - EA-DISTRITO-4;;; +FCS00405;EA-DISTRITO-5;FCS004 - EA-DISTRITO-5;;; +FCS00406;EA-DISTRITO-6;FCS004 - EA-DISTRITO-6;;; +FCS00407;EA-DISTRITO-7;FCS004 - EA-DISTRITO-7;;; +FCS00408;EA-DISTRITO-8;FCS004 - EA-DISTRITO-8;;; +FCS00409;EA-DISTRITO-9;FCS004 - EA-DISTRITO-9;;; +FCS00410;Republica Dominicana;FCS004 - Republica Dominicana;;; +FCS00411;DMR-TG314233-WiresX;FCS004 - DMR-TG314233-WiresX;;; +FCS00412;DVMEGA-WiresX-UK;FCS004 - DVMEGA-WiresX-UK;;; +FCS00413;HP-Panama-HUB;FCS004 - HP-Panama-HUB;;; +FCS00414;Guatemala;FCS004 - Guatemala;;; +FCS00415;Great-Britain;FCS004 - Great-Britain;;; +FCS00416;Miami-Latino;FCS004 - Miami-Latino;;; +FCS00417;Southern-Germany;FCS004 - Southern-Germany;;; +FCS00418;DCS018-Test;FCS004 - DCS018-Test;;; +FCS00419;Middle-Germany;FCS004 - Middle-Germany;;; +FCS00420;CQ-UK-WiresX-Room;FCS004 - CQ-UK-WiresX-Room;;; +FCS00421;Campania;FCS004 - Campania;;; +FCS00422;America-Ragchew-WiresX;FCS004 - America-Ragchew-WiresX;;; +FCS00423;Hertfordshire-RAYNET;FCS004 - Hertfordshire-RAYNET;;; +FCS00424;Fusion-Latina-WiresX-41067;FCS004 - Fusion-Latina-WiresX-41067;;; +FCS00425;Scotland;FCS004 - Scotland;;; +FCS00426;Oost-Nederland-Room;FCS004 - Oost-Nederland-Room;;; +FCS00427;Scout&Guide-JOTA;FCS004 - Scout&Guide-JOTA;;; +FCS00428;NWFG;FCS004 - NWFG;;; +FCS00429;D.A.R.C-USA;FCS004 - D.A.R.C-USA;;; +FCS00430;Irish-Scottish-Link;FCS004 - Irish-Scottish-Link;;; +FCS00431;UKHUB;FCS004 - UKHUB;;; +FCS00432;LincsLink;FCS004 - LincsLink;;; +FCS00433;Stockport-Room;FCS004 - Stockport-Room;;; +FCS00434;N8UKF-Repeater-Group;FCS004 - N8UKF-Repeater-Group;;; +FCS00435;WW-DX-Link-System;FCS004 - WW-DX-Link-System;;; +FCS00436;Essex-UK;FCS004 - Essex-UK;;; +FCS00437;Palmac;FCS004 - Palmac;;; +FCS00438;CQ-South-Wales;FCS004 - CQ-South-Wales;;; +FCS00439;Indiana-Link-SO;FCS004 - Indiana-Link-SO;;; +FCS00440;USA;FCS004 - USA;;; +FCS00441;Sevilla-TG21441;FCS004 - Sevilla-TG21441;;; +FCS00442;Eglisau-Amateur-Radio-Group;FCS004 - Eglisau-Amateur-Radio-Group;;; +FCS00443;Greenwich-Link-London;FCS004 - Greenwich-Link-London;;; +FCS00444;DMR-CHIRIQUi-TG7144;FCS004 - DMR-CHIRIQUi-TG7144;;; +FCS00445;NORTHSTAR;FCS004 - NORTHSTAR;;; +FCS00446;Kuwait-R;FCS004 - Kuwait-R;;; +FCS00447;Digital-Radio-Group-NZ;FCS004 - Digital-Radio-Group-NZ;;; +FCS00448;New-Zealand;FCS004 - New-Zealand;;; +FCS00449;MI5DAW;FCS004 - MI5DAW;;; +FCS00450;LEO-ARC;FCS004 - LEO-ARC;;; +FCS00451;RFIT;FCS004 - RFIT;;; +FCS00452;Seccion-Local-URE-Caceres;FCS004 - Seccion-Local-URE-Caceres;;; +FCS00453;Alaska-Last-Frontier;FCS004 - Alaska-Last-Frontier;;; +FCS00454;QSO-America;FCS004 - QSO-America;;; +FCS00455;Oldham-Radio-Club-Fusion-Group;FCS004 - Oldham-Radio-Club-Fusion-Group;;; +FCS00456;Nashville-HUB;FCS004 - Nashville-HUB;;; +FCS00457;Kapihan;FCS004 - Kapihan;;; +FCS00458;Catalina-Amateur-Repeater-Ass;FCS004 - Catalina-Amateur-Repeater-Ass;;; +FCS00459;Rhode-Island-Digital-Link;FCS004 - Rhode-Island-Digital-Link;;; +FCS00460;United-Kingdom-NET-WiresX;FCS004 - United-Kingdom-NET-WiresX;;; +FCS00461;21461BM-XLX051F-DSTAR-10302-NXDN-YSF-EA-SPAIN;FCS004 - 21461BM-XLX051F-DSTAR-10302-NXDN-YSF-EA-SPAIN;;; +FCS00462;Mabuhay-Canada-Link;FCS004 - Mabuhay-Canada-Link;;; +FCS00463;Uruguay-Link;FCS004 - Uruguay-Link;;; +FCS00464;WiresX 27464;FCS004 - WiresX 27464;;; +FCS00465;ADER;FCS004 - ADER;;; +FCS00466;nn;FCS004 - nn;;; +FCS00467;Minnesota-Nice;FCS004 - Minnesota-Nice;;; +FCS00468;GoldRunCa-Fusion-Group;FCS004 - GoldRunCa-Fusion-Group;;; +FCS00469;SE-Mississippi;FCS004 - SE-Mississippi;;; +FCS00470;DMR+-4370-Test;FCS004 - DMR+-4370-Test;;; +FCS00471;nn;FCS004 - nn;;; +FCS00472;nn;FCS004 - nn;;; +FCS00473;SOTA;FCS004 - SOTA;;; +FCS00474;DMR+-4374-Test;FCS004 - DMR+-4374-Test;;; +FCS00475;21369-KJ4VO-WORK-RM;FCS004 - 21369-KJ4VO-WORK-RM;;; +FCS00476;nn;FCS004 - nn;;; +FCS00477;HUBNet;FCS004 - HUBNet;;; +FCS00478;nn;FCS004 - nn;;; +FCS00479;CQ-California-Reflector;FCS004 - CQ-California-Reflector;;; +FCS00480;XLX925F;FCS004 - XLX925F;;; +FCS00481;nn;FCS004 - nn;;; +FCS00482;Netherlands;FCS004 - Netherlands;;; +FCS00483;CW-Ops;FCS004 - CW-Ops;;; +FCS00484;OMISS;FCS004 - OMISS;;; +FCS00485;XLX925E;FCS004 - XLX925E;;; +FCS00486;Argentina-Link;FCS004 - Argentina-Link;;; +FCS00487;URE-Salamanca;FCS004 - URE-Salamanca;;; +FCS00488;Philippine-Link;FCS004 - Philippine-Link;;; +FCS00489;Pinoy-Tambayan;FCS004 - Pinoy-Tambayan;;; +FCS00490;JOTA-SPAIN-2018;FCS004 - JOTA-SPAIN-2018;;; +FCS00491;SierraNorCal;FCS004 - SierraNorCal;;; +FCS00492;nn;FCS004 - nn;;; +FCS00493;nn;FCS004 - nn;;; +FCS00494;Almeria;FCS004 - Almeria;;; +FCS00495;Entrelaces-Latinos;FCS004 - Entrelaces-Latinos;;; +FCS00496;RC-Veleta;FCS004 - RC-Veleta;;; +FCS00497;APRS-Room;FCS004 - APRS-Room;;; +FCS00498;Hotspot-Test;FCS004 - Hotspot-Test;;; +FCS00499;ECHO;FCS004 - ECHO;;; +FCS00500;nn;FCS005 - nn;;; +FCS00501;nn;FCS005 - nn;;; +FCS00502;nn;FCS005 - nn;;; +FCS00503;nn;FCS005 - nn;;; +FCS00504;nn;FCS005 - nn;;; +FCS00505;nn;FCS005 - nn;;; +FCS00506;nn;FCS005 - nn;;; +FCS00507;nn;FCS005 - nn;;; +FCS00508;nn;FCS005 - nn;;; +FCS00509;nn;FCS005 - nn;;; +FCS00510;nn;FCS005 - nn;;; +FCS00511;nn;FCS005 - nn;;; +FCS00512;nn;FCS005 - nn;;; +FCS00513;nn;FCS005 - nn;;; +FCS00514;nn;FCS005 - nn;;; +FCS00515;DL-MultiNet-Bridge;FCS005 - DL-MultiNet-Bridge;;; +FCS00516;nn;FCS005 - nn;;; +FCS00517;nn;FCS005 - nn;;; +FCS00518;nn;FCS005 - nn;;; +FCS00519;nn;FCS005 - nn;;; +FCS00520;nn;FCS005 - nn;;; +FCS00521;nn;FCS005 - nn;;; +FCS00522;nn;FCS005 - nn;;; +FCS00523;nn;FCS005 - nn;;; +FCS00524;nn;FCS005 - nn;;; +FCS00525;nn;FCS005 - nn;;; +FCS00526;nn;FCS005 - nn;;; +FCS00527;nn;FCS005 - nn;;; +FCS00528;nn;FCS005 - nn;;; +FCS00529;nn;FCS005 - nn;;; +FCS00530;nn;FCS005 - nn;;; +FCS00531;nn;FCS005 - nn;;; +FCS00532;nn;FCS005 - nn;;; +FCS00533;nn;FCS005 - nn;;; +FCS00534;nn;FCS005 - nn;;; +FCS00535;nn;FCS005 - nn;;; +FCS00536;nn;FCS005 - nn;;; +FCS00537;nn;FCS005 - nn;;; +FCS00538;Niedersachsen;FCS005 - Niedersachsen;;; +FCS00539;nn;FCS005 - nn;;; +FCS00540;nn;FCS005 - nn;;; +FCS00541;nn;FCS005 - nn;;; +FCS00542;nn;FCS005 - nn;;; +FCS00543;nn;FCS005 - nn;;; +FCS00544;Pacific-Intertie-Net;FCS005 - Pacific-Intertie-Net;;; +FCS00545;nn;FCS005 - nn;;; +FCS00546;nn;FCS005 - nn;;; +FCS00547;nn;FCS005 - nn;;; +FCS00548;nn;FCS005 - nn;;; +FCS00549;nn;FCS005 - nn;;; +FCS00550;nn;FCS005 - nn;;; +FCS00551;nn;FCS005 - nn;;; +FCS00552;nn;FCS005 - nn;;; +FCS00553;nn;FCS005 - nn;;; +FCS00554;nn;FCS005 - nn;;; +FCS00555;nn;FCS005 - nn;;; +FCS00556;nn;FCS005 - nn;;; +FCS00557;nn;FCS005 - nn;;; +FCS00558;nn;FCS005 - nn;;; +FCS00559;nn;FCS005 - nn;;; +FCS00560;nn;FCS005 - nn;;; +FCS00561;nn;FCS005 - nn;;; +FCS00562;nn;FCS005 - nn;;; +FCS00563;nn;FCS005 - nn;;; +FCS00564;nn;FCS005 - nn;;; +FCS00565;nn;FCS005 - nn;;; +FCS00566;nn;FCS005 - nn;;; +FCS00567;nn;FCS005 - nn;;; +FCS00568;nn;FCS005 - nn;;; +FCS00569;nn;FCS005 - nn;;; +FCS00570;nn;FCS005 - nn;;; +FCS00571;nn;FCS005 - nn;;; +FCS00572;nn;FCS005 - nn;;; +FCS00573;nn;FCS005 - nn;;; +FCS00574;nn;FCS005 - nn;;; +FCS00575;nn;FCS005 - nn;;; +FCS00576;nn;FCS005 - nn;;; +FCS00577;nn;FCS005 - nn;;; +FCS00578;nn;FCS005 - nn;;; +FCS00579;nn;FCS005 - nn;;; +FCS00580;nn;FCS005 - nn;;; +FCS00581;nn;FCS005 - nn;;; +FCS00582;nn;FCS005 - nn;;; +FCS00583;nn;FCS005 - nn;;; +FCS00584;nn;FCS005 - nn;;; +FCS00585;nn;FCS005 - nn;;; +FCS00586;nn;FCS005 - nn;;; +FCS00587;nn;FCS005 - nn;;; +FCS00588;nn;FCS005 - nn;;; +FCS00589;nn;FCS005 - nn;;; +FCS00590;DMRplus-Chat;FCS005 - DMRplus-Chat;;; +FCS00591;nn;FCS005 - nn;;; +FCS00592;nn;FCS005 - nn;;; +FCS00593;nn;FCS005 - nn;;; +FCS00594;nn;FCS005 - nn;;; +FCS00595;nn;FCS005 - nn;;; +FCS00596;nn;FCS005 - nn;;; +FCS00597;nn;FCS005 - nn;;; +FCS00598;nn;FCS005 - nn;;; +FCS00599;ECHO;FCS005 - ECHO;;; +FCS22200;nn;FCS222 - nn;;; +FCS22201;nn;FCS222 - nn;;; +FCS22202;nn;FCS222 - nn;;; +FCS22203;nn;FCS222 - nn;;; +FCS22204;nn;FCS222 - nn;;; +FCS22205;nn;FCS222 - nn;;; +FCS22206;nn;FCS222 - nn;;; +FCS22207;nn;FCS222 - nn;;; +FCS22208;nn;FCS222 - nn;;; +FCS22209;nn;FCS222 - nn;;; +FCS22210;nn;FCS222 - nn;;; +FCS22211;nn;FCS222 - nn;;; +FCS22212;nn;FCS222 - nn;;; +FCS22213;nn;FCS222 - nn;;; +FCS22214;nn;FCS222 - nn;;; +FCS22215;nn;FCS222 - nn;;; +FCS22216;nn;FCS222 - nn;;; +FCS22217;Netherlands;FCS222 - Netherlands;;; +FCS22218;nn;FCS222 - nn;;; +FCS22219;nn;FCS222 - nn;;; +FCS22220;D-A-CH;FCS222 - D-A-CH;;; +FCS22221;nn;FCS222 - nn;;; +FCS22222;Italy;FCS222 - Italy;;; +FCS22223;nn;FCS222 - nn;;; +FCS22224;Spain;FCS222 - Spain;;; +FCS22225;nn;FCS222 - nn;;; +FCS22226;Poland;FCS222 - Poland;;; +FCS22227;nn;FCS222 - nn;;; +FCS22228;Switzerland;FCS222 - Switzerland;;; +FCS22229;nn;FCS222 - nn;;; +FCS22230;nn;FCS222 - nn;;; +FCS22231;nn;FCS222 - nn;;; +FCS22232;Austria;FCS222 - Austria;;; +FCS22233;nn;FCS222 - nn;;; +FCS22234;nn;FCS222 - nn;;; +FCS22235;nn;FCS222 - nn;;; +FCS22236;nn;FCS222 - nn;;; +FCS22237;nn;FCS222 - nn;;; +FCS22238;nn;FCS222 - nn;;; +FCS22239;nn;FCS222 - nn;;; +FCS22240;nn;FCS222 - nn;;; +FCS22241;nn;FCS222 - nn;;; +FCS22242;nn;FCS222 - nn;;; +FCS22243;nn;FCS222 - nn;;; +FCS22244;nn;FCS222 - nn;;; +FCS22245;nn;FCS222 - nn;;; +FCS22246;nn;FCS222 - nn;;; +FCS22247;nn;FCS222 - nn;;; +FCS22248;nn;FCS222 - nn;;; +FCS22249;nn;FCS222 - nn;;; +FCS22250;nn;FCS222 - nn;;; +FCS22251;nn;FCS222 - nn;;; +FCS22252;nn;FCS222 - nn;;; +FCS22253;nn;FCS222 - nn;;; +FCS22254;nn;FCS222 - nn;;; +FCS22255;nn;FCS222 - nn;;; +FCS22256;nn;FCS222 - nn;;; +FCS22257;nn;FCS222 - nn;;; +FCS22258;nn;FCS222 - nn;;; +FCS22259;nn;FCS222 - nn;;; +FCS22260;nn;FCS222 - nn;;; +FCS22261;nn;FCS222 - nn;;; +FCS22262;Germany;FCS222 - Germany;;; +FCS22263;nn;FCS222 - nn;;; +FCS22264;nn;FCS222 - nn;;; +FCS22265;nn;FCS222 - nn;;; +FCS22266;nn;FCS222 - nn;;; +FCS22267;nn;FCS222 - nn;;; +FCS22268;nn;FCS222 - nn;;; +FCS22269;nn;FCS222 - nn;;; +FCS22270;nn;FCS222 - nn;;; +FCS22271;nn;FCS222 - nn;;; +FCS22272;nn;FCS222 - nn;;; +FCS22273;nn;FCS222 - nn;;; +FCS22274;nn;FCS222 - nn;;; +FCS22275;nn;FCS222 - nn;;; +FCS22276;nn;FCS222 - nn;;; +FCS22277;nn;FCS222 - nn;;; +FCS22278;nn;FCS222 - nn;;; +FCS22279;nn;FCS222 - nn;;; +FCS22280;nn;FCS222 - nn;;; +FCS22281;nn;FCS222 - nn;;; +FCS22282;nn;FCS222 - nn;;; +FCS22283;nn;FCS222 - nn;;; +FCS22284;nn;FCS222 - nn;;; +FCS22285;nn;FCS222 - nn;;; +FCS22286;nn;FCS222 - nn;;; +FCS22287;nn;FCS222 - nn;;; +FCS22288;nn;FCS222 - nn;;; +FCS22289;nn;FCS222 - nn;;; +FCS22290;nn;FCS222 - nn;;; +FCS22291;nn;FCS222 - nn;;; +FCS22292;nn;FCS222 - nn;;; +FCS22293;nn;FCS222 - nn;;; +FCS22294;nn;FCS222 - nn;;; +FCS22295;nn;FCS222 - nn;;; +FCS22296;nn;FCS222 - nn;;; +FCS22297;nn;FCS222 - nn;;; +FCS22298;nn;FCS222 - nn;;; +FCS22299;ECHO;FCS222 - ECHO;;; +FCS22400;nn;FCS224 - nn;;; +FCS22401;nn;FCS224 - nn;;; +FCS22402;nn;FCS224 - nn;;; +FCS22403;nn;FCS224 - nn;;; +FCS22404;nn;FCS224 - nn;;; +FCS22405;nn;FCS224 - nn;;; +FCS22406;nn;FCS224 - nn;;; +FCS22407;nn;FCS224 - nn;;; +FCS22408;nn;FCS224 - nn;;; +FCS22409;nn;FCS224 - nn;;; +FCS22410;nn;FCS224 - nn;;; +FCS22411;nn;FCS224 - nn;;; +FCS22412;nn;FCS224 - nn;;; +FCS22413;nn;FCS224 - nn;;; +FCS22414;2X;FCS224 - 2X;;; +FCS22415;nn;FCS224 - nn;;; +FCS22416;nn;FCS224 - nn;;; +FCS22417;Netherlands;FCS224 - Netherlands;;; +FCS22418;nn;FCS224 - nn;;; +FCS22419;nn;FCS224 - nn;;; +FCS22420;D-A-CH;FCS224 - D-A-CH;;; +FCS22421;nn;FCS224 - nn;;; +FCS22422;Italy;FCS224 - Italy;;; +FCS22423;nn;FCS224 - nn;;; +FCS22424;Spain;FCS224 - Spain;;; +FCS22425;nn;FCS224 - nn;;; +FCS22426;Poland;FCS224 - Poland;;; +FCS22427;nn;FCS224 - nn;;; +FCS22428;Switzerland;FCS224 - Switzerland;;; +FCS22429;nn;FCS224 - nn;;; +FCS22430;nn;FCS224 - nn;;; +FCS22431;nn;FCS224 - nn;;; +FCS22432;Austria;FCS224 - Austria;;; +FCS22433;nn;FCS224 - nn;;; +FCS22434;nn;FCS224 - nn;;; +FCS22435;nn;FCS224 - nn;;; +FCS22436;nn;FCS224 - nn;;; +FCS22437;nn;FCS224 - nn;;; +FCS22438;nn;FCS224 - nn;;; +FCS22439;nn;FCS224 - nn;;; +FCS22440;nn;FCS224 - nn;;; +FCS22441;nn;FCS224 - nn;;; +FCS22442;nn;FCS224 - nn;;; +FCS22443;nn;FCS224 - nn;;; +FCS22444;nn;FCS224 - nn;;; +FCS22445;nn;FCS224 - nn;;; +FCS22446;nn;FCS224 - nn;;; +FCS22447;nn;FCS224 - nn;;; +FCS22448;nn;FCS224 - nn;;; +FCS22449;nn;FCS224 - nn;;; +FCS22450;nn;FCS224 - nn;;; +FCS22451;nn;FCS224 - nn;;; +FCS22452;nn;FCS224 - nn;;; +FCS22453;nn;FCS224 - nn;;; +FCS22454;nn;FCS224 - nn;;; +FCS22455;nn;FCS224 - nn;;; +FCS22456;nn;FCS224 - nn;;; +FCS22457;nn;FCS224 - nn;;; +FCS22458;nn;FCS224 - nn;;; +FCS22459;nn;FCS224 - nn;;; +FCS22460;nn;FCS224 - nn;;; +FCS22461;nn;FCS224 - nn;;; +FCS22462;Germany;FCS224 - Germany;;; +FCS22463;nn;FCS224 - nn;;; +FCS22464;nn;FCS224 - nn;;; +FCS22465;nn;FCS224 - nn;;; +FCS22466;nn;FCS224 - nn;;; +FCS22467;nn;FCS224 - nn;;; +FCS22468;nn;FCS224 - nn;;; +FCS22469;nn;FCS224 - nn;;; +FCS22470;nn;FCS224 - nn;;; +FCS22471;nn;FCS224 - nn;;; +FCS22472;nn;FCS224 - nn;;; +FCS22473;nn;FCS224 - nn;;; +FCS22474;nn;FCS224 - nn;;; +FCS22475;nn;FCS224 - nn;;; +FCS22476;nn;FCS224 - nn;;; +FCS22477;nn;FCS224 - nn;;; +FCS22478;2X;FCS224 - 2X;;; +FCS22479;nn;FCS224 - nn;;; +FCS22480;TST;FCS224 - TST;;; +FCS22481;nn;FCS224 - nn;;; +FCS22482;nn;FCS224 - nn;;; +FCS22483;nn;FCS224 - nn;;; +FCS22484;nn;FCS224 - nn;;; +FCS22485;nn;FCS224 - nn;;; +FCS22486;nn;FCS224 - nn;;; +FCS22487;nn;FCS224 - nn;;; +FCS22488;nn;FCS224 - nn;;; +FCS22489;nn;FCS224 - nn;;; +FCS22490;nn;FCS224 - nn;;; +FCS22491;nn;FCS224 - nn;;; +FCS22492;nn;FCS224 - nn;;; +FCS22493;nn;FCS224 - nn;;; +FCS22494;nn;FCS224 - nn;;; +FCS22495;nn;FCS224 - nn;;; +FCS22496;nn;FCS224 - nn;;; +FCS22497;nn;FCS224 - nn;;; +FCS22498;nn;FCS224 - nn;;; +FCS22499;ECHO;FCS224 - ECHO;;; +FCS23200;nn;FCS232 - nn;;; +FCS23201;2X;FCS232 - 2X;;; +FCS23202;nn;FCS232 - nn;;; +FCS23203;nn;FCS232 - nn;;; +FCS23204;2X;FCS232 - 2X;;; +FCS23205;2X;FCS232 - 2X;;; +FCS23206;2X;FCS232 - 2X;;; +FCS23207;2X;FCS232 - 2X;;; +FCS23208;2X;FCS232 - 2X;;; +FCS23209;nn;FCS232 - nn;;; +FCS23210;2X;FCS232 - 2X;;; +FCS23211;2X;FCS232 - 2X;;; +FCS23212;2X;FCS232 - 2X;;; +FCS23213;2X;FCS232 - 2X;;; +FCS23214;nn;FCS232 - nn;;; +FCS23215;nn;FCS232 - nn;;; +FCS23216;nn;FCS232 - nn;;; +FCS23217;Netherlands;FCS232 - Netherlands;;; +FCS23218;nn;FCS232 - nn;;; +FCS23219;nn;FCS232 - nn;;; +FCS23220;D-A-CH;FCS232 - D-A-CH;;; +FCS23221;nn;FCS232 - nn;;; +FCS23222;Italy;FCS232 - Italy;;; +FCS23223;nn;FCS232 - nn;;; +FCS23224;nn;FCS232 - nn;;; +FCS23225;nn;FCS232 - nn;;; +FCS23226;Poland;FCS232 - Poland;;; +FCS23227;nn;FCS232 - nn;;; +FCS23228;Switzerland;FCS232 - Switzerland;;; +FCS23229;nn;FCS232 - nn;;; +FCS23230;nn;FCS232 - nn;;; +FCS23231;nn;FCS232 - nn;;; +FCS23232;Austria;FCS232 - Austria;;; +FCS23233;nn;FCS232 - nn;;; +FCS23234;nn;FCS232 - nn;;; +FCS23235;nn;FCS232 - nn;;; +FCS23236;nn;FCS232 - nn;;; +FCS23237;nn;FCS232 - nn;;; +FCS23238;nn;FCS232 - nn;;; +FCS23239;nn;FCS232 - nn;;; +FCS23240;nn;FCS232 - nn;;; +FCS23241;nn;FCS232 - nn;;; +FCS23242;nn;FCS232 - nn;;; +FCS23243;nn;FCS232 - nn;;; +FCS23244;nn;FCS232 - nn;;; +FCS23245;nn;FCS232 - nn;;; +FCS23246;nn;FCS232 - nn;;; +FCS23247;nn;FCS232 - nn;;; +FCS23248;nn;FCS232 - nn;;; +FCS23249;nn;FCS232 - nn;;; +FCS23250;nn;FCS232 - nn;;; +FCS23251;nn;FCS232 - nn;;; +FCS23252;nn;FCS232 - nn;;; +FCS23253;nn;FCS232 - nn;;; +FCS23254;nn;FCS232 - nn;;; +FCS23255;nn;FCS232 - nn;;; +FCS23256;nn;FCS232 - nn;;; +FCS23257;nn;FCS232 - nn;;; +FCS23258;nn;FCS232 - nn;;; +FCS23259;nn;FCS232 - nn;;; +FCS23260;nn;FCS232 - nn;;; +FCS23261;nn;FCS232 - nn;;; +FCS23262;Germany;FCS232 - Germany;;; +FCS23263;nn;FCS232 - nn;;; +FCS23264;nn;FCS232 - nn;;; +FCS23265;nn;FCS232 - nn;;; +FCS23266;nn;FCS232 - nn;;; +FCS23267;nn;FCS232 - nn;;; +FCS23268;nn;FCS232 - nn;;; +FCS23269;nn;FCS232 - nn;;; +FCS23270;nn;FCS232 - nn;;; +FCS23271;2X;FCS232 - 2X;;; +FCS23272;nn;FCS232 - nn;;; +FCS23273;2X;FCS232 - 2X;;; +FCS23274;nn;FCS232 - nn;;; +FCS23275;nn;FCS232 - nn;;; +FCS23276;2X;FCS232 - 2X;;; +FCS23277;2X;FCS232 - 2X;;; +FCS23278;nn;FCS232 - nn;;; +FCS23279;nn;FCS232 - nn;;; +FCS23280;TST;FCS232 - TST;;; +FCS23281;OE-TEST;FCS232 - OE-TEST;;; +FCS23282;T2;FCS232 - T2;;; +FCS23283;T3;FCS232 - T3;;; +FCS23284;nn;FCS232 - nn;;; +FCS23285;nn;FCS232 - nn;;; +FCS23286;nn;FCS232 - nn;;; +FCS23287;nn;FCS232 - nn;;; +FCS23288;nn;FCS232 - nn;;; +FCS23289;nn;FCS232 - nn;;; +FCS23290;nn;FCS232 - nn;;; +FCS23291;OE-1;FCS232 - OE-1;;; +FCS23292;nn;FCS232 - nn;;; +FCS23293;OE-3;FCS232 - OE-3;;; +FCS23294;nn;FCS232 - nn;;; +FCS23295;nn;FCS232 - nn;;; +FCS23296;nn;FCS232 - nn;;; +FCS23297;nn;FCS232 - nn;;; +FCS23298;OE-8;FCS232 - OE-8;;; +FCS23299;ECHO;FCS232 - ECHO;;; diff --git a/DGIdGateway/GPS.cpp b/DGIdGateway/GPS.cpp new file mode 100644 index 0000000..32e129d --- /dev/null +++ b/DGIdGateway/GPS.cpp @@ -0,0 +1,272 @@ +/* +* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "GPS.h" +#include "YSFPayload.h" +#include "YSFDefines.h" +#include "Utils.h" +#include "CRC.h" +#include "Log.h" + +#include +#include +#include + +const unsigned char SHRT_GPS[] = {0x22U, 0x62U}; +const unsigned char LONG_GPS[] = {0x47U, 0x64U}; + +CGPS::CGPS(CAPRSWriter* writer) : +m_writer(writer), +m_buffer(NULL), +m_sent(false) +{ + assert(writer != NULL); + + m_buffer = new unsigned char[300U]; +} + +CGPS::~CGPS() +{ + delete[] m_buffer; +} + +void CGPS::data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft) +{ + if (m_sent) + return; + + if (fi != YSF_FI_COMMUNICATIONS) + return; + + CYSFPayload payload; + + if (dt == YSF_DT_VD_MODE1) { + if (fn == 0U || fn == 1U || fn == 2U) + return; + + bool valid = payload.readVDMode1Data(data, m_buffer + (fn - 3U) * 20U); + if (!valid) + return; + + if (fn == ft) { + bool valid = false; + + // Find the end marker + for (unsigned int i = (fn - 2U) * 20U; i > 0U; i--) { + if (m_buffer[i] == 0x03U) { + unsigned char crc = CCRC::addCRC(m_buffer, i + 1U); + if (crc == m_buffer[i + 1U]) + valid = true; + + break; + } + } + + if (valid) { + if (::memcmp(m_buffer + 1U, SHRT_GPS, 2U) == 0) { + CUtils::dump("Short GPS data received", m_buffer, (fn - 2U) * 20U); + transmitGPS(source); + } + + if (::memcmp(m_buffer + 1U, LONG_GPS, 2U) == 0) { + CUtils::dump("Long GPS data received", m_buffer, (fn - 2U) * 20U); + transmitGPS(source); + } + + m_sent = true; + } + } + } else if (dt == YSF_DT_VD_MODE2) { + if (fn != 6U && fn != 7U) + return; + + bool valid = payload.readVDMode2Data(data, m_buffer + (fn - 6U) * 10U); + if (!valid) + return; + + if (fn == ft) { + bool valid = false; + + // Find the end marker + for (unsigned int i = (fn - 5U) * 10U; i > 0U; i--) { + if (m_buffer[i] == 0x03U) { + unsigned char crc = CCRC::addCRC(m_buffer, i + 1U); + if (crc == m_buffer[i + 1U]) + valid = true; + break; + } + } + + if (valid) { + if (::memcmp(m_buffer + 1U, SHRT_GPS, 2U) == 0) { + CUtils::dump("Short GPS data received", m_buffer, (fn - 5U) * 10U); + transmitGPS(source); + } + + if (::memcmp(m_buffer + 1U, LONG_GPS, 2U) == 0) { + CUtils::dump("Long GPS data received", m_buffer, (fn - 5U) * 10U); + transmitGPS(source); + } + + m_sent = true; + } + } + } +} + +void CGPS::reset() +{ + m_sent = false; +} + +void CGPS::transmitGPS(const unsigned char* source) +{ + assert(m_writer != NULL); + + // We don't know who its from! + if (::memcmp(source, " ", YSF_CALLSIGN_LENGTH) == 0) + return; + + for (unsigned int i = 5U; i < 11U; i++) { + unsigned char b = m_buffer[i] & 0xF0U; + if (b != 0x50U && b != 0x30U) + return; // error/unknown + } + + unsigned int tens = m_buffer[5U] & 0x0FU; + unsigned int units = m_buffer[6U] & 0x0FU; + unsigned int lat_deg = (tens * 10U) + units; + if (tens > 9U || units > 9U || lat_deg > 89U) + return; // error/unknown + + tens = m_buffer[7U] & 0x0FU; + units = m_buffer[8U] & 0x0FU; + unsigned int lat_min = (tens * 10U) + units; + if (tens > 9U || units > 9U || lat_min > 59U) + return; // error/unknown + + tens = m_buffer[9U] & 0x0FU; + units = m_buffer[10U] & 0x0FU; + unsigned int lat_min_frac = (tens * 10U) + units; + if (tens > 9U || units > 10U || lat_min_frac > 99U) // units > 10 ??? .. more buggy Yaesu firmware ? + return; // error/unknown + + int lat_dir; + unsigned char b = m_buffer[8U] & 0xF0U; // currently a guess + if (b == 0x50U) + lat_dir = 1; // N + else if (b == 0x30U) + lat_dir = -1; // S + else + return; // error/unknown + + unsigned int lon_deg; + b = m_buffer[9U] & 0xF0U; + if (b == 0x50U) { + // lon deg 0 to 9, and 100 to 179 + b = m_buffer[11U]; + if (b >= 0x76U && b <= 0x7FU) + lon_deg = b - 0x76U; // 0 to 9 + else if (b >= 0x6CU && b <= 0x75U) + lon_deg = 100U + (b - 0x6CU); // 100 to 109 + else if (b >= 0x26U && b <= 0x6BU) + lon_deg = 110U + (b - 0x26U); // 110 to 179 + else + return; // error/unknown + } else if (b == 0x30U) { + // lon deg 10 to 99 + b = m_buffer[11U]; + if (b >= 0x26U && b <= 0x7FU) + lon_deg = 10U + (b - 0x26U); // 10 to 99 + else + return; // error/unknown + } else { + return; // error/unknown + } + + unsigned int lon_min; + b = m_buffer[12U]; + if (b >= 0x58U && b <= 0x61U) + lon_min = b - 0x58U; // 0 to 9 + else if (b >= 0x26U && b <= 0x57U) + lon_min = 10U + (b - 0x26U); // 10 to 59 + else + return; // error/unknown + + unsigned int lon_min_frac; + b = m_buffer[13U]; + if (b >= 0x1CU && b <= 0x7FU) + lon_min_frac = b - 0x1CU; + else + return; // error/unknown + + int lon_dir; + b = m_buffer[10U] & 0xF0U; + if (b == 0x30U) + lon_dir = 1; // E + else if (b == 0x50U) + lon_dir = -1; // W + else + return; // error/unknown + + unsigned int lat_sec = lat_min_frac * 60U; + lat_sec = (lat_sec + (lat_sec % 100U)) / 100U; // with rounding + + unsigned int lon_sec = lon_min_frac * 60U; + lon_sec = (lon_sec + (lon_sec % 100U)) / 100U; // with rounding + + // >= 0 is north, < 0 is south + float latitude = lat_deg + ((lat_min + ((float)lat_min_frac * 0.01F)) * (1.0F / 60.0F)); + latitude *= lat_dir; + + // >= 0 is east, < 0 is west + float longitude = lon_deg + ((lon_min + ((float)lon_min_frac * 0.01F)) * (1.0F / 60.0F)); + longitude *= lon_dir; + + char radio[10U]; + + switch (m_buffer[4U]) { + case 0x24U: + ::strcpy(radio, "FT-1D"); + break; + case 0x25U: + ::strcpy(radio, "FTM-400D"); + break; + case 0x26U: + ::strcpy(radio, "DR-1X"); + break; + case 0x28U: + ::strcpy(radio, "FT-2D"); + break; + case 0x29U: + ::strcpy(radio, "FTM-100D"); + break; + case 0x30U: + ::strcpy(radio, "FT-3D"); + break; + default: + ::sprintf(radio, "0x%02X", m_buffer[4U]); + break; + } + + LogMessage("GPS Position from %10.10s of radio=%s lat=%f long=%f", source, radio, latitude, longitude); + + m_writer->write(source, radio, m_buffer[4U], latitude, longitude); + + m_sent = true; +} diff --git a/DGIdGateway/GPS.h b/DGIdGateway/GPS.h new file mode 100644 index 0000000..cbdf838 --- /dev/null +++ b/DGIdGateway/GPS.h @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(GPS_H) +#define GPS_H + +#include "APRSWriter.h" + +#include + +class CGPS { +public: + CGPS(CAPRSWriter* writer); + ~CGPS(); + + void data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft); + + void reset(); + +private: + CAPRSWriter* m_writer; + unsigned char* m_buffer; + bool m_sent; + + void transmitGPS(const unsigned char* source); +}; + +#endif diff --git a/DGIdGateway/Golay24128.cpp b/DGIdGateway/Golay24128.cpp new file mode 100644 index 0000000..417da00 --- /dev/null +++ b/DGIdGateway/Golay24128.cpp @@ -0,0 +1,1108 @@ +/* + * Copyright (C) 2010,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2002 by Robert H. Morelos-Zaragoza. All rights reserved. + */ + +#include "Golay24128.h" + +#include +#include + +const unsigned int ENCODING_TABLE_23127[] = { + 0x000000U, 0x0018EAU, 0x00293EU, 0x0031D4U, 0x004A96U, 0x00527CU, 0x0063A8U, 0x007B42U, 0x008DC6U, 0x00952CU, + 0x00A4F8U, 0x00BC12U, 0x00C750U, 0x00DFBAU, 0x00EE6EU, 0x00F684U, 0x010366U, 0x011B8CU, 0x012A58U, 0x0132B2U, + 0x0149F0U, 0x01511AU, 0x0160CEU, 0x017824U, 0x018EA0U, 0x01964AU, 0x01A79EU, 0x01BF74U, 0x01C436U, 0x01DCDCU, + 0x01ED08U, 0x01F5E2U, 0x0206CCU, 0x021E26U, 0x022FF2U, 0x023718U, 0x024C5AU, 0x0254B0U, 0x026564U, 0x027D8EU, + 0x028B0AU, 0x0293E0U, 0x02A234U, 0x02BADEU, 0x02C19CU, 0x02D976U, 0x02E8A2U, 0x02F048U, 0x0305AAU, 0x031D40U, + 0x032C94U, 0x03347EU, 0x034F3CU, 0x0357D6U, 0x036602U, 0x037EE8U, 0x03886CU, 0x039086U, 0x03A152U, 0x03B9B8U, + 0x03C2FAU, 0x03DA10U, 0x03EBC4U, 0x03F32EU, 0x040D98U, 0x041572U, 0x0424A6U, 0x043C4CU, 0x04470EU, 0x045FE4U, + 0x046E30U, 0x0476DAU, 0x04805EU, 0x0498B4U, 0x04A960U, 0x04B18AU, 0x04CAC8U, 0x04D222U, 0x04E3F6U, 0x04FB1CU, + 0x050EFEU, 0x051614U, 0x0527C0U, 0x053F2AU, 0x054468U, 0x055C82U, 0x056D56U, 0x0575BCU, 0x058338U, 0x059BD2U, + 0x05AA06U, 0x05B2ECU, 0x05C9AEU, 0x05D144U, 0x05E090U, 0x05F87AU, 0x060B54U, 0x0613BEU, 0x06226AU, 0x063A80U, + 0x0641C2U, 0x065928U, 0x0668FCU, 0x067016U, 0x068692U, 0x069E78U, 0x06AFACU, 0x06B746U, 0x06CC04U, 0x06D4EEU, + 0x06E53AU, 0x06FDD0U, 0x070832U, 0x0710D8U, 0x07210CU, 0x0739E6U, 0x0742A4U, 0x075A4EU, 0x076B9AU, 0x077370U, + 0x0785F4U, 0x079D1EU, 0x07ACCAU, 0x07B420U, 0x07CF62U, 0x07D788U, 0x07E65CU, 0x07FEB6U, 0x0803DAU, 0x081B30U, + 0x082AE4U, 0x08320EU, 0x08494CU, 0x0851A6U, 0x086072U, 0x087898U, 0x088E1CU, 0x0896F6U, 0x08A722U, 0x08BFC8U, + 0x08C48AU, 0x08DC60U, 0x08EDB4U, 0x08F55EU, 0x0900BCU, 0x091856U, 0x092982U, 0x093168U, 0x094A2AU, 0x0952C0U, + 0x096314U, 0x097BFEU, 0x098D7AU, 0x099590U, 0x09A444U, 0x09BCAEU, 0x09C7ECU, 0x09DF06U, 0x09EED2U, 0x09F638U, + 0x0A0516U, 0x0A1DFCU, 0x0A2C28U, 0x0A34C2U, 0x0A4F80U, 0x0A576AU, 0x0A66BEU, 0x0A7E54U, 0x0A88D0U, 0x0A903AU, + 0x0AA1EEU, 0x0AB904U, 0x0AC246U, 0x0ADAACU, 0x0AEB78U, 0x0AF392U, 0x0B0670U, 0x0B1E9AU, 0x0B2F4EU, 0x0B37A4U, + 0x0B4CE6U, 0x0B540CU, 0x0B65D8U, 0x0B7D32U, 0x0B8BB6U, 0x0B935CU, 0x0BA288U, 0x0BBA62U, 0x0BC120U, 0x0BD9CAU, + 0x0BE81EU, 0x0BF0F4U, 0x0C0E42U, 0x0C16A8U, 0x0C277CU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3EU, 0x0C6DEAU, 0x0C7500U, + 0x0C8384U, 0x0C9B6EU, 0x0CAABAU, 0x0CB250U, 0x0CC912U, 0x0CD1F8U, 0x0CE02CU, 0x0CF8C6U, 0x0D0D24U, 0x0D15CEU, + 0x0D241AU, 0x0D3CF0U, 0x0D47B2U, 0x0D5F58U, 0x0D6E8CU, 0x0D7666U, 0x0D80E2U, 0x0D9808U, 0x0DA9DCU, 0x0DB136U, + 0x0DCA74U, 0x0DD29EU, 0x0DE34AU, 0x0DFBA0U, 0x0E088EU, 0x0E1064U, 0x0E21B0U, 0x0E395AU, 0x0E4218U, 0x0E5AF2U, + 0x0E6B26U, 0x0E73CCU, 0x0E8548U, 0x0E9DA2U, 0x0EAC76U, 0x0EB49CU, 0x0ECFDEU, 0x0ED734U, 0x0EE6E0U, 0x0EFE0AU, + 0x0F0BE8U, 0x0F1302U, 0x0F22D6U, 0x0F3A3CU, 0x0F417EU, 0x0F5994U, 0x0F6840U, 0x0F70AAU, 0x0F862EU, 0x0F9EC4U, + 0x0FAF10U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD452U, 0x0FE586U, 0x0FFD6CU, 0x1007B4U, 0x101F5EU, 0x102E8AU, 0x103660U, + 0x104D22U, 0x1055C8U, 0x10641CU, 0x107CF6U, 0x108A72U, 0x109298U, 0x10A34CU, 0x10BBA6U, 0x10C0E4U, 0x10D80EU, + 0x10E9DAU, 0x10F130U, 0x1104D2U, 0x111C38U, 0x112DECU, 0x113506U, 0x114E44U, 0x1156AEU, 0x11677AU, 0x117F90U, + 0x118914U, 0x1191FEU, 0x11A02AU, 0x11B8C0U, 0x11C382U, 0x11DB68U, 0x11EABCU, 0x11F256U, 0x120178U, 0x121992U, + 0x122846U, 0x1230ACU, 0x124BEEU, 0x125304U, 0x1262D0U, 0x127A3AU, 0x128CBEU, 0x129454U, 0x12A580U, 0x12BD6AU, + 0x12C628U, 0x12DEC2U, 0x12EF16U, 0x12F7FCU, 0x13021EU, 0x131AF4U, 0x132B20U, 0x1333CAU, 0x134888U, 0x135062U, + 0x1361B6U, 0x13795CU, 0x138FD8U, 0x139732U, 0x13A6E6U, 0x13BE0CU, 0x13C54EU, 0x13DDA4U, 0x13EC70U, 0x13F49AU, + 0x140A2CU, 0x1412C6U, 0x142312U, 0x143BF8U, 0x1440BAU, 0x145850U, 0x146984U, 0x14716EU, 0x1487EAU, 0x149F00U, + 0x14AED4U, 0x14B63EU, 0x14CD7CU, 0x14D596U, 0x14E442U, 0x14FCA8U, 0x15094AU, 0x1511A0U, 0x152074U, 0x15389EU, + 0x1543DCU, 0x155B36U, 0x156AE2U, 0x157208U, 0x15848CU, 0x159C66U, 0x15ADB2U, 0x15B558U, 0x15CE1AU, 0x15D6F0U, + 0x15E724U, 0x15FFCEU, 0x160CE0U, 0x16140AU, 0x1625DEU, 0x163D34U, 0x164676U, 0x165E9CU, 0x166F48U, 0x1677A2U, + 0x168126U, 0x1699CCU, 0x16A818U, 0x16B0F2U, 0x16CBB0U, 0x16D35AU, 0x16E28EU, 0x16FA64U, 0x170F86U, 0x17176CU, + 0x1726B8U, 0x173E52U, 0x174510U, 0x175DFAU, 0x176C2EU, 0x1774C4U, 0x178240U, 0x179AAAU, 0x17AB7EU, 0x17B394U, + 0x17C8D6U, 0x17D03CU, 0x17E1E8U, 0x17F902U, 0x18046EU, 0x181C84U, 0x182D50U, 0x1835BAU, 0x184EF8U, 0x185612U, + 0x1867C6U, 0x187F2CU, 0x1889A8U, 0x189142U, 0x18A096U, 0x18B87CU, 0x18C33EU, 0x18DBD4U, 0x18EA00U, 0x18F2EAU, + 0x190708U, 0x191FE2U, 0x192E36U, 0x1936DCU, 0x194D9EU, 0x195574U, 0x1964A0U, 0x197C4AU, 0x198ACEU, 0x199224U, + 0x19A3F0U, 0x19BB1AU, 0x19C058U, 0x19D8B2U, 0x19E966U, 0x19F18CU, 0x1A02A2U, 0x1A1A48U, 0x1A2B9CU, 0x1A3376U, + 0x1A4834U, 0x1A50DEU, 0x1A610AU, 0x1A79E0U, 0x1A8F64U, 0x1A978EU, 0x1AA65AU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD18U, + 0x1AECCCU, 0x1AF426U, 0x1B01C4U, 0x1B192EU, 0x1B28FAU, 0x1B3010U, 0x1B4B52U, 0x1B53B8U, 0x1B626CU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E8U, 0x1BA53CU, 0x1BBDD6U, 0x1BC694U, 0x1BDE7EU, 0x1BEFAAU, 0x1BF740U, 0x1C09F6U, 0x1C111CU, + 0x1C20C8U, 0x1C3822U, 0x1C4360U, 0x1C5B8AU, 0x1C6A5EU, 0x1C72B4U, 0x1C8430U, 0x1C9CDAU, 0x1CAD0EU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64CU, 0x1CE798U, 0x1CFF72U, 0x1D0A90U, 0x1D127AU, 0x1D23AEU, 0x1D3B44U, 0x1D4006U, 0x1D58ECU, + 0x1D6938U, 0x1D71D2U, 0x1D8756U, 0x1D9FBCU, 0x1DAE68U, 0x1DB682U, 0x1DCDC0U, 0x1DD52AU, 0x1DE4FEU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D0U, 0x1E2604U, 0x1E3EEEU, 0x1E45ACU, 0x1E5D46U, 0x1E6C92U, 0x1E7478U, 0x1E82FCU, 0x1E9A16U, + 0x1EABC2U, 0x1EB328U, 0x1EC86AU, 0x1ED080U, 0x1EE154U, 0x1EF9BEU, 0x1F0C5CU, 0x1F14B6U, 0x1F2562U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E20U, 0x1F6FF4U, 0x1F771EU, 0x1F819AU, 0x1F9970U, 0x1FA8A4U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E6U, + 0x1FE232U, 0x1FFAD8U, 0x200F68U, 0x201782U, 0x202656U, 0x203EBCU, 0x2045FEU, 0x205D14U, 0x206CC0U, 0x20742AU, + 0x2082AEU, 0x209A44U, 0x20AB90U, 0x20B37AU, 0x20C838U, 0x20D0D2U, 0x20E106U, 0x20F9ECU, 0x210C0EU, 0x2114E4U, + 0x212530U, 0x213DDAU, 0x214698U, 0x215E72U, 0x216FA6U, 0x21774CU, 0x2181C8U, 0x219922U, 0x21A8F6U, 0x21B01CU, + 0x21CB5EU, 0x21D3B4U, 0x21E260U, 0x21FA8AU, 0x2209A4U, 0x22114EU, 0x22209AU, 0x223870U, 0x224332U, 0x225BD8U, + 0x226A0CU, 0x2272E6U, 0x228462U, 0x229C88U, 0x22AD5CU, 0x22B5B6U, 0x22CEF4U, 0x22D61EU, 0x22E7CAU, 0x22FF20U, + 0x230AC2U, 0x231228U, 0x2323FCU, 0x233B16U, 0x234054U, 0x2358BEU, 0x23696AU, 0x237180U, 0x238704U, 0x239FEEU, + 0x23AE3AU, 0x23B6D0U, 0x23CD92U, 0x23D578U, 0x23E4ACU, 0x23FC46U, 0x2402F0U, 0x241A1AU, 0x242BCEU, 0x243324U, + 0x244866U, 0x24508CU, 0x246158U, 0x2479B2U, 0x248F36U, 0x2497DCU, 0x24A608U, 0x24BEE2U, 0x24C5A0U, 0x24DD4AU, + 0x24EC9EU, 0x24F474U, 0x250196U, 0x25197CU, 0x2528A8U, 0x253042U, 0x254B00U, 0x2553EAU, 0x25623EU, 0x257AD4U, + 0x258C50U, 0x2594BAU, 0x25A56EU, 0x25BD84U, 0x25C6C6U, 0x25DE2CU, 0x25EFF8U, 0x25F712U, 0x26043CU, 0x261CD6U, + 0x262D02U, 0x2635E8U, 0x264EAAU, 0x265640U, 0x266794U, 0x267F7EU, 0x2689FAU, 0x269110U, 0x26A0C4U, 0x26B82EU, + 0x26C36CU, 0x26DB86U, 0x26EA52U, 0x26F2B8U, 0x27075AU, 0x271FB0U, 0x272E64U, 0x27368EU, 0x274DCCU, 0x275526U, + 0x2764F2U, 0x277C18U, 0x278A9CU, 0x279276U, 0x27A3A2U, 0x27BB48U, 0x27C00AU, 0x27D8E0U, 0x27E934U, 0x27F1DEU, + 0x280CB2U, 0x281458U, 0x28258CU, 0x283D66U, 0x284624U, 0x285ECEU, 0x286F1AU, 0x2877F0U, 0x288174U, 0x28999EU, + 0x28A84AU, 0x28B0A0U, 0x28CBE2U, 0x28D308U, 0x28E2DCU, 0x28FA36U, 0x290FD4U, 0x29173EU, 0x2926EAU, 0x293E00U, + 0x294542U, 0x295DA8U, 0x296C7CU, 0x297496U, 0x298212U, 0x299AF8U, 0x29AB2CU, 0x29B3C6U, 0x29C884U, 0x29D06EU, + 0x29E1BAU, 0x29F950U, 0x2A0A7EU, 0x2A1294U, 0x2A2340U, 0x2A3BAAU, 0x2A40E8U, 0x2A5802U, 0x2A69D6U, 0x2A713CU, + 0x2A87B8U, 0x2A9F52U, 0x2AAE86U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C4U, 0x2AE410U, 0x2AFCFAU, 0x2B0918U, 0x2B11F2U, + 0x2B2026U, 0x2B38CCU, 0x2B438EU, 0x2B5B64U, 0x2B6AB0U, 0x2B725AU, 0x2B84DEU, 0x2B9C34U, 0x2BADE0U, 0x2BB50AU, + 0x2BCE48U, 0x2BD6A2U, 0x2BE776U, 0x2BFF9CU, 0x2C012AU, 0x2C19C0U, 0x2C2814U, 0x2C30FEU, 0x2C4BBCU, 0x2C5356U, + 0x2C6282U, 0x2C7A68U, 0x2C8CECU, 0x2C9406U, 0x2CA5D2U, 0x2CBD38U, 0x2CC67AU, 0x2CDE90U, 0x2CEF44U, 0x2CF7AEU, + 0x2D024CU, 0x2D1AA6U, 0x2D2B72U, 0x2D3398U, 0x2D48DAU, 0x2D5030U, 0x2D61E4U, 0x2D790EU, 0x2D8F8AU, 0x2D9760U, + 0x2DA6B4U, 0x2DBE5EU, 0x2DC51CU, 0x2DDDF6U, 0x2DEC22U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0CU, 0x2E2ED8U, 0x2E3632U, + 0x2E4D70U, 0x2E559AU, 0x2E644EU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CAU, 0x2EA31EU, 0x2EBBF4U, 0x2EC0B6U, 0x2ED85CU, + 0x2EE988U, 0x2EF162U, 0x2F0480U, 0x2F1C6AU, 0x2F2DBEU, 0x2F3554U, 0x2F4E16U, 0x2F56FCU, 0x2F6728U, 0x2F7FC2U, + 0x2F8946U, 0x2F91ACU, 0x2FA078U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3AU, 0x2FEAEEU, 0x2FF204U, 0x3008DCU, 0x301036U, + 0x3021E2U, 0x303908U, 0x30424AU, 0x305AA0U, 0x306B74U, 0x30739EU, 0x30851AU, 0x309DF0U, 0x30AC24U, 0x30B4CEU, + 0x30CF8CU, 0x30D766U, 0x30E6B2U, 0x30FE58U, 0x310BBAU, 0x311350U, 0x312284U, 0x313A6EU, 0x31412CU, 0x3159C6U, + 0x316812U, 0x3170F8U, 0x31867CU, 0x319E96U, 0x31AF42U, 0x31B7A8U, 0x31CCEAU, 0x31D400U, 0x31E5D4U, 0x31FD3EU, + 0x320E10U, 0x3216FAU, 0x32272EU, 0x323FC4U, 0x324486U, 0x325C6CU, 0x326DB8U, 0x327552U, 0x3283D6U, 0x329B3CU, + 0x32AAE8U, 0x32B202U, 0x32C940U, 0x32D1AAU, 0x32E07EU, 0x32F894U, 0x330D76U, 0x33159CU, 0x332448U, 0x333CA2U, + 0x3347E0U, 0x335F0AU, 0x336EDEU, 0x337634U, 0x3380B0U, 0x33985AU, 0x33A98EU, 0x33B164U, 0x33CA26U, 0x33D2CCU, + 0x33E318U, 0x33FBF2U, 0x340544U, 0x341DAEU, 0x342C7AU, 0x343490U, 0x344FD2U, 0x345738U, 0x3466ECU, 0x347E06U, + 0x348882U, 0x349068U, 0x34A1BCU, 0x34B956U, 0x34C214U, 0x34DAFEU, 0x34EB2AU, 0x34F3C0U, 0x350622U, 0x351EC8U, + 0x352F1CU, 0x3537F6U, 0x354CB4U, 0x35545EU, 0x35658AU, 0x357D60U, 0x358BE4U, 0x35930EU, 0x35A2DAU, 0x35BA30U, + 0x35C172U, 0x35D998U, 0x35E84CU, 0x35F0A6U, 0x360388U, 0x361B62U, 0x362AB6U, 0x36325CU, 0x36491EU, 0x3651F4U, + 0x366020U, 0x3678CAU, 0x368E4EU, 0x3696A4U, 0x36A770U, 0x36BF9AU, 0x36C4D8U, 0x36DC32U, 0x36EDE6U, 0x36F50CU, + 0x3700EEU, 0x371804U, 0x3729D0U, 0x37313AU, 0x374A78U, 0x375292U, 0x376346U, 0x377BACU, 0x378D28U, 0x3795C2U, + 0x37A416U, 0x37BCFCU, 0x37C7BEU, 0x37DF54U, 0x37EE80U, 0x37F66AU, 0x380B06U, 0x3813ECU, 0x382238U, 0x383AD2U, + 0x384190U, 0x38597AU, 0x3868AEU, 0x387044U, 0x3886C0U, 0x389E2AU, 0x38AFFEU, 0x38B714U, 0x38CC56U, 0x38D4BCU, + 0x38E568U, 0x38FD82U, 0x390860U, 0x39108AU, 0x39215EU, 0x3939B4U, 0x3942F6U, 0x395A1CU, 0x396BC8U, 0x397322U, + 0x3985A6U, 0x399D4CU, 0x39AC98U, 0x39B472U, 0x39CF30U, 0x39D7DAU, 0x39E60EU, 0x39FEE4U, 0x3A0DCAU, 0x3A1520U, + 0x3A24F4U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB6U, 0x3A6E62U, 0x3A7688U, 0x3A800CU, 0x3A98E6U, 0x3AA932U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD270U, 0x3AE3A4U, 0x3AFB4EU, 0x3B0EACU, 0x3B1646U, 0x3B2792U, 0x3B3F78U, 0x3B443AU, 0x3B5CD0U, + 0x3B6D04U, 0x3B75EEU, 0x3B836AU, 0x3B9B80U, 0x3BAA54U, 0x3BB2BEU, 0x3BC9FCU, 0x3BD116U, 0x3BE0C2U, 0x3BF828U, + 0x3C069EU, 0x3C1E74U, 0x3C2FA0U, 0x3C374AU, 0x3C4C08U, 0x3C54E2U, 0x3C6536U, 0x3C7DDCU, 0x3C8B58U, 0x3C93B2U, + 0x3CA266U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD924U, 0x3CE8F0U, 0x3CF01AU, 0x3D05F8U, 0x3D1D12U, 0x3D2CC6U, 0x3D342CU, + 0x3D4F6EU, 0x3D5784U, 0x3D6650U, 0x3D7EBAU, 0x3D883EU, 0x3D90D4U, 0x3DA100U, 0x3DB9EAU, 0x3DC2A8U, 0x3DDA42U, + 0x3DEB96U, 0x3DF37CU, 0x3E0052U, 0x3E18B8U, 0x3E296CU, 0x3E3186U, 0x3E4AC4U, 0x3E522EU, 0x3E63FAU, 0x3E7B10U, + 0x3E8D94U, 0x3E957EU, 0x3EA4AAU, 0x3EBC40U, 0x3EC702U, 0x3EDFE8U, 0x3EEE3CU, 0x3EF6D6U, 0x3F0334U, 0x3F1BDEU, + 0x3F2A0AU, 0x3F32E0U, 0x3F49A2U, 0x3F5148U, 0x3F609CU, 0x3F7876U, 0x3F8EF2U, 0x3F9618U, 0x3FA7CCU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8EU, 0x3FED5AU, 0x3FF5B0U, 0x40063AU, 0x401ED0U, 0x402F04U, 0x4037EEU, 0x404CACU, 0x405446U, + 0x406592U, 0x407D78U, 0x408BFCU, 0x409316U, 0x40A2C2U, 0x40BA28U, 0x40C16AU, 0x40D980U, 0x40E854U, 0x40F0BEU, + 0x41055CU, 0x411DB6U, 0x412C62U, 0x413488U, 0x414FCAU, 0x415720U, 0x4166F4U, 0x417E1EU, 0x41889AU, 0x419070U, + 0x41A1A4U, 0x41B94EU, 0x41C20CU, 0x41DAE6U, 0x41EB32U, 0x41F3D8U, 0x4200F6U, 0x42181CU, 0x4229C8U, 0x423122U, + 0x424A60U, 0x42528AU, 0x42635EU, 0x427BB4U, 0x428D30U, 0x4295DAU, 0x42A40EU, 0x42BCE4U, 0x42C7A6U, 0x42DF4CU, + 0x42EE98U, 0x42F672U, 0x430390U, 0x431B7AU, 0x432AAEU, 0x433244U, 0x434906U, 0x4351ECU, 0x436038U, 0x4378D2U, + 0x438E56U, 0x4396BCU, 0x43A768U, 0x43BF82U, 0x43C4C0U, 0x43DC2AU, 0x43EDFEU, 0x43F514U, 0x440BA2U, 0x441348U, + 0x44229CU, 0x443A76U, 0x444134U, 0x4459DEU, 0x44680AU, 0x4470E0U, 0x448664U, 0x449E8EU, 0x44AF5AU, 0x44B7B0U, + 0x44CCF2U, 0x44D418U, 0x44E5CCU, 0x44FD26U, 0x4508C4U, 0x45102EU, 0x4521FAU, 0x453910U, 0x454252U, 0x455AB8U, + 0x456B6CU, 0x457386U, 0x458502U, 0x459DE8U, 0x45AC3CU, 0x45B4D6U, 0x45CF94U, 0x45D77EU, 0x45E6AAU, 0x45FE40U, + 0x460D6EU, 0x461584U, 0x462450U, 0x463CBAU, 0x4647F8U, 0x465F12U, 0x466EC6U, 0x46762CU, 0x4680A8U, 0x469842U, + 0x46A996U, 0x46B17CU, 0x46CA3EU, 0x46D2D4U, 0x46E300U, 0x46FBEAU, 0x470E08U, 0x4716E2U, 0x472736U, 0x473FDCU, + 0x47449EU, 0x475C74U, 0x476DA0U, 0x47754AU, 0x4783CEU, 0x479B24U, 0x47AAF0U, 0x47B21AU, 0x47C958U, 0x47D1B2U, + 0x47E066U, 0x47F88CU, 0x4805E0U, 0x481D0AU, 0x482CDEU, 0x483434U, 0x484F76U, 0x48579CU, 0x486648U, 0x487EA2U, + 0x488826U, 0x4890CCU, 0x48A118U, 0x48B9F2U, 0x48C2B0U, 0x48DA5AU, 0x48EB8EU, 0x48F364U, 0x490686U, 0x491E6CU, + 0x492FB8U, 0x493752U, 0x494C10U, 0x4954FAU, 0x49652EU, 0x497DC4U, 0x498B40U, 0x4993AAU, 0x49A27EU, 0x49BA94U, + 0x49C1D6U, 0x49D93CU, 0x49E8E8U, 0x49F002U, 0x4A032CU, 0x4A1BC6U, 0x4A2A12U, 0x4A32F8U, 0x4A49BAU, 0x4A5150U, + 0x4A6084U, 0x4A786EU, 0x4A8EEAU, 0x4A9600U, 0x4AA7D4U, 0x4ABF3EU, 0x4AC47CU, 0x4ADC96U, 0x4AED42U, 0x4AF5A8U, + 0x4B004AU, 0x4B18A0U, 0x4B2974U, 0x4B319EU, 0x4B4ADCU, 0x4B5236U, 0x4B63E2U, 0x4B7B08U, 0x4B8D8CU, 0x4B9566U, + 0x4BA4B2U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF0U, 0x4BEE24U, 0x4BF6CEU, 0x4C0878U, 0x4C1092U, 0x4C2146U, 0x4C39ACU, + 0x4C42EEU, 0x4C5A04U, 0x4C6BD0U, 0x4C733AU, 0x4C85BEU, 0x4C9D54U, 0x4CAC80U, 0x4CB46AU, 0x4CCF28U, 0x4CD7C2U, + 0x4CE616U, 0x4CFEFCU, 0x4D0B1EU, 0x4D13F4U, 0x4D2220U, 0x4D3ACAU, 0x4D4188U, 0x4D5962U, 0x4D68B6U, 0x4D705CU, + 0x4D86D8U, 0x4D9E32U, 0x4DAFE6U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A4U, 0x4DE570U, 0x4DFD9AU, 0x4E0EB4U, 0x4E165EU, + 0x4E278AU, 0x4E3F60U, 0x4E4422U, 0x4E5CC8U, 0x4E6D1CU, 0x4E75F6U, 0x4E8372U, 0x4E9B98U, 0x4EAA4CU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10EU, 0x4EE0DAU, 0x4EF830U, 0x4F0DD2U, 0x4F1538U, 0x4F24ECU, 0x4F3C06U, 0x4F4744U, 0x4F5FAEU, + 0x4F6E7AU, 0x4F7690U, 0x4F8014U, 0x4F98FEU, 0x4FA92AU, 0x4FB1C0U, 0x4FCA82U, 0x4FD268U, 0x4FE3BCU, 0x4FFB56U, + 0x50018EU, 0x501964U, 0x5028B0U, 0x50305AU, 0x504B18U, 0x5053F2U, 0x506226U, 0x507ACCU, 0x508C48U, 0x5094A2U, + 0x50A576U, 0x50BD9CU, 0x50C6DEU, 0x50DE34U, 0x50EFE0U, 0x50F70AU, 0x5102E8U, 0x511A02U, 0x512BD6U, 0x51333CU, + 0x51487EU, 0x515094U, 0x516140U, 0x5179AAU, 0x518F2EU, 0x5197C4U, 0x51A610U, 0x51BEFAU, 0x51C5B8U, 0x51DD52U, + 0x51EC86U, 0x51F46CU, 0x520742U, 0x521FA8U, 0x522E7CU, 0x523696U, 0x524DD4U, 0x52553EU, 0x5264EAU, 0x527C00U, + 0x528A84U, 0x52926EU, 0x52A3BAU, 0x52BB50U, 0x52C012U, 0x52D8F8U, 0x52E92CU, 0x52F1C6U, 0x530424U, 0x531CCEU, + 0x532D1AU, 0x5335F0U, 0x534EB2U, 0x535658U, 0x53678CU, 0x537F66U, 0x5389E2U, 0x539108U, 0x53A0DCU, 0x53B836U, + 0x53C374U, 0x53DB9EU, 0x53EA4AU, 0x53F2A0U, 0x540C16U, 0x5414FCU, 0x542528U, 0x543DC2U, 0x544680U, 0x545E6AU, + 0x546FBEU, 0x547754U, 0x5481D0U, 0x54993AU, 0x54A8EEU, 0x54B004U, 0x54CB46U, 0x54D3ACU, 0x54E278U, 0x54FA92U, + 0x550F70U, 0x55179AU, 0x55264EU, 0x553EA4U, 0x5545E6U, 0x555D0CU, 0x556CD8U, 0x557432U, 0x5582B6U, 0x559A5CU, + 0x55AB88U, 0x55B362U, 0x55C820U, 0x55D0CAU, 0x55E11EU, 0x55F9F4U, 0x560ADAU, 0x561230U, 0x5623E4U, 0x563B0EU, + 0x56404CU, 0x5658A6U, 0x566972U, 0x567198U, 0x56871CU, 0x569FF6U, 0x56AE22U, 0x56B6C8U, 0x56CD8AU, 0x56D560U, + 0x56E4B4U, 0x56FC5EU, 0x5709BCU, 0x571156U, 0x572082U, 0x573868U, 0x57432AU, 0x575BC0U, 0x576A14U, 0x5772FEU, + 0x57847AU, 0x579C90U, 0x57AD44U, 0x57B5AEU, 0x57CEECU, 0x57D606U, 0x57E7D2U, 0x57FF38U, 0x580254U, 0x581ABEU, + 0x582B6AU, 0x583380U, 0x5848C2U, 0x585028U, 0x5861FCU, 0x587916U, 0x588F92U, 0x589778U, 0x58A6ACU, 0x58BE46U, + 0x58C504U, 0x58DDEEU, 0x58EC3AU, 0x58F4D0U, 0x590132U, 0x5919D8U, 0x59280CU, 0x5930E6U, 0x594BA4U, 0x59534EU, + 0x59629AU, 0x597A70U, 0x598CF4U, 0x59941EU, 0x59A5CAU, 0x59BD20U, 0x59C662U, 0x59DE88U, 0x59EF5CU, 0x59F7B6U, + 0x5A0498U, 0x5A1C72U, 0x5A2DA6U, 0x5A354CU, 0x5A4E0EU, 0x5A56E4U, 0x5A6730U, 0x5A7FDAU, 0x5A895EU, 0x5A91B4U, + 0x5AA060U, 0x5AB88AU, 0x5AC3C8U, 0x5ADB22U, 0x5AEAF6U, 0x5AF21CU, 0x5B07FEU, 0x5B1F14U, 0x5B2EC0U, 0x5B362AU, + 0x5B4D68U, 0x5B5582U, 0x5B6456U, 0x5B7CBCU, 0x5B8A38U, 0x5B92D2U, 0x5BA306U, 0x5BBBECU, 0x5BC0AEU, 0x5BD844U, + 0x5BE990U, 0x5BF17AU, 0x5C0FCCU, 0x5C1726U, 0x5C26F2U, 0x5C3E18U, 0x5C455AU, 0x5C5DB0U, 0x5C6C64U, 0x5C748EU, + 0x5C820AU, 0x5C9AE0U, 0x5CAB34U, 0x5CB3DEU, 0x5CC89CU, 0x5CD076U, 0x5CE1A2U, 0x5CF948U, 0x5D0CAAU, 0x5D1440U, + 0x5D2594U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED6U, 0x5D6F02U, 0x5D77E8U, 0x5D816CU, 0x5D9986U, 0x5DA852U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD310U, 0x5DE2C4U, 0x5DFA2EU, 0x5E0900U, 0x5E11EAU, 0x5E203EU, 0x5E38D4U, 0x5E4396U, 0x5E5B7CU, + 0x5E6AA8U, 0x5E7242U, 0x5E84C6U, 0x5E9C2CU, 0x5EADF8U, 0x5EB512U, 0x5ECE50U, 0x5ED6BAU, 0x5EE76EU, 0x5EFF84U, + 0x5F0A66U, 0x5F128CU, 0x5F2358U, 0x5F3BB2U, 0x5F40F0U, 0x5F581AU, 0x5F69CEU, 0x5F7124U, 0x5F87A0U, 0x5F9F4AU, + 0x5FAE9EU, 0x5FB674U, 0x5FCD36U, 0x5FD5DCU, 0x5FE408U, 0x5FFCE2U, 0x600952U, 0x6011B8U, 0x60206CU, 0x603886U, + 0x6043C4U, 0x605B2EU, 0x606AFAU, 0x607210U, 0x608494U, 0x609C7EU, 0x60ADAAU, 0x60B540U, 0x60CE02U, 0x60D6E8U, + 0x60E73CU, 0x60FFD6U, 0x610A34U, 0x6112DEU, 0x61230AU, 0x613BE0U, 0x6140A2U, 0x615848U, 0x61699CU, 0x617176U, + 0x6187F2U, 0x619F18U, 0x61AECCU, 0x61B626U, 0x61CD64U, 0x61D58EU, 0x61E45AU, 0x61FCB0U, 0x620F9EU, 0x621774U, + 0x6226A0U, 0x623E4AU, 0x624508U, 0x625DE2U, 0x626C36U, 0x6274DCU, 0x628258U, 0x629AB2U, 0x62AB66U, 0x62B38CU, + 0x62C8CEU, 0x62D024U, 0x62E1F0U, 0x62F91AU, 0x630CF8U, 0x631412U, 0x6325C6U, 0x633D2CU, 0x63466EU, 0x635E84U, + 0x636F50U, 0x6377BAU, 0x63813EU, 0x6399D4U, 0x63A800U, 0x63B0EAU, 0x63CBA8U, 0x63D342U, 0x63E296U, 0x63FA7CU, + 0x6404CAU, 0x641C20U, 0x642DF4U, 0x64351EU, 0x644E5CU, 0x6456B6U, 0x646762U, 0x647F88U, 0x64890CU, 0x6491E6U, + 0x64A032U, 0x64B8D8U, 0x64C39AU, 0x64DB70U, 0x64EAA4U, 0x64F24EU, 0x6507ACU, 0x651F46U, 0x652E92U, 0x653678U, + 0x654D3AU, 0x6555D0U, 0x656404U, 0x657CEEU, 0x658A6AU, 0x659280U, 0x65A354U, 0x65BBBEU, 0x65C0FCU, 0x65D816U, + 0x65E9C2U, 0x65F128U, 0x660206U, 0x661AECU, 0x662B38U, 0x6633D2U, 0x664890U, 0x66507AU, 0x6661AEU, 0x667944U, + 0x668FC0U, 0x66972AU, 0x66A6FEU, 0x66BE14U, 0x66C556U, 0x66DDBCU, 0x66EC68U, 0x66F482U, 0x670160U, 0x67198AU, + 0x67285EU, 0x6730B4U, 0x674BF6U, 0x67531CU, 0x6762C8U, 0x677A22U, 0x678CA6U, 0x67944CU, 0x67A598U, 0x67BD72U, + 0x67C630U, 0x67DEDAU, 0x67EF0EU, 0x67F7E4U, 0x680A88U, 0x681262U, 0x6823B6U, 0x683B5CU, 0x68401EU, 0x6858F4U, + 0x686920U, 0x6871CAU, 0x68874EU, 0x689FA4U, 0x68AE70U, 0x68B69AU, 0x68CDD8U, 0x68D532U, 0x68E4E6U, 0x68FC0CU, + 0x6909EEU, 0x691104U, 0x6920D0U, 0x69383AU, 0x694378U, 0x695B92U, 0x696A46U, 0x6972ACU, 0x698428U, 0x699CC2U, + 0x69AD16U, 0x69B5FCU, 0x69CEBEU, 0x69D654U, 0x69E780U, 0x69FF6AU, 0x6A0C44U, 0x6A14AEU, 0x6A257AU, 0x6A3D90U, + 0x6A46D2U, 0x6A5E38U, 0x6A6FECU, 0x6A7706U, 0x6A8182U, 0x6A9968U, 0x6AA8BCU, 0x6AB056U, 0x6ACB14U, 0x6AD3FEU, + 0x6AE22AU, 0x6AFAC0U, 0x6B0F22U, 0x6B17C8U, 0x6B261CU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5EU, 0x6B6C8AU, 0x6B7460U, + 0x6B82E4U, 0x6B9A0EU, 0x6BABDAU, 0x6BB330U, 0x6BC872U, 0x6BD098U, 0x6BE14CU, 0x6BF9A6U, 0x6C0710U, 0x6C1FFAU, + 0x6C2E2EU, 0x6C36C4U, 0x6C4D86U, 0x6C556CU, 0x6C64B8U, 0x6C7C52U, 0x6C8AD6U, 0x6C923CU, 0x6CA3E8U, 0x6CBB02U, + 0x6CC040U, 0x6CD8AAU, 0x6CE97EU, 0x6CF194U, 0x6D0476U, 0x6D1C9CU, 0x6D2D48U, 0x6D35A2U, 0x6D4EE0U, 0x6D560AU, + 0x6D67DEU, 0x6D7F34U, 0x6D89B0U, 0x6D915AU, 0x6DA08EU, 0x6DB864U, 0x6DC326U, 0x6DDBCCU, 0x6DEA18U, 0x6DF2F2U, + 0x6E01DCU, 0x6E1936U, 0x6E28E2U, 0x6E3008U, 0x6E4B4AU, 0x6E53A0U, 0x6E6274U, 0x6E7A9EU, 0x6E8C1AU, 0x6E94F0U, + 0x6EA524U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE66U, 0x6EEFB2U, 0x6EF758U, 0x6F02BAU, 0x6F1A50U, 0x6F2B84U, 0x6F336EU, + 0x6F482CU, 0x6F50C6U, 0x6F6112U, 0x6F79F8U, 0x6F8F7CU, 0x6F9796U, 0x6FA642U, 0x6FBEA8U, 0x6FC5EAU, 0x6FDD00U, + 0x6FECD4U, 0x6FF43EU, 0x700EE6U, 0x70160CU, 0x7027D8U, 0x703F32U, 0x704470U, 0x705C9AU, 0x706D4EU, 0x7075A4U, + 0x708320U, 0x709BCAU, 0x70AA1EU, 0x70B2F4U, 0x70C9B6U, 0x70D15CU, 0x70E088U, 0x70F862U, 0x710D80U, 0x71156AU, + 0x7124BEU, 0x713C54U, 0x714716U, 0x715FFCU, 0x716E28U, 0x7176C2U, 0x718046U, 0x7198ACU, 0x71A978U, 0x71B192U, + 0x71CAD0U, 0x71D23AU, 0x71E3EEU, 0x71FB04U, 0x72082AU, 0x7210C0U, 0x722114U, 0x7239FEU, 0x7242BCU, 0x725A56U, + 0x726B82U, 0x727368U, 0x7285ECU, 0x729D06U, 0x72ACD2U, 0x72B438U, 0x72CF7AU, 0x72D790U, 0x72E644U, 0x72FEAEU, + 0x730B4CU, 0x7313A6U, 0x732272U, 0x733A98U, 0x7341DAU, 0x735930U, 0x7368E4U, 0x73700EU, 0x73868AU, 0x739E60U, + 0x73AFB4U, 0x73B75EU, 0x73CC1CU, 0x73D4F6U, 0x73E522U, 0x73FDC8U, 0x74037EU, 0x741B94U, 0x742A40U, 0x7432AAU, + 0x7449E8U, 0x745102U, 0x7460D6U, 0x74783CU, 0x748EB8U, 0x749652U, 0x74A786U, 0x74BF6CU, 0x74C42EU, 0x74DCC4U, + 0x74ED10U, 0x74F5FAU, 0x750018U, 0x7518F2U, 0x752926U, 0x7531CCU, 0x754A8EU, 0x755264U, 0x7563B0U, 0x757B5AU, + 0x758DDEU, 0x759534U, 0x75A4E0U, 0x75BC0AU, 0x75C748U, 0x75DFA2U, 0x75EE76U, 0x75F69CU, 0x7605B2U, 0x761D58U, + 0x762C8CU, 0x763466U, 0x764F24U, 0x7657CEU, 0x76661AU, 0x767EF0U, 0x768874U, 0x76909EU, 0x76A14AU, 0x76B9A0U, + 0x76C2E2U, 0x76DA08U, 0x76EBDCU, 0x76F336U, 0x7706D4U, 0x771E3EU, 0x772FEAU, 0x773700U, 0x774C42U, 0x7754A8U, + 0x77657CU, 0x777D96U, 0x778B12U, 0x7793F8U, 0x77A22CU, 0x77BAC6U, 0x77C184U, 0x77D96EU, 0x77E8BAU, 0x77F050U, + 0x780D3CU, 0x7815D6U, 0x782402U, 0x783CE8U, 0x7847AAU, 0x785F40U, 0x786E94U, 0x78767EU, 0x7880FAU, 0x789810U, + 0x78A9C4U, 0x78B12EU, 0x78CA6CU, 0x78D286U, 0x78E352U, 0x78FBB8U, 0x790E5AU, 0x7916B0U, 0x792764U, 0x793F8EU, + 0x7944CCU, 0x795C26U, 0x796DF2U, 0x797518U, 0x79839CU, 0x799B76U, 0x79AAA2U, 0x79B248U, 0x79C90AU, 0x79D1E0U, + 0x79E034U, 0x79F8DEU, 0x7A0BF0U, 0x7A131AU, 0x7A22CEU, 0x7A3A24U, 0x7A4166U, 0x7A598CU, 0x7A6858U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDCU, 0x7AAF08U, 0x7AB7E2U, 0x7ACCA0U, 0x7AD44AU, 0x7AE59EU, 0x7AFD74U, 0x7B0896U, 0x7B107CU, + 0x7B21A8U, 0x7B3942U, 0x7B4200U, 0x7B5AEAU, 0x7B6B3EU, 0x7B73D4U, 0x7B8550U, 0x7B9DBAU, 0x7BAC6EU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72CU, 0x7BE6F8U, 0x7BFE12U, 0x7C00A4U, 0x7C184EU, 0x7C299AU, 0x7C3170U, 0x7C4A32U, 0x7C52D8U, + 0x7C630CU, 0x7C7BE6U, 0x7C8D62U, 0x7C9588U, 0x7CA45CU, 0x7CBCB6U, 0x7CC7F4U, 0x7CDF1EU, 0x7CEECAU, 0x7CF620U, + 0x7D03C2U, 0x7D1B28U, 0x7D2AFCU, 0x7D3216U, 0x7D4954U, 0x7D51BEU, 0x7D606AU, 0x7D7880U, 0x7D8E04U, 0x7D96EEU, + 0x7DA73AU, 0x7DBFD0U, 0x7DC492U, 0x7DDC78U, 0x7DEDACU, 0x7DF546U, 0x7E0668U, 0x7E1E82U, 0x7E2F56U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5414U, 0x7E65C0U, 0x7E7D2AU, 0x7E8BAEU, 0x7E9344U, 0x7EA290U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D2U, + 0x7EE806U, 0x7EF0ECU, 0x7F050EU, 0x7F1DE4U, 0x7F2C30U, 0x7F34DAU, 0x7F4F98U, 0x7F5772U, 0x7F66A6U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9022U, 0x7FA1F6U, 0x7FB91CU, 0x7FC25EU, 0x7FDAB4U, 0x7FEB60U, 0x7FF38AU, 0x800C74U, 0x80149EU, + 0x80254AU, 0x803DA0U, 0x8046E2U, 0x805E08U, 0x806FDCU, 0x807736U, 0x8081B2U, 0x809958U, 0x80A88CU, 0x80B066U, + 0x80CB24U, 0x80D3CEU, 0x80E21AU, 0x80FAF0U, 0x810F12U, 0x8117F8U, 0x81262CU, 0x813EC6U, 0x814584U, 0x815D6EU, + 0x816CBAU, 0x817450U, 0x8182D4U, 0x819A3EU, 0x81ABEAU, 0x81B300U, 0x81C842U, 0x81D0A8U, 0x81E17CU, 0x81F996U, + 0x820AB8U, 0x821252U, 0x822386U, 0x823B6CU, 0x82402EU, 0x8258C4U, 0x826910U, 0x8271FAU, 0x82877EU, 0x829F94U, + 0x82AE40U, 0x82B6AAU, 0x82CDE8U, 0x82D502U, 0x82E4D6U, 0x82FC3CU, 0x8309DEU, 0x831134U, 0x8320E0U, 0x83380AU, + 0x834348U, 0x835BA2U, 0x836A76U, 0x83729CU, 0x838418U, 0x839CF2U, 0x83AD26U, 0x83B5CCU, 0x83CE8EU, 0x83D664U, + 0x83E7B0U, 0x83FF5AU, 0x8401ECU, 0x841906U, 0x8428D2U, 0x843038U, 0x844B7AU, 0x845390U, 0x846244U, 0x847AAEU, + 0x848C2AU, 0x8494C0U, 0x84A514U, 0x84BDFEU, 0x84C6BCU, 0x84DE56U, 0x84EF82U, 0x84F768U, 0x85028AU, 0x851A60U, + 0x852BB4U, 0x85335EU, 0x85481CU, 0x8550F6U, 0x856122U, 0x8579C8U, 0x858F4CU, 0x8597A6U, 0x85A672U, 0x85BE98U, + 0x85C5DAU, 0x85DD30U, 0x85ECE4U, 0x85F40EU, 0x860720U, 0x861FCAU, 0x862E1EU, 0x8636F4U, 0x864DB6U, 0x86555CU, + 0x866488U, 0x867C62U, 0x868AE6U, 0x86920CU, 0x86A3D8U, 0x86BB32U, 0x86C070U, 0x86D89AU, 0x86E94EU, 0x86F1A4U, + 0x870446U, 0x871CACU, 0x872D78U, 0x873592U, 0x874ED0U, 0x87563AU, 0x8767EEU, 0x877F04U, 0x878980U, 0x87916AU, + 0x87A0BEU, 0x87B854U, 0x87C316U, 0x87DBFCU, 0x87EA28U, 0x87F2C2U, 0x880FAEU, 0x881744U, 0x882690U, 0x883E7AU, + 0x884538U, 0x885DD2U, 0x886C06U, 0x8874ECU, 0x888268U, 0x889A82U, 0x88AB56U, 0x88B3BCU, 0x88C8FEU, 0x88D014U, + 0x88E1C0U, 0x88F92AU, 0x890CC8U, 0x891422U, 0x8925F6U, 0x893D1CU, 0x89465EU, 0x895EB4U, 0x896F60U, 0x89778AU, + 0x89810EU, 0x8999E4U, 0x89A830U, 0x89B0DAU, 0x89CB98U, 0x89D372U, 0x89E2A6U, 0x89FA4CU, 0x8A0962U, 0x8A1188U, + 0x8A205CU, 0x8A38B6U, 0x8A43F4U, 0x8A5B1EU, 0x8A6ACAU, 0x8A7220U, 0x8A84A4U, 0x8A9C4EU, 0x8AAD9AU, 0x8AB570U, + 0x8ACE32U, 0x8AD6D8U, 0x8AE70CU, 0x8AFFE6U, 0x8B0A04U, 0x8B12EEU, 0x8B233AU, 0x8B3BD0U, 0x8B4092U, 0x8B5878U, + 0x8B69ACU, 0x8B7146U, 0x8B87C2U, 0x8B9F28U, 0x8BAEFCU, 0x8BB616U, 0x8BCD54U, 0x8BD5BEU, 0x8BE46AU, 0x8BFC80U, + 0x8C0236U, 0x8C1ADCU, 0x8C2B08U, 0x8C33E2U, 0x8C48A0U, 0x8C504AU, 0x8C619EU, 0x8C7974U, 0x8C8FF0U, 0x8C971AU, + 0x8CA6CEU, 0x8CBE24U, 0x8CC566U, 0x8CDD8CU, 0x8CEC58U, 0x8CF4B2U, 0x8D0150U, 0x8D19BAU, 0x8D286EU, 0x8D3084U, + 0x8D4BC6U, 0x8D532CU, 0x8D62F8U, 0x8D7A12U, 0x8D8C96U, 0x8D947CU, 0x8DA5A8U, 0x8DBD42U, 0x8DC600U, 0x8DDEEAU, + 0x8DEF3EU, 0x8DF7D4U, 0x8E04FAU, 0x8E1C10U, 0x8E2DC4U, 0x8E352EU, 0x8E4E6CU, 0x8E5686U, 0x8E6752U, 0x8E7FB8U, + 0x8E893CU, 0x8E91D6U, 0x8EA002U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB40U, 0x8EEA94U, 0x8EF27EU, 0x8F079CU, 0x8F1F76U, + 0x8F2EA2U, 0x8F3648U, 0x8F4D0AU, 0x8F55E0U, 0x8F6434U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B0U, 0x8FA364U, 0x8FBB8EU, + 0x8FC0CCU, 0x8FD826U, 0x8FE9F2U, 0x8FF118U, 0x900BC0U, 0x90132AU, 0x9022FEU, 0x903A14U, 0x904156U, 0x9059BCU, + 0x906868U, 0x907082U, 0x908606U, 0x909EECU, 0x90AF38U, 0x90B7D2U, 0x90CC90U, 0x90D47AU, 0x90E5AEU, 0x90FD44U, + 0x9108A6U, 0x91104CU, 0x912198U, 0x913972U, 0x914230U, 0x915ADAU, 0x916B0EU, 0x9173E4U, 0x918560U, 0x919D8AU, + 0x91AC5EU, 0x91B4B4U, 0x91CFF6U, 0x91D71CU, 0x91E6C8U, 0x91FE22U, 0x920D0CU, 0x9215E6U, 0x922432U, 0x923CD8U, + 0x92479AU, 0x925F70U, 0x926EA4U, 0x92764EU, 0x9280CAU, 0x929820U, 0x92A9F4U, 0x92B11EU, 0x92CA5CU, 0x92D2B6U, + 0x92E362U, 0x92FB88U, 0x930E6AU, 0x931680U, 0x932754U, 0x933FBEU, 0x9344FCU, 0x935C16U, 0x936DC2U, 0x937528U, + 0x9383ACU, 0x939B46U, 0x93AA92U, 0x93B278U, 0x93C93AU, 0x93D1D0U, 0x93E004U, 0x93F8EEU, 0x940658U, 0x941EB2U, + 0x942F66U, 0x94378CU, 0x944CCEU, 0x945424U, 0x9465F0U, 0x947D1AU, 0x948B9EU, 0x949374U, 0x94A2A0U, 0x94BA4AU, + 0x94C108U, 0x94D9E2U, 0x94E836U, 0x94F0DCU, 0x95053EU, 0x951DD4U, 0x952C00U, 0x9534EAU, 0x954FA8U, 0x955742U, + 0x956696U, 0x957E7CU, 0x9588F8U, 0x959012U, 0x95A1C6U, 0x95B92CU, 0x95C26EU, 0x95DA84U, 0x95EB50U, 0x95F3BAU, + 0x960094U, 0x96187EU, 0x9629AAU, 0x963140U, 0x964A02U, 0x9652E8U, 0x96633CU, 0x967BD6U, 0x968D52U, 0x9695B8U, + 0x96A46CU, 0x96BC86U, 0x96C7C4U, 0x96DF2EU, 0x96EEFAU, 0x96F610U, 0x9703F2U, 0x971B18U, 0x972ACCU, 0x973226U, + 0x974964U, 0x97518EU, 0x97605AU, 0x9778B0U, 0x978E34U, 0x9796DEU, 0x97A70AU, 0x97BFE0U, 0x97C4A2U, 0x97DC48U, + 0x97ED9CU, 0x97F576U, 0x98081AU, 0x9810F0U, 0x982124U, 0x9839CEU, 0x98428CU, 0x985A66U, 0x986BB2U, 0x987358U, + 0x9885DCU, 0x989D36U, 0x98ACE2U, 0x98B408U, 0x98CF4AU, 0x98D7A0U, 0x98E674U, 0x98FE9EU, 0x990B7CU, 0x991396U, + 0x992242U, 0x993AA8U, 0x9941EAU, 0x995900U, 0x9968D4U, 0x99703EU, 0x9986BAU, 0x999E50U, 0x99AF84U, 0x99B76EU, + 0x99CC2CU, 0x99D4C6U, 0x99E512U, 0x99FDF8U, 0x9A0ED6U, 0x9A163CU, 0x9A27E8U, 0x9A3F02U, 0x9A4440U, 0x9A5CAAU, + 0x9A6D7EU, 0x9A7594U, 0x9A8310U, 0x9A9BFAU, 0x9AAA2EU, 0x9AB2C4U, 0x9AC986U, 0x9AD16CU, 0x9AE0B8U, 0x9AF852U, + 0x9B0DB0U, 0x9B155AU, 0x9B248EU, 0x9B3C64U, 0x9B4726U, 0x9B5FCCU, 0x9B6E18U, 0x9B76F2U, 0x9B8076U, 0x9B989CU, + 0x9BA948U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20AU, 0x9BE3DEU, 0x9BFB34U, 0x9C0582U, 0x9C1D68U, 0x9C2CBCU, 0x9C3456U, + 0x9C4F14U, 0x9C57FEU, 0x9C662AU, 0x9C7EC0U, 0x9C8844U, 0x9C90AEU, 0x9CA17AU, 0x9CB990U, 0x9CC2D2U, 0x9CDA38U, + 0x9CEBECU, 0x9CF306U, 0x9D06E4U, 0x9D1E0EU, 0x9D2FDAU, 0x9D3730U, 0x9D4C72U, 0x9D5498U, 0x9D654CU, 0x9D7DA6U, + 0x9D8B22U, 0x9D93C8U, 0x9DA21CU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95EU, 0x9DE88AU, 0x9DF060U, 0x9E034EU, 0x9E1BA4U, + 0x9E2A70U, 0x9E329AU, 0x9E49D8U, 0x9E5132U, 0x9E60E6U, 0x9E780CU, 0x9E8E88U, 0x9E9662U, 0x9EA7B6U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF4U, 0x9EED20U, 0x9EF5CAU, 0x9F0028U, 0x9F18C2U, 0x9F2916U, 0x9F31FCU, 0x9F4ABEU, 0x9F5254U, + 0x9F6380U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9504U, 0x9FA4D0U, 0x9FBC3AU, 0x9FC778U, 0x9FDF92U, 0x9FEE46U, 0x9FF6ACU, + 0xA0031CU, 0xA01BF6U, 0xA02A22U, 0xA032C8U, 0xA0498AU, 0xA05160U, 0xA060B4U, 0xA0785EU, 0xA08EDAU, 0xA09630U, + 0xA0A7E4U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA6U, 0xA0ED72U, 0xA0F598U, 0xA1007AU, 0xA11890U, 0xA12944U, 0xA131AEU, + 0xA14AECU, 0xA15206U, 0xA163D2U, 0xA17B38U, 0xA18DBCU, 0xA19556U, 0xA1A482U, 0xA1BC68U, 0xA1C72AU, 0xA1DFC0U, + 0xA1EE14U, 0xA1F6FEU, 0xA205D0U, 0xA21D3AU, 0xA22CEEU, 0xA23404U, 0xA24F46U, 0xA257ACU, 0xA26678U, 0xA27E92U, + 0xA28816U, 0xA290FCU, 0xA2A128U, 0xA2B9C2U, 0xA2C280U, 0xA2DA6AU, 0xA2EBBEU, 0xA2F354U, 0xA306B6U, 0xA31E5CU, + 0xA32F88U, 0xA33762U, 0xA34C20U, 0xA354CAU, 0xA3651EU, 0xA37DF4U, 0xA38B70U, 0xA3939AU, 0xA3A24EU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90CU, 0xA3E8D8U, 0xA3F032U, 0xA40E84U, 0xA4166EU, 0xA427BAU, 0xA43F50U, 0xA44412U, 0xA45CF8U, + 0xA46D2CU, 0xA475C6U, 0xA48342U, 0xA49BA8U, 0xA4AA7CU, 0xA4B296U, 0xA4C9D4U, 0xA4D13EU, 0xA4E0EAU, 0xA4F800U, + 0xA50DE2U, 0xA51508U, 0xA524DCU, 0xA53C36U, 0xA54774U, 0xA55F9EU, 0xA56E4AU, 0xA576A0U, 0xA58024U, 0xA598CEU, + 0xA5A91AU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D258U, 0xA5E38CU, 0xA5FB66U, 0xA60848U, 0xA610A2U, 0xA62176U, 0xA6399CU, + 0xA642DEU, 0xA65A34U, 0xA66BE0U, 0xA6730AU, 0xA6858EU, 0xA69D64U, 0xA6ACB0U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F2U, + 0xA6E626U, 0xA6FECCU, 0xA70B2EU, 0xA713C4U, 0xA72210U, 0xA73AFAU, 0xA741B8U, 0xA75952U, 0xA76886U, 0xA7706CU, + 0xA786E8U, 0xA79E02U, 0xA7AFD6U, 0xA7B73CU, 0xA7CC7EU, 0xA7D494U, 0xA7E540U, 0xA7FDAAU, 0xA800C6U, 0xA8182CU, + 0xA829F8U, 0xA83112U, 0xA84A50U, 0xA852BAU, 0xA8636EU, 0xA87B84U, 0xA88D00U, 0xA895EAU, 0xA8A43EU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7CU, 0xA8EEA8U, 0xA8F642U, 0xA903A0U, 0xA91B4AU, 0xA92A9EU, 0xA93274U, 0xA94936U, 0xA951DCU, + 0xA96008U, 0xA978E2U, 0xA98E66U, 0xA9968CU, 0xA9A758U, 0xA9BFB2U, 0xA9C4F0U, 0xA9DC1AU, 0xA9EDCEU, 0xA9F524U, + 0xAA060AU, 0xAA1EE0U, 0xAA2F34U, 0xAA37DEU, 0xAA4C9CU, 0xAA5476U, 0xAA65A2U, 0xAA7D48U, 0xAA8BCCU, 0xAA9326U, + 0xAAA2F2U, 0xAABA18U, 0xAAC15AU, 0xAAD9B0U, 0xAAE864U, 0xAAF08EU, 0xAB056CU, 0xAB1D86U, 0xAB2C52U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5710U, 0xAB66C4U, 0xAB7E2EU, 0xAB88AAU, 0xAB9040U, 0xABA194U, 0xABB97EU, 0xABC23CU, 0xABDAD6U, + 0xABEB02U, 0xABF3E8U, 0xAC0D5EU, 0xAC15B4U, 0xAC2460U, 0xAC3C8AU, 0xAC47C8U, 0xAC5F22U, 0xAC6EF6U, 0xAC761CU, + 0xAC8098U, 0xAC9872U, 0xACA9A6U, 0xACB14CU, 0xACCA0EU, 0xACD2E4U, 0xACE330U, 0xACFBDAU, 0xAD0E38U, 0xAD16D2U, + 0xAD2706U, 0xAD3FECU, 0xAD44AEU, 0xAD5C44U, 0xAD6D90U, 0xAD757AU, 0xAD83FEU, 0xAD9B14U, 0xADAAC0U, 0xADB22AU, + 0xADC968U, 0xADD182U, 0xADE056U, 0xADF8BCU, 0xAE0B92U, 0xAE1378U, 0xAE22ACU, 0xAE3A46U, 0xAE4104U, 0xAE59EEU, + 0xAE683AU, 0xAE70D0U, 0xAE8654U, 0xAE9EBEU, 0xAEAF6AU, 0xAEB780U, 0xAECCC2U, 0xAED428U, 0xAEE5FCU, 0xAEFD16U, + 0xAF08F4U, 0xAF101EU, 0xAF21CAU, 0xAF3920U, 0xAF4262U, 0xAF5A88U, 0xAF6B5CU, 0xAF73B6U, 0xAF8532U, 0xAF9DD8U, + 0xAFAC0CU, 0xAFB4E6U, 0xAFCFA4U, 0xAFD74EU, 0xAFE69AU, 0xAFFE70U, 0xB004A8U, 0xB01C42U, 0xB02D96U, 0xB0357CU, + 0xB04E3EU, 0xB056D4U, 0xB06700U, 0xB07FEAU, 0xB0896EU, 0xB09184U, 0xB0A050U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB12U, + 0xB0EAC6U, 0xB0F22CU, 0xB107CEU, 0xB11F24U, 0xB12EF0U, 0xB1361AU, 0xB14D58U, 0xB155B2U, 0xB16466U, 0xB17C8CU, + 0xB18A08U, 0xB192E2U, 0xB1A336U, 0xB1BBDCU, 0xB1C09EU, 0xB1D874U, 0xB1E9A0U, 0xB1F14AU, 0xB20264U, 0xB21A8EU, + 0xB22B5AU, 0xB233B0U, 0xB248F2U, 0xB25018U, 0xB261CCU, 0xB27926U, 0xB28FA2U, 0xB29748U, 0xB2A69CU, 0xB2BE76U, + 0xB2C534U, 0xB2DDDEU, 0xB2EC0AU, 0xB2F4E0U, 0xB30102U, 0xB319E8U, 0xB3283CU, 0xB330D6U, 0xB34B94U, 0xB3537EU, + 0xB362AAU, 0xB37A40U, 0xB38CC4U, 0xB3942EU, 0xB3A5FAU, 0xB3BD10U, 0xB3C652U, 0xB3DEB8U, 0xB3EF6CU, 0xB3F786U, + 0xB40930U, 0xB411DAU, 0xB4200EU, 0xB438E4U, 0xB443A6U, 0xB45B4CU, 0xB46A98U, 0xB47272U, 0xB484F6U, 0xB49C1CU, + 0xB4ADC8U, 0xB4B522U, 0xB4CE60U, 0xB4D68AU, 0xB4E75EU, 0xB4FFB4U, 0xB50A56U, 0xB512BCU, 0xB52368U, 0xB53B82U, + 0xB540C0U, 0xB5582AU, 0xB569FEU, 0xB57114U, 0xB58790U, 0xB59F7AU, 0xB5AEAEU, 0xB5B644U, 0xB5CD06U, 0xB5D5ECU, + 0xB5E438U, 0xB5FCD2U, 0xB60FFCU, 0xB61716U, 0xB626C2U, 0xB63E28U, 0xB6456AU, 0xB65D80U, 0xB66C54U, 0xB674BEU, + 0xB6823AU, 0xB69AD0U, 0xB6AB04U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D046U, 0xB6E192U, 0xB6F978U, 0xB70C9AU, 0xB71470U, + 0xB725A4U, 0xB73D4EU, 0xB7460CU, 0xB75EE6U, 0xB76F32U, 0xB777D8U, 0xB7815CU, 0xB799B6U, 0xB7A862U, 0xB7B088U, + 0xB7CBCAU, 0xB7D320U, 0xB7E2F4U, 0xB7FA1EU, 0xB80772U, 0xB81F98U, 0xB82E4CU, 0xB836A6U, 0xB84DE4U, 0xB8550EU, + 0xB864DAU, 0xB87C30U, 0xB88AB4U, 0xB8925EU, 0xB8A38AU, 0xB8BB60U, 0xB8C022U, 0xB8D8C8U, 0xB8E91CU, 0xB8F1F6U, + 0xB90414U, 0xB91CFEU, 0xB92D2AU, 0xB935C0U, 0xB94E82U, 0xB95668U, 0xB967BCU, 0xB97F56U, 0xB989D2U, 0xB99138U, + 0xB9A0ECU, 0xB9B806U, 0xB9C344U, 0xB9DBAEU, 0xB9EA7AU, 0xB9F290U, 0xBA01BEU, 0xBA1954U, 0xBA2880U, 0xBA306AU, + 0xBA4B28U, 0xBA53C2U, 0xBA6216U, 0xBA7AFCU, 0xBA8C78U, 0xBA9492U, 0xBAA546U, 0xBABDACU, 0xBAC6EEU, 0xBADE04U, + 0xBAEFD0U, 0xBAF73AU, 0xBB02D8U, 0xBB1A32U, 0xBB2BE6U, 0xBB330CU, 0xBB484EU, 0xBB50A4U, 0xBB6170U, 0xBB799AU, + 0xBB8F1EU, 0xBB97F4U, 0xBBA620U, 0xBBBECAU, 0xBBC588U, 0xBBDD62U, 0xBBECB6U, 0xBBF45CU, 0xBC0AEAU, 0xBC1200U, + 0xBC23D4U, 0xBC3B3EU, 0xBC407CU, 0xBC5896U, 0xBC6942U, 0xBC71A8U, 0xBC872CU, 0xBC9FC6U, 0xBCAE12U, 0xBCB6F8U, + 0xBCCDBAU, 0xBCD550U, 0xBCE484U, 0xBCFC6EU, 0xBD098CU, 0xBD1166U, 0xBD20B2U, 0xBD3858U, 0xBD431AU, 0xBD5BF0U, + 0xBD6A24U, 0xBD72CEU, 0xBD844AU, 0xBD9CA0U, 0xBDAD74U, 0xBDB59EU, 0xBDCEDCU, 0xBDD636U, 0xBDE7E2U, 0xBDFF08U, + 0xBE0C26U, 0xBE14CCU, 0xBE2518U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5AU, 0xBE6F8EU, 0xBE7764U, 0xBE81E0U, 0xBE990AU, + 0xBEA8DEU, 0xBEB034U, 0xBECB76U, 0xBED39CU, 0xBEE248U, 0xBEFAA2U, 0xBF0F40U, 0xBF17AAU, 0xBF267EU, 0xBF3E94U, + 0xBF45D6U, 0xBF5D3CU, 0xBF6CE8U, 0xBF7402U, 0xBF8286U, 0xBF9A6CU, 0xBFABB8U, 0xBFB352U, 0xBFC810U, 0xBFD0FAU, + 0xBFE12EU, 0xBFF9C4U, 0xC00A4EU, 0xC012A4U, 0xC02370U, 0xC03B9AU, 0xC040D8U, 0xC05832U, 0xC069E6U, 0xC0710CU, + 0xC08788U, 0xC09F62U, 0xC0AEB6U, 0xC0B65CU, 0xC0CD1EU, 0xC0D5F4U, 0xC0E420U, 0xC0FCCAU, 0xC10928U, 0xC111C2U, + 0xC12016U, 0xC138FCU, 0xC143BEU, 0xC15B54U, 0xC16A80U, 0xC1726AU, 0xC184EEU, 0xC19C04U, 0xC1ADD0U, 0xC1B53AU, + 0xC1CE78U, 0xC1D692U, 0xC1E746U, 0xC1FFACU, 0xC20C82U, 0xC21468U, 0xC225BCU, 0xC23D56U, 0xC24614U, 0xC25EFEU, + 0xC26F2AU, 0xC277C0U, 0xC28144U, 0xC299AEU, 0xC2A87AU, 0xC2B090U, 0xC2CBD2U, 0xC2D338U, 0xC2E2ECU, 0xC2FA06U, + 0xC30FE4U, 0xC3170EU, 0xC326DAU, 0xC33E30U, 0xC34572U, 0xC35D98U, 0xC36C4CU, 0xC374A6U, 0xC38222U, 0xC39AC8U, + 0xC3AB1CU, 0xC3B3F6U, 0xC3C8B4U, 0xC3D05EU, 0xC3E18AU, 0xC3F960U, 0xC407D6U, 0xC41F3CU, 0xC42EE8U, 0xC43602U, + 0xC44D40U, 0xC455AAU, 0xC4647EU, 0xC47C94U, 0xC48A10U, 0xC492FAU, 0xC4A32EU, 0xC4BBC4U, 0xC4C086U, 0xC4D86CU, + 0xC4E9B8U, 0xC4F152U, 0xC504B0U, 0xC51C5AU, 0xC52D8EU, 0xC53564U, 0xC54E26U, 0xC556CCU, 0xC56718U, 0xC57FF2U, + 0xC58976U, 0xC5919CU, 0xC5A048U, 0xC5B8A2U, 0xC5C3E0U, 0xC5DB0AU, 0xC5EADEU, 0xC5F234U, 0xC6011AU, 0xC619F0U, + 0xC62824U, 0xC630CEU, 0xC64B8CU, 0xC65366U, 0xC662B2U, 0xC67A58U, 0xC68CDCU, 0xC69436U, 0xC6A5E2U, 0xC6BD08U, + 0xC6C64AU, 0xC6DEA0U, 0xC6EF74U, 0xC6F79EU, 0xC7027CU, 0xC71A96U, 0xC72B42U, 0xC733A8U, 0xC748EAU, 0xC75000U, + 0xC761D4U, 0xC7793EU, 0xC78FBAU, 0xC79750U, 0xC7A684U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC6U, 0xC7EC12U, 0xC7F4F8U, + 0xC80994U, 0xC8117EU, 0xC820AAU, 0xC83840U, 0xC84302U, 0xC85BE8U, 0xC86A3CU, 0xC872D6U, 0xC88452U, 0xC89CB8U, + 0xC8AD6CU, 0xC8B586U, 0xC8CEC4U, 0xC8D62EU, 0xC8E7FAU, 0xC8FF10U, 0xC90AF2U, 0xC91218U, 0xC923CCU, 0xC93B26U, + 0xC94064U, 0xC9588EU, 0xC9695AU, 0xC971B0U, 0xC98734U, 0xC99FDEU, 0xC9AE0AU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D548U, + 0xC9E49CU, 0xC9FC76U, 0xCA0F58U, 0xCA17B2U, 0xCA2666U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D24U, 0xCA6CF0U, 0xCA741AU, + 0xCA829EU, 0xCA9A74U, 0xCAABA0U, 0xCAB34AU, 0xCAC808U, 0xCAD0E2U, 0xCAE136U, 0xCAF9DCU, 0xCB0C3EU, 0xCB14D4U, + 0xCB2500U, 0xCB3DEAU, 0xCB46A8U, 0xCB5E42U, 0xCB6F96U, 0xCB777CU, 0xCB81F8U, 0xCB9912U, 0xCBA8C6U, 0xCBB02CU, + 0xCBCB6EU, 0xCBD384U, 0xCBE250U, 0xCBFABAU, 0xCC040CU, 0xCC1CE6U, 0xCC2D32U, 0xCC35D8U, 0xCC4E9AU, 0xCC5670U, + 0xCC67A4U, 0xCC7F4EU, 0xCC89CAU, 0xCC9120U, 0xCCA0F4U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB6U, 0xCCEA62U, 0xCCF288U, + 0xCD076AU, 0xCD1F80U, 0xCD2E54U, 0xCD36BEU, 0xCD4DFCU, 0xCD5516U, 0xCD64C2U, 0xCD7C28U, 0xCD8AACU, 0xCD9246U, + 0xCDA392U, 0xCDBB78U, 0xCDC03AU, 0xCDD8D0U, 0xCDE904U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2AU, 0xCE2BFEU, 0xCE3314U, + 0xCE4856U, 0xCE50BCU, 0xCE6168U, 0xCE7982U, 0xCE8F06U, 0xCE97ECU, 0xCEA638U, 0xCEBED2U, 0xCEC590U, 0xCEDD7AU, + 0xCEECAEU, 0xCEF444U, 0xCF01A6U, 0xCF194CU, 0xCF2898U, 0xCF3072U, 0xCF4B30U, 0xCF53DAU, 0xCF620EU, 0xCF7AE4U, + 0xCF8C60U, 0xCF948AU, 0xCFA55EU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1CU, 0xCFEFC8U, 0xCFF722U, 0xD00DFAU, 0xD01510U, + 0xD024C4U, 0xD03C2EU, 0xD0476CU, 0xD05F86U, 0xD06E52U, 0xD076B8U, 0xD0803CU, 0xD098D6U, 0xD0A902U, 0xD0B1E8U, + 0xD0CAAAU, 0xD0D240U, 0xD0E394U, 0xD0FB7EU, 0xD10E9CU, 0xD11676U, 0xD127A2U, 0xD13F48U, 0xD1440AU, 0xD15CE0U, + 0xD16D34U, 0xD175DEU, 0xD1835AU, 0xD19BB0U, 0xD1AA64U, 0xD1B28EU, 0xD1C9CCU, 0xD1D126U, 0xD1E0F2U, 0xD1F818U, + 0xD20B36U, 0xD213DCU, 0xD22208U, 0xD23AE2U, 0xD241A0U, 0xD2594AU, 0xD2689EU, 0xD27074U, 0xD286F0U, 0xD29E1AU, + 0xD2AFCEU, 0xD2B724U, 0xD2CC66U, 0xD2D48CU, 0xD2E558U, 0xD2FDB2U, 0xD30850U, 0xD310BAU, 0xD3216EU, 0xD33984U, + 0xD342C6U, 0xD35A2CU, 0xD36BF8U, 0xD37312U, 0xD38596U, 0xD39D7CU, 0xD3ACA8U, 0xD3B442U, 0xD3CF00U, 0xD3D7EAU, + 0xD3E63EU, 0xD3FED4U, 0xD40062U, 0xD41888U, 0xD4295CU, 0xD431B6U, 0xD44AF4U, 0xD4521EU, 0xD463CAU, 0xD47B20U, + 0xD48DA4U, 0xD4954EU, 0xD4A49AU, 0xD4BC70U, 0xD4C732U, 0xD4DFD8U, 0xD4EE0CU, 0xD4F6E6U, 0xD50304U, 0xD51BEEU, + 0xD52A3AU, 0xD532D0U, 0xD54992U, 0xD55178U, 0xD560ACU, 0xD57846U, 0xD58EC2U, 0xD59628U, 0xD5A7FCU, 0xD5BF16U, + 0xD5C454U, 0xD5DCBEU, 0xD5ED6AU, 0xD5F580U, 0xD606AEU, 0xD61E44U, 0xD62F90U, 0xD6377AU, 0xD64C38U, 0xD654D2U, + 0xD66506U, 0xD67DECU, 0xD68B68U, 0xD69382U, 0xD6A256U, 0xD6BABCU, 0xD6C1FEU, 0xD6D914U, 0xD6E8C0U, 0xD6F02AU, + 0xD705C8U, 0xD71D22U, 0xD72CF6U, 0xD7341CU, 0xD74F5EU, 0xD757B4U, 0xD76660U, 0xD77E8AU, 0xD7880EU, 0xD790E4U, + 0xD7A130U, 0xD7B9DAU, 0xD7C298U, 0xD7DA72U, 0xD7EBA6U, 0xD7F34CU, 0xD80E20U, 0xD816CAU, 0xD8271EU, 0xD83FF4U, + 0xD844B6U, 0xD85C5CU, 0xD86D88U, 0xD87562U, 0xD883E6U, 0xD89B0CU, 0xD8AAD8U, 0xD8B232U, 0xD8C970U, 0xD8D19AU, + 0xD8E04EU, 0xD8F8A4U, 0xD90D46U, 0xD915ACU, 0xD92478U, 0xD93C92U, 0xD947D0U, 0xD95F3AU, 0xD96EEEU, 0xD97604U, + 0xD98080U, 0xD9986AU, 0xD9A9BEU, 0xD9B154U, 0xD9CA16U, 0xD9D2FCU, 0xD9E328U, 0xD9FBC2U, 0xDA08ECU, 0xDA1006U, + 0xDA21D2U, 0xDA3938U, 0xDA427AU, 0xDA5A90U, 0xDA6B44U, 0xDA73AEU, 0xDA852AU, 0xDA9DC0U, 0xDAAC14U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD756U, 0xDAE682U, 0xDAFE68U, 0xDB0B8AU, 0xDB1360U, 0xDB22B4U, 0xDB3A5EU, 0xDB411CU, 0xDB59F6U, + 0xDB6822U, 0xDB70C8U, 0xDB864CU, 0xDB9EA6U, 0xDBAF72U, 0xDBB798U, 0xDBCCDAU, 0xDBD430U, 0xDBE5E4U, 0xDBFD0EU, + 0xDC03B8U, 0xDC1B52U, 0xDC2A86U, 0xDC326CU, 0xDC492EU, 0xDC51C4U, 0xDC6010U, 0xDC78FAU, 0xDC8E7EU, 0xDC9694U, + 0xDCA740U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC02U, 0xDCEDD6U, 0xDCF53CU, 0xDD00DEU, 0xDD1834U, 0xDD29E0U, 0xDD310AU, + 0xDD4A48U, 0xDD52A2U, 0xDD6376U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F2U, 0xDDA426U, 0xDDBCCCU, 0xDDC78EU, 0xDDDF64U, + 0xDDEEB0U, 0xDDF65AU, 0xDE0574U, 0xDE1D9EU, 0xDE2C4AU, 0xDE34A0U, 0xDE4FE2U, 0xDE5708U, 0xDE66DCU, 0xDE7E36U, + 0xDE88B2U, 0xDE9058U, 0xDEA18CU, 0xDEB966U, 0xDEC224U, 0xDEDACEU, 0xDEEB1AU, 0xDEF3F0U, 0xDF0612U, 0xDF1EF8U, + 0xDF2F2CU, 0xDF37C6U, 0xDF4C84U, 0xDF546EU, 0xDF65BAU, 0xDF7D50U, 0xDF8BD4U, 0xDF933EU, 0xDFA2EAU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A8U, 0xDFE87CU, 0xDFF096U, 0xE00526U, 0xE01DCCU, 0xE02C18U, 0xE034F2U, 0xE04FB0U, 0xE0575AU, + 0xE0668EU, 0xE07E64U, 0xE088E0U, 0xE0900AU, 0xE0A1DEU, 0xE0B934U, 0xE0C276U, 0xE0DA9CU, 0xE0EB48U, 0xE0F3A2U, + 0xE10640U, 0xE11EAAU, 0xE12F7EU, 0xE13794U, 0xE14CD6U, 0xE1543CU, 0xE165E8U, 0xE17D02U, 0xE18B86U, 0xE1936CU, + 0xE1A2B8U, 0xE1BA52U, 0xE1C110U, 0xE1D9FAU, 0xE1E82EU, 0xE1F0C4U, 0xE203EAU, 0xE21B00U, 0xE22AD4U, 0xE2323EU, + 0xE2497CU, 0xE25196U, 0xE26042U, 0xE278A8U, 0xE28E2CU, 0xE296C6U, 0xE2A712U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC50U, + 0xE2ED84U, 0xE2F56EU, 0xE3008CU, 0xE31866U, 0xE329B2U, 0xE33158U, 0xE34A1AU, 0xE352F0U, 0xE36324U, 0xE37BCEU, + 0xE38D4AU, 0xE395A0U, 0xE3A474U, 0xE3BC9EU, 0xE3C7DCU, 0xE3DF36U, 0xE3EEE2U, 0xE3F608U, 0xE408BEU, 0xE41054U, + 0xE42180U, 0xE4396AU, 0xE44228U, 0xE45AC2U, 0xE46B16U, 0xE473FCU, 0xE48578U, 0xE49D92U, 0xE4AC46U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D704U, 0xE4E6D0U, 0xE4FE3AU, 0xE50BD8U, 0xE51332U, 0xE522E6U, 0xE53A0CU, 0xE5414EU, 0xE559A4U, + 0xE56870U, 0xE5709AU, 0xE5861EU, 0xE59EF4U, 0xE5AF20U, 0xE5B7CAU, 0xE5CC88U, 0xE5D462U, 0xE5E5B6U, 0xE5FD5CU, + 0xE60E72U, 0xE61698U, 0xE6274CU, 0xE63FA6U, 0xE644E4U, 0xE65C0EU, 0xE66DDAU, 0xE67530U, 0xE683B4U, 0xE69B5EU, + 0xE6AA8AU, 0xE6B260U, 0xE6C922U, 0xE6D1C8U, 0xE6E01CU, 0xE6F8F6U, 0xE70D14U, 0xE715FEU, 0xE7242AU, 0xE73CC0U, + 0xE74782U, 0xE75F68U, 0xE76EBCU, 0xE77656U, 0xE780D2U, 0xE79838U, 0xE7A9ECU, 0xE7B106U, 0xE7CA44U, 0xE7D2AEU, + 0xE7E37AU, 0xE7FB90U, 0xE806FCU, 0xE81E16U, 0xE82FC2U, 0xE83728U, 0xE84C6AU, 0xE85480U, 0xE86554U, 0xE87DBEU, + 0xE88B3AU, 0xE893D0U, 0xE8A204U, 0xE8BAEEU, 0xE8C1ACU, 0xE8D946U, 0xE8E892U, 0xE8F078U, 0xE9059AU, 0xE91D70U, + 0xE92CA4U, 0xE9344EU, 0xE94F0CU, 0xE957E6U, 0xE96632U, 0xE97ED8U, 0xE9885CU, 0xE990B6U, 0xE9A162U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA20U, 0xE9EBF4U, 0xE9F31EU, 0xEA0030U, 0xEA18DAU, 0xEA290EU, 0xEA31E4U, 0xEA4AA6U, 0xEA524CU, + 0xEA6398U, 0xEA7B72U, 0xEA8DF6U, 0xEA951CU, 0xEAA4C8U, 0xEABC22U, 0xEAC760U, 0xEADF8AU, 0xEAEE5EU, 0xEAF6B4U, + 0xEB0356U, 0xEB1BBCU, 0xEB2A68U, 0xEB3282U, 0xEB49C0U, 0xEB512AU, 0xEB60FEU, 0xEB7814U, 0xEB8E90U, 0xEB967AU, + 0xEBA7AEU, 0xEBBF44U, 0xEBC406U, 0xEBDCECU, 0xEBED38U, 0xEBF5D2U, 0xEC0B64U, 0xEC138EU, 0xEC225AU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5918U, 0xEC68CCU, 0xEC7026U, 0xEC86A2U, 0xEC9E48U, 0xECAF9CU, 0xECB776U, 0xECCC34U, 0xECD4DEU, + 0xECE50AU, 0xECFDE0U, 0xED0802U, 0xED10E8U, 0xED213CU, 0xED39D6U, 0xED4294U, 0xED5A7EU, 0xED6BAAU, 0xED7340U, + 0xED85C4U, 0xED9D2EU, 0xEDACFAU, 0xEDB410U, 0xEDCF52U, 0xEDD7B8U, 0xEDE66CU, 0xEDFE86U, 0xEE0DA8U, 0xEE1542U, + 0xEE2496U, 0xEE3C7CU, 0xEE473EU, 0xEE5FD4U, 0xEE6E00U, 0xEE76EAU, 0xEE806EU, 0xEE9884U, 0xEEA950U, 0xEEB1BAU, + 0xEECAF8U, 0xEED212U, 0xEEE3C6U, 0xEEFB2CU, 0xEF0ECEU, 0xEF1624U, 0xEF27F0U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB2U, + 0xEF6D66U, 0xEF758CU, 0xEF8308U, 0xEF9BE2U, 0xEFAA36U, 0xEFB2DCU, 0xEFC99EU, 0xEFD174U, 0xEFE0A0U, 0xEFF84AU, + 0xF00292U, 0xF01A78U, 0xF02BACU, 0xF03346U, 0xF04804U, 0xF050EEU, 0xF0613AU, 0xF079D0U, 0xF08F54U, 0xF097BEU, + 0xF0A66AU, 0xF0BE80U, 0xF0C5C2U, 0xF0DD28U, 0xF0ECFCU, 0xF0F416U, 0xF101F4U, 0xF1191EU, 0xF128CAU, 0xF13020U, + 0xF14B62U, 0xF15388U, 0xF1625CU, 0xF17AB6U, 0xF18C32U, 0xF194D8U, 0xF1A50CU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4EU, + 0xF1EF9AU, 0xF1F770U, 0xF2045EU, 0xF21CB4U, 0xF22D60U, 0xF2358AU, 0xF24EC8U, 0xF25622U, 0xF267F6U, 0xF27F1CU, + 0xF28998U, 0xF29172U, 0xF2A0A6U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE4U, 0xF2EA30U, 0xF2F2DAU, 0xF30738U, 0xF31FD2U, + 0xF32E06U, 0xF336ECU, 0xF34DAEU, 0xF35544U, 0xF36490U, 0xF37C7AU, 0xF38AFEU, 0xF39214U, 0xF3A3C0U, 0xF3BB2AU, + 0xF3C068U, 0xF3D882U, 0xF3E956U, 0xF3F1BCU, 0xF40F0AU, 0xF417E0U, 0xF42634U, 0xF43EDEU, 0xF4459CU, 0xF45D76U, + 0xF46CA2U, 0xF47448U, 0xF482CCU, 0xF49A26U, 0xF4ABF2U, 0xF4B318U, 0xF4C85AU, 0xF4D0B0U, 0xF4E164U, 0xF4F98EU, + 0xF50C6CU, 0xF51486U, 0xF52552U, 0xF53DB8U, 0xF546FAU, 0xF55E10U, 0xF56FC4U, 0xF5772EU, 0xF581AAU, 0xF59940U, + 0xF5A894U, 0xF5B07EU, 0xF5CB3CU, 0xF5D3D6U, 0xF5E202U, 0xF5FAE8U, 0xF609C6U, 0xF6112CU, 0xF620F8U, 0xF63812U, + 0xF64350U, 0xF65BBAU, 0xF66A6EU, 0xF67284U, 0xF68400U, 0xF69CEAU, 0xF6AD3EU, 0xF6B5D4U, 0xF6CE96U, 0xF6D67CU, + 0xF6E7A8U, 0xF6FF42U, 0xF70AA0U, 0xF7124AU, 0xF7239EU, 0xF73B74U, 0xF74036U, 0xF758DCU, 0xF76908U, 0xF771E2U, + 0xF78766U, 0xF79F8CU, 0xF7AE58U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51AU, 0xF7E4CEU, 0xF7FC24U, 0xF80148U, 0xF819A2U, + 0xF82876U, 0xF8309CU, 0xF84BDEU, 0xF85334U, 0xF862E0U, 0xF87A0AU, 0xF88C8EU, 0xF89464U, 0xF8A5B0U, 0xF8BD5AU, + 0xF8C618U, 0xF8DEF2U, 0xF8EF26U, 0xF8F7CCU, 0xF9022EU, 0xF91AC4U, 0xF92B10U, 0xF933FAU, 0xF948B8U, 0xF95052U, + 0xF96186U, 0xF9796CU, 0xF98FE8U, 0xF99702U, 0xF9A6D6U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD94U, 0xF9EC40U, 0xF9F4AAU, + 0xFA0784U, 0xFA1F6EU, 0xFA2EBAU, 0xFA3650U, 0xFA4D12U, 0xFA55F8U, 0xFA642CU, 0xFA7CC6U, 0xFA8A42U, 0xFA92A8U, + 0xFAA37CU, 0xFABB96U, 0xFAC0D4U, 0xFAD83EU, 0xFAE9EAU, 0xFAF100U, 0xFB04E2U, 0xFB1C08U, 0xFB2DDCU, 0xFB3536U, + 0xFB4E74U, 0xFB569EU, 0xFB674AU, 0xFB7FA0U, 0xFB8924U, 0xFB91CEU, 0xFBA01AU, 0xFBB8F0U, 0xFBC3B2U, 0xFBDB58U, + 0xFBEA8CU, 0xFBF266U, 0xFC0CD0U, 0xFC143AU, 0xFC25EEU, 0xFC3D04U, 0xFC4646U, 0xFC5EACU, 0xFC6F78U, 0xFC7792U, + 0xFC8116U, 0xFC99FCU, 0xFCA828U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36AU, 0xFCE2BEU, 0xFCFA54U, 0xFD0FB6U, 0xFD175CU, + 0xFD2688U, 0xFD3E62U, 0xFD4520U, 0xFD5DCAU, 0xFD6C1EU, 0xFD74F4U, 0xFD8270U, 0xFD9A9AU, 0xFDAB4EU, 0xFDB3A4U, + 0xFDC8E6U, 0xFDD00CU, 0xFDE1D8U, 0xFDF932U, 0xFE0A1CU, 0xFE12F6U, 0xFE2322U, 0xFE3BC8U, 0xFE408AU, 0xFE5860U, + 0xFE69B4U, 0xFE715EU, 0xFE87DAU, 0xFE9F30U, 0xFEAEE4U, 0xFEB60EU, 0xFECD4CU, 0xFED5A6U, 0xFEE472U, 0xFEFC98U, + 0xFF097AU, 0xFF1190U, 0xFF2044U, 0xFF38AEU, 0xFF43ECU, 0xFF5B06U, 0xFF6AD2U, 0xFF7238U, 0xFF84BCU, 0xFF9C56U, + 0xFFAD82U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C0U, 0xFFE714U, 0xFFFFFEU}; + +static const unsigned int ENCODING_TABLE_24128[] = { + 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU, + 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U, + 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU, + 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU, + 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U, + 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U, + 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U, + 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU, + 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U, + 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U, + 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU, + 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U, + 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U, + 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U, + 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U, + 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U, + 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU, + 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U, + 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU, + 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U, + 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU, + 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U, + 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U, + 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU, + 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U, + 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U, + 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU, + 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U, + 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U, + 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU, + 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U, + 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU, + 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U, + 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU, + 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U, + 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U, + 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU, + 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U, + 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U, + 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU, + 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U, + 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U, + 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U, + 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU, + 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU, + 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U, + 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U, + 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU, + 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U, + 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU, + 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U, + 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U, + 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU, + 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U, + 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU, + 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U, + 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U, + 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU, + 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U, + 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU, + 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU, + 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U, + 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU, + 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU, + 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U, + 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU, + 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U, + 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU, + 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U, + 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U, + 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU, + 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U, + 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U, + 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU, + 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U, + 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU, + 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU, + 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U, + 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU, + 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U, + 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U, + 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U, + 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U, + 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU, + 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U, + 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U, + 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU, + 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U, + 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U, + 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U, + 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U, + 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U, + 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU, + 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U, + 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U, + 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU, + 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U, + 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU, + 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U, + 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U, + 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU, + 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U, + 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U, + 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U, + 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U, + 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U, + 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U, + 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU, + 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U, + 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U, + 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU, + 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U, + 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U, + 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U, + 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U, + 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU, + 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U, + 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU, + 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU, + 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU, + 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U, + 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U, + 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU, + 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U, + 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U, + 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU, + 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U, + 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU, + 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U, + 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU, + 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU, + 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U, + 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU, + 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU, + 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U, + 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU, + 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U, + 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U, + 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU, + 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U, + 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU, + 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U, + 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU, + 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U, + 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU, + 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U, + 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U, + 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U, + 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U, + 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU, + 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U, + 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU, + 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U, + 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U, + 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U, + 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U, + 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU, + 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U, + 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U, + 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU, + 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U, + 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U, + 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU, + 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U, + 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU, + 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U, + 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU, + 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U, + 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U, + 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU, + 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U, + 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U, + 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU, + 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U, + 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U, + 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU, + 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U, + 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU, + 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U, + 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU, + 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U, + 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U, + 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U, + 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U, + 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U, + 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU, + 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U, + 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU, + 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U, + 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U, + 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU, + 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U, + 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU, + 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U, + 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU, + 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U, + 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U, + 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU, + 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U, + 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU, + 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U, + 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U, + 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU, + 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U, + 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU, + 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU, + 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U, + 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU, + 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U, + 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U, + 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U, + 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U, + 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU, + 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U, + 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU, + 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U, + 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U, + 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU, + 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU, + 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U, + 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU, + 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U, + 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U, + 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U, + 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U, + 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU, + 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U, + 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU, + 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U, + 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U, + 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U, + 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U, + 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U, + 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU, + 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU, + 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U, + 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU, + 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U, + 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U, + 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U, + 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U, + 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U, + 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU, + 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U, + 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU, + 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U, + 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U, + 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU, + 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U, + 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U, + 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU, + 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU, + 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U, + 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU, + 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU, + 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU, + 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U, + 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U, + 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U, + 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU, + 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U, + 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU, + 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU, + 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U, + 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U, + 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU, + 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U, + 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU, + 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU, + 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U, + 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU, + 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U, + 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU, + 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U, + 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU, + 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU, + 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U, + 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U, + 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU, + 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U, + 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U, + 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU, + 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U, + 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU, + 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U, + 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U, + 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U, + 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U, + 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU, + 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U, + 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU, + 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU, + 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U, + 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU, + 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU, + 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U, + 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U, + 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U, + 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU, + 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U, + 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U, + 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U, + 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U, + 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U, + 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U, + 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U, + 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U, + 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU, + 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U, + 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU, + 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U, + 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U, + 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U, + 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U, + 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU, + 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U, + 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U, + 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U, + 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U, + 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U, + 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU, + 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U, + 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU, + 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U, + 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU, + 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U, + 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U, + 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU, + 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U, + 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U, + 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU, + 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U, + 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U, + 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U, + 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU, + 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U, + 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU, + 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U, + 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U, + 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U, + 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU, + 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U, + 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU, + 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU, + 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U, + 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU, + 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U, + 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U, + 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU, + 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU, + 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U, + 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU, + 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU, + 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U, + 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU, + 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U, + 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU, + 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU, + 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U, + 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U, + 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU, + 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U, + 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU, + 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU, + 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U, + 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU, + 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU, + 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U, + 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU, + 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U, + 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU, + 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U, + 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U, + 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU, + 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U, + 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U, + 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU, + 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U, + 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU, + 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U, + 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U, + 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U, + 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U, + 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU, + 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U, + 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U, + 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U, + 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U, + 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU}; + +static const unsigned int DECODING_TABLE_23127[] = { + 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, + 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, + 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, + 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, + 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, + 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, + 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, + 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, + 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, + 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, + 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, + 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, + 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, + 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, + 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, + 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, + 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, + 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, + 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, + 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, + 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, + 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, + 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, + 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, + 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, + 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, + 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, + 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, + 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, + 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, + 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, + 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, + 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, + 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, + 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, + 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, + 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, + 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, + 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, + 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, + 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, + 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, + 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, + 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, + 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, + 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, + 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, + 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, + 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, + 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, + 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, + 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, + 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, + 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, + 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, + 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, + 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, + 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, + 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, + 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, + 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, + 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, + 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, + 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, + 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, + 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, + 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, + 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, + 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, + 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, + 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, + 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, + 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, + 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, + 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, + 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, + 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, + 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, + 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, + 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, + 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, + 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, + 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, + 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, + 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, + 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, + 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, + 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, + 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, + 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, + 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, + 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, + 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, + 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, + 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, + 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, + 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, + 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, + 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, + 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, + 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, + 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, + 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, + 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, + 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, + 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, + 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, + 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, + 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, + 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, + 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, + 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, + 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, + 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, + 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, + 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, + 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, + 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, + 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, + 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, + 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, + 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, + 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, + 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, + 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, + 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, + 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, + 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, + 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, + 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, + 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, + 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, + 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, + 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, + 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, + 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, + 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, + 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, + 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, + 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, + 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, + 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, + 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, + 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, + 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, + 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, + 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, + 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, + 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, + 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, + 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, + 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, + 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, + 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, + 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, + 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, + 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, + 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, + 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, + 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, + 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, + 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, + 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, + 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, + 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, + 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, + 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, + 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, + 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, + 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, + 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, + 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, + 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, + 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, + 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, + 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, + 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, + 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, + 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, + 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, + 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, + 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, + 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, + 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, + 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, + 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, + 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, + 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, + 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, + 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, + 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, + 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, + 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, + 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, + 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, + 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, + 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, + 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, + 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, + 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, + 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, + 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, + 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, + 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, + 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U}; + +#define X22 0x00400000 /* vector representation of X^{22} */ +#define X11 0x00000800 /* vector representation of X^{11} */ +#define MASK12 0xfffff800 /* auxiliary vector for testing */ +#define GENPOL 0x00000c75 /* generator polinomial, g(x) */ + +static unsigned int get_syndrome_23127(unsigned int pattern) +/* + * Compute the syndrome corresponding to the given pattern, i.e., the + * remainder after dividing the pattern (when considering it as the vector + * representation of a polynomial) by the generator polynomial, GENPOL. + * In the program this pattern has several meanings: (1) pattern = infomation + * bits, when constructing the encoding table; (2) pattern = error pattern, + * when constructing the decoding table; and (3) pattern = received vector, to + * obtain its syndrome in decoding. + */ +{ + unsigned int aux = X22; + + if (pattern >= X11) { + while (pattern & MASK12) { + while (!(aux & pattern)) + aux = aux >> 1; + + pattern ^= (aux / X11) * GENPOL; + } + } + + return pattern; +} + +unsigned int CGolay24128::encode23127(unsigned int data) +{ + return ENCODING_TABLE_23127[data]; +} + +unsigned int CGolay24128::encode24128(unsigned int data) +{ + return ENCODING_TABLE_24128[data]; +} + +unsigned int CGolay24128::decode23127(unsigned int code) +{ + unsigned int syndrome = ::get_syndrome_23127(code); + unsigned int error_pattern = DECODING_TABLE_23127[syndrome]; + + code ^= error_pattern; + + return code >> 11; +} + +unsigned int CGolay24128::decode24128(unsigned int code) +{ + return decode23127(code >> 1); +} + +unsigned int CGolay24128::decode24128(unsigned char* bytes) +{ + assert(bytes != NULL); + + unsigned int code = bytes[0U]; + code <<= 8; + code |= bytes[1U]; + code <<= 8; + code |= bytes[2U]; + + return decode23127(code >> 1); +} diff --git a/DGIdGateway/Golay24128.h b/DGIdGateway/Golay24128.h new file mode 100644 index 0000000..1ac7852 --- /dev/null +++ b/DGIdGateway/Golay24128.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef Golay24128_H +#define Golay24128_H + +class CGolay24128 { +public: + static unsigned int encode23127(unsigned int data); + static unsigned int encode24128(unsigned int data); + + static unsigned int decode23127(unsigned int code); + static unsigned int decode24128(unsigned int code); + static unsigned int decode24128(unsigned char* bytes); +}; + +#endif diff --git a/DGIdGateway/Log.cpp b/DGIdGateway/Log.cpp new file mode 100644 index 0000000..fc37ebf --- /dev/null +++ b/DGIdGateway/Log.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Log.h" + +#if defined(_WIN32) || defined(_WIN64) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +static unsigned int m_fileLevel = 2U; +static std::string m_filePath; +static std::string m_fileRoot; + +static FILE* m_fpLog = NULL; + +static unsigned int m_displayLevel = 2U; + +static struct tm m_tm; + +static char LEVELS[] = " DMIWEF"; + +static bool LogOpen() +{ + if (m_fileLevel == 0U) + return true; + + time_t now; + ::time(&now); + + struct tm* tm = ::gmtime(&now); + + if (tm->tm_mday == m_tm.tm_mday && tm->tm_mon == m_tm.tm_mon && tm->tm_year == m_tm.tm_year) { + if (m_fpLog != NULL) + return true; + } else { + if (m_fpLog != NULL) + ::fclose(m_fpLog); + } + + char filename[100U]; +#if defined(_WIN32) || defined(_WIN64) + ::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +#else + ::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +#endif + + m_fpLog = ::fopen(filename, "a+t"); + m_tm = *tm; + + return m_fpLog != NULL; +} + +bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel) +{ + m_filePath = filePath; + m_fileRoot = fileRoot; + m_fileLevel = fileLevel; + m_displayLevel = displayLevel; + return ::LogOpen(); +} + +void LogFinalise() +{ + if (m_fpLog != NULL) + ::fclose(m_fpLog); +} + +void Log(unsigned int level, const char* fmt, ...) +{ + assert(fmt != NULL); + + char buffer[300U]; +#if defined(_WIN32) || defined(_WIN64) + SYSTEMTIME st; + ::GetSystemTime(&st); + + ::sprintf(buffer, "%c: %04u-%02u-%02u %02u:%02u:%02u.%03u ", LEVELS[level], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); +#else + struct timeval now; + ::gettimeofday(&now, NULL); + + struct tm* tm = ::gmtime(&now.tv_sec); + + ::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000U); +#endif + + va_list vl; + va_start(vl, fmt); + + ::vsprintf(buffer + ::strlen(buffer), fmt, vl); + + va_end(vl); + + if (level >= m_fileLevel && m_fileLevel != 0U) { + bool ret = ::LogOpen(); + if (!ret) + return; + + ::fprintf(m_fpLog, "%s\n", buffer); + ::fflush(m_fpLog); + } + + if (level >= m_displayLevel && m_displayLevel != 0U) { + ::fprintf(stdout, "%s\n", buffer); + ::fflush(stdout); + } + + if (level == 6U) { // Fatal + ::fclose(m_fpLog); + exit(1); + } +} diff --git a/DGIdGateway/Log.h b/DGIdGateway/Log.h new file mode 100644 index 0000000..d671ef9 --- /dev/null +++ b/DGIdGateway/Log.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(LOG_H) +#define LOG_H + +#include + +#define LogDebug(fmt, ...) Log(1U, fmt, ##__VA_ARGS__) +#define LogMessage(fmt, ...) Log(2U, fmt, ##__VA_ARGS__) +#define LogInfo(fmt, ...) Log(3U, fmt, ##__VA_ARGS__) +#define LogWarning(fmt, ...) Log(4U, fmt, ##__VA_ARGS__) +#define LogError(fmt, ...) Log(5U, fmt, ##__VA_ARGS__) +#define LogFatal(fmt, ...) Log(6U, fmt, ##__VA_ARGS__) + +extern void Log(unsigned int level, const char* fmt, ...); + +extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel); +extern void LogFinalise(); + +#endif diff --git a/DGIdGateway/Makefile b/DGIdGateway/Makefile new file mode 100644 index 0000000..43e868a --- /dev/null +++ b/DGIdGateway/Makefile @@ -0,0 +1,30 @@ +CC = gcc +CXX = g++ + +# Use the following CFLAGS and LIBS if you don't want to use gpsd. +CFLAGS = -g -O3 -Wall -std=c++0x -pthread +LIBS = -lm -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread +#LIBS = -lm -lpthread -lgps + +LDFLAGS = -g + +OBJECTS = APRSWriter.o Conf.o CRC.o DGIdGateway.o DGIdNetwork.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \ + UDPSocket.o Utils.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o YSFReflectors.o + +all: DGIdGateway + +DGIdGateway: $(OBJECTS) + $(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o DGIdGateway + +%.o: %.cpp + $(CXX) $(CFLAGS) -c -o $@ $< + +install: + install -m 755 DGIdGateway /usr/local/bin/ + +clean: + $(RM) DGIdGateway *.o *.d *.bak *~ + diff --git a/DGIdGateway/README.md b/DGIdGateway/README.md new file mode 100644 index 0000000..bd00ca9 --- /dev/null +++ b/DGIdGateway/README.md @@ -0,0 +1,12 @@ +The YSF Gateway interfaces the MMDVM Host to the open source YSF Reflector system using the standard Wires-X commands from the radio. It also gateways position information to aprs.fi if sent. + +The file YSFHosts.txt holds information about the reflectors available, and the gateway has the ability to reload this file at intervals to ensure that it is always up to date. + +It is expected that a call to retrieve this file is done via some mechanism such as cron on Linux. The URLs to retrieve the latest file are [http://register.ysfreflector.de/export_csv.php](http://register.ysfreflector.de/export_csv.php), or [https://register.ysfreflector.de/export_csv.php](https://register.ysfreflector.de/export_csv.php). + +An example would be following line in root's crontab, that fetches the reflector-list each 5 minutes: +> sudo crontab -e + +add following line: + +> */5 * * * * wget -O /var/YSFGateway/YSFHosts.txt http://register.ysfreflector.de/export_csv.php diff --git a/DGIdGateway/RingBuffer.h b/DGIdGateway/RingBuffer.h new file mode 100644 index 0000000..7805005 --- /dev/null +++ b/DGIdGateway/RingBuffer.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2006-2009,2012,2013,2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef RingBuffer_H +#define RingBuffer_H + +#include "Log.h" + +#include +#include +#include + +template class CRingBuffer { +public: + CRingBuffer(unsigned int length, const char* name) : + m_length(length), + m_name(name), + m_buffer(NULL), + m_iPtr(0U), + m_oPtr(0U) + { + assert(length > 0U); + assert(name != NULL); + + m_buffer = new T[length]; + + ::memset(m_buffer, 0x00, m_length * sizeof(T)); + } + + ~CRingBuffer() + { + delete[] m_buffer; + } + + bool addData(const T* buffer, unsigned int nSamples) + { + if (nSamples >= freeSpace()) { + LogError("**** Overflow in %s ring buffer, %u >= %u", m_name, nSamples, freeSpace()); + return false; + } + + for (unsigned int i = 0U; i < nSamples; i++) { + m_buffer[m_iPtr++] = buffer[i]; + + if (m_iPtr == m_length) + m_iPtr = 0U; + } + + return true; + } + + bool getData(T* buffer, unsigned int nSamples) + { + if (dataSize() < nSamples) { + LogError("**** Underflow in %s ring buffer, %u < %u", m_name, dataSize(), nSamples); + return false; + } + + for (unsigned int i = 0U; i < nSamples; i++) { + buffer[i] = m_buffer[m_oPtr++]; + + if (m_oPtr == m_length) + m_oPtr = 0U; + } + + return true; + } + + bool peek(T* buffer, unsigned int nSamples) + { + if (dataSize() < nSamples) { + LogError("**** Underflow peek in %s ring buffer, %u < %u", m_name, dataSize(), nSamples); + return false; + } + + unsigned int ptr = m_oPtr; + for (unsigned int i = 0U; i < nSamples; i++) { + buffer[i] = m_buffer[ptr++]; + + if (ptr == m_length) + ptr = 0U; + } + + return true; + } + + void clear() + { + m_iPtr = 0U; + m_oPtr = 0U; + + ::memset(m_buffer, 0x00, m_length * sizeof(T)); + } + + unsigned int freeSpace() const + { + if (m_oPtr == m_iPtr) + return m_length; + + if (m_oPtr > m_iPtr) + return m_oPtr - m_iPtr; + + return (m_length + m_oPtr) - m_iPtr; + } + + unsigned int dataSize() const + { + return m_length - freeSpace(); + } + + bool hasSpace(unsigned int length) const + { + return freeSpace() > length; + } + + bool hasData() const + { + return m_oPtr != m_iPtr; + } + + bool isEmpty() const + { + return m_oPtr == m_iPtr; + } + +private: + unsigned int m_length; + const char* m_name; + T* m_buffer; + unsigned int m_iPtr; + unsigned int m_oPtr; +}; + +#endif diff --git a/DGIdGateway/StopWatch.cpp b/DGIdGateway/StopWatch.cpp new file mode 100644 index 0000000..481241b --- /dev/null +++ b/DGIdGateway/StopWatch.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "StopWatch.h" + +#if defined(_WIN32) || defined(_WIN64) + +CStopWatch::CStopWatch() : +m_frequencyS(), +m_frequencyMS(), +m_start() +{ + ::QueryPerformanceFrequency(&m_frequencyS); + + m_frequencyMS.QuadPart = m_frequencyS.QuadPart / 1000ULL; +} + +CStopWatch::~CStopWatch() +{ +} + +unsigned long long CStopWatch::time() const +{ + LARGE_INTEGER now; + ::QueryPerformanceCounter(&now); + + return (unsigned long long)(now.QuadPart / m_frequencyMS.QuadPart); +} + +unsigned long long CStopWatch::start() +{ + ::QueryPerformanceCounter(&m_start); + + return (unsigned long long)(m_start.QuadPart / m_frequencyS.QuadPart); +} + +unsigned int CStopWatch::elapsed() +{ + LARGE_INTEGER now; + ::QueryPerformanceCounter(&now); + + LARGE_INTEGER temp; + temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000; + + return (unsigned int)(temp.QuadPart / m_frequencyS.QuadPart); +} + +#else + +#include +#include + +CStopWatch::CStopWatch() : +m_startMS(0ULL) +{ +} + +CStopWatch::~CStopWatch() +{ +} + +unsigned long long CStopWatch::time() const +{ + struct timeval now; + ::gettimeofday(&now, NULL); + + return now.tv_sec * 1000ULL + now.tv_usec / 1000ULL; +} + +unsigned long long CStopWatch::start() +{ + struct timespec now; + ::clock_gettime(CLOCK_MONOTONIC, &now); + + m_startMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL; + + return m_startMS; +} + +unsigned int CStopWatch::elapsed() +{ + struct timespec now; + ::clock_gettime(CLOCK_MONOTONIC, &now); + + unsigned long long nowMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL; + + return nowMS - m_startMS; +} + +#endif diff --git a/DGIdGateway/StopWatch.h b/DGIdGateway/StopWatch.h new file mode 100644 index 0000000..3f8fa19 --- /dev/null +++ b/DGIdGateway/StopWatch.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(STOPWATCH_H) +#define STOPWATCH_H + +#if defined(_WIN32) || defined(_WIN64) +#include +#else +#include +#endif + +class CStopWatch +{ +public: + CStopWatch(); + ~CStopWatch(); + + unsigned long long time() const; + + unsigned long long start(); + unsigned int elapsed(); + +private: +#if defined(_WIN32) || defined(_WIN64) + LARGE_INTEGER m_frequencyS; + LARGE_INTEGER m_frequencyMS; + LARGE_INTEGER m_start; +#else + unsigned long long m_startMS; +#endif +}; + +#endif diff --git a/DGIdGateway/Sync.cpp b/DGIdGateway/Sync.cpp new file mode 100644 index 0000000..c8d4d52 --- /dev/null +++ b/DGIdGateway/Sync.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Sync.h" + +#include "YSFDefines.h" + +#include +#include +#include + +void CSync::add(unsigned char* data) +{ + assert(data != NULL); + + ::memcpy(data, YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); +} diff --git a/DGIdGateway/Sync.h b/DGIdGateway/Sync.h new file mode 100644 index 0000000..860ac65 --- /dev/null +++ b/DGIdGateway/Sync.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(SYNC_H) +#define SYNC_H + +class CSync +{ +public: + static void add(unsigned char* data); + +private: +}; + +#endif diff --git a/DGIdGateway/Thread.cpp b/DGIdGateway/Thread.cpp new file mode 100644 index 0000000..b334436 --- /dev/null +++ b/DGIdGateway/Thread.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Thread.h" + +#if defined(_WIN32) || defined(_WIN64) + +CThread::CThread() : +m_handle() +{ +} + +CThread::~CThread() +{ +} + +bool CThread::run() +{ + m_handle = ::CreateThread(NULL, 0, &helper, this, 0, NULL); + + return m_handle != NULL; +} + + +void CThread::wait() +{ + ::WaitForSingleObject(m_handle, INFINITE); + + ::CloseHandle(m_handle); +} + + +DWORD CThread::helper(LPVOID arg) +{ + CThread* p = (CThread*)arg; + + p->entry(); + + return 0UL; +} + +void CThread::sleep(unsigned int ms) +{ + ::Sleep(ms); +} + +#else + +#include + +CThread::CThread() : +m_thread() +{ +} + +CThread::~CThread() +{ +} + +bool CThread::run() +{ + return ::pthread_create(&m_thread, NULL, helper, this) == 0; +} + + +void CThread::wait() +{ + ::pthread_join(m_thread, NULL); +} + + +void* CThread::helper(void* arg) +{ + CThread* p = (CThread*)arg; + + p->entry(); + + return NULL; +} + +void CThread::sleep(unsigned int ms) +{ + ::usleep(ms * 1000); +} + +#endif diff --git a/DGIdGateway/Thread.h b/DGIdGateway/Thread.h new file mode 100644 index 0000000..352d938 --- /dev/null +++ b/DGIdGateway/Thread.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(THREAD_H) +#define THREAD_H + +#if defined(_WIN32) || defined(_WIN64) +#include +#else +#include +#endif + +class CThread +{ +public: + CThread(); + virtual ~CThread(); + + virtual bool run(); + + virtual void entry() = 0; + + virtual void wait(); + + static void sleep(unsigned int ms); + +private: +#if defined(_WIN32) || defined(_WIN64) + HANDLE m_handle; +#else + pthread_t m_thread; +#endif + +#if defined(_WIN32) || defined(_WIN64) + static DWORD __stdcall helper(LPVOID arg); +#else + static void* helper(void* arg); +#endif +}; + +#endif diff --git a/DGIdGateway/Timer.cpp b/DGIdGateway/Timer.cpp new file mode 100644 index 0000000..53956e4 --- /dev/null +++ b/DGIdGateway/Timer.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009,2010,2015 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Timer.h" + +#include +#include + +CTimer::CTimer(unsigned int ticksPerSec, unsigned int secs, unsigned int msecs) : +m_ticksPerSec(ticksPerSec), +m_timeout(0U), +m_timer(0U) +{ + assert(ticksPerSec > 0U); + + if (secs > 0U || msecs > 0U) { + // m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U; + unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec; + m_timeout = (unsigned int)(temp / 1000ULL + 1ULL); + } +} + +CTimer::~CTimer() +{ +} + +void CTimer::setTimeout(unsigned int secs, unsigned int msecs) +{ + if (secs > 0U || msecs > 0U) { + // m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U; + unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec; + m_timeout = (unsigned int)(temp / 1000ULL + 1ULL); + } else { + m_timeout = 0U; + m_timer = 0U; + } +} + +unsigned int CTimer::getTimeout() const +{ + if (m_timeout == 0U) + return 0U; + + return (m_timeout - 1U) / m_ticksPerSec; +} + +unsigned int CTimer::getTimer() const +{ + if (m_timer == 0U) + return 0U; + + return (m_timer - 1U) / m_ticksPerSec; +} diff --git a/DGIdGateway/Timer.h b/DGIdGateway/Timer.h new file mode 100644 index 0000000..87d68f5 --- /dev/null +++ b/DGIdGateway/Timer.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009,2010,2011,2014 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef Timer_H +#define Timer_H + +class CTimer { +public: + CTimer(unsigned int ticksPerSec, unsigned int secs = 0U, unsigned int msecs = 0U); + ~CTimer(); + + void setTimeout(unsigned int secs, unsigned int msecs = 0U); + + unsigned int getTimeout() const; + unsigned int getTimer() const; + + unsigned int getRemaining() + { + if (m_timeout == 0U || m_timer == 0U) + return 0U; + + if (m_timer >= m_timeout) + return 0U; + + return (m_timeout - m_timer) / m_ticksPerSec; + } + + bool isRunning() + { + return m_timer > 0U; + } + + void start(unsigned int secs, unsigned int msecs = 0U) + { + setTimeout(secs, msecs); + + start(); + } + + void start() + { + if (m_timeout > 0U) + m_timer = 1U; + } + + void stop() + { + m_timer = 0U; + } + + bool hasExpired() + { + if (m_timeout == 0U || m_timer == 0U) + return false; + + if (m_timer >= m_timeout) + return true; + + return false; + } + + void clock(unsigned int ticks = 1U) + { + if (m_timer > 0U && m_timeout > 0U) + m_timer += ticks; + } + +private: + unsigned int m_ticksPerSec; + unsigned int m_timeout; + unsigned int m_timer; +}; + +#endif diff --git a/DGIdGateway/UDPSocket.cpp b/DGIdGateway/UDPSocket.cpp new file mode 100644 index 0000000..733dd20 --- /dev/null +++ b/DGIdGateway/UDPSocket.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2006-2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "UDPSocket.h" +#include "Log.h" + +#include + +#if !defined(_WIN32) && !defined(_WIN64) +#include +#include +#endif + + +CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) : +m_address(address), +m_port(port), +m_fd(-1) +{ + assert(!address.empty()); + +#if defined(_WIN32) || defined(_WIN64) + WSAData data; + int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); + if (wsaRet != 0) + LogError("Error from WSAStartup"); +#endif +} + +CUDPSocket::CUDPSocket(unsigned int port) : +m_address(), +m_port(port), +m_fd(-1) +{ +#if defined(_WIN32) || defined(_WIN64) + WSAData data; + int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); + if (wsaRet != 0) + LogError("Error from WSAStartup"); +#endif +} + +CUDPSocket::~CUDPSocket() +{ +#if defined(_WIN32) || defined(_WIN64) + ::WSACleanup(); +#endif +} + +in_addr CUDPSocket::lookup(const std::string& hostname) +{ + in_addr addr; +#if defined(_WIN32) || defined(_WIN64) + unsigned long address = ::inet_addr(hostname.c_str()); + if (address != INADDR_NONE && address != INADDR_ANY) { + addr.s_addr = address; + return addr; + } + + struct hostent* hp = ::gethostbyname(hostname.c_str()); + if (hp != NULL) { + ::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr)); + return addr; + } + + LogError("Cannot find address for host %s", hostname.c_str()); + + addr.s_addr = INADDR_NONE; + return addr; +#else + in_addr_t address = ::inet_addr(hostname.c_str()); + if (address != in_addr_t(-1)) { + addr.s_addr = address; + return addr; + } + + struct hostent* hp = ::gethostbyname(hostname.c_str()); + if (hp != NULL) { + ::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr)); + return addr; + } + + LogError("Cannot find address for host %s", hostname.c_str()); + + addr.s_addr = INADDR_NONE; + return addr; +#endif +} + +bool CUDPSocket::open() +{ + m_fd = ::socket(PF_INET, SOCK_DGRAM, 0); + if (m_fd < 0) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Cannot create the UDP socket, err: %lu", ::GetLastError()); +#else + LogError("Cannot create the UDP socket, err: %d", errno); +#endif + return false; + } + + if (m_port > 0U) { + sockaddr_in addr; + ::memset(&addr, 0x00, sizeof(sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(m_port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!m_address.empty()) { +#if defined(_WIN32) || defined(_WIN64) + addr.sin_addr.s_addr = ::inet_addr(m_address.c_str()); +#else + addr.sin_addr.s_addr = ::inet_addr(m_address.c_str()); +#endif + if (addr.sin_addr.s_addr == INADDR_NONE) { + LogError("The local address is invalid - %s", m_address.c_str()); + return false; + } + } + + int reuse = 1; + if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError()); +#else + LogError("Cannot set the UDP socket option, err: %d", errno); +#endif + return false; + } + + if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Cannot bind the UDP address, err: %lu", ::GetLastError()); +#else + LogError("Cannot bind the UDP address, err: %d", errno); +#endif + return false; + } + + LogInfo("Opening UDP port on %u", m_port); + } + + return true; +} + +int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port) +{ + assert(buffer != NULL); + assert(length > 0U); + + // Check that the readfrom() won't block + fd_set readFds; + FD_ZERO(&readFds); +#if defined(_WIN32) || defined(_WIN64) + FD_SET((unsigned int)m_fd, &readFds); +#else + FD_SET(m_fd, &readFds); +#endif + + // Return immediately + timeval tv; + tv.tv_sec = 0L; + tv.tv_usec = 0L; + + int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv); + if (ret < 0) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Error returned from UDP select, err: %lu", ::GetLastError()); +#else + LogError("Error returned from UDP select, err: %d", errno); +#endif + return -1; + } + + if (ret == 0) + return 0; + + sockaddr_in addr; +#if defined(_WIN32) || defined(_WIN64) + int size = sizeof(sockaddr_in); +#else + socklen_t size = sizeof(sockaddr_in); +#endif + +#if defined(_WIN32) || defined(_WIN64) + int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size); +#else + ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size); +#endif + if (len <= 0) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Error returned from recvfrom, err: %lu", ::GetLastError()); +#else + LogError("Error returned from recvfrom, err: %d", errno); +#endif + return -1; + } + + address = addr.sin_addr; + port = ntohs(addr.sin_port); + + return len; +} + +bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port) +{ + assert(buffer != NULL); + assert(length > 0U); + + sockaddr_in addr; + ::memset(&addr, 0x00, sizeof(sockaddr_in)); + + addr.sin_family = AF_INET; + addr.sin_addr = address; + addr.sin_port = htons(port); + +#if defined(_WIN32) || defined(_WIN64) + int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in)); +#else + ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in)); +#endif + if (ret < 0) { +#if defined(_WIN32) || defined(_WIN64) + LogError("Error returned from sendto, err: %lu", ::GetLastError()); +#else + LogError("Error returned from sendto, err: %d", errno); +#endif + return false; + } + +#if defined(_WIN32) || defined(_WIN64) + if (ret != int(length)) + return false; +#else + if (ret != ssize_t(length)) + return false; +#endif + + return true; +} + +void CUDPSocket::close() +{ +#if defined(_WIN32) || defined(_WIN64) + ::closesocket(m_fd); +#else + ::close(m_fd); +#endif +} diff --git a/DGIdGateway/UDPSocket.h b/DGIdGateway/UDPSocket.h new file mode 100644 index 0000000..e0af272 --- /dev/null +++ b/DGIdGateway/UDPSocket.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef UDPSocket_H +#define UDPSocket_H + +#include + +#if !defined(_WIN32) && !defined(_WIN64) +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +class CUDPSocket { +public: + CUDPSocket(const std::string& address, unsigned int port = 0U); + CUDPSocket(unsigned int port = 0U); + ~CUDPSocket(); + + bool open(); + + int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port); + bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port); + + void close(); + + static in_addr lookup(const std::string& hostName); + +private: + std::string m_address; + unsigned short m_port; + int m_fd; +}; + +#endif diff --git a/DGIdGateway/Utils.cpp b/DGIdGateway/Utils.cpp new file mode 100644 index 0000000..49ded13 --- /dev/null +++ b/DGIdGateway/Utils.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009,2014,2015,2016 Jonathan Naylor, G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "Utils.h" +#include "Log.h" + +#include +#include + +void CUtils::dump(const std::string& title, const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + + dump(2U, title, data, length); +} + +void CUtils::dump(int level, const std::string& title, const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + + ::Log(level, "%s", title.c_str()); + + unsigned int offset = 0U; + + while (length > 0U) { + std::string output; + + unsigned int bytes = (length > 16U) ? 16U : length; + + for (unsigned i = 0U; i < bytes; i++) { + char temp[10U]; + ::sprintf(temp, "%02X ", data[offset + i]); + output += temp; + } + + for (unsigned int i = bytes; i < 16U; i++) + output += " "; + + output += " *"; + + for (unsigned i = 0U; i < bytes; i++) { + unsigned char c = data[offset + i]; + + if (::isprint(c)) + output += c; + else + output += '.'; + } + + output += '*'; + + ::Log(level, "%04X: %s", offset, output.c_str()); + + offset += 16U; + + if (length >= 16U) + length -= 16U; + else + length = 0U; + } +} + +void CUtils::dump(const std::string& title, const bool* bits, unsigned int length) +{ + assert(bits != NULL); + + dump(2U, title, bits, length); +} + +void CUtils::dump(int level, const std::string& title, const bool* bits, unsigned int length) +{ + assert(bits != NULL); + + unsigned char bytes[100U]; + unsigned int nBytes = 0U; + for (unsigned int n = 0U; n < length; n += 8U, nBytes++) + bitsToByteBE(bits + n, bytes[nBytes]); + + dump(level, title, bytes, nBytes); +} + +void CUtils::byteToBitsBE(unsigned char byte, bool* bits) +{ + assert(bits != NULL); + + bits[0U] = (byte & 0x80U) == 0x80U; + bits[1U] = (byte & 0x40U) == 0x40U; + bits[2U] = (byte & 0x20U) == 0x20U; + bits[3U] = (byte & 0x10U) == 0x10U; + bits[4U] = (byte & 0x08U) == 0x08U; + bits[5U] = (byte & 0x04U) == 0x04U; + bits[6U] = (byte & 0x02U) == 0x02U; + bits[7U] = (byte & 0x01U) == 0x01U; +} + +void CUtils::byteToBitsLE(unsigned char byte, bool* bits) +{ + assert(bits != NULL); + + bits[0U] = (byte & 0x01U) == 0x01U; + bits[1U] = (byte & 0x02U) == 0x02U; + bits[2U] = (byte & 0x04U) == 0x04U; + bits[3U] = (byte & 0x08U) == 0x08U; + bits[4U] = (byte & 0x10U) == 0x10U; + bits[5U] = (byte & 0x20U) == 0x20U; + bits[6U] = (byte & 0x40U) == 0x40U; + bits[7U] = (byte & 0x80U) == 0x80U; +} + +void CUtils::bitsToByteBE(const bool* bits, unsigned char& byte) +{ + assert(bits != NULL); + + byte = bits[0U] ? 0x80U : 0x00U; + byte |= bits[1U] ? 0x40U : 0x00U; + byte |= bits[2U] ? 0x20U : 0x00U; + byte |= bits[3U] ? 0x10U : 0x00U; + byte |= bits[4U] ? 0x08U : 0x00U; + byte |= bits[5U] ? 0x04U : 0x00U; + byte |= bits[6U] ? 0x02U : 0x00U; + byte |= bits[7U] ? 0x01U : 0x00U; +} + +void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte) +{ + assert(bits != NULL); + + byte = bits[0U] ? 0x01U : 0x00U; + byte |= bits[1U] ? 0x02U : 0x00U; + byte |= bits[2U] ? 0x04U : 0x00U; + byte |= bits[3U] ? 0x08U : 0x00U; + byte |= bits[4U] ? 0x10U : 0x00U; + byte |= bits[5U] ? 0x20U : 0x00U; + byte |= bits[6U] ? 0x40U : 0x00U; + byte |= bits[7U] ? 0x80U : 0x00U; +} diff --git a/DGIdGateway/Utils.h b/DGIdGateway/Utils.h new file mode 100644 index 0000000..ade28c0 --- /dev/null +++ b/DGIdGateway/Utils.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009,2014,2015 by Jonathan Naylor, G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef Utils_H +#define Utils_H + +#include + +class CUtils { +public: + static void dump(const std::string& title, const unsigned char* data, unsigned int length); + static void dump(int level, const std::string& title, const unsigned char* data, unsigned int length); + + static void dump(const std::string& title, const bool* bits, unsigned int length); + static void dump(int level, const std::string& title, const bool* bits, unsigned int length); + + static void byteToBitsBE(unsigned char byte, bool* bits); + static void byteToBitsLE(unsigned char byte, bool* bits); + + static void bitsToByteBE(const bool* bits, unsigned char& byte); + static void bitsToByteLE(const bool* bits, unsigned char& byte); + +private: +}; + +#endif diff --git a/DGIdGateway/Version.h b/DGIdGateway/Version.h new file mode 100644 index 0000000..8fabccf --- /dev/null +++ b/DGIdGateway/Version.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(VERSION_H) +#define VERSION_H + +const char* VERSION = "20200803"; + +#endif diff --git a/DGIdGateway/YSFConvolution.cpp b/DGIdGateway/YSFConvolution.cpp new file mode 100644 index 0000000..23b117e --- /dev/null +++ b/DGIdGateway/YSFConvolution.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "YSFConvolution.h" + +#include +#include +#include + +const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U}; +const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U}; + +const unsigned int NUM_OF_STATES_D2 = 8U; +const unsigned int NUM_OF_STATES = 16U; +const uint32_t M = 2U; +const unsigned int K = 5U; + +CYSFConvolution::CYSFConvolution() : +m_metrics1(NULL), +m_metrics2(NULL), +m_oldMetrics(NULL), +m_newMetrics(NULL), +m_decisions(NULL), +m_dp(NULL) +{ + m_metrics1 = new uint16_t[16U]; + m_metrics2 = new uint16_t[16U]; + m_decisions = new uint64_t[180U]; +} + +CYSFConvolution::~CYSFConvolution() +{ + delete[] m_metrics1; + delete[] m_metrics2; + delete[] m_decisions; +} + +void CYSFConvolution::start() +{ + ::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); + ::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); + + m_oldMetrics = m_metrics1; + m_newMetrics = m_metrics2; + m_dp = m_decisions; +} + +void CYSFConvolution::decode(uint8_t s0, uint8_t s1) +{ + *m_dp = 0U; + + for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) { + uint8_t j = i * 2U; + + uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1); + + uint16_t m0 = m_oldMetrics[i] + metric; + uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric); + uint8_t decision0 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0; + + m0 = m_oldMetrics[i] + (M - metric); + m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric; + uint8_t decision1 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0; + + *m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U)); + } + + ++m_dp; + + assert((m_dp - m_decisions) <= 180); + + uint16_t* tmp = m_oldMetrics; + m_oldMetrics = m_newMetrics; + m_newMetrics = tmp; +} + +void CYSFConvolution::chainback(unsigned char* out, unsigned int nBits) +{ + assert(out != NULL); + + uint32_t state = 0U; + + while (nBits-- > 0) { + --m_dp; + + uint32_t i = state >> (9 - K); + uint8_t bit = uint8_t(*m_dp >> i) & 1; + state = (bit << 7) | (state >> 1); + + WRITE_BIT1(out, nBits, bit != 0U); + } +} + +void CYSFConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const +{ + assert(in != NULL); + assert(out != NULL); + assert(nBits > 0U); + + uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U; + uint32_t k = 0U; + for (unsigned int i = 0U; i < nBits; i++) { + uint8_t d = READ_BIT1(in, i) ? 1U : 0U; + + uint8_t g1 = (d + d3 + d4) & 1; + uint8_t g2 = (d + d1 + d2 + d4) & 1; + + d4 = d3; + d3 = d2; + d2 = d1; + d1 = d; + + WRITE_BIT1(out, k, g1 != 0U); + k++; + + WRITE_BIT1(out, k, g2 != 0U); + k++; + } +} diff --git a/DGIdGateway/YSFConvolution.h b/DGIdGateway/YSFConvolution.h new file mode 100644 index 0000000..3fc4956 --- /dev/null +++ b/DGIdGateway/YSFConvolution.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(YSFConvolution_H) +#define YSFConvolution_H + +#include "YSFConvolution.h" + +#include + +class CYSFConvolution { +public: + CYSFConvolution(); + ~CYSFConvolution(); + + void start(); + void decode(uint8_t s0, uint8_t s1); + void chainback(unsigned char* out, unsigned int nBits); + + void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const; + +private: + uint16_t* m_metrics1; + uint16_t* m_metrics2; + uint16_t* m_oldMetrics; + uint16_t* m_newMetrics; + uint64_t* m_decisions; + uint64_t* m_dp; +}; + +#endif + diff --git a/DGIdGateway/YSFDefines.h b/DGIdGateway/YSFDefines.h new file mode 100644 index 0000000..b2aefc6 --- /dev/null +++ b/DGIdGateway/YSFDefines.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(YSFDefines_H) +#define YSFDefines_H + +const unsigned int YSF_FRAME_LENGTH_BYTES = 120U; + +const unsigned char YSF_SYNC_BYTES[] = {0xD4U, 0x71U, 0xC9U, 0x63U, 0x4DU}; +const unsigned int YSF_SYNC_LENGTH_BYTES = 5U; + +const unsigned int YSF_FICH_LENGTH_BYTES = 25U; + +const unsigned char YSF_SYNC_OK = 0x01U; + +const unsigned int YSF_CALLSIGN_LENGTH = 10U; + +const unsigned char YSF_FI_HEADER = 0x00U; +const unsigned char YSF_FI_COMMUNICATIONS = 0x01U; +const unsigned char YSF_FI_TERMINATOR = 0x02U; +const unsigned char YSF_FI_TEST = 0x03U; + +const unsigned char YSF_DT_VD_MODE1 = 0x00U; +const unsigned char YSF_DT_DATA_FR_MODE = 0x01U; +const unsigned char YSF_DT_VD_MODE2 = 0x02U; +const unsigned char YSF_DT_VOICE_FR_MODE = 0x03U; + +const unsigned char YSF_CM_GROUP1 = 0x00U; +const unsigned char YSF_CM_GROUP2 = 0x01U; +const unsigned char YSF_CM_INDIVIDUAL = 0x03U; + +const unsigned char YSF_MR_NOT_BUSY = 0x01U; +const unsigned char YSF_MR_BUSY = 0x02U; + +const unsigned int FCS_PORT = 62500U; + +#endif diff --git a/DGIdGateway/YSFFICH.cpp b/DGIdGateway/YSFFICH.cpp new file mode 100644 index 0000000..967b339 --- /dev/null +++ b/DGIdGateway/YSFFICH.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2016,2017,2019 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "YSFConvolution.h" +#include "YSFDefines.h" +#include "Golay24128.h" +#include "YSFFICH.h" +#include "CRC.h" +#include "Log.h" + +#include +#include +#include + +const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +const unsigned int INTERLEAVE_TABLE[] = { + 0U, 40U, 80U, 120U, 160U, + 2U, 42U, 82U, 122U, 162U, + 4U, 44U, 84U, 124U, 164U, + 6U, 46U, 86U, 126U, 166U, + 8U, 48U, 88U, 128U, 168U, + 10U, 50U, 90U, 130U, 170U, + 12U, 52U, 92U, 132U, 172U, + 14U, 54U, 94U, 134U, 174U, + 16U, 56U, 96U, 136U, 176U, + 18U, 58U, 98U, 138U, 178U, + 20U, 60U, 100U, 140U, 180U, + 22U, 62U, 102U, 142U, 182U, + 24U, 64U, 104U, 144U, 184U, + 26U, 66U, 106U, 146U, 186U, + 28U, 68U, 108U, 148U, 188U, + 30U, 70U, 110U, 150U, 190U, + 32U, 72U, 112U, 152U, 192U, + 34U, 74U, 114U, 154U, 194U, + 36U, 76U, 116U, 156U, 196U, + 38U, 78U, 118U, 158U, 198U}; + +CYSFFICH::CYSFFICH(const CYSFFICH& fich) : +m_fich(NULL) +{ + m_fich = new unsigned char[6U]; + + ::memcpy(m_fich, fich.m_fich, 6U); +} + +CYSFFICH::CYSFFICH() : +m_fich(NULL) +{ + m_fich = new unsigned char[6U]; + + memset(m_fich, 0x00U, 6U); +} + +CYSFFICH::~CYSFFICH() +{ + delete[] m_fich; +} + +bool CYSFFICH::decode(const unsigned char* bytes) +{ + assert(bytes != NULL); + + // Skip the sync bytes + bytes += YSF_SYNC_LENGTH_BYTES; + + CYSFConvolution viterbi; + viterbi.start(); + + // Deinterleave the FICH and send bits to the Viterbi decoder + for (unsigned int i = 0U; i < 100U; i++) { + unsigned int n = INTERLEAVE_TABLE[i]; + uint8_t s0 = READ_BIT1(bytes, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(bytes, n) ? 1U : 0U; + + viterbi.decode(s0, s1); + } + + unsigned char output[13U]; + viterbi.chainback(output, 96U); + + unsigned int b0 = CGolay24128::decode24128(output + 0U); + unsigned int b1 = CGolay24128::decode24128(output + 3U); + unsigned int b2 = CGolay24128::decode24128(output + 6U); + unsigned int b3 = CGolay24128::decode24128(output + 9U); + + m_fich[0U] = (b0 >> 4) & 0xFFU; + m_fich[1U] = ((b0 << 4) & 0xF0U) | ((b1 >> 8) & 0x0FU); + m_fich[2U] = (b1 >> 0) & 0xFFU; + m_fich[3U] = (b2 >> 4) & 0xFFU; + m_fich[4U] = ((b2 << 4) & 0xF0U) | ((b3 >> 8) & 0x0FU); + m_fich[5U] = (b3 >> 0) & 0xFFU; + + return CCRC::checkCCITT162(m_fich, 6U); +} + +void CYSFFICH::encode(unsigned char* bytes) +{ + assert(bytes != NULL); + + // Skip the sync bytes + bytes += YSF_SYNC_LENGTH_BYTES; + + CCRC::addCCITT162(m_fich, 6U); + + unsigned int b0 = ((m_fich[0U] << 4) & 0xFF0U) | ((m_fich[1U] >> 4) & 0x00FU); + unsigned int b1 = ((m_fich[1U] << 8) & 0xF00U) | ((m_fich[2U] >> 0) & 0x0FFU); + unsigned int b2 = ((m_fich[3U] << 4) & 0xFF0U) | ((m_fich[4U] >> 4) & 0x00FU); + unsigned int b3 = ((m_fich[4U] << 8) & 0xF00U) | ((m_fich[5U] >> 0) & 0x0FFU); + + unsigned int c0 = CGolay24128::encode24128(b0); + unsigned int c1 = CGolay24128::encode24128(b1); + unsigned int c2 = CGolay24128::encode24128(b2); + unsigned int c3 = CGolay24128::encode24128(b3); + + unsigned char conv[13U]; + conv[0U] = (c0 >> 16) & 0xFFU; + conv[1U] = (c0 >> 8) & 0xFFU; + conv[2U] = (c0 >> 0) & 0xFFU; + conv[3U] = (c1 >> 16) & 0xFFU; + conv[4U] = (c1 >> 8) & 0xFFU; + conv[5U] = (c1 >> 0) & 0xFFU; + conv[6U] = (c2 >> 16) & 0xFFU; + conv[7U] = (c2 >> 8) & 0xFFU; + conv[8U] = (c2 >> 0) & 0xFFU; + conv[9U] = (c3 >> 16) & 0xFFU; + conv[10U] = (c3 >> 8) & 0xFFU; + conv[11U] = (c3 >> 0) & 0xFFU; + conv[12U] = 0x00U; + + CYSFConvolution convolution; + unsigned char convolved[25U]; + convolution.encode(conv, convolved, 100U); + + unsigned int j = 0U; + for (unsigned int i = 0U; i < 100U; i++) { + unsigned int n = INTERLEAVE_TABLE[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } +} + +unsigned char CYSFFICH::getFI() const +{ + return (m_fich[0U] >> 6) & 0x03U; +} + +unsigned char CYSFFICH::getCM() const +{ + return (m_fich[0U] >> 2) & 0x03U; +} + +unsigned char CYSFFICH::getBN() const +{ + return m_fich[0U] & 0x03U; +} + +unsigned char CYSFFICH::getBT() const +{ + return (m_fich[1U] >> 6) & 0x03U; +} + +unsigned char CYSFFICH::getFN() const +{ + return (m_fich[1U] >> 3) & 0x07U; +} + +unsigned char CYSFFICH::getFT() const +{ + return m_fich[1U] & 0x07U; +} + +unsigned char CYSFFICH::getDT() const +{ + return m_fich[2U] & 0x03U; +} + +unsigned char CYSFFICH::getMR() const +{ + return (m_fich[2U] >> 3) & 0x03U; +} + +bool CYSFFICH::getDev() const +{ + return (m_fich[2U] & 0x40U) == 0x40U; +} + +unsigned char CYSFFICH::getDGId() const +{ + return m_fich[3U] & 0x7FU; +} + +void CYSFFICH::setFI(unsigned char fi) +{ + m_fich[0U] &= 0x3FU; + m_fich[0U] |= (fi << 6) & 0xC0U; +} + +void CYSFFICH::setFN(unsigned char fn) +{ + m_fich[1U] &= 0xC7U; + m_fich[1U] |= (fn << 3) & 0x38U; +} + +void CYSFFICH::setFT(unsigned char ft) +{ + m_fich[1U] &= 0xF8U; + m_fich[1U] |= ft & 0x07U; +} + +void CYSFFICH::setMR(unsigned char mr) +{ + m_fich[2U] &= 0xC7U; + m_fich[2U] |= (mr << 3) & 0x38U; +} + +void CYSFFICH::setVoIP(bool on) +{ + if (on) + m_fich[2U] |= 0x04U; + else + m_fich[2U] &= 0xFBU; +} + +void CYSFFICH::setDev(bool on) +{ + if (on) + m_fich[2U] |= 0x40U; + else + m_fich[2U] &= 0xBFU; +} + +void CYSFFICH::setDGId(unsigned char id) +{ + m_fich[3U] &= 0x80U; + m_fich[3U] |= id & 0x7FU; +} + +CYSFFICH& CYSFFICH::operator=(const CYSFFICH& fich) +{ + if (&fich != this) + ::memcpy(m_fich, fich.m_fich, 6U); + + return *this; +} diff --git a/DGIdGateway/YSFFICH.h b/DGIdGateway/YSFFICH.h new file mode 100644 index 0000000..b7d623c --- /dev/null +++ b/DGIdGateway/YSFFICH.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016,2017,2019 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(YSFFICH_H) +#define YSFFICH_H + +class CYSFFICH { +public: + CYSFFICH(const CYSFFICH& fich); + CYSFFICH(); + ~CYSFFICH(); + + bool decode(const unsigned char* bytes); + + void encode(unsigned char* bytes); + + unsigned char getFI() const; + unsigned char getCM() const; + unsigned char getBN() const; + unsigned char getBT() const; + unsigned char getFN() const; + unsigned char getFT() const; + unsigned char getDT() const; + unsigned char getMR() const; + bool getDev() const; + unsigned char getDGId() const; + + void setFI(unsigned char fi); + void setFN(unsigned char fn); + void setFT(unsigned char ft); + void setMR(unsigned char mr); + void setVoIP(bool set); + void setDev(bool set); + void setDGId(unsigned char id); + + CYSFFICH& operator=(const CYSFFICH& fich); + +private: + unsigned char* m_fich; +}; + +#endif diff --git a/DGIdGateway/YSFHosts.txt b/DGIdGateway/YSFHosts.txt new file mode 100644 index 0000000..abb33e1 --- /dev/null +++ b/DGIdGateway/YSFHosts.txt @@ -0,0 +1,899 @@ +90681;0-0-AMERICA;CQ USA! USA!;130.211.170.41;42001;010;http:// +03729;0-0-CHINAVIRUS;COVID CHAT;130.211.170.41;42002;001;http:// +27793;0-0-CQ-UK-ROOM;cq-uk.co.uk;81.150.10.62;42200;073;http://www.mb6er.com/ysf/ +24160;0-CQ-UK-AUSSIE;Reflector 2;81.150.10.63;42100;009;https://www.cq-uk.co.uk +02203;0-HUBNet;Link to HUBNet;81.105.24.211;42000;005;https://hubnetwork.uk/ +84922;0-KP3AV-Systems;Puerto Rico HU;70.45.32.69;41000;004;https://www.kp3av.net/ +92150;0-MAGA;MAGA AMERICA;130.211.170.41;42000;001;http://no.not.yet/ +65702;0-OE-Austria;Official;94.199.173.123;42200;001;http://oe9xvi.dyndns.org:46193 +24117;00-AACQ-VK;VK WiRES-X;110.232.113.108;42002;014;http://110.232.113.108/vw +38900;00-AAYSF001;YSF001;110.232.113.108;42000;005;http://ysf001.duckdns.org +38089;0077;IRLP/ DMR/ D-S;23.94.25.146;42002;006;http://xe1dvi.crabdance.com/html/index.php +32642;021YSF;KR 021YSF;27.100.207.79;42000;006;http://ysf021.dvham.com +33280;0303_YSFColo;0303_YSFColo;3.22.106.87;42000;002;http:// +40608;069-Er-Super-Fre;BM-YSF-P25-NXD;13.57.29.35;42000;004;http:// +84905;096ysf-Busan-KR;Link TG450391;125.135.231.82;42000;000;http://096ysf.duckdns.org +11506;0970_YSFColo;0970_YSFColo;75.71.97.203;42000;004;http:// +11500;0E7XTR;Tirol Oberland;185.199.82.169;42000;002;https://inet01.synology.me:46193 +02573;1004DMR;DRM C4FM CROSS;218.144.164.10;42000;004;http://1004dmr.dvham.com/indexysf.php +74652;119-YSF;KR 119YSF;61.42.88.20;42000;030;http://ysf119.dvham.com/index.php +68800;2007-DXGROUP;Web Server;89.46.75.115;42000;005;http://89.46.75.115/index +37865;450IPSC2;C4FM TO DMR;220.71.19.222;42000;005;http://450ipsc2.dvham.com/indexysf.php +21796;4X-Israel;Israel Digital;109.226.48.53;42000;001;http://ysf972.ddns.net +06015;50525;Bridge-NXDN-P2;103.1.187.140;42000;003;http://50525.ysfreflector.net +97629;79435;IT S.M.A.M Pis;185.177.59.32;42000;005;http://185.177.59.32 +65947;843IPSC2;IPSC2-DMR(TG84;218.144.164.13;42000;001;http://ipsc2843.dvham.com/indexysf.php +60227;911-Cop-Talk;911 Cop Talk;34.238.149.231;42000;002;http://ysf.k2cop.com +83018;95ANorth;Fernley,NV USA;216.128.134.46;42000;001;http://ysf.k7wby.com +44734;AARC-Fusion;AARC Fusion;64.179.223.222;42000;001;https://ysf.spdns.org +17950;AH-HUH.NET;YSF;52.192.129.174;42000;012;http://ah-huh.net/ysf/ +02034;Alabama-Link;Alabama-Link;96.47.95.121;42000;048;http://ysf.alabamalink.info/ +64230;America-RC;YSF-TO-WIRES-X;65.101.7.50;42001;015;http://arcysf.duckdns.org +21080;AmericaLink;AmericaLink;209.126.110.236;42000;443;http://hamfm.com/ysf/ +30458;AnHui-HeFei01;YSF/BM460601;47.116.60.36;42000;003;http://eei-edu.f3322.net +31897;AR-AR-CIRCULO;ROSARIO;181.165.15.51;42000;007;http://circulorosario.linkpc.net +10111;AR-ARG;*ARG* Argentin;149.28.100.251;42000;001;http://ysfarg.ddns.net +73599;AR-TG722-LINK;YSF to TG722;80.211.1.59;42000;000;http://722ysfargentina.dnsalias.com +60842;ARG-FUSION;C4FM;200.81.152.112;42000;000;http://rotativos.dyndns.org:42002 +31302;ARG-ROOM;Argentina-ROOM;190.194.12.53;42000;008;http://xlx.argentina-room.dns-cloud.net +66099;ARGENTINA-LINK;Link to TG7227;80.211.7.43;42000;014;http://7221ysfargentina.dnsalias.com +61159;ArkLaTex;ArkLaTex;104.198.203.19;42000;002;http://104.198.203.19 +24490;ASL48270;AllStar;104.143.94.48;42042;001;http://104.143.94.48/YSFReflector/index.php +25223;AT-Austria-OE1;OE1XFV;213.47.71.17;42000;003;http://oe1xfv.ddns.net/YSFReflector-Dashboard/ +00396;AT-Austria-OE3;OE3AAS;77.116.18.249;42100;001;http://oe3aas.ddns.net/YSFReflector-Dashboard/ +71095;AT-Austria-OE5;OE5XOL;185.16.114.90;42000;001;http://oe5xol.ham-radio-op.net/YSFReflector-Dashboard/ +59911;AT-Austria-OE8;OE8VIK;178.199.109.52;42000;000;http://oe8vik.internet-box.ch/YSFReflector-Dashboard +23201;AT-C4FM-Austria;(YCS001);89.185.97.38;42000;073;http://c4fm.oevsv.at/ycs/ +73082;AU-Albury-Chat;Albury Chat;52.63.126.187;42000;009;http://52.63.126.187/ +43110;AU-NSW;AU NSW;123.243.237.216;42000;000;http://ysfnsw.gustotech.net/ +05057;AU_TAS;VK7 Tasmania;45.248.50.37;42001;001;http://vk7hse.duckdns.org/ysf +74037;BARC-ONT-CA;Burlington ARC;69.158.63.158;42000;000;http://barcysfreflector.ddns.net +00043;BAYAREA-YSF;Silicon Valley;45.32.129.65;42000;010;http://ysf.bsdworld.org/ysf/ +44992;BE-YSF-Liege;Wires-X<>YSF;51.75.249.214;42002;000;http://51.75.249.214/ysf/ +64364;BE-YSF-Vl;C4FMVlaanderen;81.95.126.168;42001;009;http://ysf.on4top.be/ysf/ +79520;BE-YSF-Wallonie;C4FM Wallon;51.255.193.63;42000;003;http://www.ysfwallonie.net/ +46197;BE-YSFEUREGIO;LNK_BE_EUREGIO;213.49.173.226;43000;003;http://rmx.noip.me:6380 +00076;Berks-County;Pennsylvania;24.115.37.118;42020;000;http:// +69733;BM2410/XLX010D;SSA Bulletin;95.216.197.75;42001;001;http://ysf2.brandmeister.se +56800;Boar's-Nest;Good Ol' Boys;67.140.163.107;42002;000;http:// +90558;BR-PU2LRZ;TG268916 WIRES;186.228.91.9;42000;010;http://ysf-brasil.com.br +08059;Brasil-AMRASE;Brasil-Link;201.62.48.60;42000;003;http://ysf.amrase.org.br/ysf +72526;BRAZIL-724;DV Brazil;191.252.203.6;42000;004;https://ysf.dvbrazil.com.br/ +85044;C4FM-SEOUL;TG45050 TO C4F;222.110.59.176;42000;004;http://ysfso.dvham.com/indexysf.php +36037;CA-420-Network;RAGCHEW;142.93.158.165;42000;003;https://ysf.420hamradio.network +77353;CA-Canada;C4FM Ontario;144.217.241.23;42100;007;http://c4fmontario.hopto.org +71083;CA-Canada-FR;Fusion Canada;38.110.97.161;42000;015;http://38.110.97.161 +29579;CA-CQ-Canada;DMR TGIF 3022;142.93.158.165;42002;003;https://cqcanada.420hamradio.network/ +71305;CA-DMRQ-3022;DMRQ TG3022;38.110.97.161;42554;003;http://dmrq.ca/ +53710;CA-Maritimes;Can Maritimes;178.128.231.202;42000;007;http://ysf.nbdmr.net +19952;CA-Nanikana;Nanikana;142.217.113.98;42000;000;http://142.217.113.98 +36010;CA-ON-ProCom;ON Prov Comms;70.50.41.195;42000;003;http://freestar.homelinux.net/ysf +23829;CA-Upper-Can;Upper Can QRP;64.118.21.239;42100;005;http://ve3ucc.ddns.net/ +13339;CA-WEST-CAN;Western Canada;172.105.26.148;42001;000;http://ysf.ve6meo.ca +13124;CA-YSF-CHARC;SW QUEBEC,CA;207.35.36.179;42000;002;https://207.35.36.179 +72576;CA-YSF-TO-WIRESX;REF-BRIDGE-LAB;192.222.226.35;42002;000;http://dashboard.va2ss.com:8080/ +48095;CAMCAST;YSF REFLECTOR;80.211.12.209;42000;000;http://80.211.12.209/index.php +01177;CARG;CURACAO YSF;138.219.142.144;42000;001;http://138.219.142.144 +79602;Carolina-Link;79602;208.104.55.181;42001;012;http://208.104.55.181/index.php +77785;CDARIN;CDARIN-XLX420;149.28.54.17;42002;000;https://xlx.cdarin.net/ysf +30998;CH-228-Swiss;YCS Group 28 S;195.225.116.245;42000;005;http://ysf.hb-connect.ch/ +63347;CH-228-Swiss2;HB-CONNECT;176.10.105.210;42002;000;http:// +15280;CH-HB9VD;Radioamateurs;217.182.128.3;42000;002;http://reflector.hb9vd.ch/ysf +37664;CH-IT-SWISS;C4FM OM;94.177.215.206;42000;000;http://94.177.215.206 +66049;ChinaLink;China YSF Refl;60.219.211.9;42000;000;http://ysf.tocall.fun:8081 +22638;CH_JOTA;Jamboree on th;157.161.57.65;42001;000;http://pi2.woody.ch:8080/YSFReflector-Dashboard/ (ipv6 only) +72350;CL-CHILE;YSF to TG730;186.64.123.59;42000;002;http://sdradio.cl/ysf +34287;CL-CL-CHILE;YSF HOTSPOT'S;186.103.150.254;42000;000;https://www.radioaficion.pro/ysf +19525;CL-EMCOMM;TG 730911;186.64.123.59;42001;000;http://sdradio.cl/ysf2 +09627;CL-YSF;CHILE YSF ROOM;186.64.123.59;42002;002;http://sdradio.cl/ysf3 +18829;CN-CC#1;TG 460501;47.104.177.248;42000;001;https://mmdvm.cc/ysf/ +86319;CN-China-#3;C4FM;123.58.6.137;42000;003;http://123.58.6.137:8088/ +46055;CN-China-#4;TG460531;112.229.25.110;42003;000;http://pi.jwebid.com:81 +49766;CN-China-#7;YSFn/DMR/P25;47.100.76.205;42002;000;http:// +50565;CN-CN-BJS-YSF;CN BJS C4FM;49.233.142.122;42250;002;https://ysf.bh1ofp.com/ +08408;CN-CN-China-4;P25;47.105.33.47;42003;002;http://www.bg3hbr.cn/ysfp25/ +25574;CN-CN-SH;YSF/TG46068;116.235.186.62;42000;002;http://chinafex.tpddns.cn:82 +99996;CN-CN-SH-BR4AC;TG46021;118.89.184.51;42000;001;http:// +41095;CN-CN-SH-JIUTING;TG4601319;140.143.12.207;42000;001;http:// +99117;CN-LiaoNing;YSF by BH2UOL;47.95.194.251;42000;000;http://47.95.194.251 +36400;CN-NMG-1#;C4FM China;39.64.187.131;42000;001;http://jw.jwebid.com:88 +01347;CN-Shanghai;YSF by BH4EZG;124.78.51.205;42000;000;http:// +45441;CN-Shenyang-2;YSF by BH2UOL;139.226.2.194;42000;000;http://angel66.f3322.net:2122/ +87327;CN-SHLK;C4FM;218.79.217.10;42000;002;http:// +19610;CN-SXXY-YSF;TG46091;123.139.189.182;42000;001;http://ysf.jzsqx.com:3578/ysf/ +10552;CN-SZ-YSF;BM TG46073;14.116.159.221;42000;005;http:// +78497;CN-TIANJIN;C4FM/TG460022;47.104.79.192;42000;002;http:// +57490;CN-Wuhan;CNWUH YSFRef;118.89.199.238;42000;004;http:// +84099;CN-XUZHOU;TG460516;119.45.191.42;42000;003;http://www.bd4two.cn +69058;CNARN;CNARN;45.76.175.5;42000;014;http://cnarn.hopto.org +20059;CN_China_#1;W24166/TG46001;58.250.171.29;42000;056;http://ysf.sz790.com:8081/ +72001;CO-HK_NAL_LCRA;BM TG732;186.29.69.76;42000;007;http://ysfnal.lcra.org.co +11115;CQ-MICHIGAN;MICHIGAN USA;107.141.52.226;42002;000;http:// +27715;CQ-OHIO;Ohio, USA;24.192.74.248;42002;001;http:// +18480;CT-BMCAT;C4FM Catalunya;94.177.237.192;42000;010;http://ysf900.dyndns.org/ysf +04523;CT-CATALANA;C4FM CATALUNYA;213.195.111.148;42000;004;http://catalana.ea3hkb.cat +68592;CT-GARRAF;C4FM CATALUNYA;213.195.111.148;42001;005;http://garraf.ea3hkb.cat +99797;CT-RI-ROOM;C4FM LINKED;45.58.45.126;42000;008;http:// +12096;CW-ToyTronNet;Sunny Curacao;186.159.96.100;42001;000;http://ysf.toytron.com +14353;CY-YSF-Cyprus;YSF Cyprus Ref;213.7.197.202;42000;001;http://xlx146.ddns.net:81/ysf/ +26541;CZ-Czech;TG2300 DCS19V;80.250.3.114;42000;011;http://80.250.3.114/index.php +26541;CZ-Czech;TG2300 DCS19V;80.250.3.114;42000;011;http://xlx230.ok2it.com +52690;CZ-YSF-Klatovy;CZ;46.23.62.124;42200;000;http://46.23.62.124:42080 +77329;CZ-YSF-Praha;CZ YSF Praha;185.32.183.148;42000;004;http://185.32.183.148/ysf/ +21972;DE-Berlin;Spandau;81.169.245.52;42000;004;http://www.comvision.de/ysf/ +42539;DE-Bremen;Bremen-Nord;82.207.204.207;42002;000;http://do0bre.ddns.net/ +14187;DE-DL-DL1BH;Bremerhaven;87.245.30.60;42000;003;http:// +90730;DE-DL-Elbe-Weser;DL-Elbe-Weser;91.58.164.76;42000;002;http://dl-elbe-weser.spdns.de +07588;DE-DL-Hamburg;Hamburg City;95.116.202.35;42000;006;http://db0fs-router.hamnet.hamburg:22225/index.php +54919;DE-DL-NORDWEST;DL-Nordwest;93.240.48.68;42000;034;http://dl-nordwest.spdns.de +68399;DE-DL-Oberberg;Bergisches Kr.;82.165.136.160;42000;001;http://ysf.shakerware.de +47791;DE-DL-Saar;Saarland;167.86.110.62;42002;001;https://c4fm.ysfreflector.de/DL-Saar/ +07794;DE-DL5OCD;Hildesheim;46.41.2.20;42000;004;http://dl5ocd.selfhost.eu +21584;DE-Fusion-MUC;Fusion-MUC;93.240.113.55;42004;002;http:// +62829;DE-Germany;YSF262 BM263;167.86.110.62;42000;010;https://c4fm.ysfreflector.de/Germany +22675;DE-Germany02;MultiNet-Bridg;185.228.139.209;42000;009;http://ysf-germany02.xreflector.net/ysf/ +92161;DE-GOETTINGEN;Raum Gö;51.15.40.103;42001;005;http://goettingen-ysf.tk +02883;DE-Hannover-XLnk;Hannover und U;81.14.225.84;42000;002;http://ysf.hannover-x.link +44305;DE-Heidekreis;Niedersachsen;91.64.24.111;41000;002;http://do3bsl.ddns.net +19138;DE-HESSEN-F17;F17 Reflector;80.69.46.184;42000;002;http:// +55160;DE-Huelzweiler;DL4WM-Reflecto;213.135.12.4;42000;000;http:// +93571;DE-Inselfreunde;BM-TG26444;88.198.94.77;42444;002;http:// +68030;DE-Laatzen;Hannover;159.69.64.204;42000;001;https://blackdan.de/ysf +90448;DE-Neumarkt;YSF Neumarkt;213.202.228.66;42000;004;http://213.202.228.66/neumarkt/YSFReflector-Dashboard/index.php +87939;DE-Notfunk;NotfunkGruppe;78.47.182.224;42001;000;https://notfunk.ysf.vfdb.org/ +61156;DE-Oberbayern;BM-TG26285;88.198.94.77;42285;003;http:// +13100;DE-OBERLAUSITZ;YSF Ostsachsen;85.214.61.75;42000;002;https://ysf02.bzsax.de/ysf-ol/ +09319;DE-Oberpfalz;Region Opf.;78.47.182.224;42009;007;https://oberpfalz.vfdb.org/ +13111;DE-OBL-RAUM-1;YSF;85.214.61.75;42001;000;http:// +64445;DE-OWL;XLX508G OWL;185.188.4.15;42001;006;http://ysf.hb9gfx.ch +74154;DE-PEGASUS;Multi-Bridge;78.46.11.65;42000;077;https://status.projekt-pegasus.net/ +20548;DE-PEGASUS2;Test System;78.46.11.65;42001;001;https://status.projekt-pegasus.net/ +63421;DE-Ruhrgebiet;Ruhrgebiet;144.76.12.90;42000;006;http://dg3yjb.beba.re/YSFReflector +10977;DE-Sachsen;BM TG2629;109.104.48.10;42001;001;http:// +68240;DE-Schwarzwald;#68240 Schwarz;185.75.164.30;42000;008;https://db0vs.de/YSFReflector-Dashboard/index.php +55966;DE-Thueringen;Thüringen Ref;195.145.3.97;42000;005;http://44.225.117.67/YSFReflector-Dashboard/ +95352;DE-Twitterrunde;GW BM TG263333;167.86.110.62;42001;001;https://c4fm.ysfreflector.de/Twitterrunde +53414;DE-VFDB;Telekom&Post;78.47.182.224;42000;001;https://vfdb.ysf.vfdb.org/ +33465;DE_DL-Baltic;Greifswald;81.169.128.244;42001;003;http://ysf.digitalfunk-nordost.de +46981;DL1SGP-YSF;Testing;51.75.79.91;42000;000;http:// +58967;DMRPlus-IT;DMRPlus Italia;185.82.114.247;42000;002;http://ysf.aotnet.it/ +01579;DO-DOMREP;YSF DRP;172.105.158.111;42000;001;http://hi8k.xreflector.es/ +30406;DO-YSF-Dom.-Rep.;YSF for HI;190.166.132.207;42000;002;http://arcrica.dyndns.org:8088 +43499;DPRNS;TH DPRNS;203.150.19.24;42000;005;http://c4fm.dprns.com +38035;DRIVETIME;FW Drivetime;71.81.181.30;42061;001;http://ysf.ki5cey.com:45000/ +53636;DV-Caribbean;DV Multimode;190.213.20.171;42100;001;http://dvcar.9y4c.tk:8080 +31769;DV-Modems;DV_Modems_YSF_;51.91.78.118;42000;001;http:// +78427;DX1ARM;DX1ARM-RPT;104.168.176.33;42000;006;http:// +11096;DX1O-Amsat-PH;DX1O Amsat PH;206.189.146.41;42000;001;http://206.189.146.41 +06989;DXhunter-SM2;DXhunter SM2;95.217.7.128;42000;001;http://95.217.7.128 +18196;EA-ARSA;EA2RKS;104.148.41.57;42003;002;http://arsa.xreflector.es/ +22401;EA-C4FM-Spain;(YCS224);212.237.3.141;42000;060;http://ycs.xreflector.es/ +73531;EA-CANARIAS;CANARIAS;164.132.96.157;42005;000;http://ysfcanarias.c4fm.es/ +94533;EA-Distrito-1;Wires X Spain;80.211.102.100;42000;001;http://80.211.102.100 +62980;EA-Distrito-4;REM Spain YSF;212.237.0.67;42000;015;http://ysfdistrito4.xreflector.es/ +90182;EA-Distrito-7;RC Veleta;212.237.11.53;42000;001;http://212.237.11.53/html/ysf/ +18470;EA-EXTREMADURA;EXTREMADURA;51.75.140.10;42002;002;http://ysfextemadura.c4fm.es/ysf2 +42670;EA-HAMNET;C4FM Spain;80.211.105.70;42000;001;http://80.211.105.70/ +42670;EA-HAMNET;C4FM Spain;80.211.105.70;42000;001;http://80.211.105.70/ +55815;EA-SPAIN-21461;MULTIPROTOCOLO;85.255.8.71;42105;002;http://hblinkspain.duckdns.org/YSFReflector +17535;EA-TG21468;CANARIAS;164.132.96.157;42003;004;http://ysfhispano.c4fm.es/ +31977;ECOAMERICA;AB6MM;104.194.206.233;42000;002;http://104.194.206.233/index.php +74161;ES-112;EMERGENCIAS;51.77.213.200;42004;000;http://51.77.213.200/ysf4 +32027;ES-ADER;ASSOCIACIO ADE;62.171.178.202;42000;004;http://digitalader.ddns.net/ysf +90884;ES-ADR;Radio Club ADR;51.254.128.134;42003;000;http://51.254.128.134/ysf3 +66492;ES-AMIRED;YAESU AMIRED;89.38.150.252;42010;000;http:// +64324;ES-BM-Sevilla;BM21441;104.148.41.57;42002;001;http://fnssevilla.c4fm.es/ysf2 +96308;ES-CACERES;SEC.LOC.URE CC;51.75.140.10;42000;001;http://ysfcaceres.c4fm.es +09059;ES-CANARIAS;Canarias C4FM;185.166.212.132;42000;000;http://185.166.212.132/ysf/ +32474;ES-CQ-DX;CQ WORLD WIDE;51.77.213.200;42003;001;http://51.77.213.200/ysf3 +41674;ES-EA-SPAIN;Red WiresX ES;212.237.11.53;42002;001;http://ysfspain.c4fm.es/html/ysf2 +34018;ES-EA4GAX-YSF;YSF EA4GAX;51.83.78.210;42002;000;http://51.83.78.210/YSF/ +16172;ES-EA7URC-Link;EA7URC Oficial;193.30.100.102;42000;001;http:// +99760;ES-EALINK;YSF EALINK;194.182.66.76;42000;000;http://www.fusion.ealink.es/ysf/ +11650;ES-EL-EJIDO;EL EJIDO SPAIN;80.88.90.73;42000;000;http://80.88.90.73/ +41996;ES-ELITE;C4FM;51.77.213.200;42002;019;http://51.77.213.200/ysf2 +96124;ES-ES-ALMERIA;YSF ALMERIA;80.211.1.143;42000;002;http://80.211.1.143/ysf/ +60725;ES-GOMERA;R5 GOMERA VHF;185.166.212.132;42003;000;http://185.166.212.132/ysf4 +10069;ES-IBERIA;C4FM;51.77.213.200;42001;001;http://51.77.213.200/ysf +14275;ES-MADRID;YSF de Madrid;51.254.128.134;42002;001;http://51.254.128.134/ysf2 +65531;ES-MARCA;YSF MARCA;80.211.41.147;42000;001;http://80.211.41.147/ysf/ +49810;ES-PEANUT-YSF;YSF PEANUT;164.132.96.157;42000;007;http://ysfpeanut.c4fm.es +15642;ES-REM-SPAIN;YSF Reflector;80.211.163.139;42000;005;http://ysfreflector-rem.spdns.org +18044;ES-TECNICO-Y-MAS;URE CT TENERIF;185.166.212.132;42002;000;http://185.166.212.132/ysf3/ +45904;ES-TENERIFE;YSF<>TG21438;185.166.212.132;42001;001;http://185.166.212.132/ysf2/ +50246;ES-Zulu-Radio;YSF Zulu Radio;51.254.128.134;42000;003;https://zuluradio.es/ysf/ +50135;EST-Ref;YSF reflector;95.216.163.65;42000;001;http://ysf.2ip.ee/dashboard +06975;Europe-YSF;Europe-YSF;93.240.48.68;42100;004;http://Europe-YSF.spdns.org:81 +00007;EUROPELINK;Europe link;161.97.73.43;42000;142;http://europelink.pa7lim.nl +13029;FI-MIKKELI;Mikkeli YSF;139.162.159.150;42000;003;http://139.162.159.150/ysf/ +96442;Foxhole;RagChew;52.176.105.136;42000;000;http://ysf.kz4fox.com +95198;FR-Centre-France;Centre-France;185.4.78.122;42002;009;http://ysf-centre-france.f1tzo.com:81 +00645;FR-FON-Gateway;Salon FON GW;185.4.78.122;42000;001;http://ysf-fon-gateway.f1tzo.com:81 +71173;FR-Franche-Comte;Franche-Comte;51.75.252.197;42000;000;http:// +30262;FR-International;Salon Interna.;185.4.78.122;42005;002;http://ysf-international-rrf.f1tzo.com:81 +72173;FR-RIDF;FR Reseau IDF;185.4.78.122;42001;001;http:// +86886;FR-Room-ZIT;Room F1ZIT;151.80.143.185;42002;035;http://151.80.143.185/zit/YSFReflector-Dashboard/ +39510;FR-wiresxfrance;Wires-X-France;151.80.143.185;42001;000;http://151.80.143.185/WXF/YSFReflector-Dashboard/index.php +83665;FR-YSF-Alpes;Rhone-Alpes;217.182.66.229;42000;000;http://ysf-alpes.f4gve.net +13844;FR-YSF-Cappelle;YSF Room F1ZKY;2.59.239.114;42000;000;http://ysf.a3rn.org:2626 +77805;FR-YSF-Dijon;FR YSF Dijon;185.216.25.140;42000;001;http:// +58617;FR-YSF-France;Fusion France;87.98.132.205;42000;037;http://ysf-france.fr/ +64879;FR-YSF-FraWide;France-Wide;5.135.190.184;42010;005;http://ns3294400.ovh.net/YSFDashboard/ +44708;FR-YSF-HBLink;C4FM HBLink TG;82.64.55.217;42000;000;http://ysf-hblink.dyndns.org:8778/ +16762;FR-YSF-HDF;Region Nord;51.15.172.24;42001;000;https://srv.hambox.fr/hdf-dashboard/ +91713;FR-YSF-Limouzi;C4FM Limousin;82.64.55.4;42000;002;http://ysf-limousin.dyndns.org:8787 +34722;FR-YSF-Linux-fr;Linux French;213.32.19.95;42000;000;http://vps.hambox.fr/ysf-linux-fr/ +41576;FR-YSF-Nantes;YSF Room F5ZLK;92.222.75.165;42000;003;http://www.f5ore.dyndns.org +46353;FR-YSF-Nord;Nord;178.32.163.106;42000;002;http:// +24703;FR-YSF-NordOuest;XLX933-E;78.206.208.208;42000;001;http://78.206.208.208:8081/YSFReflector-Dashboard/index.php +59495;FR-YSF-St-Amand;St Amand (59);51.15.172.24;42000;000;http:// +04170;FR-YSF-TEST;France-Tests;51.75.133.61;42000;000;http://vps731279.ovh.net/ +39300;FR-YSF-URGENCE;FR-emcom;78.206.208.208;42021;003;https://fr-emcom.com/ +87357;GB-2E0ENN-DIRECT;Direct Server;86.181.36.50;42003;000;http:// +46504;GB-400-Club;400 Club;157.245.45.67;42008;001;https://400club.446em.uk +91153;GB-4SQITYSF;4SquareIT YSF;34.89.92.173;42000;000;http://ysf.eilec.com +01918;GB-Allstars;Fusion Allstrs;81.133.73.69;42002;005;http:// +88473;GB-BARC-CLUB;Burnham On Sea;88.97.60.42;42002;003;http://88.97.60.42:8080/ +42233;GB-BLIND-VETS;Blind Veterans;159.65.16.93;42000;005;http:// +70507;GB-CelticCluster;YSF-Reflector;85.159.210.162;42000;000;https://ysfref.celticcluster.org +88972;GB-CovARS;Coventry ARS;18.130.199.150;42001;001;http://ysf2.g1iul.org.uk +23952;GB-CQ-Sussex;All Welcome;84.9.168.216;42002;001;http:// +19889;GB-Dartmoor-Room;Dartmoor Area;80.229.144.250;42002;001;http:// +64259;GB-Durham;YSFReflector;34.89.108.212;42000;000;http:// +91767;GB-Fusion-Kernow;Fusion SW UK;87.117.229.165;43000;001;http://ysf.mb6cc.co.uk +08248;GB-GX4MWS-Club;Macc A.R. Club;188.165.209.35;42000;000;http:// +16437;GB-hideout;xlx201;157.245.45.67;42003;001;https://ukhide.446em.uk +57727;GB-HUBNet;Link to HUBNet;5.57.94.92;42000;013;https://hubnetwork.uk/ +84338;GB-M0OUK-Link;www.OARC.uk;165.22.121.251;42002;003;http://ysf.oarc.uk/ +54916;GB-MB6RI;YSFR mb6ri.co.;86.132.7.82;42200;001;http://wires-xuk.sytes.net/ +97576;GB-N.Ireland;YSF N.Ireland;87.117.229.165;42500;002;http:// +13344;GB-North-West-UK;NWRG;209.250.255.162;42000;006;http://209.250.255.162/ +58362;GB-NorthWestLink;TG23520;217.46.179.246;42004;001;http:// +26368;GB-qso365;qso365.co.uk;212.159.79.56;42002;002;http://g6nhu.getmyip.com:8900 +41012;GB-Sandbox;Testing;88.97.60.42;42003;000;http://88.97.60.42:8090 +23551;GB-SCOT-MULTI;SCOTLAND MULTI;92.3.117.38;42000;001;http:// +67256;GB-Smoggie-UK;SMOGGIE LINK;108.61.172.174;42000;004;http:// +62400;GB-W.Mids;IO82UI;86.148.110.250;42021;001;http://wfrg.ddns.net/ +06284;GB-WARC;Warrington ARC;109.148.101.52;42000;004;http:// +93529;GB-WestBerkshire;West Berks UK;62.232.43.186;42000;003;http://m0cuk.uk:8080 +13322;GB-xlx201b;MultiMode;157.245.45.67;42001;001;https://xlx201b.446em.uk +41142;GB-XLX969;Relfector for;142.93.46.36;42000;000;http://xlx969.nwfg.online +27617;GB-YORKSHIRE-YSF;YSF Leeds UK;45.58.139.108;42000;001;http://45.58.139.108/ +23945;GB3TH;Tamworth UK;5.2.112.26;42000;004;http://5.2.112.26 +77817;GB7SJ;Repeater link;217.46.179.246;42000;006;http:// +83260;GR-HellasFame;Greek YSF Test;95.179.190.33;42000;002;http://stargate-dmr.net:8080 +96370;Gr8ter-Detroit;Great Lakes MI;107.141.52.226;42006;001;http:// +89995;Great-Lakes;Great Lakes Ar;107.141.52.226;42003;001;http:// +60237;GT-ASL-48455;AllStar Audio;190.148.222.28;42101;001;http://190.148.222.28:8502/index.php +36606;GT-Guatemala;Enlace DMR+;104.143.94.48;42142;003;http://104.143.94.48/YSFReflector/YSFHBLink/index.php +25419;Guatemala;Link Regional;ysf.tg9aor.net;42000;002;http:// +47247;HB-C4FM-Basel;Gruppo HB9CSR;212.237.33.114;43000;003;http://212.237.33.114/c4fm/index.php +87252;HBLINK-SPAIN;HBLINK SPAIN;85.255.8.71;42000;002;http://hblinkspain.duckdns.org/YSF +73821;HCRA-YSF;HCRA Refl;168.235.80.185;42001;001;http://ysf.nt1k.com +23667;HELLAS-Zone;YSF Reflector;85.93.91.80;42000;016;http://www.hellaszone.com/index.php/ysf-hellas-zone +36039;HK-HAM;YSF<=>454;119.237.142.173;42002;002;http://ysf.852ham.org/ +56322;HN-HONDURAS;YSF Honduras;104.223.170.236;42000;002;http://ysfhonduras.xreflector.es/ +01689;HP-PANAMA-HUB;C4FM DMR;179.63.194.94;42000;013;http://hp-panama-hub.c4fmpanama.org/ +14248;HR-9A-C4FM;9A C4FM HR;35.175.149.169;42000;004;http://35.175.149.169 +18164;HU-Balaton;YSF Siofok;5.189.162.5;42200;002;http://5.189.162.5 +49993;HU-HU-TG2162;BM TG2162;185.187.75.192;42300;003;http://brandmeister.hu/ysfref2162/ +41120;HU-Hungary;BM TG216;185.187.75.192;42100;003;http://brandmeister.hu/ysfref/ +26973;Hudson-City-NJ;YSF Reflector;192.223.27.159;42000;003;http://ysf.dmrnet.net/ysf +52077;IE_YSF_Ireland;Fusion <> DMR;44.155.254.23;42000;004;https://ysf-2724.ei3rcw.ampr.org/index.php +14689;Indiana-Link-So;Bridge:IRLP_00;107.155.116.148;42000;008;http://107.155.116.148/ysf +96014;IRLP_0070;Bridge to 0070;75.127.13.79;42000;003;http://k5nx.com/YSFdashboard +60905;IRLP_0087;Bridge to 0087;192.210.239.5;42000;001;http://k8lrc.crabdance.com/index.php +75373;IT-773Cluster;TG222773 - BM;89.46.75.166;42000;003;http://xlx773.iz0rin.it/ysf/ +92157;IT-APRS-PUGLIA;www.aprspuglia;185.216.27.214;42000;000;http://185.216.27.214/ +54102;IT-ARI-VINCI;C4FM;80.211.99.134;42000;001;http://80.211.99.134 +46773;IT-C4FM-ABRUZZO;IT-DMR 22261;5.88.241.47;42001;003;http://ysf-abruzzo.ariroseto.it/ysf +17120;IT-C4FM-HBLink-D;Zona1 Piemonte;94.177.173.53;42000;001;http://94.177.173.53/ysf/index.php +22201;IT-C4FM-Italy;(YCS222);94.177.187.31;42000;023;http://ycs.grupporadiofirenze.net/ycs/ +16547;IT-C4FM-LECCE;YSFReflector;80.211.133.104;42000;004;http://c4fm-lecce.ddns.net/index.php +16547;IT-C4FM-LECCE;YSFReflector;80.211.133.104;42000;004;http://c4fm-lecce.ddns.net/index.php +30483;IT-C4FM-Lodi;Lombardia;94.177.187.40;42000;004;http://ysflodi.iw2gob.it/c4fm/index.php +14115;IT-C4FM-PUGLIA;DMR TG PUGLIA;95.248.215.75;42000;002;http://ysfpuglia.iz7gll.it:8888 +26765;IT-C4FM-ROSETO;IT-DMR 222035;109.239.250.3;42000;002;http://ysf-roseto.ariroseto.it/ysf +06901;IT-C4FM-TERAMO;C4FM TERAMO;195.32.87.220;42000;000;http://ysf-teramo.ns0.it/ +94514;IT-CALABRIA;MP CALABRIA;185.250.144.228;42000;001;http://185.250.144.228/ +27746;IT-CATANIA;TG22491-BM;91.92.136.252;42000;001;http://91.92.136.252/YSFdash +23740;IT-DGT-Zona-0;Rete DGT zona0;185.177.59.221;42000;001;http://185.177.59.221/YSF/ +47946;IT-Digiland;Italia;82.223.18.138;42000;002;http://82.223.18.138/ysf/index.php +58288;IT-GDO-FUSION;C4FM OSSOLA;88.149.167.221;42000;000;http://iz1zpj.duckdns.org +76421;IT-GIOIATAURO;#76421;80.211.74.187;42000;005;http://ysf.rcdigital.it +26045;IT-GRF-YSF;TUSCANY MULTIP;31.14.142.119;42005;008;http://ysf.grupporadiofirenze.net/ysf_5 +03832;IT-I0-LAZIO;773RadioGroup;93.186.255.126;42000;005;http://ysf.iz0rin.it/ysf +45679;IT-I6-ABRUZZO;IT-I6-ABRUZZO;95.246.180.57;42000;001;http://iz6ouf77.ddns.net/ysf/ +64599;IT-IQ3CR;ARI Belluno;95.233.192.20;42000;000;http://iq3cr.ddns.net/index.php +92365;IT-IS0-Sardegna;Multiprotocoll;51.254.206.201;42000;002;https://ysf.is0.org +18255;IT-ITALIA;YSF Italia CIS;185.177.59.166;42000;002;http:// +18316;IT-ITALY-I2-MI;ITALY-I2-MI;94.33.52.82;42001;002;http://www.iw2hgl.it +82021;IT-IU3GMR-YSF;IU3GMR ROOM;95.233.192.20;43000;000;http://iu3gmr.ddns.net/index.php +05579;IT-PERAZZA;YSF Reflector;195.128.234.114;42001;000;http://ysf.iz6rnd.it +73436;IT-RedNet;Svxlink-net;80.211.239.167;42010;001;http://rednet.iu0krr.it/YSF_2/ +01444;IT-RNG-NET;GRF CLUSTER;164.68.100.69;42444;001;http://XLX038.grupporadiofirenze.net +10885;IT-RNRE-YSF;CROSSLINK;31.14.135.7;42000;001;http://ysf-10885.duckdns.org/ysf/ +34697;IT-SICILIA;#34697;80.211.84.249;42001;004;http://ysf.digitalsicilia.it +12385;IT-TERNI;TERNI TG88;80.211.239.167;42020;001;http://itterni.iu0krr.it/YSF_1/ +79445;IT-TUSCANY;C4FM-DMR-NXDN;80.211.99.134;42001;001;http://80.211.99.134/YSFTuscany/ +71249;IT-UMBRIA;YSF UMBRIA;80.211.239.167;42000;001;http://itumbria.iu0krr.it/YSF_3/ +72983;IT-VENETO;VENETO MULTIP;81.174.3.170;42010;000;http://ysfr.dyndns.org +93884;IT-YSF-BRESCIA;CLUSTER BS;212.237.56.10;42000;001;http://ysf.dmrbrescia.it +28345;IT-YSF-CUNEO;C4FM ROOM CUNE;82.56.147.96;42000;000;http:// +43102;IT-YSF-HBLINK;TG 22200;80.211.64.211;42005;001;https://ysf.hblink.it +65716;IT-YSF-LUCANIA;YSF LUCANIA;51.255.172.249;42001;000;http://ysf.iz8gur.it/ +31585;IT-YSF-NORD;ITALY NORD;212.237.9.215;42000;007;http://ysfitalynord.dyndns.biz/ysf/ +82044;IT-YSFROOM-ITALY;WIRES-X ITALY;80.211.96.39;42000;029;http://ysfroomitaly.iw2gob.it/c4fm/index.php +67411;IT-Zona-4;EmiliaRomagna;212.84.32.29;42000;000;http:// +11881;IT-Zona-9;Sicilia;80.211.62.178;42001;004;http://80.211.62.178/YSF/index.php +22211;IT_C4FM-LIGURIA;Reg. Liguria;212.237.8.77;42004;001;http:// +22236;IT_C4FM-TIGULLIO;Tigullio;188.213.173.69;42000;001;http://c4fm.selfip.com/ +00012;JAPANLINK;Japan link;207.244.224.170;42000;053;http://japanlink.xreflector-jp.org +90219;Jason's-Bar;C4FM Saloon;67.205.134.229;42000;001;http://ysf.w4jmf.com +25383;JP-JAPAN;Fusion Japan;122.222.1.50;42000;017;http://c4fm.owari.biz/ysfref/ +88748;JP-SAKURA-Net;SNWLab Fusion;153.126.179.214;42000;000;http://ysfref.snwlab.net/ +15742;JP-YSF-NAGOYA;YSF;221.170.106.177;42000;013;http://xrf098.mydns.jp:8030 +79605;JP-YSF-ONOGORO;YSF;157.65.31.91;42001;000;http://xlx970.onogoro.net/ +30051;JP-YSFDMR-Net;YSF;211.131.179.106;42000;003;http://ysfreflector.pgw.jp +80960;JP_XRF499;YSF;203.137.76.22;42000;001;http://xrf499.xreflector-jp.org/ysf/ +31983;K8JTK-Hub;DVMIS;149.28.114.219;42001;002;http://YSFReflector31983.K8JTK.org +10482;KAPIHAN;kapihan.net;45.77.186.5;42001;007;http://ysf.kapihan.net +22856;KAPIHAN2;kapihan.net;144.202.99.113;42001;001;http://ysf2.kapihan.net +89902;KB1NE-GROUP;NE Wireless;104.236.92.130;42000;001;http:// +36745;KN6CLM;Elevated RF;107.172.156.110;42000;001;http://107.172.156.110/ +92708;konabarbarian;SF Bay Area;54.197.204.105;42000;002;http:// +48316;KP4GA;Puerto Rico;66.50.96.7;42000;001;http://kp4ga.selfip.com/ +44444;KR1P;YSF to AllStar;166.70.154.77;42225;003;http://ysf.kr1p.org +17077;LaGrandeDigital;www.lagrandefl;99.145.170.193;42000;002;http://digital.lagrandefl.com +33461;LATINOS-UNIDO;HISPANIC TG;174.138.36.176;42000;002;http:// +59933;LibertyNet;W8RFA Free4all;68.60.143.37;42000;000;http:// +15425;LincsLink;14 characters;86.181.36.50;42002;003;http:// +07188;LZ0IOS;Repeater Sofia;46.233.56.166;42005;002;http:// +24597;M1AXM-CQUK;Devon UK;fusion2.m1axm.co.uk;42001;000;http://fusion.m1axm.co.uk +53278;MALLORCA;ZONA EA;82.223.122.28;42000;001;http:// +13827;ME-YSFMontenegro;TG29792;89.188.45.102;43007;004;http://13827ysf.ddns.net +74718;MID-MICHIGAN;GREAT LAKES;107.141.52.226;42005;000;http:// +21505;MIL+VET;Mil and Vets;5.81.41.50;42000;001;http://gb7rn.ddns.net/9111 +23944;MX-Fusion-Mexico;Fusion Mexico;200.57.9.10;42000;004;http://ysf.ared.org.mx +67915;MX-Normex;YSF;208.82.116.113;42000;000;http://208.82.116.113/index.php +11714;MY-Malaysia-Net;Malaysia Net;150.129.184.54;42000;002;http://ysf.dmrnet.org/ysf/index.php +35767;N1AJW-Test-2;Potpourri;104.153.109.57;42005;003;https:// 104.153.109.57 +88843;NA9PL_PAAROS;PAAROS.com;159.203.73.99;42000;004;http://NA9PL.com/YSF/ +77518;NEARC;BM TG 31257;172.245.110.121;42000;001;http://ysf.w0jay.com/YSFReflector-Dashboard/index.php +62121;NEMARC-Fusion;NEMARC;3.225.138.100;42003;005;http://k2ej-ysf.ddns.net/ +45734;NETSWATbg;YSF SWATbg NET;94.26.58.60;42005;000;https://ysf.swat.bg +32772;NL-C4FM-Dutch;NL C4FM Dutch;81.169.224.52;42000;002;http://nlc4fmdutch.pa7lim.nl +96455;NL-Central;Centraal NL;90.145.156.242;42000;079;http://c4fm.digitalevoice.nl +31911;NL-DARES;EMCOMM NL;80.115.153.238;42000;000;http://dares.ham-radio-op.net:8080 +20070;NL-Hobbyscoop;hobbyscoop.nl;44.137.42.25;42000;004;http://fusion.pi9noz.ampr.org +20431;NL-Limburg;Goojundaag LB;37.97.194.88;42002;001;http://limburg.is-very-nice.org +73238;NL-Noord;test reflector;44.137.87.82;42000;002;http://44.137.87.82/index.php +63539;NL-Oost;test reflector;44.137.87.83;42000;002;http://44.137.87.83/index.php +59819;NL-PA0ROB;test nlx204;82.171.119.45;42004;000;http://nlpa0rob.ddns.net/ +01966;NL-PD4MM;Marcel QPO;80.115.153.238;42004;001;http://pd4mm.nl +73443;NL-PI1DAF;Multi Repeater;86.80.221.107;42000;002;http:/pd0poh.ddns.net +91665;NL-RNLMC;Marine Corps;95.111.246.149;42001;001;http://Marines.Ham-Radio-OP.net +63234;NL-TechTalk;204_Z - TG2045;82.171.119.45;42002;002;http://nltechtalk.ddns.net +71117;NL-TEST;Dutch test;173.249.54.49;42000;002;http://ysftest.pa7lim.nl +76591;NL-XLX204X;Multi Mode [X];82.171.119.45;42003;002;http://nlxlx204x.ddns.net/ +44919;NO-General;Norwegian chat;80.89.46.242;42000;002;http://ysf.hamlabs.no/ysf/index.php +21302;North-Mich;W1WRS repeater;47.224.93.95;42002;002;http://192.168.1.12 +67703;Northern-NH-ASL;US NNHASL;72.73.78.92;42000;001;https://nhhub.wordpress.com/ +33156;NV-Bridge;Fernley, NV;71.89.225.19;42000;000;http:// +51561;NZ-Ashburton;Repeater;114.23.212.119;42000;008;http://zl4rx.co.nz:89 +59115;NZ-Canterbury-NZ;Wires-X <<>> B;124.197.62.162;42050;002;http://canterburydigitalreflectors.hopto.org +62078;NZ-Christchurch;South Island -;124.197.62.162;42000;001;http://xlx530.hopto.org/YSF +75161;NZ-ROAR-NZ;Rotarians ARNZ;203.86.194.92;42000;001;http://www.xlx299.nz/ysf/ +52755;NZ-Talk;Kiwi Link;123.255.62.27;42000;001;http://nz-talk.ddns.net:89 +29073;NZ-Whangarei;ZL1AMK YSF;218.101.105.192;42000;001;http://zl1amk.ddns.net:85 +33191;NZ-YSF-Reflector;NZ Reflector;114.23.212.119;43000;001;http://zl4rx.co.nz:88 +89797;NZ-YSF-XLX287;ysf.zl2wl.nz;45.32.90.50;42000;001;http://ysf.zl2wl.nz +07338;NZ-YSF-XLX750;http://www.xlx;203.86.206.49;42001;002;http://ysf.xlx750.nz +72753;Oakland;W6OAK;45.77.188.74;42000;001;http://ysf.w6oak.org/ +40557;Ohio-Link---LGLG;OHIO-LINK;209.190.4.10;42000;047;http://ysf.glorb.com +72170;openGD77;openGD77;128.199.76.58;42000;001;http://128.199.76.58/ +52792;Orobie-Reflector;EchoLink Refle;80.211.131.80;42000;002;http://ysf-dagobah.hblink.it/ +15639;Ostsee;Backup DL5CG;91.66.81.13;42001;001;http://dl5cg.ddns.net/ysf +23020;Ottawa-Ont;Canada Link;184.175.49.98;42000;003;http://ysf-ottawa.ddns.net +08344;PA-ysf-hp3icc;Ysf Chiriqui;190.141.113.82;42000;007;http://ysf-hp3icc.ddns.net/ +99999;Parrot;Parrot;137.226.79.115;42020;000;http:// +79383;PH-BISDAK;Bisayang Dako;45.79.92.86;42002;001;http://xlx.dmrphilippines.network/ysfbisdak +59008;PH-DX1AFP;PHILCCOM;167.99.190.123;42100;002;http://167.99.190.123/dx1afp/index.php +78258;PH-DX1PAR;DX1PAR;178.128.216.38;42100;012;http:// +19751;PH-DX1WPI;DX1WPI;167.99.190.123;42000;001;http://167.99.190.123/index.php +18808;PH-DX2ACV;MAHARLIKA;108.61.216.100;42030;005;http://ph-dx2acv.ddns.net +71972;PH-DX7NRD;NORAD7;140.82.14.24;42002;001;http:// +10707;PH-DX9RAG-FDCCU;PH Davao-Cotab;149.28.76.10;42000;001;http://dx9rag-n0mis.ddns.net +09543;PH-MAHARLIKA;MAHARLIKA;149.28.94.53;42100;001;http://149.28.94.53/index.php +43437;PH-WMG-ZAM;WMG;67.205.154.243;42000;004;http:// +08318;PH-YSF-DX3NE;YSF-DX3NE;8.3.29.153;42000;002;http://dx3ne.ddns.net +35328;PIJALNIA-PIWA;OPIS PIJANY;64.53.214.179;42005;000;http://64.53.214.179 +25393;PL-4280;YSF/DMR/DCS132;155.133.14.66;42031;001;https://brandmeister.network/?page=lh&DestinationID=260080 +61266;PL-BRIDGE;Poland BRIDGE;91.197.227.13;42026;000;http://ysfbridge.pzk.pl/ +68368;PL-HBLink;HBLink Polska;80.211.208.227;42080;001;https://ysf.hblink.pl +22538;PL-Kutno;Kutno;77.55.209.188;42078;001;https://ysf.hblink.kutno.pl/ +74359;PL-Local;Local;91.201.88.18;42234;000;http:// +29114;PL-POLAND;YSF PL POLAND;80.211.251.171;42025;016;http:// +15495;PL-POLSKA;POLSKA WIRESX;155.133.14.66;42026;008;http:// +55546;PL-Silesia;Poland Silesia;91.197.227.13;42003;000;http://ysfsilesia.pzk.pl/ +82068;PL-SLASK;Regionalna;91.201.88.18;42237;001;http:// +53245;PL-SP1;YSF SP1;155.133.14.66;42041;000;http://ysf016.wiresx.pl:8081/sp1/ +12508;PL-SP2;YSF SP2;155.133.14.66;42042;000;http://ysf016.wiresx.pl:8081/sp2/ +02328;PL-SP3;YSF SP3;155.133.14.66;42043;000;http://ysf016.wiresx.pl:8081/sp3/ +48598;PL-SP4;YSF SP4;155.133.14.66;42044;000;http://ysf016.wiresx.pl:8081/sp4/ +45300;PL-SP5;YSF SP5;155.133.14.66;42045;000;http://ysf016.wiresx.pl:8081/sp5/ +92967;PL-SP6;YSF SP6;155.133.14.66;42046;000;http://ysf016.wiresx.pl:8081/sp6/ +92078;PL-SP7;YSF SP7;155.133.14.66;42047;000;http://ysf016.wiresx.pl:8081/sp7/ +71372;PL-SP8;YSF SP8;155.133.14.66;42048;000;http://ysf016.wiresx.pl:8081/sp8/ +78984;PL-SP9;YSF SP9;155.133.14.66;42049;000;http://ysf016.wiresx.pl:8081/sp9/ +38691;PL-SR4H;SR4H-ROOM;91.244.185.128;42000;001;http:// +40464;PL-SR7MK;Swiety Krzyz W;155.133.14.66;42024;001;http://ysf016.wiresx.pl:8081/sr7mk/ +40594;PL-SR8DEF;Debica;155.133.14.66;42033;001;http:// +78099;PL-SR8FWD;Wlodawa WiresX;155.133.14.66;42030;001;http://sr8fwd.wiresx.pl +79009;PL-SR8K;Dubiecko;155.133.14.66;42032;002;http://ysf016.wiresx.pl:8081/sr8k/ +91407;PL-SR8LUF;Lublin;155.133.14.66;42028;001;http://ysf016.wiresx.pl:8081/sr8luf/ +87318;PL-SR8UVC;Chotylow;155.133.14.66;42034;001;http:// +54644;PL-SR8UWD;Wlodawa YSF;155.133.14.66;42027;001;http://sr8uwd.wiresx.pl +64506;PL-SR8WD;Wlodawa;155.133.14.66;42029;001;http://ysf016.wiresx.pl:8081/sr8dmr/ +83600;PL-SR9DBN;Myslowice;91.201.88.18;42235;001;http:// +39816;PL-SR9DX;Bytom;85.11.120.150;42223;001;http://www.dx.katowice.pl +52742;PL-WARMIA-MAZURY;Elblag;109.241.51.213;42055;003;http://sp2wlf.tplinkdns.com/ +09815;PL-XLX132;D-Star Gateway;91.203.55.87;42001;002;http://xlx132.dstar.radom.pl/ysf/ +80986;PL-YSF260;BM TG260;155.133.14.66;42035;003;http://ysf016.wiresx.pl:8081/260/ +37358;PLUG;The Philly LUG;173.12.0.169;42000;003;http://ham.daotechnologies.com/ysf-dashboard +92044;PR-KP4CA;Boriken DMR Ne;64.154.38.101;42000;003;http://boriken-ysf.ddns.net/ +02986;PT-YSF009;C4FM-Portugal;109.71.44.237;42000;002;http://c4fm.from-ct.com/ +45742;PT-YSF012;BM2682-Link;194.38.140.204;42100;002;http://ysf012.from-ct.com +52639;PT-YSF268;BM2682-Link;194.38.140.204;42125;001;http://ysf268.from-ct.com +15461;PT-YSF903;BM2682-Link;194.38.140.204;42150;001;http://ysf903.from-ct.com +09658;PT-YSF915;BM2682-Link;164.68.117.231;42000;001;http://ysf915.from-ct.com +30270;PUERTO-RICO;ENLACE BORICUA;162.243.169.90;42000;004;http://kp4msr.praredn.org +45591;QUAHOG-NETWORK;BM-TG-31445;45.77.213.187;42000;002;http://ysf.ridigitallink.net +95623;R.C.-AMIRED---C4;WiresX CATALUN;89.36.215.181;42000;016;http://89.36.215.181 +64150;Radio-Oasis;ham radio;50.82.207.97;42000;000;http://50.82.207.97/dashboard +66265;Randin;RCRG (Ki4eki);75.145.198.42;42000;001;http:// +23531;RAYNET-UK;RAYNET-UK_YSF_;51.91.78.118;42001;007;http://23531.raynet-uk.net/ +31444;RI-DIGITAL-LINK;BM-TG-31444;155.138.201.254;42000;002;http://c4fm.ridigitallink.net/ +43537;RO-YO-EmCom;EmCom Romania;89.33.44.100;42112;003;http://yo2loj.ro/emcom +03435;RO-YSF-BM-226;YSF BM TG226;89.33.44.100;42002;003;http://ysf2bm.hamnet.ro +95093;RO-YSF-DMR-YO-W;YSF DMR+ Link;89.33.44.100;42007;005;http://ysf2dmr.hamnet.ro +75904;RRARE-OKTX;Red RiverOK/TX;18.218.160.231;42000;002;http://18.218.160.231/index.php +40387;RU-DMR;TG2503;188.42.30.175;42000;004;https://ysf.dstar.su/dash/ +39544;RU-KAVKAZ;North Caucasus;37.18.35.2;42000;003;http://kavkaz.qrz.ru/YSF/ +09020;RU-KRSNDR;Krasnodar;176.192.125.46;42002;001;http://c4fm.tk/YSF3/index.php +67143;RU-MAYKOP;Maykop;176.192.125.46;42005;001;http://176.192.125.46/YSF5/ +27797;RU-MOSCOW;MOSKWA;128.0.132.69;42000;003;http://128.0.132.69 +31022;RU-POCTOB;Rostov-Don;83.69.77.96;42000;001;http://c4fm.xyz/our-c4fm-wires-x-room.php +11193;RU-RADIOCULT;YSF;91.247.248.67;42000;001;http://ysf.radiocult.su:8083 +17383;RU-SCANNER;Russia;176.192.125.46;42000;004;http://176.192.125.46/YSF/ +58312;RU-SHAKHTY;Shakhty;176.192.125.46;42004;001;http://c4fm.tk/YSF4/ +16530;RU-VLGDNK;Volgodonsk;176.192.125.46;42001;002;http://176.192.125.46/YSF2/ +25641;RUDIVO;YSF;194.182.85.217;42000;008;http://194.182.85.217/ +75294;RV-rpt-group;Rogue Valley;71.94.243.50;42001;001;http:// +23611;SAT-TRAC;TG 31683;192.99.245.120;42001;003;http://192.99.245.120 +40208;SC-Scotland;Scottish YSF;13.69.14.204;42000;018;http://c4fm.dvscotland.net +02868;SCAN-i-546;SCAN-i 546;149.28.202.133;42001;006;http://scanintl.spdns.org +82040;SD_HUB;DMR-ALLSTAR;155.138.225.161;42000;003;http://ysfreflector.sddstar.com +93753;SE-SE0O_CROSS;YSF>DMR TG2400;31.211.216.13;42000;002;http:// +06000;SE-SM4-SE-01302;Fusion to SM4;94.234.176.231;42000;002;http://94.234.176.231:3180 +80858;SE-SWEDEN-HUB;Wires-X, DMR;95.216.151.253;42000;007;http://ysf.forthmeijer.com +69673;SE-TG240240-Link;TG240240 Link;95.216.197.75;42000;003;http://ysf.brandmeister.se +65461;SE-Virginia;Tidewater;71.120.150.136;41500;001;http://71.120.150.136 +30217;SEOH-YSFLINK;SEOH YSFLINK;44.70.25.177;42002;002;http://k8khw.dyndns-remote.com +43075;SE_SwedenLink_28;SE_SwedenLink_;94.254.105.236;42000;002;http://ysfsl.c4fm.se +16390;SG-YSF-V2;SINGAPORE-YSF;14.102.146.160;42002;001;https://ysf.lucifernet.com/ +48857;SI-Slovenia;YSF>DMR TG293;188.230.203.194;42000;004;http://xlx511.ddns.net:46193/index.php +62716;SI-Slovenia2;YSF Slovenia;109.182.208.84;42000;002;http://router.dyn.ts.si:38401/ +98269;SK-B.Bystrica;YFS Slovak;178.143.62.29;42000;002;http://ysfreflektor.koren.network:8080 +83776;SKYNET-YSF;SKYNET/C4FM;167.172.17.107;42000;001;http://c4fm37040.ddns.net/ +28735;SMS1;SMS backup;167.99.135.20;42000;000;http:// +29961;SNARS;SNARS TG31328;162.248.93.209;42000;001;http://ysf.snars.net +27688;SO-Oregon-rc;SO RC;71.94.243.50;42000;002;http://blahdiadem.hopto.org +80956;SuperARC;Phoenix, AZ;69.71.61.230;42000;002;http:// +77982;SZ790;TG46073;58.250.171.29;50790;001;http:// +08580;tgwells-ysf;tgwells-ysf;18.191.186.57;42000;000;http://tgwells.com +40538;The-Missing-Link;Inland Empire;76.174.207.37;42003;001;http://ysfkc6gwf.ddns.net +45800;TheHideoutCrew;Yeet;69.164.222.140;42002;004;http://69.164.222.140/ +31110;Tipton-ARS;Tipton Co, TN;207.65.47.88;42000;000;http:// +22539;TN-NETDA;TN-NETDA;155.138.237.140;42040;006;http:// +44212;TNARES-EAST;TNARES-EAST;155.138.237.140;42110;001;http:// +07683;TNARES-MID;TNARES-MID;155.138.237.140;42120;000;http:// +76787;TNARES-STWIDE;TNARES-STWIDE;155.138.237.140;42100;004;http:// +76805;TNARES-TAC-E;TNARES-TAC-E;155.138.237.140;42140;000;http:// +67313;TNARES-TAC-M;TNARES-TAC-M;155.138.237.140;42150;000;http:// +47567;TNARES-TAC-W;TNARES-TAC-W;155.138.237.140;42160;000;http:// +48064;TNARES-WEST;TNARES-WEST;155.138.237.140;42130;000;http:// +43513;TROJMIASTO;Poland Tricity;195.140.190.58;42000;000;http://ysftricity.ham-dmr.pl/ +30743;TW-HAMTALK;C4FM @HAMTALK;118.150.164.96;42000;004;http://www.hamtalk.net/ysfr +26112;TW-YSF338;YSF@TYARC;114.32.215.38;42000;002;http://ysftw338.ddns.net +39369;UA-Azimuth;Azimuth-club;193.27.208.38;42000;001;http://193.27.208.38 +55467;UA-Dnipro;DMR TG25504;5.255.33.253;42004;001;http:// +57835;UA-Emergency;DMR TG2559;5.255.33.253;42003;001;http:// +46588;UA-Exolink;DMR/C4FM;5.255.33.253;42000;001;http:// +37683;UA-Kyiv-city;DMR TG25501;5.255.33.253;42001;001;http:// +82255;UA-LVOV-YSF;DMR TG25514;134.249.141.148;42002;001;http://ysf82255.uw0wu.ml +50847;UA-Mykolayiv;DMR TG25515;5.255.33.253;42005;001;http:// +85106;UA-Odesa;DMR TG25516;5.255.33.253;42002;001;http:// +88338;UA-UA-Ref;YSF UA reflect;95.216.163.65;42100;001;http://ysf.2ip.ee/dashboard2 +66216;UA-Zakarpatia;DMR TG25507;142.91.158.199;42002;001;http://xrf255.reflector.up4dar.de/ysf/index.php +13201;UK-DVMEGA;DVMEGA CHAT;212.237.34.32;42000;002;http://c4fm.dvmega.co.uk +83087;UK_YSF_BM_UK;UK_Ref_DN_ONLY;87.117.229.171;42000;012;http:// +20087;UNIVERSAL-TWR;SE MI DIGITAL;107.141.52.226;42001;000;http:// +74940;Unix;Unix system ad;185.244.130.88;42002;000;http://ysf.sysprotect.eu +74940;Unix;Unix system ad;185.244.130.88;42002;000;http://ysf.sysprotect.eu +65416;URSALAMANCA;URE SALAMANCA;31.14.139.112;42000;000;http://31.14.139.112 +51380;Uruguay-YSF;UY YSF;201.217.131.107;42000;006;http://cx4ae.no-ip.org +29727;Uruguay-YSF-Char;Uruguay C4FM;201.217.131.106;42000;001;http://ysfuruguay.ddns.net +59210;US-1st-Resp;TGIF TG 450;157.245.247.7;42000;003;http:// +51123;US-31150;Hawaii;149.28.82.52;42000;005;http://149.28.82.52/YSF +44693;US-42001hamshack;paducah;142.93.53.85;42000;000;http:// +09344;US-AC1KV;AC1KV Rptr;140.82.14.24;42000;001;http:// +75056;US-AF4Y;AF4Y Refelctor;107.191.51.252;42000;006;http:// +61482;US-AfterNetK4DJL;AfterNet K4DJL;96.47.95.121;42003;001;http://afternet.alabamalink.info +21988;US-AggielandLink;Aggieland Link;71.252.210.227;42000;000;https://www.aggielandlink.com/Dashboard +57882;US-AK4LT;The Fire Ants;51.79.69.216;42000;002;http:// +75021;US-AMLEG-NCKYP42;KB4KY Repeater;67.215.222.30;42000;000;https://tinyurl.com/y5tlg93t +11689;US-Amsat;Satellite Ops;149.28.241.59;42000;017;http://149.28.241.59 +55223;US-AZ-SEOC;Oro Valley ARC;69.244.58.8;42001;001;http:// +36252;US-AZ-TUCSON;Oro Valley ARC;69.244.58.8;42000;003;http:// +79496;US-Beards-Den;Open Room;68.4.184.234;42200;003;http://k6tvb.isa-geek.com:8888/index.php +00081;US-Berks-County;Pennsylvania;24.152.248.205;42042;000;http:// +85490;US-BM-TG-31083;CO Severe WX;54.191.50.212;42050;001;http://54.191.50.212/ysf2 +99256;US-BM-TG-31088;Colorado HD;54.191.50.212;42005;005;http://54.191.50.212 +97501;US-BRRO;688;54.89.57.238;42000;001;http://xlx688.ab8m.com/ +44742;US-CARA;CARA Group;45.79.93.167;43000;003;http://xlx.cara.nu/ysf +25662;US-Carlisle,PA;N3JUO;174.49.161.236;42002;000;http://ysfcvpa.hopto.org +94390;US-Central-AL;WiresX 21713;99.46.36.113;8001;006;http:// +49235;US-CKRG;Central Kansas;100.25.76.93;42000;004;http:// +44977;US-CNJHAM;Link to XLX020;52.23.107.220;42000;004;http://ysfreflector.kb2ear.net +99032;US-CO-KF0ABA;NOCO Ragchew;73.34.87.216;42000;000;http://ysfnode.jmrust.com/ +53927;US-CO-WE0FUN;Fun Machine Co;199.59.31.9;42000;003;http://c4fm.we0fun.com +23160;US-ColoradoMega;CO Transcode;74.91.118.134;42000;011;http://ysf.parkerradio.org/ysf +71941;US-Connecticut;N1AJW-Test;192.223.31.208;42000;000;https://192.223.31.208 +62608;US-Connecticut-1;CT Chat;192.223.31.208;42010;001;http://192.223.31.208 +91800;US-CQ-California;CAL-YSFtoWires;104.218.36.162;42001;004;http://ysfxlx.dyndns.org +62208;US-CQ-NODAK-A-ZX;CQ NorthDakota;18.217.188.43;42000;006;http://ysf.cqnodak.com +73884;US-craftwerx;team-craftwerx;67.160.251.224;42511;002;http:// +46301;US-CW-Ops;CW Academy/CW;107.182.34.107;42002;002;http://cwopsysf.dyndns.org +50279;US-DUDE-Link;DUDE XLX106;69.163.163.88;42000;008;http://xlx106.dudetronics.com +38542;US-DX-HUB;US DX-HUB;45.32.193.214;42000;000;http://45.32.193.214/YSF +40422;US-DX3CA-OMG;OLD MAN GROUP;149.248.6.211;42000;007;http://dx3caomg.tqhhc.com +23957;US-DX3L-YSF;RIZAL-LATITUDE;140.186.202.60;42000;004;http://latitudeysf.ddns.net +11102;US-DXLINKSYSTEM;DX-LINK SYSTEM;155.138.236.26;42000;003;http://xlx749ysf.drgnz.com +43953;US-East-Pipeline;Link;75.68.143.156;42007;009;http:// +88084;US-EcosDelCoqui;Conociendo Ami;66.223.212.215;42002;003;http://ecosdelcoqui.kl4ne.net +88023;US-EOH-GWY-HUB;X Hub/Bridge;64.154.38.103;42000;001;http://29999.link/YSF +12567;US-ERDN;ERDN YSF Ref;173.208.200.179;42000;001;https://ysf.kc1awv.net/index.php +12567;US-ERDN;ERDN YSF Ref;173.208.200.179;42000;000;https://xlx337.kc1awv.net +13458;US-FACSchool-ARC;New Iberia, LA;98.191.70.50;42000;002;http://longwire.net:8088 +11665;US-Farmers;Farm Talk;67.140.163.107;42010;001;http:// +37921;US-FLORIDA;FL REFLECTOR;76.109.114.132;42000;002;http:// +04154;US-Georgia;Georgia USA;45.32.223.140;42000;000;http://ysf-ga.ka7utd.com/ +99602;US-GulfBeach-FL;Gulfcoastradio;50.116.24.240;42000;006;http://50.116.24.240 +36271;US-GulfCoast-FL;Gulfcoastradio;18.205.34.190;42000;000;http://ysf36271.ddns.net +01896;US-HarleyHangout;DMR_AllStar;38.133.241.80;42000;002;http:// +93877;US-Houston-Texas;Houston Texas;23.30.91.29;42000;002;http://ysf.cognetic.com +01037;US-HRCC-LINK;HRCC LINK;209.182.218.92;42001;007;http://ysf.hrcc.link +02931;US-Hudson-NY;Upstate NY;24.105.206.243;42002;006;http://keetz.mynetgear.com +04400;US-HXO;HXO 31325;162.248.93.209;42005;001;http://ysf.hxo.radio +83132;US-Illinois-Link;Illinois Link;74.208.235.115;42000;016;http://74.208.235.115/YSFReflector-Dashboard/ +02500;US-IL_NGRMARC;NG Radio Club;73.74.148.160;42000;001;http:// +80060;US-JAXBCH-Link;JAX BCH Link;66.177.51.38;42000;000;http:// +68798;US-JerryNet;YSF Reflector;18.216.66.72;42000;002;https://ysf.ad6dm.net +01295;US-JOTA-1;9071;104.200.25.53;42001;001;http:// +27662;US-JOTA-2;9072;104.200.25.53;42002;000;http:// +02177;US-K3IHI-RPT;YSF TG;131.106.30.132;42000;003;http:// +05944;US-K4LPD-YSF;YSFReflector;134.209.44.53;42000;001;http://k4lpd.luisra369.com +32343;US-K4NWS;ALERT-K4NWS;34.219.110.119;42000;001;http://ysf.alert-alabama.org/YSFReflector-Dashboard/ +37581;US-K7SFQ-YSF;K7SFQ YSF Ref;50.39.137.114;42000;000;http:// +12345;US-K9EQ-----DYEF;Development;167.99.150.253;42004;000;http:// +81734;US-K9POL;US K9POL;104.238.162.162;42000;000;http:// +12479;US-Kansas-City;WIRES-X MOKAN;99.169.52.241;42000;006;http://www.salaman.org/ysf +08398;US-Kansas3120;ks-dmr.net;129.130.229.11;42030;004;http://129.130.229.11:15426/3120/ +77661;US-KB1NYT-YSF;Swansea, MA;24.218.238.119;42000;002;http://kb1nyt.hopto.org:8091/ysf +57046;US-KB4OVL;Indian Rvr FL;69.137.164.8;42000;001;http:// +04438;US-KC2RC;KC2RC W-X room;3.82.236.213;42000;004;http://3.82.236.213/ +69140;US-KE4SCS;KE4SCS Rptr;155.138.222.156;42000;000;http://155.138.222.156 +92516;US-Kentucky-LARC;Local Rag Chew;161.35.141.182;42000;001;http:// +43114;US-KENTUCKY-OWWZ;W4IOD Test Ref;76.244.26.57;42000;002;http:// +40806;US-KENTUCKY-WXGC;W4IOD Repeater;167.99.150.253;42002;008;http://mnwis-ysf.ddns.net/W4IOD.php +02824;US-KI5HXE;KI5HXE;157.245.138.123;42000;000;http:// +03772;US-KitsapLink;Kitsap Talk;98.125.77.141;42810;000;http:// +40438;US-KK4OVW-TN-YTR;White House T;104.56.140.47;42000;001;http:// +25956;US-KM4EDS;Blount County;96.47.95.121;42002;003;http://danny.alabamalink.info +93262;US-KO4AXW-7;Richmond, Virg;142.93.202.44;42000;000;http://ko4axw-ysf.ddns.net/index.php +29162;US-Ktown;Los Angeles Kt;104.174.35.78;42002;000;https://192.168.0.40 +43310;US-KU0S;Test Bridged Y;76.196.111.153;42000;002;http://ysf.ku0s.com/dashboard/ +21511;US-KV4S;KV4S;96.47.95.121;42004;002;http://kv4s.alabamalink.info +44967;US-Ky-Hood-Rats;Hood Rats Club;67.140.163.107;42020;001;http://kyhoodrats.ddns.net +97215;US-LEO-ARC;LEO ARC;74.91.116.36;42000;006;http://74.91.116.36 +65982;US-LHSREF;LHS Podcast;67.224.119.40;42000;001;http://reflector.k5tux.us/Dashboard +01240;US-LosAngeles;SocalPinoy;47.180.104.101;42003;002;http://socalpinoy.ddns.net +44428;US-Magnolia-Link;Magnolia Wires;76.107.175.206;42042;001;http:// +87168;US-Marana-AZ;Oro Valley ARC;69.244.58.8;42002;001;http:// +68928;US-MID-TN-RM;Middle Tenn;104.56.140.47;42001;000;http:// +42592;US-MissingLynk;MissingLynk;104.248.12.84;42000;001;http://104.248.12.84 +21493;US-MNWIS----RDNT;21493;167.99.150.253;42000;018;http://mnwis-ysf.ddns.net +77445;US-Muletown-TN;Maury County;104.237.132.247;42000;002;http://104.237.132.247 +43210;US-MVARC----KBNA;MVARC Idaho;167.99.150.253;42003;004;http:// +92059;US-N1TVI;Dew-Cave;159.65.189.183;42001;000;http://n1tvi.net:8081 +93958;US-N4KWT-ALPHA;Louisville, KY;23.126.8.172;42002;000;http://23.126.8.172/index.php +08035;US-N4KWT-BRAVO;Louisville, KY;23.126.8.173;42000;000;http://23.126.8.173/index.php +59680;US-N8RQJ-RPT;WiresX 49602;157.245.93.169;42000;001;http://157.245.93.169 +90882;US-NACS;C4FM;68.232.234.210;42000;001;http:// +54635;US-Nashville-HUB;Nashville-HUB;34.235.143.37;42000;002;http:// +06177;US-NC-440-Link;NC 440 Link;172.104.214.72;42000;001;http://ysf.msmts.com +32398;US-NE-Oregon;Oregon Room;73.25.190.37;42000;002;http:// +56521;US-Nebraska_Hub;D-Star DMR YSF;71.8.194.163;42000;003;http://ysf.ham-radio-op.net +77204;US-Nevada;Nevada TG3132;162.248.93.209;42001;002;http://ysf.snars.net/nevada +93319;US-NgakNgak;Ngakngakan YSF;45.79.92.86;42000;004;http://xlx.dmrphilippines.network/ysf +58333;US-NOMBRA;nombra.tech;172.90.53.5;42001;000;http:// +00561;US-North-America;DVSwitch.org;44.103.34.4;42000;000;http://dvswitch.org/YSF_NA/ +27402;US-Northstar;Northstar Link;149.28.113.51;42000;001;http://149.28.113.51 +83242;US-NW-Ohio;YSF-NW-Ohio;18.188.19.87;42000;001;http://ec2-18-188-19-87.us-east-2.compute.amazonaws.com/ +13070;US-NWMO;NW Missouri;199.188.121.118;42000;001;http://nwmoroom.duckdns.org +53594;US-Ohio;Ohio;192.241.240.7;42000;005;http://ysf.n8qq.com +19053;US-OklahomaLink;RCWA.org;3.208.70.29;42000;013;http://3.208.70.29 +72321;US-OMG-LA-LV;OLD MAN GROUP;149.248.21.148;42002;002;http://omglalv.tqhhc.com +14927;US-OMISS---YSF;YSF Multimode;104.49.29.243;42001;002;http:// +74158;US-Oro-Valley-AZ;Oro Valley ARC;75.146.134.22;42000;023;http:// +59281;US-OVARC-Test;Oro Valley ARC;69.244.58.8;42003;000;http:// +06864;US-Penn-Link_1;XLX045A YSF;54.85.206.3;42000;004;http://xlx045.pennlinkgroup.com/ysfA +20223;US-Penn-Link_2;XLX045D YSF;54.85.206.3;42006;000;http://xlx045.Pennlinkgroup.com/ysfD/ +69186;US-Penn-Link_3;XLX545B YSF;3.215.215.169;42001;001;http://xlx545.pennlinkgroup.com/ysfA +35119;US-Penn-Link_4;XLX045E YSF;54.85.206.3;42001;002;http://xlx045.pennlinkgroup.com/ysfE +92207;US-Penn-Link_5;XLX545E YSF;3.215.215.169;42000;002;http://xlx545.pennlinkgroup.com/ysfE +17947;US-Penn-Link_7;XLX045C YSF;54.85.206.3;42002;001;http://xlx045.Pennlinkgroup.com/ysfC/ +19669;US-Penn-Link_8;XLX545A;3.215.215.169;42002;001;http://xlx545.pennlinkgroup.com/ysfA +69614;US-Phoenix-AZ;Phoenix AZ;68.14.214.57;42500;003;http://68.14.214.57:8080 +30887;US-Phoenix-AZ-2;Phoenix AZ 2;72.194.183.82;42501;001;http://72.194.183.82:8081 +31672;US-Pi-Star-Multi;Pi-Star Multi;142.44.240.244;42000;002;https://multi-reflector.pistar.uk +03169;US-PINOY-5155;PEANUT-PINOY;107.172.83.104;45000;002;http://ysf-p555.ddns.net +00094;US-Pottstown-Pa;Pennsylvania;69.249.242.117;42000;000;http:// +63222;US-QCWA;Chapter 147;94.177.189.17;42000;003;http://94.177.189.17/ysf +63222;US-QCWA;Chapter 147;94.177.189.17;42000;003;http://ysfqcwa.xreflector.es +61324;US-Radio-Kollel;Torah Kollel;54.83.61.74;42000;000;http:// +35010;US-Reddit;DMR TG 98003;74.214.25.135;42000;007;http://xlx216.km8v.com/ +40874;US-REF020A;REF020A Link;52.23.107.220;42100;002;http://ysf020.kb2ear.net +33703;US-RKT-CTY-HSV;RKT.CTY.HSV.AL;136.53.51.207;42000;000;http://136.53.51.207 +84105;US-RMM-YSF;RMM YSF;96.244.208.211;55555;000;http://ysf.robmon.com +92805;US-RocketCity-AL;Huntsville, AL;155.138.207.101;42000;002;http://155.138.207.101 +38469;US-RuralMN-707;Rural MN;24.230.163.50;42000;002;https://707ysf.kd0ioe.com +84398;US-SADRC;SanAntonioDRC;173.226.176.18;42000;017;http:// +52470;US-SARA-QRX-FCMG;Stillwater MN;69.147.211.168;42000;001;http:// +39642;US-Secret-TG;Secret;75.118.136.88;42002;000;http:// +92722;US-Skyhub-Link;Denver SkyHub;65.114.195.171;42000;010;http://kg0sky.duckdns.org/YSFReflector-Dashboard +40861;US-SOMN-----FAPG;SO MN;64.254.189.194;42000;003;http:// +12461;US-South-MS-Net;South MS Net;50.246.136.107;42000;000;http://50.246.136.107:42001 +29364;US-South-Texas;South Texas;76.183.98.122;42011;002;http://ae5jo.bounceme.net +96447;US-SOUTHEASTLINK;Provided by: L;45.32.214.224;42000;009;http://selink.lmarc.net/YSFDash/index.php +73102;US-Southwest-USA;Southwest USA;24.121.90.225;42000;011;http://24.121.90.225:8888/index.php +18503;US-SpaceCityChat;SpaceCityChat;108.209.70.215;42000;001;http://kk4lpo.ddnsgeek.com +95375;US-Steel-City;Pittsburgh, PA;71.60.185.34;42000;000;http://steelcityusa.ddns.net/ +53632;US-TGIF;TGIF 31665;74.91.125.81;42000;003;http://tgif.network/ysf +81342;US-THINKNET;TEXAS US;104.239.146.135;42000;001;http://thinknet.mostlychris.com +23964;US-TREKFAN;TrekFan;138.68.11.56;42000;000;http://skylab.trekfan.org +08106;US-Triangle-Net;Triangle Net;74.91.121.182;42000;001;http:// +15783;US-Truck-Travel;Truck Travel;74.91.121.182;42002;004;http://travel.atruckerslife.com +00546;US-Tucson-AZ;Oro Valley ARC;69.244.58.8;42004;004;http:// +55817;US-Uni-Link;UniversityLink;128.83.129.92;42000;002;http://repeaters.as.utexas.edu/ysf/ +55326;US-US-JOTA;DMR 907;104.200.25.53;42000;001;http:// +03732;US-US-WNY-XRX;XRX Club;98.3.111.214;42000;001;http:// +99539;US-VaDigital;YSF Reflector;3.19.122.217;42000;004;http://ysf.vadigital.network +13120;US-W2MMD-Sknkwks;W2MMD Sknkwks;72.82.133.138;42000;004;http:// +39114;US-W6AUSBeeville;YSF Beeville;151.80.166.60;42000;000;http:// +02512;US-WA-PNW;PNW Rag chew;144.202.95.90;42000;000;http://ysf.kc9gwk.com +07923;US-WA3PNY-GW;Input 1 to Net;3.215.215.169;42003;006;http://xlx545.pennlinkgroup.com/ysfG +64020;US-WA3PNY-GW2;Input 2 to Net;54.85.206.3;42004;002;http://xlx245.pennlinkgroup.com/ysfG2/ +24157;US-Western-NC;WNC and nearby;199.168.200.18;42000;002;http:// +37733;US-WestSide;Waukesha, WI;54.70.201.171;42000;010;http://www.reflectorusa.com +97689;US-Wi-Fi-Talk;Wireless Pros;173.162.46.202;42000;001;http://ysf.n4taj.com:8989 +40396;US-WKENTUCKYDXEB;K4KMW RF Link;68.57.59.67;42000;001;http:// +21335;US-WM-CONNECT;Wires-X 21335;199.85.255.10;42000;009;http://ysfdash.wmtg.me +98899;US-WolfDen;Massachusetts;100.0.63.70;42000;014;http://wolfden.ddnsgeek.com:42080 +31357;US-WU3K;US WU3K;96.255.162.150;42000;000;http:// +19941;US-WV-LINK;WV DIGI LINK;142.93.246.87;42000;002;http:// +73602;US-XLX625;WA8BRO;68.55.76.168;42000;001;http://xlx625.wa8bro.com +55812;US-YSF-FDCCU;US San Diego;104.207.152.88;42000;004;http://ysf-n0mis.ddns.net +98060;US-YSF-Miami;YSF Miami;104.148.41.76;42000;002;http://104.148.41.76 +12224;US-YSF-NE;NEW-ENGLAND;18.204.209.243;42000;002;http:// +41373;US-YSF295;OMIK RADIO;64.137.187.75;42000;002;http://ysf295.dyndns.org +97912;US_SIN_Southern;Indiana_Link;142.93.181.147;42000;019;http://w9windigital.org/ysf +67356;US_SKYNET;SKYNET;104.130.158.171;42000;003;http://ysfdash.mostlychris.com:9000 +82699;VCDRC;VCDRC TG31070;162.248.93.209;42003;001;http://ysf.snars.net/vcdrc/ +20818;VE2YXY-TEST;VE2YXY-TEST;138.197.143.53;42000;001;http:// +21468;WIRES-X;Room 21468;190.148.222.28;42103;000;http:// +38635;Wires-X-YO-W;WiresX Romania;89.33.44.100;42003;001;http://wiresx.hamnet.ro +00008;WORLDLINK;World link;209.126.0.55;42000;017;http://worldlink.pa7lim.nl +27142;W_Tennessee;YSF Reflector;3.15.171.29;42000;001;http:// +18145;XLX000;XLX reflector;45.56.118.86;42000;009;http://xlx000.xlxreflector.org +71981;XLX004;XLX reflector;44.103.34.3;42001;011;http://xlx004.kb8zgl.net +65978;XLX010;XLX reflector;85.197.129.86;42000;105;http://xlx.brandmeister.se +66396;XLX020;XLX reflector;66.175.215.217;42000;019;http://xlx020.k2ie.net +53148;XLX022;XLX reflector;83.137.45.98;42000;081;http://xlx022.tms-it.net +41945;XLX023;XLX reflector;77.85.192.94;42000;015;http://xlx023.ddns.net +86381;XLX026;XLX reflector;209.42.149.140;42000;014;http://xlx026.cnharc.org +29295;XLX029;XLX reflector;45.62.239.138;42000;000;http://029.r2i.net +44644;XLX032;XLX reflector;158.64.26.140;42000;015;http://xlx032.epf.lu +67001;XLX033;XLX reflector;46.226.178.81;42000;009;http://xrf033.dyndns.org +13908;XLX037;XLX reflector;198.100.154.155;42000;002;http://xlx037.ddns.net +82176;XLX038;XLX reflector;164.68.100.69;42000;000;http://xlx038.grupporadiofirenze.net/db/dashboard/ +72207;XLX040;XLX reflector;109.71.45.29;42000;016;http://xrf040.dyndns.org +15976;XLX043;XLX reflector;206.189.239.225;42000;005;http://xlx043.pauldingares.com +80207;XLX046;XLX reflector;98.128.173.195;42000;000;https://xlx.c4fm.se +16909;XLX048;XLX reflector;45.62.213.248;42000;000;http://xlx048.ds6.com +13440;XLX051;XLX reflector;93.186.254.219;42001;037;http://xlx051-ea5spain.duckdns.org +90443;XLX056;XLX reflector;155.138.237.66;42000;008;http://scmidlands.network +89670;XLX062;XLX reflector;52.139.47.149;42000;001;http://xlx.baddogmedia.ca +64547;XLX069;XLX reflector;51.77.213.200;42000;003;http://51.77.213.200/db +42356;XLX070;COVENTRY ARS;18.130.199.150;42000;001;http://xlx070.g1iul.org.uk +67018;XLX077;XLX reflector;23.94.25.146;42000;005;http://xe1dvi.crabdance.com/db/index.php +75749;XLX094;XLX reflector;96.126.124.4;42000;000;http://xlx.txi35hams.com +59637;XLX098;XLX reflector;221.170.106.177;42001;154;http://xrf098.mydns.jp +74096;XLX100;XLX reflector;45.62.241.133;42000;000;http://xlx100.xlxreflector.org +39444;XLX101;XLX reflector;45.62.245.46;42000;000;http://xlx101.xlxreflector.org +57188;XLX102;XLX reflector;45.79.220.142;42000;027;http://xlx102.xlxreflector.org +37102;XLX104;XLX reflector;50.116.38.232;42000;007;http://xlx104.xlxreflector.org +58717;XLX105;XLX reflector;51.254.99.78;42000;003;http://ysf.xrf105.fr +92626;XLX109;XLX reflector;218.221.179.75;42000;001;http://109.bayfm78.tokyo/ +20012;XLX124;XLX reflector;211.14.169.234;42000;140;http://xrf124.xreflector-jp.org +35367;XLX126;XLX reflector;217.173.179.95;42000;002;http://xlx126.noip.pl:8080 +39815;XLX129;XLX reflector;220.145.77.199;42000;190;http://guwgw.cir-ins.com/ +88621;XLX131;XLX reflector;80.127.118.226;42000;004;https://xlx131.pe1er.nl +77462;XLX132;XLX reflector;91.203.55.87;42000;038;http://xlx132.dstar.radom.pl/index.php?show=repeaters +48375;XLX140;WORLDWIDE;95.211.211.145;42000;000;http://xlx140.nix.pt +93407;XLX143;XLX reflector;161.35.235.224;42100;001;http:// +59323;XLX174;XLX reflector;81.169.128.244;42000;007;http://xlx.digitalfunk-nordost.de +07483;XLX175;XLX Reflector;162.248.92.25;38000;000;http://ysf.ke8khn.com +95272;XLX185;XLX reflector;89.215.13.208;42000;011;http://xlx185.lz2kac.org:8680 +86930;XLX200;XLX reflector;62.171.191.147;42000;001;http://xlxzone.net/index.php +62200;XLX201;XLX reflector;157.245.45.67;42000;013;https://xlx201.446em.uk +62862;XLX204;room Z Wires-X;82.171.119.45;42001;023;http://xlx204.ddns.net/ +70248;XLX207;XLX reflector;150.129.138.49;42000;004;http://xlx.br2sy.net +20236;XLX208;XLX reflector;51.178.80.187;42000;016;https://xlx208.f5kav.fr/index.php +60106;XLX220;XLX reflector;124.41.83.11;42000;176;http://xlx220.sapotech.com +79890;XLX227;XLX reflector;89.33.44.100;42000;026;http://xlx227.hamnet.ro +34300;XLX229;XLX reflector;194.191.4.54;42000;047;http://dstar.hamnet.xyz +03349;XLX232;XLX reflector;89.185.97.35;42000;132;http://dstar.oevsv.at/db/index.php?show=modules +66065;XLX240;ZOMBIE-ALERT;107.141.52.226;42000;037;http:// +31725;XLX250;XLX reflector;44.159.15.2;42000;011;https://xlx.ham.in.th +31855;XLX255;UA XLXd255 REF;142.91.158.199;42000;029;http://xrf255.reflector.up4dar.de/db/index.php +10347;XLX256;XLX reflector;162.238.214.18;42000;008;http://162.238.214.18 +24862;XLX257;UA XLXd257 REF;134.249.141.148;42000;003;http://xlxd257.uw0wu.ml +14019;XLX260;XLX reflector;80.211.208.227;42000;008;https://xlx260.hblink.pl +83294;XLX267;XLX reflector;185.244.130.88;42000;000;http://ysf.sysprotect.eu +42725;XLX268;XLX reflector;194.38.140.204;42000;058;https://xlx268.from-ct.com +64702;XLX270;XLX reflector;158.64.26.132;42000;046;https://xlx270.epf.lu/ +44047;XLX290;XLX reflector;44.182.7.20;42000;005;http://xlx.digitalsicilia.it +81632;XLX295;XLX reflector;64.137.161.161;42000;021;http://xlx295.dyndns.org +95424;XLX298;XLX reflector;219.107.78.72;42001;015;http://xrf298.mydns.jp +23565;XLX301;Canberra Link;124.187.44.129;42000;002;http://xlx301.duckdns.org +67862;XLX302;XLX reflector;144.217.241.23;42000;027;http://xlx302.hopto.org/db/ +30362;XLX305;XLX reflector;178.250.54.203;42000;001;http://xlx.m5adi.com/ +35947;XLX307;XLX reflector;72.21.76.154;42000;035;https://xlx307.openquad.net +92688;XLX311;XLX reflector;91.204.44.37;42000;000;https://xlx311.db0he.de +08623;XLX312;TriStateDMR;192.241.160.183;42000;008;http://xlx.dmr-marc.net +29178;XLX314;XLX reflector;186.19.139.15;42000;000;http://xlx314.ddns.net +38481;XLX328;XLX reflector;212.237.33.114;42000;022;http://212.237.33.114/index.php +83603;XLX330;"Megalink 330";44.70.49.128;42000;003;http://xlx.megalink.network +66149;XLX334;XLX reflector;96.47.95.121;42001;058;http://xlx.alabamalink.info +26906;XLX339;Hannover-XLink;nc.hannover-x.link;0;005;https://xlx.hannover-x.link +51599;XLX345;XLX reflector;73.253.128.47;42000;003;http://xlx345.dyndns.org:82 +96507;XLX358;XLX reflector;93.152.167.4;42000;000;http://xlx358.ddns.net/ +22852;XLX359;XLX reflector;94.156.172.213;42000;048;http://xlx359.ddns.net/ +04965;XLX362;XLX reflector;198.166.220.68;42000;002;http://xlx362.gcdtech.ca/index.php +74839;XLX369;XLX reflector;72.89.122.8;42000;005;http://xlx369.w4eae.net +40341;XLX375;XLX reflector;12.221.169.50;42000;001;http:// +88395;XLX377;XLX reflector;186.159.96.100;42000;003;http://xlx.toytron.com +45641;XLX381;TRIANGLE NC;74.91.114.100;42000;006;http://ysf.trianglenc.net +84823;XLX383;Kingsland GA;74.91.121.41;42000;003;http://74.91.121.41 +00389;XLX389;XLX reflector;49.176.201.188;42000;051;http://xlxdmr.duckdns.org/db/ +48042;XLX395;XLX reflector;95.255.196.50;42444;011;http://xlx395.grupporadiofirenze.net +66392;XLX398;XLX reflector;139.64.246.155;42000;000;http://xlx398.dyndns.org +64192;XLX410;XLX-REFLECTOR;166.78.145.146;42000;014;https://xlx.n5amd.com +29299;XLX420;XLX reflector;149.28.54.17;42000;000;https://xlx.cdarin.net +58291;XLX421;XLX reflector;118.189.181.236;42000;041;http://9v1lh.spdns.org:8086/ +45165;XLX422;XLX reflector;93.240.48.68;42200;003;http://dl-nordwest.spdns.de:82/ +26451;XLX425;XLX reflector;77.203.220.188;42000;004;http://srv-xlx.ddns.net +92585;XLX431;XLX reflector;61.195.98.225;42000;240;http://xrf431.xreflector-jp.org/ +62243;XLX434;XLX reflector;51.254.128.134;42001;004;http://51.254.128.134/db +66583;XLX444;XLX reflector;46.38.241.228;42000;057;http://ysf444.pa3dfn.nl +68810;XLX449;XLX reflector;75.68.26.134;42000;000;http://hub.ollieted.com/db/ +90015;XLX450;XLX reflector;45.62.241.140;42000;001;http://xlx450.xlxreflector.org +71743;XLX451;XLX reflector;45.62.239.185;42000;000;http://451.ds6.com +26845;XLX452;XLX reflector;45.62.210.37;42000;000;http://xlx452.ds6.com +26845;XLX452;XLX reflector;206.208.56.14;42000;000;http://xlx451.xreflector.org +97273;XLX453;HKHAM node -1-;61.239.171.240;42000;032;http://xlx453.hkham.org:8087/db +73993;XLX454;HKHAM node -2-;218.103.102.5;42000;059;http://xlx454.hkham.net/ysf +43173;XLX455;XLX reflector;208.71.169.83;42000;002;http:// +93342;XLX456;XLX reflector;54.37.205.183;42000;046;https://xlx456.de +92227;XLX469;XLX reflector;104.207.138.156;42000;001;http://xlx469.kb0isw.com/index.php +98796;XLX479;XLX reflector;198.58.106.10;42000;007;http://zenas.n9ink.net +78936;XLX480;XLX reflector;95.179.145.178;42000;000;http://95.179.145.178 +49716;XLX500;XLX reflector;58.96.21.253;42000;006;http://xlx500.org +51594;XLX502;XLX reflector;190.148.222.28;42102;017;http://190.148.222.28:8503/dashboard/index.php +07490;XLX503;XLX reflector;179.51.0.153;42000;008;http://179.51.0.153:8503/dashboard +71247;XLX504;XLX reflector;200.52.151.155;42000;002;http://200.52.151.155:8504/index.php +85857;XLX505;XLX reflector;45.248.50.37;42000;014;http://vk7hse.duckdns.org/xlx +88194;XLX507;XLX reflector;201.224.1.251;42000;005;http://xlx507.c4fmpanama.org/ +64446;XLX508;XLX508 OWL;185.188.4.15;42000;052;http://xlx508.hb9gfx.ch +12230;XLX514;XLX reflector;203.137.118.143;42000;234;http://xrf514.xreflector-jp.org/ +07475;XLX520;XLX reflector;44.159.15.1;42000;071;http://ysf.dtdxa.com +18807;XLX522;XLX reflector;14.102.146.160;42000;035;https://xlx.lucifernet.com/dashboard/index.php +59245;XLX530;XLX reflector;124.197.62.162;42025;031;http://xlx530.hopto.org +40946;XLX531;XLX reflector;149.28.170.145;42000;035;http://xlx531.drgnz.com +19577;XLX538;XLX reflector;183.76.38.69;42000;139;http://xrf538.mydns.jp +52074;XLX546;XLX reflector;149.28.202.133;42000;001;http://xlxscanintl.spdns.org +52074;XLX546;XLX reflector;149.28.202.133;42000;001;http://scani546.mooo.com +93887;XLX547;XLX reflector;45.77.186.5;42000;005;http://xlx.kapihan.net +83362;XLX548;XLX reflector;144.202.99.113;42000;000;http://xlx2.kapihan.net +28340;XLX560;XLX reflector;150.66.42.72;42000;229;http://xrf560.xreflector-jp.org/ +08806;XLX595;XLX reflector;124.26.61.245;42000;014;http://hamradio.dip.jp +00412;XLX600;XLX reflector;13.69.14.204;42001;045;http://xlx600.dvscotland.net +91682;XLX621;HRCCLINK XLX;209.182.218.92;42000;006;http://xlxd.hrcc.link +36240;XLX634;XLX reflector;150.66.9.57;42000;016;http://xrf634.xreflector-jp.org/ +13946;XLX651;XLX reflector;104.143.94.48;42200;004;http://104.143.94.48/XLX/dashboard/index.php +52732;XLX654;XLX reflector;94.33.52.82;42002;002;http://www.iw2hgl.it:81 +84093;XLX669;XLX reflector;144.202.115.103;42000;003;http://xlx669-maharlika.ddns.net +76138;XLX679;XLX reflector;45.79.180.62;42000;005;http://xlx.borris.me +03560;XLX698;XLX reflector;203.137.123.89;42000;231;http://xrf698.xreflector-jp.org/ +86410;XLX710;XLX reflector;209.126.0.55;42001;000;http://xlx710.pa7lim.nl +51642;XLX711;XLX reflector;192.243.108.150;42000;000;http://xlx711-ni.ddns.net +51265;XLX714;XLX reflector;213.195.111.148;44000;012;http://xlx714.ea3hkb.cat +78911;XLX716;XLX reflector;190.232.249.27;42000;005;http://xlx716.ddns.net/ +88921;XLX725;XLX reflector;172.245.9.180;42000;000;http://xrf725.nq4t.com +84891;XLX741;XLX reflector;203.137.78.41;42000;220;http://xrf741.xreflector-jp.org +59607;XLX748;XLX reflector;64.137.174.49;42000;000;http://xlx748.dyndns.org +89323;XLX749;XLX reflector;45.76.252.9;42000;004;http://xlx749.drgnz.com/ +32748;XLX750;XLX reflector;203.86.206.49;42000;103;http://www.xlx750.nz +41007;XLX751;XLX-REFLECTOR;149.28.71.1;42000;027;https://xlx751.drgnz.com/ +62994;XLX758;XLX reflector;93.240.113.55;42000;001;http:// +73934;XLX760;XLX reflector;172.245.71.164;42000;002;http:// +67173;XLX776;XLX reflector;118.27.26.18;42000;172;http://776.bayfm78.tokyo/ +01906;XLX778;XLX reflector;77.237.7.125;42000;018;https://xlx.hblink.kutno.pl/ +38363;XLX781;XLX reflector;101.143.242.199;42000;240;http://xrf781.xreflector-jp.org/ +45047;XLX799;XLX reflector;37.143.205.157;42000;006;http://xlxsof.ddns.net +53055;XLX800;XLX reflector;87.252.188.119;42000;015;http://xlx800.ddns.net +16226;XLX807;XLX reflector;116.91.197.3;42000;109;http://xrf807.owari.biz +55102;XLX810;XLX reflector;71.41.121.228;42000;003;http://xlx810.xlxreflector.org +48348;XLX812;XLX reflector;203.145.233.141;42000;138;http://xrf812.xreflector-jp.org/ +70562;XLX837;XLX reflector;204.16.243.183;42000;000;http://xlx837.ai3i.net +54890;XLX840;XLX reflector;3.22.173.251;42000;001;http://ysf.lyrg.co.uk/ +51106;XLX847;XLX reflector;204.16.243.184;42000;000;http://xlx847.ai3i.net +23661;XLX857;XLX reflector;204.16.243.185;42000;003;http://xlx857.ai3i.net +39930;XLX860;Allgaeu;24.134.86.93;42000;002;http://db0ess.de +08422;XLX888;XLX reflector;212.237.11.233;42000;019;http://xlx888.duckdns.org/db/index.php +48010;XLX891;XLX reflector;209.251.60.221;42000;007;http://xlx891.cidcomm.com +44904;XLX899;XLX reflector;45.14.224.180;42000;002;http://xlx899.mywire.org/ +71144;XLX905;XLX reflector;94.199.173.123;42000;052;http://xlx905.oe9.at +82567;XLX922;XLX reflector;81.150.10.62;42000;016;https://www.cq-uk.co.uk +52616;XLX934;XLX reflector;79.6.136.177;42000;011;http://xlx934.arifvg.it +70191;XLX945;XLX reflector;213.202.229.40;42000;051;http://dcs945.xreflector.net +94341;XLX950;XLX reflector;158.64.26.134;42000;080;http://xlx950.epf.lu +43446;XLX957;XLX reflector;89.46.67.252;42000;004;http://xlx.dmrbrescia.it/xlxd/ +15401;XLX960;XLX reflector;184.23.183.98;42000;006;http://xlxlist.dyndns.org +13897;XLX965;XLX reflector;80.211.190.216;42000;012;http://xlx965.hblink.it +45678;XLX970;XLX reflector;157.65.31.91;42000;204;http://ysf.onogoro.net/ +96771;XLX973;XLX reflector;211.14.169.43;42000;015;http://xrf973.xreflector-jp.org/ +85560;XLX978;XLX reflector;3.96.147.240;42000;004;http://xlx978.dyndns.org +37815;XLX994;XLX reflector;95.179.231.28;42000;008;https://xlx994.onlineradioclub.org +30906;XLXARG;XLX reflector;45.62.247.43;42000;009;http://xlxarg.no9s.org +91940;XLXCFR;XLX reflector;104.167.102.44;42000;009;http://xlxcfr.no9s.org +50281;XLXGUS;XLX reflector;104.167.112.102;42000;009;http://xlxgus.xlxreflector.org +17004;YO-Wires-X-E;WiresX Romania;85.122.16.152;42000;000;http://85.122.16.152 +48709;YSF-24566;IT RADIOSCOUT;217.182.156.147;42000;000;http://ysf.radioscout.it/YSFReflector-Dashboard/ +75917;YSF-768;Portugal 768;80.211.15.21;42000;002;http://ysf.voxpopuli.pt +54357;YSF-HBL-GDA;HBLink Polska;77.55.212.58;42000;000;http://77.55.212.58:8888 +23053;YSF-IQ2AQ-L;YSF-SVXLINK;80.211.32.170;42000;003;http://80.211.32.170/ysf +06595;YSF-OMEGA;TAMBAYAN C4FM;107.175.49.145;42000;004;http://omegacomm.ddns.net +64915;YSF-PINOY;SPECTRUM;144.202.115.103;42030;006;http://ysf-pinoyspectrum.ddns.net +98022;YSF-PUSA;YSF-PUSA;149.248.7.112;42000;000;http://ab6bp.ddns.net +01183;YSF-TAMBAYAN;TAMBAYAN;47.157.208.97;42050;000;http://ysf-pinoytambayan.ddns.net +26626;YSF-TI;YSF Tango Indi;165.227.115.205;42000;002;http://xrf.ossdr.com/ysf +77299;YSF-TSIONG;Tambayan;107.175.215.106;42050;000;http://tsiong.ddns.net +41577;YSF-YO-W;Fusion Romania;89.33.44.100;42001;004;http://ysf.hamnet.ro +94614;YSF004;US Michigan Ro;44.103.34.3;42000;001;http://ysf004.kb8zgl.net/YSFReflector +43223;YSF2WIRESX;WIRESX 43223;104.143.94.48;42424;004;http:// +49868;YSF345;USA CTDGroup;73.253.128.47;42002;001;http://ysf345.dyndns.org:82/YSF/ +86137;ysf4aws;ysf4aws;18.210.76.48;42000;000;http:// +88240;ZOMBIE-ALERT;WiresX #28298;107.141.52.226;42009;016;http://zombiealert.ddns.net diff --git a/DGIdGateway/YSFHostsupdate.sh b/DGIdGateway/YSFHostsupdate.sh new file mode 100755 index 0000000..89314a8 --- /dev/null +++ b/DGIdGateway/YSFHostsupdate.sh @@ -0,0 +1,91 @@ +#! /bin/bash + +############################################################################### +# +# YSFHostsupdate.sh +# +# Copyright (C) 2016 by Tony Corbett G0WFV +# Adapted to YSFHosts by Paul Nannery KC2VRJ on 6/28/2016 with all crdeit +# to G0WFV for the orignal script. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +############################################################################### +# +# On a Linux based system, such as a Raspberry Pi, this script will perform all +# the steps required to maintain the YSFHosts.txt (or similar) file for you. +# +# It is designed to run from crontab and will download the YSFHosts from the +# master ysfreflector.de database and optionally keep a backup of previously +# created files for you. +# +# It will also prune the number of backup files according to a value specified +# by you in the configuration below. +# +# To install in root's crontab use the command ... +# +# sudo crontab -e +# +# ... and add the following line to the bottom of the file ... +# +# 0 0 * * * /path/to/script/YSFHostsupdate.sh 1>/dev/null 2>&1 +# +# ... where /path/to/script/ should be replaced by the path to this script. +# +############################################################################### +# +# CONFIGURATION +# +# Full path to YSFHosts +YSFHOSTS=/path/to/YSFHosts.txt + +# How many YSFHosts files do you want backed up (0 = do not keep backups) +YSFHOSTSFILEBACKUP=1 + +############################################################################### +# +# Do not edit below here +# +############################################################################### + +# Check we are root +if [ "$(id -u)" != "0" ] +then + echo "This script must be run as root" 1>&2 + exit 1 +fi + +# Create backup of old file +if [ ${YSFHOSTSFILEBACKUP} -ne 0 ] +then + cp ${YSFHOSTS} ${YSFHOSTS}.$(date +%d%m%y) +fi + +# Prune backups +BACKUPCOUNT=$(ls ${YSFHOSTS}.* | wc -l) +BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${YSFHOSTSFILEBACKUP}) + +if [ ${BACKUPCOUNT} -gt ${YSFHOSTSFILEBACKUP} ] +then + for f in $(ls -tr ${YSFHOSTS}.* | head -${BACKUPSTODELETE}) + do + rm -f $f + done +fi + +# Generate YSFHosts.txt file +curl https://register.ysfreflector.de/export_csv.php > ${YSFHOSTS} + +exit 0 diff --git a/DGIdGateway/YSFNetwork.cpp b/DGIdGateway/YSFNetwork.cpp new file mode 100644 index 0000000..91076d1 --- /dev/null +++ b/DGIdGateway/YSFNetwork.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2009-2014,2016,2017,2018 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "YSFDefines.h" +#include "YSFNetwork.h" +#include "Utils.h" +#include "Log.h" + +#include +#include +#include + +const unsigned int BUFFER_LENGTH = 200U; + +CYSFNetwork::CYSFNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug) : +m_socket(address, port), +m_debug(debug), +m_address(), +m_port(0U), +m_poll(NULL), +m_unlink(NULL), +m_buffer(1000U, "YSF Network Buffer"), +m_pollTimer(1000U, 5U), +m_name(), +m_linked(false) +{ + m_poll = new unsigned char[14U]; + ::memcpy(m_poll + 0U, "YSFP", 4U); + + m_unlink = new unsigned char[14U]; + ::memcpy(m_unlink + 0U, "YSFU", 4U); + + std::string node = callsign; + node.resize(YSF_CALLSIGN_LENGTH, ' '); + + for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) { + m_poll[i + 4U] = node.at(i); + m_unlink[i + 4U] = node.at(i); + } +} + +CYSFNetwork::CYSFNetwork(unsigned int port, const std::string& callsign, bool debug) : +m_socket(port), +m_debug(debug), +m_address(), +m_port(0U), +m_poll(NULL), +m_unlink(NULL), +m_buffer(1000U, "YSF Network Buffer"), +m_pollTimer(1000U, 5U) +{ + m_poll = new unsigned char[14U]; + ::memcpy(m_poll + 0U, "YSFP", 4U); + + m_unlink = new unsigned char[14U]; + ::memcpy(m_unlink + 0U, "YSFU", 4U); + + std::string node = callsign; + node.resize(YSF_CALLSIGN_LENGTH, ' '); + + for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) { + m_poll[i + 4U] = node.at(i); + m_unlink[i + 4U] = node.at(i); + } +} + +CYSFNetwork::~CYSFNetwork() +{ + delete[] m_poll; +} + +bool CYSFNetwork::open() +{ + LogMessage("Opening YSF network connection"); + + return m_socket.open(); +} + +void CYSFNetwork::setDestination(const std::string& name, const in_addr& address, unsigned int port) +{ + m_name = name; + m_address = address; + m_port = port; + m_linked = false; +} + +void CYSFNetwork::clearDestination() +{ + m_address.s_addr = INADDR_NONE; + m_port = 0U; + m_linked = false; + + m_pollTimer.stop(); +} + +void CYSFNetwork::write(const unsigned char* data) +{ + assert(data != NULL); + + if (m_port == 0U) + return; + + if (m_debug) + CUtils::dump(1U, "YSF Network Data Sent", data, 155U); + + m_socket.write(data, 155U, m_address, m_port); +} + +void CYSFNetwork::writePoll(unsigned int count) +{ + if (m_port == 0U) + return; + + m_pollTimer.start(); + + for (unsigned int i = 0U; i < count; i++) + m_socket.write(m_poll, 14U, m_address, m_port); +} + +void CYSFNetwork::writeUnlink(unsigned int count) +{ + m_pollTimer.stop(); + + if (m_port == 0U) + return; + + for (unsigned int i = 0U; i < count; i++) + m_socket.write(m_unlink, 14U, m_address, m_port); + + m_linked = false; +} + +void CYSFNetwork::clock(unsigned int ms) +{ + unsigned char buffer[BUFFER_LENGTH]; + in_addr address; + unsigned int port; + + m_pollTimer.clock(ms); + if (m_pollTimer.isRunning() && m_pollTimer.hasExpired()) + writePoll(); + + int length = m_socket.read(buffer, BUFFER_LENGTH, address, port); + if (length <= 0) + return; + + if (m_port == 0U) + return; + + if (address.s_addr != m_address.s_addr || port != m_port) + return; + + if (::memcmp(buffer, "YSFP", 4U) == 0 && !m_linked) { + if (strcmp(m_name.c_str(),"MMDVM")== 0) + LogMessage("Link successful to %s", m_name.c_str()); + else + LogMessage("Linked to %s", m_name.c_str()); + + m_linked = true; + } + + if (m_debug) + CUtils::dump(1U, "YSF Network Data Received", buffer, length); + + unsigned char len = length; + m_buffer.addData(&len, 1U); + + m_buffer.addData(buffer, length); +} + +unsigned int CYSFNetwork::read(unsigned char* data) +{ + assert(data != NULL); + + if (m_buffer.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_buffer.getData(&len, 1U); + + m_buffer.getData(data, len); + + return len; +} + +void CYSFNetwork::close() +{ + m_socket.close(); + + LogMessage("Closing YSF network connection"); +} diff --git a/DGIdGateway/YSFNetwork.h b/DGIdGateway/YSFNetwork.h new file mode 100644 index 0000000..7abb5b6 --- /dev/null +++ b/DGIdGateway/YSFNetwork.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009-2014,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef YSFNetwork_H +#define YSFNetwork_H + +#include "DGIdNetwork.h" +#include "YSFDefines.h" +#include "UDPSocket.h" +#include "RingBuffer.h" +#include "Timer.h" + +#include +#include + +class CYSFNetwork : public CDGIdNetwork { +public: + CYSFNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug); + CYSFNetwork(unsigned int port, const std::string& callsign, bool debug); + virtual ~CYSFNetwork(); + + virtual bool open(); + + virtual void link(); + + void setDestination(const std::string& name, const in_addr& address, unsigned int port); + + virtual void write(unsigned int dgId, const unsigned char* data); + + void writePoll(unsigned int count = 1U); + virtual void unlink(); + + virtual unsigned int read(unsigned int dgId, unsigned char* data); + + virtual void clock(unsigned int ms); + + virtual void close(); + +private: + CUDPSocket m_socket; + bool m_debug; + in_addr m_address; + unsigned int m_port; + unsigned char* m_poll; + unsigned char* m_unlink; + CRingBuffer m_buffer; + CTimer m_pollTimer; + std::string m_name; + bool m_linked; +}; + +#endif diff --git a/DGIdGateway/YSFPayload.cpp b/DGIdGateway/YSFPayload.cpp new file mode 100644 index 0000000..16b4476 --- /dev/null +++ b/DGIdGateway/YSFPayload.cpp @@ -0,0 +1,357 @@ +/* +* Copyright (C) 2016 Jonathan Naylor, G4KLX +* Copyright (C) 2016 Mathias Weyland, HB9FRV +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include "YSFConvolution.h" +#include "YSFPayload.h" +#include "YSFDefines.h" +#include "Utils.h" +#include "CRC.h" +#include "Log.h" + +#include +#include +#include +#include + +const unsigned int INTERLEAVE_TABLE_9_20[] = { + 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, + 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, + 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, + 6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U, + 8U, 48U, 88U, 128U, 168U, 208U, 248U, 288U, 328U, + 10U, 50U, 90U, 130U, 170U, 210U, 250U, 290U, 330U, + 12U, 52U, 92U, 132U, 172U, 212U, 252U, 292U, 332U, + 14U, 54U, 94U, 134U, 174U, 214U, 254U, 294U, 334U, + 16U, 56U, 96U, 136U, 176U, 216U, 256U, 296U, 336U, + 18U, 58U, 98U, 138U, 178U, 218U, 258U, 298U, 338U, + 20U, 60U, 100U, 140U, 180U, 220U, 260U, 300U, 340U, + 22U, 62U, 102U, 142U, 182U, 222U, 262U, 302U, 342U, + 24U, 64U, 104U, 144U, 184U, 224U, 264U, 304U, 344U, + 26U, 66U, 106U, 146U, 186U, 226U, 266U, 306U, 346U, + 28U, 68U, 108U, 148U, 188U, 228U, 268U, 308U, 348U, + 30U, 70U, 110U, 150U, 190U, 230U, 270U, 310U, 350U, + 32U, 72U, 112U, 152U, 192U, 232U, 272U, 312U, 352U, + 34U, 74U, 114U, 154U, 194U, 234U, 274U, 314U, 354U, + 36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U, + 38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U}; + +const unsigned int INTERLEAVE_TABLE_5_20[] = { + 0U, 40U, 80U, 120U, 160U, + 2U, 42U, 82U, 122U, 162U, + 4U, 44U, 84U, 124U, 164U, + 6U, 46U, 86U, 126U, 166U, + 8U, 48U, 88U, 128U, 168U, + 10U, 50U, 90U, 130U, 170U, + 12U, 52U, 92U, 132U, 172U, + 14U, 54U, 94U, 134U, 174U, + 16U, 56U, 96U, 136U, 176U, + 18U, 58U, 98U, 138U, 178U, + 20U, 60U, 100U, 140U, 180U, + 22U, 62U, 102U, 142U, 182U, + 24U, 64U, 104U, 144U, 184U, + 26U, 66U, 106U, 146U, 186U, + 28U, 68U, 108U, 148U, 188U, + 30U, 70U, 110U, 150U, 190U, + 32U, 72U, 112U, 152U, 192U, + 34U, 74U, 114U, 154U, 194U, + 36U, 76U, 116U, 156U, 196U, + 38U, 78U, 118U, 158U, 198U}; + +const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, + 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U}; + +const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +CYSFPayload::CYSFPayload() +{ +} + +CYSFPayload::~CYSFPayload() +{ +} + +bool CYSFPayload::readVDMode1Data(const unsigned char* data, unsigned char* dt) +{ + assert(data != NULL); + assert(dt != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[45U]; + + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p2, p1, 9U); + p1 += 18U; p2 += 9U; + } + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + unsigned char output[23U]; + conv.chainback(output, 176U); + + bool ret = CCRC::checkCCITT16(output, 22U); + if (ret) { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; + + CUtils::dump(1U, "V/D Mode 1 Data", output, 20U); + + ::memcpy(dt, output, 20U); + } + + return ret; +} + +bool CYSFPayload::readVDMode2Data(const unsigned char* data, unsigned char* dt) +{ + assert(data != NULL); + assert(dt != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[25U]; + + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p2, p1, 5U); + p1 += 18U; p2 += 5U; + } + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 100U; i++) { + unsigned int n = INTERLEAVE_TABLE_5_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + unsigned char output[13U]; + conv.chainback(output, 96U); + + bool ret = CCRC::checkCCITT16(output, 12U); + if (ret) { + for (unsigned int i = 0U; i < 10U; i++) + output[i] ^= WHITENING_DATA[i]; + + CUtils::dump(1U, "V/D Mode 2 Data", output, YSF_CALLSIGN_LENGTH); + + ::memcpy(dt, output, YSF_CALLSIGN_LENGTH); + } + + return ret; +} + +bool CYSFPayload::readDataFRModeData1(const unsigned char* data, unsigned char* dt) +{ + assert(data != NULL); + assert(dt != NULL); + + ::memset(dt, ' ', 20U); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[45U]; + + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p2, p1, 9U); + p1 += 18U; p2 += 9U; + } + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + unsigned char output[23U]; + conv.chainback(output, 176U); + + bool ret = CCRC::checkCCITT16(output, 22U); + if (ret) { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; + + CUtils::dump(1U, "FR Mode Data 1", output, 20U); + + ::memcpy(dt, output, 20U); + } + + return ret; +} + +bool CYSFPayload::readDataFRModeData2(const unsigned char* data, unsigned char* dt) +{ + assert(data != NULL); + assert(dt != NULL); + + ::memset(dt, ' ', 20U); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[45U]; + + const unsigned char* p1 = data + 9U; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p2, p1, 9U); + p1 += 18U; p2 += 9U; + } + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + unsigned char output[23U]; + conv.chainback(output, 176U); + + bool ret = CCRC::checkCCITT16(output, 22U); + if (ret) { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; + + CUtils::dump(1U, "FR Mode Data 2", output, 20U); + + ::memcpy(dt, output, 20U); + } + + return ret; +} + +void CYSFPayload::writeDataFRModeData1(const unsigned char* dt, unsigned char* data) +{ + assert(dt != NULL); + assert(data != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char output[25U]; + for (unsigned int i = 0U; i < 20U; i++) + output[i] = dt[i] ^ WHITENING_DATA[i]; + + CCRC::addCCITT16(output, 22U); + output[22U] = 0x00U; + + unsigned char convolved[45U]; + + CYSFConvolution conv; + conv.encode(output, convolved, 180U); + + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } + + unsigned char* p1 = data; + unsigned char* p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p1, p2, 9U); + p1 += 18U; p2 += 9U; + } +} + +void CYSFPayload::writeDataFRModeData2(const unsigned char* dt, unsigned char* data) +{ + assert(dt != NULL); + assert(data != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char output[25U]; + for (unsigned int i = 0U; i < 20U; i++) + output[i] = dt[i] ^ WHITENING_DATA[i]; + + CCRC::addCCITT16(output, 22U); + output[22U] = 0x00U; + + unsigned char convolved[45U]; + + CYSFConvolution conv; + conv.encode(output, convolved, 180U); + + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } + + unsigned char* p1 = data + 9U; + unsigned char* p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) { + ::memcpy(p1, p2, 9U); + p1 += 18U; p2 += 9U; + } +} diff --git a/DGIdGateway/YSFPayload.h b/DGIdGateway/YSFPayload.h new file mode 100644 index 0000000..96d4cf3 --- /dev/null +++ b/DGIdGateway/YSFPayload.h @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2016 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(YSFPayload_H) +#define YSFPayload_H + +#include + +class CYSFPayload { +public: + CYSFPayload(); + ~CYSFPayload(); + + bool readVDMode1Data(const unsigned char* data, unsigned char* dt); + + bool readVDMode2Data(const unsigned char* data, unsigned char* dt); + + bool readDataFRModeData1(const unsigned char* data, unsigned char* dt); + bool readDataFRModeData2(const unsigned char* data, unsigned char* dt); + + void writeDataFRModeData1(const unsigned char* dt, unsigned char* data); + void writeDataFRModeData2(const unsigned char* dt, unsigned char* data); + +private: +}; + +#endif diff --git a/DGIdGateway/YSFReflectors.cpp b/DGIdGateway/YSFReflectors.cpp new file mode 100644 index 0000000..2e97542 --- /dev/null +++ b/DGIdGateway/YSFReflectors.cpp @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "YSFReflectors.h" +#include "Log.h" + +#include +#include +#include +#include +#include +#include + +CYSFReflectors::CYSFReflectors(const std::string& hostsFile) : +m_hostsFile(hostsFile), +m_reflectors() +{ +} + +CYSFReflectors::~CYSFReflectors() +{ + for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) + delete *it; + + m_reflectors.clear(); +} + +bool CYSFReflectors::load() +{ + FILE* fp = ::fopen(m_hostsFile.c_str(), "rt"); + if (fp != NULL) { + char buffer[100U]; + while (::fgets(buffer, 100U, fp) != NULL) { + if (buffer[0U] == '#') + continue; + + char* p1 = ::strtok(buffer, ";\r\n"); + char* p2 = ::strtok(NULL, ";\r\n"); + char* p3 = ::strtok(NULL, ";\r\n"); + char* p4 = ::strtok(NULL, ";\r\n"); + char* p5 = ::strtok(NULL, ";\r\n"); + char* p6 = ::strtok(NULL, "\r\n"); + + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { + std::string host = std::string(p4); + + in_addr address = CUDPSocket::lookup(host); + if (address.s_addr != INADDR_NONE) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = std::string(p1); + refl->m_name = std::string(p2); + refl->m_address = address; + refl->m_port = (unsigned int)::atoi(p5); + + m_reflectors.push_back(refl); + } + } + } + + ::fclose(fp); + } + + size_t size = m_reflectors.size(); + LogInfo("Loaded %u YSF reflectors", size); + + return true; +} + +CYSFReflector* CYSFReflectors::findById(const std::string& id) +{ + for (std::vector::const_iterator it = m_reflectors.cbegin(); it != m_reflectors.cend(); ++it) { + if (id == (*it)->m_id) + return *it; + } + + LogMessage("Trying to find non existent YSF reflector with an id of %s", id.c_str()); + + return NULL; +} + +CYSFReflector* CYSFReflectors::findByName(const std::string& name) +{ + for (std::vector::const_iterator it = m_reflectors.cbegin(); it != m_reflectors.cend(); ++it) { + if (name == (*it)->m_name) + return *it; + } + + LogMessage("Trying to find non existent YSF reflector with a name of %s", name.c_str()); + + return NULL; +} + diff --git a/DGIdGateway/YSFReflectors.h b/DGIdGateway/YSFReflectors.h new file mode 100644 index 0000000..aa17b39 --- /dev/null +++ b/DGIdGateway/YSFReflectors.h @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(YSFReflectors_H) +#define YSFReflectors_H + +#include "UDPSocket.h" + +#include +#include + +class CYSFReflector { +public: + CYSFReflector() : + m_id(), + m_name(), + m_address(), + m_port(0U) + { + } + + std::string m_id; + std::string m_name; + in_addr m_address; + unsigned int m_port; +}; + +class CYSFReflectors { +public: + CYSFReflectors(const std::string& hostsFile); + ~CYSFReflectors(); + + bool load(); + + CYSFReflector* findById(const std::string& id); + CYSFReflector* findByName(const std::string& name); + +private: + std::string m_hostsFile; + std::vector m_reflectors; +}; + +#endif diff --git a/Makefile b/Makefile index dd401bd..8337006 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = YSFGateway YSFParrot YSFReflector +SUBDIRS = DGIdGateway YSFGateway YSFParrot YSFReflector CLEANDIRS = $(SUBDIRS:%=clean-%) INSTALLDIRS = $(SUBDIRS:%=install-%)