#include "proto.h" /************************************************************************** 3DigRF Protocol (Lauterbach Datentechnik GmbH) *************************************************************************/ ///////////////////////////////////////////////// // Definition of the types // ///////////////////////////////////////////////// //! Definition for the local variables typedef struct { unsigned int SysClk; //! DigRf System Clock unsigned int DigRfClock; //! DigRf Clock unsigned int DigRfClockDef; //! DigRf Default Clock, start value for analysis unsigned int DigRfSignal; //! DigRf input signal (RX,TX,RXn,TXn) unsigned int DigRfEnable; //! DigRf enable signal (ENA,ENAn,NONE) unsigned int drawchannel; //! ChannelNo, to draw unsigned int drawwave; //! use SamplingTimestamp for drawing unsigned int logchan; //! DigRF Logic Channel for Chart display unsigned int BitCodingI; //! DigRF BitCoding: PayLoad I-Data unsigned int BitCodingQ; //! DigRF BitCoding: PayLoad Q-Data unsigned int BitCodingMask; //! DigRF BitCoding: PayLoad BitMask } DigRfParameters; //! Definition of the variables for the level 1 output typedef struct { protoTime timestamp; /* Time of the DigRF activity */ unsigned short qdata; /* DigRF Payload Q-Data */ unsigned short idata; /* DigRF Payload of I-Data or Control-Frame */ unsigned char header; /* DigRF Header */ unsigned char recordtype; /* */ unsigned char status; /* Was the message successfully decoded and complete? */ } stageOneEntry; //! Definition of the variables for the level 2 output typedef struct { protoTime timestamp; /* Time of the DigRF activity */ unsigned short qdata; /* DigRF Payload Q-Data */ unsigned short idata; /* DigRF Payload I-Data */ unsigned char header; /* DigRF Header */ unsigned char recordtype; /* */ unsigned char status; /* Was the message successfully decoded and complete? */ } stageTwoEntry; ///////////////////////////////////////////////// //! Every function except PROTO_Init is defined static because they are only used intern ///////////////////////////////////////////////// ///////////////////////////////////////////////// //! Stage one: analyzing raw trace date ///////////////////////////////////////////////// static protoSizeT PROTOAPI processStageOne(protoContext context, protoPtr arrayOut, protoSizeT arrayOutSize, protoPtr arrayIn, protoSizeT arrayInSize, protoPtr localdata) { ///////////////////////////////////////////////// //! Definition of the variables ///////////////////////////////////////////////// #define TSUres 78125 // T32 Timestamp resulution (fempto seconds) #define SamplePeriodRX25G 1846153846 // femptoSeconds: Rx-Channel- A/B SamplingPeriod (48/13us /2 oversampling) #define SamplePeriodRX3G 130208333 // femptoSeconds: Rx-Channel- C/D SamplingPeriod (10000/38400us /2 oversampling) #define SamplePeriodTX3G 260416666 // femptoSeconds: Tx-Channel- C SamplingPeriod (10000/38400us /1 oversampling) #define RecordTypeMask 0x7F #define StatusOK 0x7F #define StartOfFrame 0 #define SizeError 1 #define FrameEnd 2 #define NotComplete 3 #define SysClockON 4 #define SysClockOFF 5 #define DataRecord 6 #define EndOfRecording 7 #define DataRecordIQ 8 #define edge 10 #define ErrorTimestamp 11 #define SleepReq 0x80 #define LowSpeed 0 #define MidSpeed 1 #define HiSpeed 2 #define LC_INTERFACE_CONTROL 0 #define LC_TAS_UNSOL_STATUS 1 #define LC_RFIC_CONTROL_READ 2 #define LC_RES_CTS 3 #define LC_DATA_CH_A 4 #define LC_DATA_CH_B 5 #define LC_DATA_CH_C 6 #define LC_DATA_CH_D 7 #define LC_DATA_CH_E 8 #define LC_DATA_CH_F 9 #define LC_DATA_CH_G 10 #define LC_DATA_CH_H 11 #define LogchanMask 0xf<<1 #define Size8 0 #define Size32 1<<5 #define Size64 2<<5 #define Size96 3<<5 #define Size128 4<<5 #define Size256 5<<5 #define Size512 6<<5 #define Size0 7<<5 #define SizeMask 7<<5 #define DigRfRX 0 #define DigRfTX 1 #define DigRfRXn 2 #define DigRfTXn 3 #define DigRfENA 0 #define DigRfENAn 1 #define DigRfNOENA 2 unsigned int DigRfSig, SysClkEna; protoWord64 DigRFdata; //! DigRF bitstream unsigned int DigRFcnt, //! Number of detected DigRF bits DigRFheader; float DigRFperiod; //!< fempto seconds protoSizeT result; protoSizeT index=0; unsigned int dataIndex=0, PayloadSize=0, prevBit, //!< Value of the stored bit actSysClkEna, actBit, //!< Value of the signal recordtype, i=0; //!< Both are important for the data output int chan[3]; unsigned int amount; // Counter to discover the amount of 3DigRF bits unsigned int PayloadCnt; // I/Q data count per Frame unsigned int SamplePeriod; // DigRF Sampling Periode unsigned int error; int sofDetected = 0, // Boolean to mark SOF detection headDetected = 0; // Boolean to mark HEADER detection protoTime actTime, // Timestamp of raw trace data record prevTime, // Timestamp to reduce the risk of wrong interpreting a spike frameTime; // Timestamp of FrameHeader DigRfParameters *params = (DigRfParameters *) localdata; stageOneEntry *stageOneArray; // Pointer to array which will contain the output records stageOneArray = (stageOneEntry *) arrayOut; // type cast to the used output record type //! BreakCode for Debugging of DLL //__asm int 3; //! Init search algorithm sofDetected = 0; headDetected = 0; DigRFcnt = 0; DigRFdata = 0; params->BitCodingI = 8; params->BitCodingQ = 0; params->BitCodingMask = 0xff; //default settings // read first record result = PROTO_ReadTrace(context, -1, &actTime, chan); if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfTX)) DigRfSig = chan[0]; else DigRfSig = !chan[0]; actBit = DigRfSig; prevTime = actTime, prevBit = actBit; if (params->DigRfEnable == DigRfENA) SysClkEna = chan[1]; else if (params->DigRfEnable == DigRfENAn) SysClkEna = !chan[1]; else SysClkEna = 1; actSysClkEna = SysClkEna; // check if first record is ShutDown mode if (actSysClkEna) params->DigRfClock = params ->DigRfClockDef; // set DigRfClock=DefaultClock else { params ->DigRfClock = params->SysClk / 4; // set DigRfClock=SysClk/4 stageOneArray[index].timestamp = actTime; // generate ShutDown trace record stageOneArray[index].status = SysClockOFF; index++; } DigRFperiod = (float) 1000000000000000 / params->DigRfClock; //!< fempto seconds ///////////////////////////////////////////////// While Start Sequence ///////////////////////////////////////////////// while (result >= 0) { //! Search for Signal-Edge result = PROTO_FindTrace(context, -1, 0, &actTime, chan); if (result < 0) { if (result != PROTO_PROCESS_ENDOFTRACE) return result; } if (!actSysClkEna) continue; if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfTX)) DigRfSig = chan[0]; else DigRfSig = !chan[0]; actBit = DigRfSig; if (params->DigRfEnable == DigRfENA) SysClkEna = chan[1]; else if (params->DigRfEnable == DigRfENAn) SysClkEna = !chan[1]; else SysClkEna = 1; actSysClkEna = SysClkEna; //! calculate number of DigRf bits //------------------ /* Timestamp rounding to 0.5ns resolution */ amount = (unsigned int)((float)((actTime-prevTime) * TSUres + 250000) / 500000) * 500000; /* calculation of DigRfBits with 45% DigRfBit rounding */ amount = (unsigned int)((float)(amount) / DigRFperiod + 0.45); if (amount > 1200) // maximum number of DigRf Bits with same signal level (idle period) amount=1200; if (amount==0) // minimum number of DigRf Bits amount=1; //! Found valid edge //------------------ //! build DigRF bit stream while (amount>0) { DigRFdata = (DigRFdata<<1) | prevBit; DigRFcnt++; amount--; //! check PAYLOAD if (sofDetected && headDetected && (DigRFcnt==(params->BitCodingI + params->BitCodingQ + 1))) { stageOneArray[index].timestamp = actTime - (protoTime)((amount+1) * DigRFperiod / TSUres); stageOneArray[index].qdata = (unsigned short) ((params->BitCodingQ != 0) ? ((DigRFdata>>1) & params->BitCodingMask) : 0); stageOneArray[index].idata = (unsigned short) ((DigRFdata>>(1 + params->BitCodingQ)) & params->BitCodingMask); stageOneArray[index].status = StatusOK; stageOneArray[index].recordtype = recordtype; stageOneArray[index].header = (params->logchan) << 1; // use SamplingTimestamp for waveform drawing? if (params->drawwave) { stageOneArray[index].timestamp = frameTime + (protoTime)((float)PayloadCnt * (float)SamplePeriod / (float)TSUres); PayloadCnt++; } if (dataIndex==0) // copy first byte of PAYLOAD to CONTROL-Record stageOneArray[index-1].idata = stageOneArray[index].idata; dataIndex = dataIndex + params->BitCodingI + params->BitCodingQ; DigRFcnt = 1; if (dataIndex >= PayloadSize) // Frame complete! { PayloadSize = 0; sofDetected = 0; headDetected = 0; dataIndex = 0; params->BitCodingI = 8; params->BitCodingQ = 0; params->BitCodingMask = 0xff; //default settings if ((stageOneArray[index].header & 0xFE) == 0) // size==Size8, logchan==0 // Check for Clock switching { switch (stageOneArray[index].idata) { case 0x08: // TxData SLOW if ((params->DigRfSignal == DigRfTX) || (params->DigRfSignal == DigRfTXn)) params->DigRfClock = params->SysClk / 4; break; case 0x20: // RxData SLOW if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfRXn)) params->DigRfClock = params->SysClk / 4; break; case 0x40: // RxData MEDIUM if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfRXn)) params->DigRfClock = params->SysClk; break; case 0x10: // TxData FAST if ((params->DigRfSignal == DigRfTX) || (params->DigRfSignal == DigRfTXn)) params->DigRfClock = 312000000; break; case 0x80: // RxData FAST if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfRXn)) params->DigRfClock = 312000000; break; default: break; } DigRFperiod = (float) 1000000000000000 / params->DigRfClock; //!< fempto seconds } // Used to establish a proper chart visualisation and the beginning of idle-level index++; if ((int)index>=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted stageOneArray[index].timestamp = actTime - (protoTime)(amount * DigRFperiod / TSUres); stageOneArray[index].recordtype = FrameEnd; stageOneArray[index].status = FrameEnd; if (DigRFdata & 0x1) stageOneArray[index].recordtype |= SleepReq; index++; if ((int)index>=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted } else { index++; if ((int)index>=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted } } //! check SOF if (!sofDetected && (DigRFcnt>=16)) { if ((DigRFdata & 0x1ffff) == 0xA84B) { sofDetected = 1; DigRFcnt=16; stageOneArray[index].timestamp = actTime - (protoTime)((amount+16) * DigRFperiod / TSUres) + (protoTime)((DigRFperiod / TSUres) / 2); stageOneArray[index].recordtype = StartOfFrame; } else if (amount>4) // optimize SOF search, skip long periods of no signal activity { if ((DigRFdata & 0xf) == 0x0) { amount = 0; DigRFcnt = 1; DigRFdata = 0; } else if ((DigRFdata & 0xf) == 0xf) { amount = 0; DigRFcnt = 1; DigRFdata = 1; } } } //! check HEADER if (sofDetected && !headDetected && (DigRFcnt==24)) { headDetected = 1; DigRFheader = (unsigned long)(DigRFdata & 0xFF); // Get PayloadSize switch (DigRFheader & SizeMask) { case Size8: PayloadSize = 8; break; case Size32: PayloadSize = 32; break; case Size64: PayloadSize = 64; break; case Size96: PayloadSize = 96; break; case Size128: PayloadSize = 128; break; case Size256: PayloadSize = 256; break; case Size512: PayloadSize = 512; break; default: PayloadSize = 0; stageOneArray[index].status = SizeError; break; } DigRFcnt = 0; if ((params->DigRfSignal == DigRfTX) || (params->DigRfSignal == DigRfTXn)) stageOneArray[index].header = DigRFheader; else stageOneArray[index].header = DigRFheader & ~0x1; // mask cts_bit params->logchan = (DigRFheader & LogchanMask) >> 1; // bit-coding default settings params->BitCodingI = 8; params->BitCodingQ = 0; params->BitCodingMask = 0xff; recordtype = DataRecord; SamplePeriod = 0; error = StatusOK; // bit-coding if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfRXn)) { switch (params->logchan) { case LC_DATA_CH_A: if ((stageOneArray[index].header & SizeMask) == Size256) { params->BitCodingI = 16; params->BitCodingQ = 16; params->BitCodingMask = 0xffff; recordtype = DataRecordIQ; SamplePeriod = SamplePeriodRX25G; } else error = SizeError; break; case LC_DATA_CH_B: if ((stageOneArray[index].header & SizeMask) == Size256) { params->BitCodingI = 16; params->BitCodingQ = 16; params->BitCodingMask = 0xffff; recordtype = DataRecordIQ; SamplePeriod = SamplePeriodRX25G; } else error = SizeError; break; case LC_DATA_CH_C: if ((stageOneArray[index].header & SizeMask) == Size256) { params->BitCodingI = 8; params->BitCodingQ = 8; params->BitCodingMask = 0xff; recordtype = DataRecordIQ; SamplePeriod = SamplePeriodRX3G; } else error = SizeError; break; case LC_DATA_CH_D: if ((stageOneArray[index].header & SizeMask) == Size256) { params->BitCodingI = 8; params->BitCodingQ = 8; params->BitCodingMask = 0xff; recordtype = DataRecordIQ; SamplePeriod = SamplePeriodRX3G; } else error = SizeError; break; } } else { switch (params->logchan) { case LC_DATA_CH_A: if ((stageOneArray[index].header & SizeMask) == Size256) { params->BitCodingI = 4; params->BitCodingQ = 0; params->BitCodingMask = 0xf; recordtype = DataRecord; SamplePeriod = 0; } else error = SizeError; break; case LC_DATA_CH_C: if ((stageOneArray[index].header & SizeMask) == Size96) { params->BitCodingI = 12; params->BitCodingQ = 12; params->BitCodingMask = 0xfff; recordtype = DataRecordIQ; SamplePeriod = SamplePeriodTX3G; } else error = SizeError; break; } } if (error==SizeError) { PayloadSize = 0; stageOneArray[index].status = SizeError; } // anything to draw? if (params->drawchannel != 0) { if (params->drawchannel == params->logchan) // drawchannel == header? { frameTime = stageOneArray[index].timestamp; PayloadCnt = 0; index++; } else // skip this frame { sofDetected = 0; headDetected = 0; } } else { index++; } if ((int)index>=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted } } prevTime = actTime; prevBit = actBit; ///////////////////////////////////////////////// While End Sequence ///////////////////////////////////////////////// } stageOneArray[index].timestamp = actTime; stageOneArray[index].recordtype = EndOfRecording; index++; if ((int)index>=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted return index; } static void displayStageOne(protoContext context, protoPtr pdata, protoPtr localdata) { unsigned int i=0,k=0; stageOneEntry *entry; //!< Loading the array entry=(stageOneEntry *)pdata; if ((entry->recordtype & RecordTypeMask) == DataRecordIQ) { PROTO_Printf(context, "I=0x%04x, Q=0x%04x",entry->idata,entry->qdata); } else if ((entry->recordtype & RecordTypeMask) == DataRecord) { PROTO_Printf(context, "I=0x%02x",entry->idata); } } ////////////////////////////////////////////////////////////////// //! Stage two: Calculation (copies the needed data from StageOne) ////////////////////////////////////////////////////////////////// static protoSizeT PROTOAPI processStageTwo(protoContext context, protoPtr arrayOut, protoSizeT arrayOutSize, protoPtr arrayIn, protoSizeT arrayInSize, protoPtr localdata) { int i=0,k=0; stageOneEntry *stageOneArray; //!< Pointer to array which will contain the input records stageTwoEntry *stageTwoArray; //!< Pointer to array which will contain the output records stageOneArray = (stageOneEntry *) arrayIn; stageTwoArray = (stageTwoEntry *) arrayOut; //! Copying stateOneArray to stageTwoArray, no extra calculation required while (k=arrayOutSize) //! If there is no free space to store more return PROTO_PROCESS_OUTOFMEMORY; //! records, the processing is aborted } k++; } return i; //!< Important for displayStageTwo } ////////////////////////////////////////////////////////////////// //! Stage two: Display ////////////////////////////////////////////////////////////////// static void DATA_msg (protoContext context, protoPtr pdata) { unsigned int i=0,k=0; unsigned int PayloadSize; stageOneEntry *entry; //!< Loading the array entry=(stageOneEntry *)pdata; switch (entry->header & SizeMask) { case Size8: PayloadSize = 8; break; case Size32: PayloadSize = 32; break; case Size64: PayloadSize = 64; break; case Size96: PayloadSize = 96; break; case Size128: PayloadSize = 128; break; case Size256: PayloadSize = 256; break; case Size512: PayloadSize = 512; break; default: PayloadSize = 0; break; } PROTO_Printf(context, "SIZ=%3d, ", PayloadSize); PROTO_Printf(context, "CTS=%1d ", entry->header & 0x1); } static void displayStageTwo(protoContext context, protoPtr pdata, protoPtr localdata) { unsigned int i=0,k=0; stageTwoEntry *entry; //!< Loading the array entry=(stageTwoEntry *)pdata; switch (entry->status) { case SysClockOFF: PROTO_Printf(context, "---------- ShutDown ----------"); PROTO_Control(context, PROTO_CONTROL_LINEFEED); return; break; case SysClockON: PROTO_Printf(context, "---------- SysClockEnable ----------"); PROTO_Control(context, PROTO_CONTROL_LINEFEED); return; break; case SizeError: PROTO_Control(context, PROTO_ATTRIBUTE_ERROR); PROTO_Puts(context, "---------- Error in header: SizeError ----------"); PROTO_Control(context, PROTO_CONTROL_LINEFEED); break; case NotComplete: PROTO_Control(context, PROTO_CONTROL_LINEFEED); PROTO_Control(context, PROTO_ATTRIBUTE_ERROR); PROTO_Puts(context, "Frame Not Complete"); return; break; case ErrorTimestamp: PROTO_Control(context, PROTO_CONTROL_LINEFEED); PROTO_Control(context, PROTO_ATTRIBUTE_ERROR); PROTO_Puts(context, "Error Timestamp: call technical support"); return; default: break; } switch (entry->recordtype & RecordTypeMask) { case EndOfRecording: PROTO_Control(context, PROTO_CONTROL_LINEFEED); PROTO_Puts(context, "End Of Recording"); break; case FrameEnd: if (entry->recordtype & SleepReq) { PROTO_Printf(context, "---------- sleep ----------"); PROTO_Control(context, PROTO_CONTROL_LINEFEED); } break; default: switch ((entry->header & LogchanMask) >> 1) { case LC_INTERFACE_CONTROL: if ((entry->header & SizeMask) == Size8) { PROTO_Control(context, PROTO_ATTRIBUTE_BOLD); switch (entry->idata) { case 0x00: PROTO_Puts(context, "Control : PING "); break; case 0x01: PROTO_Puts(context, "Control : Reserved "); break; case 0x02: PROTO_Puts(context, "Control : RF Clock START "); break; case 0x04: PROTO_Puts(context, "Control : RF Clock STOP "); break; case 0x08: PROTO_Puts(context, "Control : TxData SLOW "); break; case 0x10: PROTO_Puts(context, "Control : TxData FAST "); break; case 0x20: PROTO_Puts(context, "Control : RxData SLOW "); break; case 0x40: PROTO_Puts(context, "Control : RxData MEDIUM "); break; case 0x80: PROTO_Puts(context, "Control : RxData FAST "); break; case 0x31: PROTO_Puts(context, "Control : RxData ENABLE "); break; case 0x32: PROTO_Puts(context, "Control : RxData DISABLE "); break; case 0x34: PROTO_Puts(context, "Control : Clock Test Mode"); break; case 0x38: PROTO_Puts(context, "Control : Loopback OFF "); break; case 0xFF: PROTO_Puts(context, "Control : Loopback ON "); break; default: PROTO_Puts(context, "Control : SysClk ENABLE "); break; } } else { PROTO_Control(context, PROTO_ATTRIBUTE_ERROR); PROTO_Puts(context, "Control : Size Error "); DATA_msg(context, entry); } break; case LC_TAS_UNSOL_STATUS: PROTO_Printf(context, "AccStrobe: "); DATA_msg(context, entry); break; case LC_RFIC_CONTROL_READ: PROTO_Printf(context, "RF Ctrl : "); DATA_msg(context, entry); break; case LC_RES_CTS: PROTO_Printf(context, "CTS Trans: "); DATA_msg(context, entry); break; case LC_DATA_CH_A: PROTO_Printf(context, "Channel A: "); DATA_msg(context, entry); break; case LC_DATA_CH_B: PROTO_Printf(context, "Channel B: "); DATA_msg(context, entry); break; case LC_DATA_CH_C: PROTO_Printf(context, "Channel C: "); DATA_msg(context, entry); break; case LC_DATA_CH_D: PROTO_Printf(context, "Channel D: "); DATA_msg(context, entry); break; case LC_DATA_CH_E: PROTO_Printf(context, "Channel E: "); DATA_msg(context, entry); break; case LC_DATA_CH_F: PROTO_Printf(context, "Channel F: "); DATA_msg(context, entry); break; case LC_DATA_CH_G: PROTO_Printf(context, "Channel G: "); DATA_msg(context, entry); break; case LC_DATA_CH_H: PROTO_Printf(context, "Channel H: "); DATA_msg(context, entry); break; default: PROTO_Printf(context, "Reserved : "); DATA_msg(context, entry); break; } break; } } ///////////////////////////////////////////////// //! Function to use the "Chart" command ///////////////////////////////////////////////// const char * PROTO_Chart(protoContext context, protoPtr arrayIn, protoPtr localdata) { DigRfParameters *params = (DigRfParameters *) localdata; //!< Pointer to array of local parameters stageOneEntry *stageOneArray = (stageOneEntry *)arrayIn; //!< Pointer to array which will contain the input records static const char *logchan[] = {"CONTROL", "STROBE", "RF CTRL", "RVD/CTS", "CHAN-A", "CHAN-B", "CHAN-C", "CHAN-D", "CHAN-E", "CHAN-F", "CHAN-G", "CHAN-H", "LCT-C", "LCT-D", "LCT-E", "LCT-F", "idle", "sleep", "end-of-recording", "error"}; if (stageOneArray->status==SizeError) return logchan[19]; if (stageOneArray->recordtype & SleepReq) return logchan[17]; switch (stageOneArray->recordtype & RecordTypeMask) { case StartOfFrame: case DataRecord: case DataRecordIQ: return logchan[(stageOneArray->header & LogchanMask) >> 1]; break; case FrameEnd: return logchan[16]; break; case EndOfRecording: return logchan[18]; break; default: return logchan[18]; break; } } ///////////////////////////////////////////////// //! Function to use the "ProfileChart" command ///////////////////////////////////////////////// const char * PROTO_ProfileChart(protoContext context, protoPtr arrayIn, int * color, protoPtr localdata) { DigRfParameters *params = (DigRfParameters *) localdata; //!< Pointer to array of local parameters stageOneEntry *stageOneArray = (stageOneEntry *)arrayIn; //!< Pointer to array which will contain the input records static const char *logchan[] = {"CONTROL", "STROBE", "RF CTRL", "RVD/CTS", "CHAN-A", "CHAN-B", "CHAN-C", "CHAN-D", "CHAN-E", "CHAN-F", "CHAN-G", "CHAN-H", "LCT-C", "LCT-D", "LCT-E", "LCT-F", "idle", "sleep", "end-of-recording", "error"}; static const int logcolor[] = { 9, 10, 13, 14, 1, 2, 3, 4, 5, 6, 7, 12, 8, 8, 8, 8, 0, 11, 15, 15 }; if (stageOneArray->status==SizeError) { *color = logcolor[19]; return logchan[19]; } if (stageOneArray->recordtype & SleepReq) { *color = logcolor[17]; return logchan[17]; } switch (stageOneArray->recordtype & RecordTypeMask) { case StartOfFrame: case DataRecord: case DataRecordIQ: *color = logcolor[(stageOneArray->header & LogchanMask) >> 1]; return logchan[(stageOneArray->header & LogchanMask) >> 1]; break; case FrameEnd: *color = logcolor[16]; return logchan[16]; break; case EndOfRecording: *color = logcolor[18]; return logchan[18]; break; default: *color = logcolor[18]; return logchan[18]; break; } } ///////////////////////////////////////////////// //! Function to use the "Draw" command ///////////////////////////////////////////////// int PROTO_Draw(protoContext context, protoPtr pdata, protoPtr localdata, int * presult) { DigRfParameters *params = (DigRfParameters *) localdata; stageOneEntry *entry ; //!< Loading the array entry=(stageOneEntry *)pdata; if (((entry->recordtype & RecordTypeMask)==DataRecord) || ((entry->recordtype & RecordTypeMask)==DataRecordIQ)) { if ((params->DigRfSignal == DigRfRX) || (params->DigRfSignal == DigRfRXn)) { switch ((entry->header & LogchanMask) >> 1) { case LC_DATA_CH_A: if (params->drawchannel==LC_DATA_CH_A) { presult[0] = (entry->idata + 0x8000) & 0xFFFF; presult[1] = (entry->qdata + 0x8000) & 0xFFFF; return 0x3; } break; case LC_DATA_CH_B: if (params->drawchannel==LC_DATA_CH_B) { presult[0] = (entry->idata + 0x8000) & 0xFFFF; presult[1] = (entry->qdata + 0x8000) & 0xFFFF; return 0x03; } break; case LC_DATA_CH_C: if (params->drawchannel==LC_DATA_CH_C) { presult[0] = (entry->idata + 0x80) & 0xFF; presult[1] = (entry->qdata + 0x80) & 0xFF; return 0x03; } break; case LC_DATA_CH_D: if (params->drawchannel==LC_DATA_CH_D) { presult[0] = (entry->idata + 0x80) & 0xFF; presult[1] = (entry->qdata + 0x80) & 0xFF; return 0x03; } break; default: return 0; } } else { if (((entry->header & LogchanMask) >> 1) == LC_DATA_CH_C) { presult[0] = (entry->idata + 0x800) & 0xFFF; presult[1] = (entry->qdata + 0x800) & 0xFFF; return 0x03; } else return 0; } } return 0; } ///////////////////////////////////////////////// //! Function to allow sharing of processed data ///////////////////////////////////////////////// static int PROTOAPI PROTO_Share(protoContext context, protoPtr sharedata, protoPtr localdata) { DigRfParameters *local, *share; local = ((DigRfParameters *) localdata); share = ((DigRfParameters *) sharedata); if (local->SysClk == share->SysClk && local->DigRfClockDef == share->DigRfClockDef && local->DigRfSignal == share->DigRfSignal && local->DigRfEnable == share->DigRfEnable && local->drawchannel == share->drawchannel && local->drawwave == share->drawwave && local->logchan == share->logchan) { local->DigRfClock = share->DigRfClock; local->BitCodingI = share->BitCodingI; local->BitCodingQ = share->BitCodingQ; local->BitCodingMask = share->BitCodingMask; return 1; } return 0; } ///////////////////////////////////////////////// //! PROTO_Init ///////////////////////////////////////////////// int PROTOAPI PROTO_Init(protoContext context, int command) { int clkmode; int sysclk; int valin; int DigRFchannel; int DigRFenable; DigRfParameters *params; if (PROTO_RequestVersion(context, 2) != PROTO_OK) { PROTO_Puts(context, "Requires newer trace32 version"); return PROTO_FAIL; } params = (DigRfParameters *)PROTO_Alloc(context,sizeof(DigRfParameters)); // init drawchannel params->drawchannel = 0; params->drawwave = 0; // select RX or TX protocol PROTO_Parse(context, (protoPtr) &DigRFchannel, "RX,TX,RXn,TXn", PROTO_PARSE_SELECTION); params->DigRfSignal = DigRFchannel; // define target RX/TX signal, ENABLE signal PROTO_Parse(context, (protoPtr) 0, "", PROTO_PARSE_CHANNEL); /* DigRF TX or RX Channel */ // select ENABLE PROTO_Parse(context, (protoPtr) &DigRFenable, "ENA,ENAn,NONE", PROTO_PARSE_SELECTION); params->DigRfEnable = DigRFenable; if ((DigRFenable == 0) || (DigRFenable == 1)) PROTO_Parse(context, (protoPtr) 0, "", PROTO_PARSE_CHANNEL); /* DigRF Enable Channel */ // define DigRF SystemClock PROTO_Parse(context, (protoPtr) &sysclk, "19MHz,26MHz,38MHz", PROTO_PARSE_SELECTION); if (sysclk == 0) params ->SysClk = 19200000; else if (sysclk == 1) params ->SysClk = 26000000; else params ->SysClk = 38400000; // define default clockmode PROTO_Parse(context, (protoPtr) &clkmode, "slow,mid,high", PROTO_PARSE_SELECTION); if (clkmode == 0) params ->DigRfClockDef = params ->SysClk / 4; else if (clkmode == 1) params ->DigRfClockDef = params ->SysClk; else params ->DigRfClockDef = 312000000; // define DRAW channels if (command == PROTO_COMMAND_DRAW) { if ((DigRFchannel==DigRfRX)||(DigRFchannel==DigRfRXn)) { PROTO_Parse(context, (protoPtr) &valin, "ChanA,ChanB,ChanC,ChanD,ChanAWave,ChanBWave,ChanCWave,ChanDWave,", PROTO_PARSE_SELECTION|PROTO_PARSE_OPTIONAL); params->drawchannel = (valin & 0x3) + LC_DATA_CH_A; params->drawwave = !!(valin & 0x4); } else { PROTO_Parse(context, (protoPtr) &valin, "ChanC,ChanCWave", PROTO_PARSE_SELECTION|PROTO_PARSE_OPTIONAL); params->drawchannel = (valin+2 & 0x3) + LC_DATA_CH_A; params->drawwave = !!(valin & 0x1); } } ///////////////////////////////////////////////// //! Register callback functions ///////////////////////////////////////////////// PROTO_RegisterProcessCallback(context, processStageOne, (protoPtr) params, sizeof(stageOneEntry), 1); PROTO_RegisterProcessCallback(context, processStageTwo, (protoPtr) params, sizeof(stageTwoEntry), 2); PROTO_RegisterDisplayCallback(context, displayStageOne, (protoPtr) params, 1); PROTO_RegisterDisplayCallback(context, displayStageTwo, (protoPtr) params, 2); PROTO_RegisterChartCallback(context, PROTO_Chart, (protoPtr) params, 1); PROTO_RegisterProfileChartCallback(context, PROTO_ProfileChart, (protoPtr) params, 1); PROTO_RegisterDrawCallback(context, PROTO_Draw, (protoPtr) params, 1, 6, 0, 255); PROTO_RegisterShareCallback(context, PROTO_Share, (protoPtr) params, 0); PROTO_SetDefaultLevel(context, 1); return PROTO_OK; }