mirror of
https://github.com/g4klx/MMDVM_HS.git
synced 2025-12-06 07:02:00 +01:00
All tested compilers & make build now have proper timing for tx switching (gcc 4.9.3, O0, Os, O3, gcc 6.3. O0, O3)
This commit is contained in:
parent
02ee23b684
commit
70457f269e
61
ADF7021.cpp
61
ADF7021.cpp
|
|
@ -34,8 +34,6 @@ volatile uint32_t AD7021_control_word;
|
||||||
uint32_t ADF7021_RX_REG0;
|
uint32_t ADF7021_RX_REG0;
|
||||||
uint32_t ADF7021_TX_REG0;
|
uint32_t ADF7021_TX_REG0;
|
||||||
|
|
||||||
volatile bool sle_request = false;
|
|
||||||
|
|
||||||
static void Send_AD7021_control_shift()
|
static void Send_AD7021_control_shift()
|
||||||
{
|
{
|
||||||
int AD7021_counter;
|
int AD7021_counter;
|
||||||
|
|
@ -51,34 +49,24 @@ static void Send_AD7021_control_shift()
|
||||||
io.dlybit();
|
io.dlybit();
|
||||||
io.SCLK_pin(LOW);
|
io.SCLK_pin(LOW);
|
||||||
}
|
}
|
||||||
|
// to keep SDATA signal at defined level when idle (not required)
|
||||||
|
io.SDATA_pin(LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Send_AD7021_control_nosle()
|
static void Send_AD7021_control_slePulse()
|
||||||
{
|
{
|
||||||
Send_AD7021_control_shift();
|
|
||||||
sle_request = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Send_AD7021_control()
|
|
||||||
{
|
|
||||||
int AD7021_counter;
|
|
||||||
|
|
||||||
for(AD7021_counter = 31; AD7021_counter >= 0; AD7021_counter--) {
|
|
||||||
if(bitRead(AD7021_control_word, AD7021_counter) == HIGH)
|
|
||||||
io.SDATA_pin(HIGH);
|
|
||||||
else
|
|
||||||
io.SDATA_pin(LOW);
|
|
||||||
|
|
||||||
io.dlybit();
|
|
||||||
io.SCLK_pin(HIGH);
|
|
||||||
io.dlybit();
|
|
||||||
io.SCLK_pin(LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
io.SLE_pin(HIGH);
|
io.SLE_pin(HIGH);
|
||||||
io.dlybit();
|
io.dlybit();
|
||||||
io.SLE_pin(LOW);
|
io.SLE_pin(LOW);
|
||||||
io.SDATA_pin(LOW);
|
}
|
||||||
|
|
||||||
|
void Send_AD7021_control(bool doSle)
|
||||||
|
{
|
||||||
|
Send_AD7021_control_shift();
|
||||||
|
|
||||||
|
if (doSle) {
|
||||||
|
Send_AD7021_control_slePulse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SEND_RSSI_DATA)
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
|
@ -415,31 +403,36 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
|
||||||
//======================================================================================================================
|
//======================================================================================================================
|
||||||
void CIO::setTX()
|
void CIO::setTX()
|
||||||
{
|
{
|
||||||
// Send register 0 for TX operation
|
// PTT pin on (doing it earlier helps to measure timing impact)
|
||||||
|
PTT_pin(HIGH);
|
||||||
|
|
||||||
|
// Send register 0 for TX operation, but do not activate yet.
|
||||||
|
// This is done in the interrupt at the correct time
|
||||||
AD7021_control_word = ADF7021_TX_REG0;
|
AD7021_control_word = ADF7021_TX_REG0;
|
||||||
Send_AD7021_control_nosle();
|
Send_AD7021_control(false);
|
||||||
|
|
||||||
|
|
||||||
#if defined(BIDIR_DATA_PIN)
|
#if defined(BIDIR_DATA_PIN)
|
||||||
Data_dir_out(true); // Data pin output mode
|
Data_dir_out(true); // Data pin output mode
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// PTT pin on
|
|
||||||
PTT_pin(HIGH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================================================================
|
//======================================================================================================================
|
||||||
void CIO::setRX()
|
void CIO::setRX(bool doSle)
|
||||||
{
|
{
|
||||||
// Send register 0 for RX operation
|
// PTT pin off (doing it earlier helps to measure timing impact)
|
||||||
|
PTT_pin(LOW);
|
||||||
|
|
||||||
|
// Send register 0 for RX operation, but do not activate yet.
|
||||||
|
// This is done in the interrupt at the correct time
|
||||||
AD7021_control_word = ADF7021_RX_REG0;
|
AD7021_control_word = ADF7021_RX_REG0;
|
||||||
Send_AD7021_control();
|
Send_AD7021_control(doSle);
|
||||||
|
|
||||||
#if defined(BIDIR_DATA_PIN)
|
#if defined(BIDIR_DATA_PIN)
|
||||||
Data_dir_out(false); // Data pin input mode
|
Data_dir_out(false); // Data pin input mode
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// PTT pin off
|
|
||||||
PTT_pin(LOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO::setLoDevYSF(bool on)
|
void CIO::setLoDevYSF(bool on)
|
||||||
|
|
|
||||||
|
|
@ -267,8 +267,8 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
||||||
|
|
||||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
|
||||||
void Send_AD7021_control(void);
|
void Send_AD7021_control(bool doSle = true);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
83
IO.cpp
83
IO.cpp
|
|
@ -29,9 +29,11 @@ uint32_t m_frequency_rx;
|
||||||
uint32_t m_frequency_tx;
|
uint32_t m_frequency_tx;
|
||||||
uint8_t m_power;
|
uint8_t m_power;
|
||||||
|
|
||||||
extern volatile bool sle_request;
|
// TODO: move to IO class as members
|
||||||
|
volatile bool totx_request = false;
|
||||||
volatile bool torx_request = false;
|
volatile bool torx_request = false;
|
||||||
bool volatile even = true;
|
volatile bool even = true;
|
||||||
|
static uint32_t last_clk = 2;
|
||||||
|
|
||||||
CIO::CIO():
|
CIO::CIO():
|
||||||
m_started(false),
|
m_started(false),
|
||||||
|
|
@ -101,8 +103,7 @@ void CIO::process()
|
||||||
|
|
||||||
// Switch off the transmitter if needed
|
// Switch off the transmitter if needed
|
||||||
if (m_txBuffer.getData() == 0U && m_tx) {
|
if (m_txBuffer.getData() == 0U && m_tx) {
|
||||||
//while(CLK_pin()==0) { asm volatile ("nop"); }
|
setRX(false);
|
||||||
//while(CLK_pin()) { asm volatile ("nop"); }
|
|
||||||
torx_request = true;
|
torx_request = true;
|
||||||
while(torx_request) { asm volatile ("nop"); }
|
while(torx_request) { asm volatile ("nop"); }
|
||||||
}
|
}
|
||||||
|
|
@ -158,13 +159,33 @@ void CIO::interrupt()
|
||||||
if (!m_started)
|
if (!m_started)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t clk = CLK_pin();
|
uint8_t clk = CLK_pin();
|
||||||
|
|
||||||
|
// this is to prevent activation by spurious interrupts
|
||||||
|
// which seem to happen if you send out an control word
|
||||||
|
// needs investigation
|
||||||
|
// this workaround will fail if only rising or falling edge
|
||||||
|
// is used to trigger the interrupt !!!!
|
||||||
|
// TODO: figure out why sending the control word seems to issue interrupts
|
||||||
|
// possibly this is a design problem of the RF7021 board or too long wires
|
||||||
|
// on the breadboard build
|
||||||
|
// but normally this will not hurt too much
|
||||||
|
if (clk == last_clk) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
last_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock
|
// we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock
|
||||||
if (m_tx && clk == 0) {
|
if (m_tx && clk == 0) {
|
||||||
|
|
||||||
m_txBuffer.get(bit);
|
m_txBuffer.get(bit);
|
||||||
even = !even;
|
even = !even;
|
||||||
|
|
||||||
|
// use this for tracking issues
|
||||||
|
// P25_pin(even);
|
||||||
|
|
||||||
#if defined(BIDIR_DATA_PIN)
|
#if defined(BIDIR_DATA_PIN)
|
||||||
if(bit)
|
if(bit)
|
||||||
RXD_pin_write(HIGH);
|
RXD_pin_write(HIGH);
|
||||||
|
|
@ -177,21 +198,26 @@ void CIO::interrupt()
|
||||||
TXD_pin(LOW);
|
TXD_pin(LOW);
|
||||||
#endif
|
#endif
|
||||||
// wait a brief period before raising SLE
|
// wait a brief period before raising SLE
|
||||||
if (sle_request == true) {
|
if (totx_request == true) {
|
||||||
#if 1
|
asm volatile("nop \n\t"
|
||||||
asm volatile("mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
);
|
||||||
);
|
|
||||||
#endif
|
// SLE Pulse, should be moved out of here into class method
|
||||||
|
// according to datasheet in 4FSK we have to deliver this before 1/4 tbit == 26uS
|
||||||
SLE_pin(HIGH);
|
SLE_pin(HIGH);
|
||||||
asm volatile("mov r8, r8 \n\t"
|
asm volatile("nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
);
|
);
|
||||||
SLE_pin(LOW);
|
SLE_pin(LOW);
|
||||||
SDATA_pin(LOW);
|
SDATA_pin(LOW);
|
||||||
sle_request = false;
|
|
||||||
|
// now do housekeeping
|
||||||
|
totx_request = false;
|
||||||
|
// first tranmittted bit is always the odd bit
|
||||||
|
even = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we sample the RX bit at rising TXD clock edge, so TXD must be 1 and we are not in tx mode
|
// we sample the RX bit at rising TXD clock edge, so TXD must be 1 and we are not in tx mode
|
||||||
|
|
@ -203,10 +229,26 @@ void CIO::interrupt()
|
||||||
|
|
||||||
m_rxBuffer.put(bit);
|
m_rxBuffer.put(bit);
|
||||||
}
|
}
|
||||||
if (torx_request == true && even == true && m_tx && clk == 0) {
|
if (torx_request == true && even == false && m_tx && clk == 0) {
|
||||||
setRX();
|
// that is absolutely crucial in 4FSK, see datasheet:
|
||||||
|
// enable sle after 1/4 tBit == 26uS when sending MSB (even == false) and clock is low
|
||||||
|
delay_us(26);
|
||||||
|
|
||||||
|
// SLE Pulse, should be moved out of here into class method
|
||||||
|
SLE_pin(HIGH);
|
||||||
|
asm volatile("nop \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
);
|
||||||
|
SLE_pin(LOW);
|
||||||
|
SDATA_pin(LOW);
|
||||||
|
|
||||||
|
// now do housekeeping
|
||||||
m_tx = false;
|
m_tx = false;
|
||||||
torx_request = false;
|
torx_request = false;
|
||||||
|
//last tranmittted bit is always the even bit
|
||||||
|
// since the current bit is a transitional "don't care" bit, never transmitted
|
||||||
|
even = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -274,6 +316,9 @@ void CIO::write(uint8_t* data, uint16_t length)
|
||||||
// Switch the transmitter on if needed
|
// Switch the transmitter on if needed
|
||||||
if (!m_tx) {
|
if (!m_tx) {
|
||||||
setTX();
|
setTX();
|
||||||
|
totx_request = true;
|
||||||
|
// not sure if needed, would be better if handled in interrupt (like torx_request)
|
||||||
|
// or move into setTX()
|
||||||
while(CLK_pin());
|
while(CLK_pin());
|
||||||
m_tx = true;
|
m_tx = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
IO.h
3
IO.h
|
|
@ -90,7 +90,7 @@ public:
|
||||||
|
|
||||||
// RF interface API
|
// RF interface API
|
||||||
void setTX(void);
|
void setTX(void);
|
||||||
void setRX(void);
|
void setRX(bool doSle = true);
|
||||||
void ifConf(MMDVM_STATE modemState, bool reset);
|
void ifConf(MMDVM_STATE modemState, bool reset);
|
||||||
void start(void);
|
void start(void);
|
||||||
void startInt(void);
|
void startInt(void);
|
||||||
|
|
@ -102,6 +102,7 @@ public:
|
||||||
// Misc functions
|
// Misc functions
|
||||||
void dlybit(void);
|
void dlybit(void);
|
||||||
void delay_rx(void);
|
void delay_rx(void);
|
||||||
|
void delay_us(uint32_t us);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -280,9 +280,9 @@ void CIO::COS_pin(bool on)
|
||||||
digitalWrite(PIN_COS_LED, on ? HIGH : LOW);
|
digitalWrite(PIN_COS_LED, on ? HIGH : LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Investigate why. In fact there is just a single place where this is being use
|
void CIO::delay_us(uint32_t us) {
|
||||||
// during normal operation
|
::delayMicroseconds(us);
|
||||||
#pragma GCC optimize ("O0")
|
}
|
||||||
void CIO::dlybit(void)
|
void CIO::dlybit(void)
|
||||||
{
|
{
|
||||||
asm volatile("nop \n\t"
|
asm volatile("nop \n\t"
|
||||||
|
|
|
||||||
13
IOSTM.cpp
13
IOSTM.cpp
|
|
@ -579,16 +579,15 @@ void CIO::delay_rx() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIO::delay_us(uint32_t us) {
|
||||||
|
::delay_us(us);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Investigate why. In fact there is just a single place where this is being use
|
|
||||||
// during normal operation
|
|
||||||
// it seems that optimizing this code breaks some timings
|
|
||||||
#pragma GCC optimize ("O0")
|
|
||||||
static inline void delay_ns() {
|
static inline void delay_ns() {
|
||||||
|
|
||||||
asm volatile("mov r8, r8 \n\t"
|
asm volatile("nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
"mov r8, r8 \n\t"
|
"nop \n\t"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue