From 94d67aae3a0b9921a7106b592593253b73b0cdb9 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 4 Jun 2013 21:55:32 +0200 Subject: In-progress version of WM8523 driver. --- firmware/Makefile | 2 +- firmware/drivers/wm8523.c | 126 +++++++++ firmware/drivers/wm8523.h | 33 +++ firmware/lpc17xx/lpc17xx_clkpwr.c | 344 ++++++++++++++++++++++++ firmware/lpc17xx/lpc17xx_clkpwr.h | 384 ++++++++++++++++++++++++++ firmware/lpc17xx/lpc17xx_spi.c | 550 ++++++++++++++++++++++++++++++++++++++ firmware/lpc17xx/lpc17xx_spi.h | 314 ++++++++++++++++++++++ firmware/lpc17xx/lpc_types.h | 197 ++++++++++++++ firmware/src/p2m.c | 9 +- 9 files changed, 1951 insertions(+), 8 deletions(-) create mode 100644 firmware/drivers/wm8523.c create mode 100644 firmware/drivers/wm8523.h create mode 100644 firmware/lpc17xx/lpc17xx_clkpwr.c create mode 100644 firmware/lpc17xx/lpc17xx_clkpwr.h create mode 100644 firmware/lpc17xx/lpc17xx_spi.c create mode 100644 firmware/lpc17xx/lpc17xx_spi.h create mode 100644 firmware/lpc17xx/lpc_types.h 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 +#include + +#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 +#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 +#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 + + +/* 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< = (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 #include "uart.h" +#include 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); -- cgit v1.2.3