Makefile with libs and atmel source

This commit is contained in:
Christina Quast
2014-12-02 13:06:01 +01:00
parent a42c11f876
commit 8be71e4e99
63 changed files with 14441 additions and 2654 deletions

View File

@@ -116,12 +116,12 @@ LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-secti
# Directories where source files can be found
VPATH += src cmsis lib
VPATH += src_board src_sam3s cmsis
# Objects built from C source files
C_CMSIS = core_cm3.o
C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o
C_LIBLEVEL = spi.o pio.o pmc.o
C_LIBLEVEL = spi.o pio.o pmc.o usart.o
C_APPLEVEL = main.o
C_OBJECTS = $(C_CMSIS) $(C_LOWLEVEL) $(C_LIBLEVEL) $(C_APPLEVEL)
@@ -162,7 +162,7 @@ endef
$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY))))
program:
openocd -f /home/chrysh/ba_thesis/thesis/openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 /home/chrysh/ba_thesis/thesis/src/sam3s_example/bin/project-flash.bin 0" -c "reset" -c "shutdown"
openocd -f /home/chrysh/ba_thesis/thesis/openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown"
clean:
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst

View File

@@ -0,0 +1,197 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of ADS7843 driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
#define ADS_CTRL_PD0 (1 << 0) /* PD0 */
#define ADS_CTRL_PD1 (1 << 1) /* PD1 */
#define ADS_CTRL_DFR (1 << 2) /* SER/DFR */
#define ADS_CTRL_EIGHT_BITS_MOD (1 << 3) /* Mode */
#define ADS_CTRL_START (1 << 7) /* Start Bit */
#define ADS_CTRL_SWITCH_SHIFT 4 /* Address setting */
/* Get X position command */
#define CMD_Y_POSITION ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1)
/* Get Y position command */
#define CMD_X_POSITION ((5 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1)
/* Enable penIRQ */
#define CMD_ENABLE_PENIRQ ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START)
#define ADS7843_TIMEOUT 5000000
#define DELAY_BEFORE_SPCK 200 /* 2us min (tCSS) <=> 200/100 000 000 = 2us */
#define DELAY_BETWEEN_CONS_COM 0xf /* 5us min (tCSH) <=> (32 * 15) / (100 000 000) = 5us */
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Pins used by SPI */
static const Pin pinsSPI[] = {BOARD_TSC_SPI_PINS, BOARD_TSC_NPCS_PIN};
/** Touch screen BUSY pin */
static const Pin pinBusy[] = {PIN_TSC_BUSY};
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Generic function to send a command to the touchscreen controller.
*
* \param bCmd command to send
*
* \return command result
*/
static uint32_t SendCommand( uint8_t bCmd )
{
uint32_t uResult = 0;
uint32_t uTimeout = 0;
/* (volatile declaration needed for code optimisation by compiler) */
volatile uint8_t bufferRX[3];
volatile uint8_t bufferTX[3];
Pdc *pPdc = (Pdc *)SPI;
uint32_t dStatus;
bufferRX[0] = 0;
bufferRX[1] = 0;
bufferRX[2] = 0;
bufferTX[0] = bCmd;
bufferTX[1] = 0;
bufferTX[2] = 0;
/* Send Command and data through the SPI */
pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTDIS;
pPdc->PERIPH_RPR = (uint32_t) bufferRX;
pPdc->PERIPH_RCR = 3;
pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTDIS;
pPdc->PERIPH_TPR = (uint32_t) bufferTX;
pPdc->PERIPH_TCR = 3;
pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTEN;
pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTEN;
do
{
dStatus = REG_SPI_SR;
uTimeout++;
}
while ((( dStatus & SPI_SR_RXBUFF) != SPI_SR_RXBUFF) && (uTimeout < ADS7843_TIMEOUT));
pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTDIS;
pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTDIS;
uResult = (uint32_t)bufferRX[1] << 8;
uResult |= (uint32_t)bufferRX[2];
uResult = uResult >> 4;
return uResult;
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Get position of the pen by ask the ADS controller (SPI).
*
* \param px_pos pointer to the horizontal position
* \param py_pos pointer to the vertical position
*
*/
extern void ADS7843_GetPosition( uint32_t *px_pos, uint32_t *py_pos )
{
/* Get X position */
*px_pos = SendCommand(CMD_X_POSITION);
/* Get Y position */
*py_pos = SendCommand(CMD_Y_POSITION);
/* Switch to full power mode */
SendCommand(CMD_ENABLE_PENIRQ);
}
/**
* \brief Initialization of the SPI for communication with ADS7843 component.
*/
extern void ADS7843_Initialize( void )
{
volatile uint32_t uDummy;
/* Configure pins */
PIO_Configure(pinsSPI, PIO_LISTSIZE(pinsSPI));
PIO_Configure(pinBusy, PIO_LISTSIZE(pinBusy));
SPI_Configure(BOARD_TSC_SPI_BASE,
BOARD_TSC_SPI_ID,
SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_PCS(BOARD_TSC_NPCS) /* Value of the SPI configuration register. */
);
SPI_ConfigureNPCS(BOARD_TSC_SPI_BASE, BOARD_TSC_NPCS,
SPI_CSR_NCPHA | SPI_CSR_DLYBS(DELAY_BEFORE_SPCK) |
SPI_CSR_DLYBCT(DELAY_BETWEEN_CONS_COM) | SPI_CSR_SCBR(0xC8) );
SPI_Enable(BOARD_TSC_SPI_BASE);
for (uDummy=0; uDummy<100000; uDummy++);
uDummy = REG_SPI_SR;
uDummy = REG_SPI_RDR;
SendCommand(CMD_ENABLE_PENIRQ);
}
/**
* \brief Reset the ADS7843
*/
void ADS7843_Reset( void )
{
/* Disable SPI */
SPI_Disable( BOARD_TSC_SPI_BASE ) ;
}

View File

@@ -0,0 +1,316 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup spi_at45_module SPI AT45 driver
* \ingroup at45d_module
* The Dataflash driver is based on top of the corresponding Spi driver.
* A Dataflash structure instance has to be initialized using the DF_Init
* function. Then basic dataflash operations can be launched using macros such
* as DF_continuous_read. These macros invoke the DF_Command() function which
* invokes the DPI low driver using the SPI_SendCommand() function.
* Beware to compute the dataflash internal address, the dataflash sector
* description must be known (DataflashDesc). Dataflash can be automatically
* detected using the DF_Scan() function.
*
* \section Usage
* <ul>
* <li> Initializes an AT45 instance and configures SPI chip select pin
* using AT45_Configure(). </li>
* <li> Detect DF and returns DF description corresponding to the device
* connected using AT45_FindDevice().This function shall be called by
* the application before AT45_SendCommand.</li>
* <li>Sends a command to the DF through the SPI using AT45_SendCommand().
* The command is identified by its command code and the number of
* bytes to transfer.</li>
* <li>Example code for sending command to write a page to DF. </li>
* \code
* // Issue a page write through buffer 1 command
* error = AT45_SendCommand(pAt45, AT45_PAGE_WRITE_BUF1, 4,
* pBuffer, size, address, 0, 0);
* \endcode
* <li>Example code for sending command to read a page from DF.
* If data needs to be received, then a data buffer must be
* provided.</li>
* \code
* // Issue a continuous read array command
* error = AT45_SendCommand(pAt45, AT45_CONTINUOUS_READ_LEG, 8,
* pBuffer, size, address, 0, 0);
* \endcode
* <li> This function does not block; its optional callback will
* be invoked when the transfer completes.</li>
* <li> Check the AT45 driver is ready or not by polling AT45_IsBusy().
* </ul>
* Related files :\n
* \ref spi_at45.c\n
* \ref spi_at45.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of SPI At45 driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <assert.h>
#include <string.h>
/*----------------------------------------------------------------------------
* Internal definitions
*----------------------------------------------------------------------------*/
/** Number of dataflash which can be recognized.*/
#define NUMDATAFLASH (sizeof(at45Devices) / sizeof(At45Desc))
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** indicate if the device is configured as binary page or not.*/
static uint8_t configuredBinaryPage;
/** At45 device descriptor structure. */
static const At45Desc at45Devices[] = {
{ 512, 1, 264, 9, 0x0C, "AT45DB011D"},
{ 1024, 1, 264, 9, 0x14, "AT45DB021D"},
{ 2048, 1, 264, 9, 0x1C, "AT45DB041D"},
{ 4096, 1, 264, 9, 0x24, "AT45DB081D"},
{ 4096, 1, 528, 10, 0x2C, "AT45DB161D"},
{ 8192, 1, 528, 10, 0x34, "AT45DB321D"},
{ 8192, 1, 1056, 11, 0x3C, "AT45DB642D"},
{16384, 1, 1056, 11, 0x10, "AT45DB1282"},
{16384, 1, 2112, 12, 0x18, "AT45DB2562"},
{32768, 1, 2112, 12, 0x20, "AT45DB5122"}
};
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes an AT45 instance and configures SPI chip select register.
*
* \param pAt45 Pointer to the At45 instance to initialize.
* \param pSpid Pointer to the underlying SPI driver.
* \param spiCs Chip select value to connect to the At45.
* \return 0.
*/
extern uint32_t AT45_Configure( At45* pAt45, Spid* pSpid, uint8_t ucSpiCs )
{
SpidCmd* pCommand ;
/* Sanity checks */
assert( pSpid != NULL ) ;
assert( pAt45 != NULL ) ;
/* Initialize the At45 instance */
pAt45->pSpid = pSpid ;
pAt45->pDesc = 0 ;
memset( pAt45->pCmdBuffer, 0, 8 ) ;
/* Initialize the spidCmd structure */
pCommand = &(pAt45->command) ;
pCommand->pCmd = pAt45->pCmdBuffer ;
pCommand->callback = 0 ;
pCommand->pArgument = 0 ;
pCommand->spiCs = ucSpiCs ;
return 0 ;
}
/**
* \brief Check if the At45 driver is in busy.
*
* \param pAt45 Pointer to the At45 instance to initialize.
* \return 1 if the At45 driver is not executing any command,otherwise it returns 0.
*/
extern uint32_t AT45_IsBusy( At45* pAt45 )
{
return SPID_IsBusy( pAt45->pSpid ) ;
}
/**
* \brief Sends a command to the dataflash through the SPI.
* The command is identified by its command code and the number of bytes to transfer
* (1 + number of address bytes + number of dummy bytes).If data needs to be received,
* then a data buffer must be provided.
* \note This function does not block; its optional callback will be invoked when
* the transfer completes.
* \param pAt45 Pointer to the At45 instance to initialize.
* \param cmd Command code.
* \param cmdSize Size of command code + address bytes + dummy bytes.
* \param pData Data buffer.
* \param dataSize Number of data bytes to send/receive.
* \param address Address at which the command is performed if meaningful.
* \param callback Optional callback to invoke at end of transfer.
* \param pArgument Optional parameter to the callback function.
* \return 0.
*/
extern uint32_t AT45_SendCommand( At45* pAt45, uint8_t ucCmd, uint8_t ucCmdSize, uint8_t *pucData, uint32_t dwDataSize,
uint32_t dwAddress, SpidCallback pCallback, void *pArgument )
{
SpidCmd *pCommand ;
const At45Desc *pDesc;
uint32_t dfAddress = 0 ;
/* Sanity checks */
assert( pAt45 != NULL ) ;
pDesc = pAt45->pDesc ;
assert( pDesc || (ucCmd == AT45_STATUS_READ) ) ;
/* Check if the SPI driver is available*/
if ( AT45_IsBusy( pAt45 ) )
{
return AT45_ERROR_LOCK ;
}
/* Compute command pattern*/
pAt45->pCmdBuffer[0] = ucCmd ;
/* Add address bytes if necessary*/
if ( ucCmdSize > 1 )
{
assert( pDesc != NULL ) ;
if ( !configuredBinaryPage )
{
dfAddress = ((dwAddress / (pDesc->pageSize)) << pDesc->pageOffset)
+ (dwAddress % (pDesc->pageSize));
}
else
{
dfAddress = dwAddress ;
}
/* Write address bytes */
if ( pDesc->pageNumber >= 16384 )
{
pAt45->pCmdBuffer[1] = ((dfAddress & 0x0F000000) >> 24);
pAt45->pCmdBuffer[2] = ((dfAddress & 0x00FF0000) >> 16);
pAt45->pCmdBuffer[3] = ((dfAddress & 0x0000FF00) >> 8);
pAt45->pCmdBuffer[4] = ((dfAddress & 0x000000FF) >> 0);
if ( (ucCmd != AT45_CONTINUOUS_READ) && (ucCmd != AT45_PAGE_READ) )
{
ucCmdSize++ ;
}
}
else
{
pAt45->pCmdBuffer[1] = ((dfAddress & 0x00FF0000) >> 16);
pAt45->pCmdBuffer[2] = ((dfAddress & 0x0000FF00) >> 8);
pAt45->pCmdBuffer[3] = ((dfAddress & 0x000000FF) >> 0);
}
}
/* Update the SPI Transfer descriptors */
pCommand = &(pAt45->command) ;
pCommand->cmdSize = ucCmdSize ;
pCommand->pData = pucData ;
pCommand->dataSize = dwDataSize ;
pCommand->callback = pCallback ;
pCommand->pArgument = pArgument ;
/* Send Command and data through the SPI */
if ( SPID_SendCommand( pAt45->pSpid, pCommand ) )
{
return AT45_ERROR_SPI ;
}
return 0 ;
}
/**
* \brief returns the At45Desc structure corresponding to the device connected.
* It automatically initializes pAt45->pDesc field structure.
*
* \note This function shall be called by the application before AT45_SendCommand.
*
* \param pAt45 Pointer to the At45 instance to initialize.
* \param status Device status register value.
*
* \return 0 if successful; Otherwise, returns AT45_ERROR_LOCK if the At45
* driver is in use or AT45_ERROR_SPI if there was an error with the SPI driver.
*/
extern const At45Desc * AT45_FindDevice( At45 *pAt45, uint8_t status )
{
uint32_t i;
uint8_t id = AT45_STATUS_ID(status);
/* Check if status is all one; in which case, it is assumed that no device is connected*/
if ( status == 0xFF )
{
return 0 ;
}
/* Look in device array */
i = 0 ;
pAt45->pDesc = 0 ;
while ( (i < NUMDATAFLASH) && !(pAt45->pDesc) )
{
if ( at45Devices[i].id == id )
{
pAt45->pDesc = &(at45Devices[i]) ;
}
i++ ;
}
configuredBinaryPage = AT45_STATUS_BINARY(status);
return pAt45->pDesc ;
}
/**
* \brief returns the pagesize corresponding to the device connected.
* \param pAt45 Pointer to the At45 instance to initialize.
* \return page size.
*/
extern uint32_t AT45_PageSize( At45 *pAt45 )
{
uint32_t dwPageSize = pAt45->pDesc->pageSize ;
if ( ((pAt45->pDesc->hasBinaryPage) == 0) || !configuredBinaryPage )
{
return dwPageSize ;
}
return ((dwPageSize >> 8) << 8) ;
}

View File

@@ -0,0 +1,254 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \addtogroup external_component External Component
*
* \addtogroup at45d_module AT45 driver
* \ingroup external_component
* The AT45 Dataflash driver is based on the corresponding AT45 driver.
* A AT45 instance has to be initialized using the Dataflash levle function
* AT45_Configure(). AT45 Dataflash can be automatically detected using
* the AT45_FindDevice() function. Then AT45 dataflash operations such as
* read, write and erase DF can be launched using AT45_SendCommand function
* with corresponding AT45 command set.
*
* \section Usage
* <ul>
* <li> Reads data from the At45 at the specified address using AT45D_Read().</li>
* <li> Writes data on the At45 at the specified address using AT45D_Write().</li>
* <li> Erases a page of data at the given address using AT45D_Erase().</li>
* <li> Poll until the At45 has completed of corresponding operations using
* AT45D_WaitReady().</li>
* <li> Retrieves and returns the At45 current using AT45D_GetStatus().</li>
* </ul>
* Related files :\n
* \ref at45d.c\n
* \ref at45d.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of At45 driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <assert.h>
#include <string.h>
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Wait for transfer to finish calling the SPI driver ISR (interrupts are
* disabled).
*
* \param pAt45 Pointer to an AT45 driver instance.
*/
static void AT45D_Wait( At45* pAt45 )
{
assert( pAt45 != NULL ) ;
/* Wait for transfer to finish */
while ( AT45_IsBusy( pAt45 ) )
{
SPID_Handler( pAt45->pSpid ) ;
}
}
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
/**
* \brief Waits for the At45 to be ready to accept new commands.
*
* \param pAt45 Pointer to an AT45 driver instance.
*/
extern void AT45D_WaitReady( At45* pAt45 )
{
uint8_t ready = 0;
assert( pAt45 != NULL ) ;
/* Poll device until it is ready. */
while (!ready)
{
ready = AT45_STATUS_READY(AT45D_GetStatus(pAt45));
}
}
/**
* \brief Retrieves and returns the At45 current status, or 0 if an error happened.
*
* \param pAt45 Pointer to an AT45 driver instance.
*/
extern uint32_t AT45D_GetStatus( At45* pAt45 )
{
uint32_t dwError ;
uint8_t ucStatus ;
assert( pAt45 != NULL ) ;
/* Issue a status register read command */
dwError = AT45_SendCommand( pAt45, AT45_STATUS_READ, 1, &ucStatus, 1, 0, 0, 0 ) ;
assert( !dwError ) ;
/* Wait for command to terminate */
while ( AT45_IsBusy( pAt45 ) )
{
AT45D_Wait( pAt45 ) ;
}
return ucStatus ;
}
/**
* \brief Reads data from the At45 inside the provided buffer. Since a continuous
* read command is used, there is no restriction on the buffer size and read address.
*
* \param pAt45 Pointer to an AT45 driver instance.
* \param pBuffer Data buffer.
* \param size Number of bytes to read.
* \param address Address at which data shall be read.
*/
extern void AT45D_Read( At45* pAt45, uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
{
uint32_t dwError ;
assert( pAt45 != NULL ) ;
assert( pucBuffer != NULL ) ;
/* Issue a continuous read array command. */
dwError = AT45_SendCommand( pAt45, AT45_CONTINUOUS_READ_LEG, 8, pucBuffer, dwSize, dwAddress, 0, 0 ) ;
assert( !dwError ) ;
/* Wait for the read command to execute. */
while ( AT45_IsBusy( pAt45 ) )
{
AT45D_Wait( pAt45 ) ;
}
}
/**
* \brief Writes data on the At45 at the specified address. Only one page of
* data is written that way; if the address is not at the beginning of the
* page, the data is written starting from this address and wraps around to
* the beginning of the page.
*
* \param pAt45 Pointer to an AT45 driver instance.
* \param pucBuffer Data buffer.
* \param dwSize Number of bytes to write.
* \param dwAddress Destination address on the At45.
*/
extern void AT45D_Write( At45* pAt45, uint8_t *pucBuffer, uint32_t dwSize, uint32_t dwAddress )
{
uint8_t dwError ;
assert( pAt45 != NULL ) ;
assert( pucBuffer != NULL ) ;
assert( dwSize <= pAt45->pDesc->pageSize ) ;
/* Issue a page write through buffer 1 command. */
dwError = AT45_SendCommand( pAt45, AT45_PAGE_WRITE_BUF1, 4, pucBuffer, dwSize, dwAddress, 0, 0 ) ;
assert( !dwError ) ;
/* Wait until the command is sent. */
while ( AT45_IsBusy( pAt45 ) )
{
AT45D_Wait( pAt45 ) ;
}
/* Wait until the At45 becomes ready again.*/
AT45D_WaitReady( pAt45 ) ;
}
/**
* \brief Erases a page of data at the given address in the At45.
*
* \param pAt45 Pointer to an AT45 driver instance.
* \param dwAddress Address of page to erase.
*/
extern void AT45D_Erase( At45* pAt45, uint32_t dwAddress )
{
uint32_t dwError ;
assert( pAt45 != NULL ) ;
/* Issue a page erase command. */
dwError = AT45_SendCommand( pAt45, AT45_PAGE_ERASE, 4, 0, 0, dwAddress, 0, 0 ) ;
assert( !dwError ) ;
/* Wait for end of transfer. */
while ( AT45_IsBusy(pAt45 ) )
{
AT45D_Wait( pAt45 ) ;
}
/* Poll until the At45 has completed the erase operation. */
AT45D_WaitReady( pAt45 ) ;
}
/**
* \brief Configure power-of-2 binary page size in the At45.
*
* \param pAt45 Pointer to an AT45 driver instance.
*/
extern void AT45D_BinaryPage( At45* pAt45 )
{
uint8_t dwError ;
uint8_t opcode[3]= {AT45_BINARY_PAGE};
assert( pAt45 != NULL ) ;
/* Issue a binary page command. */
dwError = AT45_SendCommand( pAt45, AT45_BINARY_PAGE_FIRST_OPCODE, 1, opcode, 3, 0, 0, 0 ) ;
assert( !dwError ) ;
/* Wait for end of transfer.*/
while ( AT45_IsBusy( pAt45 ) )
{
AT45D_Wait( pAt45 ) ;
}
/* Wait until the At45 becomes ready again.*/
AT45D_WaitReady( pAt45 ) ;
}

View File

@@ -0,0 +1,319 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "board.h"
#include <string.h>
//-----------------------------------------------------------------------------
// Define
//-----------------------------------------------------------------------------
/// BMP offset for header
#define IMAGE_OFFSET 0x100
//------------------------------------------------------------------------------
// Internal constants
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Internal types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Describe the BMP palette
//------------------------------------------------------------------------------
typedef struct _BMPPaletteEntry
{
/// Blue value
uint8_t b;
/// Green value
uint8_t g;
/// Red value
uint8_t r;
/// Filler character value
uint8_t filler;
} BMPPaletteEntry ;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Test if BMP is valid
/// \param file Buffer holding the file to examinate.
/// \return 1 if the header of a BMP file is valid; otherwise returns 0.
//------------------------------------------------------------------------------
uint8_t BMP_IsValid( void *file )
{
return ((BMPHeader*) file)->type == BMP_TYPE ;
}
//------------------------------------------------------------------------------
/// Returns the size of a BMP image given at least its header (the file does
/// not have to be complete).
/// \param file Pointer to the buffer which holds the BMP file.
/// \return size of BMP image
//------------------------------------------------------------------------------
uint32_t BMP_GetFileSize( void *file )
{
return ((BMPHeader *) file)->fileSize ;
}
//-----------------------------------------------------------------------------
/// Write a BMP header
/// \param pAddressHeader Begin address of the BMP
/// \param bmpHSize BMP heigth size
/// \param bmpVSize BMP width size
/// \param nbByte_Pixels Number of byte per pixels
//-----------------------------------------------------------------------------
void WriteBMPheader( uint32_t* pAddressHeader, uint32_t bmpHSize, uint32_t bmpVSize, uint8_t nbByte_Pixels )
{
uint32_t i;
uint32_t* fill;
BMPHeader *Header;
fill = pAddressHeader;
for ( i=0 ; i < IMAGE_OFFSET ; i+=4 )
{
*fill++ = 0;
}
Header = (BMPHeader*) pAddressHeader;
Header->type = BMP_TYPE;
Header->fileSize = (bmpHSize * bmpVSize * nbByte_Pixels) + IMAGE_OFFSET;
Header->reserved1 = 0;
Header->reserved2 = 0;
Header->offset = IMAGE_OFFSET;
Header->headerSize = BITMAPINFOHEADER;
Header->width = bmpHSize;
Header->height = bmpVSize;
Header->planes = 1;
Header->bits = nbByte_Pixels * 8;
Header->compression = 0;
Header->imageSize = bmpHSize * bmpVSize * nbByte_Pixels;
Header->xresolution = 0;
Header->yresolution = 0;
Header->ncolours = 0;
Header->importantcolours = 0;
}
//------------------------------------------------------------------------------
/// debug function, dislay BMP header
/// \param pAddressHeader Address of the BMP
//------------------------------------------------------------------------------
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
void BMP_displayHeader( uint32_t* pAddressHeader )
{
BMPHeader *header;
header = (BMPHeader*) pAddressHeader;
TRACE_INFO("BMP\n\r");
TRACE_INFO("type 0x%X \n\r", header->type);
TRACE_INFO("fileSize %d \n\r", header->fileSize);
TRACE_INFO("reserved1 %d \n\r", header->reserved1);
TRACE_INFO("reserved2 %d \n\r", header->reserved2);
TRACE_INFO("offset %d \n\r", header->offset);
TRACE_INFO("headerSize %d \n\r", header->headerSize);
TRACE_INFO("width %d \n\r", header->width);
TRACE_INFO("height %d \n\r", header->height);
TRACE_INFO("planes %d \n\r", header->planes);
TRACE_INFO("bits %d \n\r", header->bits);
TRACE_INFO("compression %d \n\r", header->compression);
TRACE_INFO("imageSize %d \n\r", header->imageSize);
TRACE_INFO("xresolution %d \n\r", header->xresolution);
TRACE_INFO("yresolution %d \n\r", header->yresolution);
TRACE_INFO("ncolours %d \n\r", header->ncolours);
TRACE_INFO("importantcolours %d\n\r", header->importantcolours);
}
#endif
//------------------------------------------------------------------------------
/// Loads a BMP image located at the given address, decodes it and stores the
/// resulting image inside the provided buffer. Image must have the specified
/// width & height.
/// If no buffer is provided, this function simply checks if it is able to
/// decode the image.
/// \param file Buffer which holds the BMP file.
/// \param buffer Buffer in which to store the decoded image.
/// \param width Buffer width in pixels.
/// \param height Buffer height in pixels.
/// \param bpp Number of bits per pixels that the buffer stores.
/// \return 0 if the image has been loaded; otherwise returns an error code.
//------------------------------------------------------------------------------
uint8_t BMP_Decode( void *file, uint8_t *buffer, uint32_t width, uint32_t height, uint8_t bpp )
{
BMPHeader *header;
uint32_t i, j;
uint8_t r, g, b;
uint8_t *image;
// Read header information
header = (BMPHeader*) file;
// Verify that the file is valid
if ( !BMP_IsValid( file ) )
{
TRACE_ERROR("BMP_Decode: File type is not 'BM' (0x%04X).\n\r",header->type);
return 1;
}
// Check that parameters match
if ( (header->compression != 0) || (header->width != width) || (header->height != height))
{
TRACE_ERROR("BMP_Decode: File format not supported\n\r");
TRACE_ERROR(" -> .compression = %u\n\r", (unsigned int)header->compression);
TRACE_ERROR(" -> .width = %u\n\r", (unsigned int)header->width);
TRACE_ERROR(" -> .height = %u\n\r", (unsigned int)header->height);
TRACE_ERROR(" -> .bits = %d\n\r", (int)header->bits);
return 2;
}
// Get image data
image = (uint8_t *) ((uint32_t) file + header->offset);
// Check that the bpp resolution is supported
// Only a 24-bit output & 24- or 8-bit input are supported
if ( bpp != 24 )
{
TRACE_ERROR("BMP_Decode: Output resolution not supported\n\r");
return 3;
}
else
{
if (header->bits == 24)
{
// Decoding is ok
if (!buffer) return 0;
// Get image data (swapping red & blue)
for ( i=0 ; i < height ; i++ )
{
for ( j=0 ; j < width; j++ )
{
r = image[((height - i - 1) * width + j) * 3 + 2];
g = image[((height - i - 1) * width + j) * 3 + 1];
b = image[((height - i - 1) * width + j) * 3];
#if defined(BOARD_LCD_RGB565)
// Interlacing
r = ((r << 1) & 0xF0) | ((g & 0x80) >> 4) | ((r & 0x80) >> 5);
g = (g << 1) & 0xF8;
b = b & 0xF8;
buffer[(i * width + j) * 3] = b;
buffer[(i * width + j) * 3 + 1] = g;
buffer[(i * width + j) * 3 + 2] = r;
#else
buffer[(i * width + j) * 3] = r;
buffer[(i * width + j) * 3 + 1] = g;
buffer[(i * width + j) * 3 + 2] = b;
#endif //#if defined(BOARD_LCD_RGB565)
}
}
}
else
{
if ( header->bits == 8 )
{
BMPPaletteEntry palette[256];
// Decoding is ok
if (!buffer) return 0;
// Retrieve palette
memcpy( palette, (uint8_t *) ((uint32_t) file + sizeof( BMPHeader )), header->offset - sizeof( BMPHeader ) ) ;
// Decode image (reversing row order)
for ( i=0 ; i < height ; i++ )
{
for (j=0; j < width; j++)
{
r = palette[image[(height - i - 1) * width + j]].r;
g = palette[image[(height - i - 1) * width + j]].g;
b = palette[image[(height - i - 1) * width + j]].b;
buffer[(i * width + j) * 3] = r;
buffer[(i * width + j) * 3 + 1] = g;
buffer[(i * width + j) * 3 + 2] = b;
}
}
}
else
{
TRACE_ERROR("BMP_Decode: Input resolution not supported\n\r");
TRACE_INFO("header->bits 0x%X \n\r", header->bits);
return 4 ;
}
}
}
return 0 ;
}
//------------------------------------------------------------------------------
/// Convert RGB 565 to RGB 555 (RGB 555 is adapted to LCD)
/// \param fileSource Buffer which holds the RGB file
/// \param fileDestination Buffer in which to store the decoded image
/// \param width Buffer width in pixels.
/// \param height Buffer height in pixels.
/// \param bpp Number of bits per pixels that the buffer stores.
//------------------------------------------------------------------------------
void RGB565toBGR555( uint8_t *fileSource, uint8_t *fileDestination, uint32_t width, uint32_t height, uint8_t bpp )
{
uint32_t i;
uint32_t j;
uint32_t row;
for (i=0; i < height*(bpp/8); i++)
{
row = (i*width*(bpp/8));
for (j=0; j <= width*(bpp/8); j+=2)
{
fileDestination[row+j] = ((fileSource[row+j+1]>>3)&0x1F)
| (fileSource[row+j]&0xE0);
fileDestination[row+j+1] = (fileSource[row+j+1]&0x03)
| ((fileSource[row+j]&0x1F)<<2);
}
}
}

View File

@@ -56,9 +56,12 @@ extern uint32_t _ezero;
/*----------------------------------------------------------------------------
* ProtoTypes
*----------------------------------------------------------------------------*/
/** \cond DOXYGEN_SHOULD_SKIP_THIS */
extern int main( void ) ;
extern void __libc_init_array( void ) ;
/** \endcond */
void ResetException( void ) ;
extern void __libc_init_array( void ) ;
/*------------------------------------------------------------------------------
* Exception Table

View File

@@ -38,13 +38,12 @@
*----------------------------------------------------------------------------*/
#include "board.h"
#include "board_lowlevel.h"
/*----------------------------------------------------------------------------
* Local definitions
*----------------------------------------------------------------------------*/
/* Clock settings at 48MHz */
/* Clock settings at 48MHz for 12 MHz crystal */
#if (BOARD_MCK == 48000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
@@ -53,7 +52,7 @@
| CKGR_PLLAR_DIVA(0x1))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)
/* Clock settings at 64MHz */
/* Clock settings at 64MHz for 12 MHz crystal */
#elif (BOARD_MCK == 64000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
@@ -78,7 +77,7 @@
* This includes EFC and master clock configuration.
* It also enable a low level on the pin NRST triggers a user reset.
*/
WEAK void LowLevelInit( void )
extern WEAK void LowLevelInit( void )
{
uint32_t timeout = 0;
@@ -86,22 +85,21 @@ WEAK void LowLevelInit( void )
EFC->EEFC_FMR = EEFC_FMR_FWS(3);
/* Select external slow clock */
#if 0
if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
{
SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
timeout = 0;
while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
}
#endif
*/
/* Initialize main oscillator */
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
/* if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
}
}*/
/* Switch to 3-20MHz Xtal oscillator */
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;

View File

@@ -0,0 +1,153 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of memories configuration on board.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures the EBI for NandFlash access.
*/
extern void BOARD_ConfigureNandFlash( Smc* pSmc )
{
/* Enable peripheral clock */
PMC_EnablePeripheral( ID_SMC ) ;
/* NCS0 is assigned to a NAND Flash (NANDOE and NANWE used for NCS0) */
MATRIX->CCFG_SMCNFCS = CCFG_SMCNFCS_SMC_NFCS0;
pSmc->SMC_CS_NUMBER[0].SMC_SETUP = SMC_SETUP_NWE_SETUP(0)
| SMC_SETUP_NCS_WR_SETUP(1)
| SMC_SETUP_NRD_SETUP(0)
| SMC_SETUP_NCS_RD_SETUP(1);
pSmc->SMC_CS_NUMBER[0].SMC_PULSE = SMC_PULSE_NWE_PULSE(2)
| SMC_PULSE_NCS_WR_PULSE(3)
| SMC_PULSE_NRD_PULSE(4)
| SMC_PULSE_NCS_RD_PULSE(4);
pSmc->SMC_CS_NUMBER[0].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(4)
| SMC_CYCLE_NRD_CYCLE(7);
pSmc->SMC_CS_NUMBER[0].SMC_MODE = SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE
| SMC_MODE_DBW_8_BIT;
}
/**
* \brief Configures the EBI for %NorFlash access.
*/
extern void BOARD_ConfigureNorFlash( Smc* pSmc )
{
/* Enable peripheral clock */
PMC_EnablePeripheral( ID_SMC ) ;
/* Configure SMC, NCS3 is assigned to a norflash */
pSmc->SMC_CS_NUMBER[3].SMC_SETUP = SMC_SETUP_NWE_SETUP(2)
| SMC_SETUP_NCS_WR_SETUP(0)
| SMC_SETUP_NRD_SETUP(0)
| SMC_SETUP_NCS_RD_SETUP(0);
pSmc->SMC_CS_NUMBER[3].SMC_PULSE = SMC_PULSE_NWE_PULSE(6)
| SMC_PULSE_NCS_WR_PULSE(0xA)
| SMC_PULSE_NRD_PULSE(0xA)
| SMC_PULSE_NCS_RD_PULSE(0xA);
pSmc->SMC_CS_NUMBER[3].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(0xA)
| SMC_CYCLE_NRD_CYCLE(0xA);
pSmc->SMC_CS_NUMBER[3].SMC_MODE = SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE
| SMC_MODE_DBW_8_BIT
| SMC_MODE_EXNW_MODE_DISABLED
| SMC_MODE_TDF_CYCLES(0x1);
}
/**
* \brief An accurate one-to-one comparison is necessary between PSRAM and SMC waveforms for
* a complete SMC configuration.
* \note The system is running at 48 MHz for the EBI Bus.
* Please refer to the "AC Characteristics" section of the customer product datasheet.
*/
extern void BOARD_ConfigurePSRAM( Smc* pSmc )
{
uint32_t dwTmp ;
/* Enable peripheral clock */
PMC_EnablePeripheral( ID_SMC ) ;
/* Configure SMC, NCS1 is assigned to a external PSRAM */
/**
* PSRAM IS66WV51216BLL
* 55 ns Access time
* tdoe = 25 ns max
* SMC1 (timing SAM3S read mode SMC) = 21 ns of setup
* 21 + 55 = 76 ns => at least 5 cycles at 64 MHz
* Write pulse width minimum = 45 ns (PSRAM)
*/
pSmc->SMC_CS_NUMBER[1].SMC_SETUP = SMC_SETUP_NWE_SETUP( 1 )
| SMC_SETUP_NCS_WR_SETUP( 0 )
| SMC_SETUP_NRD_SETUP( 2 )
| SMC_SETUP_NCS_RD_SETUP( 0 ) ;
pSmc->SMC_CS_NUMBER[1].SMC_PULSE = SMC_PULSE_NWE_PULSE( 3 )
| SMC_PULSE_NCS_WR_PULSE( 4 )
| SMC_PULSE_NRD_PULSE( 3 )
| SMC_PULSE_NCS_RD_PULSE( 5 ) ;
/* NWE_CYCLE: The total duration of the write cycle.
NWE_CYCLE = NWE_SETUP + NWE_PULSE + NWE_HOLD
= NCS_WR_SETUP + NCS_WR_PULSE + NCS_WR_HOLD
(tWC) Write Cycle Time min. 70ns
NRD_CYCLE: The total duration of the read cycle.
NRD_CYCLE = NRD_SETUP + NRD_PULSE + NRD_HOLD
= NCS_RD_SETUP + NCS_RD_PULSE + NCS_RD_HOLD
(tRC) Read Cycle Time min. 70ns. */
pSmc->SMC_CS_NUMBER[1].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE( 4 )
| SMC_CYCLE_NRD_CYCLE( 5 ) ;
dwTmp = SMC->SMC_CS_NUMBER[0].SMC_MODE & (uint32_t)(~(SMC_MODE_DBW_Msk)) ;
pSmc->SMC_CS_NUMBER[1].SMC_MODE = dwTmp
| SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE
| SMC_MODE_DBW_8_BIT ;
}

View File

@@ -0,0 +1,184 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Types
*----------------------------------------------------------------------------*/
/*
* \brief Describes a possible clock configuration (processor clock & master clock),
* including the necessary register values.
*/
typedef struct _ClockConfiguration
{
/** Processor clock frequency (in MHz). */
uint16_t pck;
/** Master clock frequency (in MHz). */
uint16_t mck;
/** CKGR_PLL reqister value. */
uint32_t pllr;
/** PMC_MCKR register value. */
uint32_t mckr;
} ClockConfiguration ;
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/* Clock configurations for the AT91SAM3S4-EK */
#define CKGR_MUL_SHIFT 16
#define CKGR_PLLCOUNT_SHIFT 8
#define CKGR_DIV_SHIFT 0
/* Clock configuration for the AT91SAM3S */
static const ClockConfiguration clockConfigurations[] = {
/* PCK = 24 MHz, MCK = 24 MHz
* PCK = 12000000 * (7+1) / 2 / 2 = 24 MHz
*/
{24, 24, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
| (2 << CKGR_DIV_SHIFT)),
( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
/* PCK = 48 MHz, MCK = 48 MHz
* PCK = 12000000 * (7+1) / 1 / 2 = 48 MHz
*/
{48, 48, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
| (1 << CKGR_DIV_SHIFT)),
( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
/* PCK = 64 MHz, MCK = 64 MHz
* PCK = 12000000 * (15+1) / 3 / 1 = 64 MHz
*/
{64, 64, (CKGR_PLLAR_STUCKTO1 | (15 << CKGR_MUL_SHIFT) \
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
| (3 << CKGR_DIV_SHIFT)),
( PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)}
};
/* Number of available clock configurations */
#define NB_CLOCK_CONFIGURATION (sizeof(clockConfigurations)/sizeof(clockConfigurations[0]))
/* Current clock configuration */
uint32_t currentConfig = 0; /* 0 have to be the default configuration */
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Sets the specified clock configuration.
*
* \param configuration Index of the configuration to set.
*/
void CLOCK_SetConfig(uint8_t configuration)
{
TRACE_DEBUG("Setting clock configuration #%d ... ", configuration);
currentConfig = configuration;
/* Switch to main oscillator in two operations */
PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
/* Configure PLL */
PMC->CKGR_PLLAR = clockConfigurations[configuration].pllr;
while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);
/* Configure master clock in two operations */
PMC->PMC_MCKR = (clockConfigurations[configuration].mckr & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
PMC->PMC_MCKR = clockConfigurations[configuration].mckr;
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
/* DBGU reconfiguration */
UART_Configure(115200, clockConfigurations[configuration].mck*1000000);
TRACE_DEBUG("done.\n\r");
}
/**
* \brief Display the user menu on the DBGU.
*/
void CLOCK_DisplayMenu(void)
{
uint32_t i;
printf("\n\rMenu Clock configuration:\n\r");
for (i = 0; i < NB_CLOCK_CONFIGURATION; i++) {
printf(" %u: Set PCK = %3u MHz, MCK = %3u MHz %s\n\r",
(unsigned int)i,
(unsigned int)clockConfigurations[i].pck,
(unsigned int)clockConfigurations[i].mck,
(currentConfig==i)?"(curr)":"");
}
}
/**
* \brief Get the current MCK
*/
uint16_t CLOCK_GetCurrMCK(void)
{
return clockConfigurations[currentConfig].mck;
}
/**
* \brief Get the current PCK
*/
uint16_t CLOCK_GetCurrPCK(void)
{
return clockConfigurations[currentConfig].pck;
}
/**
* \brief Change clock configuration.
*/
void CLOCK_UserChangeConfig(void)
{
uint8_t key = 0;
while (1)
{
CLOCK_DisplayMenu();
key = UART_GetChar();
if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1)))
{
CLOCK_SetConfig(key - '0');
break;
}
}
}

View File

@@ -0,0 +1,435 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdint.h>
#include <string.h>
/** Frame buffer color cache size used to optimize memcpy */
#define FB_COLOR_CACHE_SIZE 8
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Pointer to frame buffer. It is 16 bit aligned to allow PDC operations
* LcdColor_t shall be defined in the physical lcd API (ili9225.c)
*/
static LcdColor_t *gpBuffer;
/** Frame buffer width */
static uint8_t gucWidth;
/** Frame buffer height */
static uint8_t gucHeight;
/* Pixel color cache */
static LcdColor_t gFbPixelCache[FB_COLOR_CACHE_SIZE];
/*----------------------------------------------------------------------------
* Static functions
*----------------------------------------------------------------------------*/
/**
* \brief Check Box coordinates. Return upper left and bottom right coordinates.
*
* \param pX1 X-coordinate of upper-left corner on LCD.
* \param pY1 Y-coordinate of upper-left corner on LCD.
* \param pX2 X-coordinate of lower-right corner on LCD.
* \param pY2 Y-coordinate of lower-right corner on LCD.
*/
static void CheckBoxCoordinates( uint32_t *pX1, uint32_t *pY1, uint32_t *pX2, uint32_t *pY2 )
{
uint32_t dw;
if ( *pX1 >= gucWidth )
*pX1=gucWidth-1 ;
if ( *pX2 >= gucWidth )
*pX2=gucWidth-1 ;
if ( *pY1 >= gucHeight )
*pY1=gucHeight-1 ;
if ( *pY2 >= gucHeight )
*pY2=gucHeight-1 ;
if (*pX1 > *pX2) {
dw = *pX1;
*pX1 = *pX2;
*pX2 = dw;
}
if (*pY1 > *pY2) {
dw = *pY1;
*pY1 = *pY2;
*pY2 = dw;
}
}
/*
* \brief Draw a line on LCD, which is not horizontal or vertical.
*
* \param x X-coordinate of line start.
* \param y Y-coordinate of line start.
* \param length line length.
* \param direction line direction: 0 - horizontal, 1 - vertical.
* \param color Pixel color.
*/
static uint32_t DrawLineBresenham( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
int dx, dy ;
int i ;
int xinc, yinc, cumul ;
int x, y ;
x = dwX1 ;
y = dwY1 ;
dx = dwX2 - dwX1 ;
dy = dwY2 - dwY1 ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = ( dx > 0 ) ? dx : -dx ;
dy = ( dy > 0 ) ? dy : -dy ;
FB_DrawPixel(x, y);
if ( dx > dy )
{
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ )
{
x += xinc ;
cumul += dy ;
if ( cumul >= dx )
{
cumul -= dx ;
y += yinc ;
}
FB_DrawPixel(x, y);
}
}
else
{
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ )
{
y += yinc ;
cumul += dx ;
if ( cumul >= dy )
{
cumul -= dy ;
x += xinc ;
}
FB_DrawPixel(x, y);
}
}
return 0 ;
}
/*----------------------------------------------------------------------------
* External functions
*----------------------------------------------------------------------------*/
/**
* \brief Configure the current frame buffer.
* Next frame buffer operations will take place in this frame buffer area.
* \param pBuffer 16 bit aligned sram buffer. PDC shall be able to access this
* memory area.
* \param ucWidth frame buffer width
* \param ucHeight frame buffer height
*/
extern void FB_SetFrameBuffer(LcdColor_t *pBuffer, uint8_t ucWidth, uint8_t ucHeight)
{
/* Sanity check */
assert(pBuffer != NULL);
gpBuffer = pBuffer;
gucWidth = ucWidth;
gucHeight = ucHeight;
}
/**
* \brief Configure the current color that will be used in the next graphical operations.
*
* \param dwRgb24Bits 24 bit rgb color
*/
extern void FB_SetColor(uint32_t dwRgb24Bits)
{
uint16_t i;
// LcdColor_t wColor;
// wColor = (dwRgb24Bits & 0xF80000) >> 8 |
// (dwRgb24Bits & 0x00FC00) >> 5 |
// (dwRgb24Bits & 0x0000F8) >> 3;
/* Fill the cache with selected color */
for (i = 0; i < FB_COLOR_CACHE_SIZE; ++i) {
gFbPixelCache[i] = dwRgb24Bits ;
}
}
/**
* \brief Draw a pixel on FB of given color.
*
* \param x X-coordinate of pixel.
* \param y Y-coordinate of pixel.
*
* \return 0 is operation is successful, 1 if pixel is out of the fb
*/
extern uint32_t FB_DrawPixel(
uint32_t dwX,
uint32_t dwY)
{
if ((dwX >= gucWidth) || (dwY >= gucHeight)) {
return 1;
}
gpBuffer[dwX + dwY * gucWidth] = gFbPixelCache[0];
return 0;
}
/**
* \brief Write several pixels with the same color to FB.
*
* Pixel color is set by the LCD_SetColor() function.
* This function is optimized using an sram buffer to transfer block instead of
* individual pixels in order to limit the number of SPI interrupts.
* \param dwX1 X-coordinate of upper-left corner on LCD.
* \param dwY1 Y-coordinate of upper-left corner on LCD.
* \param dwX2 X-coordinate of lower-right corner on LCD.
* \param dwY2 Y-coordinate of lower-right corner on LCD.
*
* \return 0 if operation is successfull
*/
extern uint32_t FB_DrawFilledRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
LcdColor_t *pFbBuffer, *pDestFbBuffer;
uint32_t dwY, blocks, bytes;
/* Swap coordinates if necessary */
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
blocks = ((dwX2 - dwX1 + 1) / FB_COLOR_CACHE_SIZE);
bytes = ((dwX2 - dwX1 + 1) % FB_COLOR_CACHE_SIZE);
/* Each row is sent by block to benefit from memcpy optimizations */
pFbBuffer = &(gpBuffer[dwY1 * gucWidth + dwX1]);
for (dwY = dwY1; dwY <= dwY2; ++dwY) {
pDestFbBuffer = pFbBuffer;
while (blocks--) {
memcpy(pDestFbBuffer, gFbPixelCache, FB_COLOR_CACHE_SIZE * sizeof(LcdColor_t));
pDestFbBuffer += FB_COLOR_CACHE_SIZE;
}
memcpy(pDestFbBuffer, gFbPixelCache, bytes * sizeof(LcdColor_t));
pFbBuffer += gucWidth;
}
return 0;
}
/**
* \brief Write several pixels pre-formatted in a bufer to FB.
*
* \param dwX1 X-coordinate of upper-left corner on LCD.
* \param dwY1 Y-coordinate of upper-left corner on LCD.
* \param dwX2 X-coordinate of lower-right corner on LCD.
* \param dwY2 Y-coordinate of lower-right corner on LCD.
* \param pBuffer pixel buffer area (no constraint on alignment).
*/
extern uint32_t FB_DrawPicture( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2, const void *pBuffer )
{
LcdColor_t *pFbBuffer;
uint32_t dwY;
/* Swap coordinates if necessary */
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
pFbBuffer = &(gpBuffer[dwY1 * gucWidth + dwX1]);
for (dwY = dwY1; dwY <= dwY2; ++dwY) {
memcpy(pFbBuffer, pBuffer, (dwX2 - dwX1 + 1) * sizeof(LcdColor_t));
pFbBuffer += gucWidth;
}
return 0 ;
}
/*
* \brief Draw a line on LCD, horizontal and vertical line are supported.
*
* \param dwX1 X-coordinate of line start.
* \param dwY1 Y-coordinate of line start.
* \param dwX2 X-coordinate of line end.
* \param dwY2 Y-coordinate of line end.
*
* \return 0 if operation is successful
*/
extern uint32_t FB_DrawLine ( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
/* Optimize horizontal or vertical line drawing */
if (( dwY1 == dwY2 ) || (dwX1 == dwX2)) {
FB_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY2 );
}
else {
DrawLineBresenham( dwX1, dwY1, dwX2, dwY2 ) ;
}
return 0 ;
}
/**
* \brief Draws a circle in FB, at the given coordinates.
*
* \param dwX X-coordinate of circle center.
* \param dwY Y-coordinate of circle center.
* \param dwR circle radius.
*
* \return 0 if operation is successful
*/
extern uint32_t FB_DrawCircle(
uint32_t dwX,
uint32_t dwY,
uint32_t dwR)
{
int32_t d; /* Decision Variable */
uint32_t curX; /* Current X Value */
uint32_t curY; /* Current Y Value */
if (dwR == 0)
return 0;
d = 3 - (dwR << 1);
curX = 0;
curY = dwR;
while (curX <= curY)
{
FB_DrawPixel(dwX + curX, dwY + curY);
FB_DrawPixel(dwX + curX, dwY - curY);
FB_DrawPixel(dwX - curX, dwY + curY);
FB_DrawPixel(dwX - curX, dwY - curY);
FB_DrawPixel(dwX + curY, dwY + curX);
FB_DrawPixel(dwX + curY, dwY - curX);
FB_DrawPixel(dwX - curY, dwY + curX);
FB_DrawPixel(dwX - curY, dwY - curX);
if (d < 0) {
d += (curX << 2) + 6;
}
else {
d += ((curX - curY) << 2) + 10;
curY--;
}
curX++;
}
return 0;
}
/**
* \brief Draws a filled circle in FB, at the given coordinates.
*
* \param dwX X-coordinate of circle center.
* \param dwY Y-coordinate of circle center.
* \param dwR circle radius.
*
* \return 0 if operation is successful
*/
extern uint32_t FB_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwRadius)
{
signed int d ; // Decision Variable
uint32_t dwCurX ; // Current X Value
uint32_t dwCurY ; // Current Y Value
uint32_t dwXmin, dwYmin;
if (dwRadius == 0)
return 0;
d = 3 - (dwRadius << 1) ;
dwCurX = 0 ;
dwCurY = dwRadius ;
while ( dwCurX <= dwCurY )
{
dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX;
dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY;
FB_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurX, dwYmin ) ;
FB_DrawFilledRectangle( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY ) ;
dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY;
dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX;
FB_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurY, dwYmin ) ;
FB_DrawFilledRectangle( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX ) ;
if ( d < 0 )
{
d += (dwCurX << 2) + 6 ;
}
else
{
d += ((dwCurX - dwCurY) << 2) + 10;
dwCurY-- ;
}
dwCurX++ ;
}
return 0 ;
}
/**
* Pixel color is set by the LCD_SetColor() function.
* This function is optimized using an sram buffer to transfer block instead of
* individual pixels in order to limit the number of SPI interrupts.
* \param dwX1 X-coordinate of upper-left corner on LCD.
* \param dwY1 Y-coordinate of upper-left corner on LCD.
* \param dwX2 X-coordinate of lower-right corner on LCD.
* \param dwY2 Y-coordinate of lower-right corner on LCD.
*
* \return 0 if operation is successfull
*/
extern uint32_t FB_DrawRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
FB_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY1 ) ;
FB_DrawFilledRectangle( dwX1, dwY2, dwX2, dwY2 ) ;
FB_DrawFilledRectangle( dwX1, dwY1, dwX1, dwY2 ) ;
FB_DrawFilledRectangle( dwX2, dwY1, dwX2, dwY2 ) ;
return 0 ;
}

View File

@@ -0,0 +1,339 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Internal function
*----------------------------------------------------------------------------*/
/**
* Counts and return the number of bits set to '1' in the given byte.
* \param byte Byte to count.
*/
static uint8_t CountBitsInByte(uint8_t byte)
{
uint8_t count = 0;
while (byte > 0)
{
if (byte & 1)
{
count++;
}
byte >>= 1;
}
return count;
}
/**
* Counts and return the number of bits set to '1' in the given hamming code.
* \param code Hamming code.
*/
static uint8_t CountBitsInCode256(uint8_t *code)
{
return CountBitsInByte(code[0]) + CountBitsInByte(code[1]) + CountBitsInByte(code[2]);
}
/**
* Calculates the 22-bit hamming code for a 256-bytes block of data.
* \param data Data buffer to calculate code for.
* \param code Pointer to a buffer where the code should be stored.
*/
static void Compute256(const uint8_t *data, uint8_t *code)
{
uint32_t i;
uint8_t columnSum = 0;
uint8_t evenLineCode = 0;
uint8_t oddLineCode = 0;
uint8_t evenColumnCode = 0;
uint8_t oddColumnCode = 0;
// Xor all bytes together to get the column sum;
// At the same time, calculate the even and odd line codes
for (i=0; i < 256; i++)
{
columnSum ^= data[i];
// If the xor sum of the byte is 0, then this byte has no incidence on
// the computed code; so check if the sum is 1.
if ((CountBitsInByte(data[i]) & 1) == 1)
{
// Parity groups are formed by forcing a particular index bit to 0
// (even) or 1 (odd).
// Example on one byte:
//
// bits (dec) 7 6 5 4 3 2 1 0
// (bin) 111 110 101 100 011 010 001 000
// '---'---'---'----------.
// |
// groups P4' ooooooooooooooo eeeeeeeeeeeeeee P4 |
// P2' ooooooo eeeeeee ooooooo eeeeeee P2 |
// P1' ooo eee ooo eee ooo eee ooo eee P1 |
// |
// We can see that: |
// - P4 -> bit 2 of index is 0 --------------------'
// - P4' -> bit 2 of index is 1.
// - P2 -> bit 1 of index if 0.
// - etc...
// We deduce that a bit position has an impact on all even Px if
// the log2(x)nth bit of its index is 0
// ex: log2(4) = 2, bit2 of the index must be 0 (-> 0 1 2 3)
// and on all odd Px' if the log2(x)nth bit of its index is 1
// ex: log2(2) = 1, bit1 of the index must be 1 (-> 0 1 4 5)
//
// As such, we calculate all the possible Px and Px' values at the
// same time in two variables, evenLineCode and oddLineCode, such as
// evenLineCode bits: P128 P64 P32 P16 P8 P4 P2 P1
// oddLineCode bits: P128' P64' P32' P16' P8' P4' P2' P1'
//
evenLineCode ^= (255 - i);
oddLineCode ^= i;
}
}
// At this point, we have the line parities, and the column sum. First, We
// must caculate the parity group values on the column sum.
for (i=0; i < 8; i++)
{
if (columnSum & 1)
{
evenColumnCode ^= (7 - i);
oddColumnCode ^= i;
}
columnSum >>= 1;
}
// Now, we must interleave the parity values, to obtain the following layout:
// Code[0] = Line1
// Code[1] = Line2
// Code[2] = Column
// Line = Px' Px P(x-1)- P(x-1) ...
// Column = P4' P4 P2' P2 P1' P1 PadBit PadBit
code[0] = 0;
code[1] = 0;
code[2] = 0;
for (i=0; i < 4; i++)
{
code[0] <<= 2;
code[1] <<= 2;
code[2] <<= 2;
// Line 1
if ((oddLineCode & 0x80) != 0)
{
code[0] |= 2;
}
if ((evenLineCode & 0x80) != 0)
{
code[0] |= 1;
}
// Line 2
if ((oddLineCode & 0x08) != 0)
{
code[1] |= 2;
}
if ((evenLineCode & 0x08) != 0)
{
code[1] |= 1;
}
// Column
if ((oddColumnCode & 0x04) != 0)
{
code[2] |= 2;
}
if ((evenColumnCode & 0x04) != 0)
{
code[2] |= 1;
}
oddLineCode <<= 1;
evenLineCode <<= 1;
oddColumnCode <<= 1;
evenColumnCode <<= 1;
}
// Invert codes (linux compatibility)
code[0] = (~(uint32_t)code[0]);
code[1] = (~(uint32_t)code[1]);
code[2] = (~(uint32_t)code[2]);
TRACE_DEBUG("Computed code = %02X %02X %02X\n\r",
code[0], code[1], code[2]);
}
/**
* Verifies and corrects a 256-bytes block of data using the given 22-bits
* hamming code.
*
* \param data Data buffer to check.
* \param originalCode Hamming code to use for verifying the data.
*
* \return 0 if there is no error, otherwise returns a HAMMING_ERROR code.
*/
static uint8_t Verify256( uint8_t* pucData, const uint8_t* pucOriginalCode )
{
/* Calculate new code */
uint8_t computedCode[3] ;
uint8_t correctionCode[3] ;
Compute256( pucData, computedCode ) ;
/* Xor both codes together */
correctionCode[0] = computedCode[0] ^ pucOriginalCode[0] ;
correctionCode[1] = computedCode[1] ^ pucOriginalCode[1] ;
correctionCode[2] = computedCode[2] ^ pucOriginalCode[2] ;
TRACE_DEBUG( "Correction code = %02X %02X %02X\n\r", correctionCode[0], correctionCode[1], correctionCode[2] ) ;
// If all bytes are 0, there is no error
if ( (correctionCode[0] == 0) && (correctionCode[1] == 0) && (correctionCode[2] == 0) )
{
return 0 ;
}
/* If there is a single bit error, there are 11 bits set to 1 */
if ( CountBitsInCode256( correctionCode ) == 11 )
{
// Get byte and bit indexes
uint8_t byte ;
uint8_t bit ;
byte = correctionCode[0] & 0x80;
byte |= (correctionCode[0] << 1) & 0x40;
byte |= (correctionCode[0] << 2) & 0x20;
byte |= (correctionCode[0] << 3) & 0x10;
byte |= (correctionCode[1] >> 4) & 0x08;
byte |= (correctionCode[1] >> 3) & 0x04;
byte |= (correctionCode[1] >> 2) & 0x02;
byte |= (correctionCode[1] >> 1) & 0x01;
bit = (correctionCode[2] >> 5) & 0x04;
bit |= (correctionCode[2] >> 4) & 0x02;
bit |= (correctionCode[2] >> 3) & 0x01;
/* Correct bit */
TRACE_DEBUG("Correcting byte #%d at bit %d\n\r", byte, bit ) ;
pucData[byte] ^= (1 << bit) ;
return Hamming_ERROR_SINGLEBIT ;
}
/* Check if ECC has been corrupted */
if ( CountBitsInCode256( correctionCode ) == 1 )
{
return Hamming_ERROR_ECC ;
}
/* Otherwise, this is a multi-bit error */
else
{
return Hamming_ERROR_MULTIPLEBITS ;
}
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* Computes 3-bytes hamming codes for a data block whose size is multiple of
* 256 bytes. Each 256 bytes block gets its own code.
* \param data Data to compute code for.
* \param size Data size in bytes.
* \param code Codes buffer.
*/
void Hamming_Compute256x( const uint8_t *pucData, uint32_t dwSize, uint8_t* puCode )
{
TRACE_DEBUG("Hamming_Compute256x()\n\r");
while ( dwSize > 0 )
{
Compute256( pucData, puCode ) ;
pucData += 256;
puCode += 3;
dwSize -= 256;
}
}
/**
* Verifies 3-bytes hamming codes for a data block whose size is multiple of
* 256 bytes. Each 256-bytes block is verified with its own code.
*
* \return 0 if the data is correct, Hamming_ERROR_SINGLEBIT if one or more
* block(s) have had a single bit corrected, or either Hamming_ERROR_ECC
* or Hamming_ERROR_MULTIPLEBITS.
*
* \param data Data buffer to verify.
* \param size Size of the data in bytes.
* \param code Original codes.
*/
uint8_t Hamming_Verify256x( uint8_t* pucData, uint32_t dwSize, const uint8_t* pucCode )
{
uint8_t error ;
uint8_t result = 0 ;
TRACE_DEBUG( "Hamming_Verify256x()\n\r" ) ;
while ( dwSize > 0 )
{
error = Verify256( pucData, pucCode ) ;
if ( error == Hamming_ERROR_SINGLEBIT )
{
result = Hamming_ERROR_SINGLEBIT ;
}
else
{
if ( error )
{
return error ;
}
}
pucData += 256;
pucCode += 3;
dwSize -= 256;
}
return result ;
}

View File

@@ -0,0 +1,907 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of ILI9325 driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <string.h>
#include <stdio.h>
#ifdef BOARD_LCD_ILI9325
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/* Pixel cache used to speed up communication */
#define LCD_DATA_CACHE_SIZE BOARD_LCD_WIDTH
static LcdColor_t gLcdPixelCache[LCD_DATA_CACHE_SIZE];
/*----------------------------------------------------------------------------
* Export functions
*----------------------------------------------------------------------------*/
/**
* \brief Write data to LCD Register.
*
* \param reg Register address.
* \param data Data to be written.
*/
static void LCD_WriteReg( uint8_t reg, uint16_t data )
{
LCD_IR() = 0;
LCD_IR() = reg;
LCD_D() = (data >> 8) & 0xFF;
LCD_D() = data & 0xFF;
}
/**
* \brief Read data from LCD Register.
*
* \param reg Register address.
*
* \return Readed data.
*/
static uint16_t LCD_ReadReg( uint8_t reg )
{
uint16_t value;
LCD_IR() = 0;
LCD_IR() = reg;
value = LCD_D();
value = (value << 8) | LCD_D();
return value;
}
/**
* \brief Prepare to write GRAM data.
*/
extern void LCD_WriteRAM_Prepare( void )
{
LCD_IR() = 0 ;
LCD_IR() = ILI9325_R22H ; /* Write Data to GRAM (R22h) */
}
/**
* \brief Write data to LCD GRAM.
*
* \param color 24-bits RGB color.
*/
extern void LCD_WriteRAM( LcdColor_t dwColor )
{
LCD_D() = ((dwColor >> 16) & 0xFF);
LCD_D() = ((dwColor >> 8) & 0xFF);
LCD_D() = (dwColor & 0xFF);
}
/**
* \brief Write mutiple data in buffer to LCD controller.
*
* \param pBuf data buffer.
* \param size size in pixels.
*/
static void LCD_WriteRAMBuffer(const LcdColor_t *pBuf, uint32_t size)
{
uint32_t addr ;
for ( addr = 0 ; addr < size ; addr++ )
{
LCD_WriteRAM(pBuf[addr]);
}
}
/**
* \brief Prepare to read GRAM data.
*/
extern void LCD_ReadRAM_Prepare( void )
{
LCD_IR() = 0 ;
LCD_IR() = ILI9325_R22H ; /* Write Data to GRAM (R22h) */
}
/**
* \brief Read data to LCD GRAM.
*
* \note Because pixel data LCD GRAM is 18-bits, so convertion to RGB 24-bits
* will cause low color bit lose.
*
* \return color 24-bits RGB color.
*/
extern uint32_t LCD_ReadRAM( void )
{
uint8_t value[2];
uint32_t color;
value[0] = LCD_D(); /* dummy read */
value[1] = LCD_D(); /* dummy read */
value[0] = LCD_D(); /* data upper byte */
value[1] = LCD_D(); /* data lower byte */
/* Convert RGB565 to RGB888 */
/* For BGR format */
color = ((value[0] & 0xF8)) | /* R */
((value[0] & 0x07) << 13) | ((value[1] & 0xE0) << 5) | /* G */
((value[1] & 0x1F) << 19); /* B */
return color;
}
/*----------------------------------------------------------------------------
* Basic ILI9225 primitives
*----------------------------------------------------------------------------*/
/**
* \brief Check Box coordinates. Return upper left and bottom right coordinates.
*
* \param pX1 X-coordinate of upper-left corner on LCD.
* \param pY1 Y-coordinate of upper-left corner on LCD.
* \param pX2 X-coordinate of lower-right corner on LCD.
* \param pY2 Y-coordinate of lower-right corner on LCD.
*/
static void CheckBoxCoordinates( uint32_t *pX1, uint32_t *pY1, uint32_t *pX2, uint32_t *pY2 )
{
uint32_t dw;
if ( *pX1 >= BOARD_LCD_WIDTH )
{
*pX1 = BOARD_LCD_WIDTH-1 ;
}
if ( *pX2 >= BOARD_LCD_WIDTH )
{
*pX2 = BOARD_LCD_WIDTH-1 ;
}
if ( *pY1 >= BOARD_LCD_HEIGHT )
{
*pY1 = BOARD_LCD_HEIGHT-1 ;
}
if ( *pY2 >= BOARD_LCD_HEIGHT )
{
*pY2 = BOARD_LCD_HEIGHT-1 ;
}
if (*pX1 > *pX2)
{
dw = *pX1;
*pX1 = *pX2;
*pX2 = dw;
}
if (*pY1 > *pY2)
{
dw = *pY1;
*pY1 = *pY2;
*pY2 = dw;
}
}
/**
* \brief Initialize the LCD controller.
*/
extern uint32_t LCD_Initialize( void )
{
uint16_t chipid ;
/* Check ILI9325 chipid */
chipid = LCD_ReadReg( ILI9325_R00H ) ; /* Driver Code Read (R00h) */
if ( chipid != ILI9325_DEVICE_CODE )
{
printf( "Read ILI9325 chip ID (0x%04x) error, skip initialization.\r\n", chipid ) ;
return 1 ;
}
/* Turn off LCD */
LCD_PowerDown() ;
/* Start initial sequence */
LCD_WriteReg(ILI9325_R10H, 0x0000); /* DSTB = LP = STB = 0 */
LCD_WriteReg(ILI9325_R00H, 0x0001); /* start internal OSC */
LCD_WriteReg(ILI9325_R01H, ILI9325_R01H_SS ) ; /* set SS and SM bit */
LCD_WriteReg(ILI9325_R02H, 0x0700); /* set 1 line inversion */
//LCD_WriteReg(ILI9325_R03H, 0xD030); /* set GRAM write direction and BGR=1. */
LCD_WriteReg(ILI9325_R04H, 0x0000); /* Resize register */
LCD_WriteReg(ILI9325_R08H, 0x0207); /* set the back porch and front porch */
LCD_WriteReg(ILI9325_R09H, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
LCD_WriteReg(ILI9325_R0AH, 0x0000); /* FMARK function */
LCD_WriteReg(ILI9325_R0CH, 0x0000); /* RGB interface setting */
LCD_WriteReg(ILI9325_R0DH, 0x0000); /* Frame marker Position */
LCD_WriteReg(ILI9325_R0FH, 0x0000); /* RGB interface polarity */
/* Power on sequence */
LCD_WriteReg(ILI9325_R10H, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
LCD_WriteReg(ILI9325_R11H, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
LCD_WriteReg(ILI9325_R12H, 0x0000); /* VREG1OUT voltage */
LCD_WriteReg(ILI9325_R13H, 0x0000); /* VDV[4:0] for VCOM amplitude */
Wait( 200 ) ; /* Dis-charge capacitor power voltage */
LCD_WriteReg(ILI9325_R10H, 0x1290); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
LCD_WriteReg(ILI9325_R11H, 0x0227); /* DC1[2:0], DC0[2:0], VC[2:0] */
Wait( 50 ) ;
LCD_WriteReg(ILI9325_R12H, 0x001B); /* Internal reference voltage= Vci; */
Wait( 50 ) ;
LCD_WriteReg(ILI9325_R13H, 0x1100); /* Set VDV[4:0] for VCOM amplitude */
LCD_WriteReg(ILI9325_R29H, 0x0019); /* Set VCM[5:0] for VCOMH */
LCD_WriteReg(ILI9325_R2BH, 0x000D); /* Set Frame Rate */
Wait( 50 ) ;
/* Adjust the Gamma Curve */
LCD_WriteReg(ILI9325_R30H, 0x0000);
LCD_WriteReg(ILI9325_R31H, 0x0204);
LCD_WriteReg(ILI9325_R32H, 0x0200);
LCD_WriteReg(ILI9325_R35H, 0x0007);
LCD_WriteReg(ILI9325_R36H, 0x1404);
LCD_WriteReg(ILI9325_R37H, 0x0705);
LCD_WriteReg(ILI9325_R38H, 0x0305);
LCD_WriteReg(ILI9325_R39H, 0x0707);
LCD_WriteReg(ILI9325_R3CH, 0x0701);
LCD_WriteReg(ILI9325_R3DH, 0x000e);
LCD_SetDisplayPortrait( 0 ) ;
/* Vertical Scrolling */
LCD_WriteReg( ILI9325_R61H, 0x0001 ) ;
LCD_WriteReg( ILI9325_R6AH, 0x0000 ) ;
/* Partial Display Control */
LCD_WriteReg(ILI9325_R80H, 0x0000);
LCD_WriteReg(ILI9325_R81H, 0x0000);
LCD_WriteReg(ILI9325_R82H, 0x0000);
LCD_WriteReg(ILI9325_R83H, 0x0000);
LCD_WriteReg(ILI9325_R84H, 0x0000);
LCD_WriteReg(ILI9325_R85H, 0x0000);
/* Panel Control */
LCD_WriteReg(ILI9325_R90H, 0x0010);
LCD_WriteReg(ILI9325_R92H, 0x0600);
LCD_WriteReg(ILI9325_R95H, 0x0110);
LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
LCD_SetCursor( 0, 0 ) ;
return 0 ;
}
/**
* \brief Turn on the LCD.
*/
extern void LCD_On( void )
{
/* Display Control 1 (R07h) */
/* When BASEE = “1”, the base image is displayed. */
/* GON and DTE Set the output level of gate driver G1 ~ G320 : Normal Display */
/* D1=1 D0=1 BASEE=1: Base image display Operate */
LCD_WriteReg( ILI9325_R07H, ILI9325_R07H_BASEE
| ILI9325_R07H_GON | ILI9325_R07H_DTE
| ILI9325_R07H_D1 | ILI9325_R07H_D0 ) ;
}
/**
* \brief Turn off the LCD.
*/
extern void LCD_Off( void )
{
/* Display Control 1 (R07h) */
/* When BASEE = “0”, no base image is displayed. */
/* When the display is turned off by setting D[1:0] = “00”, the ILI9325 internal display
operation is halted completely. */
/* PTDE1/0 = 0: turns off partial image. */
LCD_WriteReg( ILI9325_R07H, 0x00 ) ;
}
/**
* \brief Power down the LCD.
*/
extern void LCD_PowerDown( void )
{
/* Display Control 1 (R07h) */
/* When BASEE = “0”, no base image is displayed. */
/* GON and DTE Set the output level of gate driver G1 ~ G320 : Normal Display */
/* D1=1 D0=1 BASEE=1: Base image display Operate */
LCD_WriteReg( ILI9325_R07H, ILI9325_R07H_GON | ILI9325_R07H_DTE
| ILI9325_R07H_D1 | ILI9325_R07H_D0 ) ;
}
/**
* \brief Convert 24 bit RGB color into 5-6-5 rgb color space.
*
* Initialize the LcdColor_t cache with the color pattern.
* \param x 24-bits RGB color.
* \return 0 for successfull operation.
*/
extern uint32_t LCD_SetColor( uint32_t dwRgb24Bits )
{
uint32_t i ;
/* Fill the cache with selected color */
for ( i = 0 ; i < LCD_DATA_CACHE_SIZE ; ++i )
{
gLcdPixelCache[i] = dwRgb24Bits ;
}
return 0;
}
/**
* \brief Set cursor of LCD srceen.
*
* \param x X-coordinate of upper-left corner on LCD.
* \param y Y-coordinate of upper-left corner on LCD.
*/
extern void LCD_SetCursor( uint16_t x, uint16_t y )
{
/* GRAM Horizontal/Vertical Address Set (R20h, R21h) */
LCD_WriteReg( ILI9325_R20H, x ) ; /* column */
LCD_WriteReg( ILI9325_R21H, y ) ; /* row */
}
extern void LCD_SetWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight )
{
/* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */
/* Set Horizontal Address Start Position */
LCD_WriteReg( ILI9325_R50H, (uint16_t)dwX ) ;
/* Set Horizontal Address End Position */
LCD_WriteReg( ILI9325_R51H, (uint16_t)dwX+dwWidth-1 ) ;
/* Set Vertical Address Start Position */
LCD_WriteReg( ILI9325_R52H, (uint16_t)dwY ) ;
/* Set Vertical Address End Position */
LCD_WriteReg( ILI9325_R53H, (uint16_t)dwY+dwHeight-1 ) ;
}
extern void LCD_SetDisplayLandscape( uint32_t dwRGB )
{
uint16_t dwValue ;
/* When AM = “1”, the address is updated in vertical writing direction. */
/* DFM Set the mode of transferring data to the internal RAM when TRI = “1”. */
/* When TRI = “1”, data are transferred to the internal RAM in 8-bit x 3 transfers mode via the 8-bit interface. */
/* Use the high speed write mode (HWM=1) */
/* ORG = “1”: The original address “00000h” moves according to the I/D[1:0] setting. */
/* I/D[1:0] = 00 Horizontal : decrement Vertical : decrement, AM=0:Horizontal */
dwValue = ILI9325_R03H_AM | ILI9325_R03H_DFM | ILI9325_R03H_TRI | ILI9325_R03H_HWM | ILI9325_R03H_ORG ;
if ( dwRGB == 0 )
{
/* BGR=”1”: Swap the RGB data to BGR in writing into GRAM. */
dwValue |= ILI9325_R03H_BGR ;
}
LCD_WriteReg( ILI9325_R03H, dwValue ) ;
// LCD_WriteReg( ILI9325_R60H, (0x1d<<8)|0x00 ) ; /*Gate Scan Control */
LCD_SetWindow( 0, 0, BOARD_LCD_HEIGHT, BOARD_LCD_WIDTH ) ;
}
extern void LCD_SetDisplayPortrait( uint32_t dwRGB )
{
uint16_t dwValue ;
/* Use the high speed write mode (HWM=1) */
/* When TRI = “1”, data are transferred to the internal RAM in 8-bit x 3 transfers mode via the 8-bit interface. */
/* DFM Set the mode of transferring data to the internal RAM when TRI = “1”. */
/* I/D[1:0] = 11 Horizontal : increment Vertical : increment, AM=0:Horizontal */
dwValue = ILI9325_R03H_HWM | ILI9325_R03H_TRI | ILI9325_R03H_DFM | ILI9325_R03H_ID1 | ILI9325_R03H_ID0 ;
if ( dwRGB == 0 )
{
/* BGR=”1”: Swap the RGB data to BGR in writing into GRAM. */
dwValue |= ILI9325_R03H_BGR ;
}
LCD_WriteReg( ILI9325_R03H, dwValue ) ;
/* Gate Scan Control (R60h, R61h, R6Ah) */
/* SCN[5:0] = 00 */
/* NL[5:0]: Sets the number of lines to drive the LCD at an interval of 8 lines. */
LCD_WriteReg( ILI9325_R60H, ILI9325_R60H_GS|(0x27<<8)|0x00 ) ;
}
extern void LCD_VerticalScroll( uint16_t wY )
{
/* Gate Scan Control (R60h, R61h, R6Ah) */
/* Enables the grayscale inversion of the image by setting REV=1. */
/* VLE: Vertical scroll display enable bit */
LCD_WriteReg( ILI9325_R61H, 3 ) ;
LCD_WriteReg( ILI9325_R6AH, wY ) ;
}
extern void LCD_SetPartialImage1( uint32_t dwDisplayPos, uint32_t dwStart, uint32_t dwEnd )
{
assert( dwStart <= dwEnd ) ;
/* Partial Image 1 Display Position (R80h) */
LCD_WriteReg( ILI9325_R80H, dwDisplayPos&0x1ff ) ;
/* Partial Image 1 RAM Start/End Address (R81h, R82h) */
LCD_WriteReg( ILI9325_R81H, dwStart&0x1ff ) ;
LCD_WriteReg( ILI9325_R82H, dwEnd&0x1ff ) ;
}
extern void LCD_SetPartialImage2( uint32_t dwDisplayPos, uint32_t dwStart, uint32_t dwEnd )
{
assert( dwStart <= dwEnd ) ;
/* Partial Image 2 Display Position (R83h) */
LCD_WriteReg( ILI9325_R83H, dwDisplayPos&0x1ff ) ;
/* Partial Image 2 RAM Start/End Address (R84h, R85h) */
LCD_WriteReg( ILI9325_R84H, dwStart&0x1ff ) ;
LCD_WriteReg( ILI9325_R85H, dwEnd&0x1ff ) ;
}
/**
* \brief Draw a LcdColor_t on LCD of given color.
*
* \param x X-coordinate of pixel.
* \param y Y-coordinate of pixel.
*/
extern uint32_t LCD_DrawPixel( uint32_t x, uint32_t y )
{
if( (x >= BOARD_LCD_WIDTH) || (y >= BOARD_LCD_HEIGHT) )
{
return 1;
}
/* Set cursor */
LCD_SetCursor( x, y );
/* Prepare to write in GRAM */
LCD_WriteRAM_Prepare();
LCD_WriteRAM( *gLcdPixelCache );
return 0;
}
extern void LCD_TestPattern( uint32_t dwRGB )
{
uint32_t dwLine ;
uint32_t dw ;
LCD_SetWindow( 10, 10, 100, 20 ) ;
LCD_SetCursor( 10, 10 ) ;
LCD_WriteRAM_Prepare() ;
for ( dwLine=0 ; dwLine < 20 ; dwLine++ )
{
/* Draw White bar */
for ( dw=0 ; dw < 20 ; dw++ )
{
LCD_D() = 0xff ;
LCD_D() = 0xff ;
LCD_D() = 0xff ;
}
/* Draw Red bar */
for ( dw=0 ; dw < 20 ; dw++ )
{
if ( dwRGB == 0 )
{
LCD_D() = 0xff ;
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
}
else
{
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
LCD_D() = 0xff ;
}
}
/* Draw Green bar */
for ( dw=0 ; dw < 20 ; dw++ )
{
LCD_D() = 0x00 ;
LCD_D() = 0xff ;
LCD_D() = 0x00 ;
}
/* Draw Blue bar */
for ( dw=0 ; dw < 20 ; dw++ )
{
if ( dwRGB == 0 )
{
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
LCD_D() = 0xff ;
}
else
{
LCD_D() = 0xff ;
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
}
}
/* Draw Black bar */
for ( dw=0 ; dw < 20 ; dw++ )
{
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
LCD_D() = 0x00 ;
}
}
LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
}
/**
* \brief Write several pixels with the same color to LCD GRAM.
*
* LcdColor_t color is set by the LCD_SetColor() function.
* This function is optimized using an sram buffer to transfer block instead of
* individual pixels in order to limit the number of SPI interrupts.
* \param dwX1 X-coordinate of upper-left corner on LCD.
* \param dwY1 Y-coordinate of upper-left corner on LCD.
* \param dwX2 X-coordinate of lower-right corner on LCD.
* \param dwY2 Y-coordinate of lower-right corner on LCD.
*/
extern uint32_t LCD_DrawFilledRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
uint32_t size, blocks;
/* Swap coordinates if necessary */
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
/* Determine the refresh window area */
/* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */
LCD_WriteReg(ILI9325_R50H, (uint16_t)dwX1);
LCD_WriteReg(ILI9325_R51H, (uint16_t)dwX2);
LCD_WriteReg(ILI9325_R52H, (uint16_t)dwY1);
LCD_WriteReg(ILI9325_R53H, (uint16_t)dwY2);
/* Set cursor */
LCD_SetCursor( dwX1, dwY1 );
/* Prepare to write in GRAM */
LCD_WriteRAM_Prepare();
size = (dwX2 - dwX1 + 1) * (dwY2 - dwY1 + 1);
/* Send pixels blocks => one SPI IT / block */
blocks = size / LCD_DATA_CACHE_SIZE;
while (blocks--)
{
LCD_WriteRAMBuffer(gLcdPixelCache, LCD_DATA_CACHE_SIZE);
}
/* Send remaining pixels */
LCD_WriteRAMBuffer(gLcdPixelCache, size % LCD_DATA_CACHE_SIZE);
/* Reset the refresh window area */
/* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */
LCD_WriteReg(ILI9325_R50H, (uint16_t)0 ) ;
LCD_WriteReg(ILI9325_R51H, (uint16_t)BOARD_LCD_WIDTH - 1 ) ;
LCD_WriteReg(ILI9325_R52H, (uint16_t)0) ;
LCD_WriteReg(ILI9325_R53H, (uint16_t)BOARD_LCD_HEIGHT - 1 ) ;
return 0 ;
}
/**
* \brief Write several pixels pre-formatted in a bufer to LCD GRAM.
*
* \param dwX1 X-coordinate of upper-left corner on LCD.
* \param dwY1 Y-coordinate of upper-left corner on LCD.
* \param dwX2 X-coordinate of lower-right corner on LCD.
* \param dwY2 Y-coordinate of lower-right corner on LCD.
* \param pBuffer LcdColor_t buffer area.
*/
extern uint32_t LCD_DrawPicture( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2, const LcdColor_t *pBuffer )
{
uint32_t size, blocks;
LcdColor_t currentColor;
/* Swap coordinates if necessary */
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
/* Determine the refresh window area */
/* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */
LCD_WriteReg(ILI9325_R50H, (uint16_t)dwX1 ) ;
LCD_WriteReg(ILI9325_R51H, (uint16_t)dwX2 ) ;
LCD_WriteReg(ILI9325_R52H, (uint16_t)dwY1 ) ;
LCD_WriteReg(ILI9325_R53H, (uint16_t)dwY2 ) ;
/* Set cursor */
LCD_SetCursor( dwX1, dwY1 );
/* Prepare to write in GRAM */
LCD_WriteRAM_Prepare();
size = (dwX2 - dwX1 + 1) * (dwY2 - dwY1 + 1);
/* Check if the buffer is within the SRAM */
if ((IRAM_ADDR <= (uint32_t)pBuffer) && ((uint32_t)pBuffer < (IRAM_ADDR+IRAM_SIZE)))
{
LCD_WriteRAMBuffer(pBuffer, size);
}
/* If the buffer is not in SRAM, transfer it in SRAM first before transfer */
else
{
/* Use color buffer as a cache */
currentColor = gLcdPixelCache[0];
/* Send pixels blocks => one SPI IT / block */
blocks = size / LCD_DATA_CACHE_SIZE;
while (blocks--)
{
memcpy(gLcdPixelCache, pBuffer, LCD_DATA_CACHE_SIZE * sizeof(LcdColor_t));
LCD_WriteRAMBuffer(gLcdPixelCache, LCD_DATA_CACHE_SIZE);
pBuffer += LCD_DATA_CACHE_SIZE;
}
/* Send remaining pixels */
memcpy(gLcdPixelCache, pBuffer, (size % LCD_DATA_CACHE_SIZE) * sizeof(LcdColor_t));
LCD_WriteRAMBuffer(gLcdPixelCache, size % LCD_DATA_CACHE_SIZE);
/* Restore the color cache */
LCD_SetColor(currentColor);
}
/* Reset the refresh window area */
/* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */
LCD_WriteReg(ILI9325_R50H, (uint16_t)0 ) ;
LCD_WriteReg(ILI9325_R51H, (uint16_t)BOARD_LCD_WIDTH - 1 ) ;
LCD_WriteReg(ILI9325_R52H, (uint16_t)0 ) ;
LCD_WriteReg(ILI9325_R53H, (uint16_t)BOARD_LCD_HEIGHT - 1 ) ;
return 0 ;
}
/*
* \brief Draw a line on LCD, which is not horizontal or vertical.
*
* \param x X-coordinate of line start.
* \param y Y-coordinate of line start.
* \param length line length.
* \param direction line direction: 0 - horizontal, 1 - vertical.
* \param color LcdColor_t color.
*/
static uint32_t DrawLineBresenham( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
int dx, dy ;
int i ;
int xinc, yinc, cumul ;
int x, y ;
x = dwX1 ;
y = dwY1 ;
dx = dwX2 - dwX1 ;
dy = dwY2 - dwY1 ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = ( dx > 0 ) ? dx : -dx ;
dy = ( dy > 0 ) ? dy : -dy ;
LCD_DrawPixel( x, y ) ;
if ( dx > dy )
{
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ )
{
x += xinc ;
cumul += dy ;
if ( cumul >= dx )
{
cumul -= dx ;
y += yinc ;
}
LCD_DrawPixel( x, y ) ;
}
}
else
{
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ )
{
y += yinc ;
cumul += dx ;
if ( cumul >= dy )
{
cumul -= dy ;
x += xinc ;
}
LCD_DrawPixel( x, y ) ;
}
}
return 0 ;
}
/*
* \brief Draw a line on LCD, horizontal and vertical line are supported.
*
* \param dwX1 X-coordinate of line start.
* \param dwY1 Y-coordinate of line start.
* \param dwX2 X-coordinate of line end.
* \param dwY2 Y-coordinate of line end.
*/
extern uint32_t LCD_DrawLine ( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
/* Optimize horizontal or vertical line drawing */
if (( dwY1 == dwY2 ) || (dwX1 == dwX2))
{
LCD_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY2 );
}
else
{
DrawLineBresenham( dwX1, dwY1, dwX2, dwY2 ) ;
}
return 0 ;
}
/**
* \brief Draws a circle on LCD, at the given coordinates.
*
* \param dwX X-coordinate of circle center.
* \param dwY Y-coordinate of circle center.
* \param dwR circle radius.
*/
extern uint32_t LCD_DrawCircle( uint32_t dwX, uint32_t dwY, uint32_t dwR )
{
int32_t d; /* Decision Variable */
uint32_t curX; /* Current X Value */
uint32_t curY; /* Current Y Value */
if (dwR == 0)
{
return 0;
}
d = 3 - (dwR << 1);
curX = 0;
curY = dwR;
while (curX <= curY)
{
LCD_DrawPixel(dwX + curX, dwY + curY);
LCD_DrawPixel(dwX + curX, dwY - curY);
LCD_DrawPixel(dwX - curX, dwY + curY);
LCD_DrawPixel(dwX - curX, dwY - curY);
LCD_DrawPixel(dwX + curY, dwY + curX);
LCD_DrawPixel(dwX + curY, dwY - curX);
LCD_DrawPixel(dwX - curY, dwY + curX);
LCD_DrawPixel(dwX - curY, dwY - curX);
if (d < 0)
{
d += (curX << 2) + 6;
}
else
{
d += ((curX - curY) << 2) + 10;
curY--;
}
curX++;
}
return 0;
}
extern uint32_t LCD_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwRadius)
{
signed int d ; /* Decision Variable */
uint32_t dwCurX ; /* Current X Value */
uint32_t dwCurY ; /* Current Y Value */
uint32_t dwXmin, dwYmin;
if (dwRadius == 0)
{
return 0;
}
d = 3 - (dwRadius << 1) ;
dwCurX = 0 ;
dwCurY = dwRadius ;
while ( dwCurX <= dwCurY )
{
dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX;
dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY;
LCD_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurX, dwYmin ) ;
LCD_DrawFilledRectangle( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY ) ;
dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY;
dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX;
LCD_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurY, dwYmin ) ;
LCD_DrawFilledRectangle( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX ) ;
if ( d < 0 )
{
d += (dwCurX << 2) + 6 ;
}
else
{
d += ((dwCurX - dwCurY) << 2) + 10;
dwCurY-- ;
}
dwCurX++ ;
}
return 0 ;
}
extern uint32_t LCD_DrawRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
{
CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2);
LCD_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY1 ) ;
LCD_DrawFilledRectangle( dwX1, dwY2, dwX2, dwY2 ) ;
LCD_DrawFilledRectangle( dwX1, dwY1, dwX1, dwY2 ) ;
LCD_DrawFilledRectangle( dwX2, dwY1, dwX2, dwY2 ) ;
return 0 ;
}
/**
* \brief Set the backlight of the LCD (AAT3155).
*
* \param level Backlight brightness level [1..16], 1 means maximum brightness.
*/
extern void LCD_SetBacklight (uint32_t level)
{
uint32_t i;
const Pin pPins[] = {BOARD_BACKLIGHT_PIN};
/* Ensure valid level */
level = (level < 1) ? 1 : level;
level = (level > 16) ? 16 : level;
/* Enable pins */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Switch off backlight */
PIO_Clear(pPins);
i = 600 * (BOARD_MCK / 1000000); /* wait for at least 500us */
while(i--);
/* Set new backlight level */
for (i = 0; i < level; i++)
{
PIO_Clear(pPins);
PIO_Clear(pPins);
PIO_Clear(pPins);
PIO_Set(pPins);
PIO_Set(pPins);
PIO_Set(pPins);
}
}
#endif

View File

@@ -0,0 +1,611 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
*
* ISO 7816 driver
*
* \section Usage
*
* Explanation on the usage of the code made available through the header file.
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
/*------------------------------------------------------------------------------
* Definitions
*------------------------------------------------------------------------------*/
/** Case for APDU commands*/
#define CASE1 1
#define CASE2 2
#define CASE3 3
/** Flip flop for send and receive char */
#define USART_SEND 0
#define USART_RCV 1
#if !defined(BOARD_ISO7816_BASE_USART)
#define BOARD_ISO7816_BASE_USART USART1
#define BOARD_ISO7816_ID_USART ID_USART1
#endif
/*-----------------------------------------------------------------------------
* Internal variables
*-----------------------------------------------------------------------------*/
/** Variable for state of send and receive froom USART */
static uint8_t StateUsartGlobal = USART_RCV;
/** Pin reset master card */
static Pin st_pinIso7816RstMC;
/*----------------------------------------------------------------------------
* Internal functions
*----------------------------------------------------------------------------*/
/**
* Get a character from ISO7816
* \param pCharToReceive Pointer for store the received char
* \return 0: if timeout else status of US_CSR
*/
static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive )
{
uint32_t status;
uint32_t timeout=0;
if( StateUsartGlobal == USART_SEND ) {
while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXEMPTY) == 0) {}
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
StateUsartGlobal = USART_RCV;
}
/* Wait USART ready for reception */
while( ((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_RXRDY) == 0) ) {
if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
TRACE_DEBUG("TimeOut\n\r");
return( 0 );
}
}
TRACE_DEBUG("T: %u\n\r", timeout);
/* At least one complete character has been received and US_RHR has not yet been read. */
/* Get a char */
*pCharToReceive = ((BOARD_ISO7816_BASE_USART->US_RHR) & 0xFF);
status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
(1<<10)));
if (status != 0 ) {
/* TRACE_DEBUG("R:0x%X\n\r", status); */
TRACE_DEBUG("R:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
}
/* Return status */
return( status );
}
/**
* Send a char to ISO7816
* \param CharToSend char to be send
* \return status of US_CSR
*/
static uint32_t ISO7816_SendChar( uint8_t CharToSend )
{
uint32_t status;
if( StateUsartGlobal == USART_RCV ) {
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
StateUsartGlobal = USART_SEND;
}
/* Wait USART ready for transmit */
while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXRDY) == 0) {}
/* There is no character in the US_THR */
/* Transmit a char */
BOARD_ISO7816_BASE_USART->US_THR = CharToSend;
status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
(1<<10)));
if (status != 0 ) {
TRACE_DEBUG("E:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
}
/* Return status */
return( status );
}
/**
* Iso 7816 ICC power on
*/
static void ISO7816_IccPowerOn( void )
{
/* Set RESET Master Card */
PIO_Set(&st_pinIso7816RstMC);
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* Iso 7816 ICC power off
*/
void ISO7816_IccPowerOff( void )
{
/* Clear RESET Master Card */
PIO_Clear(&st_pinIso7816RstMC);
}
/**
* Transfert Block TPDU T=0
* \param pAPDU APDU buffer
* \param pMessage Message buffer
* \param wLength Block length
* \return Message index
*/
uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
uint8_t *pMessage,
uint16_t wLength )
{
uint16_t NeNc;
uint16_t indexApdu = 4;
uint16_t indexMessage = 0;
uint8_t SW1 = 0;
uint8_t procByte;
uint8_t cmdCase;
TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]);
TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]);
TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]);
TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]);
TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]);
TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]);
TRACE_DEBUG("wlength=%d\n\r",wLength);
ISO7816_SendChar( pAPDU[0] ); /* CLA */
ISO7816_SendChar( pAPDU[1] ); /* INS */
ISO7816_SendChar( pAPDU[2] ); /* P1 */
ISO7816_SendChar( pAPDU[3] ); /* P2 */
ISO7816_SendChar( pAPDU[4] ); /* P3 */
/* Handle the four structures of command APDU */
indexApdu = 4;
if( wLength == 4 ) {
cmdCase = CASE1;
NeNc = 0;
}
else if( wLength == 5) {
cmdCase = CASE2;
NeNc = pAPDU[4]; /* C5 */
if (NeNc == 0) {
NeNc = 256;
}
}
else if( wLength == 6) {
NeNc = pAPDU[4]; /* C5 */
cmdCase = CASE3;
}
else if( wLength == 7) {
NeNc = pAPDU[4]; /* C5 */
if( NeNc == 0 ) {
cmdCase = CASE2;
NeNc = (pAPDU[5]<<8)+pAPDU[6];
}
else {
cmdCase = CASE3;
}
}
else {
NeNc = pAPDU[4]; /* C5 */
if( NeNc == 0 ) {
cmdCase = CASE3;
NeNc = (pAPDU[5]<<8)+pAPDU[6];
}
else {
cmdCase = CASE3;
}
}
TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
/* Handle Procedure Bytes */
do {
ISO7816_GetChar(&procByte);
/* Handle NULL */
if ( procByte == ISO_NULL_VAL ) {
TRACE_DEBUG("INS\n\r");
continue;
}
/* Handle SW1 */
else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
TRACE_DEBUG("SW1\n\r");
SW1 = 1;
}
/* Handle INS */
else if ( pAPDU[1] == procByte) {
TRACE_DEBUG("HdlINS\n\r");
if (cmdCase == CASE2) {
/* receive data from card */
do {
ISO7816_GetChar(&pMessage[indexMessage++]);
} while( 0 != --NeNc );
}
else {
/* Send data */
do {
ISO7816_SendChar(pAPDU[indexApdu++]);
} while( 0 != --NeNc );
}
}
/* Handle INS ^ 0xff */
else if ( pAPDU[1] == (procByte ^ 0xff)) {
TRACE_DEBUG("HdlINS+\n\r");
if (cmdCase == CASE2) {
/* receive data from card */
ISO7816_GetChar(&pMessage[indexMessage++]);
}
else {
ISO7816_SendChar(pAPDU[indexApdu++]);
}
NeNc--;
}
else {
/* ?? */
TRACE_DEBUG("procByte=0x%X\n\r", procByte);
break;
}
} while (NeNc != 0);
/* Status Bytes */
if (SW1 == 0) {
ISO7816_GetChar(&pMessage[indexMessage++]); /* SW1 */
}
else {
pMessage[indexMessage++] = procByte;
}
ISO7816_GetChar(&pMessage[indexMessage++]); /* SW2 */
return( indexMessage );
}
/**
* Escape ISO7816
*/
void ISO7816_Escape( void )
{
TRACE_DEBUG("For user, if needed\n\r");
}
/**
* Restart clock ISO7816
*/
void ISO7816_RestartClock( void )
{
TRACE_DEBUG("ISO7816_RestartClock\n\r");
BOARD_ISO7816_BASE_USART->US_BRGR = 13;
}
/**
* Stop clock ISO7816
*/
void ISO7816_StopClock( void )
{
TRACE_DEBUG("ISO7816_StopClock\n\r");
BOARD_ISO7816_BASE_USART->US_BRGR = 0;
}
/**
* T0 APDU
*/
void ISO7816_toAPDU( void )
{
TRACE_DEBUG("ISO7816_toAPDU\n\r");
TRACE_DEBUG("Not supported at this time\n\r");
}
/**
* Answer To Reset (ATR)
* \param pAtr ATR buffer
* \param pLength Pointer for store the ATR length
*/
void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
{
uint32_t i;
uint32_t j;
uint32_t y;
*pLength = 0;
/* Read ATR TS */
ISO7816_GetChar(&pAtr[0]);
/* Read ATR T0 */
ISO7816_GetChar(&pAtr[1]);
y = pAtr[1] & 0xF0;
i = 2;
/* Read ATR Ti */
while (y) {
if (y & 0x10) { /* TA[i] */
ISO7816_GetChar(&pAtr[i++]);
}
if (y & 0x20) { /* TB[i] */
ISO7816_GetChar(&pAtr[i++]);
}
if (y & 0x40) { /* TC[i] */
ISO7816_GetChar(&pAtr[i++]);
}
if (y & 0x80) { /* TD[i] */
ISO7816_GetChar(&pAtr[i]);
y = pAtr[i++] & 0xF0;
}
else {
y = 0;
}
}
/* Historical Bytes */
y = pAtr[1] & 0x0F;
for( j=0; j < y; j++ ) {
ISO7816_GetChar(&pAtr[i++]);
}
*pLength = i;
}
/**
* Set data rate and clock frequency
* \param dwClockFrequency ICC clock frequency in KHz.
* \param dwDataRate ICC data rate in bpd
*/
void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
{
uint8_t ClockFrequency;
/* Define the baud rate divisor register */
/* CD = MCK / SCK */
/* SCK = FIDI x BAUD = 372 x 9600 */
/* BOARD_MCK */
/* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
ClockFrequency = BOARD_MCK / BOARD_ISO7816_BASE_USART->US_BRGR;
BOARD_ISO7816_BASE_USART->US_FIDI = (ClockFrequency)/dwDataRate;
}
/**
* Pin status for ISO7816 RESET
* \return 1 if the Pin RstMC is high; otherwise 0.
*/
uint8_t ISO7816_StatusReset( void )
{
return PIO_Get(&st_pinIso7816RstMC);
}
/**
* cold reset
*/
void ISO7816_cold_reset( void )
{
volatile uint32_t i;
/* tb: wait 400 cycles*/
for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
}
BOARD_ISO7816_BASE_USART->US_RHR;
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
ISO7816_IccPowerOn();
}
/**
* Warm reset
*/
void ISO7816_warm_reset( void )
{
volatile uint32_t i;
ISO7816_IccPowerOff();
/* tb: wait 400 cycles */
for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
}
BOARD_ISO7816_BASE_USART->US_RHR;
BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
ISO7816_IccPowerOn();
}
/**
* Decode ATR trace
* \param pAtr pointer on ATR buffer
*/
void ISO7816_Decode_ATR( uint8_t* pAtr )
{
uint32_t i;
uint32_t j;
uint32_t y;
uint8_t offset;
printf("\n\r");
printf("ATR: Answer To Reset:\n\r");
printf("TS = 0x%X Initial character ",pAtr[0]);
if( pAtr[0] == 0x3B ) {
printf("Direct Convention\n\r");
}
else {
if( pAtr[0] == 0x3F ) {
printf("Inverse Convention\n\r");
}
else {
printf("BAD Convention\n\r");
}
}
printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
printf(" Presence further interface byte:\n\r");
if( pAtr[1]&0x80 ) {
printf("TA ");
}
if( pAtr[1]&0x40 ) {
printf("TB ");
}
if( pAtr[1]&0x20 ) {
printf("TC ");
}
if( pAtr[1]&0x10 ) {
printf("TD ");
}
if( pAtr[1] != 0 ) {
printf(" present\n\r");
}
i = 2;
y = pAtr[1] & 0xF0;
/* Read ATR Ti */
offset = 1;
while (y) {
if (y & 0x10) { /* TA[i] */
printf("TA[%d] = 0x%X ", offset, pAtr[i]);
if( offset == 1 ) {
printf("FI = %d ", (pAtr[i]>>8));
printf("DI = %d", (pAtr[i]&0x0F));
}
printf("\n\r");
i++;
}
if (y & 0x20) { /* TB[i] */
printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
i++;
}
if (y & 0x40) { /* TC[i] */
printf("TC[%d] = 0x%X ", offset, pAtr[i]);
if( offset == 1 ) {
printf("Extra Guard Time: N = %d", pAtr[i]);
}
printf("\n\r");
i++;
}
if (y & 0x80) { /* TD[i] */
printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
y = pAtr[i++] & 0xF0;
}
else {
y = 0;
}
offset++;
}
/* Historical Bytes */
printf("Historical bytes:\n\r");
y = pAtr[1] & 0x0F;
for( j=0; j < y; j++ ) {
printf(" 0x%X", pAtr[i]);
if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) { /* ASCII */
printf("(%c) ", pAtr[i]);
}
i++;
}
printf("\n\r\n\r");
}
/** Initializes a ISO driver
* \param pPinIso7816RstMC Pin ISO 7816 Rst MC
*/
void ISO7816_Init( const Pin pPinIso7816RstMC )
{
TRACE_DEBUG("ISO_Init\n\r");
/* Pin ISO7816 initialize */
st_pinIso7816RstMC = pPinIso7816RstMC;
USART_Configure( BOARD_ISO7816_BASE_USART,
US_MR_USART_MODE_IS07816_T_0
| US_MR_USCLKS_MCK
| US_MR_NBSTOP_1_BIT
| US_MR_PAR_EVEN
| US_MR_CHRL_8_BIT
| US_MR_CLKO
| (3<<24), /* MAX_ITERATION */
1,
0);
/* Configure USART */
PMC_EnablePeripheral(BOARD_ISO7816_ID_USART);
/* Disable interrupts */
BOARD_ISO7816_BASE_USART->US_IDR = (uint32_t) -1;
BOARD_ISO7816_BASE_USART->US_FIDI = 372; /* by default */
/* Define the baud rate divisor register */
/* CD = MCK / SCK */
/* SCK = FIDI x BAUD = 372 x 9600 */
/* BOARD_MCK */
/* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (372*9600);
/* Write the Timeguard Register */
BOARD_ISO7816_BASE_USART->US_TTGR = 5;
USART_SetTransmitterEnabled(BOARD_ISO7816_BASE_USART, 1);
USART_SetReceiverEnabled(BOARD_ISO7816_BASE_USART, 1);
}

View File

@@ -0,0 +1,405 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of draw function on LCD, Include draw text, image
* and basic shapes (line, rectangle, circle).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdint.h>
#include <string.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Fills the given LCD buffer with a particular color.
*
* \param color Fill color.
*/
void LCDD_Fill( uint32_t dwColor )
{
uint32_t dw ;
LCD_SetCursor( 0, 0 ) ;
LCD_WriteRAM_Prepare() ;
for ( dw = BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT; dw > 0; dw-- )
{
LCD_WriteRAM( dwColor ) ;
}
}
/**
* \brief Draw a pixel on LCD of given color.
*
* \param x X-coordinate of pixel.
* \param y Y-coordinate of pixel.
* \param color Pixel color.
*/
extern void LCDD_DrawPixel( uint32_t x, uint32_t y, uint32_t color )
{
LCD_SetCursor( x, y ) ;
LCD_WriteRAM_Prepare() ;
LCD_WriteRAM( color ) ;
}
/**
* \brief Read a pixel from LCD.
*
* \param x X-coordinate of pixel.
* \param y Y-coordinate of pixel.
*
* \return color Readed pixel color.
*/
extern uint32_t LCDD_ReadPixel( uint32_t x, uint32_t y )
{
uint32_t color;
LCD_SetCursor(x, y);
LCD_ReadRAM_Prepare();
color = LCD_ReadRAM();
return color;
}
/*
* \brief Draw a line on LCD, horizontal and vertical line are supported.
*
* \param x X-coordinate of line start.
* \param y Y-coordinate of line start.
* \param length line length.
* \param direction line direction: 0 - horizontal, 1 - vertical.
* \param color Pixel color.
*/
extern void LCDD_DrawLine( uint32_t x, uint32_t y, uint32_t length, uint32_t direction, uint32_t color )
{
uint32_t i = 0 ;
LCD_SetCursor( x, y ) ;
if ( direction == DIRECTION_HLINE )
{
LCD_WriteRAM_Prepare() ;
for ( i = 0; i < length; i++ )
{
LCD_WriteRAM( color ) ;
}
}
else
{
for ( i = 0; i < length; i++ )
{
LCD_WriteRAM_Prepare() ;
LCD_WriteRAM( color ) ;
y++ ;
LCD_SetCursor( x, y ) ;
}
}
}
/*
* \brief Draws a rectangle on LCD, at the given coordinates.
*
* \param x X-coordinate of upper-left rectangle corner.
* \param y Y-coordinate of upper-left rectangle corner.
* \param width Rectangle width in pixels.
* \param height Rectangle height in pixels.
* \param color Rectangle color.
*/
extern void LCDD_DrawRectangle( uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color )
{
LCDD_DrawLine(x, y, width, DIRECTION_HLINE, color);
LCDD_DrawLine(x, (y + height), width, DIRECTION_HLINE, color);
LCDD_DrawLine(x, y, height, DIRECTION_VLINE, color);
LCDD_DrawLine((x + width), y, height, DIRECTION_VLINE, color);
}
/*
* \brief Draws a rectangle with fill inside on LCD, at the given coordinates.
*
* \param x X-coordinate of upper-left rectangle corner.
* \param y Y-coordinate of upper-left rectangle corner.
* \param width Rectangle width in pixels.
* \param height Rectangle height in pixels.
* \param color Rectangle color.
*/
extern void LCDD_DrawRectangleWithFill( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor )
{
uint32_t i ;
LCD_SetWindow( dwX, dwY, dwWidth, dwHeight ) ;
LCD_SetCursor( dwX, dwY ) ;
LCD_WriteRAM_Prepare() ;
for ( i = dwWidth * dwHeight; i > 0; i-- )
{
LCD_WriteRAM( dwColor ) ;
}
LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
LCD_SetCursor( 0, 0 ) ;
}
/**
* \brief Draws a circle on LCD, at the given coordinates.
*
* \param x X-coordinate of circle center.
* \param y Y-coordinate of circle center.
* \param r circle radius.
* \param color circle color.
*/
extern void LCDD_DrawCircle( uint32_t x, uint32_t y, uint32_t r, uint32_t color )
{
signed int d; /* Decision Variable */
uint32_t curX; /* Current X Value */
uint32_t curY; /* Current Y Value */
d = 3 - (r << 1);
curX = 0;
curY = r;
while (curX <= curY)
{
LCDD_DrawPixel(x + curX, y + curY, color);
LCDD_DrawPixel(x + curX, y - curY, color);
LCDD_DrawPixel(x - curX, y + curY, color);
LCDD_DrawPixel(x - curX, y - curY, color);
LCDD_DrawPixel(x + curY, y + curX, color);
LCDD_DrawPixel(x + curY, y - curX, color);
LCDD_DrawPixel(x - curY, y + curX, color);
LCDD_DrawPixel(x - curY, y - curX, color);
if (d < 0) {
d += (curX << 2) + 6;
}
else {
d += ((curX - curY) << 2) + 10;
curY--;
}
curX++;
}
}
/**
* \brief Draws a string inside a LCD buffer, at the given coordinates. Line breaks
* will be honored.
*
* \param x X-coordinate of string top-left corner.
* \param y Y-coordinate of string top-left corner.
* \param pString String to display.
* \param color String color.
*/
extern void LCDD_DrawString( uint32_t x, uint32_t y, const uint8_t *pString, uint32_t color )
{
uint32_t xorg = x ;
while ( *pString != 0 )
{
if ( *pString == '\n' )
{
y += gFont.height + 2 ;
x = xorg ;
}
else
{
LCDD_DrawChar( x, y, *pString, color ) ;
x += gFont.width + 2 ;
}
pString++ ;
}
}
/**
* \brief Draws a string inside a LCD buffer, at the given coordinates
* with given background color. Line breaks will be honored.
*
* \param x X-coordinate of string top-left corner.
* \param y Y-coordinate of string top-left corner.
* \param pString String to display.
* \param fontColor String color.
* \param bgColor Background color.
*/
extern void LCDD_DrawStringWithBGColor( uint32_t x, uint32_t y, const char *pString, uint32_t fontColor, uint32_t bgColor )
{
unsigned xorg = x;
while ( *pString != 0 )
{
if ( *pString == '\n' )
{
y += gFont.height + 2 ;
x = xorg ;
}
else
{
LCDD_DrawCharWithBGColor( x, y, *pString, fontColor, bgColor ) ;
x += gFont.width + 2;
}
pString++;
}
}
/**
* \brief Returns the width & height in pixels that a string will occupy on the screen
* if drawn using LCDD_DrawString.
*
* \param pString String.
* \param pWidth Pointer for storing the string width (optional).
* \param pHeight Pointer for storing the string height (optional).
*
* \return String width in pixels.
*/
extern void LCDD_GetStringSize( const uint8_t *pString, uint32_t *pWidth, uint32_t *pHeight )
{
uint32_t width = 0;
uint32_t height = gFont.height;
while ( *pString != 0 )
{
if ( *pString == '\n' )
{
height += gFont.height + 2 ;
}
else
{
width += gFont.width + 2 ;
}
pString++ ;
}
if ( width > 0 )
{
width -= 2;
}
if ( pWidth != NULL )
{
*pWidth = width;
}
if ( pHeight != NULL )
{
*pHeight = height ;
}
}
/*
* \brief Draw a raw image at given position on LCD.
*
* \param x X-coordinate of image start.
* \param y Y-coordinate of image start.
* \param pImage Image buffer.
* \param width Image width.
* \param height Image height.
*/
void LCDD_DrawImage( uint32_t dwX, uint32_t dwY, const uint8_t *pImage, uint32_t dwWidth, uint32_t dwHeight )
{
uint32_t dwCursor ;
LCD_SetWindow( dwX, dwY, dwWidth, dwHeight ) ;
LCD_SetCursor( dwX, dwY ) ;
LCD_WriteRAM_Prepare() ;
for ( dwCursor=dwWidth*dwHeight; dwCursor != 0; dwCursor-- )
{
LCD_D() = *pImage++ ;
LCD_D() = *pImage++ ;
LCD_D() = *pImage++ ;
}
LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
}
/*
* \brief Draw a raw image at given position on LCD.
*
* \param dwX X-coordinate of image start.
* \param dwY Y-coordinate of image start.
* \param pGIMPImage Image data.
*/
void LCDD_DrawGIMPImage( uint32_t dwX, uint32_t dwY, const SGIMPImage* pGIMPImage )
{
uint32_t dw ;
register uint32_t dwLength ;
uint8_t* pucData ;
// Draw raw RGB bitmap
LCD_SetWindow( dwX, dwY, pGIMPImage->dwWidth, pGIMPImage->dwHeight ) ;
LCD_SetCursor( dwX, dwY ) ;
LCD_WriteRAM_Prepare() ;
dwLength = pGIMPImage->dwWidth*pGIMPImage->dwHeight ;
pucData = pGIMPImage->pucPixel_data ;
for ( dw=0; dw < dwLength; dw++ )
{
LCD_D() = (*pucData++) ;
LCD_D() = (*pucData++) ;
LCD_D() = (*pucData++) ;
}
LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
}
/*
* \brief Clear a window with an color.
*
* \param dwX X-coordinate of the window.
* \param dwY Y-coordinate of the window.
* \param dwWidth window width.
* \param dwHeight window height.
* \param dwColor background color
*/
extern void LCDD_ClearWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor )
{
uint32_t dw ;
LCD_SetCursor( dwX, dwY) ;
LCD_WriteRAM_Prepare() ;
for ( dw = dwWidth * dwHeight; dw > 0; dw-- )
{
LCD_WriteRAM( dwColor ) ;
}
}

View File

@@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of draw font on LCD.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Global variable describing the font being instancied. */
const Font gFont = {10, 14};
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Draws an ASCII character on LCD.
*
* \param x X-coordinate of character upper-left corner.
* \param y Y-coordinate of character upper-left corner.
* \param c Character to output.
* \param color Character color.
*/
extern void LCDD_DrawChar( uint32_t x, uint32_t y, uint8_t c, uint32_t color )
{
uint32_t row, col ;
assert( (c >= 0x20) && (c <= 0x7F) ) ;
for ( col = 0 ; col < 10 ; col++ )
{
for ( row = 0 ; row < 8 ; row++ )
{
if ( (pCharset10x14[((c - 0x20) * 20) + col * 2] >> (7 - row)) & 0x1 )
{
LCDD_DrawPixel( x+col, y+row, color ) ;
}
}
for (row = 0; row < 6; row++ )
{
if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1)
{
LCDD_DrawPixel( x+col, y+row+8, color ) ;
}
}
}
}
/**
* \brief Draws an ASCII character on LCD with given background color.
*
* \param x X-coordinate of character upper-left corner.
* \param y Y-coordinate of character upper-left corner.
* \param c Character to output.
* \param fontColor Character color.
* \param bgColor Background color.
*/
extern void LCDD_DrawCharWithBGColor( uint32_t x, uint32_t y, uint8_t c, uint32_t fontColor, uint32_t bgColor )
{
uint32_t row, col ;
assert( (c >= 0x20) && (c <= 0x7F) ) ;
for (col = 0; col < 10; col++)
{
for (row = 0 ; row < 8 ; row++)
{
if ( (pCharset10x14[((c - 0x20) * 20) + col * 2] >> (7 - row)) & 0x1 )
{
LCDD_DrawPixel( x+col, y+row, fontColor ) ;
}
else
{
LCDD_DrawPixel( x+col, y+row, bgColor ) ;
}
}
for ( row = 0 ; row < 6 ; row++ )
{
if ( (pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1 )
{
LCDD_DrawPixel( x+col, y+row+8, fontColor ) ;
}
else
{
LCDD_DrawPixel( x+col, y+row+8, bgColor ) ;
}
}
}
}

View File

@@ -0,0 +1,233 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Font 10x14 table definition.
*
*/
#include "board.h"
/** Char set of font 10x14 */
const uint8_t pCharset10x14[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC,
0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0xC0, 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0,
0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0x60, 0x1E, 0x70, 0x3F, 0x30, 0x33, 0x30, 0xFF, 0xFC,
0xFF, 0xFC, 0x33, 0x30, 0x33, 0xF0, 0x39, 0xE0, 0x18, 0xC0,
0x60, 0x00, 0xF0, 0x0C, 0xF0, 0x3C, 0x60, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x18, 0xF0, 0x3C, 0xC0, 0x3C, 0x00, 0x18,
0x3C, 0xF0, 0x7F, 0xF8, 0xC3, 0x1C, 0xC7, 0x8C, 0xCF, 0xCC,
0xDC, 0xEC, 0x78, 0x78, 0x30, 0x30, 0x00, 0xFC, 0x00, 0xCC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xEC, 0x00,
0xF8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x3F, 0xF0, 0x78, 0x78,
0x60, 0x18, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0x60, 0x18,
0x78, 0x78, 0x3F, 0xF0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x3F, 0xF8,
0x3F, 0xF8, 0x03, 0x80, 0x07, 0xC0, 0x0E, 0xE0, 0x0C, 0x60,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0,
0x3F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x00, 0x44, 0x00, 0xEC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x00, 0x18, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0xFC, 0xC1, 0xCC, 0xC3, 0x8C,
0xC7, 0x0C, 0xCE, 0x0C, 0xFC, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x70, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0C, 0x70, 0x1C, 0xE0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC,
0xC1, 0xCC, 0xC3, 0x8C, 0xE7, 0x0C, 0x7E, 0x0C, 0x3C, 0x0C,
0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x7F, 0xF8, 0x3C, 0xF0,
0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, 0x38, 0xC0,
0x70, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xC0, 0x00, 0xC0,
0xFC, 0x30, 0xFC, 0x38, 0xCC, 0x1C, 0xCC, 0x0C, 0xCC, 0x0C,
0xCC, 0x0C, 0xCC, 0x0C, 0xCE, 0x1C, 0xC7, 0xF8, 0xC3, 0xF0,
0x3F, 0xF0, 0x7F, 0xF8, 0xE3, 0x1C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x9C, 0x71, 0xF8, 0x30, 0xF0,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC3, 0xFC,
0xC7, 0xFC, 0xCE, 0x00, 0xDC, 0x00, 0xF8, 0x00, 0xF0, 0x00,
0x3C, 0xF0, 0x7F, 0xF8, 0xE7, 0x9C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
0x3C, 0x00, 0x7E, 0x00, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x1C,
0xC3, 0x38, 0xC3, 0x70, 0xE7, 0xE0, 0x7F, 0xC0, 0x3F, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x3C, 0xF0,
0x3C, 0xF0, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x44, 0x3C, 0xEC,
0x3C, 0xF8, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0,
0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0x00, 0x00,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x00, 0x00, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x38, 0x70,
0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
0x30, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC1, 0xEC,
0xC3, 0xEC, 0xC3, 0x00, 0xE6, 0x00, 0x7E, 0x00, 0x3C, 0x00,
0x30, 0xF0, 0x71, 0xF8, 0xE3, 0x9C, 0xC3, 0x0C, 0xC3, 0xFC,
0xC3, 0xFC, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0x3F, 0xFC, 0x7F, 0xFC, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xC0, 0x7F, 0xFC, 0x3F, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30,
0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x73, 0xF8, 0x33, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x00, 0x38, 0xC0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xFC, 0xFF, 0xFC, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0,
0x1C, 0xE0, 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x70, 0x00, 0x38, 0x00, 0x1F, 0x00,
0x1F, 0x00, 0x38, 0x00, 0x70, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0xFF, 0xFC, 0xFF, 0xFC,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
0xC3, 0x00, 0xC3, 0x00, 0xE7, 0x00, 0x7E, 0x00, 0x3C, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0xCC,
0xC0, 0xEC, 0xC0, 0x7C, 0xE0, 0x38, 0x7F, 0xFC, 0x3F, 0xEC,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x80, 0xC3, 0x80,
0xC3, 0xC0, 0xC3, 0xC0, 0xE7, 0x70, 0x7E, 0x3C, 0x3C, 0x1C,
0x3C, 0x18, 0x7E, 0x1C, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x9C, 0xE1, 0xF8, 0x60, 0xF0,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xFC,
0xFF, 0xFC, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0xFF, 0xE0, 0xFF, 0xC0,
0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x3C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
0xF0, 0x3C, 0xF8, 0x7C, 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80,
0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, 0xF8, 0x7C, 0xF0, 0x3C,
0xFC, 0x00, 0xFE, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xFC,
0x01, 0xFC, 0x03, 0x80, 0x07, 0x00, 0xFE, 0x00, 0xFC, 0x00,
0xC0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC, 0xC1, 0xCC, 0xC3, 0x8C,
0xC7, 0x0C, 0xCE, 0x0C, 0xDC, 0x0C, 0xF8, 0x0C, 0xF0, 0x0C,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x03, 0x00,
0x03, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x30,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x06, 0x78, 0x0E, 0xFC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xCC, 0x07, 0xFC, 0x03, 0xF8,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C,
0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9C, 0x01, 0xF8, 0x00, 0xF0,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0x30,
0x00, 0xF0, 0x01, 0xF8, 0x03, 0x9C, 0x03, 0x0C, 0x03, 0x0C,
0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0xFF, 0xFC, 0xFF, 0xFC,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0xDC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xDC, 0x07, 0xD8, 0x03, 0x90,
0x00, 0x00, 0x03, 0x00, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x00,
0xE3, 0x00, 0x70, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xDC, 0x0F, 0xF8, 0x07, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x80, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFC,
0x1B, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x1C, 0xCF, 0xF8, 0xCF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xE0, 0x01, 0xE0,
0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x0F, 0xFC, 0x0F, 0xFC, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xC0,
0x03, 0xC0, 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xFC, 0x0F, 0xFC,
0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x00,
0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0xFC, 0x03, 0xFC,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0xF8, 0x03, 0xF0,
0x0F, 0xFC, 0x0F, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00,
0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xFC, 0x0F, 0xFC,
0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00,
0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x00,
0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xFC, 0x0E, 0x78, 0x06, 0x30,
0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFF, 0xF0, 0xFF, 0xF8,
0x0C, 0x1C, 0x0C, 0x1C, 0x0C, 0x38, 0x0C, 0x30, 0x00, 0x00,
0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x0F, 0xE0, 0x0F, 0xC0,
0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0xF0, 0x01, 0xE0,
0x01, 0xE0, 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C,
0x0C, 0x00, 0x0E, 0x00, 0x07, 0x0C, 0x03, 0x9C, 0x01, 0xF8,
0x01, 0xF0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00,
0x0C, 0x0C, 0x0C, 0x1C, 0x0C, 0x3C, 0x0C, 0x7C, 0x0C, 0xEC,
0x0D, 0xCC, 0x0F, 0x8C, 0x0F, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C,
0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x3F, 0xF0, 0x7C, 0xF8,
0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00,
0x03, 0x0C, 0x03, 0x0C, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x0C,
0xC3, 0x0C, 0xC0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C,
0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C,
0x7C, 0xF8, 0x3F, 0xF0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC
} ;

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of LCD driver, Include LCD initialization,
* LCD on/off and LCD backlight control.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes the LCD controller.
* Configure SMC to access LCD controller at 64MHz MCK.
*/
extern void LCDD_Initialize( void )
{
const Pin pPins[] = {BOARD_LCD_PINS};
Smc *pSmc = SMC;
/* Enable pins */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Enable peripheral clock */
PMC_EnablePeripheral( ID_SMC ) ;
/* EBI SMC Configuration */
pSmc->SMC_CS_NUMBER[1].SMC_SETUP = SMC_SETUP_NWE_SETUP(2)
| SMC_SETUP_NCS_WR_SETUP(2)
| SMC_SETUP_NRD_SETUP(2)
| SMC_SETUP_NCS_RD_SETUP(2);
pSmc->SMC_CS_NUMBER[1].SMC_PULSE = SMC_PULSE_NWE_PULSE(4)
| SMC_PULSE_NCS_WR_PULSE(4)
| SMC_PULSE_NRD_PULSE(10)
| SMC_PULSE_NCS_RD_PULSE(10);
pSmc->SMC_CS_NUMBER[1].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(10)
| SMC_CYCLE_NRD_CYCLE(22);
pSmc->SMC_CS_NUMBER[1].SMC_MODE = SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE
| SMC_MODE_DBW_8_BIT;
/* Initialize LCD controller */
LCD_Initialize() ;
/* Initialize LCD controller */
LCD_SetDisplayPortrait( 0 ) ;
/* Set LCD backlight */
LCDD_SetBacklight( 2 ) ;
}
/**
* \brief Turn on the LCD.
*/
void LCDD_On(void)
{
LCD_On();
}
/**
* \brief Turn off the LCD.
*/
void LCDD_Off(void)
{
LCD_Off();
}
/**
* \brief Set the backlight of the LCD.
*
* \param level Backlight brightness level [1..16], 1 means maximum brightness.
*/
void LCDD_SetBacklight (uint32_t level)
{
uint32_t i;
const Pin pPins[] = {BOARD_BACKLIGHT_PIN};
/* Ensure valid level */
level = (level < 1) ? 1 : level;
level = (level > 16) ? 16 : level;
/* Enable pins */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Switch off backlight */
PIO_Clear(pPins);
i = 600 * (BOARD_MCK / 1000000); /* wait for at least 500us */
while(i--);
/* Set new backlight level */
for (i = 0; i < level; i++) {
PIO_Clear(pPins);
PIO_Clear(pPins);
PIO_Clear(pPins);
PIO_Set(pPins);
PIO_Set(pPins);
PIO_Set(pPins);
}
}

View File

@@ -0,0 +1,168 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
/*------------------------------------------------------------------------------
* Local Variables
*------------------------------------------------------------------------------*/
#ifdef PINS_LEDS
static const Pin pinsLeds[] = { PINS_LEDS } ;
static const uint32_t numLeds = PIO_LISTSIZE( pinsLeds ) ;
#endif
/*------------------------------------------------------------------------------
* Global Functions
*------------------------------------------------------------------------------*/
/**
* Configures the pin associated with the given LED number. If the LED does
* not exist on the board, the function does nothing.
* \param led Number of the LED to configure.
* \return 1 if the LED exists and has been configured; otherwise 0.
*/
extern uint32_t LED_Configure( uint32_t dwLed )
{
#ifdef PINS_LEDS
// Check that LED exists
if ( dwLed >= numLeds)
{
return 0;
}
// Configure LED
return ( PIO_Configure( &pinsLeds[dwLed], 1 ) ) ;
#else
return 0 ;
#endif
}
/**
* Turns the given LED on if it exists; otherwise does nothing.
* \param led Number of the LED to turn on.
* \return 1 if the LED has been turned on; 0 otherwise.
*/
extern uint32_t LED_Set( uint32_t dwLed )
{
#ifdef PINS_LEDS
/* Check if LED exists */
if ( dwLed >= numLeds )
{
return 0 ;
}
/* Turn LED on */
if ( pinsLeds[dwLed].type == PIO_OUTPUT_0 )
{
PIO_Set( &pinsLeds[dwLed] ) ;
}
else
{
PIO_Clear( &pinsLeds[dwLed] ) ;
}
return 1 ;
#else
return 0 ;
#endif
}
/**
* Turns a LED off.
*
* \param led Number of the LED to turn off.
* \return 1 if the LED has been turned off; 0 otherwise.
*/
extern uint32_t LED_Clear( uint32_t dwLed )
{
#ifdef PINS_LEDS
/* Check if LED exists */
if ( dwLed >= numLeds )
{
return 0 ;
}
/* Turn LED off */
if ( pinsLeds[dwLed].type == PIO_OUTPUT_0 )
{
PIO_Clear( &pinsLeds[dwLed] ) ;
}
else
{
PIO_Set( &pinsLeds[dwLed] ) ;
}
return 1 ;
#else
return 0 ;
#endif
}
/**
* Toggles the current state of a LED.
*
* \param led Number of the LED to toggle.
* \return 1 if the LED has been toggled; otherwise 0.
*/
extern uint32_t LED_Toggle( uint32_t dwLed )
{
#ifdef PINS_LEDS
/* Check if LED exists */
if ( dwLed >= numLeds )
{
return 0 ;
}
/* Toggle LED */
if ( PIO_GetOutputDataStatus( &pinsLeds[dwLed] ) )
{
PIO_Clear( &pinsLeds[dwLed] ) ;
}
else
{
PIO_Set( &pinsLeds[dwLed] ) ;
}
return 1 ;
#else
return 0 ;
#endif
}

View File

@@ -0,0 +1,95 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
/**
* Returns the minimum value between two integers.
*
* \param a First integer to compare.
* \param b Second integer to compare.
*/
extern uint32_t min( uint32_t dwA, uint32_t dwB )
{
if ( dwA < dwB )
{
return dwA ;
}
else
{
return dwB ;
}
}
/*------------------------------------------------------------------------------
* Returns the absolute value of an integer.
*
* \param value Integer value.
*
* \note Do not call this function "abs", problem with gcc !
*/
extern uint32_t absv( int32_t lValue )
{
if ( lValue < 0 )
{
return -lValue ;
}
else
{
return lValue ;
}
}
/*------------------------------------------------------------------------------
* Computes and returns x power of y.
*
* \param x Value.
* \param y Power.
*/
extern uint32_t power( uint32_t dwX, uint32_t dwY )
{
uint32_t dwResult = 1 ;
while ( dwY > 0 )
{
dwResult *= dwX ;
dwY-- ;
}
return dwResult ;
}

View File

@@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "board.h"
/*------------------------------------------------------------------------------
* Global Variables
*------------------------------------------------------------------------------*/
static uint32_t _dwRandNext=1 ;
/*------------------------------------------------------------------------------
* Exported Functions
*------------------------------------------------------------------------------*/
/**
* Initialize the seed for rand generator.
*
* \param seed rand initiation seed
*/
extern void srand( uint32_t dwSeed )
{
_dwRandNext = dwSeed ;
}
/**
* Return a random number, maxinum assumed to be 65536
*/
extern int rand( void )
{
_dwRandNext = _dwRandNext * 1103515245 + 12345 ;
return (uint32_t)(_dwRandNext/131072) % 65536 ;
}

View File

@@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
* This file Configures the target-dependent low level functions for character I/O.
*/
#include "board.h"
#include <stdio.h>
/* Disable semihosting */
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle;} ;
FILE __stdout;
FILE __stderr;
/*------------------------------------------------------------------------------
* Outputs a character.
*------------------------------------------------------------------------------*/
int fputc(int ch, FILE *f)
{
if ((f == stdout) || (f == stderr))
{
UART_PutChar( ch ) ;
return ch ;
}
else
{
return EOF ;
}
}
/*------------------------------------------------------------------------------
* Returns the error status accumulated during file I/O.
*------------------------------------------------------------------------------*/
int ferror( FILE *f )
{
return EOF ;
}
void _ttywrch( int ch )
{
UART_PutChar( (uint8_t)ch ) ;
}
void _sys_exit(int return_code)
{
while ( 1 ) ; /* endless loop */
}
/*------------------------------------------------------------------------------
* Low level functions I/O for assert().
*------------------------------------------------------------------------------*/
void __assert_puts(const char *str)
{
printf("%s", str);
}

View File

@@ -111,18 +111,18 @@ extern int _read(int file, char *ptr, int len)
extern int _write( int file, char *ptr, int len )
{
//int iIndex ;
/*
int iIndex ;
// for ( ; *ptr != 0 ; ptr++ )
/* for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ )
for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ )
{
UART_PutChar( *ptr ) ;
}
return iIndex ;
*/
return 0;
*/
return -1;
}
extern void _exit( int status )

View File

@@ -0,0 +1,117 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
* Implement simple system tick usage.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Tick Counter united by ms */
static volatile uint32_t _dwTickCount=0 ;
/*----------------------------------------------------------------------------
* Exported Functions
*----------------------------------------------------------------------------*/
/**
* \brief Handler for Sytem Tick interrupt.
*/
extern void TimeTick_Increment( void )
{
_dwTickCount++ ;
}
/**
* \brief Configures the SAM3 SysTick & reset tickCount.
* Systick interrupt handler will generates 1ms interrupt and increase a
* tickCount.
* \param new_mck Current master clock.
*/
extern uint32_t TimeTick_Configure( uint32_t new_mck )
{
_dwTickCount = 0 ;
return SysTick_Config( new_mck/1000 ) ;
}
/**
* \brief Get current Tick Count, in ms.
*/
extern uint32_t GetTickCount( void )
{
return _dwTickCount ;
}
/**
* \brief Sync Wait for several ms
*/
extern void Wait( volatile uint32_t dwMs )
{
uint32_t dwStart ;
uint32_t dwCurrent ;
dwStart = _dwTickCount ;
do
{
dwCurrent = _dwTickCount ;
} while ( dwCurrent - dwStart < dwMs ) ;
}
/**
* \brief Sync Sleep for several ms
*/
extern void Sleep( volatile uint32_t dwMs )
{
uint32_t dwStart ;
uint32_t dwCurrent ;
dwStart = _dwTickCount ;
do
{
dwCurrent = _dwTickCount ;
if ( dwCurrent - dwStart > dwMs )
{
break ;
}
__WFI() ;
} while( 1 ) ;
}

View File

@@ -0,0 +1,59 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
/** Trace level can be set at applet initialization */
#if !defined(NOTRACE) && (DYN_TRACES == 1)
uint32_t dwTraceLevel = TRACE_LEVEL ;
#endif
/**
* Initializes the U(S)ART Console
*
* \param dwBaudRate U(S)ART baudrate.
* \param dwMCk Master clock frequency.
*/
extern void TRACE_CONFIGURE( uint32_t dwBaudRate, uint32_t dwMCk )
{
const Pin pinsUART0[] = { PINS_UART } ;
PIO_Configure( pinsUART0, PIO_LISTSIZE( pinsUART0 ) ) ;
UART_Configure( dwBaudRate, dwMCk ) ;
}

View File

@@ -0,0 +1,317 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of ADS7843 driver.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#ifdef BOARD_TSC_ADS7843
#include <stdint.h>
#include <string.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/** Delay for pushbutton debouncing (the time-base is 10 ms). */
#define DEBOUNCE_TIME 6 /* 10 * 6 = 60 ms */
/** Color of calibration points. */
#define POINTS_COLOR 0x0000FF
/** Size in pixels of calibration points. */
#define POINTS_SIZE 4
/** Maximum difference in pixels between the test point and the measured point. */
#define POINTS_MAX_ERROR 5
/*----------------------------------------------------------------------------
* Types
*----------------------------------------------------------------------------*/
/** pen state */
typedef enum {
STATE_PEN_RELEASED = 0,
STATE_PEN_PRESSED = 1,
STATE_PEN_DEBOUNCE = 2
} e_pen_state;
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Pins used by Interrupt Signal for Touch Screen Controller */
static const Pin pinPenIRQ = PIN_TSC_IRQ;
/** Global timestamp in milliseconds since start of application. */
static volatile uint32_t timestamp = 0;
/** last time when the pen is pressed on the touchscreen */
static volatile uint32_t timePress = 0;
/** last time when the pen is released */
static volatile uint32_t timeRelease = 0;
/** pen state */
static volatile e_pen_state penState = STATE_PEN_RELEASED;
/** Touch screen initiallized flag */
static uint32_t tsInitFlag = 0;
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Timer handler for touch screen. Increments the timestamp counter.
* Determine the state "Pen Pressed" or "Pen Released". To change state,
* the penIRQ has to keep the same value during DEBOUNCE_TIME.
*
* \note External timer interrupt should call it per 10ms.
*/
void TSD_TimerHandler( void )
{
uint32_t data[2];
uint32_t timeKeep;
static uint32_t point[2];
if (!tsInitFlag) return;
timestamp++;
/* Get the current position of the pen if penIRQ has low value (pen pressed) */
if ( PIO_Get(&pinPenIRQ) == 0 )
{
/* Get the current position of the pressed pen */
if ( TSDCom_IsCalibrationOk() )
{
TSD_GetRawMeasurement(data);
TSDCom_InterpolateMeasurement(data, point);
}
/* call the callback function */
if ( penState == STATE_PEN_PRESSED )
{
if(TSDCom_IsCalibrationOk())
{
TSD_PenMoved(point[0], point[1]);
}
}
}
/* Determine the pen state */
if ( PIO_Get( &pinPenIRQ ) == 0 )
{
/* reinit the last time when release */
timeRelease = timestamp;
if ( penState == STATE_PEN_DEBOUNCE )
{
timeKeep = timestamp;
timeKeep -= timePress;
if(timeKeep > DEBOUNCE_TIME)
{
/* pen is pressed during an enough time : the state change */
penState = STATE_PEN_PRESSED;
/* call the callback function */
if ( TSDCom_IsCalibrationOk() )
{
TSD_PenPressed(point[0], point[1]);
}
}
}
}
else
{
/* reinit the last time when release */
timePress = timestamp;
if ( penState == STATE_PEN_DEBOUNCE )
{
timeKeep = timestamp;
timeKeep -= timeRelease;
if ( timeKeep > DEBOUNCE_TIME )
{
/* pen is released during an enough time : the state change */
penState = STATE_PEN_RELEASED;
/* call the callback function */
if ( TSDCom_IsCalibrationOk() )
{
TSD_PenReleased(point[0], point[1]);
}
}
}
}
}
/**
* \breif Interrupt handler for Touchscreen.
*/
static void ISR_PenIRQ( void )
{
/* Check if the pen has been pressed */
if ( !PIO_Get( &pinPenIRQ ) )
{
if ( penState == STATE_PEN_RELEASED )
{
timePress = timestamp;
penState = STATE_PEN_DEBOUNCE;
}
}
else
{
if ( penState == STATE_PEN_PRESSED )
{
timeRelease = timestamp;
penState = STATE_PEN_DEBOUNCE;
}
}
}
/**
* \brief Configure PENIRQ for interrupt.
*
* \note Be sure the PIO interrupt management has been initialized by
* PIO_InitializeInterrupts() before call this function.
*/
static void ConfigurePenIRQ( void )
{
/* Configure pios */
PIO_Configure(&pinPenIRQ, PIO_LISTSIZE(pinPenIRQ));
/* Initialize interrupts */
PIO_ConfigureIt(&pinPenIRQ, (void (*)(const Pin *)) ISR_PenIRQ);
/* Enable the interrupt */
PIO_EnableIt(&pinPenIRQ);
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Reads and store a touchscreen measurement in the provided array.
*
* \param pData Array where the measurements will be stored
*/
extern void TSD_GetRawMeasurement( uint32_t* pdwData )
{
/* Get the current position of the pressed pen */
PIO_DisableIt( &pinPenIRQ ) ;
ADS7843_GetPosition( &pdwData[0], &pdwData[1] ) ;
PIO_EnableIt( &pinPenIRQ ) ;
}
/**
* \brief Wait pen pressed.
*/
extern void TSD_WaitPenPressed( void )
{
/* Wait for touch & end of conversion */
while ( penState != STATE_PEN_RELEASED ) ;
/* while (penState != STATE_PEN_PRESSED); */
while ( penState != STATE_PEN_PRESSED )
{
}
}
/**
* \brief Wait pen released.
*/
extern void TSD_WaitPenReleased( void )
{
/* Wait for contact loss */
while (penState != STATE_PEN_PRESSED);
while (penState != STATE_PEN_RELEASED);
}
/**
* \brief Do calibration.
*
* \return 1 if calibration is Ok, 0 else.
*/
extern uint8_t TSD_Calibrate( void )
{
uint8_t ret = 0 ;
/* Calibration is done only once */
if ( TSDCom_IsCalibrationOk() )
{
return 1;
}
/* Do calibration */
ret = TSDCom_Calibrate();
return ret;
}
/**
* \brief Initializes the touchscreen driver and starts the calibration process. When
* finished, the touchscreen is operational.
*
* \note Important: the LCD driver must have been initialized prior to calling this
* function.
*/
extern void TSD_Initialize( int8_t calEn )
{
ADS7843_Initialize();
ConfigurePenIRQ();
tsInitFlag = 1;
/* Calibration */
if(calEn) {
while (!TSD_Calibrate());
}
}
/**
* \brief Stop the Touchscreen, disable interrupt.
*/
extern void TSD_Reset( void )
{
/* Disable SPI 0 */
ADS7843_Reset() ;
/* Disable the interrupt */
PIO_DisableIt( &pinPenIRQ ) ;
}
#endif /* #ifdef BOARD_TSC_ADS7843 */

View File

@@ -0,0 +1,369 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of touchscreen driver device irrelevance code.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/** Size in pixels of calibration points. */
#define POINTS_SIZE 4
/** Maximum difference in pixels between the test point and the measured point. */
#define POINTS_MAX_ERROR 8
/** Delay at the end of calibartion for result display */
#define DELAY_RESULT_DISPLAY 4000000
/*----------------------------------------------------------------------------
* Types
*----------------------------------------------------------------------------*/
/** \brief Point used during the touchscreen calibration process. */
typedef struct _CalibrationPoint {
/** Coordinate of point along the X-axis of the screen. */
uint32_t x;
/** Coordinate of point along the Y-axis of the screen. */
uint32_t y;
/** Calibration data of point. */
uint32_t data[2];
} CalibrationPoint;
/*----------------------------------------------------------------------------
* Variables
*----------------------------------------------------------------------------*/
/** indicates if the touch screen has been calibrated. */
/** If not, Callback functions are not called. */
static volatile uint8_t bCalibrationOk = 0;
/** Slope for interpoling touchscreen measurements along the X-axis. */
static int32_t xSlope;
/** Slope for interpoling touchscreen measurements along the Y-axis. */
static int32_t ySlope;
/** Calibration points. */
static CalibrationPoint calibrationPoints[] = {
/* Top-left corner calibration point */
{
BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT / 10,
{0, 0}
},
/* Top-right corner calibration point */
{
BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT / 10,
{0, 0}
},
/* Bottom-right corner calibration point */
{
BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10,
{0, 0}
},
/* Bottom-left corner calibration point */
{
BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10,
{0, 0}
}
};
/** Test point */
static const CalibrationPoint testPoint = {
BOARD_LCD_WIDTH / 2,
BOARD_LCD_HEIGHT / 2,
{0, 0}
};
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Display a calibration point on the given buffer.
*
* \param pPoint Calibration point to display.
*/
static void DrawCalibrationPoint(const CalibrationPoint *pPoint)
{
LCDD_DrawRectangleWithFill(pPoint->x - POINTS_SIZE / 2,
pPoint->y - POINTS_SIZE / 2,
POINTS_SIZE,
POINTS_SIZE,
COLOR_RED);
}
/**
* \brief Clears a calibration point from the given buffer.
*
* \param pPoint Calibration point to clear.
*/
static void ClearCalibrationPoint(const CalibrationPoint *pPoint)
{
LCDD_DrawRectangleWithFill(pPoint->x - POINTS_SIZE / 2,
pPoint->y - POINTS_SIZE / 2,
POINTS_SIZE,
POINTS_SIZE,
COLOR_WHITE);
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Indicates if the calibration of the touch screen is Ok.
*
* \return 1 calibration Ok, 0 if not.
*/
uint8_t TSDCom_IsCalibrationOk(void)
{
if (bCalibrationOk == 1) {
return 1;
} else {
return 0;
}
}
/**
* \brief Interpolates the provided raw measurements using the previously calculated
* slope. The resulting x and y coordinates are stored in an array.
*
* \param pData Raw measurement data, as returned by TSD_GetRawMeasurement().
* \param pPoint Array in which x and y will be stored.
*/
void TSDCom_InterpolateMeasurement(const uint32_t *pData, uint32_t *pPoint)
{
pPoint[0] = calibrationPoints[0].x
- (((int32_t) calibrationPoints[0].data[0] - (int32_t) pData[0]) * 1024)
/ xSlope;
pPoint[1] = calibrationPoints[0].y
- (((int32_t) calibrationPoints[0].data[1] - (int32_t) pData[1]) * 1024)
/ ySlope;
if(pPoint[0] & 0x80000000) /* Is pPoint[0] negative ? */
{
pPoint[0] = 0;
}
if(pPoint[0] > BOARD_LCD_WIDTH) /* Is pPoint[0] bigger than the LCD width ? */
{
pPoint[0] = BOARD_LCD_WIDTH;
}
if(pPoint[1] & 0x80000000) /* Is pPoint[1] negative ? */
{
pPoint[1] = 0;
}
if(pPoint[1] > BOARD_LCD_HEIGHT) /* Is pPoint[1] bigger than the LCD width ? */
{
pPoint[1] = BOARD_LCD_HEIGHT;
}
}
/**
* \brief Performs the calibration process using the provided buffer to display
* information.
*
* \return True if calibration was successful; otherwise false.
*/
uint8_t TSDCom_Calibrate(void)
{
volatile uint32_t i; /* to keep the tempo with gcc code optimisation */
int32_t slope1, slope2;
CalibrationPoint measuredPoint;
uint8_t xOk, yOk;
int32_t xDiff, yDiff;
/* Calibration setup */
LCDD_Fill(COLOR_WHITE);
LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK);
LCDD_DrawString(1, 140, (uint8_t *)"Touch the dots to\ncalibrate the screen", COLOR_DARKBLUE);
/* Calibration points */
for (i=0; i < 4; i++) {
DrawCalibrationPoint(&calibrationPoints[i]);
/* Wait for touch & end of conversion */
TSD_WaitPenPressed();
TSD_GetRawMeasurement(calibrationPoints[i].data);
ClearCalibrationPoint(&calibrationPoints[i]);
/* Wait for contact loss */
TSD_WaitPenReleased();
}
/**
* Calculate slopes using the calibration data
* Theory behind those calculations:
* - We suppose the touchscreen measurements are linear, so the following equations are true (simple
* linear regression) for any two 'a' and 'b' points of the screen:
* dx = (a.data[0] - b.data[0]) / (a.x - b.x)
* dy = (a.data[1] - b.data[1]) / (a.y - b.y)
*
* - We calculate dx and dy (called xslope and yslope here) using the calibration points.
*
* - We can then use dx and dy to infer the position of a point 'p' given the measurements performed
* by the touchscreen ('c' is any of the calibration points):
* dx = (p.data[0] - c.data[0]) / (p.x - c.x)
* dy = (p.data[1] - c.data[1]) / (p.y - c.y)
* Thus:
* p.x = c.x - (p.data[0] - c.data[0]) / dx
* p.y = c.y - (p.data[1] - c.data[1]) / dy
*
* - Since there are four calibration points, dx and dy can be calculated twice, so we average
* the two values.
*/
slope1 = ((int32_t) calibrationPoints[0].data[0]) - ((int32_t) calibrationPoints[1].data[0]);
slope1 *= 1024;
slope1 /= ((int32_t) calibrationPoints[0].x) - ((int32_t) calibrationPoints[1].x);
slope2 = ((int32_t) calibrationPoints[2].data[0]) - ((int32_t) calibrationPoints[3].data[0]);
slope2 *= 1024;
slope2 /= ((int32_t) calibrationPoints[2].x) - ((int32_t) calibrationPoints[3].x);
xSlope = (slope1 + slope2) / 2;
slope1 = ((int32_t) calibrationPoints[0].data[1]) - ((int32_t) calibrationPoints[2].data[1]);
slope1 *= 1024;
slope1 /= ((int32_t) calibrationPoints[0].y) - ((int32_t) calibrationPoints[2].y);
slope2 = ((int32_t) calibrationPoints[1].data[1]) - ((int32_t) calibrationPoints[3].data[1]);
slope2 *= 1024;
slope2 /= ((int32_t) calibrationPoints[1].y) - ((int32_t) calibrationPoints[3].y);
ySlope = (slope1 + slope2) / 2;
/* Test point */
LCDD_Fill(0xFFFFFF);
LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK);
LCDD_DrawString(1, 100, (uint8_t *)" Touch the point to\nvalidate calibration", COLOR_DARKBLUE);
DrawCalibrationPoint(&testPoint);
/* Wait for touch & end of conversion */
TSD_WaitPenPressed();
TSD_GetRawMeasurement(measuredPoint.data);
TSDCom_InterpolateMeasurement(measuredPoint.data, (uint32_t *) &measuredPoint);
DrawCalibrationPoint(&measuredPoint);
/* Check resulting x and y */
xDiff = (int32_t) measuredPoint.x - (int32_t) testPoint.x;
yDiff = (int32_t) measuredPoint.y - (int32_t) testPoint.y;
xOk = (xDiff >= -POINTS_MAX_ERROR) && (xDiff <= POINTS_MAX_ERROR);
yOk = (yDiff >= -POINTS_MAX_ERROR) && (yDiff <= POINTS_MAX_ERROR);
/* Wait for contact loss */
TSD_WaitPenReleased();
/* Check calibration result */
if (xOk && yOk) {
bCalibrationOk = 1;
LCDD_Fill(COLOR_WHITE);
LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK);
LCDD_DrawString(80, 140, (uint8_t *)"Success !", COLOR_GREEN);
}
else {
bCalibrationOk = 0;
LCDD_Fill(COLOR_WHITE);
LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK);
LCDD_DrawString(40, 140, (uint8_t *)"Error too big", COLOR_RED);
}
/* Slight delay */
for (i = 0; i < DELAY_RESULT_DISPLAY; i++);
return (xOk && yOk);
}
/**
* \brief Read calibrate data to buffer.
*
* \param pBuffer Data buffer.
* \param size Size of data buffer in bytes.
*/
void TSDCom_ReadCalibrateData(void *pBuffer, uint32_t size)
{
uint8_t *pDest = (uint8_t *)pBuffer;
assert( (sizeof(bCalibrationOk) + sizeof(xSlope) +
sizeof(ySlope) + sizeof(calibrationPoints[0].data)) < size ) ;
memcpy(pDest, (void const *)&bCalibrationOk, sizeof(bCalibrationOk));
pDest += sizeof(bCalibrationOk);
memcpy(pDest, &xSlope, sizeof(xSlope));
pDest += sizeof(xSlope);
memcpy(pDest, &ySlope, sizeof(ySlope));
pDest += sizeof(ySlope);
memcpy(pDest, &calibrationPoints[0].data, sizeof(calibrationPoints[0].data));
pDest += sizeof(calibrationPoints[0].data);
}
/**
* \brief Restore calibrate data with buffer data.
*
* \param pBuffer Data buffer.
* \param size Size of data buffer in bytes.
*/
void TSDCom_RestoreCalibrateData(void *pBuffer, uint32_t size)
{
uint8_t *pSrc = (uint8_t *)pBuffer;
assert( (sizeof(bCalibrationOk) + sizeof(xSlope) +
sizeof(ySlope) + sizeof(calibrationPoints[0].data)) < size ) ;
memcpy((void *)&bCalibrationOk, pSrc, sizeof(bCalibrationOk));
pSrc += sizeof(bCalibrationOk);
memcpy(&xSlope, pSrc, sizeof(xSlope));
pSrc += sizeof(xSlope);
memcpy(&ySlope, pSrc, sizeof(ySlope));
pSrc += sizeof(ySlope);
memcpy(&calibrationPoints[0].data, pSrc, sizeof(calibrationPoints[0].data));
pSrc += sizeof(calibrationPoints[0].data);
}

View File

@@ -0,0 +1,389 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implements UART console.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdio.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 115200
/** Usart Hw interface used by the console (UART0). */
#define CONSOLE_USART UART0
/** Usart Hw ID used by the console (UART0). */
#define CONSOLE_ID ID_UART0
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define CONSOLE_PINS {PINS_UART}
/*----------------------------------------------------------------------------
* Variables
*----------------------------------------------------------------------------*/
/** Is Console Initialized. */
static uint8_t _ucIsConsoleInitialized=0 ;
/**
* \brief Configures an USART peripheral with the specified parameters.
*
* \param baudrate Baudrate at which the USART should operate (in Hz).
* \param masterClock Frequency of the system master clock (in Hz).
*/
extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
{
const Pin pPins[] = CONSOLE_PINS;
Uart *pUart = CONSOLE_USART;
/* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID;
/* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */
pUart->UART_MR = UART_MR_PAR_NO;
/* Configure baudrate */
/* Asynchronous, no oversampling */
pUart->UART_BRGR = (masterClock / baudrate) / 16;
/* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
_ucIsConsoleInitialized=1 ;
}
/**
* \brief Outputs a character on the UART line.
*
* \note This function is synchronous (i.e. uses polling).
* \param c Character to send.
*/
extern void UART_PutChar( uint8_t c )
{
Uart *pUart=CONSOLE_USART ;
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
/* Wait for the transmitter to be ready */
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
/* Send character */
pUart->UART_THR=c ;
}
/**
* \brief Input a character from the UART line.
*
* \note This function is synchronous
* \return character received.
*/
extern uint32_t UART_GetChar( void )
{
Uart *pUart=CONSOLE_USART ;
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) ;
return pUart->UART_RHR ;
}
/**
* \brief Check if there is Input from UART line.
*
* \return true if there is Input.
*/
extern uint32_t UART_IsRxReady( void )
{
Uart *pUart=CONSOLE_USART ;
if ( !_ucIsConsoleInitialized )
{
UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ;
}
return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
}
/**
* Displays the content of the given frame on the UART0.
*
* \param pucFrame Pointer to the frame to dump.
* \param dwSize Buffer size in bytes.
*/
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
{
uint32_t dw ;
for ( dw=0 ; dw < dwSize ; dw++ )
{
printf( "%02X ", pucFrame[dw] ) ;
}
printf( "\n\r" ) ;
}
/**
* Displays the content of the given buffer on the UART0.
*
* \param pucBuffer Pointer to the buffer to dump.
* \param dwSize Buffer size in bytes.
* \param dwAddress Start address to display
*/
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
{
uint32_t i ;
uint32_t j ;
uint32_t dwLastLineStart ;
uint8_t* pucTmp ;
for ( i=0 ; i < (dwSize / 16) ; i++ )
{
printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ;
pucTmp = (uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 4 ; j++ )
{
printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ;
pucTmp += 4 ;
}
pucTmp=(uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 16 ; j++ )
{
UART_PutChar( *pucTmp++ ) ;
}
printf( "\n\r" ) ;
}
if ( (dwSize%16) != 0 )
{
dwLastLineStart=dwSize - (dwSize%16) ;
printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ;
for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ )
{
if ( (j!=dwLastLineStart) && (j%4 == 0) )
{
printf( " " ) ;
}
if ( j < dwSize )
{
printf( "%02X", pucBuffer[j] ) ;
}
else
{
printf(" ") ;
}
}
printf( " " ) ;
for ( j=dwLastLineStart ; j < dwSize ; j++ )
{
UART_PutChar( pucBuffer[j] ) ;
}
printf( "\n\r" ) ;
}
}
/**
* Reads an integer
*
* \param pdwValue Pointer to the uint32_t variable to contain the input value.
*/
extern uint32_t UART_GetInteger( uint32_t* pdwValue )
{
uint8_t ucKey ;
uint8_t ucNbNb=0 ;
uint32_t dwValue=0 ;
while ( 1 )
{
ucKey=UART_GetChar() ;
UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' )
{
dwValue = (dwValue * 10) + (ucKey - '0');
ucNbNb++ ;
}
else
{
if ( ucKey == 0x0D || ucKey == ' ' )
{
if ( ucNbNb == 0 )
{
printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ;
return 0 ;
}
else
{
printf( "\n\r" ) ;
*pdwValue=dwValue ;
return 1 ;
}
}
else
{
printf( "\n\r'%c' not a number!\n\r", ucKey ) ;
return 0 ;
}
}
}
}
/**
* Reads an integer and check the value
*
* \param pdwValue Pointer to the uint32_t variable to contain the input value.
* \param dwMin Minimum value
* \param dwMax Maximum value
*/
extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax )
{
uint32_t dwValue=0 ;
if ( UART_GetInteger( &dwValue ) == 0 )
{
return 0 ;
}
if ( dwValue < dwMin || dwValue > dwMax )
{
printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ;
return 0 ;
}
printf( "\n\r" ) ;
*pdwValue = dwValue ;
return 1 ;
}
/**
* Reads an hexadecimal number
*
* \param pdwValue Pointer to the uint32_t variable to contain the input value.
*/
extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
{
uint8_t ucKey ;
uint32_t dw = 0 ;
uint32_t dwValue = 0 ;
for ( dw=0 ; dw < 8 ; dw++ )
{
ucKey = UART_GetChar() ;
UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' )
{
dwValue = (dwValue * 16) + (ucKey - '0') ;
}
else
{
if ( ucKey >= 'A' && ucKey <= 'F' )
{
dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ;
}
else
{
if ( ucKey >= 'a' && ucKey <= 'f' )
{
dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
}
else
{
printf( "\n\rIt is not a hexa character!\n\r" ) ;
return 0 ;
}
}
}
}
printf("\n\r" ) ;
*pdwValue = dwValue ;
return 1 ;
}
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */
/**
* \brief Outputs a character on the UART.
*
* \param c Character to output.
*
* \return The character that was output.
*/
extern WEAK signed int putchar( signed int c )
{
UART_PutChar( c ) ;
return c ;
}
#endif // defined __ICCARM__

View File

@@ -0,0 +1,90 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include <stdio.h>
/*----------------------------------------------------------------------------
* Definiation
*----------------------------------------------------------------------------*/
/* WAV letters "RIFF" */
#define WAV_CHUNKID 0x46464952
/* WAV letters "WAVE"*/
#define WAV_FORMAT 0x45564157
/* WAV letters "fmt "*/
#define WAV_SUBCHUNKID 0x20746D66
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Check if the header of a Wav file is valid ot not.
*
* \param file Buffer holding the file to examinate.
* \return 1 if the header of a Wav file is valid; otherwise returns 0.
*/
unsigned char WAV_IsValid(const WavHeader *header)
{
return ((header->chunkID == WAV_CHUNKID)
&& (header->format == WAV_FORMAT)
&& (header->subchunk1Size == 0x10));
}
/**
* \brief Display the information of the WAV file (sample rate, stereo/mono
* and frame size).
*
* \param header Wav head information.
*/
void WAV_DisplayInfo(const WavHeader *header)
{
printf( "Wave file header information\n\r");
printf( "--------------------------------\n\r");
printf( " - Chunk ID = 0x%08X\n\r", header->chunkID);
printf( " - Chunk Size = %u\n\r", header->chunkSize);
printf( " - Format = 0x%08X\n\r", header->format);
printf( " - SubChunk ID = 0x%08X\n\r", header->subchunk1ID);
printf( " - Subchunk1 Size = %u\n\r", header->subchunk1Size);
printf( " - Audio Format = 0x%04X\n\r", header->audioFormat);
printf( " - Num. Channels = %d\n\r", header->numChannels);
printf( " - Sample Rate = %u\n\r", header->sampleRate);
printf( " - Byte Rate = %u\n\r", header->byteRate);
printf( " - Block Align = %d\n\r", header->blockAlign);
printf( " - Bits Per Sample = %d\n\r", header->bitsPerSample);
printf( " - Subchunk2 ID = 0x%08X\n\r", header->subchunk2ID);
printf( " - Subchunk2 Size = %u\n\r", header->subchunk2Size);
}

View File

@@ -0,0 +1,139 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation WM8731 driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Read data from WM8731 Register.
*
* \param pTwid Pointer to twi driver structure
* \param device Twi slave address.
* \param regAddr Register address to read.
* \return value in the given register.
*/
uint16_t WM8731_Read(Twid *pTwid,
uint32_t device,
uint32_t regAddr)
{
uint16_t bitsDataRegister;
uint8_t Tdata[2]={0,0};
TWID_Read(pTwid, device, regAddr, 0, Tdata, 2, 0);
bitsDataRegister = (Tdata[0] << 8) | Tdata[1];
return bitsDataRegister;
}
/**
* \brief Write data to WM8731 Register.
*
* \param pTwid Pointer to twi driver structure
* \param device Twi slave address.
* \param regAddr Register address to read.
* \param data Data to write
*/
void WM8731_Write(Twid *pTwid,
uint32_t device,
uint32_t regAddr,
uint16_t data)
{
uint8_t tmpData[2];
uint16_t tmp;
tmp = ((regAddr & 0x7f) << 9) | (data & 0x1ff);
tmpData[0] = (tmp & 0xff00) >> 8;
tmpData[1] = tmp & 0xff;
TWID_Write(pTwid, device, regAddr, 0, tmpData, 2, 0);
}
/**
* \brief Init WM8731 to DAC mode.
*
* \param pTwid Pointer to twi driver structure
* \param device Twi slave address.
* \return 0.
*/
uint8_t WM8731_DAC_Init(Twid *pTwid,
uint32_t device)
{
/* reset */
WM8731_Write(pTwid, device, WM8731_REG_RESET, 0);
/* analogue audio path control */
WM8731_Write(pTwid, device, WM8731_REG_ANALOGUE_PATH_CTRL, 0x12);
/* digital audio path control*/
WM8731_Write(pTwid, device, WM8731_REG_DIGITAL_PATH_CTRL, 0x00);
/* power down control */
WM8731_Write(pTwid, device, WM8731_REG_PWDOWN_CTRL, 0x7);
/* Active control*/
WM8731_Write(pTwid, device, WM8731_REG_ACTIVE_CTRL, 0x01);
return 0;
}
/**
* \brief Set WM8731 volume
*
* \param pTwid Pointer to twi driver structure
* \param device Twi slave address.
* \param value Register value, valid value is between 0x30 to 0x7f
* \return 0.
*/
uint8_t WM8731_VolumeSet(Twid *pTwid,
uint32_t device,
uint16_t value)
{
uint16_t regValue;
value &= WM8731_LHPVOL_BITS;
regValue = WM8731_LRHPBOTH_BIT | WM8731_LZCEN_BIT | value;
WM8731_Write(pTwid, device, WM8731_REG_LEFT_HPOUT, regValue);
regValue = WM8731_RZCEN_BIT | WM8731_RLHPBOTH_BIT | value;
WM8731_Write(pTwid, device, WM8731_REG_RIGHT_HPOUT, value);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup acc_module Working with ACC
* The ACC driver provides the interface to configure and use the ACC peripheral.\n
*
* It applies comparison on two inputs and gives a compare output.
*
* To Enable a ACC Comparison,the user has to follow these few steps:
* <ul>
* <li> Enable ACC peripheral clock by setting the corresponding bit in PMC_PCER1
* (PMC Peripheral Clock Enable Register 1)
* </li>
* <li> Reset the controller by asserting ACC_CR_SWRST in ACC_CR(ACC Control Register)
</li>
* <li> Configure the mode as following steps: </li>
* -# Select inputs for SELMINUS and SELPLUS in ACC_MR (ACC Mode Register).
* -# Enable Analog Comparator by setting ACEN in ACC_MR.
* -# Configure Edge Type to detect different compare output.
* </li>
* <li> Wait until the automatic mask period expires by polling MASK bit in
* ACC_ISR.
* </ul>
*
* For more accurate information, please look at the ACC section of the
* Datasheet.
*
* Related files :\n
* \ref acc.c\n
* \ref acc.h\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Analog Comparator Controller (ACC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initialize the ACC controller
*
* \param pAcc Pointer to an Acc instance.
* \param idAcc ACC identifier
* \param ucSelplus input connected to inp, 0~7
* \param ucSelminus input connected to inm,0~7
* \param wAc_en Analog comprator enabled/disabled
* \param wEdge CF flag triggering mode
* \param wInvert INVert comparator output,use pattern defined in the device header file
*/
extern void ACC_Configure( Acc *pAcc, uint8_t idAcc, uint8_t ucSelplus, uint8_t ucSelminus,
uint16_t wAc_en, uint16_t wEdge, uint16_t wInvert )
{
/* Enable peripheral clock*/
PMC->PMC_PCER1 = 1 << (idAcc - 32) ;
/* Reset the controller */
pAcc->ACC_CR |= ACC_CR_SWRST ;
/* Write to the MR register */
ACC_CfgModeReg( pAcc,
( (ucSelplus<<ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk ) |
( (ucSelminus<<ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk ) |
( (wAc_en<<8) & ACC_MR_ACEN ) |
( (wEdge<<ACC_MR_EDGETYP_Pos) & ACC_MR_EDGETYP_Msk ) |
( (wInvert<<12) & ACC_MR_INV ) ) ;
/* set hysteresis and current option*/
pAcc->ACC_ACR = (ACC_ACR_ISEL_HISP | ((0x01 << ACC_ACR_HYST_Pos) & ACC_ACR_HYST_Msk));
/* Automatic Output Masking Period*/
while ( pAcc->ACC_ISR & (uint32_t)ACC_ISR_MASK ) ;
}
/**
* Return the Channel Converted Data
* \param pAcc Pointer to an Acc instance.
* \param selplus input applied on ACC SELPLUS
* \param selminus input applied on ACC SELMINUS
*/
extern void ACC_SetComparisionPair( Acc *pAcc, uint8_t ucSelplus, uint8_t ucSelminus )
{
uint32_t dwTemp ;
assert( ucSelplus < 8 && ucSelminus < 8 ) ;
dwTemp = pAcc->ACC_MR ;
pAcc->ACC_MR = dwTemp & (uint32_t) ((~ACC_MR_SELMINUS_Msk) & (~ACC_MR_SELPLUS_Msk));
pAcc->ACC_MR |= ( ((ucSelplus << ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk) |
((ucSelminus << ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk) ) ;
}
/**
* Return Comparison Result
* \param pAcc Pointer to an Acc instance.
* \param status value of ACC_ISR
*/
extern uint32_t ACC_GetComparisionResult( Acc *pAcc, uint32_t dwStatus )
{
uint32_t dwTemp = pAcc->ACC_MR ;
if ( (dwTemp & ACC_MR_INV) == ACC_MR_INV )
{
if ( dwStatus & ACC_ISR_SCO )
{
return 0 ; /* inn>inp*/
}
else
{
return 1 ;/* inp>inn*/
}
}
else
{
if ( dwStatus & ACC_ISR_SCO )
{
return 1 ; /* inp>inn*/
}
else
{
return 0 ;/* inn>inp*/
}
}
}

View File

@@ -0,0 +1,417 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup adc_module Working with ADC
* The ADC driver provides the interface to configure and use the ADC peripheral.
* \n
*
* It converts the analog input to digital format. The converted result could be
* 12bit or 10bit. The ADC supports up to 16 analog lines.
*
* To Enable a ADC conversion,the user has to follow these few steps:
* <ul>
* <li> Select an appropriate reference voltage on ADVREF </li>
* <li> Configure the ADC according to its requirements and special needs,which
* could be broken down into several parts:
* -# Select the resolution by setting or clearing ADC_MR_LOWRES bit in
* ADC_MR (Mode Register)
* -# Set ADC clock by setting ADC_MR_PRESCAL bits in ADC_MR, the clock is
* calculated with ADCClock = MCK / ( (PRESCAL+1) * 2 )
* -# Set Startup Time,Tracking Clock cycles and Transfer Clock respectively
* in ADC_MR.
</li>
* <li> Start conversion by setting ADC_CR_START in ADC_CR. </li>
* </ul>
*
* For more accurate information, please look at the ADC section of the
* Datasheet.
*
* Related files :\n
* \ref adc.c\n
* \ref adc.h\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Analog-to-Digital Converter (ADC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initialize the ADC controller
*
* \param pAdc Pointer to an Adc instance.
* \param idAdc ADC Index
* \param trgEn trigger mode, software or Hardware
* \param trgSel hardware trigger selection
* \param sleepMode sleep mode selection
* \param resolution resolution selection 10 bits or 12 bits
* \param mckClock value of MCK in Hz
* \param adcClock value of the ADC clock in Hz
* \param startup value of the start up time (in ADCClock) (see datasheet)
* \param tracking Tracking Time (in ADCClock cycle)
*/
extern void ADC_Initialize( Adc* pAdc, uint32_t idAdc )
{
/* Enable peripheral clock*/
PMC->PMC_PCER0 = 1 << idAdc;
/* Reset the controller */
pAdc->ADC_CR = ADC_CR_SWRST;
/* Reset Mode Register set to default */
/* TrackTime set to 0 */
/* Transfer set to 1 */
/* settling set to 3 */
pAdc->ADC_MR = ADC_MR_TRANSFER(1) | ADC_MR_TRACKTIM(0) | ADC_MR_SETTLING(3);
}
/**
* \brief Initialize the ADC Timing
*/
extern void ADC_CfgTiming( Adc* pAdc, uint32_t tracking, uint32_t settling, uint32_t transfer )
{
pAdc->ADC_MR = ADC_MR_TRANSFER( transfer )
| ADC_MR_SETTLING( settling )
| ADC_MR_TRACKTIM( tracking ) ;
}
/**
* \brief Initialize the ADC Timing
*/
extern void ADC_cfgFrequency( Adc* pAdc, uint32_t startup, uint32_t prescal )
{
pAdc->ADC_MR |= ADC_MR_PRESCAL( prescal )
| ( (startup<<ADC_MR_STARTUP_Pos) & ADC_MR_STARTUP_Msk);
}
/**
* \brief Initialize the ADC Trigering
*/
extern void ADC_CfgTrigering( Adc* pAdc, uint32_t trgEn, uint32_t trgSel, uint32_t freeRun )
{
pAdc->ADC_MR |= ((trgEn<<0) & ADC_MR_TRGEN)
| ((trgSel<<ADC_MR_TRGSEL_Pos) & ADC_MR_TRGSEL_Msk)
| ((freeRun<<7) & ADC_MR_FREERUN) ;
}
/**
* \brief Initialize the ADC Low Res
*/
extern void ADC_CfgLowRes( Adc* pAdc, uint32_t resolution )
{
pAdc->ADC_MR |= (resolution<<4) & ADC_MR_LOWRES;
}
/**
* \brief Initialize the ADC PowerSave
*/
extern void ADC_CfgPowerSave( Adc* pAdc, uint32_t sleep, uint32_t fwup )
{
pAdc->ADC_MR |= ( ((sleep<<5) & ADC_MR_SLEEP)
| ((fwup<<6) & ADC_MR_FWUP) );
}
/**
* \brief Initialize the ADC Channel Mode
*/
extern void ADC_CfgChannelMode( Adc* pAdc, uint32_t useq, uint32_t anach )
{
pAdc->ADC_MR |= ( ((anach<<23) & ADC_MR_ANACH)
| ((useq <<31) & (uint32_t)ADC_MR_USEQ) );
}
/**
* \brief calcul_startup
*/
static uint32_t calcul_startup( uint32_t startup )
{
uint32_t startup_value=0;
if( startup == 0 )
startup_value = 0;
else if( startup == 1 )
startup_value = 8;
else if( startup == 2 )
startup_value = 16;
else if( startup == 3 )
startup_value = 24;
else if( startup == 4 )
startup_value = 64;
else if( startup == 5 )
startup_value = 80;
else if( startup == 6 )
startup_value = 96;
else if( startup == 7 )
startup_value = 112;
else if( startup == 8 )
startup_value = 512;
else if( startup == 9 )
startup_value = 576;
else if( startup == 10 )
startup_value = 640;
else if( startup == 11 )
startup_value = 704;
else if( startup == 12 )
startup_value = 768;
else if( startup == 13 )
startup_value = 832;
else if( startup == 14 )
startup_value = 896;
else if( startup == 15 )
startup_value = 960;
return startup_value;
}
/**
* \brief ADC check
*/
extern void ADC_check( Adc* pAdc, uint32_t mck_freq )
{
uint32_t adc_freq;
uint32_t prescal;
uint32_t startup;
/* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
prescal = (( pAdc->ADC_MR & ADC_MR_PRESCAL_Msk) >> ADC_MR_PRESCAL_Pos);
adc_freq = mck_freq / ((prescal+1)*2);
printf("ADC clock frequency = %d Hz\r\n", (int)adc_freq );
if( adc_freq < ADC_FREQ_MIN )
{
printf("adc frequency too low (out of specification: %d Hz)\r\n", (int)ADC_FREQ_MIN);
}
if( adc_freq > ADC_FREQ_MAX )
{
printf("adc frequency too high (out of specification: %d Hz)\r\n", (int)ADC_FREQ_MAX);
}
startup = (( pAdc->ADC_MR & ADC_MR_STARTUP_Msk) >> ADC_MR_STARTUP_Pos);
if( !(pAdc->ADC_MR & ADC_MR_SLEEP_SLEEP) )
{
/* 40µs */
if( ADC_STARTUP_NORM * adc_freq / 1000000 > calcul_startup(startup) )
{
printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)calcul_startup(startup));
}
}
else
{
if(pAdc->ADC_MR & ADC_MR_FREERUN_ON)
{
printf("FreeRun forbidden in sleep mode\n\r");
}
if( !(pAdc->ADC_MR & ADC_MR_FWUP_ON) )
{
/* Sleep 40µs */
if( ADC_STARTUP_NORM * adc_freq / 1000000 > calcul_startup(startup) )
{
printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)(calcul_startup(startup)));
}
}
else
{
if( pAdc->ADC_MR & ADC_MR_FWUP_ON )
{
/* Fast Wake Up Sleep Mode: 12µs */
if( ADC_STARTUP_FAST * adc_freq / 1000000 > calcul_startup(startup) )
{
printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)(calcul_startup(startup)));
}
}
}
}
}
/**
* Return the Channel Converted Data
*
* \param pAdc Pointer to an Adc instance.
* \param channel channel to get converted value
*/
extern uint32_t ADC_GetConvertedData( Adc* pAdc, uint32_t dwChannel )
{
uint32_t dwData = 0;
assert( dwChannel < 16 ) ;
if ( 15 >= dwChannel )
{
dwData=*(pAdc->ADC_CDR+dwChannel) ;
}
return dwData ;
}
/**
* Set compare channel
*
* \param pAdc Pointer to an Adc instance.
* \param channel channel number to be set,16 for all channels
*/
extern void ADC_SetCompareChannel( Adc* pAdc, uint32_t dwChannel )
{
assert( dwChannel <= 16 ) ;
if ( dwChannel < 16 )
{
pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPALL);
pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPSEL_Msk);
pAdc->ADC_EMR |= (dwChannel << ADC_EMR_CMPSEL_Pos);
}
else
{
pAdc->ADC_EMR |= ADC_EMR_CMPALL;
}
}
/**
* Set compare mode
*
* \param pAdc Pointer to an Adc instance.
* \param mode compare mode
*/
extern void ADC_SetCompareMode( Adc* pAdc, uint32_t dwMode )
{
pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPMODE_Msk);
pAdc->ADC_EMR |= (dwMode & ADC_EMR_CMPMODE_Msk) ;
}
/**
* Set comparsion window,one thereshold each time
*
* \param pAdc Pointer to an Adc instance.
* \param hi_lo Comparison Window
*/
extern void ADC_SetComparisonWindow( Adc* pAdc, uint32_t dwHi_Lo )
{
pAdc->ADC_CWR = dwHi_Lo ;
}
/**----------------------------------------------------------------------------
* Test if ADC Interrupt is Masked
*
* \param pAdc Pointer to an Adc instance.
* \param flag flag to be tested
*
* \return 1 if interrupt is masked, otherwise 0
*/
uint32_t ADC_IsInterruptMasked( Adc* pAdc, uint32_t dwFlag )
{
return (ADC_GetInterruptMaskStatus( pAdc ) & dwFlag) ;
}
/**----------------------------------------------------------------------------
* Test if ADC Status is Set
*
* \param pAdc Pointer to an Adc instance.
* \param flag flag to be tested
*
* \return 1 if the staus is set; 0 otherwise
*/
extern uint32_t ADC_IsStatusSet( Adc* pAdc, uint32_t dwFlag )
{
return (ADC_GetStatus( pAdc ) & dwFlag) ;
}
/**----------------------------------------------------------------------------
* Test if ADC channel interrupt Status is Set
*
* \param adc_sr Value of SR register
* \param channel Channel to be tested
*
* \return 1 if interrupt status is set, otherwise 0
*/
extern uint32_t ADC_IsChannelInterruptStatusSet( uint32_t dwAdc_sr, uint32_t dwChannel )
{
uint32_t dwStatus ;
if ( (dwAdc_sr & ((uint32_t)1 << dwChannel)) == ((uint32_t)1 << dwChannel) )
{
dwStatus = 1 ;
}
else
{
dwStatus = 0 ;
}
return dwStatus ;
}
/**
* \brief Read converted data through PDC channel
*
* \param pADC the pointer of adc peripheral
* \param pBuffer the destination buffer
* \param dwSize the size of the buffer
*/
extern uint32_t ADC_ReadBuffer( Adc* pADC, int16_t *pwBuffer, uint32_t dwSize )
{
/* Check if the first PDC bank is free*/
if ( (pADC->ADC_RCR == 0) && (pADC->ADC_RNCR == 0) )
{
pADC->ADC_RPR = (uint32_t)pwBuffer ;
pADC->ADC_RCR = dwSize ;
pADC->ADC_PTCR = ADC_PTCR_RXTEN;
return 1;
}
/* Check if the second PDC bank is free*/
else
{
if ( pADC->ADC_RNCR == 0 )
{
pADC->ADC_RNPR = (uint32_t)pwBuffer ;
pADC->ADC_RNCR = dwSize ;
return 1 ;
}
else
{
return 0 ;
}
}
}

View File

@@ -0,0 +1,53 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Provide a routine for asynchronos transfer.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
/**
* \brief Returns 1 if the given transfer has ended; otherwise returns 0.
* \param pAsync Pointer to an Async instance.
*/
uint32_t ASYNC_IsFinished( Async* pAsync )
{
return (pAsync->status != ASYNC_STATUS_PENDING) ;
}

View File

@@ -0,0 +1,112 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup crccu_module Working with CRCCU
* The CRCCU driver provides the interface to configure and use the CRCCU
* peripheral.
*
* It performs a CRC computation on a Memory Area. CRC computation is performed
* from the LSB to MSB bit. Three different polynomials are available:
* CCIT802.3, CASTAGNOLI and CCIT16.
*
* To computes CRC of a buffer, the user has to follow these few steps:
* <ul>
* <li>Reset initial CRC by setting RESET bit in CRCCU_CRC_CR,</li>
* <li>Configure CRC descriptor and working mode,</li>
* <li>Start to compute CRC by setting DMAEN in CRCCU_DMA_EN,</li>
* <li>Get CRC value in CRCCU_CRC_SR.</li>
* </ul>
*
* For more accurate information, please look at the CRCCU section of the
* Datasheet.
*
* Related files :\n
* \ref crccu.c\n
* \ref crccu.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Cyclic Redundancy Check Calculation Unit (CRCCU).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
#define CRCCU_TIMEOUT 0xFFFFFFFF
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Reset initial CRC to 0xFFFFFFFF.
*/
extern void CRCCU_ResetCrcValue( Crccu* pCrccu )
{
pCrccu->CRCCU_CR = CRCCU_CR_RESET;
}
/**
* \brief Configure the CRCCU.
*
* \param dscrAddr CRC decscriptor address.
* \param mode CRC work mode
*/
extern void CRCCU_Configure( Crccu* pCrccu, uint32_t dwDscrAddr, uint32_t dwMode )
{
pCrccu->CRCCU_DSCR = dwDscrAddr ;
pCrccu->CRCCU_MR = dwMode ;
}
/**
* \brief Start to compute the CRC of a buffer.
*
* \return The CRC of the buffer.
*/
extern uint32_t CRCCU_ComputeCrc( Crccu* pCrccu )
{
uint32_t dwTimeout = 0 ;
pCrccu->CRCCU_DMA_EN = CRCCU_DMA_EN_DMAEN ;
while ( ((pCrccu->CRCCU_DMA_SR & CRCCU_DMA_SR_DMASR) == CRCCU_DMA_SR_DMASR) &&
(dwTimeout++ < CRCCU_TIMEOUT) ) ;
return (pCrccu->CRCCU_SR) ;
}

View File

@@ -0,0 +1,183 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup dacc_module Working with DACC
* The DACC driver provides the interface to configure and use the DACC peripheral.\n
*
* The DACC(Digital-to-Analog Converter Controller) converts digital code to analog output.
* The data to be converted are sent in a common register for all channels. It offers up to 2
* analog outputs.The output voltage ranges from (1/6)ADVREF to (5/6)ADVREF.
*
* To Enable a DACC conversion,the user has to follow these few steps:
* <ul>
* <li> Select an appropriate reference voltage on ADVREF </li>
* <li> Configure the DACC according to its requirements and special needs,which could be
broken down into several parts:
* -# Enable DACC in free running mode by clearing TRGEN in DACC_MR;
* -# Configure Startup Time and Refresh Period through setting STARTUP and REFRESH fields
* in DACC_MR; The refresh mechanism is used to protect the output analog value from
* decreasing.
* -# Enable channels and write digital code to DACC_CDR,in free running mode, the conversion
* is started right after at least one channel is enabled and data is written .
</li>
* </ul>
*
* For more accurate information, please look at the DACC section of the
* Datasheet.
*
* Related files :\n
* \ref DACC.c\n
* \ref DACC.h\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Digital-to-Analog Converter Controller (DACC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initialize the DACC controller
* \param pDACC Pointer to an DACC instance.
* \param idDACC identifier of DAC peripheral
* \param trgEn trigger mode, free running mode or external Hardware trigger
* \param word transfer size,word or half word
* \param trgSel hardware trigger selection
* \param sleepMode sleep mode selection
* \param mck value of MCK in Hz
* \param refresh refresh period
* \param user_sel user channel selection ,0 or 1
* \param tag_mode tag for channel number
* \param startup value of the start up time (in DACCClock) (see datasheet)
*/
extern void DACC_Initialize( Dacc* pDACC,
uint8_t idDACC,
uint8_t trgEn,
uint8_t trgSel,
uint8_t word,
uint8_t sleepMode,
uint32_t mck,
uint8_t refresh, /* refresh period */
uint8_t user_sel, /* user channel selection */
uint32_t tag_mode, /* using tag for channel number */
uint32_t startup
)
{
assert( 1024*refresh*1000/(mck>>1) < 20 ) ;
/* Enable peripheral clock*/
PMC->PMC_PCER0 = 1 << idDACC;
/* Reset the controller */
DACC_SoftReset(pDACC);
/* Write to the MR register */
DACC_CfgModeReg( pDACC,
( (trgEn<<0) & DACC_MR_TRGEN)
| DACC_MR_TRGSEL(trgSel)
| ( (word<<4) & DACC_MR_WORD)
| ( (sleepMode<<5) & DACC_MR_SLEEP)
| DACC_MR_REFRESH(refresh)
| ( (user_sel<<DACC_MR_USER_SEL_Pos)& DACC_MR_USER_SEL_Msk)
| ( (tag_mode<<20) & DACC_MR_TAG)
| ( (startup<<DACC_MR_STARTUP_Pos) & DACC_MR_STARTUP_Msk));
}
/**
* Set the Conversion Data
* \param pDACC Pointer to an Dacc instance.
* \param data date to be converted.
*/
extern void DACC_SetConversionData( Dacc* pDACC, uint32_t dwData )
{
uint32_t dwMR = pDACC->DACC_MR ;
if ( dwMR & DACC_MR_WORD )
{
pDACC->DACC_CDR = dwData ;
}
else
{
pDACC->DACC_CDR = (dwData&0xFFFF) ;
}
}
/**
* \brief Write converted data through PDC channel
* \param pDACC the pointer of DACC peripheral
* \param pBuffer the destination buffer
* \param size the size of the buffer
*/
extern uint32_t DACC_WriteBuffer( Dacc* pDACC, uint16_t *pwBuffer, uint32_t dwSize )
{
/* Check if the first PDC bank is free*/
if ( (pDACC->DACC_TCR == 0) && (pDACC->DACC_TNCR == 0) )
{
pDACC->DACC_TPR = (uint32_t)pwBuffer ;
pDACC->DACC_TCR = dwSize ;
pDACC->DACC_PTCR = DACC_PTCR_TXTEN ;
return 1 ;
}
/* Check if the second PDC bank is free*/
else
{
if (pDACC->DACC_TNCR == 0)
{
pDACC->DACC_TNPR = (uint32_t)pwBuffer ;
pDACC->DACC_TNCR = dwSize ;
return 1 ;
}
else
{
return 0 ;
}
}
}

View File

@@ -0,0 +1,289 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup efc_module Working with EEFC
* The EEFC driver provides the interface to configure and use the EEFC
* peripheral.
*
* The user needs to set the number of wait states depending on the frequency used.\n
* Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
*
* It offers a function to send flash command to EEFC and waits for the
* flash to be ready.
*
* To send flash command, the user could do in either of following way:
* <ul>
* <li>Write a correct key, command and argument in EEFC_FCR. </li>
* <li>Or, Use IAP (In Application Programming) function which is executed from
* ROM directly, this allows flash programming to be done by code running in flash.</li>
* <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
* </ul>
*
* The command argument could be a page number,GPNVM number or nothing, it depends on
* the command itself. Some useful functions in this driver could help user tranlate physical
* flash address into a page number and vice verse.
*
* For more accurate information, please look at the EEFC section of the
* Datasheet.
*
* Related files :\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Enhanced Embedded Flash Controller (EEFC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Enables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_EnableFrdyIt( Efc* efc )
{
efc->EEFC_FMR |= EEFC_FMR_FRDY ;
}
/**
* \brief Disables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_DisableFrdyIt( Efc* efc )
{
efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
}
/**
* \brief Set read/write wait state on the EEFC perpherial.
*
* \param efc Pointer to a Efc instance
* \param cycles the number of wait states in cycle.
*/
extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
{
uint32_t dwValue ;
dwValue = efc->EEFC_FMR ;
dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
dwValue |= EEFC_FMR_FWS(ucCycles);
efc->EEFC_FMR = dwValue ;
}
/**
* \brief Returns the current status of the EEFC.
*
* \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetStatus( Efc* efc )
{
return efc->EEFC_FSR ;
}
/**
* \brief Returns the result of the last executed command.
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetResult( Efc* efc )
{
return efc->EEFC_FRR ;
}
/**
* \brief Translates the given address page and offset values.
* \note The resulting values are stored in the provided variables if they are not null.
*
* \param efc Pointer to a Efc instance
* \param address Address to translate.
* \param pPage First page accessed.
* \param pOffset Byte offset in first page.
*/
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{
Efc *pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
assert( dwAddress >= IFLASH_ADDR ) ;
assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
pEfc = EFC ;
wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
/* Store values */
if ( pEfc )
{
*ppEfc = pEfc ;
}
if ( pwPage )
{
*pwPage = wPage ;
}
if ( pwOffset )
{
*pwOffset = wOffset ;
}
}
/**
* \brief Computes the address of a flash access given the page and offset.
*
* \param efc Pointer to a Efc instance
* \param page Page number.
* \param offset Byte offset inside page.
* \param pAddress Computed address (optional).
*/
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{
uint32_t dwAddress ;
assert( efc ) ;
assert( wPage <= IFLASH_NB_OF_PAGES ) ;
assert( wOffset < IFLASH_PAGE_SIZE ) ;
/* Compute address */
dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
/* Store result */
if ( pdwAddress != NULL )
{
*pdwAddress = dwAddress ;
}
}
/**
* \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
*
* \note It does NOT set the FMCN field automatically.
* \param efc Pointer to a Efc instance
* \param command Command to execute.
* \param argument Command argument (should be 0 if not used).
*/
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{
/* Check command & argument */
switch ( dwCommand )
{
case EFC_FCMD_WP:
case EFC_FCMD_WPL:
case EFC_FCMD_EWP:
case EFC_FCMD_EWPL:
case EFC_FCMD_SLB:
case EFC_FCMD_CLB:
assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
break ;
case EFC_FCMD_SFB:
case EFC_FCMD_CFB:
assert( dwArgument < 2 ) ;
break;
case EFC_FCMD_GETD:
case EFC_FCMD_EA:
case EFC_FCMD_GLB:
case EFC_FCMD_GFB:
case EFC_FCMD_STUI:
assert( dwArgument == 0 ) ;
break;
default: assert( 0 ) ;
}
/* Start command Embedded flash */
assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
}
/**
* \brief Performs the given command and wait until its completion (or an error).
*
* \param efc Pointer to a Efc instance
* \param command Command to perform.
* \param argument Optional command argument.
*
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
{
if ( dwUseIAP != 0 )
{
/* Pointer on IAP function in ROM */
static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
}
else
{
uint32_t dwStatus ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
do
{
dwStatus = efc->EEFC_FSR ;
}
while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
}
}

View File

@@ -0,0 +1,512 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup flashd_module Flash Memory Interface
* The flash driver manages the programming, erasing, locking and unlocking sequences
* with dedicated commands.
*
* To implement flash programing operation, the user has to follow these few steps :
* <ul>
* <li>Configue flash wait states to initializes the flash. </li>
* <li>Checks whether a region to be programmed is locked. </li>
* <li>Unlocks the user region to be programmed if the region have locked before.</li>
* <li>Erases the user page before program (optional).</li>
* <li>Writes the user page from the page buffer.</li>
* <li>Locks the region of programmed area if any.</li>
* </ul>
*
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
* A check of this validity and padding for 32-bit alignment should be done in write algorithm.
* Lock/unlock range associated with the user address range is automatically translated.
*
* This security bit can be enabled through the command "Set General Purpose NVM Bit 0".
*
* A 128-bit factory programmed unique ID could be read to serve several purposes.
*
* The driver accesses the flash memory by calling the lowlevel module provided in \ref efc_module.
* For more accurate information, please look at the EEFC section of the Datasheet.
*
* Related files :\n
* \ref flashd.c\n
* \ref flashd.h.\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* The flash driver provides the unified interface for flash program operations.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <string.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
//static NO_INIT uint8_t _aucPageBuffer[IFLASH_PAGE_SIZE] ;
static NO_INIT uint32_t _adwPageBuffer[IFLASH_PAGE_SIZE/4] ;
static uint8_t* _aucPageBuffer = (uint8_t*)_adwPageBuffer;
static NO_INIT uint32_t _dwUseIAP ;
/*----------------------------------------------------------------------------
* Local macros
*----------------------------------------------------------------------------*/
#define min( a, b ) (((a) < (b)) ? (a) : (b))
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Computes the lock range associated with the given address range.
*
* \param dwStart Start address of lock range.
* \param dwEnd End address of lock range.
* \param pdwActualStart Actual start address of lock range.
* \param pdwActualEnd Actual end address of lock range.
*/
static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd )
{
Efc* pStartEfc ;
Efc* pEndEfc ;
uint16_t wStartPage ;
uint16_t wEndPage ;
uint16_t wNumPagesInRegion ;
uint16_t wActualStartPage ;
uint16_t wActualEndPage ;
// Convert start and end address in page numbers
EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ;
EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ;
// Find out the first page of the first region to lock
wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ;
wActualEndPage = wEndPage ;
if ( (wEndPage % wNumPagesInRegion) != 0 )
{
wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ;
}
// Store actual page numbers
EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ;
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes the flash driver.
*
* \param mck Master clock frequency in Hz.
*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP )
{
EFC_DisableFrdyIt( EFC ) ;
if ( (dwMCk/1000000) >= 64 )
{
EFC_SetWaitState( EFC, 2 ) ;
}
else
{
if ( (dwMCk/1000000) >= 50 )
{
EFC_SetWaitState( EFC, 1 ) ;
}
else
{
EFC_SetWaitState( EFC, 0 ) ;
}
}
_dwUseIAP=dwUseIAP ;
}
/**
* \brief Erases the entire flash.
*
* \param address Flash start address.
* \return 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_Erase( uint32_t dwAddress )
{
Efc* pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
uint32_t dwError ;
assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ;
// Translate write address
EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ;
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EA, 0, _dwUseIAP ) ;
return dwError ;
}
/**
* \brief Writes a data buffer in the internal flash
*
* \note This function works in polling mode, and thus only returns when the
* data has been effectively written.
* \param address Write address.
* \param pBuffer Data buffer.
* \param size Size of data buffer in bytes.
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize )
{
Efc* pEfc ;
uint16_t page ;
uint16_t offset ;
uint32_t writeSize ;
uint32_t pageAddress ;
uint16_t padding ;
uint32_t dwError ;
uint32_t sizeTmp ;
uint32_t *pAlignedDestination ;
uint32_t *pAlignedSource ;
assert( pvBuffer ) ;
assert( dwAddress >=IFLASH_ADDR ) ;
assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
/* Translate write address */
EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ;
/* Write all pages */
while ( dwSize > 0 )
{
/* Copy data in temporary buffer to avoid alignment problems */
writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ;
EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ;
padding = IFLASH_PAGE_SIZE - offset - writeSize ;
/* Pre-buffer data */
memcpy( _aucPageBuffer, (void *) pageAddress, offset);
/* Buffer data */
memcpy( _aucPageBuffer + offset, pvBuffer, writeSize);
/* Post-buffer data */
memcpy( _aucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);
/* Write page
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption
*/
pAlignedDestination = (uint32_t*)pageAddress ;
pAlignedSource = (uint32_t*)_adwPageBuffer ;
sizeTmp = IFLASH_PAGE_SIZE ;
while ( sizeTmp >= 4 )
{
*pAlignedDestination++ = *pAlignedSource++;
sizeTmp -= 4;
}
/* Send writing command */
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EWP, page, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
/* Progression */
dwAddress += IFLASH_PAGE_SIZE ;
pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ;
dwSize -= writeSize ;
page++;
offset = 0;
}
return 0 ;
}
/**
* \brief Locks all the regions in the given address range. The actual lock range is
* reported through two output parameters.
*
* \param start Start address of lock range.
* \param end End address of lock range.
* \param pActualStart Start address of the actual lock range (optional).
* \param pActualEnd End address of the actual lock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Lock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc *pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
/* Compute actual lock range and store it */
ComputeLockRange( start, end, &actualStart, &actualEnd ) ;
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd;
}
/* Compute page numbers */
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
/* Lock all pages */
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion;
}
return 0 ;
}
/**
* \brief Unlocks all the regions in the given address range. The actual unlock range is
* reported through two output parameters.
* \param start Start address of unlock range.
* \param end End address of unlock range.
* \param pActualStart Start address of the actual unlock range (optional).
* \param pActualEnd End address of the actual unlock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Unlock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc* pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
// Compute actual unlock range and store it
ComputeLockRange(start, end, &actualStart, &actualEnd);
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd ;
}
// Compute page numbers
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
// Unlock all pages
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion ;
}
return 0 ;
}
/**
* \brief Returns the number of locked regions inside the given address range.
*
* \param start Start address of range
* \param end End address of range.
*/
extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end )
{
Efc *pEfc ;
uint16_t startPage, endPage ;
uint8_t startRegion, endRegion ;
uint32_t numPagesInRegion ;
uint32_t status ;
uint32_t dwError ;
uint32_t numLockedRegions = 0 ;
assert( end >= start ) ;
assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ;
// Compute page numbers
EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ;
EFC_TranslateAddress( 0, end, &endPage, 0 ) ;
// Compute region numbers
numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
startRegion = startPage / numPagesInRegion ;
endRegion = endPage / numPagesInRegion ;
if ((endPage % numPagesInRegion) != 0)
{
endRegion++ ;
}
// Retrieve lock status
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
status = EFC_GetResult( pEfc ) ;
// Check status of each involved region
while ( startRegion < endRegion )
{
if ( (status & (1 << startRegion)) != 0 )
{
numLockedRegions++ ;
}
startRegion++ ;
}
return numLockedRegions ;
}
/**
* \brief Check if the given GPNVM bit is set or not.
*
* \param gpnvm GPNVM bit index.
* \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
*/
extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM )
{
uint32_t dwError ;
uint32_t dwStatus ;
assert( ucGPNVM < 2 ) ;
/* Get GPNVMs status */
dwError = EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
dwStatus = EFC_GetResult( EFC ) ;
/* Check if GPNVM is set */
if ( (dwStatus & (1 << ucGPNVM)) != 0 )
{
return 1 ;
}
else
{
return 0 ;
}
}
/**
* \brief Sets the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( !FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Clears the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Read the unique ID.
*
* \param uniqueID pointer on a 4bytes char containing the unique ID value.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID )
{
uint32_t dwError ;
assert( pdwUniqueID != NULL ) ;
pdwUniqueID[0] = 0 ;
pdwUniqueID[1] = 0 ;
pdwUniqueID[2] = 0 ;
pdwUniqueID[3] = 0 ;
EFC_StartCommand( EFC, EFC_FCMD_STUI, 0 ) ;
pdwUniqueID[0] = *(uint32_t*) IFLASH_ADDR;
pdwUniqueID[1] = *(uint32_t*)(IFLASH_ADDR + 4) ;
pdwUniqueID[2] = *(uint32_t*)(IFLASH_ADDR + 8) ;
pdwUniqueID[3] = *(uint32_t*)(IFLASH_ADDR + 12) ;
dwError = EFC_PerformCommand( EFC, EFC_FCMD_SPUI, 0, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
return 0 ;
}

View File

@@ -0,0 +1,262 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of High Speed MultiMedia Card Interface (HSMCI) controller,
* not using PDC nor DMA to transfer data.
*
*/
/*---------------------------------------------------------------------------
* Headers
*---------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*---------------------------------------------------------------------------
* Local macros
*---------------------------------------------------------------------------*/
/** Reset MCI */
#define MCI_RESET(pMciHw) (pMciHw->HSMCI_CR = HSMCI_CR_SWRST)
/*---------------------------------------------------------------------------
* Exported functions
*---------------------------------------------------------------------------*/
/**
* Enable MCI
* \param pMciHw Pointer to a MCI peripheral.
*/
void MCI_Enable(Hsmci *pMciHw)
{
pMciHw->HSMCI_CR = HSMCI_CR_MCIEN;
}
/**
* Disable MCI
* \param pMciHw Pointer to a MCI peripheral.
*/
void MCI_Disable(Hsmci *pMciHw)
{
pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS;
}
/**
* Initializes a MCI driver instance and the underlying peripheral.
* \param pMci Pointer to a MCI driver instance.
* \param pMciHw Pointer to a MCI peripheral.
* \param mciId MCI peripheral identifier.
*/
void MCI_Init( Mcid *pMci, Hsmci *pMciHw, uint8_t mciId, uint32_t dwMCk )
{
unsigned short clkDiv;
/* Initialize the MCI driver structure */
pMci->pMciHw = pMciHw;
pMci->mciId = mciId;
pMci->semaphore = 1;
pMci->pCommand = NULL;
/* Enable the MCI peripheral */
PMC_EnablePeripheral( mciId ) ;
/* Reset the MCI */
pMciHw->HSMCI_CR = HSMCI_CR_SWRST;
/* Disable the MCI */
pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS | HSMCI_CR_PWSDIS;
/* Disable all the interrupts */
pMciHw->HSMCI_IDR = 0xFFFFFFFF;
/* Set the Data Timeout Register */
pMciHw->HSMCI_DTOR = HSMCI_DTOR_DTOCYC_Msk | HSMCI_DTOR_DTOMUL_Msk ;
/* CSTOR ? */
pMciHw->HSMCI_CSTOR = HSMCI_CSTOR_CSTOCYC_Msk | HSMCI_CSTOR_CSTOMUL_Msk ;
/* Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58) */
clkDiv = (dwMCk / (MCI_INITIAL_SPEED * 2)) - 1;
pMciHw->HSMCI_MR = (clkDiv | (HSMCI_MR_PWSDIV( 0x07 )) ) ;
/* Set the SDCard Register 1-bit, slot A */
pMciHw->HSMCI_SDCR = HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1 ;
/* Enable the MCI and the Power Saving */
pMciHw->HSMCI_CR = HSMCI_CR_MCIEN;
/* Configure MCI */
pMciHw->HSMCI_CFG = HSMCI_CFG_FIFOMODE
| ((1 << 4) & HSMCI_CFG_FERRCTRL);
/* Disable the MCI peripheral clock. */
PMC_DisablePeripheral(mciId);
}
/**
* Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
* MCK/2 and corresponds to CLKDIV = 0
* \param pMci Pointer to the low level MCI driver.
* \param mciSpeed MCI clock speed in Hz, 0 will not change current speed.
* \param mck MCK to generate MCI Clock, in Hz
* \return The actual speed used, 0 for fail.
*/
uint32_t MCI_SetSpeed( Mcid* pMci, uint32_t mciSpeed, uint32_t mck )
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t mciMr;
uint32_t clkdiv;
uint8_t mciDis;
assert(pMci);
assert(pMciHw);
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
mciMr = pMciHw->HSMCI_MR & (~(uint32_t)HSMCI_MR_CLKDIV_Msk);
/* Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
* divided by (2*(CLKDIV+1))
* mciSpeed = MCK / (2*(CLKDIV+1)) */
if (mciSpeed > 0)
{
clkdiv = (mck / 2 / mciSpeed);
/* Speed should not bigger than expired one */
if (mciSpeed < mck/2/clkdiv)
{
clkdiv ++;
}
if ( clkdiv > 0 )
{
clkdiv -= 1;
}
assert( (clkdiv & 0xFFFFFF00) == 0 ) ; /* "mciSpeed too small" */
}
else
{
clkdiv = 0 ;
}
/* Actual MCI speed */
mciSpeed = mck / 2 / (clkdiv + 1);
/* Modify MR */
pMciHw->HSMCI_MR = mciMr | clkdiv;
if ( mciDis )
{
PMC_DisablePeripheral( pMci->mciId ) ;
}
return (mciSpeed);
}
/**
* Configure the MCI_CFG to enable the HS mode
* \param pMci Pointer to the low level MCI driver.
* \param hsEnable 1 to enable, 0 to disable HS mode.
*/
uint8_t MCI_EnableHsMode(Mcid* pMci, uint8_t hsEnable)
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t cfgr;
uint8_t mciDis;
uint8_t rc = 0;
assert(pMci);
assert(pMci->pMciHw);
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
cfgr = pMciHw->HSMCI_CFG;
if (hsEnable == 1)
{
cfgr |= HSMCI_CFG_HSMODE;
}
else
{
if (hsEnable == 0)
{
cfgr &= ~(uint32_t)HSMCI_CFG_HSMODE;
}
else
{
rc = ((cfgr & HSMCI_CFG_HSMODE) != 0);
}
}
pMciHw->HSMCI_CFG = cfgr;
if (mciDis)
{
PMC_DisablePeripheral(pMci->mciId);
}
return rc;
}
/**
* Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available
*
* \param pMci Pointer to the low level MCI driver.
* \param busWidth MCI bus width mode. 00: 1-bit, 10: 4-bit, 11: 8-bit.
*/
uint32_t MCI_SetBusWidth(Mcid*pMci, uint32_t busWidth)
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t mciSdcr;
uint8_t mciDis;
assert(pMci);
assert(pMci->pMciHw);
if( (busWidth != HSMCI_SDCR_SDCBUS_1) && (busWidth != HSMCI_SDCR_SDCBUS_4) && (busWidth != HSMCI_SDCR_SDCBUS_8) )
{
return (uint32_t)-1;
}
busWidth &= HSMCI_SDCR_SDCBUS_Msk ;
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
mciSdcr = (pMciHw->HSMCI_SDCR & ~(uint32_t)(HSMCI_SDCR_SDCBUS_Msk));
pMciHw->HSMCI_SDCR = mciSdcr | busWidth;
if (mciDis)
{
PMC_DisablePeripheral(pMci->mciId);
}
return 0;
}

View File

@@ -0,0 +1,305 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of High Speed MultiMedia Card Interface (HSMCI) controller,
* using PDC to transfer data.
*
*/
/*---------------------------------------------------------------------------
* Headers
*---------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*---------------------------------------------------------------------------
* Local macros
*---------------------------------------------------------------------------*/
/** Reset MCI */
#define MCI_RESET(pMciHw) (pMciHw->HSMCI_CR = HSMCI_CR_SWRST)
/*---------------------------------------------------------------------------
* Exported functions
*---------------------------------------------------------------------------*/
/**
* Enable MCI
* \param pMciHw Pointer to a MCI peripheral.
*/
void MCI_Enable(Hsmci *pMciHw)
{
pMciHw->HSMCI_CR = HSMCI_CR_MCIEN;
}
/**
* Disable MCI
* \param pMciHw Pointer to a MCI peripheral.
*/
void MCI_Disable(Hsmci *pMciHw)
{
pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS;
}
/**
* Initializes a MCI driver instance and the underlying peripheral.
* \param pMci Pointer to a MCI driver instance.
* \param pMciHw Pointer to a MCI peripheral.
* \param mciId MCI peripheral identifier.
*/
void MCI_Init( Mcid *pMci, Hsmci *pMciHw, uint8_t mciId, uint32_t dwMCk )
{
unsigned short clkDiv;
/* Initialize the MCI driver structure */
pMci->pMciHw = pMciHw;
pMci->mciId = mciId;
pMci->semaphore = 1;
pMci->pCommand = NULL;
/* Enable the MCI peripheral */
PMC_EnablePeripheral( mciId ) ;
/* Reset the MCI */
pMciHw->HSMCI_CR = HSMCI_CR_SWRST;
/* Disable the MCI */
pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS | HSMCI_CR_PWSDIS;
/* Disable all the interrupts */
pMciHw->HSMCI_IDR = 0xFFFFFFFF;
/* Set the Data Timeout Register */
pMciHw->HSMCI_DTOR = HSMCI_DTOR_DTOCYC_Msk | HSMCI_DTOR_DTOMUL_Msk ;
/* CSTOR ? */
pMciHw->HSMCI_CSTOR = HSMCI_CSTOR_CSTOCYC_Msk | HSMCI_CSTOR_CSTOMUL_Msk ;
/* Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58) */
clkDiv = (dwMCk / (MCI_INITIAL_SPEED * 2)) - 1;
pMciHw->HSMCI_MR = (clkDiv | (HSMCI_MR_PWSDIV( 0x07 )) ) ;
/* Set the SDCard Register 1-bit, slot A */
pMciHw->HSMCI_SDCR = HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1 ;
/* Enable the MCI and the Power Saving */
pMciHw->HSMCI_CR = HSMCI_CR_MCIEN;
/* Configure MCI */
pMciHw->HSMCI_CFG = HSMCI_CFG_FIFOMODE
| ((1 << 4) & HSMCI_CFG_FERRCTRL);
/* Disable the MCI peripheral clock. */
PMC_DisablePeripheral(mciId);
}
/**
* Reset MCI HW interface and disable it.
* \param keepSettings Keep old register settings, including
* _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG.
*/
void MCI_Reset(Mcid *pMci, uint8_t keepSettings)
{
Hsmci *pMciHw = pMci->pMciHw;
uint8_t mciDis;
assert(pMci);
assert(pMci->pMciHw);
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
if (keepSettings)
{
uint32_t mr, sdcr, dtor, cstor;
uint32_t cfg;
mr = pMciHw->HSMCI_MR;
sdcr = pMciHw->HSMCI_SDCR;
dtor = pMciHw->HSMCI_DTOR;
cstor = pMciHw->HSMCI_CSTOR;
cfg = pMciHw->HSMCI_CFG;
MCI_RESET(pMciHw);
MCI_Disable(pMciHw);
pMciHw->HSMCI_MR = mr;
pMciHw->HSMCI_SDCR = sdcr;
pMciHw->HSMCI_DTOR = dtor;
pMciHw->HSMCI_CSTOR = cstor;
pMciHw->HSMCI_CFG = cfg;
}
else
{
MCI_RESET(pMciHw);
MCI_Disable(pMciHw);
}
if ( mciDis )
{
PMC_DisablePeripheral( pMci->mciId ) ;
}
}
/**
* Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
* MCK/2 and corresponds to CLKDIV = 0
* \param pMci Pointer to the low level MCI driver.
* \param mciSpeed MCI clock speed in Hz, 0 will not change current speed.
* \param mck MCK to generate MCI Clock, in Hz
* \return The actual speed used, 0 for fail.
*/
uint32_t MCI_SetSpeed( Mcid* pMci, uint32_t mciSpeed, uint32_t mck )
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t mciMr;
uint32_t clkdiv;
uint8_t mciDis;
assert(pMci);
assert(pMciHw);
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
mciMr = pMciHw->HSMCI_MR & (~(uint32_t)HSMCI_MR_CLKDIV_Msk);
/* Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
* divided by (2*(CLKDIV+1))
* mciSpeed = MCK / (2*(CLKDIV+1)) */
if (mciSpeed > 0)
{
clkdiv = (mck / 2 / mciSpeed);
/* Speed should not bigger than expired one */
if (mciSpeed < mck/2/clkdiv)
{
clkdiv ++;
}
if ( clkdiv > 0 )
{
clkdiv -= 1;
}
assert( (clkdiv & 0xFFFFFF00) == 0 ) ; /* "mciSpeed too small" */
}
else
{
clkdiv = 0 ;
}
/* Actual MCI speed */
mciSpeed = mck / 2 / (clkdiv + 1);
/* Modify MR */
pMciHw->HSMCI_MR = mciMr | clkdiv;
if ( mciDis )
{
PMC_DisablePeripheral( pMci->mciId ) ;
}
return (mciSpeed);
}
/**
* Configure the MCI_CFG to enable the HS mode
* \param pMci Pointer to the low level MCI driver.
* \param hsEnable 1 to enable, 0 to disable HS mode.
*/
uint8_t MCI_EnableHsMode(Mcid* pMci, uint8_t hsEnable)
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t cfgr;
uint8_t mciDis;
uint8_t rc = 0;
assert(pMci);
assert(pMci->pMciHw);
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
cfgr = pMciHw->HSMCI_CFG;
if (hsEnable == 1)
{
cfgr |= HSMCI_CFG_HSMODE;
}
else
{
if (hsEnable == 0)
{
cfgr &= ~(uint32_t)HSMCI_CFG_HSMODE;
}
else
{
rc = ((cfgr & HSMCI_CFG_HSMODE) != 0);
}
}
pMciHw->HSMCI_CFG = cfgr;
if (mciDis)
{
PMC_DisablePeripheral(pMci->mciId);
}
return rc;
}
/**
* Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available
*
* \param pMci Pointer to the low level MCI driver.
* \param busWidth MCI bus width mode. 00: 1-bit, 10: 4-bit, 11: 8-bit.
*/
uint32_t MCI_SetBusWidth(Mcid*pMci, uint32_t busWidth)
{
Hsmci *pMciHw = pMci->pMciHw;
uint32_t mciSdcr;
uint8_t mciDis;
assert(pMci);
assert(pMci->pMciHw);
if( (busWidth != HSMCI_SDCR_SDCBUS_1) && (busWidth != HSMCI_SDCR_SDCBUS_4) && (busWidth != HSMCI_SDCR_SDCBUS_8) )
{
return (uint32_t)-1;
}
busWidth &= HSMCI_SDCR_SDCBUS_Msk ;
PMC_EnablePeripheral(pMci->mciId);
mciDis = PMC_IsPeriphEnabled(pMci->mciId);
mciSdcr = (pMciHw->HSMCI_SDCR & ~(uint32_t)(HSMCI_SDCR_SDCBUS_Msk));
pMciHw->HSMCI_SDCR = mciSdcr | busWidth;
if (mciDis)
{
PMC_DisablePeripheral(pMci->mciId);
}
return 0;
}

View File

@@ -36,7 +36,6 @@
#include "pio.h"
#include "pmc.h"
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/

View File

@@ -0,0 +1,283 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup pio_capture_module Working with PIO Parallel Capture Mode
* The PIO Parallel Capture Mode driver provides the interface to configure and use the
* PIO Parallel Capture Mode peripheral.\n
*
* The PIO Controller integrates an interface able to read data from a CMOS digital
* image sensor, a high-speed parallel ADC, a DSP synchronous port in synchronous
* mode, etc.... For better understanding and to ease reading, the following
* description uses an example with a CMOS digital image sensor
*
* To use the PIO Parallel Capture, the user has to follow these few steps:
* <ul>
* <li> Enable PIOA peripheral clock </li>
* <li> Configure the PDC </li>
* <li> Configure the PIO Capture interrupt </li>
* <li> Enable the PDC </li>
* <li> Enable the PIO Capture </li>
* <li> Wait for interrupt </li>
* <li> Disable the interrupt </li>
* <li> Read the DATA </li>
* </ul>
*
* For more accurate information, please look at the PIO Parallel Capture Mode section of the
* Datasheet.
*
* Related files :\n
* \ref pio_capture.c\n
* \ref pio_capture.h\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of PIO Parallel Capture.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Local Functions
*----------------------------------------------------------------------------*/
/** Copy the API structure for interrupt handler */
static SpioCaptureInit* _PioCaptureCopy;
/*----------------------------------------------------------------------------
* Global Functions
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
* \brief The PIO_CaptureHandler must be called by the PIO Capture Interrupt
* Service Routine with the corresponding PIO Capture instance.
*/
/*----------------------------------------------------------------------------*/
extern void PIO_CaptureHandler( void )
{
volatile uint32_t pio_captureSr;
/* Read the status register*/
pio_captureSr = PIOA->PIO_PCISR ;
pio_captureSr &= PIOA->PIO_PCIMR ;
if (pio_captureSr & PIO_PCISR_DRDY)
{
/* Parallel Capture Mode Data Ready */
if ( _PioCaptureCopy->CbkDataReady != NULL )
{
_PioCaptureCopy->CbkDataReady( _PioCaptureCopy );
}
else
{
TRACE_DEBUG("IT PIO Capture Data Ready received (no callback)\n\r");
}
}
if (pio_captureSr & PIO_PCISR_OVRE)
{
/* Parallel Capture Mode Overrun Error */
if ( _PioCaptureCopy->CbkOverrun != NULL )
{
_PioCaptureCopy->CbkOverrun( _PioCaptureCopy );
}
else
{
TRACE_DEBUG("IT PIO Capture Overrun Error received (no callback)\n\r");
}
}
if (pio_captureSr & PIO_PCISR_RXBUFF)
{
/* Reception Buffer Full */
if ( _PioCaptureCopy->CbkBuffFull != NULL )
{
_PioCaptureCopy->CbkBuffFull( _PioCaptureCopy );
}
else
{
TRACE_DEBUG("IT PIO Capture Reception Buffer Full received (no callback)\n\r");
}
}
if (pio_captureSr & PIO_PCISR_ENDRX)
{
/* End of Reception Transfer */
if ( _PioCaptureCopy->CbkEndReception != NULL )
{
_PioCaptureCopy->CbkEndReception( _PioCaptureCopy );
}
else
{
TRACE_DEBUG("IT PIO Capture End of Reception Transfer received (no callback)\n\r");
}
}
}
/*----------------------------------------------------------------------------*/
/**
* \brief Disable Interupt of the PIO Capture
* \param itToDisable : Interrupt to disable
*/
/*----------------------------------------------------------------------------*/
void PIO_CaptureDisableIt( uint32_t itToDisable )
{
/* Parallel capture mode is enabled */
PIOA->PIO_PCIDR = itToDisable;
}
/*----------------------------------------------------------------------------*/
/**
* \brief Enable Interupt of the PIO Capture
* \param itToEnable : Interrupt to enable
*/
/*----------------------------------------------------------------------------*/
void PIO_CaptureEnableIt( uint32_t itToEnable )
{
/* Parallel capture mode is enabled */
PIOA->PIO_PCIER = itToEnable;
}
/*----------------------------------------------------------------------------*/
/**
* \brief Enable the PIO Capture
*/
/*----------------------------------------------------------------------------*/
void PIO_CaptureEnable( void )
{
/* PDC: Receive Pointer Register */
PIOA->PIO_RPR = (uint32_t)_PioCaptureCopy->pData ;
/* PDC: Receive Counter Register */
/* Starts peripheral data transfer if corresponding channel is active */
PIOA->PIO_RCR = PIO_RCR_RXCTR(_PioCaptureCopy->dPDCsize) ;
/* Parallel capture mode is enabled */
PIOA->PIO_PCMR |= PIO_PCMR_PCEN ;
}
/*----------------------------------------------------------------------------*/
/**
* \brief Disable the PIO Capture
*/
/*----------------------------------------------------------------------------*/
void PIO_CaptureDisable( void )
{
/* Parallel capture mode is disabled */
PIOA->PIO_PCMR &= (uint32_t)(~PIO_PCMR_PCEN) ;
}
/*----------------------------------------------------------------------------*/
/**
* \brief Initialize the PIO Capture
* Be careful to configure the PDC before enable interrupt on pio capture.
* Otherway, the pdc will go in interrupt handler continuously.
* \param dsize :
* 0 = The reception data in the PIO_PCRHR register is a BYTE (8-bit).
* 1 = The reception data in the PIO_PCRHR register is a HALF-WORD (16-bit).
* 2/3 = The reception data in the PIO_PCRHR register is a WORD (32-bit).
* \param alwaysSampling: ALWYS: Parallel Capture Mode Always Sampling
* 0 = The parallel capture mode samples the data when both data enables are active.
* 1 = The parallel capture mode samples the data whatever the data enables are.
* \param halfSampling: HALFS: Parallel Capture Mode Half Sampling
* 0 = The parallel capture mode samples all the data.
* 1 = The parallel capture mode samples the data only one time out of two.
* \param modeFirstSample: FRSTS: Parallel Capture Mode First Sample
* This bit is useful only if the HALFS bit is set to 1. If data are numbered
* in the order that they are received with an index from 0 to n:
* 0 = Only data with an even index are sampled.
* 1 = Only data with an odd index are sampled.
*/
/*----------------------------------------------------------------------------*/
void PIO_CaptureInit( SpioCaptureInit *pInit )
{
PMC_EnablePeripheral( ID_PIOA );
assert( (pInit->dsize < 0x4) ) ;
assert( (pInit->dPDCsize <= PIO_RPR_RXPTR_Msk) ) ;
assert( (pInit->alwaysSampling < 2) );
assert( (pInit->halfSampling < 2) );
assert( (pInit->modeFirstSample < 2) );
/* PDC: Transfer Control Register */
/* Disables the PDC transmitter channel requests */
PIOA->PIO_PTCR = PIO_PTCR_RXTDIS;
/* PDC: Receive Pointer Register */
PIOA->PIO_RPR = (uint32_t)pInit->pData;
/* PDC: Receive Counter Register */
/* Starts peripheral data transfer if corresponding channel is active */
PIOA->PIO_RCR = PIO_RCR_RXCTR(pInit->dPDCsize);
/* PDC: Transfer Control Register */
/* Enables PDC receiver channel requests if RXTDIS is not set */
PIOA->PIO_PTCR = PIO_PTCR_RXTEN ;
/* Copy the API structure for interrupt handler */
_PioCaptureCopy = pInit;
/* PIO Parallel Capture Mode */
PIOA->PIO_PCMR = PIO_PCMR_DSIZE(pInit->dsize)
| ((pInit->alwaysSampling<<9) & PIO_PCMR_ALWYS)
| ((pInit->halfSampling<<10) & PIO_PCMR_HALFS)
| ((pInit->modeFirstSample<<11) & PIO_PCMR_FRSTS);
if ( pInit->CbkDataReady != NULL )
{
PIOA->PIO_PCIER = PIO_PCISR_DRDY;
}
if ( pInit->CbkOverrun != NULL )
{
PIOA->PIO_PCIER = PIO_PCISR_OVRE;
}
if ( pInit->CbkEndReception != NULL )
{
PIOA->PIO_PCIER = PIO_PCISR_ENDRX;
}
if ( pInit->CbkBuffFull != NULL )
{
PIOA->PIO_PCIER = PIO_PCISR_RXBUFF;
}
// else
// {
// TRACE_INFO("No interruption, no callback\n\r");
// }
}

View File

@@ -0,0 +1,315 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
* \file
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Local definitions
*----------------------------------------------------------------------------*/
/* Maximum number of interrupt sources that can be defined. This
* constant can be increased, but the current value is the smallest possible
* that will be compatible with all existing projects. */
#define MAX_INTERRUPT_SOURCES 7
/*----------------------------------------------------------------------------
* Local types
*----------------------------------------------------------------------------*/
/**
* Describes a PIO interrupt source, including the PIO instance triggering the
* interrupt and the associated interrupt handler.
*/
typedef struct _InterruptSource
{
/* Pointer to the source pin instance. */
const Pin *pPin;
/* Interrupt handler. */
void (*handler)( const Pin* ) ;
} InterruptSource ;
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/* List of interrupt sources. */
static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
/* Number of currently defined interrupt sources. */
static uint32_t _dwNumSources = 0;
/*----------------------------------------------------------------------------
* Local Functions
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
* \brief Stub, to handling all PIO Capture interrupts, if not defined.
*/
/*----------------------------------------------------------------------------*/
//extern WEAK void PIO_CaptureHandler( void )
//{
//}
/**
* \brief Handles all interrupts on the given PIO controller.
* \param id PIO controller ID.
* \param pPio PIO controller base address.
*/
extern void PioInterruptHandler( uint32_t id, Pio *pPio )
{
uint32_t status;
uint32_t i;
/* Read PIO controller status */
status = pPio->PIO_ISR;
status &= pPio->PIO_IMR;
/* Check pending events */
if ( status != 0 )
{
TRACE_DEBUG( "PIO interrupt on PIO controller #%d\n\r", id ) ;
/* Find triggering source */
i = 0;
while ( status != 0 )
{
/* There cannot be an unconfigured source enabled. */
assert(i < _dwNumSources);
/* Source is configured on the same controller */
if (_aIntSources[i].pPin->id == id)
{
/* Source has PIOs whose statuses have changed */
if ( (status & _aIntSources[i].pPin->mask) != 0 )
{
TRACE_DEBUG( "Interrupt source #%d triggered\n\r", i ) ;
_aIntSources[i].handler(_aIntSources[i].pPin);
status &= ~(_aIntSources[i].pPin->mask);
}
}
i++;
}
}
}
/*----------------------------------------------------------------------------
* Global Functions
*----------------------------------------------------------------------------*/
/**
* \brief Parallel IO Controller A interrupt handler
* \Redefined PIOA interrupt handler for NVIC interrupt table.
*/
extern void PIOA_IrqHandler( void )
{
if ( PIOA->PIO_PCISR != 0 )
{
PIO_CaptureHandler() ;
}
PioInterruptHandler( ID_PIOA, PIOA ) ;
}
/**
* \brief Parallel IO Controller B interrupt handler
* \Redefined PIOB interrupt handler for NVIC interrupt table.
*/
extern void PIOB_IrqHandler( void )
{
PioInterruptHandler( ID_PIOB, PIOB ) ;
}
/**
* \brief Parallel IO Controller C interrupt handler
* \Redefined PIOC interrupt handler for NVIC interrupt table.
*/
extern void PIOC_IrqHandler( void )
{
PioInterruptHandler( ID_PIOC, PIOC ) ;
}
/**
* \brief Initializes the PIO interrupt management logic
*
* The desired priority of PIO interrupts must be provided.
* Calling this function multiple times result in the reset of currently
* configured interrupts.
*
* \param priority PIO controller interrupts priority.
*/
extern void PIO_InitializeInterrupts( uint32_t dwPriority )
{
TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
/* Reset sources */
_dwNumSources = 0 ;
/* Configure PIO interrupt sources */
TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
PMC_EnablePeripheral( ID_PIOA ) ;
PIOA->PIO_ISR ;
PIOA->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOA_IRQn ) ;
NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOA_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
PMC_EnablePeripheral( ID_PIOB ) ;
PIOB->PIO_ISR ;
PIOB->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOB_IRQn ) ;
NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOB_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
PMC_EnablePeripheral( ID_PIOC ) ;
PIOC->PIO_ISR ;
PIOC->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOC_IRQn ) ;
NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOC_IRQn ) ;
}
/**
* Configures a PIO or a group of PIO to generate an interrupt on status
* change. The provided interrupt handler will be called with the triggering
* pin as its parameter (enabling different pin instances to share the same
* handler).
* \param pPin Pointer to a Pin instance.
* \param handler Interrupt handler function pointer.
*/
extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
{
Pio* pio ;
InterruptSource* pSource ;
TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
assert( pPin ) ;
pio = pPin->pio ;
assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
/* Define new source */
TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources ) ;
pSource = &(_aIntSources[_dwNumSources]) ;
pSource->pPin = pPin ;
pSource->handler = handler ;
_dwNumSources++ ;
/* PIO3 with additional interrupt support
* Configure additional interrupt mode registers */
if ( pPin->attribute & PIO_IT_AIME )
{
// enable additional interrupt mode
pio->PIO_AIMER = pPin->mask ;
// if bit field of selected pin is 1, set as Rising Edge/High level detection event
if ( pPin->attribute & PIO_IT_RE_OR_HL )
{
pio->PIO_REHLSR = pPin->mask ;
}
else
{
pio->PIO_FELLSR = pPin->mask;
}
/* if bit field of selected pin is 1, set as edge detection source */
if (pPin->attribute & PIO_IT_EDGE)
pio->PIO_ESR = pPin->mask;
else
pio->PIO_LSR = pPin->mask;
}
else
{
/* disable additional interrupt mode */
pio->PIO_AIMDR = pPin->mask;
}
}
/**
* Enables the given interrupt source if it has been configured. The status
* register of the corresponding PIO controller is cleared prior to enabling
* the interrupt.
* \param pPin Interrupt source to enable.
*/
extern void PIO_EnableIt( const Pin *pPin )
{
TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;
assert( pPin != NULL ) ;
#ifndef NOASSERT
uint32_t i = 0;
uint32_t dwFound = 0;
while ( (i < _dwNumSources) && !dwFound )
{
if ( _aIntSources[i].pPin == pPin )
{
dwFound = 1 ;
}
i++ ;
}
assert( dwFound != 0 ) ;
#endif
pPin->pio->PIO_ISR;
pPin->pio->PIO_IER = pPin->mask ;
}
/**
* Disables a given interrupt source, with no added side effects.
*
* \param pPin Interrupt source to disable.
*/
extern void PIO_DisableIt( const Pin *pPin )
{
assert( pPin != NULL ) ;
TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
pPin->pio->PIO_IDR = pPin->mask;
}

View File

@@ -32,6 +32,7 @@
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "trace.h"
#include <assert.h>
@@ -62,6 +63,7 @@ extern void PMC_EnablePeripheral( uint32_t dwId )
{
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) )
{
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId ) ;
}
else
{
@@ -73,6 +75,7 @@ extern void PMC_EnablePeripheral( uint32_t dwId )
dwId -= 32;
if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId))
{
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId + 32 ) ;
}
else
{
@@ -97,6 +100,7 @@ extern void PMC_DisablePeripheral( uint32_t dwId )
{
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{
TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %u is not enabled\n\r", dwId ) ;
}
else
{
@@ -108,6 +112,7 @@ extern void PMC_DisablePeripheral( uint32_t dwId )
dwId -= 32 ;
if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{
TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %u is not enabled\n\r", dwId + 32 ) ;
}
else
{
@@ -127,6 +132,7 @@ extern void PMC_EnableAllPeripherals( void )
PMC->PMC_PCER1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ;
TRACE_DEBUG( "Enable all periph clocks\n\r" ) ;
}
/**
@@ -140,6 +146,7 @@ extern void PMC_DisableAllPeripherals( void )
PMC->PMC_PCDR1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ;
TRACE_DEBUG( "Disable all periph clocks\n\r" ) ;
}
/**

View File

@@ -0,0 +1,608 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup pwm_module Working with PWM
* The PWM driver provides the interface to configure and use the PWM
* peripheral.
*
* The PWM macrocell controls square output waveforms of 4 channels.
* Characteristics of output waveforms such as period, duty-cycle,
* dead-time can be configured.\n
* Some of PWM channels can be linked together as synchronous channel and
* duty-cycle of synchronous channels can be updated by PDC automaticly.
*
* Before enabling the channels, they must have been configured first.
* The main settings include:
* <ul>
* <li>Configuration of the clock generator.</li>
* <li>Selection of the clock for each channel.</li>
* <li>Configuration of output waveform characteristics, such as period, duty-cycle etc.</li>
* <li>Configuration for synchronous channels if needed.</li>
* - Selection of the synchronous channels.
* - Selection of the moment when the WRDY flag and the corresponding PDC
* transfer request are set (PTRM and PTRCS in the PWM_SCM register).
* - Configuration of the update mode (UPDM in the PWM_SCM register).
* - Configuration of the update period (UPR in the PWM_SCUP register).
* </ul>
*
* After the channels is enabled, the user must use respective update registers
* to change the wave characteristics to prevent unexpected output waveform.
* i.e. PWM_CDTYUPDx register should be used if user want to change duty-cycle
* when the channel is enabled.
*
* For more accurate information, please look at the PWM section of the
* Datasheet.
*
* Related files :\n
* \ref pwmc.c\n
* \ref pwmc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of the Pulse Width Modulation Controller (PWM) peripheral.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Finds a prescaler/divisor couple to generate the desired frequency
* from MCK.
*
* Returns the value to enter in PWM_CLK or 0 if the configuration cannot be
* met.
*
* \param frequency Desired frequency in Hz.
* \param mck Master clock frequency in Hz.
*/
static uint16_t FindClockConfiguration(
uint32_t frequency,
uint32_t mck)
{
uint32_t divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
uint8_t divisor = 0;
uint32_t prescaler;
assert(frequency < mck);
/* Find prescaler and divisor values */
prescaler = (mck / divisors[divisor]) / frequency;
while ((prescaler > 255) && (divisor < 11)) {
divisor++;
prescaler = (mck / divisors[divisor]) / frequency;
}
/* Return result */
if ( divisor < 11 )
{
TRACE_DEBUG( "Found divisor=%u and prescaler=%u for freq=%uHz\n\r", divisors[divisor], prescaler, frequency ) ;
return prescaler | (divisor << 8) ;
}
else
{
return 0 ;
}
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures PWM a channel with the given parameters, basic configure function.
*
* The PWM controller must have been clocked in the PMC prior to calling this
* function.
* Beware: this function disables the channel. It waits until disable is effective.
*
* \param channel Channel number.
* \param prescaler Channel prescaler.
* \param alignment Channel alignment.
* \param polarity Channel polarity.
*/
void PWMC_ConfigureChannel(
Pwm* pPwm,
uint8_t channel,
uint32_t prescaler,
uint32_t alignment,
uint32_t polarity)
{
pPwm->PWM_CH_NUM[0].PWM_CMR = 1;
// assert(prescaler < PWM_CMR0_CPRE_MCKB);
assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
/* Disable channel (effective at the end of the current period) */
if ((pPwm->PWM_SR & (1 << channel)) != 0) {
pPwm->PWM_DIS = 1 << channel;
while ((pPwm->PWM_SR & (1 << channel)) != 0);
}
/* Configure channel */
pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity;
}
/**
* \brief Configures PWM a channel with the given parameters, extend configure function.
*
* The PWM controller must have been clocked in the PMC prior to calling this
* function.
* Beware: this function disables the channel. It waits until disable is effective.
*
* \param channel Channel number.
* \param prescaler Channel prescaler.
* \param alignment Channel alignment.
* \param polarity Channel polarity.
* \param countEventSelect Channel counter event selection.
* \param DTEnable Channel dead time generator enable.
* \param DTHInverte Channel Dead-Time PWMHx output Inverted.
* \param DTLInverte Channel Dead-Time PWMHx output Inverted.
*/
void PWMC_ConfigureChannelExt(
Pwm* pPwm,
uint8_t channel,
uint32_t prescaler,
uint32_t alignment,
uint32_t polarity,
uint32_t countEventSelect,
uint32_t DTEnable,
uint32_t DTHInverte,
uint32_t DTLInverte)
{
// assert(prescaler < PWM_CMR0_CPRE_MCKB);
assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
assert((countEventSelect & (uint32_t)~PWM_CMR_CES) == 0);
assert((DTEnable & (uint32_t)~PWM_CMR_DTE) == 0);
assert((DTHInverte & (uint32_t)~PWM_CMR_DTHI) == 0);
assert((DTLInverte & (uint32_t)~PWM_CMR_DTLI) == 0);
/* Disable channel (effective at the end of the current period) */
if ((pPwm->PWM_SR & (1 << channel)) != 0) {
pPwm->PWM_DIS = 1 << channel;
while ((pPwm->PWM_SR & (1 << channel)) != 0);
}
/* Configure channel */
pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity |
countEventSelect | DTEnable | DTHInverte | DTLInverte;
}
/**
* \brief Configures PWM clocks A & B to run at the given frequencies.
*
* This function finds the best MCK divisor and prescaler values automatically.
*
* \param clka Desired clock A frequency (0 if not used).
* \param clkb Desired clock B frequency (0 if not used).
* \param mck Master clock frequency.
*/
void PWMC_ConfigureClocks(uint32_t clka, uint32_t clkb, uint32_t mck)
{
uint32_t mode = 0;
uint32_t result;
/* Clock A */
if (clka != 0) {
result = FindClockConfiguration(clka, mck);
assert( result != 0 ) ;
mode |= result;
}
/* Clock B */
if (clkb != 0) {
result = FindClockConfiguration(clkb, mck);
assert( result != 0 ) ;
mode |= (result << 16);
}
/* Configure clocks */
TRACE_DEBUG( "Setting PWM_CLK = 0x%08X\n\r", mode ) ;
PWM->PWM_CLK = mode;
}
/**
* \brief Sets the period value used by a PWM channel.
*
* This function writes directly to the CPRD register if the channel is disabled;
* otherwise, it uses the update register CPRDUPD.
*
* \param channel Channel number.
* \param period Period value.
*/
void PWMC_SetPeriod( Pwm* pPwm, uint8_t channel, uint16_t period)
{
/* If channel is disabled, write to CPRD */
if ((pPwm->PWM_SR & (1 << channel)) == 0) {
pPwm->PWM_CH_NUM[channel].PWM_CPRD = period;
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[channel].PWM_CPRDUPD = period;
}
}
/**
* \brief Sets the duty cycle used by a PWM channel.
* This function writes directly to the CDTY register if the channel is disabled;
* otherwise it uses the update register CDTYUPD.
* Note that the duty cycle must always be inferior or equal to the channel
* period.
*
* \param channel Channel number.
* \param duty Duty cycle value.
*/
void PWMC_SetDutyCycle( Pwm* pPwm, uint8_t channel, uint16_t duty)
{
assert(duty <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
/* If channel is disabled, write to CDTY */
if ((pPwm->PWM_SR & (1 << channel)) == 0) {
pPwm->PWM_CH_NUM[channel].PWM_CDTY = duty;
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[channel].PWM_CDTYUPD = duty;
}
}
/**
* \brief Sets the dead time used by a PWM channel.
* This function writes directly to the DT register if the channel is disabled;
* otherwise it uses the update register DTUPD.
* Note that the dead time must always be inferior or equal to the channel
* period.
*
* \param channel Channel number.
* \param timeH Dead time value for PWMHx output.
* \param timeL Dead time value for PWMLx output.
*/
void PWMC_SetDeadTime( Pwm* pPwm, uint8_t channel, uint16_t timeH, uint16_t timeL)
{
assert(timeH <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
assert(timeL <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
/* If channel is disabled, write to DT */
if ((pPwm->PWM_SR & (1 << channel)) == 0) {
pPwm->PWM_CH_NUM[channel].PWM_DT = timeH | (timeL << 16);
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[channel].PWM_DTUPD = timeH | (timeL << 16);
}
}
/**
* \brief Configures Syncronous channel with the given parameters.
* Beware: At this time, the channels should be disabled.
*
* \param channels Bitwise OR of Syncronous channels.
* \param updateMode Syncronous channel update mode.
* \param requestMode PDC transfer request mode.
* \param requestComparisonSelect PDC transfer request comparison selection.
*/
void PWMC_ConfigureSyncChannel( Pwm* pPwm,
uint32_t channels,
uint32_t updateMode,
uint32_t requestMode,
uint32_t requestComparisonSelect)
{
pPwm->PWM_SCM = channels | updateMode | requestMode | requestComparisonSelect;
}
/**
* \brief Sets the update period of the synchronous channels.
* This function writes directly to the SCUP register if the channel #0 is disabled;
* otherwise it uses the update register SCUPUPD.
*
* \param period update period.
*/
void PWMC_SetSyncChannelUpdatePeriod( Pwm* pPwm, uint8_t period)
{
/* If channel is disabled, write to SCUP */
if ((pPwm->PWM_SR & (1 << 0)) == 0) {
pPwm->PWM_SCUP = period;
}
/* Otherwise use update register */
else {
pPwm->PWM_SCUPUPD = period;
}
}
/**
* \brief Sets synchronous channels update unlock.
*
* Note: If the UPDM field is set to 0, writing the UPDULOCK bit to 1
* triggers the update of the period value, the duty-cycle and
* the dead-time values of synchronous channels at the beginning
* of the next PWM period. If the field UPDM is set to 1 or 2,
* writing the UPDULOCK bit to 1 triggers only the update of
* the period value and of the dead-time values of synchronous channels.
* This bit is automatically reset when the update is done.
*/
void PWMC_SetSyncChannelUpdateUnlock( Pwm* pPwm )
{
pPwm->PWM_SCUC = PWM_SCUC_UPDULOCK;
}
/**
* \brief Enables the given PWM channel.
*
* This does NOT enable the corresponding pin;this must be done in the user code.
*
* \param channel Channel number.
*/
void PWMC_EnableChannel( Pwm* pPwm, uint8_t channel)
{
pPwm->PWM_ENA = 1 << channel;
}
/**
* \brief Disables the given PWM channel.
*
* Beware, channel will be effectively disabled at the end of the current period.
* Application can check channel is disabled using the following wait loop:
* while ((PWM->PWM_SR & (1 << channel)) != 0);
*
* \param channel Channel number.
*/
void PWMC_DisableChannel( Pwm* pPwm, uint8_t channel)
{
pPwm->PWM_DIS = 1 << channel;
}
/**
* \brief Enables the period interrupt for the given PWM channel.
*
* \param channel Channel number.
*/
void PWMC_EnableChannelIt( Pwm* pPwm, uint8_t channel)
{
pPwm->PWM_IER1 = 1 << channel;
}
/**
* \brief Disables the period interrupt for the given PWM channel.
*
* \param channel Channel number.
*/
void PWMC_DisableChannelIt( Pwm* pPwm, uint8_t channel)
{
pPwm->PWM_IDR1 = 1 << channel;
}
/**
* \brief Enables the selected interrupts sources on a PWMC peripheral.
*
* \param sources1 Bitwise OR of selected interrupt sources of PWM_IER1.
* \param sources2 Bitwise OR of selected interrupt sources of PWM_IER2.
*/
void PWMC_EnableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2)
{
pPwm->PWM_IER1 = sources1;
pPwm->PWM_IER2 = sources2;
}
/**
* \brief Disables the selected interrupts sources on a PWMC peripheral.
*
* \param sources1 Bitwise OR of selected interrupt sources of PWM_IDR1.
* \param sources2 Bitwise OR of selected interrupt sources of PWM_IDR2.
*/
void PWMC_DisableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2)
{
pPwm->PWM_IDR1 = sources1;
pPwm->PWM_IDR2 = sources2;
}
/**
* \brief Sends the contents of buffer through a PWMC peripheral, using the PDC to
* take care of the transfer.
*
* Note: Duty cycle of syncronous channels can update by PDC
* when the field UPDM (Update Mode) in the PWM_SCM register is set to 2.
*
* \param pwmc Pointer to an Pwm instance.
* \param buffer Data buffer to send.
* \param length Length of the data buffer.
*/
uint8_t PWMC_WriteBuffer(Pwm *pwmc,
void *buffer,
uint32_t length)
{
/* Check if first bank is free */
if (pwmc->PWM_TCR == 0) {
pwmc->PWM_TPR = (uint32_t) buffer;
pwmc->PWM_TCR = length;
pwmc->PWM_PTCR = PERIPH_PTCR_TXTEN;
return 1;
}
/* Check if second bank is free */
else if (pwmc->PWM_TNCR == 0) {
pwmc->PWM_TNPR = (uint32_t) buffer;
pwmc->PWM_TNCR = length;
return 1;
}
/* No free banks */
return 0;
}
/**
* \brief Set PWM output override value.
*
* \param value Bitwise OR of output override value.
*/
void PWMC_SetOverrideValue( Pwm* pPwm, uint32_t value)
{
pPwm->PWM_OOV = value;
}
/**
* \brief Enalbe override output.
*
* \param value Bitwise OR of output selection.
* \param sync 0: enable the output asyncronously, 1: enable it syncronously
*/
void PWMC_EnableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync)
{
if (sync) {
pPwm->PWM_OSSUPD = value;
} else {
pPwm->PWM_OSS = value;
}
}
/**
* \brief Disalbe override output.
*
* \param value Bitwise OR of output selection.
* \param sync 0: enable the output asyncronously, 1: enable it syncronously
*/
void PWMC_DisableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync)
{
if (sync) {
pPwm->PWM_OSCUPD = value;
} else {
pPwm->PWM_OSC = value;
}
}
/**
* \brief Set PWM fault mode.
*
* \param mode Bitwise OR of fault mode.
*/
void PWMC_SetFaultMode( Pwm* pPwm, uint32_t mode)
{
pPwm->PWM_FMR = mode;
}
/**
* \brief PWM fault clear.
*
* \param fault Bitwise OR of fault to clear.
*/
void PWMC_FaultClear( Pwm* pPwm, uint32_t fault)
{
pPwm->PWM_FCR = fault;
}
/**
* \brief Set PWM fault protection value.
*
* \param value Bitwise OR of fault protection value.
*/
void PWMC_SetFaultProtectionValue( Pwm* pPwm, uint32_t value)
{
pPwm->PWM_FPV = value;
}
/**
* \brief Enable PWM fault protection.
*
* \param value Bitwise OR of FPEx[y].
*/
void PWMC_EnableFaultProtection( Pwm* pPwm, uint32_t value)
{
pPwm->PWM_FPE = value;
}
/**
* \brief Configure comparison unit.
*
* \param x comparison x index
* \param value comparison x value.
* \param mode comparison x mode
*/
void PWMC_ConfigureComparisonUnit( Pwm* pPwm, uint32_t x, uint32_t value, uint32_t mode)
{
assert(x < 8);
/* If channel is disabled, write to CMPxM & CMPxV */
if ((pPwm->PWM_SR & (1 << 0)) == 0) {
pPwm->PWM_CMP[x].PWM_CMPxM = mode;
pPwm->PWM_CMP[x].PWM_CMPxV = value;
}
/* Otherwise use update register */
else {
pPwm->PWM_CMP[x].PWM_CMPxMUPD = mode;
pPwm->PWM_CMP[x].PWM_CMPxVUPD = value;
}
}
/**
* \brief Configure event line mode.
*
* \param x Line x
* \param mode Bitwise OR of line mode selection
*/
void PWMC_ConfigureEventLineMode( Pwm* pPwm, uint32_t x, uint32_t mode)
{
assert(x < 2);
if (x == 0) {
pPwm->PWM_ELxMR[0] = mode;
} else if (x == 1) {
pPwm->PWM_ELxMR[1] = mode;
}
}

View File

@@ -0,0 +1,464 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup rtc_module Working with RTC
* The RTC driver provides the interface to configure and use the RTC
* peripheral.
*
* It manages date, time, and alarms.\n
* This timer is clocked by the 32kHz system clock, and is not impacted by
* power management settings (PMC). To be accurate, it is better to use an
* external 32kHz crystal instead of the internal 32kHz RC.\n
*
* It uses BCD format, and time can be set in AM/PM or 24h mode through a
* configuration bit in the mode register.\n
*
* To update date or time, the user has to follow these few steps :
* <ul>
* <li>Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,</li>
* <li>Polling or IRQ on the ACKUPD bit of RTC_CR,</li>
* <li>Clear ACKUPD bit in RTC_SCCR,</li>
* <li>Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),</li>
* <li>Clear UPDTIM and/or UPDCAL bit in RTC_CR.</li>
* </ul>
* An alarm can be set to happen on month, date, hours, minutes or seconds,
* by setting the proper "Enable" bit of each of these fields in the Time and
* Calendar registers.
* This allows a large number of configurations to be available for the user.
* Alarm occurence can be detected even by polling or interrupt.
*
* A check of the validity of the date and time format and values written by the user is automatically done.
* Errors are reported through the Valid Entry Register.
*
* For more accurate information, please look at the RTC section of the
* Datasheet.
*
* Related files :\n
* \ref rtc.c\n
* \ref rtc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Real Time Clock (RTC) controller.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Sets the RTC in either 12 or 24 hour mode.
*
* \param mode Hour mode.
*/
extern void RTC_SetHourMode( Rtc* pRtc, uint32_t dwMode )
{
assert((dwMode & 0xFFFFFFFE) == 0);
pRtc->RTC_MR = dwMode ;
}
/**
* \brief Gets the RTC mode.
*
* \return Hour mode.
*/
extern uint32_t RTC_GetHourMode( Rtc* pRtc )
{
uint32_t dwMode ;
TRACE_DEBUG( "RTC_SetHourMode()\n\r" ) ;
dwMode = pRtc->RTC_MR;
dwMode &= 0xFFFFFFFE;
return dwMode ;
}
/**
* \brief Enables the selected interrupt sources of the RTC.
*
* \param sources Interrupt sources to enable.
*/
extern void RTC_EnableIt( Rtc* pRtc, uint32_t dwSources )
{
assert((dwSources & (uint32_t)(~0x1F)) == 0);
TRACE_DEBUG( "RTC_EnableIt()\n\r" ) ;
pRtc->RTC_IER = dwSources ;
}
/**
* \brief Disables the selected interrupt sources of the RTC.
*
* \param sources Interrupt sources to disable.
*/
extern void RTC_DisableIt( Rtc* pRtc, uint32_t dwSources )
{
assert((dwSources & (uint32_t)(~0x1F)) == 0);
TRACE_DEBUG( "RTC_DisableIt()\n\r" ) ;
pRtc->RTC_IDR = dwSources ;
}
/**
* \brief Sets the current time in the RTC.
*
* \note In successive update operations, the user must wait at least one second
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
* bits again. Please look at the RTC section of the datasheet for detail.
*
* \param ucHour Current hour in 12 or 24 hour mode.
* \param ucMinute Current minute.
* \param ucSecond Current second.
*
* \return 0 sucess, 1 fail to set
*/
extern int RTC_SetTime( Rtc* pRtc, uint8_t ucHour, uint8_t ucMinute, uint8_t ucSecond )
{
uint32_t dwTime=0 ;
uint8_t ucHour_bcd ;
uint8_t ucMin_bcd ;
uint8_t ucSec_bcd ;
TRACE_DEBUG( "RTC_SetTime(%02d:%02d:%02d)\n\r", ucHour, ucMinute, ucSecond ) ;
/* if 12-hour mode, set AMPM bit */
if ( (pRtc->RTC_MR & RTC_MR_HRMOD) == RTC_MR_HRMOD )
{
if ( ucHour > 12 )
{
ucHour -= 12 ;
dwTime |= RTC_TIMR_AMPM ;
}
}
ucHour_bcd = (ucHour%10) | ((ucHour/10)<<4) ;
ucMin_bcd = (ucMinute%10) | ((ucMinute/10)<<4) ;
ucSec_bcd = (ucSecond%10) | ((ucSecond/10)<<4) ;
/* value overflow */
if ( (ucHour_bcd & (uint8_t)(~RTC_HOUR_BIT_LEN_MASK)) |
(ucMin_bcd & (uint8_t)(~RTC_MIN_BIT_LEN_MASK)) |
(ucSec_bcd & (uint8_t)(~RTC_SEC_BIT_LEN_MASK)))
{
return 1 ;
}
dwTime = ucSec_bcd | (ucMin_bcd << 8) | (ucHour_bcd<<16) ;
pRtc->RTC_CR |= RTC_CR_UPDTIM ;
while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
pRtc->RTC_SCCR = RTC_SCCR_ACKCLR ;
pRtc->RTC_TIMR = dwTime ;
pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDTIM) ;
pRtc->RTC_SCCR |= RTC_SCCR_SECCLR ;
return (int)(pRtc->RTC_VER & RTC_VER_NVTIM) ;
}
/**
* \brief Retrieves the current time as stored in the RTC in several variables.
*
* \param pucHour If not null, current hour is stored in this variable.
* \param pucMinute If not null, current minute is stored in this variable.
* \param pucSecond If not null, current second is stored in this variable.
*/
extern void RTC_GetTime( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond )
{
uint32_t dwTime ;
TRACE_DEBUG( "RTC_GetTime()\n\r" ) ;
/* Get current RTC time */
dwTime = pRtc->RTC_TIMR ;
while ( dwTime != pRtc->RTC_TIMR )
{
dwTime = pRtc->RTC_TIMR ;
}
/* Hour */
if ( pucHour )
{
*pucHour = ((dwTime & 0x00300000) >> 20) * 10
+ ((dwTime & 0x000F0000) >> 16);
if ( (dwTime & RTC_TIMR_AMPM) == RTC_TIMR_AMPM )
{
*pucHour += 12 ;
}
}
/* Minute */
if ( pucMinute )
{
*pucMinute = ((dwTime & 0x00007000) >> 12) * 10
+ ((dwTime & 0x00000F00) >> 8);
}
/* Second */
if ( pucSecond )
{
*pucSecond = ((dwTime & 0x00000070) >> 4) * 10
+ (dwTime & 0x0000000F);
}
}
/**
* \brief Sets a time alarm on the RTC.
* The match is performed only on the provided variables;
* Setting all pointers to 0 disables the time alarm.
*
* \note In AM/PM mode, the hour value must have bit #7 set for PM, cleared for
* AM (as expected in the time registers).
*
* \param pucHour If not null, the time alarm will hour-match this value.
* \param pucMinute If not null, the time alarm will minute-match this value.
* \param pucSecond If not null, the time alarm will second-match this value.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetTimeAlarm( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond )
{
uint32_t dwAlarm=0 ;
TRACE_DEBUG( "RTC_SetTimeAlarm()\n\r" ) ;
/* Hour */
if ( pucHour )
{
dwAlarm |= RTC_TIMALR_HOUREN | ((*pucHour / 10) << 20) | ((*pucHour % 10) << 16);
}
/* Minute */
if ( pucMinute )
{
dwAlarm |= RTC_TIMALR_MINEN | ((*pucMinute / 10) << 12) | ((*pucMinute % 10) << 8);
}
/* Second */
if ( pucSecond )
{
dwAlarm |= RTC_TIMALR_SECEN | ((*pucSecond / 10) << 4) | (*pucSecond % 10);
}
pRtc->RTC_TIMALR = dwAlarm ;
return (int)(pRtc->RTC_VER & RTC_VER_NVTIMALR) ;
}
/**
* \brief Retrieves the current year, month and day from the RTC.
* Month, day and week values are numbered starting at 1.
*
* \param pYwear Current year (optional).
* \param pucMonth Current month (optional).
* \param pucDay Current day (optional).
* \param pucWeek Current day in current week (optional).
*/
extern void RTC_GetDate( Rtc* pRtc, uint16_t *pwYear, uint8_t *pucMonth, uint8_t *pucDay, uint8_t *pucWeek )
{
uint32_t dwDate ;
/* Get current date (multiple reads are necessary to insure a stable value) */
do
{
dwDate = pRtc->RTC_CALR ;
}
while ( dwDate != pRtc->RTC_CALR ) ;
/* Retrieve year */
if ( pwYear )
{
*pwYear = (((dwDate >> 4) & 0x7) * 1000)
+ ((dwDate & 0xF) * 100)
+ (((dwDate >> 12) & 0xF) * 10)
+ ((dwDate >> 8) & 0xF);
}
/* Retrieve month */
if ( pucMonth )
{
*pucMonth = (((dwDate >> 20) & 1) * 10) + ((dwDate >> 16) & 0xF);
}
/* Retrieve day */
if ( pucDay )
{
*pucDay = (((dwDate >> 28) & 0x3) * 10) + ((dwDate >> 24) & 0xF);
}
/* Retrieve week */
if ( pucWeek )
{
*pucWeek = ((dwDate >> 21) & 0x7);
}
}
/**
* \brief Sets the current year, month and day in the RTC.
* Month, day and week values must be numbered starting from 1.
*
* \note In successive update operations, the user must wait at least one second
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
* bits again. Please look at the RTC section of the datasheet for detail.
*
* \param wYear Current year.
* \param ucMonth Current month.
* \param ucDay Current day.
* \param ucWeek Day number in current week.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetDate( Rtc* pRtc, uint16_t wYear, uint8_t ucMonth, uint8_t ucDay, uint8_t ucWeek )
{
uint32_t wDate ;
uint8_t ucCent_bcd ;
uint8_t ucYear_bcd ;
uint8_t ucMonth_bcd ;
uint8_t ucDay_bcd ;
uint8_t ucWeek_bcd ;
ucCent_bcd = ((wYear/100)%10) | ((wYear/1000)<<4);
ucYear_bcd = (wYear%10) | (((wYear/10)%10)<<4);
ucMonth_bcd = ((ucMonth%10) | (ucMonth/10)<<4);
ucDay_bcd = ((ucDay%10) | (ucDay/10)<<4);
ucWeek_bcd = ((ucWeek%10) | (ucWeek/10)<<4);
/* value over flow */
if ( (ucCent_bcd & (uint8_t)(~RTC_CENT_BIT_LEN_MASK)) |
(ucYear_bcd & (uint8_t)(~RTC_YEAR_BIT_LEN_MASK)) |
(ucMonth_bcd & (uint8_t)(~RTC_MONTH_BIT_LEN_MASK)) |
(ucWeek_bcd & (uint8_t)(~RTC_WEEK_BIT_LEN_MASK)) |
(ucDay_bcd & (uint8_t)(~RTC_DATE_BIT_LEN_MASK))
)
{
return 1 ;
}
/* Convert values to date register value */
wDate = ucCent_bcd |
(ucYear_bcd << 8) |
(ucMonth_bcd << 16) |
(ucWeek_bcd << 21) |
(ucDay_bcd << 24);
/* Update calendar register */
pRtc->RTC_CR |= RTC_CR_UPDCAL ;
while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
pRtc->RTC_SCCR = RTC_SCCR_ACKCLR;
pRtc->RTC_CALR = wDate ;
pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDCAL) ;
pRtc->RTC_SCCR |= RTC_SCCR_SECCLR; /* clear SECENV in SCCR */
return (int)(pRtc->RTC_VER & RTC_VER_NVCAL) ;
}
/**
* \brief Sets a date alarm in the RTC.
* The alarm will match only the provided values;
* Passing a null-pointer disables the corresponding field match.
*
* \param pucMonth If not null, the RTC alarm will month-match this value.
* \param pucDay If not null, the RTC alarm will day-match this value.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetDateAlarm( Rtc* pRtc, uint8_t *pucMonth, uint8_t *pucDay )
{
uint32_t dwAlarm ;
dwAlarm = ((pucMonth) || (pucDay)) ? (0) : (0x01010000);
TRACE_DEBUG( "RTC_SetDateAlarm()\n\r" ) ;
/* Compute alarm field value */
if ( pucMonth )
{
dwAlarm |= RTC_CALALR_MTHEN | ((*pucMonth / 10) << 20) | ((*pucMonth % 10) << 16);
}
if ( pucDay )
{
dwAlarm |= RTC_CALALR_DATEEN | ((*pucDay / 10) << 28) | ((*pucDay % 10) << 24);
}
/* Set alarm */
pRtc->RTC_CALALR = dwAlarm ;
return (int)(pRtc->RTC_VER & RTC_VER_NVCALALR) ;
}
/**
* \brief Clear flag bits of status clear command register in the RTC.
*
* \param mask Bits mask of cleared events
*/
extern void RTC_ClearSCCR( Rtc* pRtc, uint32_t dwMask )
{
/* Clear all flag bits in status clear command register */
dwMask &= RTC_SCCR_ACKCLR | RTC_SCCR_ALRCLR | RTC_SCCR_SECCLR | RTC_SCCR_TIMCLR | RTC_SCCR_CALCLR ;
pRtc->RTC_SCCR = dwMask ;
}
/**
* \brief Get flag bits of status register in the RTC.
*
* \param mask Bits mask of Status Register
*
* \return Status register & mask
*/
extern uint32_t RTC_GetSR( Rtc* pRtc, uint32_t dwMask )
{
uint32_t dwEvent ;
dwEvent = pRtc->RTC_SR ;
return (dwEvent & dwMask) ;
}

View File

@@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup rtt_module Working with RTT
* The RTT driver provides the interface to configure and use the RTT
* peripheral.
*
* The Real-time Timer is used to count elapsed seconds.\n
* This timer is clocked by the 32kHz system clock divided by a programmable
* 16-bit balue. To be accurate, it is better to use an
* external 32kHz crystal instead of the internal 32kHz RC.\n
*
* To count elapsed seconds, the user could follow these few steps:
* <ul>
* <li>Programming PTPRES in RTT_MR to feeding the timer with a 1Hz signal.</li>
* <li>Writing the bit RTTRST in RTT_MR to restart the timer with new settings.</li>
* </ul>
*
* An alarm can be set to happen on second by setting alarm value in RTT_AR.
* Alarm occurence can be detected by polling or interrupt.
*
* For more accurate information, please look at the RTT section of the
* Datasheet.
*
* Related files :\n
* \ref rtt.c\n
* \ref rtt.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Real Time Timer (RTT) controller.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Changes the prescaler value of the given RTT and restarts it.
*
* \note This function disables RTT interrupt sources.
*
* \param rtt Pointer to a Rtt instance.
* \param prescaler Prescaler value for the RTT.
*/
void RTT_SetPrescaler(Rtt *rtt, uint16_t prescaler)
{
rtt->RTT_MR = (prescaler | RTT_MR_RTTRST);
}
/**
* \brief Returns the current value of the RTT timer value.
*
* \param rtt Pointer to a Rtt instance.
*/
uint32_t RTT_GetTime(Rtt *rtt)
{
return rtt->RTT_VR;
}
/**
* \brief Enables the specified RTT interrupt sources.
*
* \param rtt Pointer to a Rtt instance.
* \param sources Bitmask of interrupts to enable.
*/
void RTT_EnableIT(Rtt *rtt, uint32_t sources)
{
assert( (sources & 0x0004FFFF) == 0 ) ;
rtt->RTT_MR |= sources;
}
/**
* \brief Returns the status register value of the given RTT.
*
* \param rtt Pointer to an Rtt instance.
*/
uint32_t RTT_GetStatus(Rtt *rtt)
{
return rtt->RTT_SR;
}
/**
* \brief Configures the RTT to generate an alarm at the given time.
*
* \param pRtt Pointer to an Rtt instance.
* \param time Alarm time.
*/
void RTT_SetAlarm(Rtt *pRtt, uint32_t time)
{
assert(time > 0);
pRtt->RTT_AR = time - 1;
}

View File

@@ -0,0 +1,251 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup spi_pdc_module SPI PDC driver
* \ingroup spi_at45_module
* The Spi driver is a low level spi driver which performs SPI device Initializes,
* spi transfer and receive. It can be used by upper SPI driver such as AT45
* driver and AT26 driver.
*
* \section Usage
* <ul>
* <li> Initializes a SPI instance and the corresponding SPI hardware,
* Configure SPI in Master Mode using SPID_Configure().</li>
* <li> Configures the SPI characteristics (such as Clock Polarity, Phase,
* transfers delay and Baud Rate) for the device corresponding to the
* chip select using SPID_ConfigureCS().</li>
* <li> Starts a SPI master transfer using SPID_SendCommand().
* The transfer is performed using the PDC channels. </li>
* <li> It enable the SPI clock.</li>
* <li> Set the corresponding peripheral chip select.</li>
* <li> Initialize the two SPI PDC buffers.</li>
* <li> Initialize SPI_TPR and SPI_TCR with SPI command data and size
* to send command data first.</li>
* <li> Initialize SPI_RPR and SPI_RCR with SPI command data and size
* as dummy value.</li>
* <li> Initialize SPI_TNPR and SPI_TNCR with rest of the data to be
* transfered.(if the data specified in cmd structure)</li>
* <li> Initialize SPI_RNPR and SPI_RNCR with rest of the data to be
* received.(if the data specified in cmd structure)</li>
* <li> Initialize the callback function if specified.</li>
* <li> Enable transmitter and receiver.</li>
* <li> Example for sending a command to the dataflash through the SPI.</li>
* \code
* /// Build command to be sent.
* ...
* // Send Command and data through the SPI
* if (SPID_SendCommand(pAt45->pSpid, pCommand)) {
* return AT45_ERROR_SPI;
* }
* \endcode
* <li> The SPI_Handler() must be called by the SPI Interrupt Service Routine
* with the corresponding Spi instance. It is invokes to check for pending
* interrupts. </li>
* <li> Example for initializing SPI interrupt handler in upper application.</li>
* \code
* AIC_ConfigureIT(AT91C_ID_SPI, 0, SPI_Handler);
* \endcode
* </ul>
* Related files :\n
* \ref spi_pdc.c\n
* \ref spi_pdc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of SPI PDC driver.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes the Spid structure and the corresponding SPI hardware.
*
* \param pSpid Pointer to a Spid instance.
* \param pSpiHw Associated SPI peripheral.
* \param spiId SPI peripheral identifier.
* \return 0.
*/
extern uint32_t SPID_Configure( Spid* pSpid, Spi* pSpiHw, uint8_t spiId )
{
/* Initialize the SPI structure*/
pSpid->pSpiHw = pSpiHw ;
pSpid->spiId = spiId ;
pSpid->semaphore = 1 ;
pSpid->pCurrentCommand = 0 ;
/* Enable the SPI clock*/
PMC_EnablePeripheral( pSpid->spiId ) ;
/* Configure SPI in Master Mode with No CS selected !!! */
SPI_Configure( pSpiHw, pSpid->spiId, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PCS_Msk ) ;
/* Enable the SPI */
SPI_Enable( pSpiHw ) ;
/* Disable the SPI clock */
PMC_DisablePeripheral( pSpid->spiId ) ;
return 0 ;
}
/**
* \brief Configures the parameters for the device corresponding to the cs.
*
* \param pSpid Pointer to a Spid instance.
* \param cs number corresponding to the SPI chip select.
* \param csr SPI_CSR value to setup.
*/
extern void SPID_ConfigureCS( Spid* pSpid, uint32_t dwCS, uint32_t dwCSR )
{
SPI_ConfigureNPCS( pSpid->pSpiHw, dwCS, dwCSR ) ;
}
/**
* \brief Starts a SPI master transfer. This is a non blocking function. It will
* return as soon as the transfer is started.
*
* \param pSpid Pointer to a Spid instance.
* \param pCommand Pointer to the SPI command to execute.
* \return 0 if the transfer has been started successfully; otherwise returns
* SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
* valid.
*/
extern uint32_t SPID_SendCommand( Spid* pSpid, SpidCmd* pCommand )
{
Spi* pSpiHw = pSpid->pSpiHw ;
uint32_t dwSpiMr ;
/* Try to get the dataflash semaphore */
if ( pSpid->semaphore == 0 )
{
return SPID_ERROR_LOCK ;
}
pSpid->semaphore-- ;
/* Enable the SPI clock */
PMC_EnablePeripheral( pSpid->spiId ) ;
/* Disable transmitter and receiver*/
SPI_PdcDisableRx( pSpiHw ) ;
SPI_PdcDisableTx( pSpiHw ) ;
/* Write to the MR register*/
dwSpiMr = pSpiHw->SPI_MR ;
dwSpiMr |= SPI_MR_PCS_Msk ;
dwSpiMr &= ~((1 << pCommand->spiCs) << 16 ) ;
pSpiHw->SPI_MR=dwSpiMr ;
/* Initialize the two SPI PDC buffer*/
SPI_PdcSetRx( pSpiHw, pCommand->pCmd, pCommand->cmdSize, pCommand->pData, pCommand->dataSize ) ;
SPI_PdcSetTx( pSpiHw, pCommand->pCmd, pCommand->cmdSize, pCommand->pData, pCommand->dataSize ) ;
/* Initialize the callback*/
pSpid->pCurrentCommand = pCommand ;
/* Enable transmitter and receiver*/
SPI_PdcEnableRx( pSpiHw ) ;
SPI_PdcEnableTx( pSpiHw ) ;
/* Enable buffer complete interrupt*/
SPI_EnableIt( pSpiHw, SPI_IER_RXBUFF ) ;
return 0 ;
}
/**
* \brief The SPI_Handler must be called by the SPI Interrupt Service Routine with the
* corresponding Spi instance.
*
* \note The SPI_Handler will unlock the Spi semaphore and invoke the upper application
* callback.
* \param pSpid Pointer to a Spid instance.
*/
extern void SPID_Handler( Spid* pSpid )
{
SpidCmd *pSpidCmd = pSpid->pCurrentCommand ;
Spi *pSpiHw = pSpid->pSpiHw ;
volatile uint32_t spiSr ;
/* Read the status register*/
spiSr = pSpiHw->SPI_SR ;
if ( spiSr & SPI_SR_RXBUFF )
{
/* Disable transmitter and receiver */
SPI_PdcDisableRx( pSpiHw ) ;
SPI_PdcDisableTx( pSpiHw ) ;
/* Disable the SPI clock*/
PMC_DisablePeripheral( pSpid->spiId ) ;
/* Disable buffer complete interrupt */
SPI_DisableIt( pSpiHw, SPI_IDR_RXBUFF ) ;
/* Release the dataflash semaphore*/
pSpid->semaphore++ ;
/* Invoke the callback associated with the current command*/
if ( pSpidCmd && pSpidCmd->callback )
{
pSpidCmd->callback( 0, pSpidCmd->pArgument ) ;
}
/* Nothing must be done after. A new DF operation may have been started
in the callback function.*/
}
}
/**
* \brief Returns 1 if the SPI driver is currently busy executing a command; otherwise
* returns 0.
* \param pSpid Pointer to a Spid instance.
*/
extern uint32_t SPID_IsBusy( const Spid* pSpid )
{
if ( pSpid->semaphore == 0 )
{
return 1 ;
}
else
{
return 0 ;
}
}

View File

@@ -0,0 +1,247 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup ssc_module Working with SSC
* The SSC driver provides the interface to configure and use the SSC
* peripheral.
*
* !Usage
*
* -# Enable the SSC interface pins.
* -# Configure the SSC to operate at a specific frequency by calling
* SSC_Configure(). This function enables the peripheral clock of the SSC,
* but not its PIOs.
* -# Configure the transmitter and/or the receiver using the
* SSC_ConfigureTransmitter() and SSC_ConfigureEmitter() functions.
* -# Enable the PIOs or the transmitter and/or the received.
* -# Enable the transmitter and/or the receiver using SSC_EnableTransmitter()
* and SSC_EnableReceiver()
* -# Send data through the transmitter using SSC_Write() and SSC_WriteBuffer()
* -# Receive data from the receiver using SSC_Read() and SSC_ReadBuffer()
* -# Disable the transmitter and/or the receiver using SSC_DisableTransmitter()
* and SSC_DisableReceiver()
*
* For more accurate information, please look at the RTC section of the
* Datasheet.
*
* Related files :\n
* \ref ssc.c\n
* \ref ssc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Synchronous Serial (SSC) controller.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures a SSC peripheral.If the divided clock is not used, the master
* clock frequency can be set to 0.
* \note The emitter and transmitter are disabled by this function.
* \param bitRate bit rate.
* \param masterClock master clock.
*/
void SSC_Configure(uint32_t bitRate, uint32_t masterClock)
{
/* Enable SSC peripheral clock */
PMC->PMC_PCER0 = 1 << ID_SSC;
/* Reset, disable receiver & transmitter */
SSC->SSC_CR = SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST;
SSC->SSC_PTCR = SSC_PTCR_RXTDIS | SSC_PTCR_TXTDIS;
/* Configure clock frequency */
if (bitRate != 0) {
SSC->SSC_CMR = masterClock / (2 * bitRate);
}
else {
SSC->SSC_CMR = 0;
}
}
/**
* \brief Configures the transmitter of a SSC peripheral.
* \param tcmr Transmit Clock Mode Register value.
* \param tfmr Transmit Frame Mode Register value.
*/
void SSC_ConfigureTransmitter(uint32_t tcmr, uint32_t tfmr)
{
SSC->SSC_TCMR = tcmr;
SSC->SSC_TFMR = tfmr;
}
/**
* \brief Configures the receiver of a SSC peripheral.
* \param rcmr Receive Clock Mode Register value.
* \param rfmr Receive Frame Mode Register value.
*/
void SSC_ConfigureReceiver(uint32_t rcmr, uint32_t rfmr)
{
SSC->SSC_RCMR = rcmr;
SSC->SSC_RFMR = rfmr;
}
/**
* \brief Enables the transmitter of a SSC peripheral.
*/
void SSC_EnableTransmitter(void)
{
SSC->SSC_CR = SSC_CR_TXEN;
}
/**
* \brief Disables the transmitter of a SSC peripheral.
*/
void SSC_DisableTransmitter(void)
{
SSC->SSC_CR = SSC_CR_TXDIS;
}
/**
* \brief Enables the receiver of a SSC peripheral.
*/
void SSC_EnableReceiver(void)
{
SSC->SSC_CR = SSC_CR_RXEN;
}
/**
* \brief Disables the receiver of a SSC peripheral.
*/
void SSC_DisableReceiver(void)
{
SSC->SSC_CR = SSC_CR_RXDIS;
}
/**
* \brief Enables one or more interrupt sources of a SSC peripheral.
* \param sources Bitwise OR of selected interrupt sources.
*/
void SSC_EnableInterrupts(uint32_t sources)
{
SSC->SSC_IER = sources;
}
/**
* \brief Disables one or more interrupt sources of a SSC peripheral.
* \param sources Bitwise OR of selected interrupt sources.
*/
void SSC_DisableInterrupts(uint32_t sources)
{
SSC->SSC_IDR = sources;
}
/**
* \brief Sends one data frame through a SSC peripheral. If another frame is currently
* being sent, this function waits for the previous transfer to complete.
* \param frame Data frame to send.
*/
void SSC_Write(uint32_t frame)
{
while ((SSC->SSC_SR & SSC_SR_TXRDY) == 0);
SSC->SSC_THR = frame;
}
/**
* \brief Waits until one frame is received on a SSC peripheral, and returns it.
*/
uint32_t SSC_Read(void)
{
while ((SSC->SSC_SR & SSC_SR_RXRDY) == 0);
return SSC->SSC_RHR;
}
/**
* \brief Sends the contents of a data buffer a SSC peripheral, using the PDC.
* \param buffer Data buffer to send.
* \param length Size of the data buffer.
* \return 1 if the buffer has been queued for transmission; otherwise returns 0.
*/
uint8_t SSC_WriteBuffer(void *buffer, uint32_t length)
{
/* Check if first bank is free*/
if (SSC->SSC_TCR == 0) {
SSC->SSC_TPR = (uint32_t) buffer;
SSC->SSC_TCR = length;
SSC->SSC_PTCR = SSC_PTCR_TXTEN;
return 1;
}
/* Check if second bank is free*/
else if (SSC->SSC_TNCR == 0) {
SSC->SSC_TNPR = (uint32_t) buffer;
SSC->SSC_TNCR = length;
return 1;
}
return 0;
}
/**
* \brief Reads data coming from a SSC peripheral receiver and stores it into the
* giving buffer with PDC.
* \param buffer ata buffer used for reception.
* \param length Size of the data buffer.
* \return 1 if the buffer has been queued for reception; otherwise returns 0.
*/
uint8_t SSC_ReadBuffer(void *buffer, uint32_t length)
{
/* Check if the first bank is free*/
if (SSC->SSC_RCR == 0) {
SSC->SSC_RPR = (uint32_t) buffer;
SSC->SSC_RCR = length;
SSC->SSC_PTCR = SSC_PTCR_RXTEN;
return 1;
}
/* Check if second bank is free*/
else if (SSC->SSC_RNCR == 0) {
SSC->SSC_RNPR = (uint32_t) buffer;
SSC->SSC_RNCR = length;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,196 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "chip.h"
#include <assert.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Key value for the SUPC_MR register.
#define SUPC_KEY ((uint32_t) (0xA5 << 24))
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Enables the flash power supply with the given wake-up setting.
/// \param time Wake-up time.
//------------------------------------------------------------------------------
void SUPC_EnableFlash( Supc* pSupc, uint32_t dwTime )
{
pSupc->SUPC_FWUTR = dwTime ;
pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_FLASHON ;
while ((pSupc->SUPC_SR & AT91C_SUPC_FLASHS) != AT91C_SUPC_FLASHS) ;
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Disables the flash power supply.
//------------------------------------------------------------------------------
void SUPC_DisableFlash( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_FLASHON) ;
while ((pSupc->SUPC_SR & AT91C_SUPC_FLASHS) == AT91C_SUPC_FLASHS) ;
}
//------------------------------------------------------------------------------
/// Sets the voltage regulator output voltage.
/// \param voltage Voltage to set.
//------------------------------------------------------------------------------
void SUPC_SetVoltageOutput( Supc* pSupc, uint32_t dwVoltage )
{
assert( (voltage & ~AT91C_SUPC_VRVDD) == 0 ) ;
pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_VRVDD) | dwVoltage ;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in deep mode.
//------------------------------------------------------------------------------
void SUPC_EnableDeepMode( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_VRDEEP ;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in normal mode.
//------------------------------------------------------------------------------
void SUPC_DisableDeepMode( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_VRDEEP) ;
}
//-----------------------------------------------------------------------------
/// Enables the backup SRAM power supply, so its data is saved while the device
/// is in backup mode.
//-----------------------------------------------------------------------------
void SUPC_EnableSram( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_SRAMON ;
}
//-----------------------------------------------------------------------------
/// Disables the backup SRAM power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableSram( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_SRAMON) ;
}
//-----------------------------------------------------------------------------
/// Enables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_EnableRtc( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_RTCON ;
while ((pSupc->SUPC_SR & AT91C_SUPC_RTS) != AT91C_SUPC_RTS) ;
}
//-----------------------------------------------------------------------------
/// Disables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableRtc( Supc* pSupc )
{
pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_RTCON) ;
while ((pSupc->SUPC_SR & AT91C_SUPC_RTS) == AT91C_SUPC_RTS);
}
//-----------------------------------------------------------------------------
/// Sets the BOD sampling mode (or disables it).
/// \param mode BOD sampling mode.
//-----------------------------------------------------------------------------
void SUPC_SetBodSampling( Supc* pSupc, uint32_t dwMode )
{
assert( (dwMode & ~AT91C_SUPC_BODSMPL) == 0 ) ;
pSupc->SUPC_BOMR &= ~AT91C_SUPC_BODSMPL;
pSupc->SUPC_BOMR |= dwMode ;
}
//------------------------------------------------------------------------------
/// Disables the voltage regulator, which makes the device enter backup mode.
//------------------------------------------------------------------------------
void SUPC_DisableVoltageRegulator( Supc* pSupc )
{
pSupc->SUPC_CR = SUPC_KEY | AT91C_SUPC_VROFF ;
while ( 1 ) ;
}
//------------------------------------------------------------------------------
/// Shuts the device down so it enters Off mode.
//------------------------------------------------------------------------------
void SUPC_Shutdown( Supc* pSupc )
{
pSupc->SUPC_CR = SUPC_KEY | AT91C_SUPC_SHDW ;
while (1);
}
//------------------------------------------------------------------------------
/// Sets the wake-up sources when in backup mode.
/// \param sources Wake-up sources to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpSources( Supc* pSupc, uint32_t dwSources )
{
assert( (dwSources & ~0x0000000B) == 0 ) ;
pSupc->SUPC_WUMR &= ~0x0000000B;
pSupc->SUPC_WUMR |= dwSources ;
}
//------------------------------------------------------------------------------
/// Sets the wake-up inputs when in backup mode.
/// \param inputs Wake up inputs to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpInputs( Supc* pSupc, uint32_t dwInputs )
{
assert( (dwInputs & ~0xFFFF) == 0 ) ;
pSupc->SUPC_WUIR &= ~0xFFFF ;
pSupc->SUPC_WUIR |= dwInputs ;
}

View File

@@ -0,0 +1,175 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of Timer Counter (TC).
*
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*------------------------------------------------------------------------------
* Global functions
*------------------------------------------------------------------------------*/
/**
* \brief Configures a Timer Counter Channel
*
* Configures a Timer Counter to operate in the given mode. Timer is stopped
* after configuration and must be restarted with TC_Start(). All the
* interrupts of the timer are also disabled.
*
* \param pTc Pointer to a Tc instance.
* \param channel Channel number.
* \param mode Operating mode (TC_CMR value).
*/
extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode )
{
TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ;
/* Disable TC clock */
pTcCh->TC_CCR = TC_CCR_CLKDIS ;
/* Disable interrupts */
pTcCh->TC_IDR = 0xFFFFFFFF ;
/* Clear status register */
pTcCh->TC_SR ;
/* Set mode */
pTcCh->TC_CMR = dwMode ;
}
/**
* \brief Reset and Start the TC Channel
*
* Enables the timer clock and performs a software reset to start the counting.
*
* \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number.
*/
extern void TC_Start( Tc *pTc, uint32_t dwChannel )
{
TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;
}
/**
* \brief Stop TC Channel
*
* Disables the timer clock, stopping the counting.
*
* \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number.
*/
extern void TC_Stop(Tc *pTc, uint32_t dwChannel )
{
TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKDIS ;
}
/**
* \brief Find best MCK divisor
*
* Finds the best MCK divisor given the timer frequency and MCK. The result
* is guaranteed to satisfy the following equation:
* \code
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
* \endcode
* with DIV being the highest possible value.
*
* \param dwFreq Desired timer frequency.
* \param dwMCk Master clock frequency.
* \param dwDiv Divisor value.
* \param dwTcClks TCCLKS field value for divisor.
* \param dwBoardMCK Board clock frequency.
*
* \return 1 if a proper divisor has been found, otherwise 0.
*/
extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK )
{
const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ;
uint32_t dwIndex = 0 ;
/* Satisfy lower bound */
while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) )
{
dwIndex++ ;
/* If no divisor can be found, return 0 */
if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) )
{
return 0 ;
}
}
/* Try to maximize DIV while satisfying upper bound */
while ( dwIndex < 4 )
{
if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) )
{
break ;
}
dwIndex++ ;
}
/* Store results */
if ( dwDiv )
{
*dwDiv = adwDivisors[dwIndex] ;
}
if ( dwTcClks )
{
*dwTcClks = dwIndex ;
}
return 1 ;
}

View File

@@ -0,0 +1,380 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup twi_module Working with TWI
* The TWI driver provides the interface to configure and use the TWI
* peripheral.
*
* \section Usage
* <ul>
* <li> Configures a TWI peripheral to operate in master mode, at the given
* frequency (in Hz) using TWI_Configure(). </li>
* <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
* <li> Starts a read operation on the TWI bus with the specified slave using
* TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
* a byte is available (poll using TWI_ByteReceived()).</li>
* <li> Starts a write operation on the TWI to access the selected slave using
* TWI_StartWrite(). A byte of data must be provided to start the write;
* other bytes are written next.</li>
* <li> Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().
* This function must be called once before TWI_StartWrite() with the first byte of data
* to send, then it shall be called repeatedly after that to send the remaining bytes.</li>
* <li> Check if a byte has been received and can be read on the given TWI
* peripheral using TWI_ByteReceived().<
* Check if a byte has been sent using TWI_ByteSent().</li>
* <li> Check if the current transmission is complete (the STOP has been sent)
* using TWI_TransferComplete().</li>
* <li> Enables & disable the selected interrupts sources on a TWI peripheral
* using TWI_EnableIt() and TWI_DisableIt().</li>
* <li> Get current status register of the given TWI peripheral using
* TWI_GetStatus(). Get current status register of the given TWI peripheral, but
* masking interrupt sources which are not currently enabled using
* TWI_GetMaskedStatus().</li>
* </ul>
* For more accurate information, please look at the TWI section of the
* Datasheet.
*
* Related files :\n
* \ref twi.c\n
* \ref twi.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Two Wire Interface (TWI).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures a TWI peripheral to operate in master mode, at the given
* frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
* \param pTwi Pointer to an Twi instance.
* \param twck Desired TWI clock frequency.
* \param mck Master clock frequency.
*/
void TWI_ConfigureMaster( Twi* pTwi, uint32_t dwTwCk, uint32_t dwMCk )
{
uint32_t dwCkDiv = 0 ;
uint32_t dwClDiv ;
uint32_t dwOk = 0 ;
TRACE_DEBUG( "TWI_ConfigureMaster()\n\r" ) ;
assert( pTwi ) ;
/* SVEN: TWI Slave Mode Enabled */
pTwi->TWI_CR = TWI_CR_SVEN ;
/* Reset the TWI */
pTwi->TWI_CR = TWI_CR_SWRST ;
pTwi->TWI_RHR ;
/* TWI Slave Mode Disabled, TWI Master Mode Disabled. */
pTwi->TWI_CR = TWI_CR_SVDIS ;
pTwi->TWI_CR = TWI_CR_MSDIS ;
/* Set master mode */
pTwi->TWI_CR = TWI_CR_MSEN ;
/* Configure clock */
while ( !dwOk )
{
dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1<<dwCkDiv) ;
if ( dwClDiv <= 255 )
{
dwOk = 1 ;
}
else
{
dwCkDiv++ ;
}
}
assert( dwCkDiv < 8 ) ;
TRACE_DEBUG( "Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", dwCkDiv, dwClDiv ) ;
pTwi->TWI_CWGR = 0 ;
pTwi->TWI_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv ;
}
/**
* \brief Configures a TWI peripheral to operate in slave mode.
* \param pTwi Pointer to an Twi instance.
* \param slaveAddress Slave address.
*/
void TWI_ConfigureSlave(Twi *pTwi, uint8_t slaveAddress)
{
uint32_t i;
/* TWI software reset */
pTwi->TWI_CR = TWI_CR_SWRST;
pTwi->TWI_RHR;
/* Wait at least 10 ms */
for (i=0; i < 1000000; i++);
/* TWI Slave Mode Disabled, TWI Master Mode Disabled*/
pTwi->TWI_CR = TWI_CR_SVDIS | TWI_CR_MSDIS;
/* Configure slave address. */
pTwi->TWI_SMR = 0;
pTwi->TWI_SMR = TWI_SMR_SADR(slaveAddress);
/* SVEN: TWI Slave Mode Enabled */
pTwi->TWI_CR = TWI_CR_SVEN;
/* Wait at least 10 ms */
for (i=0; i < 1000000; i++);
assert( (pTwi->TWI_CR & TWI_CR_SVDIS)!= TWI_CR_SVDIS ) ;
}
/**
* \brief Sends a STOP condition on the TWI.
* \param pTwi Pointer to an Twi instance.
*/
void TWI_Stop( Twi *pTwi )
{
assert( pTwi != NULL ) ;
pTwi->TWI_CR = TWI_CR_STOP;
}
/**
* \brief Starts a read operation on the TWI bus with the specified slave, it returns
* immediately. Data must then be read using TWI_ReadByte() whenever a byte is
* available (poll using TWI_ByteReceived()).
* \param pTwi Pointer to an Twi instance.
* \param address Slave address on the bus.
* \param iaddress Optional internal address bytes.
* \param isize Number of internal address bytes.
*/
void TWI_StartRead(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize)
{
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Set slave address and number of internal address bytes. */
pTwi->TWI_MMR = 0;
pTwi->TWI_MMR = (isize << 8) | TWI_MMR_MREAD | (address << 16);
/* Set internal address bytes */
pTwi->TWI_IADR = 0;
pTwi->TWI_IADR = iaddress;
/* Send START condition */
pTwi->TWI_CR = TWI_CR_START;
}
/**
* \brief Reads a byte from the TWI bus. The read operation must have been started
* using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()).
* \param pTwi Pointer to an Twi instance.
* \return byte read.
*/
uint8_t TWI_ReadByte(Twi *pTwi)
{
assert( pTwi != NULL ) ;
return pTwi->TWI_RHR;
}
/**
* \brief Sends a byte of data to one of the TWI slaves on the bus.
* \note This function must be called once before TWI_StartWrite() with
* the first byte of data to send, then it shall be called repeatedly
* after that to send the remaining bytes.
* \param pTwi Pointer to an Twi instance.
* \param byte Byte to send.
*/
void TWI_WriteByte(Twi *pTwi, uint8_t byte)
{
assert( pTwi != NULL ) ;
pTwi->TWI_THR = byte;
}
/**
* \brief Starts a write operation on the TWI to access the selected slave, then
* returns immediately. A byte of data must be provided to start the write;
* other bytes are written next.
* after that to send the remaining bytes.
* \param pTwi Pointer to an Twi instance.
* \param address Address of slave to acccess on the bus.
* \param iaddress Optional slave internal address.
* \param isize Number of internal address bytes.
* \param byte First byte to send.
*/
void TWI_StartWrite(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t byte)
{
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Set slave address and number of internal address bytes. */
pTwi->TWI_MMR = 0;
pTwi->TWI_MMR = (isize << 8) | (address << 16);
/* Set internal address bytes. */
pTwi->TWI_IADR = 0;
pTwi->TWI_IADR = iaddress;
/* Write first byte to send.*/
TWI_WriteByte(pTwi, byte);
}
/**
* \brief Check if a byte have been receiced from TWI.
* \param pTwi Pointer to an Twi instance.
* \return 1 if a byte has been received and can be read on the given TWI
* peripheral; otherwise, returns 0. This function resets the status register.
*/
uint8_t TWI_ByteReceived(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_RXRDY) == TWI_SR_RXRDY);
}
/**
* \brief Check if a byte have been sent to TWI.
* \param pTwi Pointer to an Twi instance.
* \return 1 if a byte has been sent so another one can be stored for
* transmission; otherwise returns 0. This function clears the status register.
*/
uint8_t TWI_ByteSent(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_TXRDY) == TWI_SR_TXRDY);
}
/**
* \brief Check if current transmission is complet.
* \param pTwi Pointer to an Twi instance.
* \return 1 if the current transmission is complete (the STOP has been sent);
* otherwise returns 0.
*/
uint8_t TWI_TransferComplete(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_TXCOMP) == TWI_SR_TXCOMP);
}
/**
* \brief Enables the selected interrupts sources on a TWI peripheral.
* \param pTwi Pointer to an Twi instance.
* \param sources Bitwise OR of selected interrupt sources.
*/
void TWI_EnableIt(Twi *pTwi, uint32_t sources)
{
assert( pTwi != NULL ) ;
assert( (sources & 0xFFFFF088) == 0 ) ;
pTwi->TWI_IER = sources;
}
/**
* \brief Disables the selected interrupts sources on a TWI peripheral.
* \param pTwi Pointer to an Twi instance.
* \param sources Bitwise OR of selected interrupt sources.
*/
void TWI_DisableIt(Twi *pTwi, uint32_t sources)
{
assert( pTwi != NULL ) ;
assert( (sources & 0xFFFFF088) == 0 ) ;
pTwi->TWI_IDR = sources;
}
/**
* \brief Get the current status register of the given TWI peripheral.
* \note This resets the internal value of the status register, so further
* read may yield different values.
* \param pTwi Pointer to an Twi instance.
* \return TWI status register.
*/
uint32_t TWI_GetStatus(Twi *pTwi)
{
assert( pTwi != NULL ) ;
return pTwi->TWI_SR;
}
/**
* \brief Returns the current status register of the given TWI peripheral, but
* masking interrupt sources which are not currently enabled.
* \note This resets the internal value of the status register, so further
* read may yield different values.
* \param pTwi Pointer to an Twi instance.
*/
uint32_t TWI_GetMaskedStatus(Twi *pTwi)
{
uint32_t status;
assert( pTwi != NULL ) ;
status = pTwi->TWI_SR;
status &= pTwi->TWI_IMR;
return status;
}
/**
* \brief Sends a STOP condition. STOP Condition is sent just after completing
* the current byte transmission in master read mode.
* \param pTwi Pointer to an Twi instance.
*/
void TWI_SendSTOPCondition(Twi *pTwi)
{
assert( pTwi != NULL ) ;
pTwi->TWI_CR |= TWI_CR_STOP;
}

View File

@@ -0,0 +1,342 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Definition
*----------------------------------------------------------------------------*/
#define TWITIMEOUTMAX 50000
/*----------------------------------------------------------------------------
* Types
*----------------------------------------------------------------------------*/
/** TWI driver callback function.*/
typedef void (*TwiCallback)(Async *);
/** \brief TWI asynchronous transfer descriptor.*/
typedef struct _AsyncTwi {
/** Asynchronous transfer status. */
volatile uint8_t status;
// Callback function to invoke when transfer completes or fails.*/
TwiCallback callback;
/** Pointer to the data buffer.*/
uint8_t *pData;
/** Total number of bytes to transfer.*/
uint32_t num;
/** Number of already transferred bytes.*/
uint32_t transferred;
} AsyncTwi;
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes a TWI driver instance, using the given TWI peripheral.
* \note The peripheral must have been initialized properly before calling this function.
* \param pTwid Pointer to the Twid instance to initialize.
* \param pTwi Pointer to the TWI peripheral to use.
*/
void TWID_Initialize(Twid *pTwid, Twi *pTwi)
{
TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;
assert( pTwid != NULL ) ;
assert( pTwi != NULL ) ;
/* Initialize driver. */
pTwid->pTwi = pTwi;
pTwid->pTransfer = 0;
}
/**
* \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer
* occuring on the bus. This function MUST be called by the interrupt service
* routine of the TWI peripheral if asynchronous read/write are needed.
* \param pTwid Pointer to a Twid instance.
*/
void TWID_Handler( Twid *pTwid )
{
uint8_t status;
AsyncTwi *pTransfer ;
Twi *pTwi ;
assert( pTwid != NULL ) ;
pTransfer = (AsyncTwi*)pTwid->pTransfer ;
assert( pTransfer != NULL ) ;
pTwi = pTwid->pTwi ;
assert( pTwi != NULL ) ;
/* Retrieve interrupt status */
status = TWI_GetMaskedStatus(pTwi);
/* Byte received */
if (TWI_STATUS_RXRDY(status)) {
pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
pTransfer->transferred++;
/* check for transfer finish */
if (pTransfer->transferred == pTransfer->num) {
TWI_DisableIt(pTwi, TWI_IDR_RXRDY);
TWI_EnableIt(pTwi, TWI_IER_TXCOMP);
}
/* Last byte? */
else if (pTransfer->transferred == (pTransfer->num - 1)) {
TWI_Stop(pTwi);
}
}
/* Byte sent*/
else if (TWI_STATUS_TXRDY(status)) {
/* Transfer finished ? */
if (pTransfer->transferred == pTransfer->num) {
TWI_DisableIt(pTwi, TWI_IDR_TXRDY);
TWI_EnableIt(pTwi, TWI_IER_TXCOMP);
TWI_SendSTOPCondition(pTwi);
}
/* Bytes remaining */
else {
TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
pTransfer->transferred++;
}
}
/* Transfer complete*/
else if (TWI_STATUS_TXCOMP(status)) {
TWI_DisableIt(pTwi, TWI_IDR_TXCOMP);
pTransfer->status = 0;
if (pTransfer->callback) {
pTransfer->callback((Async *) pTransfer);
}
pTwid->pTransfer = 0;
}
}
/**
* \brief Asynchronously reads data from a slave on the TWI bus. An optional
* callback function is triggered when the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Internal address size in bytes.
* \param pData Data buffer for storing received bytes.
* \param num Number of bytes to read.
* \param pAsync Asynchronous transfer descriptor.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_Read(
Twid *pTwid,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twi *pTwi;
AsyncTwi *pTransfer;
uint32_t timeout;
assert( pTwid != NULL ) ;
pTwi = pTwid->pTwi;
pTransfer = (AsyncTwi *) pTwid->pTransfer;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Check that no transfer is already pending*/
if (pTransfer) {
TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Set STOP signal if only one byte is sent*/
if (num == 1) {
TWI_Stop(pTwi);
}
/* Asynchronous transfer*/
if (pAsync) {
/* Update the transfer descriptor */
pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 0;
/* Enable read interrupt and start the transfer */
TWI_EnableIt(pTwi, TWI_IER_RXRDY);
TWI_StartRead(pTwi, address, iaddress, isize);
}
/* Synchronous transfer*/
else {
/* Start read*/
TWI_StartRead(pTwi, address, iaddress, isize);
/* Read all bytes, setting STOP before the last byte*/
while (num > 0) {
/* Last byte ?*/
if (num == 1) {
TWI_Stop(pTwi);
}
/* Wait for byte then read and store it*/
timeout = 0;
while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) );
if (timeout == TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout BR\n\r");
}
*pData++ = TWI_ReadByte(pTwi);
num--;
}
/* Wait for transfer to be complete */
timeout = 0;
while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
if (timeout == TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout TC\n\r");
}
}
return 0;
}
/**
* \brief Asynchronously sends data to a slave on the TWI bus. An optional callback
* function is invoked whenever the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Number of internal address bytes.
* \param pData Data buffer for storing received bytes.
* \param num Data buffer to send.
* \param pAsync Asynchronous transfer descriptor.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_Write(
Twid *pTwid,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twi *pTwi = pTwid->pTwi;
AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
uint32_t timeout;
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Check that no transfer is already pending */
if (pTransfer) {
TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Asynchronous transfer */
if (pAsync) {
/* Update the transfer descriptor */
pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 1;
/* Enable write interrupt and start the transfer */
TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
TWI_EnableIt(pTwi, TWI_IER_TXRDY);
}
/* Synchronous transfer*/
else {
// Start write
TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
num--;
/* Send all bytes */
while (num > 0) {
/* Wait before sending the next byte */
timeout = 0;
while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );
if (timeout == TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout BS\n\r");
}
TWI_WriteByte(pTwi, *pData++);
num--;
}
/* Wait for actual end of transfer */
timeout = 0;
/* Send a STOP condition */
TWI_SendSTOPCondition(pTwi);
while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
if (timeout == TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout TC2\n\r");
}
}
return 0;
}

View File

@@ -0,0 +1,410 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup usart_module Working with USART
* The USART driver provides the interface to configure and use the USART peripheral.\n
*
* The USART supports several kinds of comminication modes such as full-duplex asynchronous/
* synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes.
*
* To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps:
* <ul>
* <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by:
* -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>
* -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>
* -# Setting baudrate which is different from mode to mode.
</li>
* <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>
* <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer.
These operations could be done by polling or interruption. </li>
* <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/
US_CSR_TXBUFE (WRITE). </li>
* <li> For interruption,"enable" the status bit through US_IER and
realize the hanler with USARTx_IrqHandler according to IRQ vector
table which is defined in board_cstartup_<toolchain>.c
To enable the interruption of USART,it should be configured with priority and enabled first through
NVIC .</li>
* </ul>
*
* For more accurate information, please look at the USART section of the
* Datasheet.
*
* Related files :\n
* \ref usart.c\n
* \ref usart.h\n
*/
/**
* \file
*
* Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)
* controller.
*
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "chip.h"
#include "trace.h"
#include <assert.h>
#include <string.h>
/*----------------------------------------------------------------------------
* Local definitions
*----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
/**
* \brief Configures an USART peripheral with the specified parameters.
*
*
* \param usart Pointer to the USART peripheral to configure.
* \param mode Desired value for the USART mode register (see the datasheet).
* \param baudrate Baudrate at which the USART should operate (in Hz).
* \param masterClock Frequency of the system master clock (in Hz).
*/
void USART_Configure(Usart *usart,
uint32_t mode,
uint32_t baudrate,
uint32_t masterClock)
{
/* Reset and disable receiver & transmitter*/
usart->US_CR = US_CR_RSTRX | US_CR_RSTTX
| US_CR_RXDIS | US_CR_TXDIS;
/* Configure mode*/
usart->US_MR = mode;
/* Configure baudrate*/
/* Asynchronous, no oversampling*/
if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) )
{
usart->US_BRGR = (masterClock / baudrate) / 16;
}
if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER)
|| ((mode & US_MR_SYNC) == US_MR_SYNC))
{
if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
{
usart->US_BRGR = masterClock / baudrate;
}
else
{
if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV)
{
usart->US_BRGR = masterClock / baudrate / 8;
}
}
}
/* TODO other modes*/
}
/**
* \brief Enables or disables the transmitter of an USART peripheral.
*
*
* \param usart Pointer to an USART peripheral
* \param enabled If true, the transmitter is enabled; otherwise it is
* disabled.
*/
void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled)
{
if (enabled) {
usart->US_CR = US_CR_TXEN;
}
else {
usart->US_CR = US_CR_TXDIS;
}
}
/**
* \brief Enables or disables the receiver of an USART peripheral
*
*
* \param usart Pointer to an USART peripheral
* \param enabled If true, the receiver is enabled; otherwise it is disabled.
*/
void USART_SetReceiverEnabled(Usart *usart,
uint8_t enabled)
{
if (enabled) {
usart->US_CR = US_CR_RXEN;
}
else {
usart->US_CR = US_CR_RXDIS;
}
}
/**
* \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been
* actually sent.
*
*
* \param usart Pointer to an USART peripheral.
* \param data Data to send including 9nth bit and sync field if necessary (in
* the same format as the US_THR register in the datasheet).
* \param timeOut Time out value (0 = no timeout).
*/
void USART_Write(
Usart *usart,
uint16_t data,
volatile uint32_t timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
}
else {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) {
if (timeOut == 0) {
TRACE_ERROR("USART_Write: Timed out.\n\r");
return;
}
timeOut--;
}
}
usart->US_THR = data;
}
/**
* \brief Sends the contents of a data buffer through the specified USART peripheral.
* This function returns immediately (1 if the buffer has been queued, 0
* otherwise); poll the ENDTX and TXBUFE bits of the USART status register
* to check for the transfer completion.
*
* \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the data buffer to send.
* \param size Size of the data buffer (in bytes).
*/
uint8_t USART_WriteBuffer(
Usart *usart,
void *buffer,
uint32_t size)
{
/* Check if the first PDC bank is free*/
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (uint32_t) buffer;
usart->US_TCR = size;
usart->US_PTCR = US_PTCR_TXTEN;
return 1;
}
/* Check if the second PDC bank is free*/
else if (usart->US_TNCR == 0) {
usart->US_TNPR = (uint32_t) buffer;
usart->US_TNCR = size;
return 1;
}
else {
return 0;
}
}
/**
* \brief Reads and return a packet of data on the specified USART peripheral. This
* function operates asynchronously, so it waits until some data has been
* received.
*
* \param usart Pointer to an USART peripheral.
* \param timeOut Time out value (0 -> no timeout).
*/
uint16_t USART_Read(
Usart *usart,
volatile uint32_t timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_RXRDY) == 0);
}
else {
while ((usart->US_CSR & US_CSR_RXRDY) == 0) {
if (timeOut == 0) {
TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
return 0;
}
timeOut--;
}
}
return usart->US_RHR;
}
/**
* \brief Reads data from an USART peripheral, filling the provided buffer until it
* becomes full. This function returns immediately with 1 if the buffer has
* been queued for transmission; otherwise 0.
*
* \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the buffer where the received data will be stored.
* \param size Size of the data buffer (in bytes).
*/
uint8_t USART_ReadBuffer(Usart *usart,
void *buffer,
uint32_t size)
{
/* Check if the first PDC bank is free*/
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (uint32_t) buffer;
usart->US_RCR = size;
usart->US_PTCR = US_PTCR_RXTEN;
return 1;
}
/* Check if the second PDC bank is free*/
else if (usart->US_RNCR == 0) {
usart->US_RNPR = (uint32_t) buffer;
usart->US_RNCR = size;
return 1;
}
else {
return 0;
}
}
/**
* \brief Returns 1 if some data has been received and can be read from an USART;
* otherwise returns 0.
*
* \param usart Pointer to an Usart instance.
*/
uint8_t USART_IsDataAvailable(Usart *usart)
{
if ((usart->US_CSR & US_CSR_RXRDY) != 0) {
return 1;
}
else {
return 0;
}
}
/**
* \brief Sets the filter value for the IRDA demodulator.
*
* \param pUsart Pointer to an Usart instance.
* \param filter Filter value.
*/
void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter)
{
assert( pUsart != NULL ) ;
pUsart->US_IF = filter;
}
/**
* \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been
* actually sent.
*
* \param usart Pointer to an USART peripheral.
* \param c Character to send
*/
void USART_PutChar(
Usart *usart,
uint8_t c)
{
/* Wait for the transmitter to be ready*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
/* Send character*/
usart->US_THR = c;
/* Wait for the transfer to complete*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
}
/**
* \brief Return 1 if a character can be read in USART
*/
uint32_t USART_IsRxReady(Usart *usart)
{
return (usart->US_CSR & US_CSR_RXRDY);
}
/**
* \brief Get present status
*/
uint32_t USART_GetStatus(Usart *usart)
{
return usart->US_CSR;
}
/**
* \brief Enable interrupt
*/
void USART_EnableIt(Usart *usart,uint32_t mode)
{
usart->US_IER = mode;
}
/**
* \brief Disable interrupt
*/
void USART_DisableIt(Usart *usart,uint32_t mode)
{
usart->US_IDR = mode;
}
/**
* \brief Reads and returns a character from the USART.
*
* \note This function is synchronous (i.e. uses polling).
* \param usart Pointer to an USART peripheral.
* \return Character received.
*/
uint8_t USART_GetChar(Usart *usart)
{
while ((usart->US_CSR & US_CSR_RXRDY) == 0);
return usart->US_RHR;
}

View File

@@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Implementation of Watchdog Timer (WDT) controller.
*
*/
/** \addtogroup wdt_module Working with WDT
* The WDT driver provides the interface to configure and use the WDT
* peripheral.
*
* The WDT can be used to prevent system lock-up if the software becomes
* trapped in a deadlock. It can generate a general reset or a processor
* reset only. It is clocked by slow clock divided by 128.
*
* The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz)
* and external reset generation enabled. The user must either disable it or
* reprogram it to meet the application requires.
*
* To use the WDT, the user could follow these few steps:
* <ul>
* <li>Enable watchdog with given mode using \ref WDT_Enable().
* <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period.
* </ul>
*
* For more accurate information, please look at the WDT section of the
* Datasheet.
*
* \note
* The Watchdog Mode Register (WDT_MR) can be written only once.\n
*
* Related files :\n
* \ref wdt.c\n
* \ref wdt.h.\n
*/
/*@{*/
/*@}*/
/*---------------------------------------------------------------------------
* Headers
*---------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Enable watchdog with given mode.
*
* \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it.
*
* \param dwMode WDT mode to be set
*/
extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode )
{
pWDT->WDT_MR = dwMode ;
}
/**
* \brief Disable watchdog.
*
* \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it.
*/
extern void WDT_Disable( Wdt* pWDT )
{
pWDT->WDT_MR = WDT_MR_WDDIS;
}
/**
* \brief Watchdog restart.
*/
extern void WDT_Restart( Wdt* pWDT )
{
pWDT->WDT_CR = 0xA5000001;
}
/**
* \brief Watchdog get status.
*/
extern uint32_t WDT_GetStatus( Wdt* pWDT )
{
return (pWDT->WDT_SR & 0x3) ;
}
/**
* \brief Watchdog get period.
*
* \param dwMs desired watchdog period in millisecond.
*/
extern uint32_t WDT_GetPeriod( uint32_t dwMs )
{
if ( (dwMs < 4) || (dwMs > 16000) )
{
return 0 ;
}
return ((dwMs << 8) / 1000) ;
}

1
sam3s_example/cmsis Symbolic link
View File

@@ -0,0 +1 @@
./atmel_softpack_libraries/libchip_sam3s/cmsis

View File

@@ -1,817 +0,0 @@
/**************************************************************************//**
* @file core_cm3.c
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version V1.30
* @date 30. October 2009
*
* @note
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
/*
* Remo Giermann:
* 2012/01/09 - fixed __STREX[BHW] functions
*
*
*/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
uint32_t __get_PSP(void) ;
void __set_PSP(uint32_t topOfProcStack) ;
uint32_t __get_MSP(void) ;
void __set_MSP(uint32_t mainStackPointer) ;
uint32_t __REV16(uint16_t value) ;
int32_t __REVSH(int16_t value) ;
uint32_t __RBIT(uint32_t value) ;
uint8_t __LDREXB(uint8_t *addr) ;
uint16_t __LDREXH(uint16_t *addr) ;
uint32_t __LDREXW(uint32_t *addr) ;
uint32_t __STREXB(uint8_t value, uint8_t *addr) ;
uint32_t __STREXH(uint16_t value, uint16_t *addr) ;
uint32_t __STREXW(uint32_t value, uint32_t *addr) ;
uint32_t __get_BASEPRI(void) ;
void __set_BASEPRI(uint32_t basePri) ;
uint32_t __get_PRIMASK(void) ;
void __set_PRIMASK(uint32_t priMask) ;
uint32_t __get_FAULTMASK(void) ;
void __set_FAULTMASK(uint32_t faultMask) ;
uint32_t __get_CONTROL(void) ;
void __set_CONTROL(uint32_t control) ;
uint32_t __REV(uint32_t value) ;
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
__ASM uint32_t __get_PSP(void)
{
mrs r0, psp
bx lr
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
__ASM void __set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
__ASM uint32_t __get_MSP(void)
{
mrs r0, msp
bx lr
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
__ASM void __set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
__ASM uint32_t __REV16(uint16_t value)
{
rev16 r0, r0
bx lr
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
__ASM int32_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* Removes the exclusive lock which is created by ldrex.
*/
__ASM void __CLREX(void)
{
clrex
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
__ASM uint32_t __get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
__ASM void __set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
__ASM uint32_t __get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
__ASM void __set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
__ASM uint32_t __get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
__ASM void __set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
__ASM uint32_t __get_CONTROL(void)
{
mrs r0, control
bx lr
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
__ASM void __set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#pragma diag_suppress=Pe940
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void)
{
__ASM("mrs r0, psp");
__ASM("bx lr");
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
__ASM("bx lr");
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
__ASM("mrs r0, msp");
__ASM("bx lr");
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
__ASM("bx lr");
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
__ASM("rev16 r0, r0");
__ASM("bx lr");
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit values)
*/
uint8_t __LDREXB(uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t __LDREXH(uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t __LDREXW(uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
__ASM("strexb r2, r0, [r1]");
__ASM("mov r2, r0");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
__ASM("strexh r2, r0, [r1]");
__ASM("mov r2, r0");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
__ASM("strex r2, r0, [r1]");
__ASM("mov r2, r0");
__ASM("bx lr");
}
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
/*extern uint32_t __get_PSP(void) __attribute__( ( naked ) ); */
uint32_t __get_PSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, psp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
/*void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); */
void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n\t"
"BX lr \n\t" : : "r" (topOfProcStack) );
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
/*uint32_t __get_MSP(void) __attribute__( ( naked ) ); */
uint32_t __get_MSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, msp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
/*void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); */
void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n\t"
"BX lr \n\t" : : "r" (topOfMainStack) );
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
uint32_t __get_BASEPRI(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
uint32_t __get_PRIMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
uint32_t __get_FAULTMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
uint32_t __get_CONTROL(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/**
* @brief Reverse byte order in integer value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in integer value
*/
uint32_t __REV(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
uint32_t result=0;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
int32_t __REVSH(int16_t value)
{
uint32_t result=0;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit value
*/
uint8_t __LDREXB(uint8_t *addr)
{
uint8_t result=0;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t __LDREXH(uint16_t *addr)
{
uint16_t result=0;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t __LDREXW(uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif

File diff suppressed because it is too large Load Diff

1
sam3s_example/src_board Symbolic link
View File

@@ -0,0 +1 @@
./atmel_softpack_libraries/libboard_sam3s-ek/source

1
sam3s_example/src_sam3s Symbolic link
View File

@@ -0,0 +1 @@
./atmel_softpack_libraries/libchip_sam3s/source