mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	DSDplus library: interim state #1
This commit is contained in:
		
							parent
							
								
									0b58a50ee8
								
							
						
					
					
						commit
						dd39afdc64
					
				| @ -17,11 +17,55 @@ | ||||
| #include "dmr_voice.h" | ||||
| #include "dsd_decoder.h" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| /*
 | ||||
|  * DMR AMBE interleave schedule | ||||
|  */ | ||||
| const int DSDDMRVoice::rW[36] = { | ||||
|   0, 1, 0, 1, 0, 1, | ||||
|   0, 1, 0, 1, 0, 1, | ||||
|   0, 1, 0, 1, 0, 1, | ||||
|   0, 1, 0, 1, 0, 2, | ||||
|   0, 2, 0, 2, 0, 2, | ||||
|   0, 2, 0, 2, 0, 2 | ||||
| }; | ||||
| 
 | ||||
| const int DSDDMRVoice::rX[36] = { | ||||
|   23, 10, 22, 9, 21, 8, | ||||
|   20, 7, 19, 6, 18, 5, | ||||
|   17, 4, 16, 3, 15, 2, | ||||
|   14, 1, 13, 0, 12, 10, | ||||
|   11, 9, 10, 8, 9, 7, | ||||
|   8, 6, 7, 5, 6, 4 | ||||
| }; | ||||
| 
 | ||||
| const int DSDDMRVoice::rY[36] = { | ||||
|   0, 2, 0, 2, 0, 2, | ||||
|   0, 2, 0, 3, 0, 3, | ||||
|   1, 3, 1, 3, 1, 3, | ||||
|   1, 3, 1, 3, 1, 3, | ||||
|   1, 3, 1, 3, 1, 3, | ||||
|   1, 3, 1, 3, 1, 3 | ||||
| }; | ||||
| 
 | ||||
| const int DSDDMRVoice::rZ[36] = { | ||||
|   5, 3, 4, 2, 3, 1, | ||||
|   2, 0, 1, 13, 0, 12, | ||||
|   22, 11, 21, 10, 20, 9, | ||||
|   19, 8, 18, 7, 17, 6, | ||||
|   16, 5, 15, 4, 14, 3, | ||||
|   13, 2, 12, 1, 11, 0 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| DSDDMRVoice::DSDDMRVoice(DSDDecoder *dsdDecoder) : | ||||
|         m_dsdDecoder(dsdDecoder) | ||||
|         m_dsdDecoder(dsdDecoder), | ||||
|         m_symbolIndex(0), | ||||
|         m_dibitIndex(0), | ||||
|         mutecurrentslot(0), | ||||
|         m_slotIndex(-1) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| @ -34,13 +78,307 @@ void DSDDMRVoice::init() | ||||
|     mutecurrentslot = 0; | ||||
|     msMode = 0; | ||||
|     dibit_p = m_dsdDecoder->m_state.dibit_buf_p - 144; | ||||
|     m_slotIndex = 0; | ||||
|     m_majorBlock = 0; | ||||
|     m_symbolIndex = 0; | ||||
| 
 | ||||
|     preProcess(); | ||||
| 
 | ||||
|     m_symbolIndex = 144; // reposition symbol index in frame
 | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::process() | ||||
| { | ||||
|     m_majorBlock = m_symbolIndex / 288;           // frame (major block) index
 | ||||
|     m_dibitIndex = m_symbolIndex % 288;           // index of symbol in frame
 | ||||
|     int symbolIndex = getSlotIndex(m_dibitIndex); // returns symbol index in current slot. Updates m_slotIndex.
 | ||||
| 
 | ||||
|     switch(m_slotIndex) | ||||
|     { | ||||
|     case 0: | ||||
|         processSlot0(symbolIndex); | ||||
|         break; | ||||
|     case 1: | ||||
|         processSlot1(symbolIndex); | ||||
|         break; | ||||
|     case 2: | ||||
|         processSlot2(symbolIndex); | ||||
|         break; | ||||
|     case 3: | ||||
|         processSlot3(symbolIndex); | ||||
|         break; | ||||
|     case 4: | ||||
|         processSlot4(symbolIndex); | ||||
|         break; | ||||
|     case 5: | ||||
|         processSlot5(symbolIndex); | ||||
|         break; | ||||
|     case 6: | ||||
|         processSlot6(symbolIndex); | ||||
|         break; | ||||
|     case 7: | ||||
|         processSlot7(symbolIndex); | ||||
|         break; | ||||
|     case 8: | ||||
|         processSlot8(symbolIndex); | ||||
|         break; | ||||
|     case 9: | ||||
|         processSlot9(symbolIndex); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     m_symbolIndex++; | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::preProcess() | ||||
| { | ||||
|     // copy in memory to dibit cache
 | ||||
|     memcpy((void *) m_dibitCache, (const void *) dibit_p, 144 * sizeof(int)); | ||||
| 
 | ||||
|     m_dibitIndex = 54-1; // set cache pointer - skip slot 0
 | ||||
| 
 | ||||
|     m_dibitIndex += 12; // advance cache pointer
 | ||||
|     processSlot1(12-1); | ||||
| 
 | ||||
|     m_dibitIndex += 36; // advance cache pointer
 | ||||
|     processSlot2(36-1); | ||||
| 
 | ||||
|     m_dibitIndex += 18; // advance cache pointer
 | ||||
|     processSlot3(18-1); | ||||
| 
 | ||||
|     m_dibitIndex += 24; // advance cache pointer
 | ||||
|     processSlot4(24-1); | ||||
| 
 | ||||
|     m_dibitIndex += 18; // advance cache pointer
 | ||||
|     processSlot5(18-1); | ||||
| 
 | ||||
|     m_dibitIndex += 36; // advance cache pointer
 | ||||
|     processSlot6(36-1); | ||||
| 
 | ||||
|     m_dibitIndex += 12; // advance cache pointer
 | ||||
|     processSlot7(12-1); | ||||
| 
 | ||||
|     m_dibitIndex += 54; // advance cache pointer - skip slot 8
 | ||||
| 
 | ||||
|     processSlot9(24-1); | ||||
|     m_dibitIndex += 24; // advance cache pointer
 | ||||
|     processSlot9(24-1); | ||||
| 
 | ||||
|     m_symbolIndex = 144; // advance the main symbol index
 | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot0(int symbolIndex) // Slot0 is a 54 symbol slot
 | ||||
| { | ||||
|     m_dsdDecoder->getDibit(); // get dibit from symbol but do nothing with it
 | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot8(int symbolIndex) // Slot8 is a 54 symbol slot
 | ||||
| { | ||||
|     m_dsdDecoder->getDibit(); // get dibit from symbol but do nothing with it
 | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot1(int symbolIndex) // Slot1 is a 12 symbol slot
 | ||||
| { | ||||
|     if (m_majorBlock > 0) // 0:1 reads from 144 in memory dibits. Handled by upper layer.
 | ||||
|     { | ||||
|         int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
 | ||||
|         m_dibitCache[m_dibitIndex] = dibit; | ||||
|     } | ||||
| 
 | ||||
|     if (symbolIndex == 12-1) // last symbol -> launch process
 | ||||
|     { | ||||
|         int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
 | ||||
|         // CACH
 | ||||
|         for (int i = 0; i < 12; i++) | ||||
|         { | ||||
|             int dibit = dibitCache[i]; | ||||
|             cachdata[i] = dibit; | ||||
| 
 | ||||
|             if (i == 2) | ||||
|             { | ||||
|                 m_dsdDecoder->m_state.currentslot = (1 & (dibit >> 1));  // bit 1
 | ||||
| 
 | ||||
|                 if (m_dsdDecoder->m_state.currentslot == 0) | ||||
|                 { | ||||
|                     m_dsdDecoder->m_state.slot0light[0] = '['; | ||||
|                     m_dsdDecoder->m_state.slot0light[6] = ']'; | ||||
|                     m_dsdDecoder->m_state.slot1light[0] = ' '; | ||||
|                     m_dsdDecoder->m_state.slot1light[6] = ' '; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_dsdDecoder->m_state.slot1light[0] = '['; | ||||
|                     m_dsdDecoder->m_state.slot1light[6] = ']'; | ||||
|                     m_dsdDecoder->m_state.slot0light[0] = ' '; | ||||
|                     m_dsdDecoder->m_state.slot0light[6] = ' '; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         cachdata[12] = 0; | ||||
|         m_dibitIndex = 0; // done with the cache -> reset index
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot2(int symbolIndex) // Slot2 is a 36 symbol slot
 | ||||
| { | ||||
|     if (m_majorBlock > 0) // 0:2 reads from 144 in memory dibits. Handled by upper layer.
 | ||||
|     { | ||||
|         int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
 | ||||
|         m_dibitCache[m_dibitIndex] = dibit; | ||||
|     } | ||||
| 
 | ||||
|     if (symbolIndex == 36-1) // last symbol -> launch process
 | ||||
|     { | ||||
|         int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
 | ||||
| 
 | ||||
|         w = rW; | ||||
|         x = rX; | ||||
|         y = rY; | ||||
|         z = rZ; | ||||
| 
 | ||||
|         for (int i = 0; i < 36; i++) | ||||
|         { | ||||
|             int dibit = dibitCache[i]; | ||||
| 
 | ||||
|             ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
 | ||||
|             ambe_fr[*y][*z] = (1 & dibit);        // bit 0
 | ||||
|             w++; | ||||
|             x++; | ||||
|             y++; | ||||
|             z++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot3(int symbolIndex) // Slot3 is a 18 symbol slot
 | ||||
| { | ||||
|     if (m_majorBlock > 0) // 0:3 reads from 144 in memory dibits. Handled by upper layer.
 | ||||
|     { | ||||
|         int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
 | ||||
|         m_dibitCache[m_dibitIndex] = dibit; | ||||
|     } | ||||
| 
 | ||||
|     if (symbolIndex == 18-1) // last symbol -> launch process
 | ||||
|     { | ||||
|         int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
 | ||||
| 
 | ||||
|         w = rW; | ||||
|         x = rX; | ||||
|         y = rY; | ||||
|         z = rZ; | ||||
| 
 | ||||
|         for (int i = 0; i < 18; i++) | ||||
|         { | ||||
|             int dibit = dibitCache[i]; | ||||
| 
 | ||||
|             ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
 | ||||
|             ambe_fr2[*y][*z] = (1 & dibit);        // bit 0
 | ||||
|             w++; | ||||
|             x++; | ||||
|             y++; | ||||
|             z++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot4(int symbolIndex) // Slot4 is a 24 symbol slot
 | ||||
| { | ||||
|     if (m_majorBlock > 0) // 0:3 reads from 144 in memory dibits. Handled by upper layer.
 | ||||
|     { | ||||
|         int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
 | ||||
|         m_dibitCache[m_dibitIndex] = dibit; | ||||
|     } | ||||
| 
 | ||||
|     if (symbolIndex == 24-1) // last symbol -> launch process
 | ||||
|     { | ||||
|         int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
 | ||||
| 
 | ||||
|         for (int i = 0; i < 18; i++) | ||||
|         { | ||||
|             int dibit = dibitCache[i]; | ||||
| 
 | ||||
|             syncdata[i] = dibit; | ||||
|             sync[i] = (dibit | 1) + 48; | ||||
|         } | ||||
| 
 | ||||
|         sync[24] = 0; | ||||
|         syncdata[24] = 0; | ||||
| 
 | ||||
|         if ((strcmp(sync, DMR_BS_DATA_SYNC) == 0) | ||||
|          || (strcmp(sync, DMR_MS_DATA_SYNC) == 0)) | ||||
|         { | ||||
|             mutecurrentslot = 1; | ||||
|             if (m_dsdDecoder->m_state.currentslot == 0) | ||||
|             { | ||||
|                 sprintf(m_dsdDecoder->m_state.slot0light, "[slot0]"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 sprintf(m_dsdDecoder->m_state.slot1light, "[slot1]"); | ||||
|             } | ||||
|         } | ||||
|         else if ((strcmp(sync, DMR_BS_VOICE_SYNC) == 0) | ||||
|               || (strcmp(sync, DMR_MS_VOICE_SYNC) == 0)) | ||||
|         { | ||||
|             mutecurrentslot = 0; | ||||
|             if (m_dsdDecoder->m_state.currentslot == 0) | ||||
|             { | ||||
|                 sprintf(m_dsdDecoder->m_state.slot0light, "[SLOT0]"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 sprintf(m_dsdDecoder->m_state.slot1light, "[SLOT1]"); | ||||
|             } | ||||
|         } | ||||
|         if ((strcmp(sync, DMR_MS_VOICE_SYNC) == 0) | ||||
|          || (strcmp(sync, DMR_MS_DATA_SYNC) == 0)) | ||||
|         { | ||||
|             msMode = 1; | ||||
|         } | ||||
| 
 | ||||
|         if ((m_majorBlock == 0) && (m_dsdDecoder->m_opts.errorbars == 1)) | ||||
|         { | ||||
|             fprintf(stderr, "%s %s  VOICE e:", m_dsdDecoder->m_state.slot0light, m_dsdDecoder->m_state.slot1light); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DSDDMRVoice::processSlot5(int symbolIndex) // Slot5 is a 18 symbol slot
 | ||||
| { | ||||
|     int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
 | ||||
|     m_dibitCache[m_dibitIndex] = dibit; | ||||
| 
 | ||||
|     if (symbolIndex == 18-1) // last symbol -> launch process
 | ||||
|     { | ||||
|         int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
 | ||||
| 
 | ||||
|         for (int i = 0; i < 18; i++) | ||||
|         { | ||||
|             int dibit = dibitCache[i]; | ||||
| 
 | ||||
|             ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
 | ||||
|             ambe_fr2[*y][*z] = (1 & dibit);        // bit 0
 | ||||
|             w++; | ||||
|             x++; | ||||
|             y++; | ||||
|             z++; | ||||
|         } | ||||
| 
 | ||||
|         if (mutecurrentslot == 0) | ||||
|         { | ||||
|             if (m_dsdDecoder->m_state.firstframe == 1) | ||||
|             { // we don't know if anything received before the first sync after no carrier is valid
 | ||||
|                 m_dsdDecoder->m_state.firstframe = 0; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_dsdDecoder->m_mbeDecoder.processFrame(0, ambe_fr, 0); | ||||
|                 m_dsdDecoder->m_mbeDecoder.processFrame(0, ambe_fr2, 0); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } // namespace dsdplus
 | ||||
|  | ||||
| @ -42,7 +42,7 @@ | ||||
| #ifndef DSDPLUS_DMR_VOICE_H_ | ||||
| #define DSDPLUS_DMR_VOICE_H_ | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| class DSDDecoder; | ||||
| @ -57,12 +57,82 @@ public: | ||||
|     void process(); | ||||
| 
 | ||||
| private: | ||||
|     int getSlotIndex(int symbolInMajorBlockIndex) //!< calculates current slot index and returns symbol index in the slot
 | ||||
|     { | ||||
|         if (symbolInMajorBlockIndex < 54) | ||||
|         { | ||||
|             m_slotIndex = 0; | ||||
|             return symbolInMajorBlockIndex; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12) | ||||
|         { | ||||
|             m_slotIndex = 1; | ||||
|             return symbolInMajorBlockIndex - 54; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36) | ||||
|         { | ||||
|             m_slotIndex = 2; | ||||
|             return symbolInMajorBlockIndex - 54+12; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18) | ||||
|         { | ||||
|             m_slotIndex = 3; | ||||
|             return symbolInMajorBlockIndex - 54+12+36; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24) | ||||
|         { | ||||
|             m_slotIndex = 4; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24+18) | ||||
|         { | ||||
|             m_slotIndex = 5; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18+24; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36) | ||||
|         { | ||||
|             m_slotIndex = 6; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18+24+18; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12) | ||||
|         { | ||||
|             m_slotIndex = 7; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18+24+18+36; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12+54) | ||||
|         { | ||||
|             m_slotIndex = 8; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18+24+18+36+12; | ||||
|         } | ||||
|         else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12+54+24) | ||||
|         { | ||||
|             m_slotIndex = 9; | ||||
|             return symbolInMajorBlockIndex - 54+12+36+18+24+18+36+12+54; | ||||
|         } | ||||
|         else // cannot go there if using this function in its valid context (input is a remainder of division by 288)
 | ||||
|         { | ||||
|             m_slotIndex = -1; // invalid slot
 | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void preProcess(); //!< process the 144 in memory dibits in initial phase
 | ||||
|     void processSlot0(int symbolIndex); | ||||
|     void processSlot1(int symbolIndex); | ||||
|     void processSlot2(int symbolIndex); | ||||
|     void processSlot3(int symbolIndex); | ||||
|     void processSlot4(int symbolIndex); | ||||
|     void processSlot5(int symbolIndex); | ||||
|     void processSlot6(int symbolIndex); | ||||
|     void processSlot7(int symbolIndex); | ||||
|     void processSlot8(int symbolIndex); | ||||
|     void processSlot9(int symbolIndex); | ||||
| 
 | ||||
|     DSDDecoder *m_dsdDecoder; | ||||
|     // extracts AMBE frames from DMR frame
 | ||||
|     int m_slotIndex;  //!< Slot index in major block 0..9 //i;
 | ||||
|     int m_majorBlock; //!< Major block index 0..5 //j;
 | ||||
|     int dibit; | ||||
|     int m_symbolIndex; //!< Current absolute symbol index
 | ||||
|     int m_slotIndex;   //!< Slot index in major block 0..9 //i;
 | ||||
|     int m_majorBlock;  //!< Major block index 0..5 //j;
 | ||||
|     int *dibit_p; | ||||
|     char ambe_fr[4][24]; | ||||
|     char ambe_fr2[4][24]; | ||||
| @ -73,8 +143,14 @@ private: | ||||
|     char cachdata[13]; | ||||
|     int mutecurrentslot; | ||||
|     int msMode; | ||||
|     int m_dibitCache[54]; // biggest slot is 54 dibits
 | ||||
|     int m_dibitIndex;     // index in dibit cache
 | ||||
|     int m_dibitCache[288]; // has to handle a complete frame (288 dibits)
 | ||||
|     int m_dibitIndex;      // index in dibit cache
 | ||||
| 
 | ||||
|     static const int rW[36]; | ||||
|     static const int rX[36]; | ||||
|     static const int rY[36]; | ||||
|     static const int rZ[36]; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -17,12 +17,14 @@ | ||||
| #include <stdlib.h> | ||||
| #include "dsd_decoder.h" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| DSDDecoder::DSDDecoder() : | ||||
|         m_symbol(0), | ||||
|         m_fsmState(DSDLookForSync), | ||||
|         m_hasSync(0), | ||||
|         m_mbeDecoder(this), | ||||
|         m_dsdDMRVoice(this) | ||||
| { | ||||
|     resetSymbol(); | ||||
| @ -36,27 +38,32 @@ DSDDecoder::~DSDDecoder() | ||||
| 
 | ||||
| void DSDDecoder::run(short sample) | ||||
| { | ||||
|     if (pushSample(sample, 0)) | ||||
|     if (pushSample(sample, 0)) // a symbol is retrieved
 | ||||
|     { | ||||
|         switch (m_fsmState) | ||||
|         { | ||||
|         case DSDLookForSync: | ||||
|             m_state.synctype = getFrameSync(); | ||||
|             m_hasSync = 0; | ||||
|             m_state.synctype = getFrameSync(); // -> -2: still looking, -1 not found, 0 and above: sync found
 | ||||
| 
 | ||||
|             if (m_state.synctype > -2) | ||||
|             if (m_state.synctype > -2) // -1 and above means syncing has been processed (sync found or not but not searching)
 | ||||
|             { | ||||
|                 // TODO: deal with the noCarrier() call
 | ||||
|                 // recalibrate center/umid/lmid
 | ||||
|                 m_state.center = ((m_state.max) + (m_state.min)) / 2; | ||||
|                 m_state.umid = (((m_state.max) - m_state.center) * 5 / 8) + m_state.center; | ||||
|                 m_state.lmid = (((m_state.min) - m_state.center) * 5 / 8) + m_state.center; | ||||
| 
 | ||||
|                 if (m_state.synctype > -1) | ||||
|                 if (m_state.synctype > -1) // 0 and above means a sync has been found
 | ||||
|                 { | ||||
|                     processFrame(); | ||||
|                     m_hasSync = 1; | ||||
|                     processFrame(); // process the frame which sync has been found. This will change FSM state
 | ||||
|                 } | ||||
|                 else // no sync has been found after searching -> call noCarrier() and go back searching (same FSM state)
 | ||||
|                 { | ||||
|                     noCarrier(); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // still searching -> no change in FSM state
 | ||||
|             break; | ||||
|         case DSDprocessDMRvoice: | ||||
|             m_dsdDMRVoice.process(); | ||||
| @ -111,7 +118,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|                 m_sampleIndex--; | ||||
|             } | ||||
|             else if ((m_state.jitter >= m_state.symbolCenter + 1) | ||||
|                     && (m_state.jitter <= m_state.symbolCenter + 2)) | ||||
|                   && (m_state.jitter <= m_state.symbolCenter + 2)) | ||||
|             { | ||||
|                 m_sampleIndex++; | ||||
|             } | ||||
| @ -124,7 +131,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|                 m_sampleIndex--;          // catch up
 | ||||
|             } | ||||
|             else if ((m_state.jitter > m_state.symbolCenter) | ||||
|                     && (m_state.jitter < m_state.samplesPerSymbol)) | ||||
|                   && (m_state.jitter < m_state.samplesPerSymbol)) | ||||
|             { | ||||
|                 m_sampleIndex++;          // fall back
 | ||||
|             } | ||||
| @ -140,8 +147,8 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|         { | ||||
|             sample = m_dsdFilters.dmr_filter(sample); | ||||
|         } | ||||
|         else if (m_state.lastsynctype == 8 || m_state.lastsynctype == 9 | ||||
|                 || m_state.lastsynctype == 16 || m_state.lastsynctype == 17) | ||||
|         else if (m_state.lastsynctype == 8  || m_state.lastsynctype == 9 | ||||
|               || m_state.lastsynctype == 16 || m_state.lastsynctype == 17) | ||||
|         { | ||||
|             sample = m_dsdFilters.nxdn_filter(sample); | ||||
|         } | ||||
| @ -174,7 +181,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|                 m_state.jitter = m_sampleIndex; | ||||
|             } | ||||
|             if ((m_opts.symboltiming == 1) && (have_sync == 0) | ||||
|                     && (m_state.lastsynctype != -1)) | ||||
|              && (m_state.lastsynctype != -1)) | ||||
|             { | ||||
|                 fprintf(stderr, "O"); | ||||
|             } | ||||
| @ -182,13 +189,13 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|         else | ||||
|         { | ||||
|             if ((m_opts.symboltiming == 1) && (have_sync == 0) | ||||
|                     && (m_state.lastsynctype != -1)) | ||||
|              && (m_state.lastsynctype != -1)) | ||||
|             { | ||||
|                 fprintf(stderr, "+"); | ||||
|             } | ||||
|             if ((m_state.jitter < 0) | ||||
|                     && (m_state.lastsample < m_state.center) | ||||
|                     && (m_state.rf_mod != 1)) | ||||
|              && (m_state.lastsample < m_state.center) | ||||
|              && (m_state.rf_mod != 1)) | ||||
|             {               // first transition edge
 | ||||
|                 m_state.jitter = m_sampleIndex; | ||||
|             } | ||||
| @ -211,7 +218,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|                 m_state.jitter = m_sampleIndex; | ||||
|             } | ||||
|             if ((m_opts.symboltiming == 1) && (have_sync == 0) | ||||
|                     && (m_state.lastsynctype != -1)) | ||||
|              && (m_state.lastsynctype != -1)) | ||||
|             { | ||||
|                 fprintf(stderr, "X"); | ||||
|             } | ||||
| @ -219,13 +226,13 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|         else | ||||
|         { | ||||
|             if ((m_opts.symboltiming == 1) && (have_sync == 0) | ||||
|                     && (m_state.lastsynctype != -1)) | ||||
|              && (m_state.lastsynctype != -1)) | ||||
|             { | ||||
|                 fprintf(stderr, "-"); | ||||
|             } | ||||
|             if ((m_state.jitter < 0) | ||||
|                     && (m_state.lastsample > m_state.center) | ||||
|                     && (m_state.rf_mod != 1)) | ||||
|              && (m_state.lastsample > m_state.center) | ||||
|              && (m_state.rf_mod != 1)) | ||||
|             {               // first transition edge
 | ||||
|                 m_state.jitter = m_sampleIndex; | ||||
|             } | ||||
| @ -290,6 +297,292 @@ bool DSDDecoder::pushSample(short sample, int have_sync) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int DSDDecoder::getDibit() | ||||
| { | ||||
|     // returns one dibit value
 | ||||
|     int i, j, o, symbol; | ||||
|     int sbuf2[128]; | ||||
|     int spectrum[64]; | ||||
|     char modulation[8]; | ||||
|     int lmin, lmax, lsum; | ||||
| 
 | ||||
|     m_state.numflips = 0; | ||||
| 
 | ||||
|     symbol = m_symbol; | ||||
|     m_state.sbuf[m_state.sidx] = m_symbol; | ||||
| 
 | ||||
|     for (i = 0; i < m_opts.ssize; i++) | ||||
|     { | ||||
|         sbuf2[i] = m_state.sbuf[i]; | ||||
|     } | ||||
| 
 | ||||
|     qsort(sbuf2, m_opts.ssize, sizeof(int), comp); | ||||
|     // continuous update of min/max in rf_mod=1 (QPSK) mode
 | ||||
|     // in c4fm min/max must only be updated during sync
 | ||||
|     if (m_state.rf_mod == 1) | ||||
|     { | ||||
|         lmin = (sbuf2[0] + sbuf2[1]) / 2; | ||||
|         lmax = (sbuf2[(m_opts.ssize - 1)] + sbuf2[(m_opts.ssize - 2)]) / 2; | ||||
|         m_state.minbuf[m_state.midx] = lmin; | ||||
|         m_state.maxbuf[m_state.midx] = lmax; | ||||
| 
 | ||||
|         if (m_state.midx == (m_opts.msize - 1)) | ||||
|         { | ||||
|             m_state.midx = 0; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_state.midx++; | ||||
|         } | ||||
| 
 | ||||
|         lsum = 0; | ||||
| 
 | ||||
|         for (i = 0; i < m_opts.msize; i++) | ||||
|         { | ||||
|             lsum += m_state.minbuf[i]; | ||||
|         } | ||||
| 
 | ||||
|         m_state.min = lsum / m_opts.msize; | ||||
|         lsum = 0; | ||||
| 
 | ||||
|         for (i = 0; i < m_opts.msize; i++) | ||||
|         { | ||||
|             lsum += m_state.maxbuf[i]; | ||||
|         } | ||||
| 
 | ||||
|         m_state.max = lsum / m_opts.msize; | ||||
|         m_state.center = ((m_state.max) + (m_state.min)) / 2; | ||||
|         m_state.umid = (((m_state.max) - m_state.center) * 5 / 8) + m_state.center; | ||||
|         m_state.lmid = (((m_state.min) - m_state.center) * 5 / 8) + m_state.center; | ||||
|         m_state.maxref = ((m_state.max) * 0.80); | ||||
|         m_state.minref = ((m_state.min) * 0.80); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         m_state.maxref = m_state.max; | ||||
|         m_state.minref = m_state.min; | ||||
|     } | ||||
| 
 | ||||
|     if (m_state.sidx == (m_opts.ssize - 1)) | ||||
|     { | ||||
|         m_state.sidx = 0; | ||||
| 
 | ||||
|         if (m_opts.datascope == 1) | ||||
|         { | ||||
|             if (m_state.rf_mod == 0) | ||||
|             { | ||||
|                 sprintf(modulation, "C4FM"); | ||||
|             } | ||||
|             else if (m_state.rf_mod == 1) | ||||
|             { | ||||
|                 sprintf(modulation, "QPSK"); | ||||
|             } | ||||
|             else if (m_state.rf_mod == 2) | ||||
|             { | ||||
|                 sprintf(modulation, "GFSK"); | ||||
|             } | ||||
| 
 | ||||
|             for (i = 0; i < 64; i++) | ||||
|             { | ||||
|                 spectrum[i] = 0; | ||||
|             } | ||||
|             for (i = 0; i < m_opts.ssize; i++) | ||||
|             { | ||||
|                 o = (sbuf2[i] + 32768) / 1024; | ||||
|                 spectrum[o]++; | ||||
|             } | ||||
|             if (m_state.symbolcnt > (4800 / m_opts.scoperate)) | ||||
|             { | ||||
|                 m_state.symbolcnt = 0; | ||||
|                 fprintf(stderr, "\n"); | ||||
|                 fprintf(stderr, | ||||
|                         "Demod mode:     %s                Nac:                     %4X\n", | ||||
|                         modulation, m_state.nac); | ||||
|                 fprintf(stderr, | ||||
|                         "Frame Type:    %s        Talkgroup:            %7i\n", | ||||
|                         m_state.ftype, m_state.lasttg); | ||||
|                 fprintf(stderr, | ||||
|                         "Frame Subtype: %s       Source:          %12i\n", | ||||
|                         m_state.fsubtype, m_state.lastsrc); | ||||
|                 fprintf(stderr, | ||||
|                         "TDMA activity:  %s %s     Voice errors: %s\n", | ||||
|                         m_state.slot0light, m_state.slot1light, m_state.err_str); | ||||
|                 fprintf(stderr, | ||||
|                         "+----------------------------------------------------------------+\n"); | ||||
| 
 | ||||
|                 for (i = 0; i < 10; i++) | ||||
|                 { | ||||
|                     fprintf(stderr, "|"); | ||||
| 
 | ||||
|                     for (j = 0; j < 64; j++) | ||||
|                     { | ||||
|                         if (i == 0) | ||||
|                         { | ||||
|                             if ((j == ((m_state.min) + 32768) / 1024) | ||||
|                                     || (j == ((m_state.max) + 32768) / 1024)) | ||||
|                             { | ||||
|                                 fprintf(stderr, "#"); | ||||
|                             } | ||||
|                             else if ((j == ((m_state.lmid) + 32768) / 1024) | ||||
|                                     || (j == ((m_state.umid) + 32768) / 1024)) | ||||
|                             { | ||||
|                                 fprintf(stderr, "^"); | ||||
|                             } | ||||
|                             else if (j == (m_state.center + 32768) / 1024) | ||||
|                             { | ||||
|                                 fprintf(stderr, "!"); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 if (j == 32) | ||||
|                                 { | ||||
|                                     fprintf(stderr, "|"); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     fprintf(stderr, " "); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             if (spectrum[j] > 9 - i) | ||||
|                             { | ||||
|                                 fprintf(stderr, "*"); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 if (j == 32) | ||||
|                                 { | ||||
|                                     fprintf(stderr, "|"); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     fprintf(stderr, " "); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     fprintf(stderr, "|\n"); | ||||
|                 } | ||||
|                 fprintf(stderr, | ||||
|                         "+----------------------------------------------------------------+\n"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         m_state.sidx++; | ||||
|     } | ||||
| 
 | ||||
|     if (m_state.dibit_buf_p > m_state.dibit_buf + 900000) | ||||
|     { | ||||
|         m_state.dibit_buf_p = m_state.dibit_buf + 200; | ||||
|     } | ||||
| 
 | ||||
|     // determine dibit state
 | ||||
|     if ((m_state.synctype == 6) || (m_state.synctype == 14) | ||||
|             || (m_state.synctype == 18)) | ||||
|     { | ||||
|         if (m_symbol > m_state.center) | ||||
|         { | ||||
|             *m_state.dibit_buf_p = 1; | ||||
|             m_state.dibit_buf_p++; | ||||
|             return (0); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             *m_state.dibit_buf_p = 3; | ||||
|             m_state.dibit_buf_p++; | ||||
|             return (1); | ||||
|         } | ||||
|     } | ||||
|     else if ((m_state.synctype == 7) || (m_state.synctype == 15) | ||||
|             || (m_state.synctype == 19)) | ||||
|     { | ||||
|         if (m_symbol > m_state.center) | ||||
|         { | ||||
|             *m_state.dibit_buf_p = 1; | ||||
|             m_state.dibit_buf_p++; | ||||
|             return (1); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             *m_state.dibit_buf_p = 3; | ||||
|             m_state.dibit_buf_p++; | ||||
|             return (0); | ||||
|         } | ||||
|     } | ||||
|     else if ((m_state.synctype == 1) || (m_state.synctype == 3) | ||||
|             || (m_state.synctype == 5) || (m_state.synctype == 9) | ||||
|             || (m_state.synctype == 11) || (m_state.synctype == 13)) | ||||
|     { | ||||
|         if (m_symbol > m_state.center) | ||||
|         { | ||||
|             if (m_symbol > m_state.umid) | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 1; // store non-inverted values in dibit_buf
 | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (3); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 0; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (2); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (m_symbol < m_state.lmid) | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 3; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (1); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 2; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (0); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (m_symbol > m_state.center) | ||||
|         { | ||||
|             if (m_symbol > m_state.umid) | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 1; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (1); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 0; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (0); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (m_symbol < m_state.lmid) | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 3; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (3); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 *m_state.dibit_buf_p = 2; | ||||
|                 m_state.dibit_buf_p++; | ||||
|                 return (2); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DSDDecoder::resetFrameSync() | ||||
| { | ||||
|     for (int i = 18; i < 24; i++) | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
| #include "dsd_opts.h" | ||||
| #include "dsd_state.h" | ||||
| #include "dsd_filters.h" | ||||
| #include "dsd_mbe.h" | ||||
| #include "dmr_voice.h" | ||||
| 
 | ||||
| /*
 | ||||
| @ -57,7 +58,7 @@ | ||||
| #define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311" | ||||
| #define PROVOICE_EA_SYNC     "31131311331331111133131311311133" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| class DSDDecoder | ||||
| @ -88,6 +89,7 @@ public: | ||||
| 
 | ||||
| private: | ||||
|     bool pushSample(short sample, int have_sync); //!< push a new sample into the decoder. Returns true if a new symbol is available
 | ||||
|     int getDibit(); //!< get dibit from the last retrieved symbol. Returns the dibit as its dibit value: 0,1,2,3
 | ||||
|     int getFrameSync(); | ||||
|     void resetSymbol(); | ||||
|     void resetFrameSync(); | ||||
| @ -119,8 +121,11 @@ private: | ||||
|     int m_lsum; | ||||
|     char m_spectrum[64]; | ||||
|     int m_t; | ||||
|     int m_hasSync; //!< tells whether we are in synced phase
 | ||||
|     // Other
 | ||||
|     DSDFilters m_dsdFilters; | ||||
|     // MBE decoder
 | ||||
|     DSDMBEDecoder m_mbeDecoder; | ||||
|     // Frame decoders
 | ||||
|     DSDDMRVoice m_dsdDMRVoice; | ||||
| }; | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
| 
 | ||||
| #include "dsd_filters.h" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| // DMR filter
 | ||||
|  | ||||
| @ -21,7 +21,7 @@ | ||||
| #define NXZEROS 134 | ||||
| 
 | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| class DSDFilters | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
| 
 | ||||
| #include "dsd_opts.h" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| DSDOpts::DSDOpts() | ||||
|  | ||||
| @ -17,7 +17,7 @@ | ||||
| #ifndef DSDPLUS_DSD_OPTS_H_ | ||||
| #define DSDPLUS_DSD_OPTS_H_ | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| class DSDOpts | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
| 
 | ||||
| #include "dsd_state.h" | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| DSDState::DSDState() | ||||
|  | ||||
| @ -22,7 +22,7 @@ | ||||
| #include <string.h> | ||||
| #include <mbelib.h> | ||||
| 
 | ||||
| namespace DSDPlus | ||||
| namespace DSDplus | ||||
| { | ||||
| 
 | ||||
| class DSDState | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user