public static DemodState EASInit(DemodState s) { // NOTE: Percision differences between C# and C s.eas_2 = new State1(); s.eas = new State2(); float f; int i; for (f = 0, i = 0; i < CORRLEN; i++) { eascorr_mark_i[i] = (float)Math.Cos(f); eascorr_mark_q[i] = (float)Math.Sin(f); f += (float)(2.0 * Math.PI * FREQ_MARK / FREQ_SAMP); } for (f = 0, i = 0; i < CORRLEN; i++) { eascorr_space_i[i] = (float)Math.Cos(f); eascorr_space_q[i] = (float)Math.Sin(f); f += (float)(2.0 * Math.PI * FREQ_SPACE / FREQ_SAMP); } return(s); }
public static DemodState EASDemod(DemodState s, float[] fbuffer, int length) { float f; float dll_gain; int idx = 0; if (s.eas_2.subsamp != 0) { int numfill = SUBSAMP - (int)s.eas_2.subsamp; if (length < numfill) { s.eas_2.subsamp += (uint)length; return(s); } idx += numfill; length -= numfill; s.eas_2.subsamp = 0; } while (true) { length -= SUBSAMP; if (length < SUBSAMP) { break; } idx += SUBSAMP; f = (float)Math.Pow(Mac(fbuffer, idx, eascorr_mark_i, CORRLEN), 2.0) + (float)Math.Pow(Mac(fbuffer, idx, eascorr_mark_q, CORRLEN), 2.0) - (float)Math.Pow(Mac(fbuffer, idx, eascorr_space_i, CORRLEN), 2.0) - (float)Math.Pow(Mac(fbuffer, idx, eascorr_space_q, CORRLEN), 2.0); s.eas_2.dcd_shreg <<= 1; s.eas_2.dcd_shreg |= (f > 0 ? (uint)1 : (uint)0); if (f > 0 && s.eas_2.dcd_integrator < INTEGRATOR_MAXVAL) { s.eas_2.dcd_integrator += 1; } else if (f < 0 && s.eas_2.dcd_integrator > -INTEGRATOR_MAXVAL) { s.eas_2.dcd_integrator -= 1; } dll_gain = 0.5F; if (((s.eas_2.dcd_shreg ^ (s.eas_2.dcd_shreg >> 1)) & 1) == 1) { if (s.eas_2.sphase < (0x8000u - (SPHASEINC / 8))) { if (s.eas_2.sphase > SPHASEINC / 2) { s.eas_2.sphase -= (uint)Math.Min((int)(s.eas_2.sphase * dll_gain), DLL_MAX_INC); } } else { if (s.eas_2.sphase < (0x10000u - SPHASEINC / 2)) { s.eas_2.sphase += (uint)Math.Min((int)(0x10000u - s.eas_2.sphase) * dll_gain, DLL_MAX_INC); } } } s.eas_2.sphase += SPHASEINC; if (s.eas_2.sphase >= 0x10000u) { s.eas_2.sphase = 1; s.eas_2.lasts >>= 1; s.eas_2.lasts |= (byte)(((s.eas_2.dcd_integrator >= 0 ? 1 : 0) << 7) & 0x80u); if (s.eas_2.lasts == PREAMBLE && s.eas.state != EAS_L2_READING_MESSAGE) { s.eas_2.state = EAS_L1_SYNC; s.eas_2.byte_counter = 0; } else if (s.eas_2.state == EAS_L1_SYNC) { s.eas_2.byte_counter++; if (s.eas_2.byte_counter == 8) { if (CharacterAllowed((char)s.eas_2.lasts)) { s = EASFrame(s, (char)s.eas_2.lasts, idx); } else { s.eas_2.state = EAS_L1_IDLE; s = EASFrame(s, (char)0x00, idx); } s.eas_2.byte_counter = 0; } } } } s.eas_2.subsamp = (uint)length; return(s); }
static DemodState EASFrame(DemodState s, char data, int idx) { if (data != 0) { if (s.eas.state == EAS_L2_IDLE) { s.eas.state = EAS_L2_HEADER_SEARCH; } if (s.eas.state == EAS_L2_HEADER_SEARCH && s.eas.headlen < MAX_HEADER_LEN) { s.eas.head_buf[s.eas.headlen] = data; s.eas.headlen++; } if (s.eas.state == EAS_L2_HEADER_SEARCH && s.eas.headlen >= MAX_HEADER_LEN) { if (IsEqualUpToN(s.eas.head_buf, HEADER_BEGIN, s.eas.headlen)) { s.eas.state = EAS_L2_READING_MESSAGE; s.headerStart = (uint)idx; } else if (IsEqualUpToN(s.eas.head_buf, EOM, s.eas.headlen)) { s.eas.state = EAS_L2_READING_EOM; s.eomStart = (uint)idx; } else { s.eas.state = EAS_L2_IDLE; s.eas.headlen = 0; } } else if (s.eas.state == EAS_L2_READING_MESSAGE && s.eas.msglen <= MAX_MSG_LEN) { s.eas.msg_buf[s.eas.msglen] = data; s.eas.msglen++; } } else { if (s.eas.state == EAS_L2_READING_MESSAGE) { int lastHyphen = -1; for (int i = 0; i < s.eas.msg_buf.Length; i++) { if (s.eas.msg_buf[i] == '-') { lastHyphen = i; } } if (lastHyphen != -1) { s.eas.msg_buf[lastHyphen + 1] = '\0'; } string easMessage = ""; for (int i = 0; i < s.eas.msg_buf.Length; i++) { char c = s.eas.msg_buf[i]; if (c == 0) { break; } easMessage += c; s.eas.msg_buf[i] = '\0'; } s.message = $"{HEADER_BEGIN}{easMessage}"; Console.WriteLine($"EAS: {s.message}"); s.headerEnd = (uint)idx; s.headerDetected = DateTime.Now; } else if (s.eas.state == EAS_L2_READING_EOM) { Console.WriteLine($"EAS: {EOM}"); s.eomEnd = (uint)idx; s.eomDetected = DateTime.Now; } s.eas.state = EAS_L2_IDLE; s.eas.msglen = 0; s.eas.headlen = 0; } return(s); }