mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-14 09:47:30 -05:00
commit 833e0173f24b12a12ff80f9a35fb43107d355cc3 Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 22:51:02 2024 -0400 Fix Slot Preference Depending on Build; commit 716577ab09c0cee68bca3bcdcbaaa7cfa3be4f97 Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 22:27:24 2024 -0400 M17 - Voice Playback Only If Enabled; Misc; commit c0f9818cf38ce7f127370f19ec4afa2457cef19a Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 17:39:34 2024 -0400 Add DMR/P25p2 Stereo Channel Patch; commit 1a0baf0a17ccf8cc0eb0a01a809269354480d1d1 Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 17:37:46 2024 -0400 Add DMR Cap+ Faster Rest Patch; commit 9f5b52aa8f20bfe3eab5413f2c3fa41003d53b3c Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 17:36:24 2024 -0400 Disable EDACS Analog Debug; commit 7dd0de67b602f0acd111200f838fbb1a0541a8bf Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 17:36:04 2024 -0400 Squashed commit of the following: commit 95d46fb35d6cb6fb0a9825084f4c2accf8edad4a Author: lwvmobile <lwvmobile@gmail.com> Date: Mon Mar 25 17:48:57 2024 -0400 Enable HPF_D by default; Increase manual analog gain to 50; commit 1f37837664e16760b5cbf5653fc4d829ee6cce83 Author: lwvmobile <lwvmobile@gmail.com> Date: Mon Mar 25 08:43:17 2024 -0400 Enable HPF_D on M17 Voice; commit9bbe4de7fdAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 16:08:16 2024 -0400 EDACS: Digitize Analog For Analysis of 'Data Burst' Like Behavior; commit9249b7a943Author: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 12:28:26 2024 -0400 Simply Mono Short Playback; commit89ad0f17e3Author: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 23 21:12:44 2024 -0400 Add HPF to SS4, SS3, and SS Audio Methods; commite8184c7fbdAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 23 17:13:44 2024 -0400 RTL - Add The Sample / Volume Multiplier as a user configurable option; commitee04d11116Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 23:15:04 2024 -0400 Fix HPF_D so it actually works correctly; commite549b21497Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 20:11:34 2024 -0400 Make Analog Auto Gain Control Mostly Tolerable; commit2f9e0525feAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 18:20:38 2024 -0400 User Toggle HPF on Digital; commitff58d3a6faAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 18:10:15 2024 -0400 User Toggles and Displays for Filters; commitb6fc17c506Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 15:55:09 2024 -0400 More Analog Manual Audio Gain Tweaks; commit076b9fbf04Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 06:26:10 2024 -0400 Add SQL Hit on EDACS if Colors Disabled; commit59fe47ef05Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:23:08 2024 -0400 Disable HPF Test on Digital Voice; commit4a63068ce1Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 23:39:43 2024 -0400 Misc Code Organizing; audio_gainA Tweaks; commit3585e7e594Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 13:18:31 2024 -0400 Test Tweak to RTL Sample Multiplier; commitfa5b25283fAuthor: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 13:18:07 2024 -0400 Adjust Manual Mic Gain on M17 Encoder; Ncurses Display; commitc985fea035Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 12:34:01 2024 -0400 Misc Notes on using raw_rms values during testing; commitb273e5b7beAuthor: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 12:31:33 2024 -0400 Bugfix for EDACS Analog Segfault when using the digitize function for an extended period; commiteadf3fdf23Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 10:12:04 2024 -0400 Analog Gain Has Own Variable; Ncurses Keys; Misc; commit0debcc647eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 08:49:51 2024 -0400 Filtering Misc Cleanup; commit98e10b2627Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 00:02:21 2024 -0400 Automatic Gain On Analog WIP; Manual Gain Control; commit89736ae543Author: lwvmobile <lwvmobile@gmail.com> Date: Wed Mar 20 10:22:20 2024 -0400 Passband Filter Testing on Raw Analog / EDACS / M17 Encoder; commit43f6218129Author: lwvmobile <lwvmobile@gmail.com> Date: Wed Mar 20 09:03:02 2024 -0400 Passband and Notch Filter Setup; Debug Output; commit35a1b53867Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 22:35:36 2024 -0400 HPF: Only Use On RTL Input when M17 Encoder Uses It; commitb9949f0d80Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 17:31:59 2024 -0400 Disable LFP on EDACS Analog Out; commit3666740674Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 13:42:07 2024 -0400 Test HPF On Digital Voice Out; commitef13343925Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 12:46:27 2024 -0400 RTL_FM Input for Analog/M17 Encoder; commit2b7de90474Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 11:03:55 2024 -0400 New Analog Audio Filters WIP; commit 3b9f9f5a3befb295da284379262323fad7d69c7a Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 26 17:33:34 2024 -0400 Squashed commit of the following: commit a5c5be3b955a82cc72f1486ff87d7c1b4893295f Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Tue Mar 26 17:28:35 2024 -0400 EDACS: Standard display rewrite, parsing/RE fixes, tune i-calls and all-calls (#246) * EDACS EA: Fix reversed TDMA/data calls * EDACS: deduplicate ncurses printing logic * EDACS: pass call state via new state struct field * EDACS: RE some differences from Standard spec * EDACS: show state for data calls * EDACS: tune individual calls on Standard * EDACS: tune all-calls on Standard * EDACS: properly identify emergency on channel updates * EDACS: fix build break * EDACS: fix conditions for refreshing the display source * EDACS EA: Identify calls as voice for display * EDACS: voice channel update emergency refactor * EDACS: Show interconnect calls in call log * EDACS EA: show unknown data channel assignments in log * EDACS: check LCN is not 0 before assigning it * EDACS: C operator precedence is dumb * Initialize edacs_vc_call_type * use j and not i in call_matrix for call history; --------- Co-authored-by: lwvmobile <lwvmobile@gmail.com> commitc8d00846b1Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sun Mar 24 17:48:46 2024 -0400 EDACS: Display cached call source on Standard, tune group calls on assignment (#241) * Trim trailing whitespace * EDACS: Display cached call source on Standard The logic in `edacs-fme.c` didn't work, in retrospect, because it would have depended on getting back-to-back messages for the same call. In practice, that is unlikely even on an idle system as system state gets displayed. Instead, cache on the display end, for a "better" user experience. * EDACS: Pad channel freq to "000.000000 MHz" * EDACS: Process/tune group calls on assignment commit8d432e8b3eAuthor: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sun Mar 24 12:29:22 2024 -0400 EDACS: ESK fixes, RE of standard channel assignments, cleanups (#238) * EDACS: Make i-calls very obvious on standard * EDACS: abstract target for Interconnect Channel Assignment * EDACS: little shortcut example updates * EDACS: Apply ESK to both FR1 and FR4 * EDACS: Group channel assignment by mode * EDACS: Merge MT-A 0/1 and 2/3 cases commit0440dea1deAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 02:47:09 2024 -0400 EDACS: Fix Call History For Standard Maybe; commit208f188e55Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 23 21:35:42 2024 -0400 EDACS: Speculative RE of MT-A value 0, pretty colours (#231) * EDACS: fix log formatting * EDACS: Speculative RE of MT-A value 0 * EDACS: CC message pretty colours * EDACS: little formatting * EDACS: eh make interconnect magenta commit36f76a7e21Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 23 17:35:45 2024 -0400 EDACS: Fix copy/paste error (#230) I went through by hand and I'm confident this is the last of the `get_lcn_status_string()` errors. commit4bc73d8c68Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 23 17:24:32 2024 -0400 EDACS: Rewrite Standard/Networked parsing per TIA/EIA TSB 69.3 (#229) * EDACS EA: refactor log messages for consistency * EDACS: Log LCN status values * EDACS EA: channel assignment vs update * EDACS: Implement TIA/EIA TSB 69.3 * EDACS: clean up Site ID message * EDACS: Actually process call for Channel Update * EDACS: Update display for Standard calls * EDACS: Format of Voice Group Channel Assignment * EDACS Standard: Log LCN status values * EDACS: Rebase and fix some issues * EDACS: Fix copy/paste error commit03507055a4Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 23 16:05:09 2024 -0400 EDACS: add EA messages / start mass Standard refactor (#226) * EDACS EA: refactor log messages for consistency * EDACS EA: channel assignment command (unknown data) * EDACS EA: status/message command * EDACS Standard: Refactor variable declarations * EDACS Standard: log raw payloads for debugging * EDACS: Fix typing * EDACS EA: update status/message CC command * EDACS: Log LCN status values * EDACS: String format * EDACS EA: channel assignment vs update * EDACS: fix syntax error * EDACS: change string for reserved LCN status commitfbe5fd2093Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Fri Mar 22 15:26:50 2024 -0400 EDACS EA: emergency calls, MT1 fixes, logging improvements (#221) * EDACS EA: Fix i-call MT1 after ESK changes * EDACS EA: Fix all-call ncurses display * EDACS EA: Make detailed log slightly more readable * EDACS EA: Improve colours in logs * EDACS EA: Space in logs for consistency * EDACS EA: Fix MT1 for analog group voice after ESK change * EDACS EA: add parsing for emergency calls commit413e5f76a2Merge:de9127c388a57dAuthor: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Fri Mar 22 06:59:31 2024 -0400 Merge pull request #220 from lwvmobile/edacs_manual_modes Edacs manual modes commit388a57d8fcAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 05:28:11 2024 -0400 EDACS: Re-enable the -9 switch to maintain user compatability; Fix Missing Bracket on non color mode; commit058099f1aaAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 03:24:57 2024 -0400 EDACS: Tweak Mode Toggle Display; Add Frame Dump on No Mode Set; commit68aa6b018eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:19:38 2024 -0400 EDACS: Update Docs to Reflect Changes; commitc404f3c48cAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:01:09 2024 -0400 EDACS: Ncurses Display Working Mode Tweaks; commitb2d1608eb7Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 01:08:28 2024 -0400 EDACS: Toggle Keys A and S for Mode Selection; commita4553a0a0aAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 00:45:37 2024 -0400 EDACS: Remove Auto Detect Code; Make CLI Switches; commitde9127cfb4Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Thu Mar 21 21:02:53 2024 -0400 EDACS: support for EA system all-calls (#214) * Refactor debug printing a bit * Clean up group call logic * Minor changes to debug printing * EDACS EA: support for system all-calls * EDACS: split out MT1 for TDMA call since we can't decode it anyway * Refactor identifying call mode (digital/analog) * Maintain consistent indentation for all MT1 * EDACS: Fix Compiler Error. Had an extra right bracket on line 383 --------- Co-authored-by: lwvmobile <59371473+lwvmobile@users.noreply.github.com> commitc85dd60399Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 17:38:30 2024 -0400 EDACS: NET/STD LCN > 0 Check; commitbed766a86eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 09:34:10 2024 -0400 EDACS: STD/NET Don't Tune Unless CC LCN Set; commit69f532a022Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Mon Mar 18 11:41:58 2024 -0400 EDACS: EA I-Call decoding improvements (#205) * EDACS: formatting nit * EDACS: add name to credits * EDACS: Handle initial grant vs grant update for i-call * EDACS: consistency for group vs i-call * EDACS: file naming for i-call recordings * EDACS: EA refactor when MT1 is 0x1F * EDACS: check we know CC LCN before leaving it * EDACS: fix breaking change for Standard Revert mistake inf68367c4f3* Fix patent number * EDACS: Fix Compiler Error 1; Fix Rogue Copy Paste * EDACS: Add MT1, MT2, and FR1 and FR4 Dumps on Payload; --------- Co-authored-by: lwvmobile <59371473+lwvmobile@users.noreply.github.com> commita7de24c47bAuthor: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Mon Mar 18 07:47:34 2024 -0400 EDACS: fixes and improvements to EA analog and i-call parsing (#204) * Fix MT1 math given esk_mask value is 0xA0 * EDACS: Clean up formatting for I-Calls * EDACS: typo, fix the TGID for group calls Fix copy-pasta * EDACS: Fix MT2 for I-Calls Incorrectly copied decimal values as hex - obviously MT2 is only 4 bits so it cannot be greater than 15. * EDACS: check LCN is > 0 before trying to tune An EA CC sometimes includes commands that parse as LCN 0 - but otherwise valid - analog call voice grants for TG 1. Since LCN 0 is not valid, ensure that we don't try to tune to them while we try to figure out what they're about. * EDACS: Process "login" message on CC Log "login" messages sent on the CC. Verified behaviour against UniTrunker. commit10eacd99ccAuthor: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sun Mar 17 18:56:41 2024 -0400 EDACS: Clean up formatting for I-Calls (#203) * Fix MT1 math given esk_mask value is 0xA0 * EDACS: Clean up formatting for I-Calls commitebe6e8fc65Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sun Mar 17 18:02:12 2024 -0400 Fix MT1 math given esk_mask value is 0xA0 (#202) commit8619612b76Author: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 16 22:42:44 2024 -0400 EDACS: Setup Analog Calls and WAVs on EA and ICALL; commit9ac1573f0bAuthor: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 16 17:17:14 2024 -0400 EDACS: Add MT1 value / logging for analog group calls (#198) * Add MT1 value / logging for analog group calls * Respect user preference for tuning to group calls * Revert "Respect user preference for tuning to group calls" This reverts commit83ac8feab7. commit0aa01a45efAuthor: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 16 17:16:52 2024 -0400 EDACS: Respect user preference for tuning to group calls (#201) commitf68367c4f3Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com> Date: Sat Mar 16 17:16:20 2024 -0400 EDACS: Add parsing for individual calls (#200) * EDACS: Add parsing for individual calls This change adds parsing for I-Calls on EA systems. Both analog and ProVoice modes are parsed and processed. See related issue for discussion. * Respect user preference for tuning to private calls * EDACS: Respect user preference for tuning to private calls * EDACS: Handle i-call target in ProVoice logging * EDACS: Show i-calls distinctly from group calls
704 lines
21 KiB
C
704 lines
21 KiB
C
/*
|
|
* Copyright (C) 2010 DSD Author
|
|
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "dsd.h"
|
|
#include "dpmr_const.h"
|
|
|
|
void processdPMRvoice (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
uint32_t i, j, k, dibit;
|
|
uint8_t CCH[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
|
uint8_t CCHDescrambled[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
|
uint8_t CCHDeInterleaved[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][72] = {0};
|
|
uint8_t CCHDataHammingCorrected[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][48];
|
|
uint8_t CCHDataCRC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
|
|
memset (CCHDataHammingCorrected, 1, sizeof(CCHDataHammingCorrected));
|
|
memset (CCHDataCRC, 1, sizeof(CCHDataCRC));
|
|
|
|
uint8_t CCHDataCRCComputed[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
memset (CCHDataCRCComputed, 0, sizeof(CCHDataCRCComputed));
|
|
|
|
uint8_t CC[NB_OF_DPMR_VOICE_FRAME_TO_DECODE / 2][24] = {0};
|
|
char ambe_fr[NB_OF_DPMR_VOICE_FRAME_TO_DECODE * 4][4][24];
|
|
memset (ambe_fr, 0, sizeof (ambe_fr));
|
|
const int *w, *x, *y, *z;
|
|
uint32_t ScramblerLFSR = 0;
|
|
bool correctable = true;
|
|
bool HammingCorrectable[NB_OF_DPMR_VOICE_FRAME_TO_DECODE][6] = {0};
|
|
uint32_t CrcOk[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
|
uint32_t HammingOk[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
|
uint32_t Temp = 0;
|
|
/* CCH (Control CHannel) data */
|
|
uint32_t CCH_FrameNumber[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
|
uint32_t CCH_CalledID = 0;
|
|
uint32_t CCH_CallingID = 0;
|
|
uint32_t CCH_CommunicationMode[NB_OF_DPMR_VOICE_FRAME_TO_DECODE] = {0};
|
|
uint32_t CCH_Version[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
uint32_t CCH_CommsFormat[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
uint32_t CCH_EmergencyPriority[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
uint32_t CCH_Reserved[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
uint32_t CCH_SlowData[NB_OF_DPMR_VOICE_FRAME_TO_DECODE];
|
|
uint32_t PartOfSuperFrame = 0;
|
|
uint8_t CalledID[8] = {0};
|
|
uint8_t CallingID[8] = {0};
|
|
UNUSED(PartOfSuperFrame);
|
|
|
|
/* First CCH (Control CHannel) - 72 bit */
|
|
k = 0;
|
|
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
if (opts->inverted_dpmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
|
|
CCH[0][(i * 2)] = (1 & (dibit >> 1)); // bit 1
|
|
CCH[0][(i * 2) + 1] = (1 & dibit); // bit 0
|
|
|
|
}
|
|
|
|
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
|
k = 0;
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
w = dPmrW;
|
|
x = dPmrX;
|
|
y = dPmrY;
|
|
z = dPmrZ;
|
|
k = 0;
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
if (opts->inverted_dpmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
|
|
ambe_fr[j][*w][*x] = (1 & (dibit >> 1)); // bit 1
|
|
ambe_fr[j][*y][*z] = (1 & dibit); // bit 0
|
|
state->dPMRVoiceFS2Frame.RawVoiceBit[j][k] = (1 & (dibit >> 1)); // bit 1
|
|
state->dPMRVoiceFS2Frame.RawVoiceBit[j][k + 1] = (1 & dibit); // bit 0
|
|
k = k + 2;
|
|
w++;
|
|
x++;
|
|
y++;
|
|
z++;
|
|
}
|
|
}
|
|
|
|
/* First CC (Channel Code) - 24 bit */
|
|
k = 0;
|
|
for (i = 0; i < 12; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
if (opts->inverted_dpmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
|
|
CC[0][k++] = (1 & (dibit >> 1)); // bit 1
|
|
CC[0][k++] = (1 & dibit); // bit 0
|
|
|
|
|
|
}
|
|
|
|
/* Get the color code */
|
|
state->dPMRVoiceFS2Frame.ColorCode[0] = (unsigned int)GetdPmrColorCode(CC[0]);
|
|
|
|
/* Second CCH (Control CHannel) - 72 bit */
|
|
k = 0;
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
if (opts->inverted_dpmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
|
|
CCH[1][k++] = (1 & (dibit >> 1)); // bit 1
|
|
CCH[1][k++] = (1 & dibit); // bit 0
|
|
|
|
|
|
}
|
|
|
|
/* 4 TCH (Traffic CHannel) = 4 x 72 bit voice playload */
|
|
|
|
k = 0;
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
w = dPmrW;
|
|
x = dPmrX;
|
|
y = dPmrY;
|
|
z = dPmrZ;
|
|
k = 0;
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
if (opts->inverted_dpmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
|
|
ambe_fr[j + 4][*w][*x] = (1 & (dibit >> 1)); // bit 1
|
|
ambe_fr[j + 4][*y][*z] = (1 & dibit); // bit 0
|
|
state->dPMRVoiceFS2Frame.RawVoiceBit[j + 4][k] = (1 & (dibit >> 1)); // bit 1
|
|
state->dPMRVoiceFS2Frame.RawVoiceBit[j + 4][k + 1] = (1 & dibit); // bit 0
|
|
k = k + 2;
|
|
w++;
|
|
x++;
|
|
y++;
|
|
z++;
|
|
|
|
}
|
|
}
|
|
|
|
/* Decoding all CCH (Control CHannel) */
|
|
for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++)
|
|
{
|
|
/* Init LFSR value - All bit to '1' */
|
|
ScramblerLFSR = 0x1FF;
|
|
|
|
/* Descramble data - Input 72 bit => Output 72 bit */
|
|
ScrambledPMRBit(&ScramblerLFSR, CCH[i], CCHDescrambled[i], 72);
|
|
|
|
/* Deinterleave data - Input 72 bit => Output 72 bit */
|
|
DeInterleave6x12DPmrBit(CCHDescrambled[i], CCHDeInterleaved[i]);
|
|
|
|
correctable = true;
|
|
for(j = 0; j < 6; j++)
|
|
{
|
|
/* Apply the Hamming(12,8) correction - Input 72 bit => Output 48 bit */
|
|
HammingCorrectable[i][j] = Hamming_12_8_decode(&CCHDeInterleaved[i][j*12], &CCHDataHammingCorrected[i][j*8], 1);
|
|
if(HammingCorrectable[i][j] == false) correctable = false;
|
|
}
|
|
|
|
if(correctable) HammingOk[i] = 1;
|
|
else HammingOk[i] = 0;
|
|
|
|
/* Reconstitute the 7 bit CRC */
|
|
CCHDataCRC[i] = 0;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][41]) << 6;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][42]) << 5;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][43]) << 4;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][44]) << 3;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][45]) << 2;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][46]) << 1;
|
|
CCHDataCRC[i] |= (CCHDataHammingCorrected[i][47]) << 0;
|
|
|
|
/* Compute the 7 bit CRC */
|
|
CCHDataCRCComputed[i] = CRC7BitdPMR(CCHDataHammingCorrected[i], 41);
|
|
|
|
if(CCHDataCRC[i] == CCHDataCRCComputed[i]) CrcOk[i] = 1;
|
|
else CrcOk[i] = 0;
|
|
|
|
/* Fill the frame number */
|
|
CCH_FrameNumber[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][0], 2);
|
|
|
|
/* Fill the communication mode */
|
|
CCH_CommunicationMode[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][14], 3);
|
|
|
|
/* Fill the version */
|
|
CCH_Version[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][17], 2);
|
|
|
|
/* Fill the comm format */
|
|
CCH_CommsFormat[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][19], 2);
|
|
|
|
/* Fill the emergency priority bit */
|
|
CCH_EmergencyPriority[i] = (uint32_t)CCHDataHammingCorrected[i][21];
|
|
|
|
/* Fill the reserved bit */
|
|
CCH_Reserved[i] = (uint32_t)CCHDataHammingCorrected[i][22];
|
|
|
|
/* Fill the slow data */
|
|
CCH_SlowData[i] = ConvertBitIntoBytes(&CCHDataHammingCorrected[i][23], 18);
|
|
|
|
/* Copy the CCH data into the structure */
|
|
memcpy(state->dPMRVoiceFS2Frame.CCHData[i], CCHDataHammingCorrected[i], 48);
|
|
state->dPMRVoiceFS2Frame.CCHDataHammingOk[i] = HammingOk[i];
|
|
state->dPMRVoiceFS2Frame.CCHDataCRC[i] = CCHDataCRC[i];
|
|
state->dPMRVoiceFS2Frame.CCHDataCrcOk[i] = CrcOk[i];
|
|
state->dPMRVoiceFS2Frame.FrameNumbering[i] = CCH_FrameNumber[i];
|
|
state->dPMRVoiceFS2Frame.CommunicationMode[i] = CCH_CommunicationMode[i];
|
|
state->dPMRVoiceFS2Frame.Version[i] = CCH_Version[i];
|
|
state->dPMRVoiceFS2Frame.CommsFormat[i] = CCH_CommsFormat[i];
|
|
state->dPMRVoiceFS2Frame.EmergencyPriority[i] = CCH_EmergencyPriority[i];
|
|
state->dPMRVoiceFS2Frame.Reserved[i] = CCH_Reserved[i];
|
|
state->dPMRVoiceFS2Frame.SlowData[i] = CCH_SlowData[i];
|
|
} /* End for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++) */
|
|
|
|
/* Get the last TG */
|
|
strcpy((char *)CalledID, (char *)state->dPMRVoiceFS2Frame.CalledID);
|
|
CalledID[7] = '\0';
|
|
|
|
/* Get the last source ID */
|
|
strcpy((char *)CallingID, (char *)state->dPMRVoiceFS2Frame.CallingID);
|
|
CallingID[7] = '\0';
|
|
|
|
|
|
/* To determine the part of the payload frame, we need to check the
|
|
* Hamming code result, the CRC and the frame number */
|
|
|
|
// if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 0)) ||
|
|
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 1)))
|
|
|
|
if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 0)) ||
|
|
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 1)))
|
|
{
|
|
/* First part of the super frame */
|
|
PartOfSuperFrame = 1;
|
|
|
|
/* The next part will normally be the second part */
|
|
opts->dPMR_next_part_of_superframe = 2;
|
|
|
|
/* Fill the called ID (talk group - TG) */
|
|
Temp = ConvertBitIntoBytes(&CCHDataHammingCorrected[0][2], 12);
|
|
CCH_CalledID = ((Temp << 12) & 0x00FFF000); /* 12 MSBit */
|
|
Temp = ConvertBitIntoBytes(&CCHDataHammingCorrected[1][2], 12);
|
|
CCH_CalledID |= (Temp & 0x00000FFF); /* 12 LSBit */
|
|
ConvertAirInterfaceID(CCH_CalledID, CalledID);
|
|
CalledID[7] = '\0';
|
|
|
|
/* Determine if the called TG ID only is correct */
|
|
//if(HammingOk[0] && CrcOk[0] && HammingOk[1] && CrcOk[1])
|
|
if((CrcOk[0] || (HammingCorrectable[0][0] && HammingCorrectable[0][1])) &&
|
|
(CrcOk[1] || (HammingCorrectable[1][0] && HammingCorrectable[1][1])))
|
|
{
|
|
/* Save CCH data parameters */
|
|
state->dPMRVoiceFS2Frame.CalledIDOk = 1;
|
|
}
|
|
else
|
|
{
|
|
state->dPMRVoiceFS2Frame.CalledIDOk = 0;
|
|
}
|
|
|
|
/* BUGFIX : Copy in all case the TG ID */
|
|
strcpy((char *)state->dPMRVoiceFS2Frame.CalledID, (char *)CalledID);
|
|
}
|
|
|
|
/* To determine the part of the payload frame, we need to check the
|
|
* Hamming code result, the CRC and the frame number */
|
|
|
|
// else if( (HammingOk[0] && CrcOk[0] && (CCH_FrameNumber[0] == 2)) ||
|
|
// (HammingOk[1] && CrcOk[1] && (CCH_FrameNumber[1] == 3)))
|
|
|
|
else if(((CrcOk[0] || HammingCorrectable[0][0]) && (CCH_FrameNumber[0] == 2)) ||
|
|
((CrcOk[1] || HammingCorrectable[1][0]) && (CCH_FrameNumber[1] == 3)))
|
|
{
|
|
/* Second part of the super frame */
|
|
PartOfSuperFrame = 2;
|
|
|
|
/* The next part will normally be the first part */
|
|
opts->dPMR_next_part_of_superframe = 1;
|
|
|
|
/* Fill the calling ID (source) */
|
|
Temp = ConvertBitIntoBytes(&CCHDataHammingCorrected[0][2], 12);
|
|
CCH_CallingID = ((Temp << 12) & 0x00FFF000); /* 12 MSBit */
|
|
Temp = ConvertBitIntoBytes(&CCHDataHammingCorrected[1][2], 12);
|
|
CCH_CallingID |= (Temp & 0x00000FFF); /* 12 LSBit */
|
|
ConvertAirInterfaceID(CCH_CallingID, CallingID);
|
|
CallingID[7] = '\0';
|
|
|
|
/* Determine if the calling SRC ID is correct */
|
|
|
|
//if(HammingOk[0] && CrcOk[0] && HammingOk[1] && CrcOk[1])
|
|
|
|
if((CrcOk[0] || (HammingCorrectable[0][0] && HammingCorrectable[0][1])) &&
|
|
(CrcOk[1] || (HammingCorrectable[1][0] && HammingCorrectable[1][1])))
|
|
{
|
|
/* Save CCH data parameters */
|
|
state->dPMRVoiceFS2Frame.CallingIDOk = 1;
|
|
}
|
|
else
|
|
{
|
|
state->dPMRVoiceFS2Frame.CallingIDOk = 0;
|
|
}
|
|
|
|
/* BUGFIX : Copy in all case the SRC ID */
|
|
strcpy((char *)state->dPMRVoiceFS2Frame.CallingID, (char *)CallingID);
|
|
}
|
|
else
|
|
{
|
|
/* The dPMR source and destination ID are now invalid */
|
|
state->dPMRVoiceFS2Frame.CalledIDOk = 0;
|
|
state->dPMRVoiceFS2Frame.CallingIDOk = 0;
|
|
|
|
/* Unknown part of superframe => We suppose
|
|
* it is the next part of the previous frame received */
|
|
PartOfSuperFrame = opts->dPMR_next_part_of_superframe;
|
|
|
|
/* Set the next part of the superframe to receive */
|
|
if(opts->dPMR_next_part_of_superframe == 1)
|
|
{
|
|
/* Set the next part as the second part */
|
|
opts->dPMR_next_part_of_superframe = 2;
|
|
}
|
|
else if(opts->dPMR_next_part_of_superframe == 2)
|
|
{
|
|
/* Set the next part as the first part */
|
|
opts->dPMR_next_part_of_superframe = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Unknown current part, set to 0 */
|
|
opts->dPMR_next_part_of_superframe = 0;
|
|
}
|
|
}
|
|
|
|
/* Display the destination ID (talk group - TG) */
|
|
fprintf (stderr, "\n");
|
|
|
|
if(state->dPMRVoiceFS2Frame.CalledIDOk)
|
|
{
|
|
fprintf (stderr, "%s", KGRN);
|
|
fprintf(stderr, " TG=%s", CalledID);
|
|
fprintf (stderr, "%s", KNRM);
|
|
|
|
//check other as well before assigning
|
|
if(state->dPMRVoiceFS2Frame.CallingIDOk) sprintf (state->dpmr_target_id, "%s", CalledID);
|
|
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "%s", KRED);
|
|
fprintf(stderr, " TG=(CRC ERR)");
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
/* Display the source ID */
|
|
if(state->dPMRVoiceFS2Frame.CallingIDOk)
|
|
{
|
|
fprintf (stderr, "%s", KGRN);
|
|
fprintf(stderr, " Src=%s", CallingID);
|
|
fprintf (stderr, "%s", KNRM);
|
|
|
|
//check other as well before assigning
|
|
if(state->dPMRVoiceFS2Frame.CalledIDOk) sprintf (state->dpmr_caller_id, "%s", CallingID);
|
|
|
|
//stashed channel code in here, more likely to be correct, but no guarantee
|
|
if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1))
|
|
{
|
|
fprintf (stderr, "%s", KGRN);
|
|
fprintf(stderr, " Channel Code=%02d", (int)state->dPMRVoiceFS2Frame.ColorCode[0]);
|
|
fprintf (stderr, "%s", KNRM);
|
|
|
|
//check other as well before assigning
|
|
if(state->dPMRVoiceFS2Frame.CalledIDOk) state->dpmr_color_code = (int)state->dPMRVoiceFS2Frame.ColorCode[0];
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "%s", KRED);
|
|
fprintf(stderr, " Src=(CRC ERR) Channel Code =(CRC ERR)");
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
if (state->dPMRVoiceFS2Frame.Version[0] == 3)
|
|
{
|
|
fprintf (stderr, "%s", KRED);
|
|
fprintf (stderr, " Scrambler");
|
|
fprintf (stderr, "%s", KNRM);
|
|
if (state->R != 0)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf (stderr, " Key %05lld ", state->R );
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
}
|
|
|
|
//Play only voice frames by first looking to see if there is a TCH voice in CommunicationMode,
|
|
short start = 0;
|
|
short end = 4;
|
|
|
|
//not really even sure why I made this loop
|
|
//I probably should actually read the manual again
|
|
for (short o = 0; o < 2; o++)
|
|
{
|
|
|
|
//reset scrambler key seed on frame 0
|
|
if (state->dPMRVoiceFS2Frame.FrameNumbering[o] == 0) state->payload_miN = 0;
|
|
|
|
//depending on first or second TCH, set start and end variables appropriately
|
|
if (o == 1)
|
|
{
|
|
start = 4;
|
|
end = 8;
|
|
|
|
}
|
|
|
|
//this is used so we can simply pass the voice here to the
|
|
//nxdn scrambler by telling mbe these are nxdn frames and to
|
|
//apply the same descramble method to them if necessary
|
|
int realsynctype = state->synctype;
|
|
|
|
// fprintf (stderr, "\nCommunication Mode: %d\n", state->dPMRVoiceFS2Frame.CommunicationMode[o]);
|
|
// fprintf (stderr, "Encryption Mode: %d\n", state->dPMRVoiceFS2Frame.Version[o]); //shows as 3 (manufacturer specific, 5.16) on the dPMR scrambler values received
|
|
// fprintf (stderr, "Superframe Number: %d", state->dPMRVoiceFS2Frame.FrameNumbering[o]);
|
|
|
|
if((state->dPMRVoiceFS2Frame.CommunicationMode[o] == 0) ||
|
|
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 1) ||
|
|
(state->dPMRVoiceFS2Frame.CommunicationMode[o] == 5))
|
|
{
|
|
|
|
//check to see if we are using scrambler
|
|
if (state->dPMRVoiceFS2Frame.Version[o] == 3) //!= 0
|
|
{
|
|
state->synctype = 28; //fake it as nxdn
|
|
state->nxdn_cipher_type = 0x01; //turn on nxdn scrambler cipher
|
|
state->dmr_encL = 1; //flag on enc bit here so we can mute if no key provided
|
|
}
|
|
|
|
//flag back off if key is provided
|
|
if (state->R != 0) state->dmr_encL = 0;
|
|
|
|
//There are 4 AMBE voice frames per TCH
|
|
for(i = start; i < end; i++)
|
|
{
|
|
processMbeFrame (opts, state, NULL, ambe_fr[i], NULL);
|
|
if (opts->floating_point == 0)
|
|
playSynthesizedVoiceMS(opts, state);
|
|
if (opts->floating_point == 1)
|
|
playSynthesizedVoiceFM(opts, state);
|
|
}
|
|
|
|
//set the correct sync type again and flag off the cipher
|
|
state->synctype = realsynctype;
|
|
state->nxdn_cipher_type = 0;
|
|
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
//keep code below, could be handy cheat sheet for other info
|
|
#ifdef dPMR_PRINT_DEBUG_INFO
|
|
//Display the CCH content
|
|
for(i = 0; i < NB_OF_DPMR_VOICE_FRAME_TO_DECODE; i++)
|
|
{
|
|
fprintf(stderr, "i = %u - ", i);
|
|
fprintf(stderr, "Comm Mode = %01u - ", state->dPMRVoiceFS2Frame.CommunicationMode[i]);
|
|
fprintf(stderr, "Version = %01u - ", state->dPMRVoiceFS2Frame.Version[i]);
|
|
fprintf(stderr, "Comms Format = %01u - ", state->dPMRVoiceFS2Frame.CommsFormat[i]);
|
|
fprintf(stderr, "Emergency = %01u - ", state->dPMRVoiceFS2Frame.EmergencyPriority[i]);
|
|
fprintf(stderr, "Reserved = %01u - ", state->dPMRVoiceFS2Frame.Reserved[i]);
|
|
fprintf(stderr, "Slow Data = 0x%05X - ", state->dPMRVoiceFS2Frame.SlowData[i]);
|
|
if(HammingOk[i] && CrcOk[i]) fprintf(stderr, "Valid");
|
|
else fprintf(stderr, "CRC ERROR");
|
|
fprintf(stderr, "\n");
|
|
}
|
|
#endif //dPMR_PRINT_DEBUG_INFO
|
|
|
|
} //End processdPMRvoice()
|
|
|
|
|
|
/* Scrambler used for dPMR transmission (different of the
|
|
* voice encryption scrambler), see ETSI TS 102 658 chapter
|
|
* 7.3 for the polynomial description.
|
|
* It is a X^9 + X^5 + 1 polynomial. */
|
|
|
|
void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferOut, uint32_t NbOfBitToScramble)
|
|
{
|
|
uint8_t S[9] = {0};
|
|
uint32_t i;
|
|
uint8_t Temp;
|
|
uint32_t LFSRValue;
|
|
|
|
LFSRValue = *LfsrValue;
|
|
|
|
/* Load the initial LFSR value */
|
|
for(i = 0; i < 9; i++)
|
|
{
|
|
S[i] = LFSRValue & 1;
|
|
LFSRValue >>= 1;
|
|
}
|
|
|
|
/* There are 72 bit to descramble for voice and 288 bit for data */
|
|
for(i = 0; i < NbOfBitToScramble; i++)
|
|
{
|
|
BufferOut[i] = (BufferIn[i] ^ S[0]) & 0x01;
|
|
|
|
/* Shift registers */
|
|
Temp = S[4] ^ S[0];
|
|
S[0] = S[1];
|
|
S[1] = S[2];
|
|
S[2] = S[3];
|
|
S[3] = S[4];
|
|
S[4] = S[5];
|
|
S[5] = S[6];
|
|
S[6] = S[7];
|
|
S[7] = S[8];
|
|
S[8] = Temp;
|
|
}
|
|
|
|
/* Save the final LFSR value */
|
|
LFSRValue = 0;
|
|
for(i = 9; i > 0; i--)
|
|
{
|
|
LFSRValue <<= 1;
|
|
LFSRValue |= S[i - 1] & 1;
|
|
}
|
|
|
|
*LfsrValue = LFSRValue;
|
|
} /* End ScrambleDPmrBit() */
|
|
|
|
|
|
/* Scrambler used for dPMR scrambling / descrambling,
|
|
* see ETSI TS 102 658 chapter 7.4 for the
|
|
* polynomial description.
|
|
* It is a X^9 + X^5 + 1 polynomial. */
|
|
void DeInterleave6x12DPmrBit(uint8_t * BufferIn, uint8_t * BufferOut)
|
|
{
|
|
uint8_t Matrix[12][6] = {0};
|
|
uint32_t i, j, k;
|
|
|
|
/* Step 1 : Filling the 12 x 6 bit matrix */
|
|
k = 0;
|
|
for(i = 0; i < 12; i++)
|
|
{
|
|
for(j = 0; j < 6; j++)
|
|
{
|
|
Matrix[i][j] = BufferIn[k++];
|
|
}
|
|
}
|
|
|
|
/* Step 2 : Filling the output buffer with deinterleaved data */
|
|
k = 0;
|
|
for(j = 0; j < 6; j++)
|
|
{
|
|
for(i = 0; i < 12; i++)
|
|
{
|
|
BufferOut[k++] = Matrix[i][j];
|
|
}
|
|
}
|
|
} /* End DeInterleave6x12DPmrBit() */
|
|
|
|
|
|
/* CRC 7 bit computation with the following
|
|
* polynomial : X^7 + X^3 + 1 */
|
|
uint8_t CRC7BitdPMR(uint8_t * BufferIn, uint32_t BitLength)
|
|
{
|
|
uint8_t ShiftRegister = 0x00; /* All bit to '0' (7 LSBit only used) */
|
|
uint8_t Polynome = 0x09; /* X^7 + X^3 + 1 */
|
|
uint32_t i;
|
|
|
|
for(i = 0; i < BitLength; i++)
|
|
{
|
|
if(((ShiftRegister >> 6) & 1) ^ BufferIn[i])
|
|
{
|
|
ShiftRegister = ((ShiftRegister << 1) ^ Polynome) & 0x7F;
|
|
}
|
|
else
|
|
{
|
|
ShiftRegister = (ShiftRegister << 1) & 0x7F;
|
|
}
|
|
}
|
|
|
|
return ShiftRegister;
|
|
} /* End CRC7BitdPMR() */
|
|
|
|
|
|
/* CRC 8 bit computation with the following
|
|
* polynomial : X^8 + X^2 + X + 1 */
|
|
uint8_t CRC8BitdPMR(uint8_t * BufferIn, uint32_t BitLength)
|
|
{
|
|
uint8_t ShiftRegister = 0xFF; /* All bit to '1' */
|
|
uint8_t Polynome = 0x07; /* X^7 + X^3 + 1 */
|
|
uint32_t i;
|
|
|
|
for(i = 0; i < BitLength; i++)
|
|
{
|
|
if(((ShiftRegister >> 7) & 1) ^ BufferIn[i])
|
|
{
|
|
ShiftRegister = ((ShiftRegister << 1) ^ Polynome) & 0xFF;
|
|
}
|
|
else
|
|
{
|
|
ShiftRegister = (ShiftRegister << 1) & 0xFF;
|
|
}
|
|
}
|
|
|
|
return ShiftRegister;
|
|
} /* End CRC8BitdPMR() */
|
|
|
|
|
|
/* Convert an air interface identifier (AI ID) into
|
|
* a 7 ASCII digit string.
|
|
*
|
|
* See dPMR standard chapter A.1.2.1.1.6
|
|
* "Mapping of dialled strings to the AI address space" */
|
|
void ConvertAirInterfaceID(uint32_t AI_ID, uint8_t ID[8])
|
|
{
|
|
uint32_t AI_ID_Temp = AI_ID;
|
|
uint32_t Digit;
|
|
|
|
/* 1st digit */
|
|
Digit = AI_ID_Temp / 1464100;
|
|
AI_ID_Temp = AI_ID_Temp % 1464100;
|
|
if(Digit == 10) ID[0] = '*';
|
|
else ID[0] = Digit + '0';
|
|
|
|
/* 2nd digit */
|
|
Digit = AI_ID_Temp / 146410;
|
|
AI_ID_Temp = AI_ID_Temp % 146410;
|
|
if(Digit == 10) ID[1] = '*';
|
|
else ID[1] = Digit + '0';
|
|
|
|
/* 3rd digit */
|
|
Digit = AI_ID_Temp / 14641;
|
|
AI_ID_Temp = AI_ID_Temp % 14641;
|
|
if(Digit == 10) ID[2] = '*';
|
|
else ID[2] = Digit + '0';
|
|
|
|
/* 4th digit */
|
|
Digit = AI_ID_Temp / 1331;
|
|
AI_ID_Temp = AI_ID_Temp % 1331;
|
|
if(Digit == 10) ID[3] = '*';
|
|
else ID[3] = Digit + '0';
|
|
|
|
/* 5th digit */
|
|
Digit = AI_ID_Temp / 121;
|
|
AI_ID_Temp = AI_ID_Temp % 121;
|
|
if(Digit == 10) ID[4] = '*';
|
|
else ID[4] = Digit + '0';
|
|
|
|
/* 6th digit */
|
|
Digit = AI_ID_Temp / 11;
|
|
AI_ID_Temp = AI_ID_Temp % 11;
|
|
if(Digit == 10) ID[5] = '*';
|
|
else ID[5] = Digit + '0';
|
|
|
|
/* 7th digit */
|
|
Digit = AI_ID_Temp;
|
|
if(Digit == 10) ID[6] = '*';
|
|
else ID[6] = Digit + '0';
|
|
|
|
/* Add the "end of string" */
|
|
ID[7] = '\0';
|
|
|
|
} /* End convertAirInterfaceID() */
|
|
|
|
/* End of file */
|