// P25 TDMA Decoder (C) Copyright 2013, 2014, 2016 Max H. Parke KA1RBI // // This file is part of OP25 // // OP25 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 3, or (at your option) // any later version. // // OP25 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 OP25; see the file COPYING. If not, write to the Free // Software Foundation, Inc., 51 Franklin Street, Boston, MA // 02110-1301, USA. #include #include #include "p25p2_vf.h" #include "rs.h" static void load_i(const uint8_t src[], int& dest, int count) { dest = 0; for (int i=0; i> 1; } } static inline void store_reg(int reg, uint8_t val[], int len) { for (int i=0; i> (len-1-i)) & 1; } } static inline int load_reg(const uint8_t val[], int len) { int acc = 0; for (int i=0; i> 5) & 0x78) + ((u3 >> 9) & 0x7); b[1] = ((u0 >> 3) & 0x1e) + ((u3 >> 13) & 0x1); b[2] = ((u0 << 1) & 0x1e) + ((u3 >> 12) & 0x1); b[3] = ((u1 >> 3) & 0x1fe) + ((u3 >> 8) & 0x1); b[4] = ((u1 << 3) & 0x78) + ((u3 >> 5) & 0x7); b[5] = ((u2 >> 6) & 0x1e) + ((u3 >> 4) & 0x1); b[6] = ((u2 >> 3) & 0x0e) + ((u3 >> 3) & 0x1); b[7] = ( u2 & 0x0e) + ((u3 >> 2) & 0x1); b[8] = ((u2 << 2) & 0x04) + ( u3 & 0x3); } void p25p2_vf::encode_vcw(uint8_t vf[], const int* b) { uint32_t c0,c1,c2,c3; int u0,u1,u2,u3; u0 = \ ((b[0] & 0x78) << 5 ) | \ ((b[1] & 0x1e) << 3 ) | \ ((b[2] & 0x1e) >> 1 ); u1 = \ ((b[3] & 0x1fe) << 3 ) | \ ((b[4] & 0x78) >> 3 ); u2 = \ ((b[5] & 0x1e) << 6 ) | \ ((b[6] & 0xe) << 3 ) | \ ((b[7] & 0xe) ) | \ ((b[8] & 0x4) >> 2 ); u3 = \ ((b[1] & 0x1) << 13 ) | \ ((b[2] & 0x1) << 12 ) | \ ((b[0] & 0x7) << 9 ) | \ ((b[3] & 0x1) << 8 ) | \ ((b[4] & 0x7) << 5 ) | \ ((b[5] & 0x1) << 4 ) | \ ((b[6] & 0x1) << 3 ) | \ ((b[7] & 0x1) << 2 ) | \ ((b[8] & 0x3) ); int m1 = pr_n[u0]; c0 = golay_24_encode(u0); c1 = golay_23_encode(u1) ^ m1; c2 = u2; c3 = u3; interleave_vcw(vf, c0, c1, c2, c3); } void p25p2_vf::interleave_vcw(uint8_t _vf[], int _c0, int _c1, int _c2, int _c3){ uint8_t vf[72]; uint8_t c0[24]; uint8_t c1[23]; uint8_t c2[11]; uint8_t c3[14]; dump_i(c0, _c0, 24); dump_i(c1, _c1, 23); dump_i(c2, _c2, 11); dump_i(c3, _c3, 14); vf[0] = c0[23]; vf[1] = c0[5]; vf[2] = c1[10]; vf[3] = c2[3]; vf[4] = c0[22]; vf[5] = c0[4]; vf[6] = c1[9]; vf[7] = c2[2]; vf[8] = c0[21]; vf[9] = c0[3]; vf[10] = c1[8]; vf[11] = c2[1]; vf[12] = c0[20]; vf[13] = c0[2]; vf[14] = c1[7]; vf[15] = c2[0]; vf[16] = c0[19]; vf[17] = c0[1]; vf[18] = c1[6]; vf[19] = c3[13]; vf[20] = c0[18]; vf[21] = c0[0]; vf[22] = c1[5]; vf[23] = c3[12]; vf[24] = c0[17]; vf[25] = c1[22]; vf[26] = c1[4]; vf[27] = c3[11]; vf[28] = c0[16]; vf[29] = c1[21]; vf[30] = c1[3]; vf[31] = c3[10]; vf[32] = c0[15]; vf[33] = c1[20]; vf[34] = c1[2]; vf[35] = c3[9]; vf[36] = c0[14]; vf[37] = c1[19]; vf[38] = c1[1]; vf[39] = c3[8]; vf[40] = c0[13]; vf[41] = c1[18]; vf[42] = c1[0]; vf[43] = c3[7]; vf[44] = c0[12]; vf[45] = c1[17]; vf[46] = c2[10]; vf[47] = c3[6]; vf[48] = c0[11]; vf[49] = c1[16]; vf[50] = c2[9]; vf[51] = c3[5]; vf[52] = c0[10]; vf[53] = c1[15]; vf[54] = c2[8]; vf[55] = c3[4]; vf[56] = c0[9]; vf[57] = c1[14]; vf[58] = c2[7]; vf[59] = c3[3]; vf[60] = c0[8]; vf[61] = c1[13]; vf[62] = c2[6]; vf[63] = c3[2]; vf[64] = c0[7]; vf[65] = c1[12]; vf[66] = c2[5]; vf[67] = c3[1]; vf[68] = c0[6]; vf[69] = c1[11]; vf[70] = c2[4]; vf[71] = c3[0]; for (int i=0; i> 1) & 1; vf[i*2+1] = _vf[i] & 1; } c0[23] = vf[0]; c0[5] = vf[1]; c1[10] = vf[2]; c2[3] = vf[3]; c0[22] = vf[4]; c0[4] = vf[5]; c1[9] = vf[6]; c2[2] = vf[7]; c0[21] = vf[8]; c0[3] = vf[9]; c1[8] = vf[10]; c2[1] = vf[11]; c0[20] = vf[12]; c0[2] = vf[13]; c1[7] = vf[14]; c2[0] = vf[15]; c0[19] = vf[16]; c0[1] = vf[17]; c1[6] = vf[18]; c3[13] = vf[19]; c0[18] = vf[20]; c0[0] = vf[21]; c1[5] = vf[22]; c3[12] = vf[23]; c0[17] = vf[24]; c1[22] = vf[25]; c1[4] = vf[26]; c3[11] = vf[27]; c0[16] = vf[28]; c1[21] = vf[29]; c1[3] = vf[30]; c3[10] = vf[31]; c0[15] = vf[32]; c1[20] = vf[33]; c1[2] = vf[34]; c3[9] = vf[35]; c0[14] = vf[36]; c1[19] = vf[37]; c1[1] = vf[38]; c3[8] = vf[39]; c0[13] = vf[40]; c1[18] = vf[41]; c1[0] = vf[42]; c3[7] = vf[43]; c0[12] = vf[44]; c1[17] = vf[45]; c2[10] = vf[46]; c3[6] = vf[47]; c0[11] = vf[48]; c1[16] = vf[49]; c2[9] = vf[50]; c3[5] = vf[51]; c0[10] = vf[52]; c1[15] = vf[53]; c2[8] = vf[54]; c3[4] = vf[55]; c0[9] = vf[56]; c1[14] = vf[57]; c2[7] = vf[58]; c3[3] = vf[59]; c0[8] = vf[60]; c1[13] = vf[61]; c2[6] = vf[62]; c3[2] = vf[63]; c0[7] = vf[64]; c1[12] = vf[65]; c2[5] = vf[66]; c3[1] = vf[67]; c0[6] = vf[68]; c1[11] = vf[69]; c2[4] = vf[70]; c3[0] = vf[71]; load_i(c0, _c0, 24); load_i(c1, _c1, 23); load_i(c2, _c2, 11); load_i(c3, _c3, 14); } void p25p2_vf::encode_dstar(uint8_t result[72], const int b[9]) { uint8_t pbuf[49]; pbuf[0] = (b[0] >> 6) & 1; pbuf[1] = (b[0] >> 5) & 1; pbuf[2] = (b[0] >> 4) & 1; pbuf[3] = (b[0] >> 3) & 1; pbuf[4] = (b[0] >> 2) & 1; pbuf[5] = (b[0] >> 1) & 1; pbuf[6] = (b[2] >> 5) & 1; pbuf[7] = (b[2] >> 4) & 1; pbuf[8] = (b[2] >> 3) & 1; pbuf[9] = (b[2] >> 2) & 1; pbuf[10] = (b[3] >> 8) & 1; pbuf[11] = (b[3] >> 7) & 1; pbuf[12] = (b[3] >> 6) & 1; pbuf[13] = (b[3] >> 5) & 1; pbuf[14] = (b[3] >> 4) & 1; pbuf[15] = (b[3] >> 3) & 1; pbuf[16] = (b[3] >> 2) & 1; pbuf[17] = (b[4] >> 6) & 1; pbuf[18] = (b[4] >> 5) & 1; pbuf[19] = (b[4] >> 4) & 1; pbuf[20] = (b[4] >> 3) & 1; pbuf[21] = (b[4] >> 2) & 1; pbuf[22] = (b[5] >> 3) & 1; pbuf[23] = (b[5] >> 2) & 1; pbuf[25] = (b[5] >> 1) & 1; pbuf[26] = b[5] & 1; pbuf[27] = (b[6] >> 3) & 1; pbuf[28] = (b[6] >> 2) & 1; pbuf[29] = (b[6] >> 1) & 1; pbuf[30] = b[6] & 1; pbuf[31] = (b[7] >> 3) & 1; pbuf[32] = (b[7] >> 2) & 1; pbuf[33] = (b[7] >> 1) & 1; pbuf[34] = b[7] & 1; pbuf[35] = (b[8] >> 3) & 1; pbuf[36] = (b[8] >> 2) & 1; pbuf[37] = (b[8] >> 1) & 1; pbuf[38] = (b[1] >> 3) & 1; pbuf[39] = (b[1] >> 2) & 1; pbuf[40] = (b[1] >> 1) & 1; pbuf[41] = b[1] & 1; pbuf[42] = (b[2] >> 1) & 1; pbuf[43] = b[2] & 1; pbuf[44] = (b[3] >> 1) & 1; pbuf[45] = b[3] & 1; pbuf[46] = (b[4] >> 1) & 1; pbuf[47] = b[4] & 1; pbuf[48] = b[0] & 1; int u0 = load_reg(pbuf+0, 12); int u1 = load_reg(pbuf+12, 12); int u2 = load_reg(pbuf+24, 11); int u3 = load_reg(pbuf+35, 14); int m1 = pr_n[u0]; int c0 = golay_24_encode(u0); int c1 = golay_23_encode(u1) ^ m1; int c2 = u2; int c3 = u3; uint8_t ambe_fr[4][24]; store_reg(c0, ambe_fr[0], 24); store_reg(c1, ambe_fr[1], 23); store_reg(c2, ambe_fr[2], 11); store_reg(c3, ambe_fr[3], 14); result[0] = ambe_fr[0][10]; result[1] = ambe_fr[0][22]; result[2] = ambe_fr[3][11]; result[3] = ambe_fr[2][9]; result[4] = ambe_fr[1][10]; result[5] = ambe_fr[1][22]; result[6] = ambe_fr[0][11]; result[7] = ambe_fr[0][23]; result[8] = ambe_fr[1][8]; result[9] = ambe_fr[1][20]; result[10] = ambe_fr[0][9]; result[11] = ambe_fr[0][21]; result[12] = ambe_fr[3][10]; result[13] = ambe_fr[2][8]; result[14] = ambe_fr[1][9]; result[15] = ambe_fr[1][21]; result[16] = ambe_fr[3][8]; result[17] = ambe_fr[2][6]; result[18] = ambe_fr[1][7]; result[19] = ambe_fr[1][19]; result[20] = ambe_fr[0][8]; result[21] = ambe_fr[0][20]; result[22] = ambe_fr[3][9]; result[23] = ambe_fr[2][7]; result[24] = ambe_fr[0][6]; result[25] = ambe_fr[0][18]; result[26] = ambe_fr[3][7]; result[27] = ambe_fr[2][5]; result[28] = ambe_fr[1][6]; result[29] = ambe_fr[1][18]; result[30] = ambe_fr[0][7]; result[31] = ambe_fr[0][19]; result[32] = ambe_fr[1][4]; result[33] = ambe_fr[1][16]; result[34] = ambe_fr[0][5]; result[35] = ambe_fr[0][17]; result[36] = ambe_fr[3][6]; result[37] = ambe_fr[2][4]; result[38] = ambe_fr[1][5]; result[39] = ambe_fr[1][17]; result[40] = ambe_fr[3][4]; result[41] = ambe_fr[2][2]; result[42] = ambe_fr[1][3]; result[43] = ambe_fr[1][15]; result[44] = ambe_fr[0][4]; result[45] = ambe_fr[0][16]; result[46] = ambe_fr[3][5]; result[47] = ambe_fr[2][3]; result[48] = ambe_fr[0][2]; result[49] = ambe_fr[0][14]; result[50] = ambe_fr[3][3]; result[51] = ambe_fr[2][1]; result[52] = ambe_fr[1][2]; result[53] = ambe_fr[1][14]; result[54] = ambe_fr[0][3]; result[55] = ambe_fr[0][15]; result[56] = ambe_fr[1][0]; result[57] = ambe_fr[1][12]; result[58] = ambe_fr[0][1]; result[59] = ambe_fr[0][13]; result[60] = ambe_fr[3][2]; result[61] = ambe_fr[2][0]; result[62] = ambe_fr[1][1]; result[63] = ambe_fr[1][13]; result[64] = ambe_fr[3][0]; result[65] = ambe_fr[3][12]; result[66] = ambe_fr[2][10]; result[67] = ambe_fr[1][11]; result[68] = ambe_fr[0][0]; result[69] = ambe_fr[0][12]; result[70] = ambe_fr[3][1]; result[71] = ambe_fr[3][13]; }