RFFC5071: Further refactoring to create common SPI interface.

This commit is contained in:
Jared Boone
2014-11-09 09:36:18 -08:00
parent 487b8cc168
commit 69867bb637
3 changed files with 53 additions and 48 deletions

View File

@ -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)

View File

@ -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);
} }

View File

@ -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