summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2013-06-04 21:55:32 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2013-06-04 21:55:32 +0200
commit94d67aae3a0b9921a7106b592593253b73b0cdb9 (patch)
treefd2f6797b8fd7013c5b717887a584dd1c36a535a
parent65a0e3eb0aef883983fc91b79aed6963445d4322 (diff)
In-progress version of WM8523 driver.
-rw-r--r--firmware/Makefile2
-rw-r--r--firmware/drivers/wm8523.c126
-rw-r--r--firmware/drivers/wm8523.h33
-rw-r--r--firmware/lpc17xx/lpc17xx_clkpwr.c344
-rw-r--r--firmware/lpc17xx/lpc17xx_clkpwr.h384
-rw-r--r--firmware/lpc17xx/lpc17xx_spi.c550
-rw-r--r--firmware/lpc17xx/lpc17xx_spi.h314
-rw-r--r--firmware/lpc17xx/lpc_types.h197
-rw-r--r--firmware/src/p2m.c9
9 files changed, 1951 insertions, 8 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
index ef9b0e1..e398623 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -22,7 +22,7 @@ CP = $(ARCH)-objcopy
OD = $(ARCH)-objdump
SIZE = $(ARCH)-size
RM = rm
-Q = # @./quiet "$@"
+#Q = # @./quiet "$@"
# Flags
CFLAGS = -W -Wall -O0 --std=gnu99 -fgnu89-inline -mcpu=cortex-m3 -mthumb
diff --git a/firmware/drivers/wm8523.c b/firmware/drivers/wm8523.c
new file mode 100644
index 0000000..36d293a
--- /dev/null
+++ b/firmware/drivers/wm8523.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wm8523.c
+ *
+ * Tue Jun 4 20:47:15 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pedal2Metal.
+ *
+ * Pedal2Metal 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Pedal2Metal 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 Pedal2Metal; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "wm8523.h"
+
+#include <string.h>
+#include <lpc17xx_spi.h>
+
+#define WM8523_WRITE 0
+#define WM8523_READ 1
+
+static SPI_CFG_Type spi_cfg;
+static LPC_SPI_TypeDef spi;
+
+typedef struct __attribute__ ((packed)) {
+ uint8_t rw:1; ///< See WM8523_WRITE and WM8523_READ
+ uint8_t reg:7; ///< See page 35 in the WM8523 manual.
+ uint16_t data;
+} WM8523_transfer_t;
+
+void WM8523_Init()
+{
+ // 16 bit data tranfers
+ spi_cfg.Databit = SPI_DATABIT_16;
+
+ // WM8523 samples bits on rising edges. Mode 0 or 3 will work
+ // http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase
+
+ // Mode 0
+ spi_cfg.CPHA = SPI_CPHA_FIRST; // 0
+ spi_cfg.CPOL = SPI_CPOL_HI; // 0
+ /*
+ // Mode 3
+ spi_cfg.CPHA = SPI_CPHA_SECOND; // 1
+ spi_cfg.CPOL = SPI_CPOL_LO; // 1
+ */
+
+ // We are the master
+ spi_cfg.Mode = SPI_MASTER_MODE;
+
+ // We run on a little endian mcu.
+ spi_cfg.DataOrder = SPI_DATA_LSB_FIRST;
+
+ // Se WM8523 manual page 14. Min clock pulse width 40ns ~= 25MHz
+ spi_cfg.ClockRate = 1000000000; // 1MHz
+
+ SPI_Init(&spi, &spi_cfg);
+}
+
+static volatile int spi_done = 0;
+void spi_mark_as_done()
+{
+ spi_done = 1;
+}
+
+static void send(void *data, size_t size)
+{
+ SPI_DATA_SETUP_Type dst;
+ memset(&dst, 0, sizeof(dst));
+ dst.rx_data = data;
+ dst.length = size;
+ dst.callback = spi_mark_as_done;
+
+ spi_done = 0;
+ SPI_ReadWrite(&spi, &dst, SPI_TRANSFER_INTERRUPT);
+
+ while(!spi_done) {}
+}
+
+static void receive(void *data, size_t size)
+{
+ // http://anhnvnguyen.blogspot.dk/2010/04/lpc17xx-gpio-basic_05.html
+ // TODO: set SSEL0 low
+ // PINSEL3[13:12] = p1.21 (SSEL0)
+ LPC_PINCON->PINSEL3 &= ~((1<<13)|(1<<12)); // set to 00
+
+ SPI_DATA_SETUP_Type dst;
+ memset(&dst, 0, sizeof(dst));
+ dst.tx_data = data;
+ dst.length = size;
+ dst.callback = spi_mark_as_done;
+
+ spi_done = 0;
+ SPI_ReadWrite(&spi, &dst, SPI_TRANSFER_INTERRUPT);
+
+ while(!spi_done) {}
+
+ // TODO: set SSEL0 high
+}
+
+/**
+Volume update registers R06h and R07h are unavailable in SPI control mode.
+To use volume update in software control mode, I2C mode must be used.
+*/
+void WM8523_Configure()
+{
+ WM8523_transfer_t transfer;
+ transfer.rw = WM8523_READ;
+ transfer.reg = 0; // R0 read version : 0x8523
+ transfer.data = 0;
+ //send(&transfer, sizeof(transfer));
+ receive(&transfer, sizeof(transfer));
+}
diff --git a/firmware/drivers/wm8523.h b/firmware/drivers/wm8523.h
new file mode 100644
index 0000000..085b1f4
--- /dev/null
+++ b/firmware/drivers/wm8523.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wm8523.h
+ *
+ * Tue Jun 4 20:47:15 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pedal2Metal.
+ *
+ * Pedal2Metal 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Pedal2Metal 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 Pedal2Metal; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PEDAL2METAL_WM8523_H__
+#define __PEDAL2METAL_WM8523_H__
+
+void WM8523_Init();
+void WM8523_Configure();
+
+#endif/*__PEDAL2METAL_WM8523_H__*/
diff --git a/firmware/lpc17xx/lpc17xx_clkpwr.c b/firmware/lpc17xx/lpc17xx_clkpwr.c
new file mode 100644
index 0000000..4d075d4
--- /dev/null
+++ b/firmware/lpc17xx/lpc17xx_clkpwr.c
@@ -0,0 +1,344 @@
+/**
+ * @file : lpc17xx_clkpwr.c
+ * @brief : Contains all functions support for Clock and Power Control
+ * firmware library on LPC17xx
+ * @version : 1.0
+ * @date : 18. Mar. 2009
+ * @author : HieuNguyen
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup CLKPWR
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_clkpwr.h"
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup CLKPWR_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Set value of each Peripheral Clock Selection
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @param[in] DivVal Value of divider, should be:
+ * - CLKPWR_PCLKSEL_CCLK_DIV_4 : PCLK_peripheral = CCLK/4
+ * - CLKPWR_PCLKSEL_CCLK_DIV_1 : PCLK_peripheral = CCLK/1
+ * - CLKPWR_PCLKSEL_CCLK_DIV_2 : PCLK_peripheral = CCLK/2
+ *
+ * @return none
+ **********************************************************************/
+void CLKPWR_SetPCLKDiv (uint32_t ClkType, uint32_t DivVal)
+{
+ uint32_t bitpos;
+
+ bitpos = (ClkType < 32) ? (ClkType) : (ClkType - 32);
+
+ /* PCLKSEL0 selected */
+ if (ClkType < 32)
+ {
+ /* Clear two bit at bit position */
+ LPC_SC->PCLKSEL0 &= (~(CLKPWR_PCLKSEL_BITMASK(bitpos)));
+
+ /* Set two selected bit */
+ LPC_SC->PCLKSEL0 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal));
+ }
+ /* PCLKSEL1 selected */
+ else
+ {
+ /* Clear two bit at bit position */
+ LPC_SC->PCLKSEL1 &= ~(CLKPWR_PCLKSEL_BITMASK(bitpos));
+
+ /* Set two selected bit */
+ LPC_SC->PCLKSEL1 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal));
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Get current value of each Peripheral Clock Selection
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @return Value of Selected Peripheral Clock Selection
+ **********************************************************************/
+uint32_t CLKPWR_GetPCLKSEL (uint32_t ClkType)
+{
+ uint32_t bitpos, retval;
+
+ if (ClkType < 32)
+ {
+ bitpos = ClkType;
+ retval = LPC_SC->PCLKSEL0;
+ }
+ else
+ {
+ bitpos = ClkType - 32;
+ retval = LPC_SC->PCLKSEL1;
+ }
+
+ retval = CLKPWR_PCLKSEL_GET(bitpos, retval);
+ return retval;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Get current value of each Peripheral Clock
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @return Value of Selected Peripheral Clock
+ **********************************************************************/
+uint32_t CLKPWR_GetPCLK (uint32_t ClkType)
+{
+ uint32_t retval, div;
+
+ retval = SystemCoreClock;
+ div = CLKPWR_GetPCLKSEL(ClkType);
+
+ switch (div)
+ {
+ case 0:
+ div = 4;
+ break;
+
+ case 1:
+ div = 1;
+ break;
+
+ case 2:
+ div = 2;
+ break;
+
+ case 3:
+ div = 8;
+ break;
+ }
+ retval /= div;
+
+ return retval;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Configure power supply for each peripheral according to NewState
+ * @param[in] PPType Type of peripheral used to enable power,
+ * should be one of the following:
+ * - CLKPWR_PCONP_PCTIM0 : Timer 0
+ - CLKPWR_PCONP_PCTIM1 : Timer 1
+ - CLKPWR_PCONP_PCUART0 : UART 0
+ - CLKPWR_PCONP_PCUART1 : UART 1
+ - CLKPWR_PCONP_PCPWM1 : PWM 1
+ - CLKPWR_PCONP_PCI2C0 : I2C 0
+ - CLKPWR_PCONP_PCSPI : SPI
+ - CLKPWR_PCONP_PCRTC : RTC
+ - CLKPWR_PCONP_PCSSP1 : SSP 1
+ - CLKPWR_PCONP_PCAD : ADC
+ - CLKPWR_PCONP_PCAN1 : CAN 1
+ - CLKPWR_PCONP_PCAN2 : CAN 2
+ - CLKPWR_PCONP_PCGPIO : GPIO
+ - CLKPWR_PCONP_PCRIT : RIT
+ - CLKPWR_PCONP_PCMC : MC
+ - CLKPWR_PCONP_PCQEI : QEI
+ - CLKPWR_PCONP_PCI2C1 : I2C 1
+ - CLKPWR_PCONP_PCSSP0 : SSP 0
+ - CLKPWR_PCONP_PCTIM2 : Timer 2
+ - CLKPWR_PCONP_PCTIM3 : Timer 3
+ - CLKPWR_PCONP_PCUART2 : UART 2
+ - CLKPWR_PCONP_PCUART3 : UART 3
+ - CLKPWR_PCONP_PCI2C2 : I2C 2
+ - CLKPWR_PCONP_PCI2S : I2S
+ - CLKPWR_PCONP_PCGPDMA : GPDMA
+ - CLKPWR_PCONP_PCENET : Ethernet
+ - CLKPWR_PCONP_PCUSB : USB
+ *
+ * @param[in] NewState New state of Peripheral Power, should be:
+ * - ENABLE : Enable power for this peripheral
+ * - DISABLE : Disable power for this peripheral
+ *
+ * @return none
+ **********************************************************************/
+void CLKPWR_ConfigPPWR (uint32_t PPType, FunctionalState NewState)
+{
+ if (NewState == ENABLE)
+ {
+ LPC_SC->PCONP |= PPType & CLKPWR_PCONP_BITMASK;
+ }
+ else if (NewState == DISABLE)
+ {
+ LPC_SC->PCONP &= (~PPType) & CLKPWR_PCONP_BITMASK;
+ }
+}
+
+
+/**
+ * @brief Enter Sleep mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ */
+void CLKPWR_Sleep(void)
+{
+ LPC_SC->PCON = 0x00;
+ /* Sleep Mode*/
+ __WFI();
+}
+
+
+/**
+ * @brief Enter Deep Sleep mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ */
+void CLKPWR_DeepSleep(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x00;
+ /* Sleep Mode*/
+ __WFI();
+}
+
+
+/**
+ * @brief Enter Power Down mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ */
+void CLKPWR_PowerDown(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x01;
+ /* Sleep Mode*/
+ __WFI();
+}
+
+
+/**
+ * @brief Enter Deep Power Down mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ */
+void CLKPWR_DeepPowerDown(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x03;
+ /* Sleep Mode*/
+ __WFI();
+}
+
+
+/**
+ * @brief Configure Brown-Out function in
+ */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/firmware/lpc17xx/lpc17xx_clkpwr.h b/firmware/lpc17xx/lpc17xx_clkpwr.h
new file mode 100644
index 0000000..190d5bb
--- /dev/null
+++ b/firmware/lpc17xx/lpc17xx_clkpwr.h
@@ -0,0 +1,384 @@
+/***********************************************************************//**
+ * @file : lpc17xx_clkpwr.h
+ * @brief : Contains all macro definitions and function prototypes
+ * support for Clock and Power Control firmware library on LPC17xx
+ * @version : 1.0
+ * @date : 18. Mar. 2009
+ * @author : HieuNguyen
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **************************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @defgroup CLKPWR
+ * @ingroup LPC1700CMSIS_FwLib_Drivers
+ * @{
+ */
+
+#ifndef LPC17XX_CLKPWR_H_
+#define LPC17XX_CLKPWR_H_
+
+/* Includes ------------------------------------------------------------------- */
+#include <LPC17xx.h>
+#include "lpc_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/* Private Macros ------------------------------------------------------------- */
+/** @defgroup CLKPWR_Private_Macros
+ * @{
+ */
+
+/** @defgroup CLKPPWR_REGISTER_BIT_DEFINITIONS
+ * @{
+ */
+
+/* Clock source selection multiplexer definition */
+/** Internal RC oscillator */
+#define CLKPWR_CLKSRCSEL_CLKSRC_IRC ((uint32_t)(0x00))
+/** Main oscillator */
+#define CLKPWR_CLKSRCSEL_CLKSRC_MAINOSC ((uint32_t)(0x01))
+/** RTC oscillator */
+#define CLKPWR_CLKSRCSEL_CLKSRC_RTC ((uint32_t)(0x02))
+/** Clock source selection bit mask */
+#define CLKPWR_CLKSRCSEL_BITMASK ((uint32_t)(0x03))
+
+
+/* Clock Output Configuration register definition */
+/** Selects the CPU clock as the CLKOUT source */
+#define CLKPWR_CLKOUTCFG_CLKOUTSEL_CPU ((uint32_t)(0x00))
+/** Selects the main oscillator as the CLKOUT source */
+#define CLKPWR_CLKOUTCFG_CLKOUTSEL_MAINOSC ((uint32_t)(0x01))
+/** Selects the Internal RC oscillator as the CLKOUT source */
+#define CLKPWR_CLKOUTCFG_CLKOUTSEL_RC ((uint32_t)(0x02))
+/** Selects the USB clock as the CLKOUT source */
+#define CLKPWR_CLKOUTCFG_CLKOUTSEL_USB ((uint32_t)(0x03))
+/** Selects the RTC oscillator as the CLKOUT source */
+#define CLKPWR_CLKOUTCFG_CLKOUTSEL_RTC ((uint32_t)(0x04))
+/** Integer value to divide the output clock by, minus one */
+#define CLKPWR_CLKOUTCFG_CLKOUTDIV(n) ((uint32_t)((n&0x0F)<<4))
+/** CLKOUT enable control */
+#define CLKPWR_CLKOUTCFG_CLKOUT_EN ((uint32_t)(1<<8))
+/** CLKOUT activity indication */
+#define CLKPWR_CLKOUTCFG_CLKOUT_ACT ((uint32_t)(1<<9))
+/** Clock source selection bit mask */
+#define CLKPWR_CLKOUTCFG_BITMASK ((uint32_t)(0x3FF))
+
+
+/* PLL 0 control definition */
+/** PLL 0 control enable */
+#define CLKPWR_PLL0CON_ENABLE ((uint32_t)(0x01))
+/** PLL 0 control connect */
+#define CLKPWR_PLL0CON_CONNECT ((uint32_t)(0x02))
+/** PLL 0 control bit mask */
+#define CLKPWR_PLL0CON_BITMASK ((uint32_t)(0x03))
+
+
+/* PLL 0 Configuration register definition */
+/** PLL 0 Configuration MSEL field */
+#define CLKPWR_PLL0CFG_MSEL(n) ((uint32_t)(n&0x7FFF))
+/** PLL 0 Configuration NSEL field */
+#define CLKPWR_PLL0CFG_NSEL(n) ((uint32_t)((n<<16)&0xFF0000))
+/** PLL 0 Configuration bit mask */
+#define CLKPWR_PLL0CFG_BITMASK ((uint32_t)(0xFF7FFF))
+
+
+/* PLL 0 status definition */
+/** PLL 0 MSEL value */
+#define CLKPWR_PLL0STAT_MSEL(n) ((uint32_t)(n&0x7FFF))
+/** PLL NSEL get value */
+#define CLKPWR_PLL0STAT_NSEL(n) ((uint32_t)((n>>16)&0xFF))
+/** PLL status enable bit */
+#define CLKPWR_PLL0STAT_PLLE ((uint32_t)(1<<24))
+/** PLL status Connect bit */
+#define CLKPWR_PLL0STAT_PLLC ((uint32_t)(1<<25))
+/** PLL status lock */
+#define CLKPWR_PLL0STAT_PLOCK ((uint32_t)(1<<26))
+
+
+/* PLL0 Feed register definition */
+/** PLL0 Feed bit mask */
+#define CLKPWR_PLL0FEED_BITMASK ((uint32_t)0xFF)
+
+
+/* USB PLL control definition */
+/** USB PLL control enable */
+#define CLKPWR_PLL1CON_ENABLE ((uint32_t)(0x01))
+/** USB PLL control connect */
+#define CLKPWR_PLL1CON_CONNECT ((uint32_t)(0x02))
+/** USB PLL control bit mask */
+#define CLKPWR_PLL1CON_BITMASK ((uint32_t)(0x03))
+
+
+/* USB PLL configuration definition */
+/** USB PLL MSEL set value */
+#define CLKPWR_PLL1CFG_MSEL(n) ((uint32_t)(n&0x1F))
+/** USB PLL PSEL set value */
+#define CLKPWR_PLL1CFG_PSEL(n) ((uint32_t)((n&0x03)<<5))
+/** USB PLL configuration bit mask */
+#define CLKPWR_PLL1CFG_BITMASK ((uint32_t)(0x7F))
+
+
+/* USB PLL status definition */
+/** USB PLL MSEL get value */
+#define CLKPWR_PLL1STAT_MSEL(n) ((uint32_t)(n&0x1F))
+/** USB PLL PSEL get value */
+#define CLKPWR_PLL1STAT_PSEL(n) ((uint32_t)((n>>5)&0x03))
+/** USB PLL status enable bit */
+#define CLKPWR_PLL1STAT_PLLE ((uint32_t)(1<<8))
+/** USB PLL status Connect bit */
+#define CLKPWR_PLL1STAT_PLLC ((uint32_t)(1<<9))
+/** USB PLL status lock */
+#define CLKPWR_PLL1STAT_PLOCK ((uint32_t)(1<<10))
+
+
+/* PLL1 Feed register definition */
+/** PLL1 Feed bit mask */
+#define CLKPWR_PLL1FEED_BITMASK ((uint32_t)0xFF)
+
+
+/* CPU Clock Configuration register definition */
+/** CPU Clock configuration bit mask */
+#define CLKPWR_CCLKCFG_BITMASK ((uint32_t)(0xFF))
+
+/* USB Clock Configuration register definition */
+/** USB Clock Configuration bit mask */
+#define CLKPWR_USBCLKCFG_BITMASK ((uint32_t)(0x0F))
+
+/* IRC Trim register definition */
+/** IRC Trim bit mask */
+#define CLKPWR_IRCTRIM_BITMASK ((uint32_t)(0x0F))
+
+
+/* Peripheral clock divider bit position definition */
+/** Peripheral Clock Selection 0 mask bit */
+#define CLKPWR_PCLKSEL0_BITMASK ((uint32_t)(0xFFF3F3FF))
+/** Peripheral Clock Selection 1 mask bit */
+#define CLKPWR_PCLKSEL1_BITMASK ((uint32_t)(0xFCF3F0F3))
+
+
+/** Macro to set peripheral clock of each type
+ * p: position of two bits that hold divider of peripheral clock
+ * n: value of divider of peripheral clock to be set */
+#define CLKPWR_PCLKSEL_SET(p,n) _SBF(p,n)
+/** Macro to mask peripheral clock of each type */
+#define CLKPWR_PCLKSEL_BITMASK(p) _SBF(p,0x03)
+/** Macro to get peripheral clock of each type */
+#define CLKPWR_PCLKSEL_GET(p, n) ((uint32_t)((n>>p)&0x03))
+
+
+/* Power Mode Control register definition */
+/** Power mode control bit 0 */
+#define CLKPWR_PCON_PM0 ((uint32_t)(1<<0))
+/** Power mode control bit 1 */
+#define CLKPWR_PCON_PM1 ((uint32_t)(1<<1))
+/** Brown-Out Reduced Power Mode */
+#define CLKPWR_PCON_BODPDM ((uint32_t)(1<<2))
+/** Brown-Out Global Disable */
+#define CLKPWR_PCON_BOGD ((uint32_t)(1<<3))
+/** Brown Out Reset Disable */
+#define CLKPWR_PCON_BORD ((uint32_t)(1<<4))
+/** Sleep Mode entry flag */
+#define CLKPWR_PCON_SMFLAG ((uint32_t)(1<<8))
+/** Deep Sleep entry flag */
+#define CLKPWR_PCON_DSFLAG ((uint32_t)(1<<9))
+/** Power-down entry flag */
+#define CLKPWR_PCON_PDFLAG ((uint32_t)(1<<10))
+/** Deep Power-down entry flag */
+#define CLKPWR_PCON_DPDFLAG ((uint32_t)(1<<11))
+
+
+/** Power Control for Peripherals bit mask */
+#define CLKPWR_PCONP_BITMASK 0xEFEFF7DE
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/* Public Macros -------------------------------------------------------------- */
+/** @defgroup CLKPWR_Public_Macros
+ * @{
+ */
+
+/**********************************************************************
+ * Peripheral Clock Selection Definitions
+ **********************************************************************/
+/** Peripheral clock divider bit position for WDT */
+#define CLKPWR_PCLKSEL_WDT ((uint32_t)(0))
+/** Peripheral clock divider bit position for TIMER0 */
+#define CLKPWR_PCLKSEL_TIMER0 ((uint32_t)(2))
+/** Peripheral clock divider bit position for TIMER1 */
+#define CLKPWR_PCLKSEL_TIMER1 ((uint32_t)(4))
+/** Peripheral clock divider bit position for UART0 */
+#define CLKPWR_PCLKSEL_UART0 ((uint32_t)(6))
+/** Peripheral clock divider bit position for UART1 */
+#define CLKPWR_PCLKSEL_UART1 ((uint32_t)(8))
+/** Peripheral clock divider bit position for PWM1 */
+#define CLKPWR_PCLKSEL_PWM1 ((uint32_t)(12))
+/** Peripheral clock divider bit position for I2C0 */
+#define CLKPWR_PCLKSEL_I2C0 ((uint32_t)(14))
+/** Peripheral clock divider bit position for SPI */
+#define CLKPWR_PCLKSEL_SPI ((uint32_t)(16))
+/** Peripheral clock divider bit position for SSP1 */
+#define CLKPWR_PCLKSEL_SSP1 ((uint32_t)(20))
+/** Peripheral clock divider bit position for DAC */
+#define CLKPWR_PCLKSEL_DAC ((uint32_t)(22))
+/** Peripheral clock divider bit position for ADC */
+#define CLKPWR_PCLKSEL_ADC ((uint32_t)(24))
+/** Peripheral clock divider bit position for CAN1 */
+#define CLKPWR_PCLKSEL_CAN1 ((uint32_t)(26))
+/** Peripheral clock divider bit position for CAN2 */
+#define CLKPWR_PCLKSEL_CAN2 ((uint32_t)(28))
+/** Peripheral clock divider bit position for ACF */
+#define CLKPWR_PCLKSEL_ACF ((uint32_t)(30))
+/** Peripheral clock divider bit position for QEI */
+#define CLKPWR_PCLKSEL_QEI ((uint32_t)(32))
+/** Peripheral clock divider bit position for PCB */
+#define CLKPWR_PCLKSEL_PCB ((uint32_t)(36))
+/** Peripheral clock divider bit position for I2C1 */
+#define CLKPWR_PCLKSEL_I2C1 ((uint32_t)(38))
+/** Peripheral clock divider bit position for SSP0 */
+#define CLKPWR_PCLKSEL_SSP0 ((uint32_t)(42))
+/** Peripheral clock divider bit position for TIMER2 */
+#define CLKPWR_PCLKSEL_TIMER2 ((uint32_t)(44))
+/** Peripheral clock divider bit position for TIMER3 */
+#define CLKPWR_PCLKSEL_TIMER3 ((uint32_t)(46))
+/** Peripheral clock divider bit position for UART2 */
+#define CLKPWR_PCLKSEL_UART2 ((uint32_t)(48))
+/** Peripheral clock divider bit position for UART3 */
+#define CLKPWR_PCLKSEL_UART3 ((uint32_t)(50))
+/** Peripheral clock divider bit position for I2C2 */
+#define CLKPWR_PCLKSEL_I2C2 ((uint32_t)(52))
+/** Peripheral clock divider bit position for I2S */
+#define CLKPWR_PCLKSEL_I2S ((uint32_t)(54))
+/** Peripheral clock divider bit position for RIT */
+#define CLKPWR_PCLKSEL_RIT ((uint32_t)(58))
+/** Peripheral clock divider bit position for SYSCON */
+#define CLKPWR_PCLKSEL_SYSCON ((uint32_t)(60))
+/** Peripheral clock divider bit position for MC */
+#define CLKPWR_PCLKSEL_MC ((uint32_t)(62))
+
+/** Macro for Peripheral Clock Selection register bit values
+ * Note: When CCLK_DIV_8, Peripheral’s clock is selected to
+ * PCLK_xyz = CCLK/8 except for CAN1, CAN2, and CAN filtering
+ * when ’11’selects PCLK_xyz = CCLK/6 */
+/* Peripheral clock divider is set to 4 from CCLK */
+#define CLKPWR_PCLKSEL_CCLK_DIV_4 ((uint32_t)(0))
+/** Peripheral clock divider is the same with CCLK */
+#define CLKPWR_PCLKSEL_CCLK_DIV_1 ((uint32_t)(1))
+/** Peripheral clock divider is set to 2 from CCLK */
+#define CLKPWR_PCLKSEL_CCLK_DIV_2 ((uint32_t)(2))
+
+
+/********************************************************************
+* Power Control for Peripherals Definitions
+**********************************************************************/
+/** Timer/Counter 0 power/clock control bit */
+#define CLKPWR_PCONP_PCTIM0 ((uint32_t)(1<<1))
+/* Timer/Counter 1 power/clock control bit */
+#define CLKPWR_PCONP_PCTIM1 ((uint32_t)(1<<2))
+/** UART0 power/clock control bit */
+#define CLKPWR_PCONP_PCUART0 ((uint32_t)(1<<3))
+/** UART1 power/clock control bit */
+#define CLKPWR_PCONP_PCUART1 ((uint32_t)(1<<4))
+/** PWM1 power/clock control bit */
+#define CLKPWR_PCONP_PCPWM1 ((uint32_t)(1<<6))
+/** The I2C0 interface power/clock control bit */
+#define CLKPWR_PCONP_PCI2C0 ((uint32_t)(1<<7))
+/** The SPI interface power/clock control bit */
+#define CLKPWR_PCONP_PCSPI ((uint32_t)(1<<8))
+/** The RTC power/clock control bit */
+#define CLKPWR_PCONP_PCRTC ((uint32_t)(1<<9))
+/** The SSP1 interface power/clock control bit */
+#define CLKPWR_PCONP_PCSSP1 ((uint32_t)(1<<10))
+/** A/D converter 0 (ADC0) power/clock control bit */
+#define CLKPWR_PCONP_PCAD ((uint32_t)(1<<12))
+/** CAN Controller 1 power/clock control bit */
+#define CLKPWR_PCONP_PCAN1 ((uint32_t)(1<<13))
+/** CAN Controller 2 power/clock control bit */
+#define CLKPWR_PCONP_PCAN2 ((uint32_t)(1<<14))
+/** GPIO power/clock control bit */
+#define CLKPWR_PCONP_PCGPIO ((uint32_t)(1<<15))
+/** Repetitive Interrupt Timer power/clock control bit */
+#define CLKPWR_PCONP_PCRIT ((uint32_t)(1<<16))
+/** Motor Control PWM */
+#define CLKPWR_PCONP_PCMC ((uint32_t)(1<<17))
+/** Quadrature Encoder Interface power/clock control bit */
+#define CLKPWR_PCONP_PCQEI ((uint32_t)(1<<18))
+/** The I2C1 interface power/clock control bit */
+#define CLKPWR_PCONP_PCI2C1 ((uint32_t)(1<<19))
+/** The SSP0 interface power/clock control bit */
+#define CLKPWR_PCONP_PCSSP0 ((uint32_t)(1<<21))
+/** Timer 2 power/clock control bit */
+#define CLKPWR_PCONP_PCTIM2 ((uint32_t)(1<<22))
+/** Timer 3 power/clock control bit */
+#define CLKPWR_PCONP_PCTIM3 ((uint32_t)(1<<23))
+/** UART 2 power/clock control bit */
+#define CLKPWR_PCONP_PCUART2 ((uint32_t)(1<<24))
+/** UART 3 power/clock control bit */
+#define CLKPWR_PCONP_PCUART3 ((uint32_t)(1<<25))
+/** I2C interface 2 power/clock control bit */
+#define CLKPWR_PCONP_PCI2C2 ((uint32_t)(1<<26))
+/** I2S interface power/clock control bit*/
+#define CLKPWR_PCONP_PCI2S ((uint32_t)(1<<27))
+/** GP DMA function power/clock control bit*/
+#define CLKPWR_PCONP_PCGPDMA ((uint32_t)(1<<29))
+/** Ethernet block power/clock control bit*/
+#define CLKPWR_PCONP_PCENET ((uint32_t)(1<<30))
+/** USB interface power/clock control bit*/
+#define CLKPWR_PCONP_PCUSB ((uint32_t)(1<<31))
+
+
+/**
+ * @}
+ */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @defgroup CLKPWR_Public_Functions
+ * @{
+ */
+
+void CLKPWR_SetPCLKDiv (uint32_t ClkType, uint32_t DivVal);
+uint32_t CLKPWR_GetPCLKSEL (uint32_t ClkType);
+uint32_t CLKPWR_GetPCLK (uint32_t ClkType);
+void CLKPWR_ConfigPPWR (uint32_t PPType, FunctionalState NewState);
+void CLKPWR_Sleep(void);
+void CLKPWR_DeepSleep(void);
+void CLKPWR_PowerDown(void);
+void CLKPWR_DeepPowerDown(void);
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LPC17XX_CLKPWR_H_ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/firmware/lpc17xx/lpc17xx_spi.c b/firmware/lpc17xx/lpc17xx_spi.c
new file mode 100644
index 0000000..622b1e7
--- /dev/null
+++ b/firmware/lpc17xx/lpc17xx_spi.c
@@ -0,0 +1,550 @@
+/**
+ * @file : lpc17xx_spi.c
+ * @brief : Contains all functions support for SPI firmware library on LPC17xx
+ * @version : 1.0
+ * @date : 3. April. 2009
+ * @author : HieuNguyen
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup SPI
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_spi.h"
+#include "lpc17xx_clkpwr.h"
+
+#define CHECK_PARAM(expr)
+
+/* Private Types -------------------------------------------------------------- */
+/** @defgroup SPI_Private_Types
+ * @{
+ */
+
+/** @brief SPI device configuration structure type */
+typedef struct
+{
+ int32_t dataword; /* Current data word: 0 - 8 bit; 1 - 16 bit */
+ uint32_t txrx_setup; /* Transmission setup */
+ void (*inthandler)(void); /* Transmission interrupt handler */
+} SPI_CFG_T;
+
+/**
+ * @}
+ */
+
+
+/* Private Variables ---------------------------------------------------------- */
+/* SPI configuration data */
+static SPI_CFG_T spidat;
+
+
+/* Private Functions ---------------------------------------------------------- */
+/** @defgroup SPI_Private_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Standard Private SPI Interrupt handler
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+void SPI_IntHandler(void)
+{
+ SPI_DATA_SETUP_Type *xf_setup;
+ uint16_t tmp;
+
+ xf_setup = (SPI_DATA_SETUP_Type *)spidat.txrx_setup;
+
+ /* Dummy read to clear SPI interrupt flag */
+ if (LPC_SPI->SPINT & SPI_SPINT_INTFLAG){
+ LPC_SPI->SPINT = SPI_SPINT_INTFLAG;
+ }
+
+ // save status
+ tmp = LPC_SPI->SPSR;
+ xf_setup->status = tmp;
+ // Check for error
+ if (tmp & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){
+ xf_setup->status |= SPI_STAT_ERROR;
+ // Disable Interrupt and call call-back
+ SPI_IntCmd(LPC_SPI, DISABLE);
+ if (xf_setup->callback != NULL){
+ xf_setup->callback();
+ }
+ return;
+ }
+
+ /* Check SPI complete flag */
+ if (tmp & SPI_SPSR_SPIF){
+ // Read data from SPI data
+ tmp = SPI_ReceiveData(LPC_SPI);
+ if (xf_setup->rx_data != NULL)
+ {
+// if (spidat.dataword == 0){
+// *(uint8_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp;
+// } else {
+// *(uint16_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp;
+// }
+ if (spidat.dataword == 0){
+ *(uint8_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp;
+ } else {
+ *(uint16_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp;
+ }
+ }
+ // Increase counter
+ if (spidat.dataword == 0){
+ xf_setup->counter++;
+ } else {
+ xf_setup->counter += 2;
+ }
+ }
+
+ if (xf_setup->counter < xf_setup->length){
+ // Write data to buffer
+ if(xf_setup->tx_data == NULL){
+ if (spidat.dataword == 0){
+ SPI_SendData(LPC_SPI, 0xFF);
+ } else {
+ SPI_SendData(LPC_SPI, 0xFFFF);
+ }
+ } else {
+// if (spidat.dataword == 0){
+// SPI_SendData(SPI, (*(uint8_t *)(xf_setup->tx_data + xf_setup->counter)));
+// } else {
+// SPI_SendData(SPI, (*(uint16_t *)(xf_setup->tx_data + xf_setup->counter)));
+// }
+ if (spidat.dataword == 0){
+ SPI_SendData(LPC_SPI, (*(uint8_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter)));
+ } else {
+ SPI_SendData(LPC_SPI, (*(uint16_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter)));
+ }
+ }
+ }
+ // No more data to send
+ else {
+ xf_setup->status |= SPI_STAT_DONE;
+ // Disable Interrupt and call call-back
+ SPI_IntCmd(LPC_SPI, DISABLE);
+ if (xf_setup->callback != NULL){
+ xf_setup->callback();
+ }
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup SPI_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Setup clock rate for SPI device
+ * @param[in] SPIx SPI peripheral definition, should be SPI
+ * @param[in] target_clock : clock of SPI (Hz)
+ * @return None
+ ***********************************************************************/
+void SPI_SetClock (LPC_SPI_TypeDef *SPIx, uint32_t target_clock)
+{
+ uint32_t spi_pclk;
+ uint32_t prescale, temp;
+
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if (SPIx == LPC_SPI){
+ spi_pclk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SPI);
+ } else {
+ return;
+ }
+
+ prescale = 8;
+ // Find closest clock to target clock
+ while (1){
+ temp = target_clock * prescale;
+ if (temp >= spi_pclk){
+ break;
+ }
+ prescale += 2;
+ if(prescale >= 254){
+ break;
+ }
+ }
+
+ // Write to register
+ SPIx->SPCCR = SPI_SPCCR_COUNTER(prescale);
+}
+
+
+/*********************************************************************//**
+ * @brief De-initializes the SPIx peripheral registers to their
+* default reset values.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @return None
+ **********************************************************************/
+void SPI_DeInit(LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if (SPIx == LPC_SPI){
+ /* Set up clock and power for SPI module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, DISABLE);
+ }
+}
+
+
+
+/********************************************************************//**
+ * @brief Initializes the SPIx peripheral according to the specified
+* parameters in the UART_ConfigStruct.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @param[in] SPI_ConfigStruct Pointer to a SPI_CFG_Type structure
+* that contains the configuration information for the
+* specified SPI peripheral.
+ * @return None
+ *********************************************************************/
+void SPI_Init(LPC_SPI_TypeDef *SPIx, SPI_CFG_Type *SPI_ConfigStruct)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if(SPIx == LPC_SPI){
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, ENABLE);
+ } else {
+ return;
+ }
+
+ // Configure SPI, interrupt is disable as default
+ tmp = ((SPI_ConfigStruct->CPHA) | (SPI_ConfigStruct->CPOL) \
+ | (SPI_ConfigStruct->DataOrder) | (SPI_ConfigStruct->Databit) \
+ | (SPI_ConfigStruct->Mode) | SPI_SPCR_BIT_EN) & SPI_SPCR_BITMASK;
+ // write back to SPI control register
+ SPIx->SPCR = tmp;
+
+ if (SPI_ConfigStruct->Databit > SPI_DATABIT_8){
+ spidat.dataword = 1;
+ } else {
+ spidat.dataword = 0;
+ }
+
+ // Set clock rate for SPI peripheral
+ SPI_SetClock(SPIx, SPI_ConfigStruct->ClockRate);
+
+ // If interrupt flag is set, Write '1' to Clear interrupt flag
+ if (SPIx->SPINT & SPI_SPINT_INTFLAG){
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+ }
+}
+
+
+
+/*****************************************************************************//**
+* @brief Fills each SPI_InitStruct member with its default value:
+* - CPHA = SPI_CPHA_FIRST
+* - CPOL = SPI_CPOL_HI
+* - ClockRate = 1000000
+* - DataOrder = SPI_DATA_MSB_FIRST
+* - Databit = SPI_DATABIT_8
+* - Mode = SPI_MASTER_MODE
+* @param[in] SPI_InitStruct Pointer to a SPI_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void SPI_ConfigStructInit(SPI_CFG_Type *SPI_InitStruct)
+{
+ SPI_InitStruct->CPHA = SPI_CPHA_FIRST;
+ SPI_InitStruct->CPOL = SPI_CPOL_HI;
+ SPI_InitStruct->ClockRate = 1000000;
+ SPI_InitStruct->DataOrder = SPI_DATA_MSB_FIRST;
+ SPI_InitStruct->Databit = SPI_DATABIT_8;
+ SPI_InitStruct->Mode = SPI_MASTER_MODE;
+}
+
+/*********************************************************************//**
+ * @brief Transmit a single data through SPIx peripheral
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @param[in] Data Data to transmit (must be 16 or 8-bit long,
+ * this depend on SPI data bit number configured)
+ * @return none
+ **********************************************************************/
+void SPI_SendData(LPC_SPI_TypeDef* SPIx, uint16_t Data)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ SPIx->SPDR = Data & SPI_SPDR_BITMASK;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Receive a single data from SPIx peripheral
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @return Data received (16-bit long)
+ **********************************************************************/
+uint16_t SPI_ReceiveData(LPC_SPI_TypeDef* SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return ((uint16_t) (SPIx->SPDR & SPI_SPDR_BITMASK));
+}
+
+/*********************************************************************//**
+ * @brief SPI Read write data function
+ * @param[in] SPIx Pointer to SPI peripheral, should be SPI
+ * @param[in] dataCfg Pointer to a SPI_DATA_SETUP_Type structure that
+ * contains specified information about transmit
+ * data configuration.
+ * @param[in] xfType Transfer type, should be:
+ * - SPI_TRANSFER_POLLING: Polling mode
+ * - SPI_TRANSFER_INTERRUPT: Interrupt mode
+ * @return Actual Data length has been transferred in polling mode.
+ * In interrupt mode, always return (0)
+ * Return (-1) if error.
+ * Note: This function can be used in both master and slave mode.
+ ***********************************************************************/
+int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, \
+ SPI_TRANSFER_Type xfType)
+{
+ uint8_t *rdata8;
+ uint8_t *wdata8;
+ uint16_t *rdata16;
+ uint16_t *wdata16;
+ uint32_t stat;
+ uint32_t temp;
+
+ //read for empty buffer
+ temp = SPIx->SPDR;
+ //dummy to clear status
+ temp = SPIx->SPSR;
+ dataCfg->counter = 0;
+ dataCfg->status = 0;
+
+ if (xfType == SPI_TRANSFER_POLLING){
+
+ if (spidat.dataword == 0){
+ rdata8 = (uint8_t *)dataCfg->rx_data;
+ wdata8 = (uint8_t *)dataCfg->tx_data;
+ } else {
+ rdata16 = (uint16_t *)dataCfg->rx_data;
+ wdata16 = (uint16_t *)dataCfg->tx_data;
+ }
+
+ while(dataCfg->counter < dataCfg->length)
+ {
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (spidat.dataword == 0){
+ SPI_SendData(SPIx, 0xFF);
+ } else {
+ SPI_SendData(SPIx, 0xFFFF);
+ }
+ } else {
+ if (spidat.dataword == 0){
+ SPI_SendData(SPIx, *wdata8);
+ wdata8++;
+ } else {
+ SPI_SendData(SPIx, *wdata16);
+ wdata16++;
+ }
+ }
+ // Wait for transfer complete
+ while (!((stat = SPIx->SPSR) & SPI_SPSR_SPIF));
+ // Check for error
+ if (stat & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){
+ // save status
+ dataCfg->status = stat | SPI_STAT_ERROR;
+ return (dataCfg->counter);
+ }
+ // Read data from SPI dat
+ temp = (uint32_t) SPI_ReceiveData(SPIx);
+
+ // Store data to destination
+ if (dataCfg->rx_data != NULL)
+ {
+ if (spidat.dataword == 0){
+ *(rdata8) = (uint8_t) temp;
+ rdata8++;
+ } else {
+ *(rdata16) = (uint16_t) temp;
+ rdata16++;
+ }
+ }
+ // Increase counter
+ if (spidat.dataword == 0){
+ dataCfg->counter++;
+ } else {
+ dataCfg->counter += 2;
+ }
+ }
+
+ // Return length of actual data transferred
+ // save status
+ dataCfg->status = stat | SPI_STAT_DONE;
+ return (dataCfg->counter);
+ }
+ // Interrupt mode
+ else {
+ spidat.txrx_setup = (uint32_t)dataCfg;
+ spidat.inthandler = SPI_IntHandler;
+
+ // Check if interrupt flag is already set
+ if(SPIx->SPINT & SPI_SPINT_INTFLAG){
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+ }
+ if (dataCfg->counter < dataCfg->length){
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (spidat.dataword == 0){
+ SPI_SendData(SPIx, 0xFF);
+ } else {
+ SPI_SendData(SPIx, 0xFFFF);
+ }
+ } else {
+ if (spidat.dataword == 0){
+ SPI_SendData(SPIx, (*(uint8_t *)dataCfg->tx_data));
+ } else {
+ SPI_SendData(SPIx, (*(uint16_t *)dataCfg->tx_data));
+ }
+ }
+ SPI_IntCmd(SPIx, ENABLE);
+ } else {
+ // Save status
+ dataCfg->status = SPI_STAT_DONE;
+ }
+ return (0);
+ }
+ return (0);
+}
+
+
+/********************************************************************//**
+ * @brief Enable or disable SPIx interrupt.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @param[in] NewState New state of specified UART interrupt type,
+ * should be:
+ * - ENALBE: Enable this SPI interrupt.
+* - DISALBE: Disable this SPI interrupt.
+ * @return None
+ *********************************************************************/
+void SPI_IntCmd(LPC_SPI_TypeDef *SPIx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SPIx->SPCR |= SPI_SPCR_SPIE;
+ }
+ else
+ {
+ SPIx->SPCR &= (~SPI_SPCR_SPIE) & SPI_SPCR_BITMASK;
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Checks whether the SPI interrupt flag is set or not.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @return The new state of SPI Interrupt Flag (SET or RESET)
+ *********************************************************************/
+IntStatus SPI_GetIntStatus (LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return ((SPIx->SPINT & SPI_SPINT_INTFLAG) ? SET : RESET);
+}
+
+
+/********************************************************************//**
+ * @brief Clear SPI interrupt flag.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @return None
+ *********************************************************************/
+void SPI_ClearIntPending(LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+}
+
+
+/********************************************************************//**
+ * @brief Get current value of SPI Status register in SPIx peripheral.
+ * @param[in] SPIx SPI peripheral selected, should be SPI
+ * @return Current value of SPI Status register in SPI peripheral.
+ * Note: The return value of this function must be used with
+ * SPI_CheckStatus() to determine current flag status
+ * corresponding to each SPI status type. Because some flags in
+ * SPI Status register will be cleared after reading, the next reading
+ * SPI Status register could not be correct. So this function used to
+ * read SPI status register in one time only, then the return value
+ * used to check all flags.
+ *********************************************************************/
+uint32_t SPI_GetStatus(LPC_SPI_TypeDef* SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return (SPIx->SPSR & SPI_SPSR_BITMASK);
+}
+
+
+
+/********************************************************************//**
+ * @brief Checks whether the specified SPI Status flag is set or not
+ * via inputSPIStatus parameter.
+ * @param[in] inputSPIStatus Value to check status of each flag type.
+ * This value is the return value from SPI_GetStatus().
+ * @param[in] SPIStatus Specifies the SPI status flag to check,
+ * should be one of the following:
+ - SPI_STAT_ABRT: Slave abort.
+ - SPI_STAT_MODF: Mode fault.
+ - SPI_STAT_ROVR: Read overrun.
+ - SPI_STAT_WCOL: Write collision.
+ - SPI_STAT_SPIF: SPI transfer complete.
+ * @return The new state of SPIStatus (SET or RESET)
+ *********************************************************************/
+FlagStatus SPI_CheckStatus (uint32_t inputSPIStatus, uint8_t SPIStatus)
+{
+ CHECK_PARAM(PARAM_SPI_STAT(SPIStatus));
+
+ return ((inputSPIStatus & SPIStatus) ? SET : RESET);
+}
+
+/**
+ * @brief Standard SPI Interrupt handler
+ * @param[in] None
+ * @return None
+ */
+void SPI_StdIntHandler(void)
+{
+ // Call relevant handler
+ spidat.inthandler();
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/firmware/lpc17xx/lpc17xx_spi.h b/firmware/lpc17xx/lpc17xx_spi.h
new file mode 100644
index 0000000..a7d0b50
--- /dev/null
+++ b/firmware/lpc17xx/lpc17xx_spi.h
@@ -0,0 +1,314 @@
+/***********************************************************************//**
+ * @file : lpc17xx_spi.h
+ * @brief : Contains all macro definitions and function prototypes
+ * support for SPI firmware library on LPC17xx
+ * @version : 1.0
+ * @date : 3. April. 2009
+ * @author : HieuNguyen
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **************************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @defgroup SPI
+ * @ingroup LPC1700CMSIS_FwLib_Drivers
+ * @{
+ */
+
+#ifndef LPC17XX_SPI_H_
+#define LPC17XX_SPI_H_
+
+/* Includes ------------------------------------------------------------------- */
+#include <LPC17xx.h>
+#include "lpc_types.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Private Macros ------------------------------------------------------------- */
+/** @defgroup SPI_Private_Macros
+ * @{
+ */
+
+/*********************************************************************//**
+ * Macro defines for SPI Control Register
+ **********************************************************************/
+/** @defgroup SPI_REGISTER_BIT_DEFINITION
+ * @{
+ */
+
+/** Bit enable, the SPI controller sends and receives the number
+ * of bits selected by bits 11:8 */
+#define SPI_SPCR_BIT_EN ((uint32_t)(1<<2))
+/** Clock phase control bit */
+#define SPI_SPCR_CPHA_SECOND ((uint32_t)(1<<3))
+/** Clock polarity control bit */
+#define SPI_SPCR_CPOL_LOW ((uint32_t)(1<<4))
+/** SPI master mode enable */
+#define SPI_SPCR_MSTR ((uint32_t)(1<<5))
+/** LSB enable bit */
+#define SPI_SPCR_LSBF ((uint32_t)(1<<6))
+/** SPI interrupt enable bit */
+#define SPI_SPCR_SPIE ((uint32_t)(1<<7))
+/** When bit 2 of this register is 1, this field controls the
+number of bits per transfer */
+#define SPI_SPCR_BITS(n) ((n==0) ? ((uint32_t)0) : ((uint32_t)((n&0x0F)<<8)))
+/** SPI Control bit mask */
+#define SPI_SPCR_BITMASK ((uint32_t)(0xFFC))
+
+
+/*********************************************************************//**
+ * Macro defines for SPI Status Register
+ **********************************************************************/
+/** Slave abort */
+#define SPI_SPSR_ABRT ((uint32_t)(1<<3))
+/** Mode fault */
+#define SPI_SPSR_MODF ((uint32_t)(1<<4))
+/** Read overrun */
+#define SPI_SPSR_ROVR ((uint32_t)(1<<5))
+/** Write collision */
+#define SPI_SPSR_WCOL ((uint32_t)(1<<6))
+/** SPI transfer complete flag */
+#define SPI_SPSR_SPIF ((uint32_t)(1<<7))
+/** SPI Status bit mask */
+#define SPI_SPSR_BITMASK ((uint32_t)(0xF8))
+
+
+/*********************************************************************//**
+ * Macro defines for SPI Data Register
+ **********************************************************************/
+/** SPI Data low bit-mask */
+#define SPI_SPDR_LO_MASK ((uint32_t)(0xFF))
+/** SPI Data high bit-mask */
+#define SPI_SPDR_HI_MASK ((uint32_t)(0xFF00))
+/** SPI Data bit-mask */
+#define SPI_SPDR_BITMASK ((uint32_t)(0xFFFF))
+
+
+/*********************************************************************//**
+ * Macro defines for SPI Clock Counter Register
+ **********************************************************************/
+/** SPI clock counter setting */
+#define SPI_SPCCR_COUNTER(n) ((uint32_t)(n&0xFF))
+/** SPI clock counter bit-mask */
+#define SPI_SPCCR_BITMASK ((uint32_t)(0xFF))
+
+
+/***********************************************************************
+ * Macro defines for SPI Test Control Register
+ **********************************************************************/
+/** SPI Test bit */
+#define SPI_SPTCR_TEST_MASK ((uint32_t)(0xFE))
+/** SPI Test register bit mask */
+#define SPI_SPTCR_BITMASK ((uint32_t)(0xFE))
+
+
+
+/*********************************************************************//**
+ * Macro defines for SPI Test Status Register
+ **********************************************************************/
+/** Slave abort */
+#define SPI_SPTSR_ABRT ((uint32_t)(1<<3))
+/** Mode fault */
+#define SPI_SPTSR_MODF ((uint32_t)(1<<4))
+/** Read overrun */
+#define SPI_SPTSR_ROVR ((uint32_t)(1<<5))
+/** Write collision */
+#define SPI_SPTSR_WCOL ((uint32_t)(1<<6))
+/** SPI transfer complete flag */
+#define SPI_SPTSR_SPIF ((uint32_t)(1<<7))
+/** SPI Status bit mask */
+#define SPI_SPTSR_MASKBIT ((uint32_t)(0xF8))
+
+
+
+/*********************************************************************//**
+ * Macro defines for SPI Interrupt Register
+ **********************************************************************/
+/** SPI interrupt flag */
+#define SPI_SPINT_INTFLAG ((uint32_t)(1<<0))
+/** SPI interrupt register bit mask */
+#define SPI_SPINT_BITMASK ((uint32_t)(0x01))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/* Public Types --------------------------------------------------------------- */
+/** @defgroup SPI_Public_Types
+ * @{
+ */
+
+/** @brief SPI configuration structure */
+typedef struct {
+ uint32_t Databit; /** Databit number, should be SPI_DATABIT_x,
+ where x is in range from 8 - 16 */
+ uint32_t CPHA; /** Clock phase, should be:
+ - SPI_CPHA_FIRST: first clock edge
+ - SPI_CPHA_SECOND: second clock edge */
+ uint32_t CPOL; /** Clock polarity, should be:
+ - SPI_CPOL_HI: high level
+ - SPI_CPOL_LO: low level */
+ uint32_t Mode; /** SPI mode, should be:
+ - SPI_MASTER_MODE: Master mode
+ - SPI_SLAVE_MODE: Slave mode */
+ uint32_t DataOrder; /** Data order, should be:
+ - SPI_DATA_MSB_FIRST: MSB first
+ - SPI_DATA_LSB_FIRST: LSB first */
+ uint32_t ClockRate; /** Clock rate,in Hz, should not exceed
+ (SPI peripheral clock)/8 */
+} SPI_CFG_Type;
+
+
+/**
+ * @brief SPI Transfer Type definitions
+ */
+typedef enum {
+ SPI_TRANSFER_POLLING = 0, /**< Polling transfer */
+ SPI_TRANSFER_INTERRUPT /**< Interrupt transfer */
+} SPI_TRANSFER_Type;
+
+/**
+ * @brief SPI Data configuration structure definitions
+ */
+typedef struct {
+ void *tx_data; /**< Pointer to transmit data */
+ void *rx_data; /**< Pointer to transmit data */
+ uint32_t length; /**< Length of transfer data */
+ uint32_t counter; /**< Data counter index */
+ uint32_t status; /**< Current status of SPI activity */
+ void (*callback)(void); /**< Pointer to Call back function when transmission complete
+ used in interrupt transfer mode */
+} SPI_DATA_SETUP_Type;
+
+/**
+ * @}
+ */
+
+
+/* Public Macros -------------------------------------------------------------- */
+/** @defgroup SPI_Public_Macros
+ * @{
+ */
+
+/** Macro to determine if it is valid SPI port number */
+#define PARAM_SPIx(n) (((uint32_t *)n)==((uint32_t *)LPC_SPI))
+
+/*********************************************************************//**
+ * SPI configuration parameter defines
+ **********************************************************************/
+/** Clock phase control bit */
+#define SPI_CPHA_FIRST ((uint32_t)(0))
+#define SPI_CPHA_SECOND SPI_SPCR_CPHA_SECOND
+#define PARAM_SPI_CPHA(n) ((n==SPI_CPHA_FIRST) || (n==SPI_CPHA_SECOND))
+
+/** Clock polarity control bit */
+#define SPI_CPOL_HI ((uint32_t)(0))
+#define SPI_CPOL_LO SPI_SPCR_CPOL_LOW
+#define PARAM_SPI_CPOL(n) ((n==SPI_CPOL_HI) || (n==SPI_CPOL_LO))
+
+/** SPI master mode enable */
+#define SPI_SLAVE_MODE ((uint32_t)(0))
+#define SPI_MASTER_MODE SPI_SPCR_MSTR
+#define PARAM_SPI_MODE(n) ((n==SPI_SLAVE_MODE) || (n==SPI_MASTER_MODE))
+
+/** LSB enable bit */
+#define SPI_DATA_MSB_FIRST ((uint32_t)(0))
+#define SPI_DATA_LSB_FIRST SPI_SPCR_LSBF
+#define PARAM_SPI_DATA_ORDER(n) ((n==SPI_DATA_MSB_FIRST) || (n==SPI_DATA_LSB_FIRST))
+
+/** SPI data bit number defines */
+#define SPI_DATABIT_16 SPI_SPCR_BITS(0) /*!< Databit number = 16 */
+#define SPI_DATABIT_8 SPI_SPCR_BITS(0x08) /*!< Databit number = 8 */
+#define SPI_DATABIT_9 SPI_SPCR_BITS(0x09) /*!< Databit number = 9 */
+#define SPI_DATABIT_10 SPI_SPCR_BITS(0x0A) /*!< Databit number = 10 */
+#define SPI_DATABIT_11 SPI_SPCR_BITS(0x0B) /*!< Databit number = 11 */
+#define SPI_DATABIT_12 SPI_SPCR_BITS(0x0C) /*!< Databit number = 12 */
+#define SPI_DATABIT_13 SPI_SPCR_BITS(0x0D) /*!< Databit number = 13 */
+#define SPI_DATABIT_14 SPI_SPCR_BITS(0x0E) /*!< Databit number = 14 */
+#define SPI_DATABIT_15 SPI_SPCR_BITS(0x0F) /*!< Databit number = 15 */
+#define PARAM_SPI_DATABIT(n) ((n==SPI_DATABIT_16) || (n==SPI_DATABIT_8) \
+|| (n==SPI_DATABIT_9) || (n==SPI_DATABIT_10) \
+|| (n==SPI_DATABIT_11) || (n==SPI_DATABIT_12) \
+|| (n==SPI_DATABIT_13) || (n==SPI_DATABIT_14) \
+|| (n==SPI_DATABIT_15))
+
+
+/*********************************************************************//**
+ * SPI Status Flag defines
+ **********************************************************************/
+/** Slave abort */
+#define SPI_STAT_ABRT SPI_SPSR_ABRT
+/** Mode fault */
+#define SPI_STAT_MODF SPI_SPSR_MODF
+/** Read overrun */
+#define SPI_STAT_ROVR SPI_SPSR_ROVR
+/** Write collision */
+#define SPI_STAT_WCOL SPI_SPSR_WCOL
+/** SPI transfer complete flag */
+#define SPI_STAT_SPIF SPI_SPSR_SPIF
+#define PARAM_SPI_STAT(n) ((n==SPI_STAT_ABRT) || (n==SPI_STAT_MODF) \
+|| (n==SPI_STAT_ROVR) || (n==SPI_STAT_WCOL) \
+|| (n==SPI_STAT_SPIF))
+
+
+/* SPI Status Implementation definitions */
+#define SPI_STAT_DONE (1UL<<8) /**< Done */
+#define SPI_STAT_ERROR (1UL<<9) /**< Error */
+
+/**
+ * @}
+ */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @defgroup SPI_Public_Functions
+ * @{
+ */
+
+void SPI_SetClock (LPC_SPI_TypeDef *SPIx, uint32_t target_clock);
+void SPI_DeInit(LPC_SPI_TypeDef *SPIx);
+void SPI_Init(LPC_SPI_TypeDef *SPIx, SPI_CFG_Type *SPI_ConfigStruct);
+void SPI_ConfigStructInit(SPI_CFG_Type *SPI_InitStruct);
+void SPI_SendData(LPC_SPI_TypeDef *SPIx, uint16_t Data);
+uint16_t SPI_ReceiveData(LPC_SPI_TypeDef *SPIx);
+int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, SPI_TRANSFER_Type xfType);
+void SPI_IntCmd(LPC_SPI_TypeDef *SPIx, FunctionalState NewState);
+IntStatus SPI_GetIntStatus (LPC_SPI_TypeDef *SPIx);
+void SPI_ClearIntPending(LPC_SPI_TypeDef *SPIx);
+uint32_t SPI_GetStatus(LPC_SPI_TypeDef *SPIx);
+FlagStatus SPI_CheckStatus (uint32_t inputSPIStatus, uint8_t SPIStatus);
+void SPI_StdIntHandler(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LPC17XX_SPI_H_ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/firmware/lpc17xx/lpc_types.h b/firmware/lpc17xx/lpc_types.h
new file mode 100644
index 0000000..89659f3
--- /dev/null
+++ b/firmware/lpc17xx/lpc_types.h
@@ -0,0 +1,197 @@
+/***********************************************************************//**
+ * @file : lpc_types.h
+ * @brief :
+ * Contains the NXP ABL typedefs for C standard types.
+ * It is intended to be used in ISO C conforming development
+ * environments and checks for this insofar as it is possible
+ * to do so.
+ * @version : 1.0
+ * @date : 27 Jul. 2008
+ * @author : wellsk
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **************************************************************************/
+
+/* Type group ----------------------------------------------------------- */
+/** @defgroup LPC_Types
+ * @ingroup LPC1700CMSIS_FwLib_Drivers
+ * @{
+ */
+
+#ifndef LPC_TYPES_H
+#define LPC_TYPES_H
+
+/* Includes ------------------------------------------------------------------- */
+#include <stdint.h>
+
+
+/* Public Types --------------------------------------------------------------- */
+/** @defgroup LPC_Types_Public_Types
+ * @{
+ */
+
+/**
+ * @brief Boolean Type definition
+ */
+typedef enum {FALSE = 0, TRUE = !FALSE} Bool;
+
+/**
+ * @brief Flag Status and Interrupt Flag Status type definition
+ */
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState;
+#define PARAM_SETSTATE(State) ((State==RESET) || (State==SET))
+
+/**
+ * @brief Functional State Definition
+ */
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+#define PARAM_FUNCTIONALSTATE(State) ((State==DISABLE) || (State==ENABLE))
+
+/**
+ * @ Status type definition
+ */
+typedef enum {ERROR = 0, SUCCESS = !ERROR} Status;
+
+
+/**
+ * Read/Write transfer type mode (Block or non-block)
+ */
+typedef enum
+{
+ NONE_BLOCKING = 0, /**< None Blocking type */
+ BLOCKING, /**< Blocking type */
+} TRANSFER_BLOCK_Type;
+
+
+/** Pointer to Function returning Void (any number of parameters) */
+typedef void (*PFV)();
+
+/** Pointer to Function returning int32_t (any number of parameters) */
+typedef int32_t(*PFI)();
+
+/**
+ * @}
+ */
+
+
+/* Public Macros -------------------------------------------------------------- */
+/** @defgroup LPC_Types_Public_Macros
+ * @{
+ */
+
+/* _BIT(n) sets the bit at position "n"
+ * _BIT(n) is intended to be used in "OR" and "AND" expressions:
+ * e.g., "(_BIT(3) | _BIT(7))".
+ */
+#undef _BIT
+/* Set bit macro */
+#define _BIT(n) (1<<n)
+
+/* _SBF(f,v) sets the bit field starting at position "f" to value "v".
+ * _SBF(f,v) is intended to be used in "OR" and "AND" expressions:
+ * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)"
+ */
+#undef _SBF
+/* Set bit field macro */
+#define _SBF(f,v) (v<<f)
+
+/* _BITMASK constructs a symbol with 'field_width' least significant
+ * bits set.
+ * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF
+ * The symbol is intended to be used to limit the bit field width
+ * thusly:
+ * <a_register> = (any_expression) & _BITMASK(x), where 0 < x <= 32.
+ * If "any_expression" results in a value that is larger than can be
+ * contained in 'x' bits, the bits above 'x - 1' are masked off. When
+ * used with the _SBF example above, the example would be written:
+ * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16))
+ * This ensures that the value written to a_reg is no wider than
+ * 16 bits, and makes the code easier to read and understand.
+ */
+#undef _BITMASK
+/* Bitmask creation macro */
+#define _BITMASK(field_width) ( _BIT(field_width) - 1)
+
+/* NULL pointer */
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+/* Number of elements in an array */
+#define NELEMENTS(array) (sizeof (array) / sizeof (array[0]))
+
+/* Static data/function define */
+#define STATIC static
+/* External data/function define */
+#define EXTERN extern
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/**
+ * @}
+ */
+
+
+/* Old Type Definition compatibility ------------------------------------------ */
+/** @addtogroup LPC_Types_Public_Types
+ * @{
+ */
+
+/** SMA type for character type */
+typedef char CHAR;
+
+/** SMA type for 8 bit unsigned value */
+typedef uint8_t UNS_8;
+
+/** SMA type for 8 bit signed value */
+typedef int8_t INT_8;
+
+/** SMA type for 16 bit unsigned value */
+typedef uint16_t UNS_16;
+
+/** SMA type for 16 bit signed value */
+typedef int16_t INT_16;
+
+/** SMA type for 32 bit unsigned value */
+typedef uint32_t UNS_32;
+
+/** SMA type for 32 bit signed value */
+typedef int32_t INT_32;
+
+/** SMA type for 64 bit signed value */
+typedef int64_t INT_64;
+
+/** SMA type for 64 bit unsigned value */
+typedef uint64_t UNS_64;
+
+/** 32 bit boolean type */
+typedef Bool BOOL_32;
+
+/** 16 bit boolean type */
+typedef Bool BOOL_16;
+
+/** 8 bit boolean type */
+typedef Bool BOOL_8;
+
+/**
+ * @}
+ */
+
+
+#endif /* LPC_TYPES_H */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/firmware/src/p2m.c b/firmware/src/p2m.c
index 422cd34..d4ecb21 100644
--- a/firmware/src/p2m.c
+++ b/firmware/src/p2m.c
@@ -94,6 +94,7 @@ int main (void)
#include "LPC17xx.h"
#include <stdint.h>
#include "uart.h"
+#include <wm8523.h>
int main (void)
{
@@ -101,13 +102,7 @@ int main (void)
UARTSend(0, (uint8_t *)"init\n\r", 6);
- // PCONP register (Table 46), set bit PCSPI.
- LPC_SC->PCONP |= 1 << 8;
-
- // In the PCLKSEL0 register (Table 40), set bit PCLK_SPI. In master mode, the
- // clock must be an even number greater than or equal to 8
- LPC_SC->PCLKSEL0PCLK_SPI = 0;//(3 << 17);
- // 1Mhz
+ WM8523_Init();
while (1) {
UARTSend(0, (uint8_t *)"hello\n\r", 7);