Merge branch 'master' into devel

pull/32/head
Andy CA6JAU 8 years ago
commit 40260e5275

@ -1,6 +1,6 @@
# Building instructions
This is a detailed guide for building the firmware of MMDVM_HS from the source code. For quick instructions, please see [README.md](README.md). This software runs on STM32F103 microcontroller. You can build this code using Arduino IDE with STM32duino package, or using "make" with ARM GCC tools. Also, Arduino with 3.3 V I/O (Arduino Due and Zero) and Teensy (3.1, 3.2, 3.5 or 3.6) are supported.
This is a detailed guide for building the firmware of MMDVM_HS from the source code. For quick instructions, please see [README.md](README.md). This software runs on STM32F103 microcontroller. Also, Arduino with 3.3 V I/O (Arduino Due and Zero) and Teensy (3.1, 3.2, 3.5 or 3.6) are supported. You can build this code using Arduino IDE with Roger Clark's [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/ZUMspot) package, or using command line tools with ARM GCC tools. The preferred method under Windows is using STM32duino, and under Linux or macOS (command line) is using [STM32F10X_Lib](https://github.com/juribeparada/STM32F10X_Lib).
# Index
@ -210,6 +210,8 @@ Once the transfer is completed, press the RESET button of the board or disconnec
connect the USB cable. You will see the LED (PC13) of the blue pill blinking. Once you connect
with MMDVMHost, the LED will blink fast.
For further help with STM32duino and STM32F103 blue pill boards, please see the STM32duino [forum](http://www.stm32duino.com).
## Windows with command line
Download the source code (zip file) of MMDVM_HS from:

@ -1,6 +1,6 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
*
* 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,17 +41,25 @@ m_slot(false),
m_patternBuffer(0x00U),
m_buffer(),
m_dataPtr(0U),
m_syncPtr(0U),
m_startPtr(0U),
m_endPtr(NOENDPTR),
m_syncPtr1(0U),
m_startPtr1(0U),
m_endPtr1(NOENDPTR),
m_control1(CONTROL_NONE),
m_syncCount1(0U),
m_state1(DMRRXS_NONE),
m_n1(0U),
m_type1(0U),
m_syncPtr2(0U),
m_startPtr2(0U),
m_endPtr2(NOENDPTR),
m_control2(CONTROL_NONE),
m_syncCount2(0U),
m_state2(DMRRXS_NONE),
m_n2(0U),
m_type2(0U),
m_delayPtr(0U),
m_control(CONTROL_NONE),
m_syncCount(0U),
m_colorCode(0U),
m_delay(0U),
m_state(DMRRXS_NONE),
m_n(0U),
m_type(0U)
m_delay(0U)
{
}
@ -63,22 +71,38 @@ void CDMRSlotRX::start(bool slot)
void CDMRSlotRX::reset()
{
m_syncPtr = 0U;
m_dataPtr = 0U;
m_delayPtr = 0U;
m_control = CONTROL_NONE;
m_syncCount = 0U;
m_state = DMRRXS_NONE;
m_startPtr = 0U;
m_patternBuffer = 0U;
m_endPtr = NOENDPTR;
m_syncPtr1 = 0U;
m_control1 = CONTROL_NONE;
m_syncCount1 = 0U;
m_state1 = DMRRXS_NONE;
m_startPtr1 = 0U;
m_endPtr1 = NOENDPTR;
m_type1 = 0U;
m_n1 = 0U;
m_syncPtr2 = 0U;
m_control2 = CONTROL_NONE;
m_syncCount2 = 0U;
m_state2 = DMRRXS_NONE;
m_startPtr2 = 0U;
m_endPtr2 = NOENDPTR;
m_type2 = 0U;
m_n2 = 0U;
}
bool CDMRSlotRX::databit(bool bit)
{
uint16_t min;
uint16_t max;
m_delayPtr++;
if (m_delayPtr < m_delay)
return m_state != DMRRXS_NONE;
return (m_state1 != DMRRXS_NONE) || (m_state2 != DMRRXS_NONE);
m_buffer[m_dataPtr] = bit;
@ -86,12 +110,16 @@ bool CDMRSlotRX::databit(bool bit)
if (bit)
m_patternBuffer |= 0x01U;
if (m_state == DMRRXS_NONE) {
if (m_state1 == DMRRXS_NONE || m_state2 == DMRRXS_NONE) {
correlateSync();
} else {
uint16_t min = m_syncPtr + DMR_BUFFER_LENGTH_BITS - 2;
uint16_t max = m_syncPtr + 2;
if(m_slot) {
min = m_syncPtr2 + DMR_BUFFER_LENGTH_BITS - 2;
max = m_syncPtr2 + 2;
} else {
min = m_syncPtr1 + DMR_BUFFER_LENGTH_BITS - 2;
max = m_syncPtr1 + 2;
}
if (min >= DMR_BUFFER_LENGTH_BITS)
min -= DMR_BUFFER_LENGTH_BITS;
@ -107,144 +135,285 @@ bool CDMRSlotRX::databit(bool bit)
}
}
if (m_dataPtr == m_endPtr) {
frame[0U] = m_control;
if(m_slot)
procSlot2();
else
procSlot1();
m_dataPtr++;
bitsToBytes(m_startPtr, DMR_FRAME_LENGTH_BYTES, frame + 1U);
if (m_dataPtr >= DMR_BUFFER_LENGTH_BITS)
m_dataPtr = 0U;
if (m_control == CONTROL_DATA) {
return (m_state1 != DMRRXS_NONE) || (m_state2 != DMRRXS_NONE);;
}
void CDMRSlotRX::procSlot1()
{
if (m_dataPtr == m_endPtr1) {
frame1[0U] = m_control1;
bitsToBytes(m_startPtr1, DMR_FRAME_LENGTH_BYTES, frame1 + 1U);
if (m_control1 == CONTROL_DATA) {
// Data sync
uint8_t colorCode;
uint8_t dataType;
CDMRSlotType slotType;
slotType.decode(frame + 1U, colorCode, dataType);
slotType.decode(frame1 + 1U, colorCode, dataType);
if (colorCode == m_colorCode) {
m_syncCount = 0U;
m_n = 0U;
m_syncCount1 = 0U;
m_n1 = 0U;
frame[0U] |= dataType;
frame1[0U] |= dataType;
switch (dataType) {
case DT_DATA_HEADER:
DEBUG3("DMRSlotRX: data header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_DATA;
m_type = 0x00U;
DEBUG2("DMRSlot1RX: data header found pos", m_syncPtr1);
writeRSSIData1();
m_state1 = DMRRXS_DATA;
m_type1 = 0x00U;
break;
case DT_RATE_12_DATA:
case DT_RATE_34_DATA:
case DT_RATE_1_DATA:
if (m_state == DMRRXS_DATA) {
DEBUG3("DMRSlotRX: data payload found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_type = dataType;
if (m_state1 == DMRRXS_DATA) {
DEBUG2("DMRSlot1RX: data payload found pos", m_syncPtr1);
writeRSSIData1();
m_type1 = dataType;
}
break;
case DT_VOICE_LC_HEADER:
DEBUG3("DMRSlotRX: voice header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_VOICE;
DEBUG2("DMRSlot1RX: voice header found pos", m_syncPtr1);
writeRSSIData1();
m_state1 = DMRRXS_VOICE;
break;
case DT_VOICE_PI_HEADER:
if (m_state == DMRRXS_VOICE) {
DEBUG3("DMRSlotRX: voice pi header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
if (m_state1 == DMRRXS_VOICE) {
DEBUG2("DMRSlot1RX: voice pi header found pos", m_syncPtr1);
writeRSSIData1();
}
m_state = DMRRXS_VOICE;
m_state1 = DMRRXS_VOICE;
break;
case DT_TERMINATOR_WITH_LC:
if (m_state == DMRRXS_VOICE) {
DEBUG3("DMRSlotRX: voice terminator found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_NONE;
m_endPtr = NOENDPTR;
if (m_state1 == DMRRXS_VOICE) {
DEBUG2("DMRSlot1RX: voice terminator found pos", m_syncPtr1);
writeRSSIData1();
m_state1 = DMRRXS_NONE;
m_endPtr1 = NOENDPTR;
}
break;
default: // DT_CSBK
DEBUG3("DMRSlotRX: csbk found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_NONE;
m_endPtr = NOENDPTR;
DEBUG2("DMRSlot1RX: csbk found pos", m_syncPtr1);
writeRSSIData1();
m_state1 = DMRRXS_NONE;
m_endPtr1 = NOENDPTR;
break;
}
}
} else if (m_control == CONTROL_VOICE) {
} else if (m_control1 == CONTROL_VOICE) {
// Voice sync
DEBUG3("DMRSlotRX: voice sync found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_VOICE;
m_syncCount = 0U;
m_n = 0U;
DEBUG2("DMRSlot1RX: voice sync found pos", m_syncPtr1);
writeRSSIData1();
m_state1 = DMRRXS_VOICE;
m_syncCount1 = 0U;
m_n1 = 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_state1 != DMRRXS_NONE) {
m_syncCount1++;
if (m_syncCount1 >= MAX_SYNC_LOST_FRAMES) {
serial.writeDMRLost(0U);
m_state1 = DMRRXS_NONE;
m_endPtr1 = NOENDPTR;
}
}
if (m_state == DMRRXS_VOICE) {
if (m_n >= 5U) {
frame[0U] = CONTROL_VOICE;
m_n = 0U;
if (m_state1 == DMRRXS_VOICE) {
if (m_n1 >= 5U) {
frame1[0U] = CONTROL_VOICE;
m_n1 = 0U;
} else {
frame[0U] = ++m_n;
frame1[0U] = ++m_n1;
}
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;
writeRSSIData(frame);
serial.writeDMRData(0U, frame1, DMR_FRAME_LENGTH_BYTES + 1U);
} else if (m_state1 == DMRRXS_DATA) {
if (m_type1 != 0x00U) {
frame1[0U] = CONTROL_DATA | m_type1;
writeRSSIData1();
}
}
}
// End of this slot, reset some items for the next slot.
m_control = CONTROL_NONE;
m_control1 = CONTROL_NONE;
}
}
m_dataPtr++;
void CDMRSlotRX::procSlot2()
{
if (m_dataPtr == m_endPtr2) {
frame2[0U] = m_control2;
if (m_dataPtr >= DMR_BUFFER_LENGTH_BITS)
m_dataPtr = 0U;
bitsToBytes(m_startPtr2, DMR_FRAME_LENGTH_BYTES, frame2 + 1U);
if (m_control2 == CONTROL_DATA) {
// Data sync
uint8_t colorCode;
uint8_t dataType;
CDMRSlotType slotType;
slotType.decode(frame2 + 1U, colorCode, dataType);
if (colorCode == m_colorCode) {
m_syncCount2 = 0U;
m_n2 = 0U;
frame2[0U] |= dataType;
switch (dataType) {
case DT_DATA_HEADER:
DEBUG2("DMRSlot2RX: data header found pos", m_syncPtr2);
writeRSSIData2();
m_state2 = DMRRXS_DATA;
m_type2 = 0x00U;
break;
case DT_RATE_12_DATA:
case DT_RATE_34_DATA:
case DT_RATE_1_DATA:
if (m_state2 == DMRRXS_DATA) {
DEBUG2("DMRSlot2RX: data payload found pos", m_syncPtr2);
writeRSSIData2();
m_type2 = dataType;
}
break;
case DT_VOICE_LC_HEADER:
DEBUG2("DMRSlot2RX: voice header found pos", m_syncPtr2);
writeRSSIData2();
m_state2 = DMRRXS_VOICE;
break;
case DT_VOICE_PI_HEADER:
if (m_state2 == DMRRXS_VOICE) {
DEBUG2("DMRSlot2RX: voice pi header found pos", m_syncPtr2);
writeRSSIData2();
}
m_state2 = DMRRXS_VOICE;
break;
case DT_TERMINATOR_WITH_LC:
if (m_state2 == DMRRXS_VOICE) {
DEBUG2("DMRSlot2RX: voice terminator found pos", m_syncPtr2);
writeRSSIData2();
m_state2 = DMRRXS_NONE;
m_endPtr2 = NOENDPTR;
}
break;
default: // DT_CSBK
DEBUG2("DMRSlot2RX: csbk found pos", m_syncPtr2);
writeRSSIData2();
m_state2 = DMRRXS_NONE;
m_endPtr2 = NOENDPTR;
break;
}
}
} else if (m_control2 == CONTROL_VOICE) {
// Voice sync
DEBUG2("DMRSlot2RX: voice sync found pos", m_syncPtr2);
writeRSSIData2();
m_state2 = DMRRXS_VOICE;
m_syncCount2 = 0U;
m_n2 = 0U;
} else {
if (m_state2 != DMRRXS_NONE) {
m_syncCount2++;
if (m_syncCount2 >= MAX_SYNC_LOST_FRAMES) {
serial.writeDMRLost(1U);
m_state2 = DMRRXS_NONE;
m_endPtr2 = NOENDPTR;
}
}
return m_state != DMRRXS_NONE;
if (m_state2 == DMRRXS_VOICE) {
if (m_n2 >= 5U) {
frame2[0U] = CONTROL_VOICE;
m_n2 = 0U;
} else {
frame2[0U] = ++m_n2;
}
serial.writeDMRData(1U, frame2, DMR_FRAME_LENGTH_BYTES + 1U);
} else if (m_state2 == DMRRXS_DATA) {
if (m_type2 != 0x00U) {
frame2[0U] = CONTROL_DATA | m_type2;
writeRSSIData2();
}
}
}
// End of this slot, reset some items for the next slot.
m_control2 = CONTROL_NONE;
}
}
void CDMRSlotRX::correlateSync()
{
{
uint16_t syncPtr;
uint16_t startPtr;
uint16_t endPtr;
uint8_t control;
if (countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_DATA_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) {
m_control = CONTROL_DATA;
m_syncPtr = m_dataPtr;
control = CONTROL_DATA;
syncPtr = m_dataPtr;
m_startPtr = m_dataPtr + DMR_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
if (m_startPtr >= DMR_BUFFER_LENGTH_BITS)
m_startPtr -= DMR_BUFFER_LENGTH_BITS;
startPtr = m_dataPtr + DMR_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
if (startPtr >= DMR_BUFFER_LENGTH_BITS)
startPtr -= DMR_BUFFER_LENGTH_BITS;
m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
if (m_endPtr >= DMR_BUFFER_LENGTH_BITS)
m_endPtr -= DMR_BUFFER_LENGTH_BITS;
//DEBUG4("SYNC corr MS Data found pos/start/end:", m_dataPtr, m_startPtr, m_endPtr);
endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
if (endPtr >= DMR_BUFFER_LENGTH_BITS)
endPtr -= DMR_BUFFER_LENGTH_BITS;
if(m_slot) {
m_syncPtr2 = syncPtr;
m_startPtr2 = startPtr;
m_endPtr2 = endPtr;
m_control2 = control;
} else {
m_syncPtr1 = syncPtr;
m_startPtr1 = startPtr;
m_endPtr1 = endPtr;
m_control1 = control;
}
//DEBUG5("SYNC corr MS Data found slot/pos/start/end:", m_slot ? 2U : 1U, m_dataPtr, startPtr, endPtr);
} else if (countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) {
m_control = CONTROL_VOICE;
m_syncPtr = m_dataPtr;
m_startPtr = m_dataPtr + DMR_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
if (m_startPtr >= DMR_BUFFER_LENGTH_BITS)
m_startPtr -= DMR_BUFFER_LENGTH_BITS;
m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
if (m_endPtr >= DMR_BUFFER_LENGTH_BITS)
m_endPtr -= DMR_BUFFER_LENGTH_BITS;
control = CONTROL_VOICE;
syncPtr = m_dataPtr;
startPtr = m_dataPtr + DMR_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
if (startPtr >= DMR_BUFFER_LENGTH_BITS)
startPtr -= DMR_BUFFER_LENGTH_BITS;
//DEBUG4("SYNC corr MS Voice found pos/start/end: ", m_dataPtr, m_startPtr, m_endPtr);
endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
if (endPtr >= DMR_BUFFER_LENGTH_BITS)
endPtr -= DMR_BUFFER_LENGTH_BITS;
if(m_slot) {
m_syncPtr2 = syncPtr;
m_startPtr2 = startPtr;
m_endPtr2 = endPtr;
m_control2 = control;
} else {
m_syncPtr1 = syncPtr;
m_startPtr1 = startPtr;
m_endPtr1 = endPtr;
m_control1 = control;
}
//DEBUG5("SYNC corr MS Voice found slot/pos/start/end: ", m_slot ? 2U : 1U, m_dataPtr, startPtr, endPtr);
}
}
@ -289,17 +458,31 @@ void CDMRSlotRX::setDelay(uint8_t delay)
m_delay = delay / 5;
}
void CDMRSlotRX::writeRSSIData(uint8_t* frame)
void CDMRSlotRX::writeRSSIData1()
{
#if defined(SEND_RSSI_DATA)
uint16_t rssi = io.readRSSI();
frame1[34U] = (rssi >> 8) & 0xFFU;
frame1[35U] = (rssi >> 0) & 0xFFU;
serial.writeDMRData(0U, frame1, DMR_FRAME_LENGTH_BYTES + 3U);
#else
serial.writeDMRData(0U, frame1, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}
void CDMRSlotRX::writeRSSIData2()
{
#if defined(SEND_RSSI_DATA)
uint16_t rssi = io.readRSSI();
frame[34U] = (rssi >> 8) & 0xFFU;
frame[35U] = (rssi >> 0) & 0xFFU;
frame2[34U] = (rssi >> 8) & 0xFFU;
frame2[35U] = (rssi >> 0) & 0xFFU;
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U);
serial.writeDMRData(1U, frame2, DMR_FRAME_LENGTH_BYTES + 3U);
#else
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
serial.writeDMRData(1U, frame2, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}

@ -1,6 +1,6 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
*
* 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
@ -51,23 +51,38 @@ private:
bool m_slot;
uint64_t m_patternBuffer;
uint8_t m_buffer[DMR_BUFFER_LENGTH_BITS];
uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U];
uint16_t m_dataPtr;
uint16_t m_syncPtr;
uint16_t m_startPtr;
uint16_t m_endPtr;
uint8_t frame1[DMR_FRAME_LENGTH_BYTES + 3U];
uint16_t m_syncPtr1;
uint16_t m_startPtr1;
uint16_t m_endPtr1;
uint8_t m_control1;
uint8_t m_syncCount1;
DMRRX_STATE m_state1;
uint8_t m_n1;
uint8_t m_type1;
uint8_t frame2[DMR_FRAME_LENGTH_BYTES + 3U];
uint16_t m_syncPtr2;
uint16_t m_startPtr2;
uint16_t m_endPtr2;
uint8_t m_control2;
uint8_t m_syncCount2;
DMRRX_STATE m_state2;
uint8_t m_n2;
uint8_t m_type2;
uint16_t m_delayPtr;
uint8_t m_control;
uint8_t m_syncCount;
uint8_t m_colorCode;
uint16_t m_delay;
DMRRX_STATE m_state;
uint8_t m_n;
uint8_t m_type;
void procSlot1();
void procSlot2();
void correlateSync();
void bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer);
void writeRSSIData(uint8_t* frame);
void writeRSSIData1();
void writeRSSIData2();
};
#endif

@ -1,6 +1,6 @@
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
*
* 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
@ -46,7 +46,7 @@ const uint8_t DATA_SYNC_ERRS = 2U;
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
const uint8_t END_SYNC_ERRS = 3U;
const uint8_t END_SYNC_ERRS = 1U;
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
const uint8_t BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};

@ -2,7 +2,7 @@
This is the source code of ZUMspot/MMDVM_HS, personal hotspot (ADF7021 version of the MMDVM firmware), based on Jonathan G4KLX's [MMDVM](https://github.com/g4klx/MMDVM) software. This firmware supports D-Star, DMR, System Fusion and P25 digital modes.
This software is intended to be run on STM32F103 microcontroller. You can build this code using Arduino IDE with STM32duino package, or using "make" with ARM GCC tools. Also, Arduino with 3.3 V I/O (Arduino Due and Zero) and Teensy (3.1, 3.2, 3.5 or 3.6) are supported.
This software is intended to be run on STM32F103 microcontroller. Also, Arduino with 3.3 V I/O (Arduino Due and Zero) and Teensy (3.1, 3.2, 3.5 or 3.6) are supported. You can build this code using Arduino IDE with Roger Clark's [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/ZUMspot) package, or using command line tools with ARM GCC tools. The preferred method under Windows is using STM32duino, and under Linux or macOS (command line) is using [STM32F10X_Lib](https://github.com/juribeparada/STM32F10X_Lib).
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
*
* 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
@ -20,11 +20,12 @@
#define VERSION_H
#include "Config.h"
#include "ADF7021.h"
#define VER_MAJOR "1"
#define VER_MINOR "1"
#define VER_REV "0"
#define VERSION_DATE "20180106"
#define VER_REV "2"
#define VERSION_DATE "20180121"
#if defined(ZUMSPOT_ADF7021)
#define BOARD_INFO "ZUMspot"
@ -34,7 +35,9 @@
#define BOARD_INFO "MMDVM_HS"
#endif
#if defined(ENABLE_ADF7021)
#if defined(ENABLE_ADF7021) && defined(ADF7021_N_VER)
#define RF_CHIP "ADF7021N"
#elif defined(ENABLE_ADF7021)
#define RF_CHIP "ADF7021"
#endif

Loading…
Cancel
Save

Powered by TurnKey Linux.