From e6c02bea62d80af1b08a89c7178a9490a4b1747d Mon Sep 17 00:00:00 2001
From: Jared Boone <jboone@earfeast.com>
Date: Sun, 9 Nov 2014 13:48:15 -0800
Subject: [PATCH 23/68] MAX5864: Abstract SPI, extract target code

---
 firmware/common/hackrf_core.c                  | 49 +++++-----------
 firmware/common/hackrf_core.h                  |  3 +-
 firmware/common/max5864.c                      | 44 ++++++++-------
 firmware/common/max5864.h                      | 20 +++++--
 firmware/common/max5864_spi.c                  | 78 ++++++++++++++++++++++++++
 firmware/common/max5864_spi.h                  | 33 +++++++++++
 firmware/common/max5864_target.c               | 38 +++++++++++++
 firmware/common/max5864_target.h               | 29 ++++++++++
 firmware/common/rf_path.c                      |  9 +--
 firmware/hackrf-common.cmake                   |  2 +
 firmware/hackrf_usb/hackrf_usb.c               |  2 -
 firmware/mixertx/mixertx.c                     |  1 -
 firmware/sgpio-rx/sgpio-rx.c                   |  1 -
 firmware/sgpio/sgpio_test.c                    |  4 +-
 firmware/sgpio_passthrough/sgpio_passthrough.c |  1 -
 firmware/simpletx/simpletx.c                   |  1 -
 16 files changed, 240 insertions(+), 75 deletions(-)
 create mode 100644 firmware/common/max5864_spi.c
 create mode 100644 firmware/common/max5864_spi.h
 create mode 100644 firmware/common/max5864_target.c
 create mode 100644 firmware/common/max5864_target.h

--- a/firmware/common/hackrf_core.c
+++ b/firmware/common/hackrf_core.c
@@ -26,6 +26,9 @@
 #include "max2837.h"
 #include "max2837_spi.h"
 #include "max2837_target.h"
+#include "max5864.h"
+#include "max5864_spi.h"
+#include "max5864_target.h"
 #include "rffc5071.h"
 #include "rffc5071_spi.h"
 #include "sgpio.h"
@@ -52,6 +55,15 @@
 	.spi = &max2837_spi,
 };
 
+spi_t max5864_spi = {
+	.init = max5864_spi_init,
+	.transfer = max5864_spi_transfer,
+	.transfer_gather = max5864_spi_transfer_gather,
+};
+
+max5864_driver_t max5864 = {
+	.spi = &max5864_spi,
+};
 
 spi_t rffc5071_spi = {
 	.init = rffc5071_spi_init,
@@ -534,17 +546,6 @@
 
 }
 
-void ssp1_init(void)
-{
-	/*
-	 * Configure CS_AD pin to keep the MAX5864 SPI disabled while we use the
-	 * SPI bus for the MAX2837. FIXME: this should probably be somewhere else.
-	 */
-	scu_pinmux(SCU_AD_CS, SCU_GPIO_FAST);
-	GPIO_SET(PORT_AD_CS) = PIN_AD_CS;
-	GPIO_DIR(PORT_AD_CS) |= PIN_AD_CS;
-}
-
 void ssp1_set_mode_max2837(void)
 {
 	spi_init(max2837.spi);
@@ -552,25 +553,7 @@
 
 void ssp1_set_mode_max5864(void)
 {
-	/* FIXME speed up once everything is working reliably */
-	/*
-	// Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
-	const uint8_t serial_clock_rate = 32;
-	const uint8_t clock_prescale_rate = 128;
-	*/
-	// Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
-	const uint8_t serial_clock_rate = 21;
-	const uint8_t clock_prescale_rate = 2;
-	
-	ssp_init(SSP1_NUM,
-		SSP_DATA_8BITS,
-		SSP_FRAME_SPI,
-		SSP_CPOL_0_CPHA_0,
-		serial_clock_rate,
-		clock_prescale_rate,
-		SSP_MODE_NORMAL,
-		SSP_MASTER,
-		SSP_SLAVE_OUT_ENABLE);
+	spi_init(max5864.spi);
 }
 
 void pin_setup(void) {
@@ -616,12 +599,6 @@
 
 	rf_path_pin_setup();
 	
-	/* Configure SSP1 Peripheral (to be moved later in SSP driver) */
-	scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
-	scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
-	scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
-	scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
-	
 	/* Configure external clock in */
 	scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
 
--- a/firmware/common/hackrf_core.h
+++ b/firmware/common/hackrf_core.h
@@ -35,6 +35,7 @@
 #include "si5351c_drv.h"
 
 #include "max2837.h"
+#include "max5864.h"
 #include "rffc5071.h"
 #include "w25q80bv.h"
 
--- a/firmware/common/max5864.c
+++ b/firmware/common/max5864.c
@@ -21,16 +21,20 @@
 
 #include <stdint.h>
 
-#include <libopencm3/lpc43xx/gpio.h>
-#include <libopencm3/lpc43xx/ssp.h>
-
-#include "hackrf_core.h"
 #include "max5864.h"
+#include "max5864_target.h"
+
+static void max5864_write(max5864_driver_t* const drv, uint8_t value) {
+	spi_transfer(drv->spi, &value, 1);
+}
+
+void max5864_init(max5864_driver_t* const drv) {
+	spi_init(drv->spi);
+	max5864_target_init(drv);
+}
 
-void max5864_spi_write(uint_fast8_t value) {
-	gpio_clear(PORT_AD_CS, PIN_AD_CS);
-	ssp_transfer(SSP1_NUM, value);
-	gpio_set(PORT_AD_CS, PIN_AD_CS);
+void max5864_setup(max5864_driver_t* const drv) {
+	max5864_init(drv);
 }
 
 /* Set MAX5864 operation mode to "Shutdown":
@@ -39,9 +43,9 @@
  *   ADCs: off (bus is tri-stated)
  *   DACs: off (set input bus to zero or OVdd)
  */
-void max5864_shutdown()
+void max5864_shutdown(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x00);
+	max5864_write(drv, 0x00);
 }
 
 /* Set MAX5864 operation mode to "Standby":
@@ -50,9 +54,9 @@
  *   ADCs: off (bus is tri-stated)
  *   DACs: off (set input bus to zero or OVdd)
  */
-void max5864_standby()
+void max5864_standby(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x05);
+	max5864_write(drv, 0x05);
 }
 
 /* Set MAX5864 operation mode to "Idle":
@@ -61,9 +65,9 @@
  *   ADCs: off (bus is tri-stated)
  *   DACs: off (set input bus to zero or OVdd)
  */
-void max5864_idle()
+void max5864_idle(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x01);
+	max5864_write(drv, 0x01);
 }
 
 /* Set MAX5864 operation mode to "Rx":
@@ -72,9 +76,9 @@
  *   ADCs: on
  *   DACs: off (set input bus to zero or OVdd)
  */
-void max5864_rx()
+void max5864_rx(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x02);
+	max5864_write(drv, 0x02);
 }
 
 /* Set MAX5864 operation mode to "Tx":
@@ -83,9 +87,9 @@
  *   ADCs: off (bus is tri-stated)
  *   DACs: on
  */
-void max5864_tx()
+void max5864_tx(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x03);
+	max5864_write(drv, 0x03);
 }
 
 /* Set MAX5864 operation mode to "Xcvr":
@@ -94,7 +98,7 @@
  *   ADCs: on
  *   DACs: on
  */
-void max5864_xcvr()
+void max5864_xcvr(max5864_driver_t* const drv)
 {
-	max5864_spi_write(0x04);
+	max5864_write(drv, 0x04);
 }
--- a/firmware/common/max5864.h
+++ b/firmware/common/max5864.h
@@ -22,11 +22,19 @@
 #ifndef __MAX5864_H
 #define __MAX5864_H
 
-void max5864_shutdown();
-void max5864_standby();
-void max5864_idle();
-void max5864_rx();
-void max5864_tx();
-void max5864_xcvr();
+#include "spi.h"
+
+typedef struct max5864_driver_t {
+	spi_t* const spi;
+} max5864_driver_t;
+
+void max5864_setup(max5864_driver_t* const drv);
+
+void max5864_shutdown(max5864_driver_t* const drv);
+void max5864_standby(max5864_driver_t* const drv);
+void max5864_idle(max5864_driver_t* const drv);
+void max5864_rx(max5864_driver_t* const drv);
+void max5864_tx(max5864_driver_t* const drv);
+void max5864_xcvr(max5864_driver_t* const drv);
 
 #endif // __MAX5864_H
--- /dev/null
+++ b/firmware/common/max5864_spi.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
+ *
+ * This file is part of HackRF.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "max5864_spi.h"
+
+#include <libopencm3/lpc43xx/gpio.h>
+#include <libopencm3/lpc43xx/scu.h>
+#include <libopencm3/lpc43xx/ssp.h>
+
+#include "hackrf_core.h"
+
+void max5864_spi_init(spi_t* const spi) {
+	(void)spi;
+
+	/* FIXME speed up once everything is working reliably */
+	/*
+	// Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
+	const uint8_t serial_clock_rate = 32;
+	const uint8_t clock_prescale_rate = 128;
+	*/
+	// Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
+	const uint8_t serial_clock_rate = 21;
+	const uint8_t clock_prescale_rate = 2;
+	
+	ssp_init(SSP1_NUM,
+		SSP_DATA_8BITS,
+		SSP_FRAME_SPI,
+		SSP_CPOL_0_CPHA_0,
+		serial_clock_rate,
+		clock_prescale_rate,
+		SSP_MODE_NORMAL,
+		SSP_MASTER,
+		SSP_SLAVE_OUT_ENABLE);
+
+	/* Configure SSP1 Peripheral (to be moved later in SSP driver) */
+	scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
+	scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
+	scu_pinmux(SCU_SSP1_SCK,  (SCU_SSP_IO | SCU_CONF_FUNCTION1));
+}
+
+void max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) {
+	(void)spi;
+
+	gpio_clear(PORT_AD_CS, PIN_AD_CS);
+	for(size_t i=0; i<count; i++) {
+		const size_t data_count = transfers[i].count;
+		uint8_t* const data = transfers[i].data;
+		for(size_t j=0; j<data_count; j++) {
+			data[j] = ssp_transfer(SSP1_NUM, data[j]);
+		}
+	}		
+	gpio_set(PORT_AD_CS, PIN_AD_CS);
+}
+
+void max5864_spi_transfer(spi_t* const spi, void* const data, const size_t count) {
+	const spi_transfer_t transfers[] = {
+		{ data, count },
+	};
+	max5864_spi_transfer_gather(spi, transfers, 1);
+}
--- /dev/null
+++ b/firmware/common/max5864_spi.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
+ *
+ * This file is part of HackRF.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MAX5864_SPI_H__
+#define __MAX5864_SPI_H__
+
+#include <stddef.h>
+
+#include "spi.h"
+
+void max5864_spi_init(spi_t* const spi);
+void max5864_spi_transfer(spi_t* const spi, void* const value, const size_t count);
+void max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count);
+
+#endif/*__MAX5864_SPI_H__*/
--- /dev/null
+++ b/firmware/common/max5864_target.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
+ *
+ * This file is part of HackRF.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "max5864_target.h"
+
+#include <libopencm3/lpc43xx/scu.h>
+#include <libopencm3/lpc43xx/gpio.h>
+#include "hackrf_core.h"
+
+void max5864_target_init(max5864_driver_t* const drv) {
+	(void)drv;
+	
+	/*
+	 * Configure CS_AD pin to keep the MAX5864 SPI disabled while we use the
+	 * SPI bus for the MAX2837. FIXME: this should probably be somewhere else.
+	 */
+	scu_pinmux(SCU_AD_CS, SCU_GPIO_FAST);
+	GPIO_SET(PORT_AD_CS) = PIN_AD_CS;
+	GPIO_DIR(PORT_AD_CS) |= PIN_AD_CS;
+}
--- /dev/null
+++ b/firmware/common/max5864_target.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
+ *
+ * This file is part of HackRF.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MAX5864_TARGET_H__
+#define __MAX5864_TARGET_H__
+
+#include "max5864.h"
+
+void max5864_target_init(max5864_driver_t* const drv);
+
+#endif/*__MAX5864_TARGET_H__*/
--- a/firmware/common/rf_path.c
+++ b/firmware/common/rf_path.c
@@ -209,7 +209,8 @@
 
 void rf_path_init(void) {
 	ssp1_set_mode_max5864();
-	max5864_shutdown();
+	max5864_setup(&max5864);
+	max5864_shutdown(&max5864);
 	
 	ssp1_set_mode_max2837();
 	max2837_setup(&max2837);
@@ -236,7 +237,7 @@
 			rffc5071_enable(&rffc5072);
 		}
 		ssp1_set_mode_max5864();
-		max5864_tx();
+		max5864_tx(&max5864);
 		ssp1_set_mode_max2837();
 		max2837_tx(&max2837);
 		sgpio_configure(SGPIO_DIRECTION_TX);
@@ -255,7 +256,7 @@
 			rffc5071_enable(&rffc5072);
 		}
 		ssp1_set_mode_max5864();
-		max5864_rx();
+		max5864_rx(&max5864);
 		ssp1_set_mode_max2837();
 		max2837_rx(&max2837);
 		sgpio_configure(SGPIO_DIRECTION_RX);
@@ -271,7 +272,7 @@
 		switchctrl &= ~SWITCHCTRL_TX;
 		rffc5071_disable(&rffc5072);
 		ssp1_set_mode_max5864();
-		max5864_standby();
+		max5864_standby(&max5864);
 		ssp1_set_mode_max2837();
 		max2837_set_mode(&max2837, MAX2837_MODE_STANDBY);
 		sgpio_configure(SGPIO_DIRECTION_RX);
--- a/firmware/hackrf-common.cmake
+++ b/firmware/hackrf-common.cmake
@@ -139,6 +139,8 @@
 		${PATH_HACKRF_FIRMWARE_COMMON}/max2837_spi.c
 		${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c
 		${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c
+		${PATH_HACKRF_FIRMWARE_COMMON}/max5864_spi.c
+		${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c
 		${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
 		${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c
 		${PATH_HACKRF_FIRMWARE_COMMON}/spi.c
--- a/firmware/hackrf_usb/hackrf_usb.c
+++ b/firmware/hackrf_usb/hackrf_usb.c
@@ -243,8 +243,6 @@
 
 	usb_run(&usb_device);
 	
-	ssp1_init();
-
 	rf_path_init();
 
 	unsigned int phase = 0;
--- a/firmware/mixertx/mixertx.c
+++ b/firmware/mixertx/mixertx.c
@@ -38,7 +38,6 @@
 	enable_rf_power();
 #endif
 	cpu_clock_init();
-	ssp1_init();
 
 	gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
 
--- a/firmware/sgpio-rx/sgpio-rx.c
+++ b/firmware/sgpio-rx/sgpio-rx.c
@@ -96,7 +96,6 @@
 	enable_rf_power();
 #endif
 	cpu_clock_init();
-    ssp1_init();
     rf_path_init();
     rf_path_set_direction(RF_PATH_DIRECTION_RX);
 
--- a/firmware/sgpio/sgpio_test.c
+++ b/firmware/sgpio/sgpio_test.c
@@ -72,12 +72,12 @@
 	pin_setup();
 	enable_1v8_power();
 	cpu_clock_init();
-	ssp1_init();
 
 	gpio_set(PORT_LED1_3, PIN_LED1);
 
 	ssp1_set_mode_max5864();
-	max5864_xcvr();
+	max5864_setup(&max5864);
+	max5864_xcvr(&max5864);
 
 	while (1) {
 
--- a/firmware/sgpio_passthrough/sgpio_passthrough.c
+++ b/firmware/sgpio_passthrough/sgpio_passthrough.c
@@ -353,7 +353,6 @@
 	pin_setup();
 	enable_1v8_power();
 	cpu_clock_init();
-	ssp1_init();
 	gpio_set(PORT_LED1_3, PIN_LED1);
 
 	//test_sgpio_sliceA_D();
--- a/firmware/simpletx/simpletx.c
+++ b/firmware/simpletx/simpletx.c
@@ -37,7 +37,6 @@
 	enable_rf_power();
 #endif
 	cpu_clock_init();
-    ssp1_init();
     
 	gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
 
