Beispiel #1
0
bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
{
  m_buffer[m_dataPtr] = sample;
  m_rssi[m_dataPtr] = rssi;

  m_bitBuffer[m_bitPtr] <<= 1;
  if (sample < 0)
    m_bitBuffer[m_bitPtr] |= 0x01U;

  if (m_state == DMORXS_NONE) {
    correlateSync(true);
  } else {

    uint16_t min  = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U;
    uint16_t max  = m_syncPtr + 1U;

    if (min >= DMO_BUFFER_LENGTH_SAMPLES)
      min -= DMO_BUFFER_LENGTH_SAMPLES;
    if (max >= DMO_BUFFER_LENGTH_SAMPLES)
      max -= DMO_BUFFER_LENGTH_SAMPLES;

    if (min < max) {
      if (m_dataPtr >= min && m_dataPtr <= max)
        correlateSync(false);
    } else {
      if (m_dataPtr >= min || m_dataPtr <= max)
        correlateSync(false);
    }
  }

  if (m_dataPtr == m_endPtr) {
    // Find the average centre and threshold values
    q15_t centre    = (m_centre[0U]    + m_centre[1U]    + m_centre[2U]    + m_centre[3U])    >> 2;
    q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2;

    uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U];
    frame[0U] = m_control;

    uint16_t ptr = m_endPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U;
    if (ptr >= DMO_BUFFER_LENGTH_SAMPLES)
      ptr -= DMO_BUFFER_LENGTH_SAMPLES;

    samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, centre, threshold);

    if (m_control == CONTROL_DATA) {
      // Data sync
      uint8_t colorCode;
      uint8_t dataType;
      CDMRSlotType slotType;
      slotType.decode(frame + 1U, colorCode, dataType);

      if (colorCode == m_colorCode) {
        m_syncCount = 0U;
        m_n         = 0U;

        frame[0U] |= dataType;

        switch (dataType) {
          case DT_DATA_HEADER:
            DEBUG4("DMRDMORX: data header found pos/centre/threshold", m_syncPtr, centre, threshold);
            writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
            writeSamples(ptr, frame[0U]);
#endif
            m_state = DMORXS_DATA;
            m_type  = 0x00U;
            break;
          case DT_RATE_12_DATA:
          case DT_RATE_34_DATA:
          case DT_RATE_1_DATA:
            if (m_state == DMORXS_DATA) {
              DEBUG4("DMRDMORX: data payload found pos/centre/threshold", m_syncPtr, centre, threshold);
              writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
              writeSamples(ptr, frame[0U]);
#endif
              m_type = dataType;
            }
            break;
          case DT_VOICE_LC_HEADER:
            DEBUG4("DMRDMORX: voice header found pos/centre/threshold", m_syncPtr, centre, threshold);
            writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
            writeSamples(ptr, frame[0U]);
#endif
            m_state = DMORXS_VOICE;
            break;
          case DT_VOICE_PI_HEADER:
            if (m_state == DMORXS_VOICE) {
              DEBUG4("DMRDMORX: voice pi header found pos/centre/threshold", m_syncPtr, centre, threshold);
              writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
              writeSamples(ptr, frame[0U]);
#endif
            }
            m_state = DMORXS_VOICE;
            break;
          case DT_TERMINATOR_WITH_LC:
            if (m_state == DMORXS_VOICE) {
              DEBUG4("DMRDMORX: voice terminator found pos/centre/threshold", m_syncPtr, centre, threshold);
              writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
              writeSamples(ptr, frame[0U]);
#endif
              reset();
            }
            break;
          default:    // DT_CSBK
            DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold);
            writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
            writeSamples(ptr, frame[0U]);
#endif
            reset();
            break;
        }
      }
    } else if (m_control == CONTROL_VOICE) {
      // Voice sync
      DEBUG4("DMRDMORX: voice sync found pos/centre/threshold", m_syncPtr, centre, threshold);
	    writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
      writeSamples(ptr, frame[0U]);
#endif
      m_state     = DMORXS_VOICE;
      m_syncCount = 0U;
      m_n         = 0U;
    } else {
      if (m_state != DMORXS_NONE) {
        m_syncCount++;
        if (m_syncCount >= MAX_SYNC_LOST_FRAMES) {
          serial.writeDMRLost(true);
          reset();
        }
      }

      if (m_state == DMORXS_VOICE) {
        if (m_n >= 5U) {
          frame[0U] = CONTROL_VOICE;
          m_n = 0U;
        } else {
          frame[0U] = ++m_n;
        }

        serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#if defined(DUMP_SAMPLES)
        writeSamples(ptr, frame[0U]);
#endif
      } else if (m_state == DMORXS_DATA) {
        if (m_type != 0x00U) {
          frame[0U] = CONTROL_DATA | m_type;
          writeRSSIData(frame);
#if defined(DUMP_SAMPLES)
          writeSamples(ptr, frame[0U]);
#endif
        }
      }
    }

    // End of this slot, reset some items for the next slot.
    m_maxCorr = 0;
    m_control = CONTROL_NONE;
  }
Beispiel #2
0
bool CDMRSlotRX::processSample(q15_t sample)
{
  m_delayPtr++;
  if (m_delayPtr < m_delay)
    return m_state != DMRRXS_NONE;

  if (m_state != DMRRXS_NONE) {
    if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr)
      io.setADCDetection(true);
    else
      io.setADCDetection(false);
  } else {
    io.setADCDetection(false);
  }

  // Ensure that the buffer doesn't overflow
  if (m_dataPtr > m_endPtr || m_dataPtr >= 900U)
    return m_state != DMRRXS_NONE;

  m_buffer[m_dataPtr] = sample;

  m_bitBuffer[m_bitPtr] <<= 1;
  if (sample < 0)
    m_bitBuffer[m_bitPtr] |= 0x01U;

  if (m_state == DMRRXS_NONE) {
    if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END)
      correlateSync(true);
  } else {
    uint16_t min = m_syncPtr - 1U;
    uint16_t max = m_syncPtr + 1U;
    if (m_dataPtr >= min && m_dataPtr <= max)
      correlateSync(false);
  }

  if (m_dataPtr == m_endPtr) {
    // Find the average centre and threshold values
    q15_t centre    = (m_centre[0U]    + m_centre[1U]    + m_centre[2U]    + m_centre[3U])    >> 2;
    q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2;

    uint8_t frame[DMR_FRAME_LENGTH_BYTES + 1U];
    frame[0U] = m_control;

    uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U;
    samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, centre, threshold);

    if (m_control == CONTROL_DATA) {
      // Data sync
      uint8_t colorCode;
      uint8_t dataType;
      CDMRSlotType slotType;
      slotType.decode(frame + 1U, colorCode, dataType);

      if (colorCode == m_colorCode) {
        m_syncCount = 0U;
        m_n         = 0U;

        frame[0U] |= dataType;

        switch (dataType) {
          case DT_DATA_HEADER:
            DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
            serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
            m_state = DMRRXS_DATA;
            m_type  = 0x00U;
            break;
          case DT_RATE_12_DATA:
          case DT_RATE_34_DATA:
          case DT_RATE_1_DATA:
            if (m_state == DMRRXS_DATA) {
              DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
              serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
              m_type = dataType;
            }
            break;
          case DT_VOICE_LC_HEADER:
            DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
            serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
            m_state = DMRRXS_VOICE;
            break;
          case DT_VOICE_PI_HEADER:
            if (m_state == DMRRXS_VOICE) {
              DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
              serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
            }
            m_state = DMRRXS_VOICE;
            break;
          case DT_TERMINATOR_WITH_LC:
            if (m_state == DMRRXS_VOICE) {
              DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
              serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
              m_state  = DMRRXS_NONE;
              m_endPtr = NOENDPTR;
            }
            break;
          default:    // DT_CSBK
            DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
            serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
            m_state  = DMRRXS_NONE;
            m_endPtr = NOENDPTR;
            break;
        }
      }
    } else if (m_control == CONTROL_VOICE) {
      // Voice sync
      DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
      serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
      m_state     = DMRRXS_VOICE;
      m_syncCount = 0U;
      m_n         = 0U;
    } else {
      if (m_state != DMRRXS_NONE) {
        m_syncCount++;
        if (m_syncCount >= MAX_SYNC_LOST_FRAMES) {
          serial.writeDMRLost(m_slot);
          m_state  = DMRRXS_NONE;
          m_endPtr = NOENDPTR;
        }
      }

      if (m_state == DMRRXS_VOICE) {
        if (m_n >= 5U) {
          frame[0U] = CONTROL_VOICE;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
          m_n = 0U;
        } else {
          frame[0U] = ++m_n;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
        }
      } else if (m_state == DMRRXS_DATA) {
        if (m_type != 0x00U) {
          frame[0U] = CONTROL_DATA | m_type;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
        }
      }
    }
  }
Beispiel #3
0
bool CDMRSlotRX::processSample(q15_t sample)
{
  // Ensure that the buffer doesn't overflow
  if (m_dataPtr > m_endPtr || m_dataPtr >= 900U)
    return m_receiving;

  m_buffer[m_dataPtr] = sample;

  // The approximate position of the sync samples, XXX to be updated later
  // XXX change range when m_endPtr is set, make it tighter.
  if (m_dataPtr >= 160U && m_dataPtr <= 530U)
    correlateSync(sample);

  if (m_dataPtr == m_endPtr) {
    uint8_t frame[DMR_FRAME_LENGTH_BYTES + 1U];
    frame[0U] = m_control;

    uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U;
    samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centre, m_threshold);

    if (m_control == 0x40U) {
      // Data sync
      uint8_t colorCode;
      uint8_t dataType;
      CDMRSlotType slotType;
      slotType.decode(frame + 1U, colorCode, dataType);

      frame[0U] |= dataType;

      switch (dataType) {
        case DT_DATA_HEADER:
        case DT_VOICE_LC_HEADER:
        case DT_VOICE_PI_HEADER:
          DEBUG4("DMRSlotRX: header for slot/color code/data type", m_slot ? 2U : 1U, colorCode, dataType);
          m_receiving = true;
          m_syncCount = 0U;
          m_n         = 0U;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
          break;
        case DT_TERMINATOR_WITH_LC:
          DEBUG3("DMRSlotRX: terminator for slot/color code", m_slot ? 2U : 1U, colorCode);
          m_receiving = false;
          m_endPtr    = 999U;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
          break;
        default:
          DEBUG4("DMRSlotRX: data sync for slot/color code/data type", m_slot ? 2U : 1U, colorCode, dataType);
          m_receiving = false;
          serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
          break;
      }
    } else if (m_control == 0x20U) {
      // Voice sync
      DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U);
      serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
      m_receiving = true;
      m_syncCount = 0U;
      m_n         = 0U;
    } else {
      // Voice data
      frame[0U] |= ++m_n;
      serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
    }
  }

  m_dataPtr++;

  return m_receiving;
}