kopia lustrzana https://github.com/OpenRTX/OpenRTX
HR_Cx000: driver refactoring
- removed the Cx000_uSpiBusy() function. - HR_Cx000 class is no more singleton. - added constructor parameters for USPI interface.pull/292/head
rodzic
eda8d5d835
commit
c34e4462c2
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Copyright (C) 2021 - 2024 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Copyright (C) 2020 - 2024 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
|
@ -63,10 +63,6 @@ template< class M >
|
|||
void HR_Cx000< M >::terminate()
|
||||
{
|
||||
gpio_setPin(DMR_SLEEP);
|
||||
gpio_setMode(DMR_CS, INPUT);
|
||||
gpio_setMode(DMR_CLK, INPUT);
|
||||
gpio_setMode(DMR_MOSI, INPUT);
|
||||
gpio_setMode(DMR_MISO, INPUT);
|
||||
gpio_setMode(DMR_SLEEP, INPUT);
|
||||
}
|
||||
|
||||
|
@ -186,47 +182,3 @@ void HR_Cx000< M >::stopAnalogTx()
|
|||
{
|
||||
writeReg(M::CONFIG, 0x60, 0x00); // Disable both analog and DMR transmission
|
||||
}
|
||||
|
||||
/*
|
||||
* SPI interface driver
|
||||
*/
|
||||
template< class M >
|
||||
void HR_Cx000< M >::uSpi_init()
|
||||
{
|
||||
gpio_setMode(DMR_CS, OUTPUT);
|
||||
gpio_setMode(DMR_CLK, OUTPUT);
|
||||
gpio_setMode(DMR_MOSI, OUTPUT);
|
||||
gpio_setMode(DMR_MISO, OUTPUT);
|
||||
|
||||
// Deselect HR_C5000, idle state of the CS line.
|
||||
gpio_setPin(DMR_CS);
|
||||
}
|
||||
|
||||
template< class M >
|
||||
uint8_t HR_Cx000< M >::uSpi_sendRecv(const uint8_t value)
|
||||
{
|
||||
gpio_clearPin(DMR_CLK);
|
||||
|
||||
uint8_t incoming = 0;
|
||||
|
||||
for(uint8_t cnt = 0; cnt < 8; cnt++)
|
||||
{
|
||||
gpio_setPin(DMR_CLK);
|
||||
|
||||
if(value & (0x80 >> cnt))
|
||||
{
|
||||
gpio_setPin(DMR_MOSI);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_clearPin(DMR_MOSI);
|
||||
}
|
||||
|
||||
delayUs(1);
|
||||
gpio_clearPin(DMR_CLK);
|
||||
incoming = (incoming << 1) | gpio_readPin(DMR_MISO);
|
||||
delayUs(1);
|
||||
}
|
||||
|
||||
return incoming;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Copyright (C) 2021 - 2024 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
|
|
|
@ -140,7 +140,6 @@ template< class M >
|
|||
void HR_Cx000< M >::terminate()
|
||||
{
|
||||
gpio_setPin(DMR_SLEEP);
|
||||
gpio_setMode(DMR_CS, INPUT);
|
||||
}
|
||||
|
||||
template< class M >
|
||||
|
|
|
@ -52,9 +52,7 @@ template class HR_Cx000 < C6000_SpiOpModes >;
|
|||
template< class M >
|
||||
void HR_Cx000< M >::init()
|
||||
{
|
||||
gpio_setMode(DMR_CS, OUTPUT);
|
||||
gpio_setMode(DMR_SLEEP, OUTPUT);
|
||||
|
||||
gpio_setPin(DMR_SLEEP);
|
||||
|
||||
delayMs(10);
|
||||
|
@ -117,7 +115,6 @@ template< class M >
|
|||
void HR_Cx000< M >::terminate()
|
||||
{
|
||||
gpio_setPin(DMR_SLEEP);
|
||||
gpio_setMode(DMR_CS, INPUT);
|
||||
}
|
||||
|
||||
template< class M >
|
||||
|
@ -226,47 +223,3 @@ void HR_Cx000< M >::stopAnalogTx()
|
|||
writeReg(M::CONFIG, 0x34, 0x98); // FM bpf enabled, 25kHz bandwidth
|
||||
writeReg(M::CONFIG, 0x26, 0xFD); // Undocumented register, enable FM receive
|
||||
}
|
||||
|
||||
/*
|
||||
* SPI interface driver
|
||||
*/
|
||||
template< class M >
|
||||
void HR_Cx000< M >::uSpi_init()
|
||||
{
|
||||
gpio_setMode(DMR_CS, OUTPUT);
|
||||
gpio_setMode(DMR_CLK, OUTPUT);
|
||||
gpio_setMode(DMR_MOSI, OUTPUT);
|
||||
gpio_setMode(DMR_MISO, OUTPUT);
|
||||
|
||||
// Deselect HR_C6000, idle state of the CS line.
|
||||
gpio_setPin(DMR_CS);
|
||||
}
|
||||
|
||||
template< class M >
|
||||
uint8_t HR_Cx000< M >::uSpi_sendRecv(const uint8_t value)
|
||||
{
|
||||
gpio_clearPin(DMR_CLK);
|
||||
|
||||
uint8_t incoming = 0;
|
||||
|
||||
for(uint8_t cnt = 0; cnt < 8; cnt++)
|
||||
{
|
||||
gpio_setPin(DMR_CLK);
|
||||
|
||||
if(value & (0x80 >> cnt))
|
||||
{
|
||||
gpio_setPin(DMR_MOSI);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_clearPin(DMR_MOSI);
|
||||
}
|
||||
|
||||
delayUs(1);
|
||||
gpio_clearPin(DMR_CLK);
|
||||
incoming = (incoming << 1) | gpio_readPin(DMR_MISO);
|
||||
delayUs(1);
|
||||
}
|
||||
|
||||
return incoming;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Copyright (C) 2021 - 2024 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
|
@ -26,11 +26,6 @@
|
|||
#include "HR_C5000.h"
|
||||
#include "HR_C6000.h"
|
||||
|
||||
bool Cx000_uSpiBusy()
|
||||
{
|
||||
return (gpio_readPin(DMR_CS) == 0) ? true : false;
|
||||
}
|
||||
|
||||
template <>
|
||||
void HR_Cx000< C5000_SpiOpModes >::setDacGain(int8_t gain)
|
||||
{
|
||||
|
@ -120,16 +115,22 @@ void HR_Cx000< C6000_SpiOpModes >::setInputGain(int8_t value)
|
|||
writeReg(C6000_SpiOpModes::CONFIG, 0xE4, regValue);
|
||||
}
|
||||
|
||||
ScopedChipSelect::ScopedChipSelect()
|
||||
ScopedChipSelect::ScopedChipSelect(const struct spiDevice *spi,
|
||||
const struct gpioPin& cs) : spi(spi), cs(cs)
|
||||
{
|
||||
gpio_clearPin(DMR_CS);
|
||||
spi_acquire(spi);
|
||||
gpioPin_clear(&cs);
|
||||
}
|
||||
|
||||
ScopedChipSelect::~ScopedChipSelect()
|
||||
{
|
||||
// NOTE: it seems that, without the 2us delays before and after the nCS
|
||||
// deassertion, the HR_C6000 doesn't work properly. At least this is what
|
||||
// has been observed on the Retevis RT3s.
|
||||
delayUs(2);
|
||||
gpio_setPin(DMR_CS);
|
||||
gpioPin_set(&cs);
|
||||
delayUs(2);
|
||||
spi_release(spi);
|
||||
}
|
||||
|
||||
FmConfig operator |(FmConfig lhs, FmConfig rhs)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Copyright (C) 2021 - 2024 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
|
@ -21,29 +21,12 @@
|
|||
#ifndef HRCx000_H
|
||||
#define HRCx000_H
|
||||
|
||||
#include <peripherals/gpio.h>
|
||||
#include <peripherals/spi.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if "user" SPI bus, on some platforms shared between the baseband and
|
||||
* other chips, is in use by the HR_Cx000 driver. This function is callable
|
||||
* either from C or C++ sources.
|
||||
*
|
||||
* WARNING: this function is NOT thread safe! A proper critical section has to
|
||||
* be set up to ensure it is accessed by one task at a time.
|
||||
*
|
||||
* @return true if SPI lines are being used by this driver.
|
||||
*/
|
||||
bool Cx000_uSpiBusy();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for analog FM mode.
|
||||
* Each option is tied to a particular bit of the Configuration register 0x34.
|
||||
|
@ -66,32 +49,26 @@ enum class TxAudioSource
|
|||
LINE_IN ///< Audio source is "line in", e.g. tone generator.
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic driver for HR_C5000/HR_C6000 "baseband" chip.
|
||||
*
|
||||
*
|
||||
* WARNING: on some MDx devices the PLL and DMR chips share the SPI MOSI line,
|
||||
* thus particular care has to be put to avoid them stomping reciprocally.
|
||||
* This driver does not make any check if a SPI transfer is already in progress,
|
||||
* deferring the correct bus management to higher level modules. However,
|
||||
* a function returning true if the bus is currently in use by this driver is
|
||||
* provided.
|
||||
*/
|
||||
|
||||
class ScopedChipSelect;
|
||||
|
||||
/**
|
||||
* Generic driver for HR_C5000/HR_C6000 "baseband" chip.
|
||||
*/
|
||||
template< class M >
|
||||
class HR_Cx000
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* \return a reference to the instance of the AT1846S class (singleton).
|
||||
* Constructor.
|
||||
*
|
||||
* @param dev: pointer to chip's hardware interface descriptor.
|
||||
*/
|
||||
static HR_Cx000& instance()
|
||||
HR_Cx000(const struct spiDevice *uSpi, const struct gpioPin uCs) : uSpi(uSpi), uCs(uCs)
|
||||
{
|
||||
static HR_Cx000< M > Cx000;
|
||||
return Cx000;
|
||||
// Configure chip select pin
|
||||
gpioPin_setMode(&uCs, OUTPUT);
|
||||
gpioPin_set(&uCs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,6 +78,7 @@ public:
|
|||
~HR_Cx000()
|
||||
{
|
||||
terminate();
|
||||
gpioPin_setMode(&uCs, INPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,15 +190,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
HR_Cx000()
|
||||
{
|
||||
// Being a singleton class, uSPI is initialised only once.
|
||||
uSpi_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for register writing.
|
||||
*
|
||||
|
@ -230,10 +199,14 @@ private:
|
|||
*/
|
||||
void writeReg(const M opMode, const uint8_t addr, const uint8_t value)
|
||||
{
|
||||
ScopedChipSelect cs;
|
||||
(void) uSpi_sendRecv(static_cast< uint8_t >(opMode));
|
||||
(void) uSpi_sendRecv(addr);
|
||||
(void) uSpi_sendRecv(value);
|
||||
uint8_t data[3];
|
||||
|
||||
data[0] = static_cast< uint8_t >(opMode);
|
||||
data[1] = addr;
|
||||
data[2] = value;
|
||||
|
||||
ScopedChipSelect cs(uSpi, uCs);
|
||||
spi_send(uSpi, data, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,10 +218,17 @@ private:
|
|||
*/
|
||||
uint8_t readReg(const M opMode, const uint8_t addr)
|
||||
{
|
||||
ScopedChipSelect cs;
|
||||
(void) uSpi_sendRecv(static_cast< uint8_t >(opMode) | 0x80);
|
||||
(void) uSpi_sendRecv(addr);
|
||||
return uSpi_sendRecv(0x00);
|
||||
uint8_t cmd[3];
|
||||
uint8_t ret[3];
|
||||
|
||||
cmd[0] = 0x80 | static_cast< uint8_t >(opMode);
|
||||
cmd[1] = addr;
|
||||
cmd[2] = 0x00;
|
||||
|
||||
ScopedChipSelect cs(uSpi, uCs);
|
||||
spi_transfer(uSpi, cmd, ret, 3);
|
||||
|
||||
return ret[2];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,26 +240,12 @@ private:
|
|||
*/
|
||||
void sendSequence(const uint8_t *seq, const size_t len)
|
||||
{
|
||||
ScopedChipSelect cs;
|
||||
for(size_t i = 0; i < len; i++)
|
||||
{
|
||||
(void) uSpi_sendRecv(seq[i]);
|
||||
}
|
||||
ScopedChipSelect cs(uSpi, uCs);
|
||||
spi_send(uSpi, seq, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the low-level driver which manages "user" SPI interface, that
|
||||
* is the one used to configure the chipset functionalities.
|
||||
*/
|
||||
void uSpi_init();
|
||||
|
||||
/**
|
||||
* Transfer one byte across the "user" SPI interface.
|
||||
*
|
||||
* @param value: value to be sent.
|
||||
* @return incoming byte from the baseband chip.
|
||||
*/
|
||||
uint8_t uSpi_sendRecv(const uint8_t value);
|
||||
const struct spiDevice *uSpi;
|
||||
const struct gpioPin uCs;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -299,19 +265,23 @@ public:
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
* When called it brings the HR_C5000/HR_C6000 chip select to logical low,
|
||||
* selecting it.
|
||||
* When called it acquires exclusive ownership on the "user" SPI bus and
|
||||
* brings the HR_C5000/HR_C6000 chip select to logical low.
|
||||
*
|
||||
* @param dev: pointer to device interface.
|
||||
*/
|
||||
ScopedChipSelect();
|
||||
ScopedChipSelect(const struct spiDevice *spi, const struct gpioPin& cs);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* When called it brings the HR_C5000/HR_C6000 chip select to logical high,
|
||||
* deselecting it.
|
||||
* and releases exclusive ownership on the "user" SPI bus.
|
||||
*/
|
||||
~ScopedChipSelect();
|
||||
|
||||
private:
|
||||
const struct spiDevice *spi;
|
||||
const struct gpioPin& cs;
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // HRCx000_H
|
||||
|
|
Ładowanie…
Reference in New Issue