Add DMR calibration.

48kHz
Jonathan Naylor 2016-04-14 17:42:38 +01:00
parent 8bfff17ace
commit 51f26b1330
13 changed files with 184 additions and 46 deletions

49
CalDMR.cpp 100644
View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "CalDMR.h"
CCalDMR::CCalDMR() :
m_transmit(false)
{
}
void CCalDMR::process()
{
if (m_transmit) {
dmrTX.setCal(true);
dmrTX.process();
} else {
dmrTX.setCal(false);
}
}
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
m_transmit = data[0U] == 1U;
return 0U;
}

39
CalDMR.h 100644
View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(CALDMR_H)
#define CALDMR_H
#include "Config.h"
#include "DMRDefines.h"
class CCalDMR {
public:
CCalDMR();
void process();
uint8_t write(const uint8_t* data, uint8_t length);
private:
bool m_transmit;
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,7 +18,7 @@
#include "Config.h"
#include "Globals.h"
#include "CalRX.h"
#include "CalDStarRX.h"
#include "Utils.h"
const unsigned int BUFFER_LENGTH = 200U;
@ -33,7 +33,7 @@ const uint32_t DATA_SYNC_DATA2 = 0x00554B97U;
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
const uint8_t DATA_SYNC_ERRS = 2U;
CCalRX::CCalRX() :
CCalDStarRX::CCalDStarRX() :
m_pll(0U),
m_prev(false),
m_patternBuffer(0x00U),
@ -42,7 +42,7 @@ m_ptr(0U)
{
}
void CCalRX::samples(const q15_t* samples, uint8_t length)
void CCalDStarRX::samples(const q15_t* samples, uint8_t length)
{
for (uint16_t i = 0U; i < length; i++) {
bool bit = samples[i] < 0;
@ -65,7 +65,7 @@ void CCalRX::samples(const q15_t* samples, uint8_t length)
}
}
void CCalRX::process(q15_t value)
void CCalDStarRX::process(q15_t value)
{
m_patternBuffer <<= 1;
if (value < 0)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,15 +16,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(CALRX_H)
#define CALRX_H
#if !defined(CALDSTARRX_H)
#define CALDSTARRX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalRX {
class CCalDStarRX {
public:
CCalRX();
CCalDStarRX();
void samples(const q15_t* samples, uint8_t length);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,7 +18,7 @@
#include "Config.h"
#include "Globals.h"
#include "CalTX.h"
#include "CalDStarTX.h"
const uint8_t HEADER[] = {0x00U, 0x00U, 0x00U, 'D', 'I', 'R', 'E', 'C', 'T', ' ', ' ',
'D', 'I', 'R', 'E', 'C', 'T', ' ', ' ',
@ -28,13 +28,13 @@ const uint8_t HEADER[] = {0x00U, 0x00U, 0x00U, 'D', 'I', 'R', 'E', 'C', 'T', ' '
const uint8_t SLOW_DATA_TEXT[] = {'M', 'M', 'D', 'V', 'M', ' ', 'M', 'o', 'd', 'e', 'm', ' ', 'T', 'e', 's', 't', ' ', ' ', ' ', ' '};
CCalTX::CCalTX() :
CCalDStarTX::CCalDStarTX() :
m_transmit(false),
m_count(0U)
{
}
void CCalTX::process()
void CCalDStarTX::process()
{
dstarTX.process();
@ -162,7 +162,7 @@ void CCalTX::process()
m_count = (m_count + 1U) % (30U * 21U);
}
uint8_t CCalTX::write(const uint8_t* data, uint8_t length)
uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,15 +16,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(CALTX_H)
#define CALTX_H
#if !defined(CALDSTARTX_H)
#define CALDSTARTX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalTX {
class CCalDStarTX {
public:
CCalTX();
CCalDStarTX();
uint8_t write(const uint8_t* data, uint8_t length);

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -98,6 +99,10 @@ void CDMRTX::process()
m_state = DMRTXSTATE_CACH1;
break;
case DMRTXSTATE_CAL:
createCal();
break;
default:
createCACH(0U, 1U);
m_state = DMRTXSTATE_SLOT1;
@ -193,6 +198,13 @@ void CDMRTX::setStart(bool start)
m_count = 0U;
}
void CDMRTX::setCal(bool start)
{
m_state = start ? DMRTXSTATE_CAL : DMRTXSTATE_IDLE;
m_count = 0U;
}
void CDMRTX::writeByte(uint8_t c, uint8_t control)
{
q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U];
@ -279,6 +291,17 @@ void CDMRTX::createData(uint8_t slotIndex)
m_poPtr = 0U;
}
void CDMRTX::createCal()
{
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = 0x5FU; // +3, +3, -3, -3 pattern for deviation cal.
m_markBuffer[i] = MARK_NONE;
}
m_poLen = DMR_FRAME_LENGTH_BYTES;
m_poPtr = 0U;
}
void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
{
if (m_cachPtr >= 12U)

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -29,7 +30,8 @@ enum DMRTXSTATE {
DMRTXSTATE_SLOT1,
DMRTXSTATE_CACH1,
DMRTXSTATE_SLOT2,
DMRTXSTATE_CACH2
DMRTXSTATE_CACH2,
DMRTXSTATE_CAL
};
class CDMRTX {
@ -41,6 +43,7 @@ public:
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
void setStart(bool start);
void setCal(bool start);
void process();
@ -66,6 +69,7 @@ private:
void createData(uint8_t slotIndex);
void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex);
void createCal();
void writeByte(uint8_t c, uint8_t control);
};

View File

@ -39,7 +39,8 @@ enum MMDVM_STATE {
STATE_DSTAR = 1,
STATE_DMR = 2,
STATE_YSF = 3,
STATE_CALIBRATE = 99
STATE_DMRCAL = 98,
STATE_DSTARCAL = 99
};
#include "SerialPort.h"
@ -50,8 +51,9 @@ enum MMDVM_STATE {
#include "DMRTX.h"
#include "YSFRX.h"
#include "YSFTX.h"
#include "CalRX.h"
#include "CalTX.h"
#include "CalDStarRX.h"
#include "CalDStarTX.h"
#include "CalDMR.h"
#include "Debug.h"
#include "IO.h"
@ -85,8 +87,9 @@ extern CDMRTX dmrTX;
extern CYSFRX ysfRX;
extern CYSFTX ysfTX;
extern CCalRX calRX;
extern CCalTX calTX;
extern CCalDStarRX calDStarRX;
extern CCalDStarTX calDStarTX;
extern CCalDMR calDMR;
#endif

4
IO.cpp
View File

@ -361,11 +361,11 @@ void CIO::process()
ysfRX.samples(C4FSKVals, blockSize);
}
} else if (m_modemState == STATE_CALIBRATE) {
} else if (m_modemState == STATE_DSTARCAL) {
q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize);
calRX.samples(GMSKVals, blockSize);
calDStarRX.samples(GMSKVals, blockSize);
}
}
}

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -44,8 +45,9 @@ CDMRTX dmrTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CCalRX calRX;
CCalTX calTX;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
CCalDMR calDMR;
CSerialPort serial;
CIO io;
@ -71,8 +73,11 @@ void loop()
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
if (m_modemState == STATE_CALIBRATE)
calTX.process();
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
if (m_modemState == STATE_DMRCAL)
calDMR.process();
}
int main()

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -41,8 +42,9 @@ CDMRTX dmrTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CCalRX calRX;
CCalTX calTX;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
CCalDMR calDMR;
CSerialPort serial;
CIO io;
@ -68,7 +70,10 @@ void loop()
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
if (m_modemState == STATE_CALIBRATE)
calTX.process();
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
if (m_modemState == STATE_DMRCAL)
calDMR.process();
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2013,2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -57,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U;
const uint8_t MMDVM_DEBUG4 = 0xF4U;
const uint8_t MMDVM_DEBUG5 = 0xF5U;
const uint8_t HARDWARE[] = "MMDVM 20160412 24kHz (D-Star/DMR/System Fusion)";
const uint8_t HARDWARE[] = "MMDVM 20160413 24kHz (D-Star/DMR/System Fusion)";
const uint8_t PROTOCOL_VERSION = 1U;
@ -191,7 +192,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_CALIBRATE)
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL)
return 4U;
if (modemState == STATE_DSTAR && !dstarEnable)
return 4U;
@ -252,7 +253,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
if (modemState == m_modemState)
return 0U;
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_CALIBRATE)
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL)
return 4U;
if (modemState == STATE_DSTAR && !m_dstarEnable)
return 4U;
@ -286,8 +287,15 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dmrRX.reset();
dstarRX.reset();
break;
case STATE_CALIBRATE:
DEBUG1("Mode set to Calibrate");
case STATE_DSTARCAL:
DEBUG1("Mode set to D-Star Calibrate");
dmrIdleRX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
break;
case STATE_DMRCAL:
DEBUG1("Mode set to DMR Calibrate");
dmrIdleRX.reset();
dmrRX.reset();
dstarRX.reset();
@ -375,8 +383,10 @@ void CSerialPort::process()
break;
case MMDVM_CAL_DATA:
if (m_modemState == STATE_CALIBRATE)
err = calTX.write(m_buffer + 3U, m_len - 3U);
if (m_modemState == STATE_DSTARCAL)
err = calDStarTX.write(m_buffer + 3U, m_len - 3U);
if (m_modemState == STATE_DMRCAL)
err = calDMR.write(m_buffer + 3U, m_len - 3U);
if (err == 0U) {
sendACK();
} else {
@ -673,7 +683,7 @@ void CSerialPort::writeYSFLost()
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_CALIBRATE)
if (m_modemState != STATE_DSTARCAL)
return;
uint8_t reply[130U];