2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 * Author: Giles Burgess (giles@multiflite.co.uk)
24 * This source code is provided as is and can be used/modified so long
25 * as this header is maintained with the file at all times.
33 #if defined(USE_VTX_RTC6705)
35 #include "common/maths.h"
37 #include "drivers/bus_spi.h"
38 #include "drivers/bus_spi_impl.h"
39 #include "drivers/io.h"
40 #include "drivers/time.h"
41 #include "drivers/vtx_rtc6705_soft_spi.h"
43 #include "vtx_rtc6705.h"
45 // 1 MHz max SPI frequency - datasheet says 10MHz, but this is lower for some reason
46 #define RTC6705_MAX_SPI_CLK_HZ 1000000
48 #define RTC6705_SET_HEAD 0x3210 //fosc=8mhz r=400
49 #define RTC6705_SET_R 400 //Reference clock
50 #define RTC6705_SET_FDIV 1024 //128*(fosc/1000000)
51 #define RTC6705_SET_NDIV 16 //Remainder divider to get 'A' part of equation
52 #define RTC6705_SET_WRITE 0x11 //10001b to write to register
53 #define RTC6705_SET_DIVMULT 1000000 //Division value (to fit into a uint32_t) (Hz to MHz)
55 #ifdef RTC6705_POWER_PIN
56 static IO_t vtxPowerPin
= IO_NONE
;
59 static extDevice_t
*dev
= NULL
;
61 #define DISABLE_RTC6705() IOHi(dev->busType_u.spi.csnPin)
62 #define ENABLE_RTC6705() IOLo(dev->busType_u.spi.csnPin)
64 #define DP_5G_MASK 0x7000 // b111000000000000
65 #define PA5G_BS_MASK 0x0E00 // b000111000000000
66 #define PA5G_PW_MASK 0x0180 // b000000110000000
67 #define PD_Q5G_MASK 0x0040 // b000000001000000
68 #define QI_5G_MASK 0x0038 // b000000000111000
69 #define PA_BS_MASK 0x0007 // b000000000000111
71 #define PA_CONTROL_DEFAULT 0x4FBD
73 #define RTC6705_RW_CONTROL_BIT (1 << 4)
74 #define RTC6705_ADDRESS (0x07)
77 * Reverse a uint32_t (LSB to MSB)
78 * This is easier for when generating the frequency to then
79 * reverse the bits afterwards
81 static uint32_t reverse32(uint32_t in
)
85 for (uint8_t i
= 0 ; i
< 32 ; i
++) {
86 out
|= ((in
>>i
) & 1)<<(31-i
);
93 * Start chip if available
95 bool rtc6705IOInit(const vtxIOConfig_t
*vtxIOConfig
)
97 static extDevice_t devInstance
;
99 IO_t csnPin
= IOGetByTag(vtxIOConfig
->csTag
);
104 vtxPowerPin
= IOGetByTag(vtxIOConfig
->powerTag
);
106 IOInit(vtxPowerPin
, OWNER_VTX_POWER
, 0);
110 IOConfigGPIO(vtxPowerPin
, IOCFG_OUT_PP
);
113 // RTC6705 when using SOFT SPI driver doesn't use an SPI device, so don't attempt to initialise an spiInstance.
114 SPI_TypeDef
*spiInstance
= spiInstanceByDevice(SPI_CFG_TO_DEV(vtxIOConfig
->spiDevice
));
115 if (spiInstance
&& spiSetBusInstance(dev
, vtxIOConfig
->spiDevice
)) {
116 devInstance
.busType_u
.spi
.csnPin
= csnPin
;
117 IOInit(devInstance
.busType_u
.spi
.csnPin
, OWNER_VTX_CS
, 0);
120 // GPIO bit is enabled so here so the output is not pulled low when the GPIO is set in output mode.
121 // Note: It's critical to ensure that incorrect signals are not sent to the VTX.
122 IOConfigGPIO(devInstance
.busType_u
.spi
.csnPin
, IOCFG_OUT_PP
);
125 #if defined(USE_VTX_RTC6705_SOFTSPI)
127 return rtc6705SoftSpiIOInit(vtxIOConfig
, csnPin
);
135 * Transfer a 25bit packet to RTC6705
136 * This will just send it as a 32bit packet LSB meaning
137 * extra 0's get truncated on RTC6705 end
139 static void rtc6705Transfer(uint32_t command
)
141 // Perform bitwise reverse of the command.
142 command
= reverse32(command
);
144 spiReadWriteBuf(dev
, (uint8_t *)&command
, NULL
, sizeof(command
));
146 delayMicroseconds(2);
150 * Set a frequency in Mhz
151 * Formula derived from datasheet
153 void rtc6705SetFrequency(uint16_t frequency
)
155 #if defined(USE_VTX_RTC6705_SOFTSPI)
157 rtc6705SoftSpiSetFrequency(frequency
);
163 frequency
= constrain(frequency
, VTX_RTC6705_FREQ_MIN
, VTX_RTC6705_FREQ_MAX
);
165 const uint32_t val_a
= ((((uint64_t)frequency
*(uint64_t)RTC6705_SET_DIVMULT
*(uint64_t)RTC6705_SET_R
)/(uint64_t)RTC6705_SET_DIVMULT
) % RTC6705_SET_FDIV
) / RTC6705_SET_NDIV
; //Casts required to make sure correct math (large numbers)
166 const uint32_t val_n
= (((uint64_t)frequency
*(uint64_t)RTC6705_SET_DIVMULT
*(uint64_t)RTC6705_SET_R
)/(uint64_t)RTC6705_SET_DIVMULT
) / RTC6705_SET_FDIV
; //Casts required to make sure correct math (large numbers)
168 uint32_t val_hex
= RTC6705_SET_WRITE
;
169 val_hex
|= (val_a
<< 5);
170 val_hex
|= (val_n
<< 12);
172 spiSetClkDivisor(dev
, spiCalculateDivider(RTC6705_MAX_SPI_CLK_HZ
));
174 rtc6705Transfer(RTC6705_SET_HEAD
);
175 delayMicroseconds(10);
176 rtc6705Transfer(val_hex
);
179 void rtc6705SetRFPower(uint8_t rf_power
)
181 rf_power
= constrain(rf_power
, 1, 2);
182 #if defined(USE_VTX_RTC6705_SOFTSPI)
184 rtc6705SoftSpiSetRFPower(rf_power
);
190 uint32_t val_hex
= RTC6705_RW_CONTROL_BIT
; // write
191 val_hex
|= RTC6705_ADDRESS
; // address
192 const uint32_t data
= rf_power
> 1 ? PA_CONTROL_DEFAULT
: (PA_CONTROL_DEFAULT
| PD_Q5G_MASK
) & (~(PA5G_PW_MASK
| PA5G_BS_MASK
));
193 val_hex
|= data
<< 5; // 4 address bits and 1 rw bit.
195 spiSetClkDivisor(dev
, spiCalculateDivider(RTC6705_MAX_SPI_CLK_HZ
));
197 rtc6705Transfer(val_hex
);
200 void rtc6705Disable(void)
207 void rtc6705Enable(void)