diff options
| -rw-r--r-- | firmware/Makefile | 2 | ||||
| -rw-r--r-- | firmware/drivers/wm8523.c | 126 | ||||
| -rw-r--r-- | firmware/drivers/wm8523.h | 33 | ||||
| -rw-r--r-- | firmware/lpc17xx/lpc17xx_clkpwr.c | 344 | ||||
| -rw-r--r-- | firmware/lpc17xx/lpc17xx_clkpwr.h | 384 | ||||
| -rw-r--r-- | firmware/lpc17xx/lpc17xx_spi.c | 550 | ||||
| -rw-r--r-- | firmware/lpc17xx/lpc17xx_spi.h | 314 | ||||
| -rw-r--r-- | firmware/lpc17xx/lpc_types.h | 197 | ||||
| -rw-r--r-- | firmware/src/p2m.c | 9 | 
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);
  | 
