mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-16 00:34:12 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d063a1da1e | ||
|
|
6a4dad4c44 | ||
|
|
ed6bd66fab | ||
|
|
1a07a6f0d1 | ||
|
|
70bf47f93e | ||
|
|
a5eaafc7e0 | ||
|
|
2200945857 | ||
|
|
63a8e61a45 | ||
|
|
7275f65e44 | ||
|
|
2aabdb61ab | ||
|
|
96c0e5b141 | ||
|
|
9c883cfafd | ||
|
|
8a1ab88c3a | ||
|
|
f4e1c0b401 |
+3
-3
@@ -1,9 +1,9 @@
|
||||
[submodule "STM32F4XX_Lib"]
|
||||
path = STM32F4XX_Lib
|
||||
url = https://github.com/juribeparada/STM32F4XX_Lib.git
|
||||
[submodule "STM32F7XX_Lib"]
|
||||
path = STM32F7XX_Lib
|
||||
url = https://github.com/juribeparada/STM32F7XX_Lib.git
|
||||
[submodule "STM32F10X_Lib"]
|
||||
path = STM32F10X_Lib
|
||||
url = https://github.com/shawnchain/STM32F10X_Lib.git
|
||||
[submodule "STM32F7XX_Lib"]
|
||||
path = STM32F7XX_Lib
|
||||
url = https://github.com/g4klx/STM32F7XX_Lib.git
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable.
|
||||
//
|
||||
// For 12 MHz
|
||||
// #define EXTERNAL_OSC 12000000
|
||||
#define EXTERNAL_OSC 12000000
|
||||
// For 12.288 MHz
|
||||
// #define EXTERNAL_OSC 12288000
|
||||
// For 14.4 MHz
|
||||
@@ -66,19 +66,16 @@
|
||||
// For 19.2 MHz
|
||||
// #define EXTERNAL_OSC 19200000
|
||||
|
||||
// Use a higher baudrate for host communication. Required for FM network !
|
||||
// #define SERIAL_SPEED 115200 //suitable for most older boards (Arduino, Due STM32F1_POG etc). External FM will NOT work with this !
|
||||
// #define SERIAL_SPEED 230400 // Only works on newer board M4, M7, Teensy. External FM might work with this
|
||||
#define SERIAL_SPEED 460800 // Only works on newer board M4, M7, Teensy. External FM should work with this
|
||||
// Select a baud rate for host communication. The faster speeds are needed for external FM to work.
|
||||
// #define SERIAL_SPEED 115200 // Suitable for most older boards (Arduino Due, STM32F1_POG, etc). External FM will NOT work with this!
|
||||
// #define SERIAL_SPEED 230400 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM might work with this
|
||||
#define SERIAL_SPEED 460800 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM should work with this
|
||||
|
||||
// Allow the use of the COS line to lockout the modem
|
||||
// #define USE_COS_AS_LOCKOUT
|
||||
|
||||
// Use pins to output the current mode via LEDs
|
||||
// #define MODE_LEDS
|
||||
|
||||
// Use an OLED to show the current mode via a small screen (64x32) on I2C3
|
||||
#define MODE_OLED
|
||||
#define MODE_LEDS
|
||||
|
||||
// For the original Arduino Due pin layout
|
||||
// #define ARDUINO_DUE_PAPA
|
||||
@@ -108,7 +105,10 @@
|
||||
#define SEND_RSSI_DATA
|
||||
|
||||
// Use the modem as a serial repeater for Nextion displays
|
||||
// #define SERIAL_REPEATER
|
||||
#define SERIAL_REPEATER
|
||||
|
||||
// Use the modem as an I2C repeater for OLED displays
|
||||
// #define I2C_REPEATER
|
||||
|
||||
// To reduce CPU load, you can remove the DC blocker by commenting out the next line
|
||||
#define USE_DCBLOCKER
|
||||
@@ -121,16 +121,18 @@
|
||||
// #define USE_ALTERNATE_NXDN_LEDS
|
||||
|
||||
// Use the D-Star and P25 LEDs for M17
|
||||
// #define USE_ALTERNATE_M17_LEDS
|
||||
#define USE_ALTERNATE_M17_LEDS
|
||||
|
||||
// Use the D-Star and DMR LEDs for POCSAG
|
||||
// #define USE_ALTERNATE_POCSAG_LEDS
|
||||
#define USE_ALTERNATE_POCSAG_LEDS
|
||||
|
||||
// Use the D-Star and YSF LEDs for FM
|
||||
// #define USE_ALTERNATE_FM_LEDS
|
||||
#define USE_ALTERNATE_FM_LEDS
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
#undef MODE_LEDS
|
||||
#if defined(STM32F1_POG)
|
||||
// Slower boards need to run their serial at 115200 baud
|
||||
#undef SERIAL_SPEED
|
||||
#define SERIAL_SPEED 115200
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,13 +28,6 @@ const uint16_t FM_SERIAL_BLOCK_SIZE = 80U;//this is the number of sample pairs t
|
||||
//three times this value shall never exceed 252
|
||||
const uint16_t FM_SERIAL_BLOCK_SIZE_BYTES = FM_SERIAL_BLOCK_SIZE * 3U;
|
||||
|
||||
/*
|
||||
* Access Mode values are:
|
||||
* 0 - Carrier access with COS
|
||||
* 1 - CTCSS only access without COS
|
||||
* 2 - CTCSS only access with COS
|
||||
* 3 - CTCSS only access with COS to start, then carrier access with COS
|
||||
*/
|
||||
|
||||
CFM::CFM() :
|
||||
m_callsign(),
|
||||
@@ -63,6 +56,7 @@ m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
|
||||
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
|
||||
m_blanking(),
|
||||
m_accessMode(1U),
|
||||
m_linkMode(false),
|
||||
m_cosInvert(false),
|
||||
m_noiseSquelch(false),
|
||||
m_rfAudioBoost(1U),
|
||||
@@ -72,7 +66,9 @@ m_extEnabled(false),
|
||||
m_rxLevel(1),
|
||||
m_inputRFRB(2401U), // 100ms of audio + 1 sample
|
||||
m_outputRFRB(2400U), // 100ms of audio
|
||||
m_inputExtRB()
|
||||
m_inputExtRB(),
|
||||
m_rfSignal(false),
|
||||
m_extSignal(false)
|
||||
{
|
||||
m_statusTimer.setTimeout(1U, 0U);
|
||||
m_reverseTimer.setTimeout(0U, 150U);
|
||||
@@ -164,28 +160,42 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||
if (m_modemState != STATE_FM)
|
||||
continue;
|
||||
|
||||
if (m_state == FS_LISTENING && !m_rfAck.isWanted() && !m_extAck.isWanted() && !m_callsign.isWanted() && !m_reverseTimer.isRunning())
|
||||
continue;
|
||||
q15_t currentSample;
|
||||
|
||||
q15_t currentSample = currentRFSample;
|
||||
q15_t currentBoost = m_rfAudioBoost;
|
||||
if (m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
|
||||
currentSample = currentExtSample;
|
||||
currentBoost = m_extAudioBoost;
|
||||
}
|
||||
|
||||
// Only let RF audio through when relaying RF audio
|
||||
if (m_duplex) {
|
||||
if (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF || m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
|
||||
currentSample = m_blanking.process(currentSample);
|
||||
if (m_extEnabled && (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF))
|
||||
m_downSampler.addSample(currentSample);
|
||||
|
||||
currentSample *= currentBoost;
|
||||
} else {
|
||||
currentSample = 0;
|
||||
if (m_linkMode) {
|
||||
if (m_rfSignal && m_extEnabled) {
|
||||
q15_t currentSample = m_blanking.process(currentRFSample);
|
||||
m_downSampler.addSample(currentSample);
|
||||
}
|
||||
|
||||
if (m_extSignal)
|
||||
currentSample = currentExtSample * m_extAudioBoost;
|
||||
|
||||
if (!m_extSignal)
|
||||
continue;
|
||||
} else {
|
||||
if (m_state == FS_LISTENING && !m_rfAck.isWanted() && !m_extAck.isWanted() && !m_callsign.isWanted() && !m_reverseTimer.isRunning())
|
||||
continue;
|
||||
|
||||
q15_t currentSample = currentRFSample;
|
||||
q15_t currentBoost = m_rfAudioBoost;
|
||||
if (m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
|
||||
currentSample = currentExtSample;
|
||||
currentBoost = m_extAudioBoost;
|
||||
}
|
||||
|
||||
// Only let RF audio through when relaying RF audio
|
||||
if (m_duplex) {
|
||||
if (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF || m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
|
||||
currentSample = m_blanking.process(currentSample);
|
||||
if (m_extEnabled && (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF))
|
||||
m_downSampler.addSample(currentSample);
|
||||
|
||||
currentSample *= currentBoost;
|
||||
} else {
|
||||
currentSample = 0;
|
||||
}
|
||||
} else {
|
||||
if (m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
|
||||
currentSample *= currentBoost;
|
||||
} else {
|
||||
@@ -193,6 +203,7 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||
m_downSampler.addSample(currentSample);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_callsign.isRunning() && !m_extAck.isRunning())
|
||||
@@ -287,6 +298,8 @@ void CFM::reset()
|
||||
m_squelch.reset();
|
||||
|
||||
m_needReverse = false;
|
||||
m_rfSignal = false;
|
||||
m_extSignal = false;
|
||||
}
|
||||
|
||||
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch)
|
||||
@@ -317,9 +330,10 @@ uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_
|
||||
return m_rfAck.setParams(rfAck, speed, frequency, level, level);
|
||||
}
|
||||
|
||||
uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
|
||||
uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
|
||||
{
|
||||
m_accessMode = accessMode;
|
||||
m_linkMode = linkMode;
|
||||
m_cosInvert = cosInvert;
|
||||
m_noiseSquelch = noiseSquelch;
|
||||
|
||||
@@ -356,10 +370,14 @@ uint8_t CFM::setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t
|
||||
|
||||
void CFM::stateMachine(bool validRFSignal, bool validExtSignal)
|
||||
{
|
||||
if (m_duplex)
|
||||
duplexStateMachine(validRFSignal, validExtSignal);
|
||||
else
|
||||
simplexStateMachine(validRFSignal, validExtSignal);
|
||||
if (m_linkMode) {
|
||||
linkStateMachine(validRFSignal, validExtSignal);
|
||||
} else {
|
||||
if (m_duplex)
|
||||
duplexStateMachine(validRFSignal, validExtSignal);
|
||||
else
|
||||
simplexStateMachine(validRFSignal, validExtSignal);
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::simplexStateMachine(bool validRFSignal, bool validExtSignal)
|
||||
@@ -1009,6 +1027,63 @@ void CFM::timeoutExtWaitStateSimplex(bool validSignal)
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::linkStateMachine(bool validRFSignal, bool validExtSignal)
|
||||
{
|
||||
if (validRFSignal && !m_rfSignal) {
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
if (!m_extSignal) {
|
||||
DEBUG1("State to RELAYING_RF");
|
||||
m_state = FS_RELAYING_RF;
|
||||
m_statusTimer.start();
|
||||
serial.writeFMStatus(m_state);
|
||||
}
|
||||
|
||||
m_rfSignal = true;
|
||||
}
|
||||
|
||||
if (validExtSignal && !m_extSignal) {
|
||||
if (!m_rfSignal) {
|
||||
DEBUG1("State to RELAYING_EXT");
|
||||
m_state = FS_RELAYING_EXT;
|
||||
m_statusTimer.start();
|
||||
serial.writeFMStatus(m_state);
|
||||
}
|
||||
|
||||
insertSilence(50U);
|
||||
|
||||
m_extSignal = true;
|
||||
}
|
||||
|
||||
if (!validRFSignal && m_rfSignal) {
|
||||
io.setDecode(false);
|
||||
io.setADCDetection(false);
|
||||
|
||||
if (!m_extSignal) {
|
||||
DEBUG1("State to LISTENING");
|
||||
m_state = FS_LISTENING;
|
||||
m_statusTimer.stop();
|
||||
}
|
||||
|
||||
m_rfSignal = false;
|
||||
|
||||
if (m_extEnabled)
|
||||
serial.writeFMEOT();
|
||||
}
|
||||
|
||||
if (!validExtSignal && m_extSignal) {
|
||||
if (!m_rfSignal) {
|
||||
DEBUG1("State to LISTENING");
|
||||
m_state = FS_LISTENING;
|
||||
m_statusTimer.stop();
|
||||
}
|
||||
|
||||
m_needReverse = true;
|
||||
m_extSignal = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::sendCallsign()
|
||||
{
|
||||
if (m_holdoffTimer.isRunning()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2021 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
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
|
||||
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
|
||||
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
|
||||
|
||||
uint8_t getSpace() const;
|
||||
@@ -97,6 +97,7 @@ private:
|
||||
CFMDirectFormI m_filterStage3;
|
||||
CFMBlanking m_blanking;
|
||||
uint8_t m_accessMode;
|
||||
bool m_linkMode;
|
||||
bool m_cosInvert;
|
||||
bool m_noiseSquelch;
|
||||
q15_t m_rfAudioBoost;
|
||||
@@ -107,6 +108,8 @@ private:
|
||||
CRingBuffer<q15_t> m_inputRFRB;
|
||||
CRingBuffer<q15_t> m_outputRFRB;
|
||||
CFMUpSampler m_inputExtRB;
|
||||
bool m_rfSignal;
|
||||
bool m_extSignal;
|
||||
|
||||
void stateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
@@ -135,6 +138,8 @@ private:
|
||||
void timeoutExtStateSimplex(bool validSignal);
|
||||
void timeoutExtWaitStateSimplex(bool validSignal);
|
||||
|
||||
void linkStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void clock(uint8_t length);
|
||||
|
||||
void sendCallsign();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 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
|
||||
@@ -100,12 +100,10 @@ enum MMDVM_STATE {
|
||||
#include "CalNXDN.h"
|
||||
#include "CalPOCSAG.h"
|
||||
#include "CalRSSI.h"
|
||||
#include "I2COLED.h"
|
||||
#include "CWIdTX.h"
|
||||
#include "AX25RX.h"
|
||||
#include "AX25TX.h"
|
||||
#include "Debug.h"
|
||||
#include "I2C3.h"
|
||||
#include "IO.h"
|
||||
#include "FM.h"
|
||||
|
||||
@@ -144,10 +142,6 @@ extern bool m_dcd;
|
||||
extern CSerialPort serial;
|
||||
extern CIO io;
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
extern CI2COLED oled;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
extern CDStarRX dstarRX;
|
||||
extern CDStarTX dstarTX;
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020,2021 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
|
||||
* 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"
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
|
||||
#include "I2C3.h"
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
|
||||
#define I2C_WRITE_REG(REG, VAL) ((REG) = (VAL))
|
||||
#define I2C_READ_REG(REG) ((REG))
|
||||
|
||||
#define I2C_CLEAR_FLAG(__FLAG__) (((__FLAG__) == I2C_FLAG_TXE) ? (I2C3->ISR |= (__FLAG__)) : (I2C3->ICR = (__FLAG__)))
|
||||
#define I2C_GET_FLAG(__FLAG__) ((((I2C3->ISR) & (__FLAG__)) == (__FLAG__)) ? SET : RESET)
|
||||
|
||||
#define I2C_RESET_CR2() (I2C3->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN)))
|
||||
|
||||
#define I2C_MODIFY_REG(REG, CLEARMASK, SETMASK) I2C_WRITE_REG((REG), (((I2C_READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
|
||||
|
||||
#define TIMING_CLEAR_MASK (0xF0FFFFFFU)
|
||||
|
||||
#define I2C_DUALADDRESS_DISABLE (0x00000000U)
|
||||
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN
|
||||
|
||||
#define I2C_GENERALCALL_DISABLE (0x00000000U)
|
||||
|
||||
#define I2C_NOSTRETCH_DISABLE (0x00000000U)
|
||||
|
||||
#define I2C_ANALOGFILTER_ENABLE 0x00000000U
|
||||
|
||||
#define RCC_I2C3CLKSOURCE_PCLK1 ((uint32_t)0x00000000U)
|
||||
|
||||
#define I2C_OA2_NOMASK ((uint8_t)0x00U)
|
||||
|
||||
#define GPIO_MODE_AF_OD ((uint32_t)0x00000012U)
|
||||
|
||||
#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010U)
|
||||
|
||||
#define GPIO_MODE ((uint32_t)0x00000003U)
|
||||
|
||||
#define GPIO_NUMBER (16U)
|
||||
|
||||
#define I2C_ENABLE() (SET_BIT(I2C3->CR1, I2C_CR1_PE))
|
||||
|
||||
#define I2C_DISABLE() (CLEAR_BIT(I2C3->CR1, I2C_CR1_PE))
|
||||
|
||||
#define RCC_GPIOA_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\
|
||||
} while(0)
|
||||
|
||||
#define RCC_GPIOC_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\
|
||||
} while(0)
|
||||
|
||||
#define RCC_I2C3_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg; \
|
||||
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\
|
||||
tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\
|
||||
} while(0)
|
||||
|
||||
CI2C3::CI2C3()
|
||||
{
|
||||
}
|
||||
|
||||
void CI2C3::init()
|
||||
{
|
||||
// Enable the I2C3 clock
|
||||
I2C_MODIFY_REG(RCC->DCKCFGR2, RCC_DCKCFGR2_I2C3SEL, RCC_I2C3CLKSOURCE_PCLK1);
|
||||
|
||||
// Enable the GPIOs for the SCL/SDA Pins
|
||||
RCC_GPIOC_CLK_ENABLE();
|
||||
RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
initI2C3();
|
||||
|
||||
// Configure Analogue filter
|
||||
configAnalogFilter(I2C_ANALOGFILTER_ENABLE);
|
||||
|
||||
// Configure Digital filter
|
||||
configDigitalFilter(0U);
|
||||
}
|
||||
|
||||
void CI2C3::write(uint16_t addr, const uint8_t* data, uint8_t length)
|
||||
{
|
||||
DEBUG2("OLED Data", addr);
|
||||
DEBUG_DUMP(data, length);
|
||||
|
||||
// Shift the address to the left
|
||||
addr <<= 3;
|
||||
|
||||
// Wait for the I2C transmitter to become free
|
||||
while (I2C_GET_FLAG(I2C_FLAG_BUSY) == SET)
|
||||
;
|
||||
|
||||
// Configure the data transfer
|
||||
transferConfig(addr, length, I2C_CR2_AUTOEND, I2C_Generate_Start_Write);
|
||||
|
||||
// Start Writing Data
|
||||
for (uint16_t i = 0U; i < length; i++) {
|
||||
// Wait for the TXIS flag to be set
|
||||
while (I2C_GET_FLAG(I2C_FLAG_TXIS) == RESET)
|
||||
;
|
||||
|
||||
// Write the byte to the TXDR
|
||||
I2C3->TXDR = data[i];
|
||||
}
|
||||
|
||||
// No need to Check TC flag, with AUTOEND mode the stop is automatically generated Wait until STOPF flag is set
|
||||
while (I2C_GET_FLAG(I2C_FLAG_STOPF) == RESET)
|
||||
;
|
||||
|
||||
// Clear STOP flag
|
||||
I2C_CLEAR_FLAG(I2C_FLAG_STOPF);
|
||||
|
||||
// Clear Configuration Register 2
|
||||
I2C_RESET_CR2();
|
||||
}
|
||||
|
||||
void CI2C3::transferConfig(uint16_t addr, uint8_t length, uint32_t mode, uint32_t request)
|
||||
{
|
||||
// Update CR2 register
|
||||
I2C_MODIFY_REG(I2C3->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | \
|
||||
(I2C_CR2_RD_WRN & (uint32_t)(request >> (31U - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP)), \
|
||||
(uint32_t)(((uint32_t)addr & I2C_CR2_SADD) |
|
||||
(((uint32_t)length << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)mode | (uint32_t)request));
|
||||
}
|
||||
|
||||
void CI2C3::configAnalogFilter(uint32_t AnalogFilter)
|
||||
{
|
||||
// Disable the selected I2C peripheral
|
||||
I2C_DISABLE();
|
||||
|
||||
// Reset I2Cx ANOFF bit
|
||||
I2C3->CR1 &= ~(I2C_CR1_ANFOFF);
|
||||
|
||||
// Set analog filter bit
|
||||
I2C3->CR1 |= AnalogFilter;
|
||||
|
||||
I2C_ENABLE();
|
||||
}
|
||||
|
||||
void CI2C3::configDigitalFilter(uint32_t DigitalFilter)
|
||||
{
|
||||
// Disable the selected I2C peripheral
|
||||
I2C_DISABLE();
|
||||
|
||||
// Get the old register value
|
||||
uint32_t tmpreg = I2C3->CR1;
|
||||
|
||||
// Reset I2Cx DNF bits [11:8]
|
||||
tmpreg &= ~(I2C_CR1_DNF);
|
||||
|
||||
// Set I2Cx DNF coefficient
|
||||
tmpreg |= DigitalFilter << 8U;
|
||||
|
||||
// Store the new register value
|
||||
I2C3->CR1 = tmpreg;
|
||||
|
||||
I2C_ENABLE();
|
||||
}
|
||||
|
||||
void CI2C3::initI2C3()
|
||||
{
|
||||
initMSP();
|
||||
|
||||
/* Disable the selected I2C peripheral */
|
||||
I2C_DISABLE();
|
||||
|
||||
/*---------------------------- I2Cx TIMINGR Configuration ------------------*/
|
||||
/* Configure I2Cx: Frequency range */
|
||||
I2C3->TIMINGR = 0x0010061AU & TIMING_CLEAR_MASK;
|
||||
|
||||
/*---------------------------- I2Cx OAR1 Configuration ---------------------*/
|
||||
/* Disable Own Address1 before set the Own Address1 configuration */
|
||||
I2C3->OAR1 &= ~I2C_OAR1_OA1EN;
|
||||
|
||||
/* Configure I2Cx: Own Address1 and ack own address1 mode */
|
||||
I2C3->OAR1 = (I2C_OAR1_OA1EN | 0U);
|
||||
|
||||
/*---------------------------- I2Cx CR2 Configuration ----------------------*/
|
||||
/* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
|
||||
I2C3->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
|
||||
|
||||
/*---------------------------- I2Cx OAR2 Configuration ---------------------*/
|
||||
/* Disable Own Address2 before set the Own Address2 configuration */
|
||||
I2C3->OAR2 &= ~I2C_DUALADDRESS_ENABLE;
|
||||
|
||||
/* Configure I2Cx: Dual mode and Own Address2 */
|
||||
I2C3->OAR2 = (I2C_DUALADDRESS_DISABLE | 0U | (I2C_OA2_NOMASK << 8));
|
||||
|
||||
/*---------------------------- I2Cx CR1 Configuration ----------------------*/
|
||||
/* Configure I2Cx: Generalcall and NoStretch mode */
|
||||
I2C3->CR1 = (I2C_GENERALCALL_DISABLE | I2C_NOSTRETCH_DISABLE);
|
||||
|
||||
/* Enable the selected I2C peripheral */
|
||||
I2C_ENABLE();
|
||||
}
|
||||
|
||||
void CI2C3::initMSP()
|
||||
{
|
||||
RCC_GPIOC_CLK_ENABLE();
|
||||
RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
/* I2C3 GPIO Configuration
|
||||
PC9 ------> I2C3_SDA
|
||||
PA8 ------> I2C3_SCL
|
||||
*/
|
||||
initGPIO(GPIOC, GPIO_Pin_9);
|
||||
initGPIO(GPIOA, GPIO_Pin_8);
|
||||
|
||||
// Peripheral clock enable
|
||||
RCC_I2C3_CLK_ENABLE();
|
||||
}
|
||||
|
||||
void CI2C3::initGPIO(GPIO_TypeDef* GPIOx, uint32_t Pin)
|
||||
{
|
||||
// Configure the port pins
|
||||
for (uint32_t position = 0U; position < GPIO_NUMBER; position++)
|
||||
{
|
||||
// Get the IO position
|
||||
uint32_t ioposition = ((uint32_t)0x01) << position;
|
||||
|
||||
// Get the current IO position
|
||||
uint32_t iocurrent = Pin & ioposition;
|
||||
|
||||
if (iocurrent == ioposition)
|
||||
{
|
||||
// Configure the IO Speed
|
||||
uint32_t temp = GPIOx->OSPEEDR;
|
||||
temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));
|
||||
temp |= (GPIO_High_Speed << (position * 2));
|
||||
GPIOx->OSPEEDR = temp;
|
||||
|
||||
// Configure the IO Output Type
|
||||
temp = GPIOx->OTYPER;
|
||||
temp &= ~(GPIO_OTYPER_OT_0 << position) ;
|
||||
temp |= (((GPIO_MODE_AF_OD & GPIO_OUTPUT_TYPE) >> 4) << position);
|
||||
GPIOx->OTYPER = temp;
|
||||
|
||||
// Activate the Pull Up resistor for the current IO
|
||||
temp = GPIOx->PUPDR;
|
||||
temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));
|
||||
temp |= ((GPIO_PuPd_UP) << (position * 2));
|
||||
GPIOx->PUPDR = temp;
|
||||
|
||||
// Configure Alternate function mapped with the current IO
|
||||
temp = GPIOx->AFR[position >> 3];
|
||||
temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
|
||||
temp |= ((uint32_t)(GPIO_AF4_I2C3) << (((uint32_t)position & (uint32_t)0x07) * 4));
|
||||
GPIOx->AFR[position >> 3] = temp;
|
||||
|
||||
// Configure IO Direction mode (Input, Output, Alternate or Analog)
|
||||
temp = GPIOx->MODER;
|
||||
temp &= ~(GPIO_MODER_MODER0 << (position * 2));
|
||||
temp |= ((GPIO_MODE_AF_OD & GPIO_MODE) << (position * 2));
|
||||
GPIOx->MODER = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020,2021 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
|
||||
* 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"
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
|
||||
#if !defined(I2C3_H)
|
||||
#define I2C3_H
|
||||
|
||||
#if defined(STM32F7XX)
|
||||
#include "stm32f7xx.h"
|
||||
#include "stm32f7xx_i2c.h"
|
||||
#endif
|
||||
|
||||
|
||||
class CI2C3 {
|
||||
public:
|
||||
CI2C3();
|
||||
|
||||
void init();
|
||||
|
||||
void write(uint16_t addr, const uint8_t* data, uint8_t length);
|
||||
|
||||
private:
|
||||
void transferConfig(uint16_t addr, uint8_t length, uint32_t mode, uint32_t request);
|
||||
void configAnalogFilter(uint32_t AnalogFilter);
|
||||
void configDigitalFilter(uint32_t DigitalFilter);
|
||||
void initI2C3();
|
||||
void initMSP();
|
||||
void initGPIO(GPIO_TypeDef* GPIOx, uint32_t Pin);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
-509
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020,2021 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
|
||||
* 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"
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
|
||||
#include "I2COLED.h"
|
||||
#include "I2C3.h"
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
const uint8_t OLED_ADDRESS = 0x78U;
|
||||
|
||||
const uint8_t OLED_WIDTH = 64U;
|
||||
const uint8_t OLED_HEIGHT = 32U;
|
||||
const uint16_t OLED_BUFFER_SIZE = (OLED_HEIGHT * OLED_WIDTH) / 8U;
|
||||
|
||||
const uint8_t SSD_Command_Mode = 0x00U; /* C0 and DC bit are 0 */
|
||||
const uint8_t SSD_Data_Mode = 0x40U; /* C0 bit is 0 and DC bit is 1 */
|
||||
|
||||
const uint8_t SSD1306_Set_Lower_Column_Start_Address = 0x00U;
|
||||
const uint8_t SSD1306_Set_Higher_Column_Start_Address = 0x10U;
|
||||
const uint8_t SSD1306_Set_Start_Line = 0x40U;
|
||||
|
||||
const uint8_t CHAR_HEIGHT = 5U;
|
||||
const uint8_t CHAR_WIDTH = 7U;
|
||||
|
||||
// Standard ascii 5x7 font
|
||||
const uint8_t FONT[] = {
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x3EU, 0x5BU, 0x4FU, 0x5BU, 0x3EU,
|
||||
0x3EU, 0x6BU, 0x4FU, 0x6BU, 0x3EU,
|
||||
0x1CU, 0x3EU, 0x7CU, 0x3EU, 0x1CU,
|
||||
0x18U, 0x3CU, 0x7EU, 0x3CU, 0x18U,
|
||||
0x1CU, 0x57U, 0x7DU, 0x57U, 0x1CU,
|
||||
0x1CU, 0x5EU, 0x7FU, 0x5EU, 0x1CU,
|
||||
0x00U, 0x18U, 0x3CU, 0x18U, 0x00U,
|
||||
0xFFU, 0xE7U, 0xC3U, 0xE7U, 0xFFU,
|
||||
0x00U, 0x18U, 0x24U, 0x18U, 0x00U,
|
||||
0xFFU, 0xE7U, 0xDBU, 0xE7U, 0xFFU,
|
||||
0x30U, 0x48U, 0x3AU, 0x06U, 0x0EU,
|
||||
0x26U, 0x29U, 0x79U, 0x29U, 0x26U,
|
||||
0x40U, 0x7FU, 0x05U, 0x05U, 0x07U,
|
||||
0x40U, 0x7FU, 0x05U, 0x25U, 0x3FU,
|
||||
0x5AU, 0x3CU, 0xE7U, 0x3CU, 0x5AU,
|
||||
0x7FU, 0x3EU, 0x1CU, 0x1CU, 0x08U,
|
||||
0x08U, 0x1CU, 0x1CU, 0x3EU, 0x7FU,
|
||||
0x14U, 0x22U, 0x7FU, 0x22U, 0x14U,
|
||||
0x5FU, 0x5FU, 0x00U, 0x5FU, 0x5FU,
|
||||
0x06U, 0x09U, 0x7FU, 0x01U, 0x7FU,
|
||||
0x00U, 0x66U, 0x89U, 0x95U, 0x6AU,
|
||||
0x60U, 0x60U, 0x60U, 0x60U, 0x60U,
|
||||
0x94U, 0xA2U, 0xFFU, 0xA2U, 0x94U,
|
||||
0x08U, 0x04U, 0x7EU, 0x04U, 0x08U,
|
||||
0x10U, 0x20U, 0x7EU, 0x20U, 0x10U,
|
||||
0x08U, 0x08U, 0x2AU, 0x1CU, 0x08U,
|
||||
0x08U, 0x1CU, 0x2AU, 0x08U, 0x08U,
|
||||
0x1EU, 0x10U, 0x10U, 0x10U, 0x10U,
|
||||
0x0CU, 0x1EU, 0x0CU, 0x1EU, 0x0CU,
|
||||
0x30U, 0x38U, 0x3EU, 0x38U, 0x30U,
|
||||
0x06U, 0x0EU, 0x3EU, 0x0EU, 0x06U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x5FU, 0x00U, 0x00U,
|
||||
0x00U, 0x07U, 0x00U, 0x07U, 0x00U,
|
||||
0x14U, 0x7FU, 0x14U, 0x7FU, 0x14U,
|
||||
0x24U, 0x2AU, 0x7FU, 0x2AU, 0x12U,
|
||||
0x23U, 0x13U, 0x08U, 0x64U, 0x62U,
|
||||
0x36U, 0x49U, 0x56U, 0x20U, 0x50U,
|
||||
0x00U, 0x08U, 0x07U, 0x03U, 0x00U,
|
||||
0x00U, 0x1CU, 0x22U, 0x41U, 0x00U,
|
||||
0x00U, 0x41U, 0x22U, 0x1CU, 0x00U,
|
||||
0x2AU, 0x1CU, 0x7FU, 0x1CU, 0x2AU,
|
||||
0x08U, 0x08U, 0x3EU, 0x08U, 0x08U,
|
||||
0x00U, 0x80U, 0x70U, 0x30U, 0x00U,
|
||||
0x08U, 0x08U, 0x08U, 0x08U, 0x08U,
|
||||
0x00U, 0x00U, 0x60U, 0x60U, 0x00U,
|
||||
0x20U, 0x10U, 0x08U, 0x04U, 0x02U,
|
||||
0x3EU, 0x51U, 0x49U, 0x45U, 0x3EU,
|
||||
0x00U, 0x42U, 0x7FU, 0x40U, 0x00U,
|
||||
0x72U, 0x49U, 0x49U, 0x49U, 0x46U,
|
||||
0x21U, 0x41U, 0x49U, 0x4DU, 0x33U,
|
||||
0x18U, 0x14U, 0x12U, 0x7FU, 0x10U,
|
||||
0x27U, 0x45U, 0x45U, 0x45U, 0x39U,
|
||||
0x3CU, 0x4AU, 0x49U, 0x49U, 0x31U,
|
||||
0x41U, 0x21U, 0x11U, 0x09U, 0x07U,
|
||||
0x36U, 0x49U, 0x49U, 0x49U, 0x36U,
|
||||
0x46U, 0x49U, 0x49U, 0x29U, 0x1EU,
|
||||
0x00U, 0x00U, 0x14U, 0x00U, 0x00U,
|
||||
0x00U, 0x40U, 0x34U, 0x00U, 0x00U,
|
||||
0x00U, 0x08U, 0x14U, 0x22U, 0x41U,
|
||||
0x14U, 0x14U, 0x14U, 0x14U, 0x14U,
|
||||
0x00U, 0x41U, 0x22U, 0x14U, 0x08U,
|
||||
0x02U, 0x01U, 0x59U, 0x09U, 0x06U,
|
||||
0x3EU, 0x41U, 0x5DU, 0x59U, 0x4EU,
|
||||
0x7CU, 0x12U, 0x11U, 0x12U, 0x7CU,
|
||||
0x7FU, 0x49U, 0x49U, 0x49U, 0x36U,
|
||||
0x3EU, 0x41U, 0x41U, 0x41U, 0x22U,
|
||||
0x7FU, 0x41U, 0x41U, 0x41U, 0x3EU,
|
||||
0x7FU, 0x49U, 0x49U, 0x49U, 0x41U,
|
||||
0x7FU, 0x09U, 0x09U, 0x09U, 0x01U,
|
||||
0x3EU, 0x41U, 0x41U, 0x51U, 0x73U,
|
||||
0x7FU, 0x08U, 0x08U, 0x08U, 0x7FU,
|
||||
0x00U, 0x41U, 0x7FU, 0x41U, 0x00U,
|
||||
0x20U, 0x40U, 0x41U, 0x3FU, 0x01U,
|
||||
0x7FU, 0x08U, 0x14U, 0x22U, 0x41U,
|
||||
0x7FU, 0x40U, 0x40U, 0x40U, 0x40U,
|
||||
0x7FU, 0x02U, 0x1CU, 0x02U, 0x7FU,
|
||||
0x7FU, 0x04U, 0x08U, 0x10U, 0x7FU,
|
||||
0x3EU, 0x41U, 0x41U, 0x41U, 0x3EU,
|
||||
0x7FU, 0x09U, 0x09U, 0x09U, 0x06U,
|
||||
0x3EU, 0x41U, 0x51U, 0x21U, 0x5EU,
|
||||
0x7FU, 0x09U, 0x19U, 0x29U, 0x46U,
|
||||
0x26U, 0x49U, 0x49U, 0x49U, 0x32U,
|
||||
0x03U, 0x01U, 0x7FU, 0x01U, 0x03U,
|
||||
0x3FU, 0x40U, 0x40U, 0x40U, 0x3FU,
|
||||
0x1FU, 0x20U, 0x40U, 0x20U, 0x1FU,
|
||||
0x3FU, 0x40U, 0x38U, 0x40U, 0x3FU,
|
||||
0x63U, 0x14U, 0x08U, 0x14U, 0x63U,
|
||||
0x03U, 0x04U, 0x78U, 0x04U, 0x03U,
|
||||
0x61U, 0x59U, 0x49U, 0x4DU, 0x43U,
|
||||
0x00U, 0x7FU, 0x41U, 0x41U, 0x41U,
|
||||
0x02U, 0x04U, 0x08U, 0x10U, 0x20U,
|
||||
0x00U, 0x41U, 0x41U, 0x41U, 0x7FU,
|
||||
0x04U, 0x02U, 0x01U, 0x02U, 0x04U,
|
||||
0x40U, 0x40U, 0x40U, 0x40U, 0x40U,
|
||||
0x00U, 0x03U, 0x07U, 0x08U, 0x00U,
|
||||
0x20U, 0x54U, 0x54U, 0x78U, 0x40U,
|
||||
0x7FU, 0x28U, 0x44U, 0x44U, 0x38U,
|
||||
0x38U, 0x44U, 0x44U, 0x44U, 0x28U,
|
||||
0x38U, 0x44U, 0x44U, 0x28U, 0x7FU,
|
||||
0x38U, 0x54U, 0x54U, 0x54U, 0x18U,
|
||||
0x00U, 0x08U, 0x7EU, 0x09U, 0x02U,
|
||||
0x18U, 0xA4U, 0xA4U, 0x9CU, 0x78U,
|
||||
0x7FU, 0x08U, 0x04U, 0x04U, 0x78U,
|
||||
0x00U, 0x44U, 0x7DU, 0x40U, 0x00U,
|
||||
0x20U, 0x40U, 0x40U, 0x3DU, 0x00U,
|
||||
0x7FU, 0x10U, 0x28U, 0x44U, 0x00U,
|
||||
0x00U, 0x41U, 0x7FU, 0x40U, 0x00U,
|
||||
0x7CU, 0x04U, 0x78U, 0x04U, 0x78U,
|
||||
0x7CU, 0x08U, 0x04U, 0x04U, 0x78U,
|
||||
0x38U, 0x44U, 0x44U, 0x44U, 0x38U,
|
||||
0xFCU, 0x18U, 0x24U, 0x24U, 0x18U,
|
||||
0x18U, 0x24U, 0x24U, 0x18U, 0xFCU,
|
||||
0x7CU, 0x08U, 0x04U, 0x04U, 0x08U,
|
||||
0x48U, 0x54U, 0x54U, 0x54U, 0x24U,
|
||||
0x04U, 0x04U, 0x3FU, 0x44U, 0x24U,
|
||||
0x3CU, 0x40U, 0x40U, 0x20U, 0x7CU,
|
||||
0x1CU, 0x20U, 0x40U, 0x20U, 0x1CU,
|
||||
0x3CU, 0x40U, 0x30U, 0x40U, 0x3CU,
|
||||
0x44U, 0x28U, 0x10U, 0x28U, 0x44U,
|
||||
0x4CU, 0x90U, 0x90U, 0x90U, 0x7CU,
|
||||
0x44U, 0x64U, 0x54U, 0x4CU, 0x44U,
|
||||
0x00U, 0x08U, 0x36U, 0x41U, 0x00U,
|
||||
0x00U, 0x00U, 0x77U, 0x00U, 0x00U,
|
||||
0x00U, 0x41U, 0x36U, 0x08U, 0x00U,
|
||||
0x02U, 0x01U, 0x02U, 0x04U, 0x02U,
|
||||
0x3CU, 0x26U, 0x23U, 0x26U, 0x3CU,
|
||||
0x1EU, 0xA1U, 0xA1U, 0x61U, 0x12U,
|
||||
0x3AU, 0x40U, 0x40U, 0x20U, 0x7AU,
|
||||
0x38U, 0x54U, 0x54U, 0x55U, 0x59U,
|
||||
0x21U, 0x55U, 0x55U, 0x79U, 0x41U,
|
||||
0x21U, 0x54U, 0x54U, 0x78U, 0x41U,
|
||||
0x21U, 0x55U, 0x54U, 0x78U, 0x40U,
|
||||
0x20U, 0x54U, 0x55U, 0x79U, 0x40U,
|
||||
0x0CU, 0x1EU, 0x52U, 0x72U, 0x12U,
|
||||
0x39U, 0x55U, 0x55U, 0x55U, 0x59U,
|
||||
0x39U, 0x54U, 0x54U, 0x54U, 0x59U,
|
||||
0x39U, 0x55U, 0x54U, 0x54U, 0x58U,
|
||||
0x00U, 0x00U, 0x45U, 0x7CU, 0x41U,
|
||||
0x00U, 0x02U, 0x45U, 0x7DU, 0x42U,
|
||||
0x00U, 0x01U, 0x45U, 0x7CU, 0x40U,
|
||||
0xF0U, 0x29U, 0x24U, 0x29U, 0xF0U,
|
||||
0xF0U, 0x28U, 0x25U, 0x28U, 0xF0U,
|
||||
0x7CU, 0x54U, 0x55U, 0x45U, 0x00U,
|
||||
0x20U, 0x54U, 0x54U, 0x7CU, 0x54U,
|
||||
0x7CU, 0x0AU, 0x09U, 0x7FU, 0x49U,
|
||||
0x32U, 0x49U, 0x49U, 0x49U, 0x32U,
|
||||
0x32U, 0x48U, 0x48U, 0x48U, 0x32U,
|
||||
0x32U, 0x4AU, 0x48U, 0x48U, 0x30U,
|
||||
0x3AU, 0x41U, 0x41U, 0x21U, 0x7AU,
|
||||
0x3AU, 0x42U, 0x40U, 0x20U, 0x78U,
|
||||
0x00U, 0x9DU, 0xA0U, 0xA0U, 0x7DU,
|
||||
0x39U, 0x44U, 0x44U, 0x44U, 0x39U,
|
||||
0x3DU, 0x40U, 0x40U, 0x40U, 0x3DU,
|
||||
0x3CU, 0x24U, 0xFFU, 0x24U, 0x24U,
|
||||
0x48U, 0x7EU, 0x49U, 0x43U, 0x66U,
|
||||
0x2BU, 0x2FU, 0xFCU, 0x2FU, 0x2BU,
|
||||
0xFFU, 0x09U, 0x29U, 0xF6U, 0x20U,
|
||||
0xC0U, 0x88U, 0x7EU, 0x09U, 0x03U,
|
||||
0x20U, 0x54U, 0x54U, 0x79U, 0x41U,
|
||||
0x00U, 0x00U, 0x44U, 0x7DU, 0x41U,
|
||||
0x30U, 0x48U, 0x48U, 0x4AU, 0x32U,
|
||||
0x38U, 0x40U, 0x40U, 0x22U, 0x7AU,
|
||||
0x00U, 0x7AU, 0x0AU, 0x0AU, 0x72U,
|
||||
0x7DU, 0x0DU, 0x19U, 0x31U, 0x7DU,
|
||||
0x26U, 0x29U, 0x29U, 0x2FU, 0x28U,
|
||||
0x26U, 0x29U, 0x29U, 0x29U, 0x26U,
|
||||
0x30U, 0x48U, 0x4DU, 0x40U, 0x20U,
|
||||
0x38U, 0x08U, 0x08U, 0x08U, 0x08U,
|
||||
0x08U, 0x08U, 0x08U, 0x08U, 0x38U,
|
||||
0x2FU, 0x10U, 0xC8U, 0xACU, 0xBAU,
|
||||
0x2FU, 0x10U, 0x28U, 0x34U, 0xFAU,
|
||||
0x00U, 0x00U, 0x7BU, 0x00U, 0x00U,
|
||||
0x08U, 0x14U, 0x2AU, 0x14U, 0x22U,
|
||||
0x22U, 0x14U, 0x2AU, 0x14U, 0x08U,
|
||||
0xAAU, 0x00U, 0x55U, 0x00U, 0xAAU,
|
||||
0xAAU, 0x55U, 0xAAU, 0x55U, 0xAAU,
|
||||
0x00U, 0x00U, 0x00U, 0xFFU, 0x00U,
|
||||
0x10U, 0x10U, 0x10U, 0xFFU, 0x00U,
|
||||
0x14U, 0x14U, 0x14U, 0xFFU, 0x00U,
|
||||
0x10U, 0x10U, 0xFFU, 0x00U, 0xFFU,
|
||||
0x10U, 0x10U, 0xF0U, 0x10U, 0xF0U,
|
||||
0x14U, 0x14U, 0x14U, 0xFCU, 0x00U,
|
||||
0x14U, 0x14U, 0xF7U, 0x00U, 0xFFU,
|
||||
0x00U, 0x00U, 0xFFU, 0x00U, 0xFFU,
|
||||
0x14U, 0x14U, 0xF4U, 0x04U, 0xFCU,
|
||||
0x14U, 0x14U, 0x17U, 0x10U, 0x1FU,
|
||||
0x10U, 0x10U, 0x1FU, 0x10U, 0x1FU,
|
||||
0x14U, 0x14U, 0x14U, 0x1FU, 0x00U,
|
||||
0x10U, 0x10U, 0x10U, 0xF0U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x1FU, 0x10U,
|
||||
0x10U, 0x10U, 0x10U, 0x1FU, 0x10U,
|
||||
0x10U, 0x10U, 0x10U, 0xF0U, 0x10U,
|
||||
0x00U, 0x00U, 0x00U, 0xFFU, 0x10U,
|
||||
0x10U, 0x10U, 0x10U, 0x10U, 0x10U,
|
||||
0x10U, 0x10U, 0x10U, 0xFFU, 0x10U,
|
||||
0x00U, 0x00U, 0x00U, 0xFFU, 0x14U,
|
||||
0x00U, 0x00U, 0xFFU, 0x00U, 0xFFU,
|
||||
0x00U, 0x00U, 0x1FU, 0x10U, 0x17U,
|
||||
0x00U, 0x00U, 0xFCU, 0x04U, 0xF4U,
|
||||
0x14U, 0x14U, 0x17U, 0x10U, 0x17U,
|
||||
0x14U, 0x14U, 0xF4U, 0x04U, 0xF4U,
|
||||
0x00U, 0x00U, 0xFFU, 0x00U, 0xF7U,
|
||||
0x14U, 0x14U, 0x14U, 0x14U, 0x14U,
|
||||
0x14U, 0x14U, 0xF7U, 0x00U, 0xF7U,
|
||||
0x14U, 0x14U, 0x14U, 0x17U, 0x14U,
|
||||
0x10U, 0x10U, 0x1FU, 0x10U, 0x1FU,
|
||||
0x14U, 0x14U, 0x14U, 0xF4U, 0x14U,
|
||||
0x10U, 0x10U, 0xF0U, 0x10U, 0xF0U,
|
||||
0x00U, 0x00U, 0x1FU, 0x10U, 0x1FU,
|
||||
0x00U, 0x00U, 0x00U, 0x1FU, 0x14U,
|
||||
0x00U, 0x00U, 0x00U, 0xFCU, 0x14U,
|
||||
0x00U, 0x00U, 0xF0U, 0x10U, 0xF0U,
|
||||
0x10U, 0x10U, 0xFFU, 0x10U, 0xFFU,
|
||||
0x14U, 0x14U, 0x14U, 0xFFU, 0x14U,
|
||||
0x10U, 0x10U, 0x10U, 0x1FU, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0xF0U, 0x10U,
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xF0U, 0xF0U, 0xF0U, 0xF0U, 0xF0U,
|
||||
0xFFU, 0xFFU, 0xFFU, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0xFFU, 0xFFU,
|
||||
0x0FU, 0x0FU, 0x0FU, 0x0FU, 0x0FU,
|
||||
0x38U, 0x44U, 0x44U, 0x38U, 0x44U,
|
||||
0x7CU, 0x2AU, 0x2AU, 0x3EU, 0x14U,
|
||||
0x7EU, 0x02U, 0x02U, 0x06U, 0x06U,
|
||||
0x02U, 0x7EU, 0x02U, 0x7EU, 0x02U,
|
||||
0x63U, 0x55U, 0x49U, 0x41U, 0x63U,
|
||||
0x38U, 0x44U, 0x44U, 0x3CU, 0x04U,
|
||||
0x40U, 0x7EU, 0x20U, 0x1EU, 0x20U,
|
||||
0x06U, 0x02U, 0x7EU, 0x02U, 0x02U,
|
||||
0x99U, 0xA5U, 0xE7U, 0xA5U, 0x99U,
|
||||
0x1CU, 0x2AU, 0x49U, 0x2AU, 0x1CU,
|
||||
0x4CU, 0x72U, 0x01U, 0x72U, 0x4CU,
|
||||
0x30U, 0x4AU, 0x4DU, 0x4DU, 0x30U,
|
||||
0x30U, 0x48U, 0x78U, 0x48U, 0x30U,
|
||||
0xBCU, 0x62U, 0x5AU, 0x46U, 0x3DU,
|
||||
0x3EU, 0x49U, 0x49U, 0x49U, 0x00U,
|
||||
0x7EU, 0x01U, 0x01U, 0x01U, 0x7EU,
|
||||
0x2AU, 0x2AU, 0x2AU, 0x2AU, 0x2AU,
|
||||
0x44U, 0x44U, 0x5FU, 0x44U, 0x44U,
|
||||
0x40U, 0x51U, 0x4AU, 0x44U, 0x40U,
|
||||
0x40U, 0x44U, 0x4AU, 0x51U, 0x40U,
|
||||
0x00U, 0x00U, 0xFFU, 0x01U, 0x03U,
|
||||
0xE0U, 0x80U, 0xFFU, 0x00U, 0x00U,
|
||||
0x08U, 0x08U, 0x6BU, 0x6BU, 0x08U,
|
||||
0x36U, 0x12U, 0x36U, 0x24U, 0x36U,
|
||||
0x06U, 0x0FU, 0x09U, 0x0FU, 0x06U,
|
||||
0x00U, 0x00U, 0x18U, 0x18U, 0x00U,
|
||||
0x00U, 0x00U, 0x10U, 0x10U, 0x00U,
|
||||
0x30U, 0x40U, 0xFFU, 0x01U, 0x01U,
|
||||
0x00U, 0x1FU, 0x01U, 0x01U, 0x1EU,
|
||||
0x00U, 0x19U, 0x1DU, 0x17U, 0x12U,
|
||||
0x00U, 0x3CU, 0x3CU, 0x3CU, 0x3CU,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
|
||||
|
||||
// Arduino Compatible Macro
|
||||
#define _BV(bit) (1 << (bit))
|
||||
|
||||
|
||||
|
||||
CI2COLED::CI2COLED() :
|
||||
m_i2c(),
|
||||
m_oledBuffer(NULL)
|
||||
{
|
||||
m_oledBuffer = new uint8_t[OLED_BUFFER_SIZE];
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void CI2COLED::init()
|
||||
{
|
||||
m_i2c.init();
|
||||
|
||||
// Initialise the VG-6432TSWEG02 OLED display
|
||||
// Taken from https://datasheet.lcsc.com/szlcsc/1912111437_WiseChip-VG-6432TSWAG01-IIC-sh1106_C194312.pdf
|
||||
|
||||
sendCommand(0xAEU); // Display off
|
||||
|
||||
sendCommand(0x00U); // Set lower column address
|
||||
sendCommand(0x12U); // Set higher column address
|
||||
|
||||
sendCommand(0x00U); // Set display start line
|
||||
|
||||
sendCommand(0xB0U); // Set page address
|
||||
|
||||
sendCommand(0x81U, 0x4FU); // Contract control, 128
|
||||
|
||||
sendCommand(0xA1U); // Set segment remap
|
||||
|
||||
sendCommand(0xA6U); // Normal/reverse
|
||||
|
||||
sendCommand(0xA8U, 0x1FU); // Multiplex ratio, duty = 1/32
|
||||
|
||||
sendCommand(0xC8U); // Com scan direction
|
||||
|
||||
sendCommand(0xD3U, 0x00U); // Set display offset
|
||||
|
||||
sendCommand(0xD5U, 0x80U); // Set osc division
|
||||
|
||||
sendCommand(0xD9U, 0x1FU); // Set pre-charge period
|
||||
|
||||
sendCommand(0xDAU, 0x12U); // Set COM pins
|
||||
|
||||
sendCommand(0xDBU, 0x40U); // Set vcomh
|
||||
|
||||
sendCommand(0x8DU, 0x14U); // Set charge pump enable
|
||||
|
||||
sendCommand(0xAFU); // Display on
|
||||
}
|
||||
|
||||
void CI2COLED::setMode(int state)
|
||||
{
|
||||
clear();
|
||||
|
||||
switch (MMDVM_STATE(state)) {
|
||||
case STATE_IDLE:
|
||||
write("Idle");
|
||||
break;
|
||||
case STATE_DSTAR:
|
||||
write("D-Star");
|
||||
break;
|
||||
case STATE_DMR:
|
||||
write("DMR");
|
||||
break;
|
||||
case STATE_YSF:
|
||||
write("YSF");
|
||||
break;
|
||||
case STATE_P25:
|
||||
write("P25");
|
||||
break;
|
||||
case STATE_NXDN:
|
||||
write("NXDN");
|
||||
break;
|
||||
case STATE_FM:
|
||||
write("FM");
|
||||
break;
|
||||
case STATE_M17:
|
||||
write("M17");
|
||||
break;
|
||||
case STATE_POCSAG:
|
||||
write("POCSAG");
|
||||
break;
|
||||
case STATE_AX25:
|
||||
write("AX.25");
|
||||
break;
|
||||
default:
|
||||
write("Calibrate");
|
||||
break;
|
||||
}
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
void CI2COLED::sendCommand(uint8_t c0, uint8_t c1)
|
||||
{
|
||||
uint8_t buff[3U];
|
||||
|
||||
buff[0U] = SSD_Command_Mode;
|
||||
buff[1U] = c0;
|
||||
buff[2U] = c1;
|
||||
|
||||
// Write Data on I2C
|
||||
m_i2c.write(OLED_ADDRESS, buff, 3U);
|
||||
}
|
||||
|
||||
void CI2COLED::sendCommand(uint8_t c)
|
||||
{
|
||||
uint8_t buff[2U];
|
||||
|
||||
buff[0U] = SSD_Command_Mode;
|
||||
buff[1U] = c;
|
||||
|
||||
// Write Data on I2C
|
||||
m_i2c.write(OLED_ADDRESS, buff, 2U);
|
||||
}
|
||||
|
||||
void CI2COLED::sendData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
uint8_t buff[20U];
|
||||
|
||||
buff[0U] = SSD_Data_Mode;
|
||||
::memcpy(buff + 1U, data, length * sizeof(uint8_t));
|
||||
|
||||
// Write Data on I2C
|
||||
m_i2c.write(OLED_ADDRESS, buff, length + 1U);
|
||||
}
|
||||
|
||||
void CI2COLED::clear()
|
||||
{
|
||||
::memset(m_oledBuffer, 0x00U, OLED_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void CI2COLED::write(const char* text)
|
||||
{
|
||||
size_t len = ::strlen(text);
|
||||
|
||||
uint16_t scale = OLED_WIDTH / (len * (CHAR_WIDTH + 1U));
|
||||
if (scale == 0U) scale = 1U;
|
||||
|
||||
uint8_t charHeight = CHAR_HEIGHT * scale;
|
||||
uint8_t charWidth = (CHAR_WIDTH + 1U) * scale;
|
||||
|
||||
uint8_t x = (OLED_HEIGHT - charHeight) / 2U;
|
||||
uint8_t y = (OLED_WIDTH - charWidth) / 2U;
|
||||
|
||||
for (size_t i = 0U; i < len; i++) {
|
||||
write(x, y, text[i], scale);
|
||||
y += charWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void CI2COLED::write(uint8_t x, uint8_t y, char c, uint8_t size)
|
||||
{
|
||||
for (uint8_t i = 0U; i < 6U; i++) {
|
||||
uint8_t line;
|
||||
if (i == 5U)
|
||||
line = 0U;
|
||||
else
|
||||
line = FONT[(c * 5U) + i];
|
||||
|
||||
for (uint8_t j = 0U; j < 8U; j++) {
|
||||
if (line & 0x1U) {
|
||||
if (size == 1U) // default size
|
||||
drawPixel(x + i, y + j);
|
||||
else // big size
|
||||
fillRect(x + (i * size), y + (j * size), size, size);
|
||||
}
|
||||
|
||||
line >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CI2COLED::fillRect(uint8_t x, uint8_t y, uint8_t width, uint8_t height)
|
||||
{
|
||||
for (uint8_t i = x; i < (x + height - 1U); i++) {
|
||||
for (uint8_t j = y; j < (y + width - 1U); j++)
|
||||
drawPixel(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
void CI2COLED::drawPixel(uint8_t x, uint8_t y)
|
||||
{
|
||||
// Get where to do the change in the buffer
|
||||
uint8_t* p = m_oledBuffer + (x + (y / 8U) * OLED_WIDTH);
|
||||
|
||||
// x is which column
|
||||
*p |= _BV((y % 8U));
|
||||
}
|
||||
|
||||
void CI2COLED::display()
|
||||
{
|
||||
sendCommand(SSD1306_Set_Lower_Column_Start_Address | 0x00U); // Low col = 0
|
||||
sendCommand(SSD1306_Set_Higher_Column_Start_Address | 0x00U); // High col = 0
|
||||
sendCommand(SSD1306_Set_Start_Line | 0x00U); // Line #0
|
||||
|
||||
// loop trough all OLED buffer and send a bunch of 16 data byte in one transmission
|
||||
for (uint16_t i = 0U; i < OLED_BUFFER_SIZE; i += 16U)
|
||||
sendData(m_oledBuffer + i, 16U);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020,2021 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
|
||||
* 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"
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
|
||||
#if !defined(I2COLED_H)
|
||||
#define I2COLED_H
|
||||
|
||||
#include "I2C3.h"
|
||||
|
||||
class CI2COLED {
|
||||
public:
|
||||
CI2COLED();
|
||||
|
||||
void init();
|
||||
|
||||
void setMode(int state);
|
||||
|
||||
private:
|
||||
CI2C3 m_i2c;
|
||||
uint8_t* m_oledBuffer;
|
||||
|
||||
void write(const char* text);
|
||||
void write(uint8_t x, uint8_t y, char c, uint8_t size);
|
||||
void drawPixel(uint8_t x, uint8_t y);
|
||||
void fillRect(uint8_t x, uint8_t y, uint8_t width, uint8_t height);
|
||||
void clear();
|
||||
void display();
|
||||
|
||||
void sendCommand(uint8_t c);
|
||||
void sendCommand(uint8_t c0, uint8_t c1);
|
||||
void sendData(const uint8_t* c, uint16_t length);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -746,6 +746,7 @@ void CIO::setMode(MMDVM_STATE state)
|
||||
case STATE_M17: setM17Int(false); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(false); break;
|
||||
case STATE_FM: setFMInt(false); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
@@ -757,13 +758,10 @@ void CIO::setMode(MMDVM_STATE state)
|
||||
case STATE_M17: setM17Int(true); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(true); break;
|
||||
case STATE_FM: setFMInt(true); break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
oled.setMode(state);
|
||||
#endif
|
||||
|
||||
m_modemState = state;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2019,2020 by BG5HHP
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -190,10 +190,6 @@ void CIO::initInt()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
oled.init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::startInt()
|
||||
|
||||
+1
-8
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -217,7 +217,6 @@ static inline void GPIOInit()
|
||||
GPIOConfigPin(PORT_LED, PIN_LED, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_COS, PIN_COS, GPIO_CRL_CNF0_1);
|
||||
|
||||
#if defined(MODE_LEDS)
|
||||
GPIOConfigPin(PORT_DSTAR, PIN_DSTAR, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
|
||||
@@ -230,7 +229,6 @@ static inline void GPIOInit()
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
||||
@@ -359,9 +357,6 @@ void CIO::initInt()
|
||||
#if defined(STM32F1_POG)
|
||||
FancyLEDEffect();
|
||||
#endif
|
||||
#if defined(MODE_OLED)
|
||||
oled.init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::startInt()
|
||||
@@ -426,7 +421,6 @@ void CIO::setCOSInt(bool on)
|
||||
BB_COSLED = !!on;
|
||||
}
|
||||
|
||||
#if defined(MODE_LEDS)
|
||||
void CIO::setDStarInt(bool on)
|
||||
{
|
||||
BB_DSTAR = !!on;
|
||||
@@ -484,7 +478,6 @@ void CIO::setFMInt(bool on)
|
||||
BB_YSF = !!on;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void CIO::delayInt(unsigned int dly)
|
||||
{
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 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
|
||||
@@ -27,18 +27,17 @@ const unsigned int M17_FRAME_LENGTH_SYMBOLS = M17_FRAME_LENGTH_BITS / 2U;
|
||||
const unsigned int M17_FRAME_LENGTH_SAMPLES = M17_FRAME_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
|
||||
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
|
||||
const unsigned int M17_SYNC_LENGTH_SYMBOLS = M17_SYNC_LENGTH_BITS / 2U;
|
||||
const unsigned int M17_SYNC_LENGTH_SAMPLES = M17_SYNC_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t M17_LINK_SETUP_SYNC_BYTES[] = {0x55U, 0xF7U};
|
||||
const uint8_t M17_STREAM_SYNC_BYTES[] = {0xFFU, 0x5DU};
|
||||
const uint8_t M17_PACKET_SYNC_BYTES[] = {0x75U, 0xFFU};
|
||||
|
||||
const uint8_t M17_SYNC_BYTES_LENGTH = 2U;
|
||||
const uint8_t M17_EOF_SYNC_BYTES[] = {0x55U, 0x5DU};
|
||||
|
||||
const uint16_t M17_LINK_SETUP_SYNC_BITS = 0x55F7U;
|
||||
const uint16_t M17_STREAM_SYNC_BITS = 0xFF5DU;
|
||||
const uint16_t M17_PACKET_SYNC_BITS = 0x75FFU;
|
||||
const uint16_t M17_EOF_SYNC_BITS = 0x555DU;
|
||||
|
||||
// 5 5 F 7
|
||||
// 01 01 01 01 11 11 01 11
|
||||
@@ -56,13 +55,13 @@ const int8_t M17_STREAM_SYNC_SYMBOLS_VALUES[] = {-3, -3, -3, -3, +3, +3, -3, +3}
|
||||
|
||||
const uint8_t M17_STREAM_SYNC_SYMBOLS = 0x0DU;
|
||||
|
||||
// 7 5 F F
|
||||
// 01 11 01 01 11 11 11 11
|
||||
// +3 -3 +3 +3 -3 -3 -3 -3
|
||||
// 5 5 5 D
|
||||
// 01 01 01 01 01 01 11 01
|
||||
// +3 +3 +3 +3 +3 +3 -3 +3
|
||||
|
||||
const int8_t M17_PACKET_SYNC_SYMBOLS_VALUES[] = {+3, -3, +3, +3, -3, -3, -3, -3};
|
||||
const int8_t M17_EOF_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, +3, +3, -3, +3};
|
||||
|
||||
const uint8_t M17_PACKET_SYNC_SYMBOLS = 0xB0U;
|
||||
const uint8_t M17_EOF_SYNC_SYMBOLS = 0xFDU;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ void CM17RX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length)
|
||||
switch (m_state) {
|
||||
case M17RXS_LINK_SETUP:
|
||||
case M17RXS_STREAM:
|
||||
case M17RXS_PACKET:
|
||||
processData(sample);
|
||||
break;
|
||||
default:
|
||||
@@ -127,9 +126,8 @@ void CM17RX::processNone(q15_t sample)
|
||||
{
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
|
||||
if (ret1 || ret2 /* || ret3 */ ) {
|
||||
if (ret1 || ret2) {
|
||||
// On the first sync, start the countdown to the state change
|
||||
if (m_countdown == 0U) {
|
||||
m_rssiAccum = 0U;
|
||||
@@ -144,7 +142,6 @@ void CM17RX::processNone(q15_t sample)
|
||||
|
||||
if (ret1) m_nextState = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_nextState = M17RXS_STREAM;
|
||||
// if (ret3) m_nextState = M17RXS_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,28 +165,42 @@ void CM17RX::processNone(q15_t sample)
|
||||
|
||||
void CM17RX::processData(q15_t sample)
|
||||
{
|
||||
bool eof = false;
|
||||
|
||||
if (m_minSyncPtr < m_maxSyncPtr) {
|
||||
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) {
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret1) m_state = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_state = M17RXS_STREAM;
|
||||
// if (ret3) m_state = M17RXS_PACKET;
|
||||
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret) m_state = M17RXS_STREAM;
|
||||
}
|
||||
} else {
|
||||
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) {
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret1) m_state = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_state = M17RXS_STREAM;
|
||||
// if (ret3) m_state = M17RXS_PACKET;
|
||||
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret) m_state = M17RXS_STREAM;
|
||||
}
|
||||
}
|
||||
|
||||
if (eof) {
|
||||
DEBUG4("M17RX: eof sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
|
||||
io.setDecode(false);
|
||||
io.setADCDetection(false);
|
||||
|
||||
serial.writeM17EOT();
|
||||
|
||||
m_state = M17RXS_NONE;
|
||||
m_endPtr = NOENDPTR;
|
||||
m_averagePtr = NOAVEPTR;
|
||||
m_countdown = 0U;
|
||||
m_nextState = M17RXS_NONE;
|
||||
m_maxCorr = 0;
|
||||
}
|
||||
|
||||
if (m_dataPtr == m_endPtr) {
|
||||
// Only update the centre and threshold if they are from a good sync
|
||||
if (m_lostCount == MAX_SYNC_FRAMES) {
|
||||
@@ -211,9 +222,8 @@ void CM17RX::processData(q15_t sample)
|
||||
case M17RXS_STREAM:
|
||||
DEBUG4("M17RX: stream sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
break;
|
||||
case M17RXS_PACKET:
|
||||
DEBUG4("M17RX: packet sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t frame[M17_FRAME_LENGTH_BYTES + 3U];
|
||||
@@ -236,8 +246,7 @@ void CM17RX::processData(q15_t sample)
|
||||
m_nextState = M17RXS_NONE;
|
||||
m_maxCorr = 0;
|
||||
} else {
|
||||
frame[0U] = 0x00U;
|
||||
frame[0U] |= m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
|
||||
switch (m_state) {
|
||||
case M17RXS_LINK_SETUP:
|
||||
@@ -246,9 +255,8 @@ void CM17RX::processData(q15_t sample)
|
||||
case M17RXS_STREAM:
|
||||
writeRSSIStream(frame);
|
||||
break;
|
||||
case M17RXS_PACKET:
|
||||
writeRSSIPacket(frame);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_maxCorr = 0;
|
||||
@@ -308,11 +316,11 @@ bool CM17RX::correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues,
|
||||
if (startPtr >= M17_FRAME_LENGTH_SAMPLES)
|
||||
startPtr -= M17_FRAME_LENGTH_SAMPLES;
|
||||
|
||||
uint8_t sync[M17_SYNC_BYTES_LENGTH];
|
||||
uint8_t sync[M17_SYNC_LENGTH_BYTES];
|
||||
samplesToBits(startPtr, M17_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal);
|
||||
|
||||
uint8_t errs = 0U;
|
||||
for (uint8_t i = 0U; i < M17_SYNC_BYTES_LENGTH; i++)
|
||||
for (uint8_t i = 0U; i < M17_SYNC_LENGTH_BYTES; i++)
|
||||
errs += countBits8(sync[i] ^ syncBytes[i]);
|
||||
|
||||
if (errs <= maxBitErrs) {
|
||||
@@ -437,8 +445,8 @@ void CM17RX::writeRSSILinkSetup(uint8_t* data)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
data[49U] = (rssi >> 8) & 0xFFU;
|
||||
data[50U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
@@ -458,8 +466,8 @@ void CM17RX::writeRSSIStream(uint8_t* data)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
data[49U] = (rssi >> 8) & 0xFFU;
|
||||
data[50U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
@@ -473,26 +481,5 @@ void CM17RX::writeRSSIStream(uint8_t* data)
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
void CM17RX::writeRSSIPacket(uint8_t* data)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
#else
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
enum M17RX_STATE {
|
||||
M17RXS_NONE,
|
||||
M17RXS_LINK_SETUP,
|
||||
M17RXS_STREAM,
|
||||
M17RXS_PACKET
|
||||
M17RXS_STREAM
|
||||
};
|
||||
|
||||
class CM17RX {
|
||||
@@ -70,7 +69,6 @@ private:
|
||||
void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
|
||||
void writeRSSILinkSetup(uint8_t* data);
|
||||
void writeRSSIStream(uint8_t* data);
|
||||
void writeRSSIPacket(uint8_t* data);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -33,10 +33,10 @@ static q15_t RRC_0_5_FILTER[] = {0, 0, 0, 0, -290, -174, 142, 432, 438, 90, -387
|
||||
438, 432, 142, -174, -290}; // numTaps = 45, L = 5
|
||||
const uint16_t RRC_0_5_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L
|
||||
|
||||
const q15_t M17_LEVELA = 1683;
|
||||
const q15_t M17_LEVELB = 561;
|
||||
const q15_t M17_LEVELC = -561;
|
||||
const q15_t M17_LEVELD = -1683;
|
||||
const q15_t M17_LEVELA = 1481;
|
||||
const q15_t M17_LEVELB = 494;
|
||||
const q15_t M17_LEVELC = -494;
|
||||
const q15_t M17_LEVELD = -1481;
|
||||
|
||||
const uint8_t M17_START_SYNC = 0x77U;
|
||||
const uint8_t M17_END_SYNC = 0xFFU;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
@@ -41,10 +41,6 @@ bool m_duplex = true;
|
||||
bool m_tx = false;
|
||||
bool m_dcd = false;
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
CI2COLED oled;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
CDStarRX dstarRX;
|
||||
CDStarTX dstarTX;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -38,10 +38,6 @@ bool m_duplex = true;
|
||||
bool m_tx = false;
|
||||
bool m_dcd = false;
|
||||
|
||||
#if defined(MODE_OLED)
|
||||
CI2COLED oled;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
CDStarRX dstarRX;
|
||||
CDStarTX dstarTX;
|
||||
|
||||
+132
-61
@@ -67,6 +67,7 @@ const uint8_t MMDVM_M17_LINK_SETUP = 0x45U;
|
||||
const uint8_t MMDVM_M17_STREAM = 0x46U;
|
||||
const uint8_t MMDVM_M17_PACKET = 0x47U;
|
||||
const uint8_t MMDVM_M17_LOST = 0x48U;
|
||||
const uint8_t MMDVM_M17_EOT = 0x49U;
|
||||
|
||||
const uint8_t MMDVM_POCSAG_DATA = 0x50U;
|
||||
|
||||
@@ -84,6 +85,7 @@ const uint8_t MMDVM_ACK = 0x70U;
|
||||
const uint8_t MMDVM_NAK = 0x7FU;
|
||||
|
||||
const uint8_t MMDVM_SERIAL_DATA = 0x80U;
|
||||
const uint8_t MMDVM_I2C_DATA = 0x81U;
|
||||
|
||||
const uint8_t MMDVM_TRANSPARENT = 0x90U;
|
||||
const uint8_t MMDVM_QSO_INFO = 0x91U;
|
||||
@@ -133,7 +135,6 @@ const uint8_t PROTOCOL_VERSION = 2U;
|
||||
const int MAX_SERIAL_DATA = 250;
|
||||
const uint16_t MAX_SERIAL_COUNT = 100U;
|
||||
|
||||
|
||||
CSerialPort::CSerialPort() :
|
||||
m_buffer(),
|
||||
m_ptr(0U),
|
||||
@@ -141,30 +142,31 @@ m_len(0U),
|
||||
m_debug(false),
|
||||
m_serialData(),
|
||||
m_lastSerialAvail(0),
|
||||
m_lastSerialAvailCount(0U)
|
||||
m_lastSerialAvailCount(0U),
|
||||
m_i2CData()
|
||||
{
|
||||
}
|
||||
|
||||
void CSerialPort::sendACK()
|
||||
void CSerialPort::sendACK(uint8_t type)
|
||||
{
|
||||
uint8_t reply[4U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 4U;
|
||||
reply[2U] = MMDVM_ACK;
|
||||
reply[3U] = m_buffer[2U];
|
||||
reply[3U] = type;
|
||||
|
||||
writeInt(1U, reply, 4);
|
||||
}
|
||||
|
||||
void CSerialPort::sendNAK(uint8_t err)
|
||||
void CSerialPort::sendNAK(uint8_t type, uint8_t err)
|
||||
{
|
||||
uint8_t reply[5U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 5U;
|
||||
reply[2U] = MMDVM_NAK;
|
||||
reply[3U] = m_buffer[2U];
|
||||
reply[3U] = type;
|
||||
reply[4U] = err;
|
||||
|
||||
writeInt(1U, reply, 5);
|
||||
@@ -373,22 +375,41 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
|
||||
bool txInvert = (data[0U] & 0x02U) == 0x02U;
|
||||
bool pttInvert = (data[0U] & 0x04U) == 0x04U;
|
||||
#if defined(MODE_YSF)
|
||||
bool ysfLoDev = (data[0U] & 0x08U) == 0x08U;
|
||||
#endif
|
||||
bool useCOSAsLockout = (data[0U] & 0x20U) == 0x20U;
|
||||
bool simplex = (data[0U] & 0x80U) == 0x80U;
|
||||
|
||||
m_debug = (data[0U] & 0x10U) == 0x10U;
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
|
||||
#endif
|
||||
#if defined(MODE_DMR)
|
||||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||
#endif
|
||||
#if defined(MODE_YSF)
|
||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||
#endif
|
||||
#if defined(MODE_P25)
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
#endif
|
||||
#if defined(MODE_NXDN)
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
#endif
|
||||
#if defined(MODE_FM)
|
||||
bool fmEnable = (data[1U] & 0x20U) == 0x20U;
|
||||
#endif
|
||||
#if defined(MODE_M17)
|
||||
bool m17Enable = (data[1U] & 0x40U) == 0x40U;
|
||||
|
||||
#endif
|
||||
#if defined(MODE_POCSAG)
|
||||
bool pocsagEnable = (data[2U] & 0x01U) == 0x01U;
|
||||
#endif
|
||||
#if defined(MODE_AX25)
|
||||
bool ax25Enable = (data[2U] & 0x02U) == 0x02U;
|
||||
#endif
|
||||
|
||||
uint8_t txDelay = data[3U];
|
||||
if (txDelay > 50U)
|
||||
@@ -479,17 +500,28 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
uint8_t fmTXLevel = data[16U];
|
||||
uint8_t ax25TXLevel = data[17U];
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
uint8_t ysfTXHang = data[20U];
|
||||
#endif
|
||||
#if defined(MODE_P25)
|
||||
uint8_t p25TXHang = data[21U];
|
||||
#endif
|
||||
#if defined(MODE_NXDN)
|
||||
uint8_t nxdnTXHang = data[22U];
|
||||
#endif
|
||||
#if defined(MODE_M17)
|
||||
uint8_t m17TXHang = data[23U];
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
uint8_t colorCode = data[26U];
|
||||
if (colorCode > 15U)
|
||||
return 4U;
|
||||
|
||||
uint8_t dmrDelay = data[27U];
|
||||
#endif
|
||||
|
||||
#if defined(MODE_AX25)
|
||||
int8_t ax25RXTwist = int8_t(data[28U]) - 128;
|
||||
if (ax25RXTwist < -4 || ax25RXTwist > 10)
|
||||
return 4U;
|
||||
@@ -497,6 +529,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
uint8_t ax25TXDelay = data[29U];
|
||||
uint8_t ax25SlotTime = data[30U];
|
||||
uint8_t ax25PPersist = data[31U];
|
||||
#endif
|
||||
|
||||
setMode(modemState);
|
||||
|
||||
@@ -619,6 +652,7 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint16_t length)
|
||||
uint8_t hangTime = data[7U];
|
||||
|
||||
uint8_t accessMode = data[8U] & 0x0FU;
|
||||
bool linkMode = (data[8U] & 0x20U) == 0x20U;
|
||||
bool noiseSquelch = (data[8U] & 0x40U) == 0x40U;
|
||||
bool cosInvert = (data[8U] & 0x80U) == 0x80U;
|
||||
|
||||
@@ -629,7 +663,7 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint16_t length)
|
||||
uint8_t squelchHighThreshold = data[12U];
|
||||
uint8_t squelchLowThreshold = data[13U];
|
||||
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, cosInvert, noiseSquelch, squelchHighThreshold, squelchLowThreshold, rfAudioBoost, maxDev, rxLevel);
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, linkMode, cosInvert, noiseSquelch, squelchHighThreshold, squelchLowThreshold, rfAudioBoost, maxDev, rxLevel);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setFMParams4(const uint8_t* data, uint16_t length)
|
||||
@@ -858,6 +892,9 @@ void CSerialPort::start()
|
||||
#if defined(SERIAL_REPEATER)
|
||||
beginInt(3U, 9600);
|
||||
#endif
|
||||
#if defined(I2C_REPEATER)
|
||||
beginInt(10U, 9600);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSerialPort::process()
|
||||
@@ -935,13 +972,29 @@ void CSerialPort::process()
|
||||
}
|
||||
writeSerialData(buffer, serialAvail - m_lastSerialAvail);
|
||||
m_lastSerialAvailCount = 0U;
|
||||
} else if (serialAvail > 0U && serialAvail == m_lastSerialAvail) {
|
||||
} else if (serialAvail > 0 && serialAvail == m_lastSerialAvail) {
|
||||
m_lastSerialAvailCount++;
|
||||
} else {
|
||||
m_lastSerialAvail = serialAvail;
|
||||
m_lastSerialAvailCount = 0U;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(I2C_REPEATER)
|
||||
// Write any outgoing serial data
|
||||
uint16_t i2CSpace = m_i2CData.getData();
|
||||
if (i2CSpace > 0U) {
|
||||
int avail = availableForWriteInt(10U);
|
||||
if (avail < i2CSpace)
|
||||
i2CSpace = avail;
|
||||
|
||||
for (uint16_t i = 0U; i < i2CSpace; i++) {
|
||||
uint8_t c = 0U;
|
||||
m_i2CData.get(c);
|
||||
writeInt(10U, &c, 1U);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t length)
|
||||
@@ -960,61 +1013,61 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
case MMDVM_SET_CONFIG:
|
||||
err = setConfig(buffer, length);
|
||||
if (err == 0U)
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
else
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
break;
|
||||
|
||||
case MMDVM_SET_MODE:
|
||||
err = setMode(buffer, length);
|
||||
if (err == 0U)
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
else
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
break;
|
||||
|
||||
case MMDVM_SET_FREQ:
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
break;
|
||||
|
||||
#if defined(MODE_FM)
|
||||
case MMDVM_FM_PARAMS1:
|
||||
err = setFMParams1(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 1", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS2:
|
||||
err = setFMParams2(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 2", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS3:
|
||||
err = setFMParams3(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 3", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS4:
|
||||
err = setFMParams4(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 4", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
@@ -1022,7 +1075,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
case MMDVM_FM_PARAMS2:
|
||||
case MMDVM_FM_PARAMS3:
|
||||
case MMDVM_FM_PARAMS4:
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -1052,10 +1105,10 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = calPOCSAG.write(buffer, length);
|
||||
#endif
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid calibration data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1065,7 +1118,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = cwIdTX.write(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Invalid CW Id data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1080,7 +1133,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star header", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1094,7 +1147,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1108,7 +1161,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star EOT", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1126,7 +1179,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DMR);
|
||||
} else {
|
||||
DEBUG2("Received invalid DMR data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1144,7 +1197,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DMR);
|
||||
} else {
|
||||
DEBUG2("Received invalid DMR data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1165,7 +1218,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
}
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR start", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1174,7 +1227,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = dmrTX.writeShortLC(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR Short LC", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1183,7 +1236,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = dmrTX.writeAbort(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR Abort", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1199,7 +1252,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_YSF);
|
||||
} else {
|
||||
DEBUG2("Received invalid System Fusion data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1215,7 +1268,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_P25);
|
||||
} else {
|
||||
DEBUG2("Received invalid P25 header", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1229,7 +1282,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_P25);
|
||||
} else {
|
||||
DEBUG2("Received invalid P25 LDU", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1245,7 +1298,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_NXDN);
|
||||
} else {
|
||||
DEBUG2("Received invalid NXDN data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1261,7 +1314,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 link setup data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1275,11 +1328,11 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 stream data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_M17_PACKET:
|
||||
case MMDVM_M17_EOT:
|
||||
if (m_m17Enable) {
|
||||
if (m_modemState == STATE_IDLE || m_modemState == STATE_M17)
|
||||
err = m17TX.writeData(buffer, length);
|
||||
@@ -1288,8 +1341,8 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
if (m_modemState == STATE_IDLE)
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 packet data", err);
|
||||
sendNAK(err);
|
||||
DEBUG2("Received invalid M17 EOT", err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1305,7 +1358,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_POCSAG);
|
||||
} else {
|
||||
DEBUG2("Received invalid POCSAG data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1321,7 +1374,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_FM);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1334,7 +1387,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
}
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid AX.25 data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1352,9 +1405,17 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(I2C_REPEATER)
|
||||
case MMDVM_I2C_DATA: {
|
||||
for (uint16_t i = 0U; i < length; i++)
|
||||
m_i2CData.put(buffer[i]);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// Handle this, send a NAK back
|
||||
sendNAK(1U);
|
||||
sendNAK(type, 1U);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1681,7 +1742,7 @@ void CSerialPort::writeM17Stream(const uint8_t* data, uint8_t length)
|
||||
writeInt(1U, reply, count);
|
||||
}
|
||||
|
||||
void CSerialPort::writeM17Packet(const uint8_t* data, uint8_t length)
|
||||
void CSerialPort::writeM17EOT()
|
||||
{
|
||||
if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE)
|
||||
return;
|
||||
@@ -1689,19 +1750,13 @@ void CSerialPort::writeM17Packet(const uint8_t* data, uint8_t length)
|
||||
if (!m_m17Enable)
|
||||
return;
|
||||
|
||||
uint8_t reply[130U];
|
||||
uint8_t reply[3U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 0U;
|
||||
reply[2U] = MMDVM_M17_PACKET;
|
||||
reply[1U] = 3U;
|
||||
reply[2U] = MMDVM_M17_EOT;
|
||||
|
||||
uint8_t count = 3U;
|
||||
for (uint8_t i = 0U; i < length; i++, count++)
|
||||
reply[count] = data[i];
|
||||
|
||||
reply[1U] = count;
|
||||
|
||||
writeInt(1U, reply, count);
|
||||
writeInt(1U, reply, 3);
|
||||
}
|
||||
|
||||
void CSerialPort::writeM17Lost()
|
||||
@@ -1844,6 +1899,25 @@ void CSerialPort::writeSerialData(const uint8_t* data, uint8_t length)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(I2C_REPEATER)
|
||||
void CSerialPort::writeI2CData(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
uint8_t reply[255U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 0U;
|
||||
reply[2U] = MMDVM_I2C_DATA;
|
||||
|
||||
uint8_t count = 3U;
|
||||
for (uint8_t i = 0U; i < length; i++, count++)
|
||||
reply[count] = data[i];
|
||||
|
||||
reply[1U] = count;
|
||||
|
||||
writeInt(1U, reply, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (m_modemState != STATE_DSTARCAL)
|
||||
@@ -2016,9 +2090,6 @@ void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n
|
||||
|
||||
void CSerialPort::writeDebugDump(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length > 500U)
|
||||
length = 500U;
|
||||
|
||||
uint8_t reply[512U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
|
||||
+8
-3
@@ -67,8 +67,8 @@ public:
|
||||
#if defined(MODE_M17)
|
||||
void writeM17LinkSetup(const uint8_t* data, uint8_t length);
|
||||
void writeM17Stream(const uint8_t* data, uint8_t length);
|
||||
void writeM17Packet(const uint8_t* data, uint8_t length);
|
||||
void writeM17Lost();
|
||||
void writeM17EOT();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_AX25)
|
||||
@@ -85,6 +85,10 @@ public:
|
||||
void writeSerialData(const uint8_t* data, uint8_t length);
|
||||
#endif
|
||||
|
||||
#if defined(I2C_REPEATER)
|
||||
void writeI2CData(const uint8_t* data, uint8_t length);
|
||||
#endif
|
||||
|
||||
void writeCalData(const uint8_t* data, uint8_t length);
|
||||
void writeRSSIData(const uint8_t* data, uint8_t length);
|
||||
|
||||
@@ -103,9 +107,10 @@ private:
|
||||
CRingBuffer<uint8_t> m_serialData;
|
||||
int m_lastSerialAvail;
|
||||
uint16_t m_lastSerialAvailCount;
|
||||
CRingBuffer<uint8_t> m_i2CData;
|
||||
|
||||
void sendACK();
|
||||
void sendNAK(uint8_t err);
|
||||
void sendACK(uint8_t type);
|
||||
void sendNAK(uint8_t type, uint8_t err);
|
||||
void getStatus();
|
||||
void getVersion();
|
||||
uint8_t setConfig(const uint8_t* data, uint16_t length);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION "20210508"
|
||||
#define VERSION "20210919"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# mmdvmmenu.sh
|
||||
#
|
||||
# Copyright (C) 2016 by Paul Nannery KC2VRJ
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# On a Linux based system, such as a Raspberry Pi, this script will perform
|
||||
# Modification of the Config.h file for most options. It makes a Back up when
|
||||
# you start the script if none is present. You must recompile and load firmware
|
||||
# onto the Arduino Due if changes are made.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# CONFIGURATION
|
||||
#
|
||||
# Location of Config.h
|
||||
conf=Config.h
|
||||
#Location of backup file
|
||||
confbak=Config.h.bak
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Do not edit below here
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
||||
# Check for backup file and make one if not present
|
||||
|
||||
if [ ! -f $confbak ];then
|
||||
|
||||
cp -f $conf $confbak
|
||||
|
||||
fi
|
||||
|
||||
while :
|
||||
do
|
||||
clear
|
||||
cat<<EOF
|
||||
==============================================================
|
||||
MMDVM Configuration Options
|
||||
--------------------------------------------------------------
|
||||
Please enter your choice:
|
||||
|
||||
(1) Enable 12.000 MHZ Clock
|
||||
(2) Enable 12.288 MHZ Clock
|
||||
(3) Enable 14.400 MHz Clock
|
||||
(4) Enable 19.200 MHz Clock
|
||||
(5) Use the COS to lockout the modem
|
||||
(6) Use pins to output the current mode
|
||||
(7) Use layout for the PAPA board
|
||||
(8) Use layout for ZUM V1.0 and V1.0.1 boards
|
||||
(9) Use layout for SP8NTH board
|
||||
(0) Use modem as display driver
|
||||
(A) Return to Default
|
||||
|
||||
(Q)uit
|
||||
---------------------------------------------------------------
|
||||
EOF
|
||||
read -n1 -s
|
||||
case "$REPLY" in
|
||||
"1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.000 MHz clock enabled";;
|
||||
"2") sed -e 's/\/\/ #define EXTERNAL_OSC 12288000/#define EXTERNAL_OSC 12288000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.288 MHz clock enabled";;
|
||||
"3") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.400 MHz clock enabled";;
|
||||
"4") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.200 MHz clock enabled";;
|
||||
"5") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";;
|
||||
"6") sed -e 's/\/\/ #define MODE_LEDS/#define MODE_LEDS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins enabled";;
|
||||
"7") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";;
|
||||
"8") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.0.1 boards enabled";;
|
||||
"9") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";;
|
||||
"0") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";;
|
||||
"A") mv -f $confbak $conf ;;
|
||||
"a") mv -f $confbak $conf ;;
|
||||
"Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;;
|
||||
"q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;;
|
||||
* ) echo "invalid option" ;;
|
||||
esac
|
||||
sleep 1
|
||||
done
|
||||
Reference in New Issue
Block a user