Add files via upload

master
EA5SW 8 years ago committed by GitHub
parent b1e63f6faa
commit 124f47981b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,829 @@
/*
* Copyright (C) 2010,2014,2016 by 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; 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 "Golay24128.h"
#include "Hamming.h"
#include "AMBEFEC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT(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_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const unsigned int PRNG_TABLE[] = {
0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU,
0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U,
0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU,
0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU,
0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU,
0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U,
0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU,
0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U,
0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU,
0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU,
0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU,
0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U,
0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U,
0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U,
0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U,
0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U,
0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U,
0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U,
0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U,
0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U,
0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U,
0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U,
0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U,
0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U,
0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU,
0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU,
0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U,
0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU,
0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU,
0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU,
0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU,
0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU,
0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U,
0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU,
0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU,
0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU,
0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U,
0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U,
0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U,
0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U,
0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U,
0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U,
0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U,
0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U,
0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U,
0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U,
0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U,
0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U,
0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U,
0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U,
0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U,
0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU,
0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU,
0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU,
0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U,
0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU,
0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U,
0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU,
0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU,
0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U,
0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU,
0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU,
0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU,
0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U,
0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U,
0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U,
0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U,
0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U,
0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U,
0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U,
0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U,
0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U,
0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U,
0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U,
0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U,
0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U,
0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU,
0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU,
0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU,
0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU,
0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU,
0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U,
0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU,
0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU,
0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU,
0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU,
0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU,
0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U,
0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU,
0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U,
0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U,
0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U,
0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U,
0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U,
0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U,
0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U,
0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U,
0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U,
0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U,
0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U,
0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U,
0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U,
0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U,
0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU,
0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU,
0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU,
0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U,
0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU,
0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U,
0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU,
0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU,
0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU,
0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U,
0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU,
0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU,
0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U,
0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U,
0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U,
0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U,
0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U,
0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U,
0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U,
0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U,
0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U,
0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U,
0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U,
0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U,
0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U,
0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU,
0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU,
0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U,
0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU,
0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU,
0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU,
0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU,
0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU,
0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U,
0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU,
0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU,
0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU,
0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU,
0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U,
0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U,
0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U,
0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U,
0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U,
0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U,
0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U,
0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U,
0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U,
0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U,
0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U,
0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U,
0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U,
0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU,
0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U,
0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU,
0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U,
0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU,
0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU,
0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU,
0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U,
0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU,
0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU,
0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU,
0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU,
0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU,
0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U,
0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U,
0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U,
0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U,
0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U,
0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U,
0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U,
0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U,
0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U,
0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U,
0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U,
0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U,
0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U,
0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU,
0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU,
0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U,
0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU,
0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU,
0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU,
0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U,
0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU,
0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U,
0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU,
0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU,
0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU,
0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U,
0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U,
0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U,
0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U,
0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U,
0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U,
0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U,
0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U,
0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U,
0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U,
0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U,
0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U,
0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U,
0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U,
0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U,
0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU,
0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU,
0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU,
0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U,
0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU,
0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU,
0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU,
0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU,
0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU,
0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U,
0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU,
0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU,
0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U,
0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U,
0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U,
0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U,
0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U,
0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U,
0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U,
0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U,
0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U,
0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U,
0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U,
0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U,
0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U,
0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU,
0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU,
0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU,
0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU,
0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU,
0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U,
0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU,
0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU,
0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU,
0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U,
0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU,
0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U,
0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU,
0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U,
0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U,
0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U,
0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U,
0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U,
0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U,
0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U,
0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U,
0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U,
0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U,
0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U,
0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U,
0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U,
0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU,
0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U,
0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU,
0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU,
0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU,
0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU,
0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU,
0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU,
0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU,
0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU,
0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U,
0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU,
0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU,
0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U,
0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U,
0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U,
0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U,
0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U,
0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U,
0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U,
0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U,
0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U,
0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U,
0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U,
0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U,
0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU,
0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU,
0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU,
0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U,
0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU,
0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU,
0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU,
0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U,
0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU,
0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U,
0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU,
0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU,
0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU,
0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U,
0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U,
0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U,
0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U,
0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U,
0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U,
0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U,
0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U,
0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U,
0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U,
0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U,
0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U,
0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U,
0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU,
0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU,
0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U,
0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU,
0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU,
0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU,
0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU,
0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU,
0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U,
0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU,
0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU,
0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU,
0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU,
0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U,
0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U,
0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U,
0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U,
0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U,
0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U,
0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U,
0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U,
0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U,
0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U,
0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U,
0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U,
0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U,
0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U,
0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU,
0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU,
0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU,
0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U,
0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU,
0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U,
0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU,
0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU,
0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU,
0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU,
0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU,
0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU,
0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U,
0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U,
0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U,
0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U,
0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U,
0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U,
0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U,
0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U,
0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U,
0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U,
0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U,
0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U,
0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U,
0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU,
0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU,
0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU,
0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU,
0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU,
0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U,
0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU,
0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU,
0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU,
0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU,
0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU,
0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U,
0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU,
0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U,
0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U,
0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U,
0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U,
0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U,
0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U,
0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U,
0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U,
0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U,
0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U,
0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U,
0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U,
0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U,
0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U,
0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU,
0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU,
0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU,
0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U,
0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU,
0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U,
0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU,
0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU,
0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU,
0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U,
0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU,
0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U,
0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U,
0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U,
0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U,
0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U,
0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U,
0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U,
0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U,
0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U,
0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U,
0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U};
const unsigned int DMR_A_TABLE[] = { 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U,
48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U};
const unsigned int DMR_B_TABLE[] = {25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U,
2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U};
const unsigned int DMR_C_TABLE[] = {50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U, 23U,
27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U};
const unsigned int DSTAR_A_TABLE[] = {0U, 6U, 12U, 18U, 24U, 30U, 36U, 42U, 48U, 54U, 60U, 66U,
1U, 7U, 13U, 19U, 25U, 31U, 37U, 43U, 49U, 55U, 61U, 67U};
const unsigned int DSTAR_B_TABLE[] = {2U, 8U, 14U, 20U, 26U, 32U, 38U, 44U, 50U, 56U, 62U, 68U,
3U, 9U, 15U, 21U, 27U, 33U, 39U, 45U, 51U, 57U, 63U, 69U};
const unsigned int DSTAR_C_TABLE[] = {4U, 10U, 16U, 22U, 28U, 34U, 40U, 46U, 52U, 58U, 64U, 70U,
5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 59U, 65U, 71U};
const unsigned int IMBE_INTERLEAVE[] = {
0, 7, 12, 19, 24, 31, 36, 43, 48, 55, 60, 67, 72, 79, 84, 91, 96, 103, 108, 115, 120, 127, 132, 139,
1, 6, 13, 18, 25, 30, 37, 42, 49, 54, 61, 66, 73, 78, 85, 90, 97, 102, 109, 114, 121, 126, 133, 138,
2, 9, 14, 21, 26, 33, 38, 45, 50, 57, 62, 69, 74, 81, 86, 93, 98, 105, 110, 117, 122, 129, 134, 141,
3, 8, 15, 20, 27, 32, 39, 44, 51, 56, 63, 68, 75, 80, 87, 92, 99, 104, 111, 116, 123, 128, 135, 140,
4, 11, 16, 23, 28, 35, 40, 47, 52, 59, 64, 71, 76, 83, 88, 95, 100, 107, 112, 119, 124, 131, 136, 143,
5, 10, 17, 22, 29, 34, 41, 46, 53, 58, 65, 70, 77, 82, 89, 94, 101, 106, 113, 118, 125, 130, 137, 142
};
CAMBEFEC::CAMBEFEC()
{
}
CAMBEFEC::~CAMBEFEC()
{
}
unsigned int CAMBEFEC::regenerateDMR(unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned int a1 = 0U, a2 = 0U, a3 = 0U;
unsigned int b1 = 0U, b2 = 0U, b3 = 0U;
unsigned int c1 = 0U, c2 = 0U, c3 = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
unsigned int a1Pos = DMR_A_TABLE[i];
unsigned int b1Pos = DMR_B_TABLE[i];
unsigned int c1Pos = DMR_C_TABLE[i];
unsigned int a2Pos = a1Pos + 72U;
if (a2Pos >= 108U)
a2Pos += 48U;
unsigned int b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
unsigned int c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
unsigned int a3Pos = a1Pos + 192U;
unsigned int b3Pos = b1Pos + 192U;
unsigned int c3Pos = c1Pos + 192U;
if (READ_BIT(bytes, a1Pos))
a1 |= MASK;
if (READ_BIT(bytes, a2Pos))
a2 |= MASK;
if (READ_BIT(bytes, a3Pos))
a3 |= MASK;
if (READ_BIT(bytes, b1Pos))
b1 |= MASK;
if (READ_BIT(bytes, b2Pos))
b2 |= MASK;
if (READ_BIT(bytes, b3Pos))
b3 |= MASK;
if (READ_BIT(bytes, c1Pos))
c1 |= MASK;
if (READ_BIT(bytes, c2Pos))
c2 |= MASK;
if (READ_BIT(bytes, c3Pos))
c3 |= MASK;
MASK >>= 1;
}
unsigned int errors = regenerate(a1, b1, c1, true);
errors += regenerate(a2, b2, c2, true);
errors += regenerate(a3, b3, c3, true);
MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
unsigned int a1Pos = DMR_A_TABLE[i];
unsigned int b1Pos = DMR_B_TABLE[i];
unsigned int c1Pos = DMR_C_TABLE[i];
unsigned int a2Pos = a1Pos + 72U;
if (a2Pos >= 108U)
a2Pos += 48U;
unsigned int b2Pos = b1Pos + 72U;
if (b2Pos >= 108U)
b2Pos += 48U;
unsigned int c2Pos = c1Pos + 72U;
if (c2Pos >= 108U)
c2Pos += 48U;
unsigned int a3Pos = a1Pos + 192U;
unsigned int b3Pos = b1Pos + 192U;
unsigned int c3Pos = c1Pos + 192U;
WRITE_BIT(bytes, a1Pos, a1 & MASK);
WRITE_BIT(bytes, a2Pos, a2 & MASK);
WRITE_BIT(bytes, a3Pos, a3 & MASK);
WRITE_BIT(bytes, b1Pos, b1 & MASK);
WRITE_BIT(bytes, b2Pos, b2 & MASK);
WRITE_BIT(bytes, b3Pos, b3 & MASK);
WRITE_BIT(bytes, c1Pos, c1 & MASK);
WRITE_BIT(bytes, c2Pos, c2 & MASK);
WRITE_BIT(bytes, c3Pos, c3 & MASK);
MASK >>= 1;
}
return errors;
}
unsigned int CAMBEFEC::regenerateDStar(unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned int a = 0U;
unsigned int b = 0U;
unsigned int c = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
if (READ_BIT(bytes, DSTAR_A_TABLE[i]))
a |= MASK;
if (READ_BIT(bytes, DSTAR_B_TABLE[i]))
b |= MASK;
if (READ_BIT(bytes, DSTAR_C_TABLE[i]))
c |= MASK;
MASK >>= 1;
}
unsigned int errors = regenerate(a, b, c, false);
MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
WRITE_BIT(bytes, DSTAR_A_TABLE[i], a & MASK);
WRITE_BIT(bytes, DSTAR_B_TABLE[i], b & MASK);
WRITE_BIT(bytes, DSTAR_C_TABLE[i], c & MASK);
MASK >>= 1;
}
return errors;
}
unsigned int CAMBEFEC::regenerateYSFDN(unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned int a = 0U;
unsigned int b = 0U;
unsigned int c = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
unsigned int aPos = DMR_A_TABLE[i];
unsigned int bPos = DMR_B_TABLE[i];
unsigned int cPos = DMR_C_TABLE[i];
if (READ_BIT(bytes, aPos))
a |= MASK;
if (READ_BIT(bytes, bPos))
b |= MASK;
if (READ_BIT(bytes, cPos))
c |= MASK;
MASK >>= 1;
}
unsigned int errors = regenerate(a, b, c, true);
MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++) {
unsigned int aPos = DMR_A_TABLE[i];
unsigned int bPos = DMR_B_TABLE[i];
unsigned int cPos = DMR_C_TABLE[i];
WRITE_BIT(bytes, aPos, a & MASK);
WRITE_BIT(bytes, bPos, b & MASK);
WRITE_BIT(bytes, cPos, c & MASK);
MASK >>= 1;
}
return errors;
}
unsigned int CAMBEFEC::regenerateIMBE(unsigned char* bytes) const
{
assert(bytes != NULL);
bool orig[144U];
bool temp[144U];
// De-interleave
for (unsigned int i = 0U; i < 144U; i++) {
unsigned int n = IMBE_INTERLEAVE[i];
orig[i] = temp[i] = READ_BIT(bytes, n);
}
// now ..
// 12 voice bits 0
// 11 golay bits 12
//
// 12 voice bits 23
// 11 golay bits 35
//
// 12 voice bits 46
// 11 golay bits 58
//
// 12 voice bits 69
// 11 golay bits 81
//
// 11 voice bits 92
// 4 hamming bits 103
//
// 11 voice bits 107
// 4 hamming bits 118
//
// 11 voice bits 122
// 4 hamming bits 133
//
// 7 voice bits 137
// Process the c0 section first to allow the de-whitening to be accurate
// Check/Fix FEC
bool* bit = temp;
// c0
unsigned int g1 = 0U;
for (unsigned int i = 0U; i < 23U; i++)
g1 = (g1 << 1) | (bit[i] ? 0x01U : 0x00U);
unsigned int c0data = CGolay24128::decode23127(g1);
unsigned int g2 = CGolay24128::encode23127(c0data);
for (int i = 23; i >= 0; i--) {
bit[i] = (g2 & 0x01U) == 0x01U;
g2 >>= 1;
}
bit += 23U;
bool prn[114U];
// Create the whitening vector and save it for future use
unsigned int p = 16U * c0data;
for (unsigned int i = 0U; i < 114U; i++) {
p = (173U * p + 13849U) % 65536U;
prn[i] = p >= 32768U;
}
// De-whiten some bits
for (unsigned int i = 0U; i < 114U; i++)
temp[i + 23U] ^= prn[i];
// c1
g1 = 0U;
for (unsigned int i = 0U; i < 23U; i++)
g1 = (g1 << 1) | (bit[i] ? 0x01U : 0x00U);
unsigned int c1data = CGolay24128::decode23127(g1);
g2 = CGolay24128::encode23127(c1data);
for (int i = 23; i >= 0; i--) {
bit[i] = (g2 & 0x01U) == 0x01U;
g2 >>= 1;
}
bit += 23U;
// c2
g1 = 0;
for (unsigned int i = 0U; i < 23U; i++)
g1 = (g1 << 1) | (bit[i] ? 0x01U : 0x00U);
unsigned int c2data = CGolay24128::decode23127(g1);
g2 = CGolay24128::encode23127(c2data);
for (int i = 23; i >= 0; i--) {
bit[i] = (g2 & 0x01U) == 0x01U;
g2 >>= 1;
}
bit += 23U;
// c3
g1 = 0U;
for (unsigned int i = 0U; i < 23U; i++)
g1 = (g1 << 1) | (bit[i] ? 0x01U : 0x00U);
unsigned int c3data = CGolay24128::decode23127(g1);
g2 = CGolay24128::encode23127(c3data);
for (int i = 23; i >= 0; i--) {
bit[i] = (g2 & 0x01U) == 0x01U;
g2 >>= 1;
}
bit += 23U;
// c4
CHamming::decode15113_1(bit);
bit += 15U;
// c5
CHamming::decode15113_1(bit);
bit += 15U;
// c6
CHamming::decode15113_1(bit);
// Whiten some bits
for (unsigned int i = 0U; i < 114U; i++)
temp[i + 23U] ^= prn[i];
unsigned int errors = 0U;
for (unsigned int i = 0U; i < 144U; i++) {
if (orig[i] != temp[i])
errors++;
}
// Interleave
for (unsigned int i = 0U; i < 144U; i++) {
unsigned int n = IMBE_INTERLEAVE[i];
WRITE_BIT(bytes, n, temp[i]);
}
return errors;
}
unsigned int CAMBEFEC::regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const
{
unsigned int old_a = a;
unsigned int old_b = b;
// For the b23 bypass
bool b24 = (b & 0x01U) == 0x01U;
unsigned int data = CGolay24128::decode24128(a);
unsigned int new_a = CGolay24128::encode24128(data);
// The PRNG
unsigned int p = PRNG_TABLE[data];
b ^= p;
unsigned int datb = CGolay24128::decode24128(b);
unsigned int new_b = CGolay24128::encode24128(datb);
new_b ^= p;
if (b23) {
new_b &= 0xFFFFFEU;
new_b |= b24 ? 0x01U : 0x00U;
}
unsigned int errsA = 0U, errsB = 0U;
unsigned int v = new_a ^ old_a;
while (v != 0U) {
v &= v - 1U;
errsA++;
}
v = new_b ^ old_b;
while (v != 0U) {
v &= v - 1U;
errsB++;
}
if (b23) {
if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
a = 0xF00292U;
b = 0x0E0B20U;
c = 0x000000U;
}
}
a = new_a;
b = new_b;
return errsA + errsB;
}

@ -0,0 +1,39 @@
/*
* Copyright (C) 2010,2014,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(AMBEFEC_H)
#define AMBEFEC_H
class CAMBEFEC {
public:
CAMBEFEC();
~CAMBEFEC();
unsigned int regenerateDMR(unsigned char* bytes) const;
unsigned int regenerateDStar(unsigned char* bytes) const;
unsigned int regenerateYSFDN(unsigned char* bytes) const;
unsigned int regenerateIMBE(unsigned char* bytes) const;
private:
unsigned int regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const;
};
#endif

@ -0,0 +1,139 @@
/*
* File: bch3.c
* Title: Encoder/decoder for binary BCH codes in C (Version 3.1)
* Author: Robert Morelos-Zaragoza
* Date: August 1994
* Revised: June 13, 1997
*
* =============== Encoder/Decoder for binary BCH codes in C =================
*
* Version 1: Original program. The user provides the generator polynomial
* of the code (cumbersome!).
* Version 2: Computes the generator polynomial of the code.
* Version 3: No need to input the coefficients of a primitive polynomial of
* degree m, used to construct the Galois Field GF(2**m). The
* program now works for any binary BCH code of length such that:
* 2**(m-1) - 1 < length <= 2**m - 1
*
* Note: You may have to change the size of the arrays to make it work.
*
* The encoding and decoding methods used in this program are based on the
* book "Error Control Coding: Fundamentals and Applications", by Lin and
* Costello, Prentice Hall, 1983.
*
* Thanks to Patrick Boyle (pboyle@era.com) for his observation that 'bch2.c'
* did not work for lengths other than 2**m-1 which led to this new version.
* Portions of this program are from 'rs.c', a Reed-Solomon encoder/decoder
* in C, written by Simon Rockliff (simon@augean.ua.oz.au) on 21/9/89. The
* previous version of the BCH encoder/decoder in C, 'bch2.c', was written by
* Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) on 5/19/92.
*
* NOTE:
* The author is not responsible for any malfunctioning of
* this program, nor for any damage caused by it. Please include the
* original program along with these comments in any redistribution.
*
* For more information, suggestions, or other ideas on implementing error
* correcting codes, please contact me at:
*
* Robert Morelos-Zaragoza
* 5120 Woodway, Suite 7036
* Houston, Texas 77056
*
* email: r.morelos-zaragoza@ieee.org
*
* COPYRIGHT NOTICE: This computer program is free for non-commercial purposes.
* You may implement this program for any non-commercial application. You may
* also implement this program for commercial purposes, provided that you
* obtain my written permission. Any modification of this program is covered
* by this copyright.
*
* == Copyright (c) 1994-7, Robert Morelos-Zaragoza. All rights reserved. ==
*
* m = order of the Galois field GF(2**m)
* n = 2**m - 1 = size of the multiplicative group of GF(2**m)
* length = length of the BCH code
* t = error correcting capability (max. no. of errors the code corrects)
* d = 2*t + 1 = designed min. distance = no. of consecutive roots of g(x) + 1
* k = n - deg(g(x)) = dimension (no. of information bits/codeword) of the code
* p[] = coefficients of a primitive polynomial used to generate GF(2**m)
* g[] = coefficients of the generator polynomial, g(x)
* alpha_to [] = log table of GF(2**m)
* index_of[] = antilog table of GF(2**m)
* data[] = information bits = coefficients of data polynomial, i(x)
* bb[] = coefficients of redundancy polynomial x^(length-k) i(x) modulo g(x)
* numerr = number of errors
* errpos[] = error positions
* recd[] = coefficients of the received polynomial
* decerror = number of decoding errors (in _message_ positions)
*
*/
#include "BCH.h"
#include <cmath>
#include <cstdio>
#include <cassert>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(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_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const int length = 63;
const int k = 16;
const int g[] = {1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1};
CBCH::CBCH()
{
}
CBCH::~CBCH()
{
}
void CBCH::encode(const int* data, int* bb)
/*
* Compute redundacy bb[], the coefficients of b(x). The redundancy
* polynomial b(x) is the remainder after dividing x^(length-k)*data(x)
* by the generator polynomial g(x).
*/
{
for (int i = 0; i < length - k; i++)
bb[i] = 0;
for (int i = k - 1; i >= 0; i--) {
int feedback = data[i] ^ bb[length - k - 1];
if (feedback != 0) {
for (int j = length - k - 1; j > 0; j--)
if (g[j] != 0)
bb[j] = bb[j - 1] ^ feedback;
else
bb[j] = bb[j - 1];
bb[0] = g[0] && feedback;
} else {
for (int j = length - k - 1; j > 0; j--)
bb[j] = bb[j - 1];
bb[0] = 0;
}
}
}
void CBCH::encode(unsigned char* nid)
{
assert(nid != NULL);
int data[16];
for (int i = 0; i < 16; i++)
data[i] = READ_BIT(nid, i) ? 1 : 0;
int bb[63];
encode(data, bb);
for (int i = 0; i < (length - k); i++) {
bool b = bb[i] == 1;
WRITE_BIT(nid, i + 16U, b);
}
}

33
BCH.h

@ -0,0 +1,33 @@
/*
* 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(BCH_H)
#define BCH_H
class CBCH {
public:
CBCH();
~CBCH();
void encode(unsigned char* data);
private:
void encode(const int* data, int* bb);
};
#endif

@ -0,0 +1,347 @@
/*
* Copyright (C) 2012 by Ian Wraith
* Copyright (C) 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 "BPTC19696.h"
#include "Hamming.h"
#include "Utils.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CBPTC19696::CBPTC19696() :
m_rawData(NULL),
m_deInterData(NULL)
{
m_rawData = new bool[196];
m_deInterData = new bool[196];
}
CBPTC19696::~CBPTC19696()
{
delete[] m_rawData;
delete[] m_deInterData;
}
// The main decode function
void CBPTC19696::decode(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
// Get the raw binary
decodeExtractBinary(in);
// Deinterleave
decodeDeInterleave();
// Error check
decodeErrorCheck();
// Extract Data
decodeExtractData(out);
}
// The main encode function
void CBPTC19696::encode(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
// Extract Data
encodeExtractData(in);
// Error check
encodeErrorCheck();
// Deinterleave
encodeInterleave();
// Get the raw binary
encodeExtractBinary(out);
}
void CBPTC19696::decodeExtractBinary(const unsigned char* in)
{
// First block
CUtils::byteToBitsBE(in[0U], m_rawData + 0U);
CUtils::byteToBitsBE(in[1U], m_rawData + 8U);
CUtils::byteToBitsBE(in[2U], m_rawData + 16U);
CUtils::byteToBitsBE(in[3U], m_rawData + 24U);
CUtils::byteToBitsBE(in[4U], m_rawData + 32U);
CUtils::byteToBitsBE(in[5U], m_rawData + 40U);
CUtils::byteToBitsBE(in[6U], m_rawData + 48U);
CUtils::byteToBitsBE(in[7U], m_rawData + 56U);
CUtils::byteToBitsBE(in[8U], m_rawData + 64U);
CUtils::byteToBitsBE(in[9U], m_rawData + 72U);
CUtils::byteToBitsBE(in[10U], m_rawData + 80U);
CUtils::byteToBitsBE(in[11U], m_rawData + 88U);
CUtils::byteToBitsBE(in[12U], m_rawData + 96U);
// Handle the two bits
bool bits[8U];
CUtils::byteToBitsBE(in[20U], bits);
m_rawData[98U] = bits[6U];
m_rawData[99U] = bits[7U];
// Second block
CUtils::byteToBitsBE(in[21U], m_rawData + 100U);
CUtils::byteToBitsBE(in[22U], m_rawData + 108U);
CUtils::byteToBitsBE(in[23U], m_rawData + 116U);
CUtils::byteToBitsBE(in[24U], m_rawData + 124U);
CUtils::byteToBitsBE(in[25U], m_rawData + 132U);
CUtils::byteToBitsBE(in[26U], m_rawData + 140U);
CUtils::byteToBitsBE(in[27U], m_rawData + 148U);
CUtils::byteToBitsBE(in[28U], m_rawData + 156U);
CUtils::byteToBitsBE(in[29U], m_rawData + 164U);
CUtils::byteToBitsBE(in[30U], m_rawData + 172U);
CUtils::byteToBitsBE(in[31U], m_rawData + 180U);
CUtils::byteToBitsBE(in[32U], m_rawData + 188U);
}
// Deinterleave the raw data
void CBPTC19696::decodeDeInterleave()
{
for (unsigned int i = 0U; i < 196U; i++)
m_deInterData[i] = false;
// The first bit is R(3) which is not used so can be ignored
for (unsigned int a = 0U; a < 196U; a++) {
// Calculate the interleave sequence
unsigned int interleaveSequence = (a * 181U) % 196U;
// Shuffle the data
m_deInterData[a] = m_rawData[interleaveSequence];
}
}
// Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code
void CBPTC19696::decodeErrorCheck()
{
bool fixing;
unsigned int count = 0U;
do {
fixing = false;
// Run through each of the 15 columns
bool col[13U];
for (unsigned int c = 0U; c < 15U; c++) {
unsigned int pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++) {
col[a] = m_deInterData[pos];
pos = pos + 15U;
}
if (CHamming::decode1393(col)) {
unsigned int pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++) {
m_deInterData[pos] = col[a];
pos = pos + 15U;
}
fixing = true;
}
}
// Run through each of the 9 rows containing data
for (unsigned int r = 0U; r < 9U; r++) {
unsigned int pos = (r * 15U) + 1U;
if (CHamming::decode15113_2(m_deInterData + pos))
fixing = true;
}
count++;
} while (fixing && count < 5U);
}
// Extract the 96 bits of payload
void CBPTC19696::decodeExtractData(unsigned char* data) const
{
bool bData[96U];
unsigned int pos = 0U;
for (unsigned int a = 4U; a <= 11U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 16U; a <= 26U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 31U; a <= 41U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 46U; a <= 56U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 61U; a <= 71U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 76U; a <= 86U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 91U; a <= 101U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 106U; a <= 116U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 121U; a <= 131U; a++, pos++)
bData[pos] = m_deInterData[a];
CUtils::bitsToByteBE(bData + 0U, data[0U]);
CUtils::bitsToByteBE(bData + 8U, data[1U]);
CUtils::bitsToByteBE(bData + 16U, data[2U]);
CUtils::bitsToByteBE(bData + 24U, data[3U]);
CUtils::bitsToByteBE(bData + 32U, data[4U]);
CUtils::bitsToByteBE(bData + 40U, data[5U]);
CUtils::bitsToByteBE(bData + 48U, data[6U]);
CUtils::bitsToByteBE(bData + 56U, data[7U]);
CUtils::bitsToByteBE(bData + 64U, data[8U]);
CUtils::bitsToByteBE(bData + 72U, data[9U]);
CUtils::bitsToByteBE(bData + 80U, data[10U]);
CUtils::bitsToByteBE(bData + 88U, data[11U]);
}
// Extract the 96 bits of payload
void CBPTC19696::encodeExtractData(const unsigned char* in) const
{
bool bData[96U];
CUtils::byteToBitsBE(in[0U], bData + 0U);
CUtils::byteToBitsBE(in[1U], bData + 8U);
CUtils::byteToBitsBE(in[2U], bData + 16U);
CUtils::byteToBitsBE(in[3U], bData + 24U);
CUtils::byteToBitsBE(in[4U], bData + 32U);
CUtils::byteToBitsBE(in[5U], bData + 40U);
CUtils::byteToBitsBE(in[6U], bData + 48U);
CUtils::byteToBitsBE(in[7U], bData + 56U);
CUtils::byteToBitsBE(in[8U], bData + 64U);
CUtils::byteToBitsBE(in[9U], bData + 72U);
CUtils::byteToBitsBE(in[10U], bData + 80U);
CUtils::byteToBitsBE(in[11U], bData + 88U);
for (unsigned int i = 0U; i < 196U; i++)
m_deInterData[i] = false;
unsigned int pos = 0U;
for (unsigned int a = 4U; a <= 11U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 16U; a <= 26U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 31U; a <= 41U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 46U; a <= 56U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 61U; a <= 71U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 76U; a <= 86U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 91U; a <= 101U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 106U; a <= 116U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 121U; a <= 131U; a++, pos++)
m_deInterData[a] = bData[pos];
}
// Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code
void CBPTC19696::encodeErrorCheck()
{
// Run through each of the 9 rows containing data
for (unsigned int r = 0U; r < 9U; r++) {
unsigned int pos = (r * 15U) + 1U;
CHamming::encode15113_2(m_deInterData + pos);
}
// Run through each of the 15 columns
bool col[13U];
for (unsigned int c = 0U; c < 15U; c++) {
unsigned int pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++) {
col[a] = m_deInterData[pos];
pos = pos + 15U;
}
CHamming::encode1393(col);
pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++) {
m_deInterData[pos] = col[a];
pos = pos + 15U;
}
}
}
// Interleave the raw data
void CBPTC19696::encodeInterleave()
{
for (unsigned int i = 0U; i < 196U; i++)
m_rawData[i] = false;
// The first bit is R(3) which is not used so can be ignored
for (unsigned int a = 0U; a < 196U; a++) {
// Calculate the interleave sequence
unsigned int interleaveSequence = (a * 181U) % 196U;
// Unshuffle the data
m_rawData[interleaveSequence] = m_deInterData[a];
}
}
void CBPTC19696::encodeExtractBinary(unsigned char* data)
{
// First block
CUtils::bitsToByteBE(m_rawData + 0U, data[0U]);
CUtils::bitsToByteBE(m_rawData + 8U, data[1U]);
CUtils::bitsToByteBE(m_rawData + 16U, data[2U]);
CUtils::bitsToByteBE(m_rawData + 24U, data[3U]);
CUtils::bitsToByteBE(m_rawData + 32U, data[4U]);
CUtils::bitsToByteBE(m_rawData + 40U, data[5U]);
CUtils::bitsToByteBE(m_rawData + 48U, data[6U]);
CUtils::bitsToByteBE(m_rawData + 56U, data[7U]);
CUtils::bitsToByteBE(m_rawData + 64U, data[8U]);
CUtils::bitsToByteBE(m_rawData + 72U, data[9U]);
CUtils::bitsToByteBE(m_rawData + 80U, data[10U]);
CUtils::bitsToByteBE(m_rawData + 88U, data[11U]);
// Handle the two bits
unsigned char byte;
CUtils::bitsToByteBE(m_rawData + 96U, byte);
data[12U] = (data[12U] & 0x3FU) | ((byte >> 0) & 0xC0U);
data[20U] = (data[20U] & 0xFCU) | ((byte >> 4) & 0x03U);
// Second block
CUtils::bitsToByteBE(m_rawData + 100U, data[21U]);
CUtils::bitsToByteBE(m_rawData + 108U, data[22U]);
CUtils::bitsToByteBE(m_rawData + 116U, data[23U]);
CUtils::bitsToByteBE(m_rawData + 124U, data[24U]);
CUtils::bitsToByteBE(m_rawData + 132U, data[25U]);
CUtils::bitsToByteBE(m_rawData + 140U, data[26U]);
CUtils::bitsToByteBE(m_rawData + 148U, data[27U]);
CUtils::bitsToByteBE(m_rawData + 156U, data[28U]);
CUtils::bitsToByteBE(m_rawData + 164U, data[29U]);
CUtils::bitsToByteBE(m_rawData + 172U, data[30U]);
CUtils::bitsToByteBE(m_rawData + 180U, data[31U]);
CUtils::bitsToByteBE(m_rawData + 188U, data[32U]);
}

@ -0,0 +1,47 @@
/*
* Copyright (C) 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.
*/
#if !defined(BPTC19696_H)
#define BPTC19696_H
class CBPTC19696
{
public:
CBPTC19696();
~CBPTC19696();
void decode(const unsigned char* in, unsigned char* out);
void encode(const unsigned char* in, unsigned char* out);
private:
bool* m_rawData;
bool* m_deInterData;
void decodeExtractBinary(const unsigned char* in);
void decodeErrorCheck();
void decodeDeInterleave();
void decodeExtractData(unsigned char* data) const;
void encodeExtractData(const unsigned char* in) const;
void encodeInterleave();
void encodeErrorCheck();
void encodeExtractBinary(unsigned char* data);
};
#endif

@ -0,0 +1,240 @@
/*
* 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 <cstdint>
#include <cstdio>
#include <cassert>
#include <cmath>
const uint8_t CRC8_TABLE[] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31,
0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9,
0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1,
0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE,
0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16,
0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80,
0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8,
0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10,
0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F,
0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7,
0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF,
0xFA, 0xFD, 0xF4, 0xF3, 0x01 };
const uint16_t CCITT16_TABLE1[] = {
0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U,
0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU,
0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U,
0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU,
0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U,
0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU,
0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U,
0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU,
0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U,
0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU,
0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U,
0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U,
0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U,
0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U,
0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U,
0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U,
0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU,
0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U,
0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU,
0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U,
0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU,
0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U,
0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU,
0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U,
0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU,
0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U,
0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU,
0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U,
0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U,
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U };
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 };
bool CCRC::checkFiveBit(bool* in, unsigned int tcrc)
{
assert(in != NULL);
unsigned int crc;
encodeFiveBit(in, crc);
return crc == tcrc;
}
void CCRC::encodeFiveBit(const bool* in, unsigned int& tcrc)
{
assert(in != NULL);
unsigned short total = 0U;
for (unsigned int i = 0U; i < 72U; i += 8U) {
unsigned char c;
CUtils::bitsToByteBE(in + i, c);
total += c;
}
total %= 31U;
tcrc = total;
}
void CCRC::addCCITT162(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::checkCCITT162(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];
}
void CCRC::addCCITT161(unsigned char *in, unsigned int length)
{
assert(in != NULL);
assert(length > 2U);
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0xFFFFU;
for (unsigned int i = 0U; i < (length - 2U); i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]];
crc16 = ~crc16;
in[length - 2U] = crc8[0U];
in[length - 1U] = crc8[1U];
}
bool CCRC::checkCCITT161(const unsigned char *in, unsigned int length)
{
assert(in != NULL);
assert(length > 2U);
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0xFFFFU;
for (unsigned int i = 0U; i < (length - 2U); i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]];
crc16 = ~crc16;
return crc8[0U] == in[length - 2U] && crc8[1U] == in[length - 1U];
}
unsigned char CCRC::crc8(const unsigned char *in, unsigned int length)
{
assert(in != NULL);
uint8_t crc = 0U;
for (unsigned int i = 0U; i < length; i++)
crc = CRC8_TABLE[crc ^ in[i]];
return crc;
}

37
CRC.h

@ -0,0 +1,37 @@
/*
* 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 bool checkFiveBit(bool* in, unsigned int tcrc);
static void encodeFiveBit(const bool* in, unsigned int& tcrc);
static void addCCITT161(unsigned char* in, unsigned int length);
static void addCCITT162(unsigned char* in, unsigned int length);
static bool checkCCITT161(const unsigned char* in, unsigned int length);
static bool checkCCITT162(const unsigned char* in, unsigned int length);
static unsigned char crc8(const unsigned char* in, unsigned int length);
};
#endif

1357
Conf.cpp

File diff suppressed because it is too large Load Diff

380
Conf.h

@ -0,0 +1,380 @@
/*
* Copyright (C) 2015,2016,2017 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 <string>
#include <vector>
class CConf
{
public:
CConf(const std::string& file);
~CConf();
bool read();
// The General section
std::string getCallsign() const;
unsigned int getId() const;
unsigned int getTimeout() const;
bool getDuplex() const;
std::string getDisplay() 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 getLocation() const;
std::string getDescription() const;
std::string getURL() const;
// The Log section
unsigned int getLogDisplayLevel() const;
unsigned int getLogFileLevel() const;
std::string getLogFilePath() const;
std::string getLogFileRoot() const;
// The CW ID section
bool getCWIdEnabled() const;
unsigned int getCWIdTime() const;
std::string getCWIdCallsign() const;
// The DMR Id section
std::string getDMRIdLookupFile() const;
unsigned int getDMRIdLookupTime() const;
// The Modem section
std::string getModemPort() const;
bool getModemRXInvert() const;
bool getModemTXInvert() const;
bool getModemPTTInvert() const;
unsigned int getModemTXDelay() const;
unsigned int getModemDMRDelay() const;
int getModemTXOffset() const;
int getModemRXOffset() const;
int getModemRXDCOffset() const;
int getModemTXDCOffset() const;
float getModemRXLevel() const;
float getModemCWIdTXLevel() const;
float getModemDStarTXLevel() const;
float getModemDMRTXLevel() const;
float getModemYSFTXLevel() const;
float getModemP25TXLevel() const;
std::string getModemRSSIMappingFile() const;
bool getModemTrace() const;
bool getModemDebug() const;
// The UMP section
bool getUMPEnabled() const;
std::string getUMPPort() const;
// The D-Star section
bool getDStarEnabled() const;
std::string getDStarModule() const;
bool getDStarSelfOnly() const;
std::vector<std::string> getDStarBlackList() const;
bool getDStarAckReply() const;
unsigned int getDStarAckTime() const;
bool getDStarErrorReply() const;
bool getDStarRemoteGateway() const;
unsigned int getDStarModeHang() const;
// The DMR section
bool getDMREnabled() const;
bool getDMRBeacons() const;
unsigned int getDMRId() const;
unsigned int getDMRColorCode() const;
bool getDMREmbeddedLCOnly() const;
bool getDMRDumpTAData() const;
bool getDMRSelfOnly() const;
std::vector<unsigned int> getDMRPrefixes() const;
std::vector<unsigned int> getDMRBlackList() const;
std::vector<unsigned int> getDMRWhiteList() const;
std::vector<unsigned int> getDMRSlot1TGWhiteList() const;
std::vector<unsigned int> getDMRSlot2TGWhiteList() const;
unsigned int getDMRCallHang() const;
unsigned int getDMRTXHang() const;
unsigned int getDMRModeHang() const;
// The System Fusion section
bool getFusionEnabled() const;
bool getFusionLowDeviation() const;
bool getFusionRemoteGateway() const;
bool getFusionSelfOnly() const;
bool getFusionSQLEnabled() const;
unsigned char getFusionSQL() const;
unsigned int getFusionModeHang() const;
// The P25 section
bool getP25Enabled() const;
unsigned int getP25Id() const;
unsigned int getP25NAC() const;
bool getP25SelfOnly() const;
bool getP25OverrideUID() const;
bool getP25RemoteGateway() const;
unsigned int getP25ModeHang() const;
// The D-Star Network section
bool getDStarNetworkEnabled() const;
std::string getDStarGatewayAddress() const;
unsigned int getDStarGatewayPort() const;
unsigned int getDStarLocalPort() const;
unsigned int getDStarNetworkModeHang() const;
bool getDStarNetworkDebug() const;
// The DMR Network section
bool getDMRNetworkEnabled() const;
std::string getDMRNetworkAddress() const;
unsigned int getDMRNetworkPort() const;
unsigned int getDMRNetworkLocal() const;
std::string getDMRNetworkPassword() const;
std::string getDMRNetworkOptions() const;
bool getDMRNetworkDebug() const;
unsigned int getDMRNetworkJitter() const;
bool getDMRNetworkSlot1() const;
bool getDMRNetworkSlot2() const;
unsigned int getDMRNetworkModeHang() const;
// The System Fusion Network section
bool getFusionNetworkEnabled() const;
std::string getFusionNetworkMyAddress() const;
unsigned int getFusionNetworkMyPort() const;
std::string getFusionNetworkGatewayAddress() const;
unsigned int getFusionNetworkGatewayPort() const;
unsigned int getFusionNetworkModeHang() const;
bool getFusionNetworkDebug() const;
// The P25 Network section
bool getP25NetworkEnabled() const;
std::string getP25GatewayAddress() const;
unsigned int getP25GatewayPort() const;
unsigned int getP25LocalPort() const;
unsigned int getP25NetworkModeHang() const;
bool getP25NetworkDebug() const;
// The TFTSERIAL section
std::string getTFTSerialPort() const;
unsigned int getTFTSerialBrightness() const;
// The HD44780 section
unsigned int getHD44780Rows() const;
unsigned int getHD44780Columns() const;
std::vector<unsigned int> getHD44780Pins() const;
unsigned int getHD44780i2cAddress() const;
bool getHD44780PWM() const;
unsigned int getHD44780PWMPin() const;
unsigned int getHD44780PWMBright() const;
unsigned int getHD44780PWMDim() const;
bool getHD44780DisplayClock() const;
bool getHD44780UTC() const;
// The Nextion section
std::string getNextionPort() const;
unsigned int getNextionBrightness() const;
bool getNextionDisplayClock() const;
bool getNextionUTC() const;
unsigned int getNextionIdleBrightness() const;
unsigned int getNextionScreenLayout() const;
std::string getNextionFilesConfig() const;
// The OLED section
unsigned char getOLEDType() const;
unsigned char getOLEDBrightness() const;
bool getOLEDInvert() const;
bool getOLEDScroll() const;
// The LCDproc section
std::string getLCDprocAddress() const;
unsigned int getLCDprocPort() const;
unsigned int getLCDprocLocalPort() const;
bool getLCDprocDisplayClock() const;
bool getLCDprocUTC() const;
bool getLCDprocDimOnIdle() const;
private:
std::string m_file;
std::string m_callsign;
unsigned int m_id;
unsigned int m_timeout;
bool m_duplex;
std::string m_display;
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_location;
std::string m_description;
std::string m_url;
unsigned int m_logDisplayLevel;
unsigned int m_logFileLevel;
std::string m_logFilePath;
std::string m_logFileRoot;
bool m_cwIdEnabled;
unsigned int m_cwIdTime;
std::string m_cwIdCallsign;
std::string m_dmrIdLookupFile;
unsigned int m_dmrIdLookupTime;
std::string m_modemPort;
bool m_modemRXInvert;
bool m_modemTXInvert;
bool m_modemPTTInvert;
unsigned int m_modemTXDelay;
unsigned int m_modemDMRDelay;
int m_modemTXOffset;
int m_modemRXOffset;
int m_modemRXDCOffset;
int m_modemTXDCOffset;
float m_modemRXLevel;
float m_modemCWIdTXLevel;
float m_modemDStarTXLevel;
float m_modemDMRTXLevel;
float m_modemYSFTXLevel;
float m_modemP25TXLevel;
std::string m_modemRSSIMappingFile;
bool m_modemTrace;
bool m_modemDebug;
bool m_umpEnabled;
std::string m_umpPort;
bool m_dstarEnabled;
std::string m_dstarModule;
bool m_dstarSelfOnly;
std::vector<std::string> m_dstarBlackList;
bool m_dstarAckReply;
unsigned int m_dstarAckTime;
bool m_dstarErrorReply;
bool m_dstarRemoteGateway;
unsigned int m_dstarModeHang;
bool m_dmrEnabled;
bool m_dmrBeacons;
unsigned int m_dmrId;
unsigned int m_dmrColorCode;
bool m_dmrSelfOnly;
bool m_dmrEmbeddedLCOnly;
bool m_dmrDumpTAData;
std::vector<unsigned int> m_dmrPrefixes;
std::vector<unsigned int> m_dmrBlackList;
std::vector<unsigned int> m_dmrWhiteList;
std::vector<unsigned int> m_dmrSlot1TGWhiteList;
std::vector<unsigned int> m_dmrSlot2TGWhiteList;
unsigned int m_dmrCallHang;
unsigned int m_dmrTXHang;
unsigned int m_dmrModeHang;
bool m_fusionEnabled;
bool m_fusionLowDeviation;
bool m_fusionRemoteGateway;
bool m_fusionSelfOnly;
bool m_fusionSQLEnabled;
unsigned char m_fusionSQL;
unsigned int m_fusionModeHang;
bool m_p25Enabled;
unsigned int m_p25Id;
unsigned int m_p25NAC;
bool m_p25SelfOnly;
bool m_p25OverrideUID;
bool m_p25RemoteGateway;
unsigned int m_p25ModeHang;
bool m_dstarNetworkEnabled;
std::string m_dstarGatewayAddress;
unsigned int m_dstarGatewayPort;
unsigned int m_dstarLocalPort;
unsigned int m_dstarNetworkModeHang;
bool m_dstarNetworkDebug;
bool m_dmrNetworkEnabled;
std::string m_dmrNetworkAddress;
unsigned int m_dmrNetworkPort;
unsigned int m_dmrNetworkLocal;
std::string m_dmrNetworkPassword;
std::string m_dmrNetworkOptions;
bool m_dmrNetworkDebug;
unsigned int m_dmrNetworkJitter;
bool m_dmrNetworkSlot1;
bool m_dmrNetworkSlot2;
unsigned int m_dmrNetworkModeHang;
bool m_fusionNetworkEnabled;
std::string m_fusionNetworkMyAddress;
unsigned int m_fusionNetworkMyPort;
std::string m_fusionNetworkGatewayAddress;
unsigned int m_fusionNetworkGatewayPort;
unsigned int m_fusionNetworkModeHang;
bool m_fusionNetworkDebug;
bool m_p25NetworkEnabled;
std::string m_p25GatewayAddress;
unsigned int m_p25GatewayPort;
unsigned int m_p25LocalPort;
unsigned int m_p25NetworkModeHang;
bool m_p25NetworkDebug;
std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness;
unsigned int m_hd44780Rows;
unsigned int m_hd44780Columns;
std::vector<unsigned int> m_hd44780Pins;
unsigned int m_hd44780i2cAddress;
bool m_hd44780PWM;
unsigned int m_hd44780PWMPin;
unsigned int m_hd44780PWMBright;
unsigned int m_hd44780PWMDim;
bool m_hd44780DisplayClock;
bool m_hd44780UTC;
std::string m_nextionPort;
unsigned int m_nextionBrightness;
bool m_nextionDisplayClock;
bool m_nextionUTC;
unsigned int m_nextionIdleBrightness;
unsigned int m_nextionScreenLayout;
std::string m_nextionFilesConfig;
unsigned char m_oledType;
unsigned char m_oledBrightness;
bool m_oledInvert;
bool m_oledScroll;
std::string m_lcdprocAddress;
unsigned int m_lcdprocPort;
unsigned int m_lcdprocLocalPort;
bool m_lcdprocDisplayClock;
bool m_lcdprocUTC;
bool m_lcdprocDimOnIdle;
};
#endif

@ -0,0 +1,99 @@
/*
* Copyright (C) 2016 by Simon Rune G7RZU
* Copyright (C) 2016,2017 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
*/
#include "DMRAccessControl.h"
#include "Log.h"
#include <algorithm>
#include <vector>
#include <cstring>
std::vector<unsigned int> CDMRAccessControl::m_blackList;
std::vector<unsigned int> CDMRAccessControl::m_whiteList;
std::vector<unsigned int> CDMRAccessControl::m_prefixes;
std::vector<unsigned int> CDMRAccessControl::m_slot1TGWhiteList;
std::vector<unsigned int> CDMRAccessControl::m_slot2TGWhiteList;
bool CDMRAccessControl::m_selfOnly = false;
unsigned int CDMRAccessControl::m_id = 0U;
void CDMRAccessControl::init(const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, bool selfOnly, const std::vector<unsigned int>& prefixes, unsigned int id)
{
m_slot1TGWhiteList = slot1TGWhitelist;
m_slot2TGWhiteList = slot2TGWhitelist;
m_blackList = blacklist;
m_whiteList = whitelist;
m_selfOnly = selfOnly;
m_prefixes = prefixes;
m_id = id;
}
bool CDMRAccessControl::validateSrcId(unsigned int id)
{
if (m_selfOnly) {
if (m_id > 99999999U) // Check that the Config DMR-ID is bigger than 8 digits
return id == m_id / 100U; // Does RF ID match Config ID / 100
else if (m_id > 9999999U) // Check that the Config DMR-ID is bigger than 7 digits
return id == m_id / 10U; // Does RF ID match Config ID / 10
else
return id == m_id;
}
if (std::find(m_blackList.begin(), m_blackList.end(), id) != m_blackList.end())
return false;
unsigned int prefix = id / 10000U;
if (prefix == 0U || prefix > 999U)
return false;
if (!m_prefixes.empty()) {
bool ret = std::find(m_prefixes.begin(), m_prefixes.end(), prefix) == m_prefixes.end();
if (ret)
return false;
}
if (!m_whiteList.empty())
return std::find(m_whiteList.begin(), m_whiteList.end(), id) != m_whiteList.end();
return true;
}
bool CDMRAccessControl::validateTGId(unsigned int slotNo, bool group, unsigned int id)
{
if (!group)
return true;
// TG0 is never valid
if (id == 0U)
return false;
if (slotNo == 1U) {
if (m_slot1TGWhiteList.empty())
return true;
return std::find(m_slot1TGWhiteList.begin(), m_slot1TGWhiteList.end(), id) != m_slot1TGWhiteList.end();
} else {
if (m_slot2TGWhiteList.empty())
return true;
return std::find(m_slot2TGWhiteList.begin(), m_slot2TGWhiteList.end(), id) != m_slot2TGWhiteList.end();
}
}

@ -0,0 +1,44 @@
/*
* Copyright (C) 2016 by Simon Rune G7RZU
* Copyright (C) 2016,2017 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
*/
#if !defined(DMRAccessControl_H)
#define DMRAccessControl_H
#include <vector>
class CDMRAccessControl {
public:
static bool validateSrcId(unsigned int id);
static bool validateTGId(unsigned int slotNo, bool group, unsigned int id);
static void init(const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, bool selfOnly, const std::vector<unsigned int>& prefixes, unsigned int id);
private:
static std::vector<unsigned int> m_blackList;
static std::vector<unsigned int> m_whiteList;
static std::vector<unsigned int> m_prefixes;
static std::vector<unsigned int> m_slot1TGWhiteList;
static std::vector<unsigned int> m_slot2TGWhiteList;
static bool m_selfOnly;
static unsigned int m_id;
};
#endif

@ -0,0 +1,172 @@
/*
* 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 "DMRCSBK.h"
#include "BPTC19696.h"
#include "Utils.h"
#include "CRC.h"
#include <cstdio>
#include <cassert>
CDMRCSBK::CDMRCSBK() :
m_data(NULL),
m_CSBKO(CSBKO_NONE),
m_FID(0x00U),
m_GI(false),
m_bsId(0U),
m_srcId(0U),
m_dstId(0U),
m_dataContent(false),
m_CBF(0U)
{
m_data = new unsigned char[12U];
}
CDMRCSBK::~CDMRCSBK()
{
delete[] m_data;
}
bool CDMRCSBK::put(const unsigned char* bytes)
{
assert(bytes != NULL);
CBPTC19696 bptc;
bptc.decode(bytes, m_data);
m_data[10U] ^= CSBK_CRC_MASK[0U];
m_data[11U] ^= CSBK_CRC_MASK[1U];
bool valid = CCRC::checkCCITT162(m_data, 12U);
if (!valid)
return false;
// Restore the checksum
m_data[10U] ^= CSBK_CRC_MASK[0U];
m_data[11U] ^= CSBK_CRC_MASK[1U];
m_CSBKO = CSBKO(m_data[0U] & 0x3FU);
m_FID = m_data[1U];
switch (m_CSBKO) {
case CSBKO_BSDWNACT:
m_GI = false;
m_bsId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Downlink Activate CSBK", m_data, 12U);
break;
case CSBKO_UUVREQ:
m_GI = false;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Unit to Unit Service Request CSBK", m_data, 12U);
break;
case CSBKO_UUANSRSP:
m_GI = false;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Unit to Unit Service Answer Response CSBK", m_data, 12U);
break;
case CSBKO_PRECCSBK:
m_GI = (m_data[2U] & 0x40U) == 0x40U;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = (m_data[2U] & 0x80U) == 0x80U;
m_CBF = m_data[3U];
CUtils::dump(1U, "Preamble CSBK", m_data, 12U);
break;
case CSBKO_NACKRSP:
m_GI = false;
m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Negative Acknowledge Response CSBK", m_data, 12U);
break;
default:
m_GI = false;
m_srcId = 0U;
m_dstId = 0U;
m_dataContent = false;
m_CBF = 0U;
CUtils::dump("Unhandled CSBK type", m_data, 12U);
return true;
}
return true;
}
void CDMRCSBK::get(unsigned char* bytes) const
{
assert(bytes != NULL);
CBPTC19696 bptc;
bptc.encode(m_data, bytes);
}
CSBKO CDMRCSBK::getCSBKO() const
{
return m_CSBKO;
}
unsigned char CDMRCSBK::getFID() const
{
return m_FID;
}
bool CDMRCSBK::getGI() const
{
return m_GI;
}
unsigned int CDMRCSBK::getBSId() const
{
return m_bsId;
}
unsigned int CDMRCSBK::getSrcId() const
{
return m_srcId;
}
unsigned int CDMRCSBK::getDstId() const
{
return m_dstId;
}
bool CDMRCSBK::getDataContent() const
{
return m_dataContent;
}
unsigned char CDMRCSBK::getCBF() const
{
return m_CBF;
}

@ -0,0 +1,72 @@
/*
* 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(DMRCSBK_H)
#define DMRCSBK_H
#include "DMRDefines.h"
enum CSBKO {
CSBKO_NONE = 0x00,
CSBKO_UUVREQ = 0x04,
CSBKO_UUANSRSP = 0x05,
CSBKO_CTCSBK = 0x07,
CSBKO_NACKRSP = 0x26,
CSBKO_BSDWNACT = 0x38,
CSBKO_PRECCSBK = 0x3D
};
class CDMRCSBK
{
public:
CDMRCSBK();
~CDMRCSBK();
bool put(const unsigned char* bytes);
void get(unsigned char* bytes) const;
// Generic fields
CSBKO getCSBKO() const;
unsigned char getFID() const;
// For BS Dwn Act
unsigned int getBSId() const;
// For Pre
bool getGI() const;
unsigned int getSrcId() const;
unsigned int getDstId() const;
bool getDataContent() const;
unsigned char getCBF() const;
private:
unsigned char* m_data;
CSBKO m_CSBKO;
unsigned char m_FID;
bool m_GI;
unsigned int m_bsId;
unsigned int m_srcId;
unsigned int m_dstId;
bool m_dataContent;
unsigned char m_CBF;
};
#endif

@ -0,0 +1,124 @@
/*
* Copyright (C) 2015,2016,2017 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 "DMRControl.h"
#include "DMRAccessControl.h"
#include "Defines.h"
#include "DMRCSBK.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter) :
m_colorCode(colorCode),
m_modem(modem),
m_network(network),
m_slot1(1U, timeout),
m_slot2(2U, timeout),
m_lookup(lookup)
{
assert(id != 0U);
assert(modem != NULL);
assert(display != NULL);
assert(lookup != NULL);
assert(rssi != NULL);
// Load black and white lists to DMRAccessControl
CDMRAccessControl::init(blacklist, whitelist, slot1TGWhitelist, slot2TGWhitelist, selfOnly, prefixes, id);
CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter);
}
CDMRControl::~CDMRControl()
{
}
bool CDMRControl::processWakeup(const unsigned char* data)
{
assert(data != NULL);
// Wakeups always come in on slot 1
if (data[0U] != TAG_DATA || data[1U] != (DMR_IDLE_RX | DMR_SYNC_DATA | DT_CSBK))
return false;
CDMRCSBK csbk;
bool valid = csbk.put(data + 2U);
if (!valid)
return false;
CSBKO csbko = csbk.getCSBKO();
if (csbko != CSBKO_BSDWNACT)
return false;
unsigned int srcId = csbk.getSrcId();
std::string src = m_lookup->find(srcId);
bool ret = CDMRAccessControl::validateSrcId(srcId);
if (!ret) {
LogMessage("Invalid Downlink Activate received from %s", src.c_str());
return false;
}
LogMessage("Downlink Activate received from %s", src.c_str());
return true;
}
bool CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)
{
assert(data != NULL);
return m_slot1.writeModem(data, len);
}
bool CDMRControl::writeModemSlot2(unsigned char *data, unsigned int len)
{
assert(data != NULL);
return m_slot2.writeModem(data, len);
}
unsigned int CDMRControl::readModemSlot1(unsigned char *data)
{
assert(data != NULL);
return m_slot1.readModem(data);
}
unsigned int CDMRControl::readModemSlot2(unsigned char *data)
{
assert(data != NULL);
return m_slot2.readModem(data);
}
void CDMRControl::clock()
{
if (m_network != NULL) {
CDMRData data;
bool ret = m_network->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
switch (slotNo) {
case 1U: m_slot1.writeNetwork(data); break;
case 2U: m_slot2.writeNetwork(data); break;
default: LogError("Invalid slot no %u", slotNo); break;
}
}
}
m_slot1.clock();
m_slot2.clock();
}

@ -0,0 +1,56 @@
/*
* Copyright (C) 2015,2016,2017 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(DMRControl_H)
#define DMRControl_H
#include "RSSIInterpolator.h"
#include "DMRNetwork.h"
#include "DMRLookup.h"
#include "Display.h"
#include "DMRSlot.h"
#include "DMRData.h"
#include "Modem.h"
#include <vector>
class CDMRControl {
public:
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter);
~CDMRControl();
bool processWakeup(const unsigned char* data);
bool writeModemSlot1(unsigned char* data, unsigned int len);
bool writeModemSlot2(unsigned char* data, unsigned int len);
unsigned int readModemSlot1(unsigned char* data);
unsigned int readModemSlot2(unsigned char* data);
void clock();
private:
unsigned int m_colorCode;
CModem* m_modem;
CDMRNetwork* m_network;
CDMRSlot m_slot1;
CDMRSlot m_slot2;
CDMRLookup* m_lookup;
};
#endif

@ -0,0 +1,198 @@
/*
* Copyright (C) 2015,2016,2017 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 "DMRData.h"
#include "DMRDefines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cstring>
#include <cassert>
CDMRData::CDMRData(const CDMRData& data) :
m_slotNo(data.m_slotNo),
m_data(NULL),
m_srcId(data.m_srcId),
m_dstId(data.m_dstId),
m_flco(data.m_flco),
m_dataType(data.m_dataType),
m_seqNo(data.m_seqNo),
m_missing(data.m_missing),
m_n(data.m_n),
m_ber(data.m_ber),
m_rssi(data.m_rssi)
{
m_data = new unsigned char[2U * DMR_FRAME_LENGTH_BYTES];
::memcpy(m_data, data.m_data, 2U * DMR_FRAME_LENGTH_BYTES);
}
CDMRData::CDMRData() :
m_slotNo(1U),
m_data(NULL),
m_srcId(0U),
m_dstId(0U),
m_flco(FLCO_GROUP),
m_dataType(0U),
m_seqNo(0U),
m_missing(false),
m_n(0U),
m_ber(0U),
m_rssi(0U)
{
m_data = new unsigned char[2U * DMR_FRAME_LENGTH_BYTES];
}
CDMRData::~CDMRData()
{
delete[] m_data;
}
CDMRData& CDMRData::operator=(const CDMRData& data)
{
if (this != &data) {
::memcpy(m_data, data.m_data, DMR_FRAME_LENGTH_BYTES);
m_slotNo = data.m_slotNo;
m_srcId = data.m_srcId;
m_dstId = data.m_dstId;
m_flco = data.m_flco;
m_dataType = data.m_dataType;
m_seqNo = data.m_seqNo;
m_missing = data.m_missing;
m_n = data.m_n;
m_ber = data.m_ber;
m_rssi = data.m_rssi;
}
return *this;
}
unsigned int CDMRData::getSlotNo() const
{
return m_slotNo;
}
void CDMRData::setSlotNo(unsigned int slotNo)
{
assert(slotNo == 1U || slotNo == 2U);
m_slotNo = slotNo;
}
unsigned char CDMRData::getDataType() const
{
return m_dataType;
}
void CDMRData::setDataType(unsigned char dataType)
{
m_dataType = dataType;
}
unsigned int CDMRData::getSrcId() const
{
return m_srcId;
}
void CDMRData::setSrcId(unsigned int id)
{
m_srcId = id;
}
unsigned int CDMRData::getDstId() const
{
return m_dstId;
}
void CDMRData::setDstId(unsigned int id)
{
m_dstId = id;
}
FLCO CDMRData::getFLCO() const
{
return m_flco;
}
void CDMRData::setFLCO(FLCO flco)
{
m_flco = flco;
}
unsigned char CDMRData::getSeqNo() const
{
return m_seqNo;
}
void CDMRData::setSeqNo(unsigned char seqNo)
{
m_seqNo = seqNo;
}
bool CDMRData::isMissing() const
{
return m_missing;
}
void CDMRData::setMissing(bool missing)
{
m_missing = missing;
}
unsigned char CDMRData::getN() const
{
return m_n;
}
void CDMRData::setN(unsigned char n)
{
m_n = n;
}
unsigned char CDMRData::getBER() const
{
return m_ber;
}
void CDMRData::setBER(unsigned char ber)
{
m_ber = ber;
}
unsigned char CDMRData::getRSSI() const
{
return m_rssi;
}
void CDMRData::setRSSI(unsigned char rssi)
{
m_rssi = rssi;
}
unsigned int CDMRData::getData(unsigned char* buffer) const
{
assert(buffer != NULL);
::memcpy(buffer, m_data, DMR_FRAME_LENGTH_BYTES);
return DMR_FRAME_LENGTH_BYTES;
}
void CDMRData::setData(const unsigned char* buffer)
{
assert(buffer != NULL);
::memcpy(m_data, buffer, DMR_FRAME_LENGTH_BYTES);
}

@ -0,0 +1,74 @@
/*
* Copyright (C) 2015,2016,2017 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 DMRData_H
#define DMRData_H
#include "DMRDefines.h"
class CDMRData {
public:
CDMRData(const CDMRData& data);
CDMRData();
~CDMRData();
CDMRData& operator=(const CDMRData& data);
unsigned int getSlotNo() const;
void setSlotNo(unsigned int slotNo);
unsigned int getSrcId() const;
void setSrcId(unsigned int id);
unsigned int getDstId() const;
void setDstId(unsigned int id);
FLCO getFLCO() const;
void setFLCO(FLCO flco);
unsigned char getN() const;
void setN(unsigned char n);
unsigned char getSeqNo() const;
void setSeqNo(unsigned char seqNo);
unsigned char getDataType() const;
void setDataType(unsigned char dataType);
bool isMissing() const;
void setMissing(bool missing);
unsigned char getBER() const;
void setBER(unsigned char ber);
unsigned char getRSSI() const;
void setRSSI(unsigned char rssi);
void setData(const unsigned char* buffer);
unsigned int getData(unsigned char* buffer) const;
private:
unsigned int m_slotNo;
unsigned char* m_data;
unsigned int m_srcId;
unsigned int m_dstId;
FLCO m_flco;
unsigned char m_dataType;
unsigned char m_seqNo;
bool m_missing;
unsigned char m_n;
unsigned char m_ber;
unsigned char m_rssi;
};
#endif

@ -0,0 +1,175 @@
/*
* Copyright (C) 2012 by Ian Wraith
* Copyright (C) 2015,2016,2017 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 "DMRDataHeader.h"
#include "DMRDefines.h"
#include "BPTC19696.h"
#include "RS129.h"
#include "Utils.h"
#include "CRC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char UDTF_NMEA = 0x05U;
CDMRDataHeader::CDMRDataHeader() :
m_data(NULL),
m_GI(false),
m_A(false),
m_srcId(0U),
m_dstId(0U),
m_blocks(0U),
m_F(false),
m_S(false),
m_Ns(0U)
{
m_data = new unsigned char[12U];
}
CDMRDataHeader::~CDMRDataHeader()
{
delete[] m_data;
}
bool CDMRDataHeader::put(const unsigned char* bytes)
{
assert(bytes != NULL);
CBPTC19696 bptc;
bptc.decode(bytes, m_data);
m_data[10U] ^= DATA_HEADER_CRC_MASK[0U];
m_data[11U] ^= DATA_HEADER_CRC_MASK[1U];
bool valid = CCRC::checkCCITT162(m_data, 12U);
if (!valid)
return false;
// Restore the checksum
m_data[10U] ^= DATA_HEADER_CRC_MASK[0U];
m_data[11U] ^= DATA_HEADER_CRC_MASK[1U];
m_GI = (m_data[0U] & 0x80U) == 0x80U;
m_A = (m_data[0U] & 0x40U) == 0x40U;
unsigned char dpf = m_data[0U] & 0x0FU;
if (dpf == DPF_PROPRIETARY)
return true;
m_dstId = m_data[2U] << 16 | m_data[3U] << 8 | m_data[4U];
m_srcId = m_data[5U] << 16 | m_data[6U] << 8 | m_data[7U];
switch (dpf) {
case DPF_UNCONFIRMED_DATA:
CUtils::dump(1U, "DMR, Unconfirmed Data Header", m_data, 12U);
m_F = (m_data[8U] & 0x80U) == 0x80U;
m_blocks = m_data[8U] & 0x7FU;
break;
case DPF_CONFIRMED_DATA:
CUtils::dump(1U, "DMR, Confirmed Data Header", m_data, 12U);
m_F = (m_data[8U] & 0x80U) == 0x80U;
m_blocks = m_data[8U] & 0x7FU;
m_S = (m_data[9U] & 0x80U) == 0x80U;
m_Ns = (m_data[9U] >> 4) & 0x07U;
break;
case DPF_RESPONSE:
CUtils::dump(1U, "DMR, Response Data Header", m_data, 12U);
m_blocks = m_data[8U] & 0x7FU;
break;
case DPF_PROPRIETARY:
CUtils::dump(1U, "DMR, Proprietary Data Header", m_data, 12U);
break;
case DPF_DEFINED_RAW:
CUtils::dump(1U, "DMR, Raw or Status/Precoded Short Data Header", m_data, 12U);
m_blocks = (m_data[0U] & 0x30U) + (m_data[1U] & 0x0FU);
m_F = (m_data[8U] & 0x01U) == 0x01U;
m_S = (m_data[8U] & 0x02U) == 0x02U;
break;
case DPF_DEFINED_SHORT:
CUtils::dump(1U, "DMR, Defined Short Data Header", m_data, 12U);
m_blocks = (m_data[0U] & 0x30U) + (m_data[1U] & 0x0FU);
m_F = (m_data[8U] & 0x01U) == 0x01U;
m_S = (m_data[8U] & 0x02U) == 0x02U;
break;
case DPF_UDT:
CUtils::dump(1U, "DMR, Unified Data Transport Header", m_data, 12U);
m_blocks = (m_data[8U] & 0x03U) + 1U;
break;
default:
CUtils::dump("DMR, Unknown Data Header", m_data, 12U);
break;
}
return true;
}
void CDMRDataHeader::get(unsigned char* bytes) const
{
assert(bytes != NULL);
CBPTC19696 bptc;
bptc.encode(m_data, bytes);
}
bool CDMRDataHeader::getGI() const
{
return m_GI;
}
unsigned int CDMRDataHeader::getSrcId() const
{
return m_srcId;
}
unsigned int CDMRDataHeader::getDstId() const
{
return m_dstId;
}
unsigned int CDMRDataHeader::getBlocks() const
{
return m_blocks;
}
CDMRDataHeader& CDMRDataHeader::operator=(const CDMRDataHeader& header)
{
if (&header != this) {
::memcpy(m_data, header.m_data, 12U);
m_GI = header.m_GI;
m_A = header.m_A;
m_srcId = header.m_srcId;
m_dstId = header.m_dstId;
m_blocks = header.m_blocks;
m_F = header.m_F;
m_S = header.m_S;
m_Ns = header.m_Ns;
}
return *this;
}

@ -0,0 +1,54 @@
/*
* Copyright (C) 2015,2016,2017 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 DMRDataHeader_H
#define DMRDataHeader_H
class CDMRDataHeader
{
public:
CDMRDataHeader();
~CDMRDataHeader();
bool put(const unsigned char* bytes);
void get(unsigned char* bytes) const;
bool getGI() const;
unsigned int getSrcId() const;
unsigned int getDstId() const;
unsigned int getBlocks() const;
CDMRDataHeader& operator=(const CDMRDataHeader& header);
private:
unsigned char* m_data;
bool m_GI;
bool m_A;
unsigned int m_srcId;
unsigned int m_dstId;
unsigned int m_blocks;
bool m_F;
bool m_S;
unsigned char m_Ns;
};
#endif

@ -0,0 +1,126 @@
/*
* 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(DMRDefines_H)
#define DMRDefines_H
#include "Defines.h" // For TAG_DATA
const unsigned int DMR_FRAME_LENGTH_BITS = 264U;
const unsigned int DMR_FRAME_LENGTH_BYTES = 33U;
const unsigned int DMR_SYNC_LENGTH_BITS = 48U;
const unsigned int DMR_SYNC_LENGTH_BYTES = 6U;
const unsigned int DMR_EMB_LENGTH_BITS = 8U;
const unsigned int DMR_EMB_LENGTH_BYTES = 1U;
const unsigned int DMR_SLOT_TYPE_LENGTH_BITS = 8U;
const unsigned int DMR_SLOT_TYPE_LENGTH_BYTES = 1U;
const unsigned int DMR_EMBEDDED_SIGNALLING_LENGTH_BITS = 32U;
const unsigned int DMR_EMBEDDED_SIGNALLING_LENGTH_BYTES = 4U;
const unsigned int DMR_AMBE_LENGTH_BITS = 108U * 2U;
const unsigned int DMR_AMBE_LENGTH_BYTES = 27U;
const unsigned char BS_SOURCED_AUDIO_SYNC[] = {0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U};
const unsigned char BS_SOURCED_DATA_SYNC[] = {0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U};
const unsigned char MS_SOURCED_AUDIO_SYNC[] = {0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U};
const unsigned char MS_SOURCED_DATA_SYNC[] = {0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U};
const unsigned char DIRECT_SLOT1_AUDIO_SYNC[] = {0x05U, 0xD5U, 0x77U, 0xF7U, 0x75U, 0x7FU, 0xF0U};
const unsigned char DIRECT_SLOT1_DATA_SYNC[] = {0x0FU, 0x7FU, 0xDDU, 0x5DU, 0xDFU, 0xD5U, 0x50U};
const unsigned char DIRECT_SLOT2_AUDIO_SYNC[] = {0x07U, 0xDFU, 0xFDU, 0x5FU, 0x55U, 0xD5U, 0xF0U};
const unsigned char DIRECT_SLOT2_DATA_SYNC[] = {0x0DU, 0x75U, 0x57U, 0xF5U, 0xFFU, 0x7FU, 0x50U};
const unsigned char SYNC_MASK[] = {0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U};
// The PR FILL and Data Sync pattern.
const unsigned char DMR_IDLE_DATA[] = {TAG_DATA, 0x00U,
0x53U, 0xC2U, 0x5EU, 0xABU, 0xA8U, 0x67U, 0x1DU, 0xC7U, 0x38U, 0x3BU, 0xD9U,
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U};
// A silence frame only
const unsigned char DMR_SILENCE_DATA[] = {TAG_DATA, 0x00U,
0xACU, 0xAAU, 0x40U, 0x20U, 0x00U, 0x44U, 0x40U, 0x80U, 0x80U, 0xACU, 0xAAU,
0x40U, 0x20U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x44U, 0x40U,
0x80U, 0x80U, 0xACU, 0xAAU, 0x40U, 0x20U, 0x00U, 0x44U, 0x40U, 0x80U, 0x80U};
// 0x88U, 0xC8U, 0xA3U, 0x54U, 0x22U, 0x16U, 0x31U, 0x69U, 0x6AU, 0xAAU, 0xCAU,
// 0x81U, 0x54U, 0x20U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x27U, 0x13U,
// 0x29U, 0x48U, 0xAAU, 0xCAU, 0x81U, 0x54U, 0x21U, 0x27U, 0x31U, 0x39U, 0x6AU};
const unsigned char PAYLOAD_LEFT_MASK[] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U};
const unsigned char PAYLOAD_RIGHT_MASK[] = {0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
const unsigned char VOICE_LC_HEADER_CRC_MASK[] = {0x96U, 0x96U, 0x96U};
const unsigned char TERMINATOR_WITH_LC_CRC_MASK[] = {0x99U, 0x99U, 0x99U};
const unsigned char PI_HEADER_CRC_MASK[] = {0x69U, 0x69U};
const unsigned char DATA_HEADER_CRC_MASK[] = {0xCCU, 0xCCU};
const unsigned char CSBK_CRC_MASK[] = {0xA5U, 0xA5U};
const unsigned int DMR_SLOT_TIME = 60U;
const unsigned int AMBE_PER_SLOT = 3U;
const unsigned char DT_MASK = 0x0FU;
const unsigned char DT_VOICE_PI_HEADER = 0x00U;
const unsigned char DT_VOICE_LC_HEADER = 0x01U;
const unsigned char DT_TERMINATOR_WITH_LC = 0x02U;
const unsigned char DT_CSBK = 0x03U;
const unsigned char DT_DATA_HEADER = 0x06U;
const unsigned char DT_RATE_12_DATA = 0x07U;
const unsigned char DT_RATE_34_DATA = 0x08U;
const unsigned char DT_IDLE = 0x09U;
const unsigned char DT_RATE_1_DATA = 0x0AU;
// Dummy values
const unsigned char DT_VOICE_SYNC = 0xF0U;
const unsigned char DT_VOICE = 0xF1U;
const unsigned char DMR_IDLE_RX = 0x80U;
const unsigned char DMR_SYNC_DATA = 0x40U;
const unsigned char DMR_SYNC_AUDIO = 0x20U;
const unsigned char DMR_SLOT1 = 0x00U;
const unsigned char DMR_SLOT2 = 0x80U;
const unsigned char DPF_UDT = 0x00U;
const unsigned char DPF_RESPONSE = 0x01U;
const unsigned char DPF_UNCONFIRMED_DATA = 0x02U;
const unsigned char DPF_CONFIRMED_DATA = 0x03U;
const unsigned char DPF_DEFINED_SHORT = 0x0DU;
const unsigned char DPF_DEFINED_RAW = 0x0EU;
const unsigned char DPF_PROPRIETARY = 0x0FU;
const unsigned char FID_ETSI = 0U;
const unsigned char FID_DMRA = 16U;
enum FLCO {
FLCO_GROUP = 0,
FLCO_USER_USER = 3,
FLCO_TALKER_ALIAS_HEADER = 4,
FLCO_TALKER_ALIAS_BLOCK1 = 5,
FLCO_TALKER_ALIAS_BLOCK2 = 6,
FLCO_TALKER_ALIAS_BLOCK3 = 7,
FLCO_GPS_INFO = 8
};
#endif

@ -0,0 +1,100 @@
/*
* 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 "DMREMB.h"
#include "QR1676.h"
#include <cstdio>
#include <cassert>
CDMREMB::CDMREMB() :
m_colorCode(0U),
m_PI(false),
m_LCSS(0U)
{
}
CDMREMB::~CDMREMB()
{
}
void CDMREMB::putData(const unsigned char* data)
{
assert(data != NULL);
unsigned char DMREMB[2U];
DMREMB[0U] = (data[13U] << 4) & 0xF0U;
DMREMB[0U] |= (data[14U] >> 4) & 0x0FU;
DMREMB[1U] = (data[18U] << 4) & 0xF0U;
DMREMB[1U] |= (data[19U] >> 4) & 0x0FU;
CQR1676::decode(DMREMB);
m_colorCode = (DMREMB[0U] >> 4) & 0x0FU;
m_PI = (DMREMB[0U] & 0x08U) == 0x08U;
m_LCSS = (DMREMB[0U] >> 1) & 0x03U;
}
void CDMREMB::getData(unsigned char* data) const
{
assert(data != NULL);
unsigned char DMREMB[2U];
DMREMB[0U] = (m_colorCode << 4) & 0xF0U;
DMREMB[0U] |= m_PI ? 0x08U : 0x00U;
DMREMB[0U] |= (m_LCSS << 1) & 0x06U;
DMREMB[1U] = 0x00U;
CQR1676::encode(DMREMB);
data[13U] = (data[13U] & 0xF0U) | ((DMREMB[0U] >> 4U) & 0x0FU);
data[14U] = (data[14U] & 0x0FU) | ((DMREMB[0U] << 4U) & 0xF0U);
data[18U] = (data[18U] & 0xF0U) | ((DMREMB[1U] >> 4U) & 0x0FU);
data[19U] = (data[19U] & 0x0FU) | ((DMREMB[1U] << 4U) & 0xF0U);
}
unsigned char CDMREMB::getColorCode() const
{
return m_colorCode;
}
void CDMREMB::setColorCode(unsigned char code)
{
m_colorCode = code;
}
bool CDMREMB::getPI() const
{
return m_PI;
}
void CDMREMB::setPI(bool pi)
{
m_PI = pi;
}
unsigned char CDMREMB::getLCSS() const
{
return m_LCSS;
}
void CDMREMB::setLCSS(unsigned char lcss)
{
m_LCSS = lcss;
}

@ -0,0 +1,46 @@
/*
* 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(DMREMB_H)
#define DMREMB_H
class CDMREMB
{
public:
CDMREMB();
~CDMREMB();
void putData(const unsigned char* data);
void getData(unsigned char* data) const;
unsigned char getColorCode() const;
void setColorCode(unsigned char code);
bool getPI() const;
void setPI(bool pi);
unsigned char getLCSS() const;
void setLCSS(unsigned char lcss);
private:
unsigned char m_colorCode;
bool m_PI;
unsigned char m_LCSS;
};
#endif

@ -0,0 +1,322 @@
/*
* Copyright (C) 2015,2016,2017 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 "DMREmbeddedData.h"
#include "Hamming.h"
#include "Utils.h"
#include "CRC.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CDMREmbeddedData::CDMREmbeddedData() :
m_raw(NULL),
m_state(LCS_NONE),
m_data(NULL),
m_FLCO(FLCO_GROUP),
m_valid(false)
{
m_raw = new bool[128U];
m_data = new bool[72U];
}
CDMREmbeddedData::~CDMREmbeddedData()
{
delete[] m_raw;
delete[] m_data;
}
// Add LC data (which may consist of 4 blocks) to the data store
bool CDMREmbeddedData::addData(const unsigned char* data, unsigned char lcss)
{
assert(data != NULL);
bool rawData[40U];
CUtils::byteToBitsBE(data[14U], rawData + 0U);
CUtils::byteToBitsBE(data[15U], rawData + 8U);
CUtils::byteToBitsBE(data[16U], rawData + 16U);
CUtils::byteToBitsBE(data[17U], rawData + 24U);
CUtils::byteToBitsBE(data[18U], rawData + 32U);
// Is this the first block of a 4 block embedded LC ?
if (lcss == 1U) {
for (unsigned int a = 0U; a < 32U; a++)
m_raw[a] = rawData[a + 4U];
// Show we are ready for the next LC block
m_state = LCS_FIRST;
m_valid = false;
return false;
}
// Is this the 2nd block of a 4 block embedded LC ?
if (lcss == 3U && m_state == LCS_FIRST) {
for (unsigned int a = 0U; a < 32U; a++)
m_raw[a + 32U] = rawData[a + 4U];
// Show we are ready for the next LC block
m_state = LCS_SECOND;
return false;
}
// Is this the 3rd block of a 4 block embedded LC ?
if (lcss == 3U && m_state == LCS_SECOND) {
for (unsigned int a = 0U; a < 32U; a++)
m_raw[a + 64U] = rawData[a + 4U];
// Show we are ready for the final LC block
m_state = LCS_THIRD;
return false;
}
// Is this the final block of a 4 block embedded LC ?
if (lcss == 2U && m_state == LCS_THIRD) {
for (unsigned int a = 0U; a < 32U; a++)
m_raw[a + 96U] = rawData[a + 4U];
// Show that we're not ready for any more data
m_state = LCS_NONE;
// Process the complete data block
decodeEmbeddedData();
if (m_valid)
encodeEmbeddedData();
return m_valid;
}
return false;
}
void CDMREmbeddedData::setLC(const CDMRLC& lc)
{
lc.getData(m_data);
m_FLCO = lc.getFLCO();
m_valid = true;
encodeEmbeddedData();
}
void CDMREmbeddedData::encodeEmbeddedData()
{
unsigned int crc;
CCRC::encodeFiveBit(m_data, crc);
bool data[128U];
::memset(data, 0x00U, 128U * sizeof(bool));
data[106U] = (crc & 0x01U) == 0x01U;
data[90U] = (crc & 0x02U) == 0x02U;
data[74U] = (crc & 0x04U) == 0x04U;
data[58U] = (crc & 0x08U) == 0x08U;
data[42U] = (crc & 0x10U) == 0x10U;
unsigned int b = 0U;
for (unsigned int a = 0U; a < 11U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 16U; a < 27U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 32U; a < 42U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 48U; a < 58U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 64U; a < 74U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 80U; a < 90U; a++, b++)
data[a] = m_data[b];
for (unsigned int a = 96U; a < 106U; a++, b++)
data[a] = m_data[b];
// Hamming (16,11,4) check each row except the last one
for (unsigned int a = 0U; a < 112U; a += 16U)
CHamming::encode16114(data + a);
// Add the parity bits for each column
for (unsigned int a = 0U; a < 16U; a++)
data[a + 112U] = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U];
// The data is packed downwards in columns
b = 0U;
for (unsigned int a = 0U; a < 128U; a++) {
m_raw[a] = data[b];
b += 16U;
if (b > 127U)
b -= 127U;
}
}
unsigned char CDMREmbeddedData::getData(unsigned char* data, unsigned char n) const
{
assert(data != NULL);
if (n >= 1U && n < 5U) {
n--;
bool bits[40U];
::memset(bits, 0x00U, 40U * sizeof(bool));
::memcpy(bits + 4U, m_raw + n * 32U, 32U * sizeof(bool));
unsigned char bytes[5U];
CUtils::bitsToByteBE(bits + 0U, bytes[0U]);
CUtils::bitsToByteBE(bits + 8U, bytes[1U]);
CUtils::bitsToByteBE(bits + 16U, bytes[2U]);
CUtils::bitsToByteBE(bits + 24U, bytes[3U]);
CUtils::bitsToByteBE(bits + 32U, bytes[4U]);
data[14U] = (data[14U] & 0xF0U) | (bytes[0U] & 0x0FU);
data[15U] = bytes[1U];
data[16U] = bytes[2U];
data[17U] = bytes[3U];
data[18U] = (data[18U] & 0x0FU) | (bytes[4U] & 0xF0U);
switch (n) {
case 0U:
return 1U;
case 3U:
return 2U;
default:
return 3U;
}
} else {
data[14U] &= 0xF0U;
data[15U] = 0x00U;
data[16U] = 0x00U;
data[17U] = 0x00U;
data[18U] &= 0x0FU;
return 0U;
}
}
// Unpack and error check an embedded LC
void CDMREmbeddedData::decodeEmbeddedData()
{
// The data is unpacked downwards in columns
bool data[128U];
::memset(data, 0x00U, 128U * sizeof(bool));
unsigned int b = 0U;
for (unsigned int a = 0U; a < 128U; a++) {
data[b] = m_raw[a];
b += 16U;
if (b > 127U)
b -= 127U;
}
// Hamming (16,11,4) check each row except the last one
for (unsigned int a = 0U; a < 112U; a += 16U) {
if (!CHamming::decode16114(data + a))
return;
}
// Check the parity bits
for (unsigned int a = 0U; a < 16U; a++) {
bool parity = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U] ^ data[a + 112U];
if (parity)
return;
}
// We have passed the Hamming check so extract the actual payload
b = 0U;
for (unsigned int a = 0U; a < 11U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 16U; a < 27U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 32U; a < 42U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 48U; a < 58U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 64U; a < 74U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 80U; a < 90U; a++, b++)
m_data[b] = data[a];
for (unsigned int a = 96U; a < 106U; a++, b++)
m_data[b] = data[a];
// Extract the 5 bit CRC
unsigned int crc = 0U;
if (data[42]) crc += 16U;
if (data[58]) crc += 8U;
if (data[74]) crc += 4U;
if (data[90]) crc += 2U;
if (data[106]) crc += 1U;
// Now CRC check this
if (!CCRC::checkFiveBit(m_data, crc))
return;
m_valid = true;
// Extract the FLCO
unsigned char flco;
CUtils::bitsToByteBE(m_data + 0U, flco);
m_FLCO = FLCO(flco & 0x3FU);
}
CDMRLC* CDMREmbeddedData::getLC() const
{
if (!m_valid)
return NULL;
if (m_FLCO != FLCO_GROUP && m_FLCO != FLCO_USER_USER)
return NULL;
return new CDMRLC(m_data);
}
bool CDMREmbeddedData::isValid() const
{
return m_valid;
}
FLCO CDMREmbeddedData::getFLCO() const
{
return m_FLCO;
}
void CDMREmbeddedData::reset()
{
m_state = LCS_NONE;
m_valid = false;
}
bool CDMREmbeddedData::getRawData(unsigned char* data) const
{
assert(data != NULL);
if (!m_valid)
return false;
CUtils::bitsToByteBE(m_data + 0U, data[0U]);
CUtils::bitsToByteBE(m_data + 8U, data[1U]);
CUtils::bitsToByteBE(m_data + 16U, data[2U]);
CUtils::bitsToByteBE(m_data + 24U, data[3U]);
CUtils::bitsToByteBE(m_data + 32U, data[4U]);
CUtils::bitsToByteBE(m_data + 40U, data[5U]);
CUtils::bitsToByteBE(m_data + 48U, data[6U]);
CUtils::bitsToByteBE(m_data + 56U, data[7U]);
CUtils::bitsToByteBE(m_data + 64U, data[8U]);
return true;
}

@ -0,0 +1,63 @@
/*
* Copyright (C) 2015,2016,2017 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 DMREmbeddedData_H
#define DMREmbeddedData_H
#include "DMRDefines.h"
#include "DMRLC.h"
enum LC_STATE {
LCS_NONE,
LCS_FIRST,
LCS_SECOND,
LCS_THIRD
};
class CDMREmbeddedData
{
public:
CDMREmbeddedData();
~CDMREmbeddedData();
bool addData(const unsigned char* data, unsigned char lcss);
CDMRLC* getLC() const;
void setLC(const CDMRLC& lc);
unsigned char getData(unsigned char* data, unsigned char n) const;
bool getRawData(unsigned char* data) const;
bool isValid() const;
FLCO getFLCO() const;
void reset();
private:
bool* m_raw;
LC_STATE m_state;
bool* m_data;
FLCO m_FLCO;
bool m_valid;
void decodeEmbeddedData();
void encodeEmbeddedData();
};
#endif

@ -0,0 +1,99 @@
/*
* Copyright (C) 2012 by Ian Wraith
* 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 "DMRFullLC.h"
#include "DMRDefines.h"
#include "RS129.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
CDMRFullLC::CDMRFullLC() :
m_bptc()
{
}
CDMRFullLC::~CDMRFullLC()
{
}
CDMRLC* CDMRFullLC::decode(const unsigned char* data, unsigned char type)
{
assert(data != NULL);
unsigned char lcData[12U];
m_bptc.decode(data, lcData);
switch (type) {
case DT_VOICE_LC_HEADER:
lcData[9U] ^= VOICE_LC_HEADER_CRC_MASK[0U];
lcData[10U] ^= VOICE_LC_HEADER_CRC_MASK[1U];
lcData[11U] ^= VOICE_LC_HEADER_CRC_MASK[2U];
break;
case DT_TERMINATOR_WITH_LC:
lcData[9U] ^= TERMINATOR_WITH_LC_CRC_MASK[0U];
lcData[10U] ^= TERMINATOR_WITH_LC_CRC_MASK[1U];
lcData[11U] ^= TERMINATOR_WITH_LC_CRC_MASK[2U];
break;
default:
::LogError("Unsupported LC type - %d", int(type));
return NULL;
}
if (!CRS129::check(lcData))
return NULL;
return new CDMRLC(lcData);
}
void CDMRFullLC::encode(const CDMRLC& lc, unsigned char* data, unsigned char type)
{
assert(data != NULL);
unsigned char lcData[12U];
lc.getData(lcData);
unsigned char parity[4U];
CRS129::encode(lcData, 9U, parity);
switch (type) {
case DT_VOICE_LC_HEADER:
lcData[9U] = parity[2U] ^ VOICE_LC_HEADER_CRC_MASK[0U];
lcData[10U] = parity[1U] ^ VOICE_LC_HEADER_CRC_MASK[1U];
lcData[11U] = parity[0U] ^ VOICE_LC_HEADER_CRC_MASK[2U];
break;
case DT_TERMINATOR_WITH_LC:
lcData[9U] = parity[2U] ^ TERMINATOR_WITH_LC_CRC_MASK[0U];
lcData[10U] = parity[1U] ^ TERMINATOR_WITH_LC_CRC_MASK[1U];
lcData[11U] = parity[0U] ^ TERMINATOR_WITH_LC_CRC_MASK[2U];
break;
default:
::LogError("Unsupported LC type - %d", int(type));
return;
}
m_bptc.encode(lcData, data);
}

@ -0,0 +1,42 @@
/*
* 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.
*/
#ifndef DMRFullLC_H
#define DMRFullLC_H
#include "DMRLC.h"
#include "DMRSlotType.h"
#include "BPTC19696.h"
class CDMRFullLC
{
public:
CDMRFullLC();
~CDMRFullLC();
CDMRLC* decode(const unsigned char* data, unsigned char type);
void encode(const CDMRLC& lc, unsigned char* data, unsigned char type);
private:
CBPTC19696 m_bptc;
};
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,205 @@
/*
* 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 "DMRLC.h"
#include "Utils.h"
#include <cstdio>
#include <cassert>
CDMRLC::CDMRLC(FLCO flco, unsigned int srcId, unsigned int dstId) :
m_PF(false),
m_R(false),
m_FLCO(flco),
m_FID(0U),
m_options(0U),
m_srcId(srcId),
m_dstId(dstId)
{
}
CDMRLC::CDMRLC(const unsigned char* bytes) :
m_PF(false),
m_R(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_options(0U),
m_srcId(0U),
m_dstId(0U)
{
assert(bytes != NULL);
m_PF = (bytes[0U] & 0x80U) == 0x80U;
m_R = (bytes[0U] & 0x40U) == 0x40U;
m_FLCO = FLCO(bytes[0U] & 0x3FU);
m_FID = bytes[1U];
m_options = bytes[2U];
m_dstId = bytes[3U] << 16 | bytes[4U] << 8 | bytes[5U];
m_srcId = bytes[6U] << 16 | bytes[7U] << 8 | bytes[8U];
}
CDMRLC::CDMRLC(const bool* bits) :
m_PF(false),
m_R(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_options(0U),
m_srcId(0U),
m_dstId(0U)
{
assert(bits != NULL);
m_PF = bits[0U];
m_R = bits[1U];
unsigned char temp1, temp2, temp3;
CUtils::bitsToByteBE(bits + 0U, temp1);
m_FLCO = FLCO(temp1 & 0x3FU);
CUtils::bitsToByteBE(bits + 8U, temp2);
m_FID = temp2;
CUtils::bitsToByteBE(bits + 16U, temp3);
m_options = temp3;
unsigned char d1, d2, d3;
CUtils::bitsToByteBE(bits + 24U, d1);
CUtils::bitsToByteBE(bits + 32U, d2);
CUtils::bitsToByteBE(bits + 40U, d3);
unsigned char s1, s2, s3;
CUtils::bitsToByteBE(bits + 48U, s1);
CUtils::bitsToByteBE(bits + 56U, s2);
CUtils::bitsToByteBE(bits + 64U, s3);
m_srcId = s1 << 16 | s2 << 8 | s3;
m_dstId = d1 << 16 | d2 << 8 | d3;
}
CDMRLC::CDMRLC() :
m_PF(false),
m_R(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_options(0U),
m_srcId(0U),
m_dstId(0U)
{
}
CDMRLC::~CDMRLC()
{
}
void CDMRLC::getData(unsigned char* bytes) const
{
assert(bytes != NULL);
bytes[0U] = (unsigned char)m_FLCO;
if (m_PF)
bytes[0U] |= 0x80U;
if (m_R)
bytes[0U] |= 0x40U;
bytes[1U] = m_FID;
bytes[2U] = m_options;
bytes[3U] = m_dstId >> 16;
bytes[4U] = m_dstId >> 8;
bytes[5U] = m_dstId >> 0;
bytes[6U] = m_srcId >> 16;
bytes[7U] = m_srcId >> 8;
bytes[8U] = m_srcId >> 0;
}
void CDMRLC::getData(bool* bits) const
{
assert(bits != NULL);
unsigned char bytes[9U];
getData(bytes);
CUtils::byteToBitsBE(bytes[0U], bits + 0U);
CUtils::byteToBitsBE(bytes[1U], bits + 8U);
CUtils::byteToBitsBE(bytes[2U], bits + 16U);
CUtils::byteToBitsBE(bytes[3U], bits + 24U);
CUtils::byteToBitsBE(bytes[4U], bits + 32U);
CUtils::byteToBitsBE(bytes[5U], bits + 40U);
CUtils::byteToBitsBE(bytes[6U], bits + 48U);
CUtils::byteToBitsBE(bytes[7U], bits + 56U);
CUtils::byteToBitsBE(bytes[8U], bits + 64U);
}
bool CDMRLC::getPF() const
{
return m_PF;
}
void CDMRLC::setPF(bool pf)
{
m_PF = pf;
}
FLCO CDMRLC::getFLCO() const
{
return m_FLCO;
}
void CDMRLC::setFLCO(FLCO flco)
{
m_FLCO = flco;
}
unsigned char CDMRLC::getFID() const
{
return m_FID;
}
void CDMRLC::setFID(unsigned char fid)
{
m_FID = fid;
}
unsigned int CDMRLC::getSrcId() const
{
return m_srcId;
}
void CDMRLC::setSrcId(unsigned int id)
{
m_srcId = id;
}
unsigned int CDMRLC::getDstId() const
{
return m_dstId;
}
void CDMRLC::setDstId(unsigned int id)
{
m_dstId = id;
}

@ -0,0 +1,62 @@
/*
* 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(DMRLC_H)
#define DMRLC_H
#include "DMRDefines.h"
class CDMRLC
{
public:
CDMRLC(FLCO flco, unsigned int srcId, unsigned int dstId);
CDMRLC(const unsigned char* bytes);
CDMRLC(const bool* bits);
CDMRLC();
~CDMRLC();
void getData(unsigned char* bytes) const;
void getData(bool* bits) const;
bool getPF() const;
void setPF(bool pf);
FLCO getFLCO() const;
void setFLCO(FLCO flco);
unsigned char getFID() const;
void setFID(unsigned char fid);
unsigned int getSrcId() const;
void setSrcId(unsigned int id);
unsigned int getDstId() const;
void setDstId(unsigned int id);
private:
bool m_PF;
bool m_R;
FLCO m_FLCO;
unsigned char m_FID;
unsigned char m_options;
unsigned int m_srcId;
unsigned int m_dstId;
};
#endif

@ -0,0 +1,158 @@
/*
* Copyright (C) 2016,2017 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 "DMRLookup.h"
#include "Timer.h"
#include "Log.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
CDMRLookup::CDMRLookup(const std::string& filename, unsigned int reloadTime) :
CThread(),
m_filename(filename),
m_reloadTime(reloadTime),
m_table(),
m_mutex(),
m_stop(false)
{
}
CDMRLookup::~CDMRLookup()
{
}
bool CDMRLookup::read()
{
bool ret = load();
if (m_reloadTime > 0U)
run();
return ret;
}
void CDMRLookup::entry()
{
LogInfo("Started the DMR Id lookup reload thread");
CTimer timer(1U, 3600U * m_reloadTime);
timer.start();
while (!m_stop) {
sleep(1000U);
timer.clock();
if (timer.hasExpired()) {
load();
timer.start();
}
}
LogInfo("Stopped the DMR Id lookup reload thread");
}
void CDMRLookup::stop()
{
if (m_reloadTime == 0U) {
delete this;
return;
}
m_stop = true;
wait();
}
std::string CDMRLookup::find(unsigned int id)
{
std::string callsign;
if (id == 0xFFFFFFU)
return std::string("ALL");
m_mutex.lock();
try {
callsign = m_table.at(id);
} catch (...) {
char text[10U];
::sprintf(text, "%u", id);
callsign = std::string(text);
}
m_mutex.unlock();
return callsign;
}
bool CDMRLookup::exists(unsigned int id)
{
m_mutex.lock();
bool found = m_table.count(id) == 1U;
m_mutex.unlock();
return found;
}
bool CDMRLookup::load()
{
FILE* fp = ::fopen(m_filename.c_str(), "rt");
if (fp == NULL) {
LogWarning("Cannot open the Id lookup file - %s", m_filename.c_str());
return false;
}
m_mutex.lock();
// Remove the old entries
m_table.clear();
char buffer[100U];
while (::fgets(buffer, 100U, fp) != NULL) {
if (buffer[0U] == '#')
continue;
char* p1 = ::strtok(buffer, " \t\r\n");
char* p2 = ::strtok(NULL, " \t\r\n");
if (p1 != NULL && p2 != NULL) {
unsigned int id = (unsigned int)::atoi(p1);
for (char* p = p2; *p != 0x00U; p++)
*p = ::toupper(*p);
m_table[id] = std::string(p2);
}
}
m_mutex.unlock();
::fclose(fp);
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfo("Loaded %u Ids to the callsign lookup table", size);
return true;
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2016,2017 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 DMRLookup_H
#define DMRLookup_H
#include "Thread.h"
#include "Mutex.h"
#include <string>
#include <unordered_map>
class CDMRLookup : public CThread {
public:
CDMRLookup(const std::string& filename, unsigned int reloadTime);
virtual ~CDMRLookup();
bool read();
virtual void entry();
std::string find(unsigned int id);
bool exists(unsigned int id);
void stop();
private:
std::string m_filename;
unsigned int m_reloadTime;
std::unordered_map<unsigned int, std::string> m_table;
CMutex m_mutex;
bool m_stop;
bool load();
};
#endif

@ -0,0 +1,617 @@
/*
* Copyright (C) 2015,2016,2017 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 "DMRNetwork.h"
#include "StopWatch.h"
#include "SHA256.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
const unsigned int BUFFER_LENGTH = 500U;
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
m_address(),
m_port(port),
m_id(NULL),
m_password(password),
m_duplex(duplex),
m_version(version),
m_debug(debug),
m_socket(local),
m_enabled(false),
m_slot1(slot1),
m_slot2(slot2),
m_hwType(hwType),
m_status(WAITING_CONNECT),
m_retryTimer(1000U, 10U),
m_timeoutTimer(1000U, 60U),
m_buffer(NULL),
m_salt(NULL),
m_streamId(NULL),
m_rxData(1000U, "DMR Network"),
m_options(),
m_callsign(),
m_rxFrequency(0U),
m_txFrequency(0U),
m_power(0U),
m_colorCode(0U),
m_latitude(0.0F),
m_longitude(0.0F),
m_height(0),
m_location(),
m_description(),
m_url(),
m_beacon(false)
{
assert(!address.empty());
assert(port > 0U);
assert(id > 1000U);
assert(!password.empty());
m_address = CUDPSocket::lookup(address);
m_buffer = new unsigned char[BUFFER_LENGTH];
m_salt = new unsigned char[sizeof(uint32_t)];
m_id = new uint8_t[4U];
m_streamId = new uint32_t[2U];
m_streamId[0U] = 0x00U;
m_streamId[1U] = 0x00U;
m_id[0U] = id >> 24;
m_id[1U] = id >> 16;
m_id[2U] = id >> 8;
m_id[3U] = id >> 0;
CStopWatch stopWatch;
::srand(stopWatch.start());
}
CDMRNetwork::~CDMRNetwork()
{
delete[] m_buffer;
delete[] m_salt;
delete[] m_streamId;
delete[] m_id;
}
void CDMRNetwork::setOptions(const std::string& options)
{
m_options = options;
}
void CDMRNetwork::setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
{
m_callsign = callsign;
m_rxFrequency = rxFrequency;
m_txFrequency = txFrequency;
m_power = power;
m_colorCode = colorCode;
m_latitude = latitude;
m_longitude = longitude;
m_height = height;
m_location = location;
m_description = description;
m_url = url;
}
bool CDMRNetwork::open()
{
LogMessage("DMR, Opening DMR Network");
m_status = WAITING_CONNECT;
m_timeoutTimer.stop();
m_retryTimer.start();
return true;
}
void CDMRNetwork::enable(bool enabled)
{
m_enabled = enabled;
}
bool CDMRNetwork::read(CDMRData& data)
{
if (m_status != RUNNING)
return false;
if (m_rxData.isEmpty())
return false;
unsigned char length = 0U;
m_rxData.getData(&length, 1U);
m_rxData.getData(m_buffer, length);
// Is this a data packet?
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
return false;
unsigned char seqNo = m_buffer[4U];
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
// DMO mode slot disabling
if (slotNo == 1U && !m_duplex)
return false;
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
data.setSeqNo(seqNo);
data.setSlotNo(slotNo);
data.setSrcId(srcId);
data.setDstId(dstId);
data.setFLCO(flco);
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
if (dataSync) {
unsigned char dataType = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(dataType);
data.setN(0U);
} else if (voiceSync) {
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE_SYNC);
data.setN(0U);
} else {
unsigned char n = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE);
data.setN(n);
}
return true;
}
bool CDMRNetwork::write(const CDMRData& data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
buffer[0U] = 'D';
buffer[1U] = 'M';
buffer[2U] = 'R';
buffer[3U] = 'D';
unsigned int srcId = data.getSrcId();
buffer[5U] = srcId >> 16;
buffer[6U] = srcId >> 8;
buffer[7U] = srcId >> 0;
unsigned int dstId = data.getDstId();
buffer[8U] = dstId >> 16;
buffer[9U] = dstId >> 8;
buffer[10U] = dstId >> 0;
::memcpy(buffer + 11U, m_id, 4U);
unsigned int slotNo = data.getSlotNo();
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
FLCO flco = data.getFLCO();
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
unsigned int slotIndex = slotNo - 1U;
unsigned int count = 1U;
unsigned char dataType = data.getDataType();
if (dataType == DT_VOICE_SYNC) {
buffer[15U] |= 0x10U;
} else if (dataType == DT_VOICE) {
buffer[15U] |= data.getN();
} else {
if (dataType == DT_VOICE_LC_HEADER) {
m_streamId[slotIndex] = ::rand() + 1U;
count = 2U;
}
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) {
m_streamId[slotIndex] = ::rand() + 1U;
count = 1U;
}
buffer[15U] |= (0x20U | dataType);
}
buffer[4U] = data.getSeqNo();
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
data.getData(buffer + 20U);
buffer[53U] = data.getBER();
buffer[54U] = data.getRSSI();
if (m_debug)
CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
for (unsigned int i = 0U; i < count; i++)
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
return true;
}
bool CDMRNetwork::writePosition(unsigned int id, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
::memcpy(buffer + 11U, data + 2U, 7U);
return write(buffer, 18U);
}
bool CDMRNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRA", 4U);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
buffer[11U] = type;
::memcpy(buffer + 12U, data + 2U, 7U);
return write(buffer, 19U);
}
void CDMRNetwork::close()
{
LogMessage("DMR, Closing DMR Network");
if (m_status == RUNNING) {
unsigned char buffer[9U];
::memcpy(buffer + 0U, "RPTCL", 5U);
::memcpy(buffer + 5U, m_id, 4U);
write(buffer, 9U);
}
m_socket.close();
m_retryTimer.stop();
m_timeoutTimer.stop();
}
void CDMRNetwork::clock(unsigned int ms)
{
if (m_status == WAITING_CONNECT) {
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
bool ret = m_socket.open();
if (ret) {
ret = writeLogin();
if (!ret)
return;
m_status = WAITING_LOGIN;
m_timeoutTimer.start();
}
m_retryTimer.start();
}
return;
}
in_addr address;
unsigned int port;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, port);
if (length < 0) {
LogError("DMR, Socket has failed, retrying connection to the master");
close();
open();
return;
}
// if (m_debug && length > 0)
// CUtils::dump(1U, "Network Received", m_buffer, length);
if (length > 0 && m_address.s_addr == address.s_addr && m_port == port) {
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_enabled) {
if (m_debug)
CUtils::dump(1U, "Network Received", m_buffer, length);
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
}
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
if (m_status == RUNNING) {
LogWarning("DMR, Login to the master has failed, retrying login ...");
m_status = WAITING_LOGIN;
m_timeoutTimer.start();
m_retryTimer.start();
} else {
/* Once the modem death spiral has been prevented in Modem.cpp
the Network sometimes times out and reaches here.
We want it to reconnect so... */
LogError("DMR, Login to the master has failed, retrying network ...");
close();
open();
return;
}
} else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) {
switch (m_status) {
case WAITING_LOGIN:
LogDebug("DMR, Sending authorisation");
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
writeAuthorisation();
m_status = WAITING_AUTHORISATION;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_AUTHORISATION:
LogDebug("DMR, Sending configuration");
writeConfig();
m_status = WAITING_CONFIG;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_CONFIG:
if (m_options.empty()) {
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
} else {
LogDebug("DMR, Sending options");
writeOptions();
m_status = WAITING_OPTIONS;
}
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_OPTIONS:
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
m_timeoutTimer.start();
m_retryTimer.start();
break;
default:
break;
}
} else if (::memcmp(m_buffer, "MSTCL", 5U) == 0) {
LogError("DMR, Master is closing down");
close();
open();
} else if (::memcmp(m_buffer, "MSTPONG", 7U) == 0) {
m_timeoutTimer.start();
} else if (::memcmp(m_buffer, "RPTSBKN", 7U) == 0) {
m_beacon = true;
} else {
CUtils::dump("Unknown packet from the master", m_buffer, length);
}
}
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
switch (m_status) {
case WAITING_LOGIN:
writeLogin();
break;
case WAITING_AUTHORISATION:
writeAuthorisation();
break;
case WAITING_OPTIONS:
writeOptions();
break;
case WAITING_CONFIG:
writeConfig();
break;
case RUNNING:
writePing();
break;
default:
break;
}
m_retryTimer.start();
}
m_timeoutTimer.clock(ms);
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
LogError("DMR, Connection to the master has timed out, retrying connection");
close();
open();
}
}
bool CDMRNetwork::writeLogin()
{
unsigned char buffer[8U];
::memcpy(buffer + 0U, "RPTL", 4U);
::memcpy(buffer + 4U, m_id, 4U);
return write(buffer, 8U);
}
bool CDMRNetwork::writeAuthorisation()
{
size_t size = m_password.size();
unsigned char* in = new unsigned char[size + sizeof(uint32_t)];
::memcpy(in, m_salt, sizeof(uint32_t));
for (size_t i = 0U; i < size; i++)
in[i + sizeof(uint32_t)] = m_password.at(i);
unsigned char out[40U];
::memcpy(out + 0U, "RPTK", 4U);
::memcpy(out + 4U, m_id, 4U);
CSHA256 sha256;
sha256.buffer(in, (unsigned int)(size + sizeof(uint32_t)), out + 8U);
delete[] in;
return write(out, 40U);
}
bool CDMRNetwork::writeOptions()
{
char buffer[300U];
::memcpy(buffer + 0U, "RPTO", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::strcpy(buffer + 8U, m_options.c_str());
return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U);
}
bool CDMRNetwork::writeConfig()
{
const char* software = "MMDVM";
char slots = '0';
if (m_duplex) {
if (m_slot1 && m_slot2)
slots = '3';
else if (m_slot1 && !m_slot2)
slots = '1';
else if (!m_slot1 && m_slot2)
slots = '2';
} else {
slots = '4';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM_DMO";
break;
case HWT_DVMEGA:
software = "MMDVM_DVMega";
break;
case HWT_MMDVM_HS:
software = "MMDVM_HS";
break;
default:
software = "MMDVM_Unknown";
break;
}
}
char buffer[400U];
::memcpy(buffer + 0U, "RPTC", 4U);
::memcpy(buffer + 4U, m_id, 4U);
char latitude[20U];
::sprintf(latitude, "%08f", m_latitude);
char longitude[20U];
::sprintf(longitude, "%09f", m_longitude);
unsigned int power = m_power;
if (power > 99U)
power = 99U;
int height = m_height;
if (height > 999)
height = 999;
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(),
m_description.c_str(), slots, m_url.c_str(), m_version, software);
return write((unsigned char*)buffer, 302U);
}
bool CDMRNetwork::writePing()
{
unsigned char buffer[11U];
::memcpy(buffer + 0U, "RPTPING", 7U);
::memcpy(buffer + 7U, m_id, 4U);
return write(buffer, 11U);
}
bool CDMRNetwork::wantsBeacon()
{
bool beacon = m_beacon;
m_beacon = false;
return beacon;
}
bool CDMRNetwork::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
// if (m_debug)
// CUtils::dump(1U, "Network Transmitted", data, length);
bool ret = m_socket.write(data, length, m_address, m_port);
if (!ret) {
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
m_socket.close();
open();
return false;
}
return true;
}

@ -0,0 +1,116 @@
/*
* Copyright (C) 2015,2016,2017 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(DMRNetwork_H)
#define DMRNetwork_H
#include "UDPSocket.h"
#include "Timer.h"
#include "RingBuffer.h"
#include "DMRData.h"
#include "Defines.h"
#include <string>
#include <cstdint>
class CDMRNetwork
{
public:
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType);
~CDMRNetwork();
void setOptions(const std::string& options);
void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
bool open();
void enable(bool enabled);
bool read(CDMRData& data);
bool write(const CDMRData& data);
bool writePosition(unsigned int id, const unsigned char* data);
bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
bool wantsBeacon();
void clock(unsigned int ms);
void close();
private:
in_addr m_address;
unsigned int m_port;
uint8_t* m_id;
std::string m_password;
bool m_duplex;
const char* m_version;
bool m_debug;
CUDPSocket m_socket;
bool m_enabled;
bool m_slot1;
bool m_slot2;
HW_TYPE m_hwType;
enum STATUS {
WAITING_CONNECT,
WAITING_LOGIN,
WAITING_AUTHORISATION,
WAITING_CONFIG,
WAITING_OPTIONS,
RUNNING
};
STATUS m_status;
CTimer m_retryTimer;
CTimer m_timeoutTimer;
unsigned char* m_buffer;
unsigned char* m_salt;
uint32_t* m_streamId;
CRingBuffer<unsigned char> m_rxData;
std::string m_options;
std::string m_callsign;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_power;
unsigned int m_colorCode;
float m_latitude;
float m_longitude;
int m_height;
std::string m_location;
std::string m_description;
std::string m_url;
bool m_beacon;
bool writeLogin();
bool writeAuthorisation();
bool writeOptions();
bool writeConfig();
bool writePing();
bool write(const unsigned char* data, unsigned int length);
};
#endif

@ -0,0 +1,228 @@
/*
* 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 "DMRShortLC.h"
#include "Hamming.h"
#include "Utils.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CDMRShortLC::CDMRShortLC() :
m_rawData(NULL),
m_deInterData(NULL)
{
m_rawData = new bool[72U];
m_deInterData = new bool[68U];
}
CDMRShortLC::~CDMRShortLC()
{
delete[] m_rawData;
delete[] m_deInterData;
}
// The main decode function
bool CDMRShortLC::decode(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
// Get the raw binary
decodeExtractBinary(in);
// Deinterleave
decodeDeInterleave();
// Error check
bool ret = decodeErrorCheck();
if (!ret)
return false;
// Extract Data
decodeExtractData(out);
return true;
}
// The main encode function
void CDMRShortLC::encode(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
// Extract Data
encodeExtractData(in);
// Error check
encodeErrorCheck();
// Deinterleave
encodeInterleave();
// Get the raw binary
encodeExtractBinary(out);
}
void CDMRShortLC::decodeExtractBinary(const unsigned char* in)
{
assert(in != NULL);
CUtils::byteToBitsBE(in[0U], m_rawData + 0U);
CUtils::byteToBitsBE(in[1U], m_rawData + 8U);
CUtils::byteToBitsBE(in[2U], m_rawData + 16U);
CUtils::byteToBitsBE(in[3U], m_rawData + 24U);
CUtils::byteToBitsBE(in[4U], m_rawData + 32U);
CUtils::byteToBitsBE(in[5U], m_rawData + 40U);
CUtils::byteToBitsBE(in[6U], m_rawData + 48U);
CUtils::byteToBitsBE(in[7U], m_rawData + 56U);
CUtils::byteToBitsBE(in[8U], m_rawData + 64U);
}
// Deinterleave the raw data
void CDMRShortLC::decodeDeInterleave()
{
for (unsigned int i = 0U; i < 68U; i++)
m_deInterData[i] = false;
for (unsigned int a = 0U; a < 67U; a++) {
// Calculate the interleave sequence
unsigned int interleaveSequence = (a * 4U) % 67U;
// Shuffle the data
m_deInterData[a] = m_rawData[interleaveSequence];
}
m_deInterData[67U] = m_rawData[67U];
}
// Check each row with a Hamming (17,12,3) code and each column with a parity bit
bool CDMRShortLC::decodeErrorCheck()
{
// Run through each of the 3 rows containing data
CHamming::decode17123(m_deInterData + 0U);
CHamming::decode17123(m_deInterData + 17U);
CHamming::decode17123(m_deInterData + 34U);
// Run through each of the 17 columns
for (unsigned int c = 0U; c < 17U; c++) {
bool bit = m_deInterData[c + 0U] ^ m_deInterData[c + 17U] ^ m_deInterData[c + 34U];
if (bit != m_deInterData[c + 51U])
return false;
}
return true;
}
// Extract the 36 bits of payload
void CDMRShortLC::decodeExtractData(unsigned char* data) const
{
assert(data != NULL);
bool bData[40U];
for (unsigned int i = 0U; i < 40U; i++)
bData[i] = false;
unsigned int pos = 4U;
for (unsigned int a = 0U; a < 12U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 17U; a < 29U; a++, pos++)
bData[pos] = m_deInterData[a];
for (unsigned int a = 34U; a < 46U; a++, pos++)
bData[pos] = m_deInterData[a];
CUtils::bitsToByteBE(bData + 0U, data[0U]);
CUtils::bitsToByteBE(bData + 8U, data[1U]);
CUtils::bitsToByteBE(bData + 16U, data[2U]);
CUtils::bitsToByteBE(bData + 24U, data[3U]);
CUtils::bitsToByteBE(bData + 32U, data[4U]);
}
// Extract the 36 bits of payload
void CDMRShortLC::encodeExtractData(const unsigned char* in) const
{
assert(in != NULL);
bool bData[40U];
CUtils::byteToBitsBE(in[0U], bData + 0U);
CUtils::byteToBitsBE(in[1U], bData + 8U);
CUtils::byteToBitsBE(in[2U], bData + 16U);
CUtils::byteToBitsBE(in[3U], bData + 24U);
CUtils::byteToBitsBE(in[4U], bData + 32U);
for (unsigned int i = 0U; i < 68U; i++)
m_deInterData[i] = false;
unsigned int pos = 4U;
for (unsigned int a = 0U; a < 12U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 17U; a < 29U; a++, pos++)
m_deInterData[a] = bData[pos];
for (unsigned int a = 34U; a < 46U; a++, pos++)
m_deInterData[a] = bData[pos];
}
// Check each row with a Hamming (17,12,3) code and each column with a parity bit
void CDMRShortLC::encodeErrorCheck()
{
// Run through each of the 3 rows containing data
CHamming::encode17123(m_deInterData + 0U);
CHamming::encode17123(m_deInterData + 17U);
CHamming::encode17123(m_deInterData + 34U);
// Run through each of the 17 columns
for (unsigned int c = 0U; c < 17U; c++)
m_deInterData[c + 51U] = m_deInterData[c + 0U] ^ m_deInterData[c + 17U] ^ m_deInterData[c + 34U];
}
// Interleave the raw data
void CDMRShortLC::encodeInterleave()
{
for (unsigned int i = 0U; i < 72U; i++)
m_rawData[i] = false;
for (unsigned int a = 0U; a < 67U; a++) {
// Calculate the interleave sequence
unsigned int interleaveSequence = (a * 4U) % 67U;
// Unshuffle the data
m_rawData[interleaveSequence] = m_deInterData[a];
}
m_rawData[67U] = m_deInterData[67U];
}
void CDMRShortLC::encodeExtractBinary(unsigned char* data)
{
assert(data != NULL);
CUtils::bitsToByteBE(m_rawData + 0U, data[0U]);
CUtils::bitsToByteBE(m_rawData + 8U, data[1U]);
CUtils::bitsToByteBE(m_rawData + 16U, data[2U]);
CUtils::bitsToByteBE(m_rawData + 24U, data[3U]);
CUtils::bitsToByteBE(m_rawData + 32U, data[4U]);
CUtils::bitsToByteBE(m_rawData + 40U, data[5U]);
CUtils::bitsToByteBE(m_rawData + 48U, data[6U]);
CUtils::bitsToByteBE(m_rawData + 56U, data[7U]);
CUtils::bitsToByteBE(m_rawData + 64U, data[8U]);
}

@ -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(DMRSHORTLC_H)
#define DMRSHORTLC_H
class CDMRShortLC
{
public:
CDMRShortLC();
~CDMRShortLC();
bool decode(const unsigned char* in, unsigned char* out);
void encode(const unsigned char* in, unsigned char* out);
private:
bool* m_rawData;
bool* m_deInterData;
void decodeExtractBinary(const unsigned char* in);
bool decodeErrorCheck();
void decodeDeInterleave();
void decodeExtractData(unsigned char* data) const;
void encodeExtractData(const unsigned char* in) const;
void encodeInterleave();
void encodeErrorCheck();
void encodeExtractBinary(unsigned char* data);
};
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,155 @@
/*
* Copyright (C) 2015,2016,2017 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(DMRSlot_H)
#define DMRSlot_H
#include "RSSIInterpolator.h"
#include "DMREmbeddedData.h"
#include "DMRNetwork.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "DMRLookup.h"
#include "AMBEFEC.h"
#include "DMRSlot.h"
#include "DMRData.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include "DMRLC.h"
#include <vector>
enum ACTIVITY_TYPE {
ACTIVITY_NONE,
ACTIVITY_VOICE,
ACTIVITY_DATA,
ACTIVITY_CSBK,
ACTIVITY_EMERG
};
class CDMRSlot {
public:
CDMRSlot(unsigned int slotNo, unsigned int timeout);
~CDMRSlot();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void writeNetwork(const CDMRData& data);
void clock();
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter);
private:
unsigned int m_slotNo;
CRingBuffer<unsigned char> m_queue;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
CDMREmbeddedData m_rfEmbeddedLC;
CDMREmbeddedData* m_rfEmbeddedData;
unsigned int m_rfEmbeddedReadN;
unsigned int m_rfEmbeddedWriteN;
unsigned char m_rfTalkerId;
unsigned char* m_rfTalkerAlias;
CDMREmbeddedData m_netEmbeddedLC;
CDMREmbeddedData* m_netEmbeddedData;
unsigned int m_netEmbeddedReadN;
unsigned int m_netEmbeddedWriteN;
unsigned char m_netTalkerId;
CDMRLC* m_rfLC;
CDMRLC* m_netLC;
unsigned char m_rfSeqNo;
unsigned char m_netSeqNo;
unsigned char m_rfN;
unsigned char m_netN;
CTimer m_networkWatchdog;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_packetTimer;
CStopWatch m_interval;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_netLost;
CAMBEFEC m_fec;
unsigned int m_rfBits;
unsigned int m_netBits;
unsigned int m_rfErrs;
unsigned int m_netErrs;
bool m_rfTimeout;
bool m_netTimeout;
unsigned char* m_lastFrame;
bool m_lastFrameValid;
unsigned char m_rssi;
unsigned char m_maxRSSI;
unsigned char m_minRSSI;
unsigned int m_aveRSSI;
unsigned int m_rssiCount;
FILE* m_fp;
static unsigned int m_colorCode;
static bool m_embeddedLCOnly;
static bool m_dumpTAData;
static CModem* m_modem;
static CDMRNetwork* m_network;
static CDisplay* m_display;
static bool m_duplex;
static CDMRLookup* m_lookup;
static unsigned int m_hangCount;
static CRSSIInterpolator* m_rssiMapper;
static unsigned int m_jitterTime;
static unsigned int m_jitterSlots;
static unsigned char* m_idle;
static FLCO m_flco1;
static unsigned char m_id1;
static ACTIVITY_TYPE m_activity1;
static FLCO m_flco2;
static unsigned char m_id2;
static ACTIVITY_TYPE m_activity2;
void logGPSPosition(const unsigned char* data);
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
void writeNetworkRF(const unsigned char* data, unsigned char dataType, unsigned char errors = 0U);
void writeNetworkRF(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId, unsigned char errors = 0U);
void writeEndRF(bool writeEnd = false);
void writeEndNet(bool writeEnd = false);
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
bool insertSilence(const unsigned char* data, unsigned char seqNo);
void insertSilence(unsigned int count);
static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, ACTIVITY_TYPE type = ACTIVITY_NONE);
};
#endif

@ -0,0 +1,92 @@
/*
* 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 "DMRSlotType.h"
#include "Golay2087.h"
#include <cstdio>
#include <cassert>
CDMRSlotType::CDMRSlotType() :
m_colorCode(0U),
m_dataType(0U)
{
}
CDMRSlotType::~CDMRSlotType()
{
}
void CDMRSlotType::putData(const unsigned char* data)
{
assert(data != NULL);
unsigned char DMRSlotType[3U];
DMRSlotType[0U] = (data[12U] << 2) & 0xFCU;
DMRSlotType[0U] |= (data[13U] >> 6) & 0x03U;
DMRSlotType[1U] = (data[13U] << 2) & 0xC0U;
DMRSlotType[1U] |= (data[19U] << 2) & 0x3CU;
DMRSlotType[1U] |= (data[20U] >> 6) & 0x03U;
DMRSlotType[2U] = (data[20U] << 2) & 0xF0U;
unsigned char code = CGolay2087::decode(DMRSlotType);
m_colorCode = (code >> 4) & 0x0FU;
m_dataType = (code >> 0) & 0x0FU;
}
void CDMRSlotType::getData(unsigned char* data) const
{
assert(data != NULL);
unsigned char DMRSlotType[3U];
DMRSlotType[0U] = (m_colorCode << 4) & 0xF0U;
DMRSlotType[0U] |= (m_dataType << 0) & 0x0FU;
DMRSlotType[1U] = 0x00U;
DMRSlotType[2U] = 0x00U;
CGolay2087::encode(DMRSlotType);
data[12U] = (data[12U] & 0xC0U) | ((DMRSlotType[0U] >> 2) & 0x3FU);
data[13U] = (data[13U] & 0x0FU) | ((DMRSlotType[0U] << 6) & 0xC0U) | ((DMRSlotType[1U] >> 2) & 0x30U);
data[19U] = (data[19U] & 0xF0U) | ((DMRSlotType[1U] >> 2) & 0x0FU);
data[20U] = (data[20U] & 0x03U) | ((DMRSlotType[1U] << 6) & 0xC0U) | ((DMRSlotType[2U] >> 2) & 0x3CU);
}
unsigned char CDMRSlotType::getColorCode() const
{
return m_colorCode;
}
void CDMRSlotType::setColorCode(unsigned char code)
{
m_colorCode = code;
}
unsigned char CDMRSlotType::getDataType() const
{
return m_dataType;
}
void CDMRSlotType::setDataType(unsigned char type)
{
m_dataType = type;
}

@ -0,0 +1,42 @@
/*
* 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(DMRSLOTTYPE_H)
#define DMRSLOTTYPE_H
class CDMRSlotType
{
public:
CDMRSlotType();
~CDMRSlotType();
void putData(const unsigned char* data);
void getData(unsigned char* data) const;
unsigned char getColorCode() const;
void setColorCode(unsigned char code);
unsigned char getDataType() const;
void setDataType(unsigned char type);
private:
unsigned char m_colorCode;
unsigned char m_dataType;
};
#endif

@ -0,0 +1,374 @@
/*
* 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; 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 "DMRTrellis.h"
#include "DMRDefines.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
const unsigned int INTERLEAVE_TABLE[] = {
0U, 1U, 8U, 9U, 16U, 17U, 24U, 25U, 32U, 33U, 40U, 41U, 48U, 49U, 56U, 57U, 64U, 65U, 72U, 73U, 80U, 81U, 88U, 89U, 96U, 97U,
2U, 3U, 10U, 11U, 18U, 19U, 26U, 27U, 34U, 35U, 42U, 43U, 50U, 51U, 58U, 59U, 66U, 67U, 74U, 75U, 82U, 83U, 90U, 91U,
4U, 5U, 12U, 13U, 20U, 21U, 28U, 29U, 36U, 37U, 44U, 45U, 52U, 53U, 60U, 61U, 68U, 69U, 76U, 77U, 84U, 85U, 92U, 93U,
6U, 7U, 14U, 15U, 22U, 23U, 30U, 31U, 38U, 39U, 46U, 47U, 54U, 55U, 62U, 63U, 70U, 71U, 78U, 79U, 86U, 87U, 94U, 95U};
const unsigned char ENCODE_TABLE[] = {
0U, 8U, 4U, 12U, 2U, 10U, 6U, 14U,
4U, 12U, 2U, 10U, 6U, 14U, 0U, 8U,
1U, 9U, 5U, 13U, 3U, 11U, 7U, 15U,
5U, 13U, 3U, 11U, 7U, 15U, 1U, 9U,
3U, 11U, 7U, 15U, 1U, 9U, 5U, 13U,
7U, 15U, 1U, 9U, 5U, 13U, 3U, 11U,
2U, 10U, 6U, 14U, 0U, 8U, 4U, 12U,
6U, 14U, 0U, 8U, 4U, 12U, 2U, 10U};
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT(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_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CDMRTrellis::CDMRTrellis()
{
}
CDMRTrellis::~CDMRTrellis()
{
}
bool CDMRTrellis::decode(const unsigned char* data, unsigned char* payload)
{
assert(data != NULL);
assert(payload != NULL);
signed char dibits[98U];
deinterleave(data, dibits);
unsigned char points[49U];
dibitsToPoints(dibits, points);
// Check the original code
unsigned char tribits[49U];
unsigned int failPos = checkCode(points, tribits);
if (failPos == 999U) {
tribitsToBits(tribits, payload);
return true;
}
unsigned char savePoints[49U];
for (unsigned int i = 0U; i < 49U; i++)
savePoints[i] = points[i];
bool ret = fixCode(points, failPos, payload);
if (ret)
return true;
if (failPos == 0U)
return false;
// Backtrack one place for a last go
return fixCode(savePoints, failPos - 1U, payload);
}
void CDMRTrellis::encode(const unsigned char* payload, unsigned char* data)
{
assert(payload != NULL);
assert(data != NULL);
unsigned char tribits[49U];
bitsToTribits(payload, tribits);
unsigned char points[49U];
unsigned char state = 0U;
for (unsigned int i = 0U; i < 49U; i++) {
unsigned char tribit = tribits[i];
points[i] = ENCODE_TABLE[state * 8U + tribit];
state = tribit;
}
signed char dibits[98U];
pointsToDibits(points, dibits);
interleave(dibits, data);
}
void CDMRTrellis::deinterleave(const unsigned char* data, signed char* dibits) const
{
for (unsigned int i = 0U; i < 98U; i++) {
unsigned int n = i * 2U + 0U;
if (n >= 98U) n += 68U;
bool b1 = READ_BIT(data, n) != 0x00U;
n = i * 2U + 1U;
if (n >= 98U) n += 68U;
bool b2 = READ_BIT(data, n) != 0x00U;
signed char dibit;
if (!b1 && b2)
dibit = +3;
else if (!b1 && !b2)
dibit = +1;
else if (b1 && !b2)
dibit = -1;
else
dibit = -3;
n = INTERLEAVE_TABLE[i];
dibits[n] = dibit;
}
}
void CDMRTrellis::interleave(const signed char* dibits, unsigned char* data) const
{
for (unsigned int i = 0U; i < 98U; i++) {
unsigned int n = INTERLEAVE_TABLE[i];
bool b1, b2;
switch (dibits[n]) {
case +3:
b1 = false;
b2 = true;
break;
case +1:
b1 = false;
b2 = false;
break;
case -1:
b1 = true;
b2 = false;
break;
default:
b1 = true;
b2 = true;
break;
}
n = i * 2U + 0U;
if (n >= 98U) n += 68U;
WRITE_BIT(data, n, b1);
n = i * 2U + 1U;
if (n >= 98U) n += 68U;
WRITE_BIT(data, n, b2);
}
}
void CDMRTrellis::dibitsToPoints(const signed char* dibits, unsigned char* points) const
{
for (unsigned int i = 0U; i < 49U; i++) {
if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == -1)
points[i] = 0U;
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == -1)
points[i] = 1U;
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == -3)
points[i] = 2U;
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == -3)
points[i] = 3U;
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == -1)
points[i] = 4U;
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == -1)
points[i] = 5U;
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == -3)
points[i] = 6U;
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == -3)
points[i] = 7U;
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == +3)
points[i] = 8U;
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == +3)
points[i] = 9U;
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == +1)
points[i] = 10U;
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == +1)
points[i] = 11U;
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == +3)
points[i] = 12U;
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == +3)
points[i] = 13U;
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == +1)
points[i] = 14U;
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == +1)
points[i] = 15U;
}
}
void CDMRTrellis::pointsToDibits(const unsigned char* points, signed char* dibits) const
{
for (unsigned int i = 0U; i < 49U; i++) {
switch (points[i]) {
case 0U:
dibits[i * 2U + 0U] = +1;
dibits[i * 2U + 1U] = -1;
break;
case 1U:
dibits[i * 2U + 0U] = -1;
dibits[i * 2U + 1U] = -1;
break;
case 2U:
dibits[i * 2U + 0U] = +3;
dibits[i * 2U + 1U] = -3;
break;
case 3U:
dibits[i * 2U + 0U] = -3;
dibits[i * 2U + 1U] = -3;
break;
case 4U:
dibits[i * 2U + 0U] = -3;
dibits[i * 2U + 1U] = -1;
break;
case 5U:
dibits[i * 2U + 0U] = +3;
dibits[i * 2U + 1U] = -1;
break;
case 6U:
dibits[i * 2U + 0U] = -1;
dibits[i * 2U + 1U] = -3;
break;
case 7U:
dibits[i * 2U + 0U] = +1;
dibits[i * 2U + 1U] = -3;
break;
case 8U:
dibits[i * 2U + 0U] = -3;
dibits[i * 2U + 1U] = +3;
break;
case 9U:
dibits[i * 2U + 0U] = +3;
dibits[i * 2U + 1U] = +3;
break;
case 10U:
dibits[i * 2U + 0U] = -1;
dibits[i * 2U + 1U] = +1;
break;
case 11U:
dibits[i * 2U + 0U] = +1;
dibits[i * 2U + 1U] = +1;
break;
case 12U:
dibits[i * 2U + 0U] = +1;
dibits[i * 2U + 1U] = +3;
break;
case 13U:
dibits[i * 2U + 0U] = -1;
dibits[i * 2U + 1U] = +3;
break;
case 14U:
dibits[i * 2U + 0U] = +3;
dibits[i * 2U + 1U] = +1;
break;
default:
dibits[i * 2U + 0U] = -3;
dibits[i * 2U + 1U] = +1;
break;
}
}
}
void CDMRTrellis::bitsToTribits(const unsigned char* payload, unsigned char* tribits) const
{
for (unsigned int i = 0U; i < 48U; i++) {
unsigned int n = 143U - i * 3U;
bool b1 = READ_BIT(payload, n) != 0x00U;
n--;
bool b2 = READ_BIT(payload, n) != 0x00U;
n--;
bool b3 = READ_BIT(payload, n) != 0x00U;
unsigned char tribit = 0U;
tribit |= b1 ? 4U : 0U;
tribit |= b2 ? 2U : 0U;
tribit |= b3 ? 1U : 0U;
tribits[i] = tribit;
}
tribits[48U] = 0U;
}
void CDMRTrellis::tribitsToBits(const unsigned char* tribits, unsigned char* payload) const
{
for (unsigned int i = 0U; i < 48U; i++) {
unsigned char tribit = tribits[i];
bool b1 = (tribit & 0x04U) == 0x04U;
bool b2 = (tribit & 0x02U) == 0x02U;
bool b3 = (tribit & 0x01U) == 0x01U;
unsigned int n = 143U - i * 3U;
WRITE_BIT(payload, n, b1);
n--;
WRITE_BIT(payload, n, b2);
n--;
WRITE_BIT(payload, n, b3);
}
}
bool CDMRTrellis::fixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) const
{
for (unsigned j = 0U; j < 20U; j++) {
unsigned int bestPos = 0U;
unsigned int bestVal = 0U;
for (unsigned int i = 0U; i < 16U; i++) {
points[failPos] = i;
unsigned char tribits[49U];
unsigned int pos = checkCode(points, tribits);
if (pos == 999U) {
tribitsToBits(tribits, payload);
return true;
}
if (pos > bestPos) {
bestPos = pos;
bestVal = i;
}
}
points[failPos] = bestVal;
failPos = bestPos;
}
return false;
}
unsigned int CDMRTrellis::checkCode(const unsigned char* points, unsigned char* tribits) const
{
unsigned char state = 0U;
for (unsigned int i = 0U; i < 49U; i++) {
tribits[i] = 9U;
for (unsigned int j = 0U; j < 8U; j++) {
if (points[i] == ENCODE_TABLE[state * 8U + j]) {
tribits[i] = j;
break;
}
}
if (tribits[i] == 9U)
return i;
state = tribits[i];
}
if (tribits[48U] != 0U)
return 48U;
return 999U;
}

@ -0,0 +1,36 @@
/*
* 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; 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 DMRTrellis_H
#define DMRTrellis_H
class CDMRTrellis {
public:
CDMRTrellis();
~CDMRTrellis();
bool decode(const unsigned char* data, unsigned char* payload);
void encode(const unsigned char* payload, unsigned char* data);
private:
void deinterleave(const unsigned char* in, signed char* dibits) const;
void interleave(const signed char* dibits, unsigned char* out) const;
void dibitsToPoints(const signed char* dibits, unsigned char* points) const;
void pointsToDibits(const unsigned char* points, signed char* dibits) const;
void bitsToTribits(const unsigned char* payload, unsigned char* tribits) const;
void tribitsToBits(const unsigned char* tribits, unsigned char* payload) const;
bool fixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) const;
unsigned int checkCode(const unsigned char* points, unsigned char* tribits) const;
};
#endif

@ -0,0 +1,32 @@
# DMRplus - Startup Options
## Introduction
This file is to give an overview over the Options-parameter in MMDVM.ini [DMR Network]-section.
## Example
You can pull some conection-info at startup to the DMRplus-Network to define the behavior of TS1 and TS2 in DMR-mode.
An example of such a line would be following:
Options=StartRef=4013;RelinkTime=15;UserLink=1;TS1_1=262;TS1_2=1;TS1_3=20;TS1_4=110;TS1_5=270;
If an option is set, it overwrites the setting preset at the master, if an option is empty, it unsets a predefined setting from
the master. If an option is not set, the default from the master would be taken over.
## What the parameters are about?
Here is a quick explaination about the options to be set:
* StartRef: This is the default reflector in TS2, in example: Refl. 4013
* RelinkTime: This is the time to fall back to the default-reflector if linked to another one and no local traffic is done,
not yet implemented, would come next
* UserLink: This defines, if users are allowed to link to another reflector (other than defined as startreflector)
* 1 = allow
* 0 = disallow
* TS1_1: This is the first of 5 talkgroups that could be set static, in example: TG262
* TS1_2: This is the second of 5 talkgroups that could be set static, in example: TG1
* TS1_3: This is the third of 5 talkgroups that could be set static, in example: TG20
* TS1_4: This is the fourth of 5 talkgroups that could be set static, in example: TG110
* TS1_5: This is the fifth of 5 talkgroups that could be set static, in example: TG270
---
Info created by DG9VH 2016-11-11

@ -0,0 +1,58 @@
/*
* Copyright (C) 2015,2016,2017 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(Defines_H)
#define Defines_H
const unsigned char MODE_IDLE = 0U;
const unsigned char MODE_DSTAR = 1U;
const unsigned char MODE_DMR = 2U;
const unsigned char MODE_YSF = 3U;
const unsigned char MODE_P25 = 4U;
const unsigned char MODE_CW = 98U;
const unsigned char MODE_LOCKOUT = 99U;
const unsigned char MODE_ERROR = 100U;
const unsigned char TAG_HEADER = 0x00U;
const unsigned char TAG_DATA = 0x01U;
const unsigned char TAG_LOST = 0x02U;
const unsigned char TAG_EOT = 0x03U;
enum HW_TYPE {
HWT_MMDVM,
HWT_DVMEGA,
HWT_MMDVM_HS,
HWT_UNKNOWN
};
enum RPT_RF_STATE {
RS_RF_LISTENING,
RS_RF_LATE_ENTRY,
RS_RF_AUDIO,
RS_RF_DATA,
RS_RF_REJECTED,
RS_RF_INVALID
};
enum RPT_NET_STATE {
RS_NET_IDLE,
RS_NET_AUDIO,
RS_NET_DATA
};
#endif

@ -0,0 +1,510 @@
/*
* Copyright (C) 2016,2017 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 "Display.h"
#include "Defines.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CDisplay::CDisplay() :
m_timer1(3000U, 3U),
m_timer2(3000U, 3U),
m_mode1(MODE_IDLE),
m_mode2(MODE_IDLE)
{
}
CDisplay::~CDisplay()
{
}
void CDisplay::setIdle()
{
m_timer1.stop();
m_timer2.stop();
m_mode1 = MODE_IDLE;
m_mode2 = MODE_IDLE;
setIdleInt();
}
void CDisplay::setLockout()
{
m_timer1.stop();
m_timer2.stop();
m_mode1 = MODE_IDLE;
m_mode2 = MODE_IDLE;
setLockoutInt();
}
void CDisplay::setError(const char* text)
{
assert(text != NULL);
m_timer1.stop();
m_timer2.stop();
m_mode1 = MODE_IDLE;
m_mode2 = MODE_IDLE;
setErrorInt(text);
}
void CDisplay::writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{
assert(my1 != NULL);
assert(my2 != NULL);
assert(your != NULL);
assert(type != NULL);
assert(reflector != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeDStarInt(my1, my2, your, type, reflector);
}
void CDisplay::writeDStarRSSI(unsigned char rssi)
{
if (rssi != 0U)
writeDStarRSSIInt(rssi);
}
void CDisplay::writeDStarBER(float ber)
{
writeDStarBERInt(ber);
}
void CDisplay::clearDStar()
{
if (m_timer1.hasExpired()) {
clearDStarInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_DSTAR;
}
}
void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{
assert(type != NULL);
if (slotNo == 1U) {
m_timer1.start();
m_mode1 = MODE_IDLE;
} else {
m_timer2.start();
m_mode2 = MODE_IDLE;
}
writeDMRInt(slotNo, src, group, dst, type);
//TTS
char voice[80];
strcpy (voice,"echo \"");
if (strcmp ("",src.c_str()) !=0){
std::string s =src.c_str();
for (char & c : s)
{
if (c == 'A'){
strcat(voice," Alfa ");
}
else if (c == 'B'){
strcat(voice," Bravo ");
}
else if (c == 'C'){
strcat(voice," Charli ");
}
else if (c == 'D'){
strcat(voice," Delta ");
}
else if (c == 'E'){
strcat(voice," Eko ");
}
else if (c == 'F'){
strcat(voice," Foxtrot ");
}
else if (c == 'G'){
strcat(voice," Golf ");
}
else if (c == 'H'){
strcat(voice," Hotel ");
}
else if (c == 'I'){
strcat(voice," India ");
}
else if (c == 'J'){
strcat(voice," Yuliet ");
}
else if (c == 'K'){
strcat(voice," Kilo ");
}
else if (c == 'L'){
strcat(voice," Lima ");
}
else if (c == 'M'){
strcat(voice," Maik ");
}
else if (c == 'N'){
strcat(voice," November ");
}
else if (c == 'O'){
strcat(voice," Oscar ");
}
else if (c == 'P'){
strcat(voice," Papa ");
}
else if (c == 'Q'){
strcat(voice," Quebec ");
}
else if (c == 'R'){
strcat(voice," Romeo ");
}
else if (c == 'S'){
strcat(voice," Sierra ");
}
else if (c == 'T'){
strcat(voice," Tango ");
}
else if (c == 'U'){
strcat(voice," Union ");
}
else if (c == 'V'){
strcat(voice," Victor ");
}
else if (c == 'W'){
strcat(voice," Güisky ");
}
else if (c == 'X'){
strcat(voice," Exray ");
}
else if (c == 'Y'){
strcat(voice," Yanki ");
}
else if (c == 'Z'){
strcat(voice," Zulu ");
}
else if (c == '0'){
strcat(voice," 0 ");
}
else if (c == '1'){
strcat(voice," uno ");
}
else if (c == '2'){
strcat(voice," 2 ");
}
else if (c == '3'){
strcat(voice," treess ");
}
else if (c == '4'){
strcat(voice," 4 ");
}
else if (c == '5'){
strcat(voice," 5 ");
}
else if (c == '6'){
strcat(voice," seiiss ");
}
else if (c == '7'){
strcat(voice," 7 ");
}
else if (c == '8'){
strcat(voice," 8 ");
}
else if (c == '9'){
strcat(voice," 9 ");
}
c = '*';
}
// strcat (voice,src.c_str());
strcat (voice,"\"| festival --tts\n");
//strcat (voice,"\n");
//printf ("%s\n",voice);
FILE *fpa;
fpa = fopen ( "/ram/mm_voice.sh", "r+" );
fprintf (fpa,voice);
fclose ( fpa );
system ("/ram/mm_voice.sh &");
}
if ((strcmp ("99990",dst.c_str()) ==0))
{
printf ("Wifi Off\n");
system("sudo rfkill block 0");
}
else if ((strcmp ("99991",dst.c_str()) ==0))
{
printf ("Wifi On\n");
system("sudo rfkill unblock 0");
}
}
void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi)
{
if (rssi != 0U)
writeDMRRSSIInt(slotNo, rssi);
}
void CDisplay::writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
{
char TA[32U];
unsigned char *b;
unsigned char c;
int j;
unsigned int i,t1,t2, TAsize, TAformat;
if (strcmp(type," ")==0) { writeDMRTAInt(slotNo, (unsigned char*)TA, type); return; }
TAformat=(talkerAlias[0]>>6U) & 0x03U;
TAsize = (talkerAlias[0]>>1U) & 0x1FU;
::strcpy(TA,"(could not decode)");
switch (TAformat) {
case 0U: // 7 bit
::memset (&TA,0,32U);
b=&talkerAlias[0];
t1=0; t2=0; c=0;
for (i=0;(i<32U)&&(t2<TAsize);i++) {
for (j=7U;j>=0;j--) {
c = (c<<1U) | (b[i] >> j);
if (++t1==7U) { if (i>0) {TA[t2++]=c & 0x7FU; } t1=0; c=0; }
}
}
break;
case 1U: // ISO 8 bit
case 2U: // UTF8
::strcpy(TA,(char*)talkerAlias+1U);
break;
case 3U: // UTF16 poor man's conversion
t2=0;
::memset (&TA,0,32U);
for(i=0;(i<15)&&(t2<TAsize);i++) {
if (talkerAlias[2U*i+1U]==0)
TA[t2++]=talkerAlias[2U*i+2U]; else TA[t2++]='?';
}
TA[TAsize]=0;
break;
}
LogMessage("DMR Talker Alias (Data Format %u, Received %u/%u char): '%s'", TAformat, ::strlen(TA), TAsize, TA);
if (::strlen(TA)>TAsize) { if (strlen(TA)<29U) strcat(TA," ?"); else strcpy(TA+28U," ?"); }
if (strlen((char*)TA)>=4U) writeDMRTAInt(slotNo, (unsigned char*)TA, type);
}
void CDisplay::writeDMRBER(unsigned int slotNo, float ber)
{
writeDMRBERInt(slotNo, ber);
}
void CDisplay::clearDMR(unsigned int slotNo)
{
if (slotNo == 1U) {
if (m_timer1.hasExpired()) {
clearDMRInt(slotNo);
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_DMR;
}
} else {
if (m_timer2.hasExpired()) {
clearDMRInt(slotNo);
m_timer2.stop();
m_mode2 = MODE_IDLE;
} else {
m_mode2 = MODE_DMR;
}
}
}
void CDisplay::writeFusion(const char* source, const char* dest, const char* type, const char* origin)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
assert(origin != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeFusionInt(source, dest, type, origin);
}
void CDisplay::writeFusionRSSI(unsigned char rssi)
{
if (rssi != 0U)
writeFusionRSSIInt(rssi);
}
void CDisplay::writeFusionBER(float ber)
{
writeFusionBERInt(ber);
}
void CDisplay::clearFusion()
{
if (m_timer1.hasExpired()) {
clearFusionInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_YSF;
}
}
void CDisplay::writeP25(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeP25Int(source, group, dest, type);
}
void CDisplay::writeP25RSSI(unsigned char rssi)
{
if (rssi != 0U)
writeP25RSSIInt(rssi);
}
void CDisplay::writeP25BER(float ber)
{
writeP25BERInt(ber);
}
void CDisplay::clearP25()
{
if (m_timer1.hasExpired()) {
clearP25Int();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_P25;
}
}
void CDisplay::writeCW()
{
m_timer1.start();
m_mode1 = MODE_CW;
writeCWInt();
}
void CDisplay::clock(unsigned int ms)
{
m_timer1.clock(ms);
if (m_timer1.isRunning() && m_timer1.hasExpired()) {
switch (m_mode1) {
case MODE_DSTAR:
clearDStarInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_DMR:
clearDMRInt(1U);
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_YSF:
clearFusionInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_P25:
clearP25Int();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_CW:
clearCWInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
default:
break;
}
}
// Timer/mode 2 are only used for DMR
m_timer2.clock(ms);
if (m_timer2.isRunning() && m_timer2.hasExpired()) {
if (m_mode2 == MODE_DMR) {
clearDMRInt(2U);
m_mode2 = MODE_IDLE;
m_timer2.stop();
}
}
clockInt(ms);
}
void CDisplay::clockInt(unsigned int ms)
{
}
void CDisplay::writeDStarRSSIInt(unsigned char rssi)
{
}
void CDisplay::writeDStarBERInt(float ber)
{
}
void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
{
}
void CDisplay::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
{
}
void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber)
{
}
void CDisplay::writeFusionRSSIInt(unsigned char rssi)
{
}
void CDisplay::writeFusionBERInt(float ber)
{
}
void CDisplay::writeP25RSSIInt(unsigned char rssi)
{
}
void CDisplay::writeP25BERInt(float ber)
{
}

@ -0,0 +1,104 @@
/*
* Copyright (C) 2016,2017 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(DISPLAY_H)
#define DISPLAY_H
#include "Timer.h"
#include <string>
class CDisplay
{
public:
CDisplay();
virtual ~CDisplay() = 0;
virtual bool open() = 0;
void setIdle();
void setLockout();
void setError(const char* text);
void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
void writeDStarRSSI(unsigned char rssi);
void writeDStarBER(float ber);
void clearDStar();
void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
void writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
void writeDMRBER(unsigned int slotNo, float ber);
void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
void clearDMR(unsigned int slotNo);
void writeFusion(const char* source, const char* dest, const char* type, const char* origin);
void writeFusionRSSI(unsigned char rssi);
void writeFusionBER(float ber);
void clearFusion();
void writeP25(const char* source, bool group, unsigned int dest, const char* type);
void writeP25RSSI(unsigned char rssi);
void writeP25BER(float ber);
void clearP25();
void writeCW();
void clearCW();
virtual void close() = 0;
void clock(unsigned int ms);
protected:
virtual void setIdleInt() = 0;
virtual void setLockoutInt() = 0;
virtual void setErrorInt(const char* text) = 0;
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0;
virtual void writeDStarRSSIInt(unsigned char rssi);
virtual void writeDStarBERInt(float ber);
virtual void clearDStarInt() = 0;
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0;
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
virtual void writeDMRBERInt(unsigned int slotNo, float ber);
virtual void clearDMRInt(unsigned int slotNo) = 0;
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) = 0;
virtual void writeFusionRSSIInt(unsigned char rssi);
virtual void writeFusionBERInt(float ber);
virtual void clearFusionInt() = 0;
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type) = 0;
virtual void writeP25RSSIInt(unsigned char rssi);
virtual void writeP25BERInt(float ber);
virtual void clearP25Int() = 0;
virtual void writeCWInt() = 0;
virtual void clearCWInt() = 0;
virtual void clockInt(unsigned int ms);
private:
CTimer m_timer1;
CTimer m_timer2;
unsigned char m_mode1;
unsigned char m_mode2;
};
#endif
Loading…
Cancel
Save

Powered by TurnKey Linux.