diff --git a/platform/drivers/baseband/SKY72310.c b/platform/drivers/baseband/SKY72310.c
index 13bc3d18..69c57db3 100644
--- a/platform/drivers/baseband/SKY72310.c
+++ b/platform/drivers/baseband/SKY72310.c
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2020 - 2023 by Silvano Seva IU2KWO *
+ * Copyright (C) 2020 - 2024 by Silvano Seva IU2KWO *
* and Niccolò Izzo IU2KIN *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -16,78 +16,58 @@
* along with this program; if not, see *
***************************************************************************/
-#include
#include
-#include
#include
#include "SKY72310.h"
-#define REF_CLK 16800000.0F /* Reference clock: 16.8MHz */
-#define PHD_GAIN 0x1F /* Phase detector gain: hex value, max 0x1F */
-
-void _spiSend(uint16_t value)
+static inline void writeReg(const struct sky73210 *dev, const uint16_t value)
{
- uint16_t temp = value;
+ const uint16_t tmp = __builtin_bswap16(value);
- gpio_clearPin(PLL_CS);
+ /*
+ * NOTE: for some (yet) unknown reason, there must be at least 10us between
+ * chip select assertion/deassertion and the SPI transaction. For lower
+ * values the PLL seems to go nuts.
+ */
+ spi_acquire(dev->spi);
+ gpioPin_clear(&dev->cs);
delayUs(10);
- for(uint8_t i = 0; i < 16; i++)
- {
- gpio_setPin(PLL_CLK);
- delayUs(1);
-
- if(temp & 0x8000)
- {
- gpio_setPin(PLL_DAT);
- }
- else
- {
- gpio_clearPin(PLL_DAT);
- }
-
- temp <<= 1;
-
- delayUs(1);
- gpio_clearPin(PLL_CLK);
- delayUs(1);
- }
-
- gpio_setPin(PLL_CLK);
+ spi_send(dev->spi, &tmp, 2);
delayUs(10);
- gpio_setPin(PLL_CS);
+ gpioPin_set(&dev->cs);
+ spi_release(dev->spi);
}
-void SKY73210_init()
-{
- gpio_setMode(PLL_CLK, OUTPUT);
- gpio_setMode(PLL_DAT, OUTPUT);
- gpio_setMode(PLL_CS, OUTPUT);
- gpio_setPin(PLL_CS);
- gpio_setMode(PLL_LD, INPUT);
- _spiSend(0x6000 | ((uint16_t) PHD_GAIN)); /* Phase detector gain */
- _spiSend(0x73D0); /* Power down/multiplexer control register */
- _spiSend(0x8000); /* Modulation control register */
- _spiSend(0x9000); /* Modulation data register */
+void SKY73210_init(const struct sky73210 *dev)
+{
+ gpioPin_setMode(&dev->cs, OUTPUT);
+ gpioPin_set(&dev->cs);
+
+ writeReg(dev, 0x6000 | 0x1F); // Phase detector gain
+ writeReg(dev, 0x73D0); // Power down/multiplexer control register
+ writeReg(dev, 0x8000); // Modulation control register
+ writeReg(dev, 0x9000); // Modulation data register
}
-void SKY73210_terminate()
+void SKY73210_terminate(const struct sky73210 *dev)
{
- gpio_setMode(PLL_CLK, INPUT);
- gpio_setMode(PLL_DAT, INPUT);
- gpio_setMode(PLL_CS, INPUT);
+ (void) dev;
}
-void SKY73210_setFrequency(float freq, uint8_t clkDiv)
+void SKY73210_setFrequency(const struct sky73210 *dev, const uint32_t freq,
+ uint8_t clkDiv)
{
- /* Maximum allowable value for reference clock divider is 32 */
- if (clkDiv > 32) clkDiv = 32;
+ // Maximum allowable value for reference clock divider is 32
+ if (clkDiv > 32)
+ clkDiv = 32;
- float K = freq/(REF_CLK/((float) clkDiv));
+ float clk = ((float) dev->refClk) / ((float) clkDiv);
+ float K = ((float) freq) / clk;
float Ndiv = floor(K) - 32.0;
- float Ndnd = round(262144*(K - Ndiv - 32.0));
+ float Ndnd = round(262144 * (K - Ndiv - 32.0));
/*
* With PLL in fractional mode, dividend range is [-131017 +131071].
@@ -95,25 +75,14 @@ void SKY73210_setFrequency(float freq, uint8_t clkDiv)
* signed 18-bit one and increment the divider by one if dividend is negative.
*/
uint32_t dnd = ((uint32_t) Ndnd) & 0x03FFFF;
- if(dnd & 0x20000) Ndiv += 1;
+ if(dnd & 0x20000)
+ Ndiv += 1;
uint16_t dndMsb = dnd >> 8;
uint16_t dndLsb = dnd & 0x00FF;
- _spiSend((uint16_t) Ndiv); /* Divider register */
- _spiSend(0x2000 | dndLsb); /* Dividend LSB register */
- _spiSend(0x1000 | dndMsb); /* Dividend MSB register */
- _spiSend(0x5000 | ((uint16_t)clkDiv - 1)); /* Reference clock divider */
+ writeReg(dev, (uint16_t) Ndiv); // Divider register
+ writeReg(dev, 0x2000 | dndLsb); // Dividend LSB register
+ writeReg(dev, 0x1000 | dndMsb); // Dividend MSB register
+ writeReg(dev, 0x5000 | ((uint16_t)clkDiv - 1)); // Reference clock divider
}
-
-bool SKY73210_isPllLocked()
-{
- return (gpio_readPin(PLL_LD) == 1) ? true : false;
-}
-
-bool SKY73210_spiInUse()
-{
- /* If PLL chip select is low, SPI is being used by this driver. */
- return (gpio_readPin(PLL_CS) == 1) ? false : true;
-}
-
diff --git a/platform/drivers/baseband/SKY72310.h b/platform/drivers/baseband/SKY72310.h
index ac3e9b6e..2f50df5c 100644
--- a/platform/drivers/baseband/SKY72310.h
+++ b/platform/drivers/baseband/SKY72310.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2020 - 2023 by Silvano Seva IU2KWO *
+ * Copyright (C) 2020 - 2024 by Silvano Seva IU2KWO *
* and Niccolò Izzo IU2KIN *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -19,6 +19,8 @@
#ifndef SKY73210_H
#define SKY73210_H
+#include
+#include
#include
#include
@@ -27,45 +29,38 @@ extern "C" {
#endif
/**
- * Driver for SKY73210 PLL IC.
- *
- * WARNING: on MD3x0 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.
+ * SKY73210 device data.
*/
+struct sky73210
+{
+ const struct spiDevice *spi; ///< SPI bus device driver
+ const struct gpioPin cs; ///< Chip select gpio
+ const uint32_t refClk; ///< Reference clock frequency, in Hz
+};
/**
* Initialise the PLL.
+ *
+ * @param dev: pointer to device data.
*/
-void SKY73210_init();
+void SKY73210_init(const struct sky73210 *dev);
/**
- * Terminate PLL driver, bringing GPIOs back to reset state.
+ * Terminate PLL driver.
+ *
+ * @param dev: pointer to device data.
*/
-void SKY73210_terminate();
+void SKY73210_terminate(const struct sky73210 *dev);
/**
* Change VCO frequency.
+ *
+ * @param dev: pointer to device data.
* @param freq: new VCO frequency, in Hz.
* @param clkDiv: reference clock division factor.
*/
-void SKY73210_setFrequency(float freq, uint8_t clkDiv);
-
-/**
- * Check if PLL is locked.
- * @return true if PLL is locked.
- */
-bool SKY73210_isPllLocked();
-
-/**
- * Check if the SPI bus in common between PLL and DMR chips is in use by this
- * driver.
- * @return true if this driver is using the SPI bus.
- */
-bool SKY73210_spiInUse();
+void SKY73210_setFrequency(const struct sky73210 *dev, const uint32_t freq,
+ uint8_t clkDiv);
#ifdef __cplusplus
}