I have another weird module, a combined nRF52832 and SX1262 module named Insight ISP4520.
This module uses DIO3 as a power supply for the antenna switch:
They have a sample code how to set DIO3 as output and put it to high level:
static void SX126xDio3Control (bool state)
{
uint8_t reg_0x0580;
uint8_t reg_0x0583;
uint8_t reg_0x0584;
uint8_t reg_0x0585;
uint8_t reg_0x0920;
if (state)
{
// Configure DIO3 as output
// Read 0x0580
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0580 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0583
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0583 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0584
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0584 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0585
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0585 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Write 0x0580
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0580 | 0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0583
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0583 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0584
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0584 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0585
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0585 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0920
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0x06);
GpioWrite (&SX126x.Spi.Nss, 1);
// Set DIO3 High
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0920 | 0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
}
else
{
// Set DIO3 Low
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0920 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
}
}
but I have problems to transform this to work within your library.
I didn't find a readRegister()
only a writeRegister()
function. So I tried to write readRegister()
, but found that the SPItransfer
when in read mode only transfers the command, but for reading the registers after the command it is required to send the register address.
So I needed to write a SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy)
functions that sends the two address bytes after the command and then reads the register values.
After I got that to work I changed above code to work with your library and added it as a function setDio3AsOutput(bool enable)
.
Not sure if others need something like that, but here are the functions I added:
SX126x::readRegister
int16_t SX126x::readRegister(uint16_t addr, uint8_t *data, uint8_t numBytes)
{
uint8_t *dat = new uint8_t[numBytes];
int16_t state = SPItransferAddr(SX126X_CMD_READ_REGISTER,
(uint8_t)((addr >> 8) & 0xFF),
(uint8_t)(addr & 0xFF),
false,
NULL,
dat,
numBytes,
true);
memcpy(data, dat, numBytes);
delete[] dat;
return (state);
}
int16_t SX126x::SPItransferAddr
int16_t SX126x::SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy)
{
// get pointer to used SPI interface and the settings
SPIClass *spi = _mod->getSpi();
SPISettings spiSettings = _mod->getSpiSettings();
// ensure BUSY is low (state meachine ready)
// TODO timeout
while (digitalRead(_mod->getRx()))
;
// start transfer
digitalWrite(_mod->getCs(), LOW);
spi->beginTransaction(spiSettings);
// send command byte
spi->transfer(cmd);
DEBUG_PRINT(cmd, HEX);
DEBUG_PRINT('\t');
// send addr byte 1
spi->transfer(addr1);
DEBUG_PRINT(addr1, HEX);
DEBUG_PRINT('\t');
// send addr byte 2
spi->transfer(addr2);
DEBUG_PRINT(addr2, HEX);
DEBUG_PRINT('\t');
// variable to save error during SPI transfer
uint8_t status = 0;
// send/receive all bytes
if (write)
{
for (uint8_t n = 0; n < numBytes; n++)
{
// send byte
uint8_t in = spi->transfer(dataOut[n]);
DEBUG_PRINT(dataOut[n], HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(in, HEX);
DEBUG_PRINT('\t');
// check status
if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
{
status = in;
}
}
DEBUG_PRINTLN();
}
else
{
// skip the first byte for read-type commands (status-only)
uint8_t in = spi->transfer(SX126X_CMD_NOP);
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(in, HEX);
DEBUG_PRINT('\t')
// check status
if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
{
status = in;
}
for (uint8_t n = 0; n < numBytes; n++)
{
dataIn[n] = spi->transfer(SX126X_CMD_NOP);
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(dataIn[n], HEX);
DEBUG_PRINT('\t');
}
DEBUG_PRINTLN();
}
// stop transfer
spi->endTransaction();
digitalWrite(_mod->getCs(), HIGH);
// wait for BUSY to go high and then low
// TODO timeout
if (waitForBusy)
{
delayMicroseconds(1);
while (digitalRead(_mod->getRx()))
;
}
// parse status
switch (status)
{
case SX126X_STATUS_CMD_TIMEOUT:
return (ERR_SPI_CMD_TIMEOUT);
case SX126X_STATUS_CMD_INVALID:
return (ERR_SPI_CMD_INVALID);
case SX126X_STATUS_CMD_FAILED:
return (ERR_SPI_CMD_FAILED);
default:
return (ERR_NONE);
}
}
SX126x::setDio3AsOutput
int16_t SX126x::setDio3AsOutput(bool enable)
{
uint8_t reg_0x0580;
uint8_t reg_0x0583;
uint8_t reg_0x0584;
uint8_t reg_0x0585;
uint8_t reg_0x0920;
int state;
if (enable)
{
state = readRegister(0x0580, ®_0x0580, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0583, ®_0x0583, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0584, ®_0x0584, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0585, ®_0x0585, 1);
if (state != ERR_NONE)
{
return state;
}
// Set the register values
reg_0x0580 = reg_0x0580 | 0x08;
reg_0x0583 = reg_0x0583 & ~0x08;
reg_0x0584 = reg_0x0584 & ~0x08;
reg_0x0585 = reg_0x0585 & ~0x08;
reg_0x0920 = 0x08;
state = writeRegister(0x0580, ®_0x0580, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0583, ®_0x0583, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0584, ®_0x0584, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0585, ®_0x0585, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
return ERR_NONE;
}
else
{
{
state = readRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
reg_0x0920 = reg_0x0920 & ~0x08;
state = writeRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
}
}
return ERR_NONE;
}
PS: I have no idea where Insight got the register addresses 0x0580, 0x0583, 0x0584, 0x0585 and 0x0920 from. They are not in the datasheets. I guess they got it from Semtech directly.