RFFC5071: Further refactoring to create common SPI interface.
This commit is contained in:
@ -91,7 +91,7 @@ void rffc5071_setup(rffc5071_driver_t* const drv)
|
|||||||
{
|
{
|
||||||
rffc5071_init(drv);
|
rffc5071_init(drv);
|
||||||
|
|
||||||
rffc5071_pin_config(drv);
|
rffc5071_spi_init(drv->spi);
|
||||||
|
|
||||||
/* initial setup */
|
/* initial setup */
|
||||||
/* put zeros in freq contol registers */
|
/* put zeros in freq contol registers */
|
||||||
@ -124,7 +124,7 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) {
|
|||||||
(void)drv;
|
(void)drv;
|
||||||
|
|
||||||
uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff };
|
uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff };
|
||||||
rffc5071_spi_transfer(drv, data, 2);
|
rffc5071_spi_transfer(drv->spi, data, 2);
|
||||||
return data[1];
|
return data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t
|
|||||||
(void)drv;
|
(void)drv;
|
||||||
|
|
||||||
uint16_t data[] = { 0x00 | (r & 0x7f), v };
|
uint16_t data[] = { 0x00 | (r & 0x7f), v };
|
||||||
rffc5071_spi_transfer(drv, data, 2);
|
rffc5071_spi_transfer(drv->spi, data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r)
|
uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r)
|
||||||
|
@ -25,45 +25,51 @@
|
|||||||
#include <libopencm3/lpc43xx/gpio.h>
|
#include <libopencm3/lpc43xx/gpio.h>
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
static void rffc5071_target_select() {
|
static void rffc5071_spi_target_select(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX);
|
gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_target_unselect() {
|
static void rffc5071_spi_target_unselect(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
|
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_direction_out() {
|
static void rffc5071_spi_direction_out(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA;
|
GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_direction_in() {
|
static void rffc5071_spi_direction_in(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA;
|
GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_data_out(const bool bit) {
|
static void rffc5071_spi_data_out(spi_t* const spi, const bool bit) {
|
||||||
|
(void)spi;
|
||||||
if (bit)
|
if (bit)
|
||||||
gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
||||||
else
|
else
|
||||||
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rffc5071_spi_data_in() {
|
static bool rffc5071_spi_data_in(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
return MIXER_SDATA_STATE;
|
return MIXER_SDATA_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_init() {
|
static void rffc5071_spi_bus_init(spi_t* const spi) {
|
||||||
scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||||
scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST);
|
scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST);
|
||||||
|
|
||||||
GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK;
|
GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK;
|
||||||
rffc5071_spi_direction_out();
|
rffc5071_spi_direction_out(spi);
|
||||||
|
|
||||||
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
||||||
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_target_init() {
|
static void rffc5071_spi_target_init(spi_t* const spi) {
|
||||||
/* Configure GPIO pins. */
|
/* Configure GPIO pins. */
|
||||||
scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST);
|
scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST);
|
||||||
scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST);
|
scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST);
|
||||||
@ -73,45 +79,44 @@ static void rffc5071_target_init() {
|
|||||||
GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX;
|
GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX;
|
||||||
|
|
||||||
/* set to known state */
|
/* set to known state */
|
||||||
rffc5071_target_unselect();
|
rffc5071_spi_target_unselect(spi);
|
||||||
gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */
|
gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_pin_config(rffc5071_driver_t* const drv) {
|
void rffc5071_spi_init(spi_t* const spi) {
|
||||||
(void)drv;
|
rffc5071_spi_bus_init(spi);
|
||||||
|
rffc5071_spi_target_init(spi);
|
||||||
rffc5071_spi_init();
|
|
||||||
rffc5071_target_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_serial_delay(void) {
|
static void rffc5071_spi_serial_delay(spi_t* const spi) {
|
||||||
|
(void)spi;
|
||||||
volatile uint32_t i;
|
volatile uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rffc5071_spi_sck() {
|
static void rffc5071_spi_sck(spi_t* const spi) {
|
||||||
rffc5071_spi_serial_delay();
|
rffc5071_spi_serial_delay(spi);
|
||||||
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
||||||
|
|
||||||
rffc5071_spi_serial_delay();
|
rffc5071_spi_serial_delay(spi);
|
||||||
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rffc5071_spi_exchange_bit(const uint32_t bit) {
|
static uint32_t rffc5071_spi_exchange_bit(spi_t* const spi, const uint32_t bit) {
|
||||||
rffc5071_spi_data_out(bit);
|
rffc5071_spi_data_out(spi, bit);
|
||||||
rffc5071_spi_sck();
|
rffc5071_spi_sck(spi);
|
||||||
return rffc5071_spi_data_in() ? 1 : 0;
|
return rffc5071_spi_data_in(spi) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rffc5071_spi_exchange_word(const uint32_t data, const size_t count) {
|
static uint32_t rffc5071_spi_exchange_word(spi_t* const spi, const uint32_t data, const size_t count) {
|
||||||
size_t bits = count;
|
size_t bits = count;
|
||||||
const uint32_t msb = 1UL << (count - 1);
|
const uint32_t msb = 1UL << (count - 1);
|
||||||
uint32_t t = data;
|
uint32_t t = data;
|
||||||
|
|
||||||
while (bits--) {
|
while (bits--) {
|
||||||
t = (t << 1) | rffc5071_spi_exchange_bit(t & msb);
|
t = (t << 1) | rffc5071_spi_exchange_bit(spi, t & msb);
|
||||||
}
|
}
|
||||||
|
|
||||||
return t & ((1UL << count) - 1);
|
return t & ((1UL << count) - 1);
|
||||||
@ -133,9 +138,7 @@ static uint32_t rffc5071_spi_exchange_word(const uint32_t data, const size_t cou
|
|||||||
* next 7 bits are register address,
|
* next 7 bits are register address,
|
||||||
* next 16 bits are register value.
|
* next 16 bits are register value.
|
||||||
*/
|
*/
|
||||||
void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count) {
|
void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count) {
|
||||||
(void)drv;
|
|
||||||
|
|
||||||
if( count != 2 ) {
|
if( count != 2 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -146,25 +149,25 @@ void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, c
|
|||||||
* The device requires two clocks while ENX is high before a serial
|
* The device requires two clocks while ENX is high before a serial
|
||||||
* transaction. This is not clearly documented.
|
* transaction. This is not clearly documented.
|
||||||
*/
|
*/
|
||||||
rffc5071_spi_sck();
|
rffc5071_spi_sck(spi);
|
||||||
rffc5071_spi_sck();
|
rffc5071_spi_sck(spi);
|
||||||
|
|
||||||
rffc5071_target_select();
|
rffc5071_spi_target_select(spi);
|
||||||
data[0] = rffc5071_spi_exchange_word(data[0], 9);
|
data[0] = rffc5071_spi_exchange_word(spi, data[0], 9);
|
||||||
|
|
||||||
if( direction_read ) {
|
if( direction_read ) {
|
||||||
rffc5071_spi_direction_in();
|
rffc5071_spi_direction_in(spi);
|
||||||
rffc5071_spi_sck();
|
rffc5071_spi_sck(spi);
|
||||||
}
|
}
|
||||||
data[1] = rffc5071_spi_exchange_word(data[1], 16);
|
data[1] = rffc5071_spi_exchange_word(spi, data[1], 16);
|
||||||
|
|
||||||
rffc5071_spi_serial_delay();
|
rffc5071_spi_serial_delay(spi);
|
||||||
rffc5071_target_unselect();
|
rffc5071_spi_target_unselect(spi);
|
||||||
rffc5071_spi_direction_out();
|
rffc5071_spi_direction_out(spi);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The device requires a clock while ENX is high after a serial
|
* The device requires a clock while ENX is high after a serial
|
||||||
* transaction. This is not clearly documented.
|
* transaction. This is not clearly documented.
|
||||||
*/
|
*/
|
||||||
rffc5071_spi_sck();
|
rffc5071_spi_sck(spi);
|
||||||
}
|
}
|
||||||
|
@ -20,19 +20,21 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RFFC5071_DRV_H
|
#ifndef __RFFC5071_SPI_H
|
||||||
#define __RFFC5071_DRV_H
|
#define __RFFC5071_SPI_H
|
||||||
|
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
/* 31 registers, each containing 16 bits of data. */
|
/* 31 registers, each containing 16 bits of data. */
|
||||||
#define RFFC5071_NUM_REGS 31
|
#define RFFC5071_NUM_REGS 31
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
spi_t* const spi;
|
||||||
uint16_t regs[RFFC5071_NUM_REGS];
|
uint16_t regs[RFFC5071_NUM_REGS];
|
||||||
uint32_t regs_dirty;
|
uint32_t regs_dirty;
|
||||||
} rffc5071_driver_t;
|
} rffc5071_driver_t;
|
||||||
|
|
||||||
void rffc5071_pin_config(rffc5071_driver_t* const drv);
|
void rffc5071_spi_init(spi_t* const spi);
|
||||||
|
void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count);
|
||||||
|
|
||||||
void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count);
|
#endif // __RFFC5071_SPI_H
|
||||||
|
|
||||||
#endif // __RFFC5071_DRV_H
|
|
||||||
|
Reference in New Issue
Block a user