mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-16 21:28:33 +03:00
Makefile with libs and atmel source
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 ) ;
|
||||
}
|
||||
@@ -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) ;
|
||||
}
|
||||
@@ -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 ) ;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ) ;
|
||||
}
|
||||
}
|
||||
@@ -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 ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
} ;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
@@ -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 ) ;
|
||||
}
|
||||
|
||||
@@ -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 ) ;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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__
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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) ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "pio.h"
|
||||
#include "pmc.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
@@ -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");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 ;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
175
sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c
Normal file
175
sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c
Normal 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 ;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
1
sam3s_example/cmsis
Symbolic link
@@ -0,0 +1 @@
|
||||
./atmel_softpack_libraries/libchip_sam3s/cmsis
|
||||
@@ -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
1
sam3s_example/src_board
Symbolic link
@@ -0,0 +1 @@
|
||||
./atmel_softpack_libraries/libboard_sam3s-ek/source
|
||||
1
sam3s_example/src_sam3s
Symbolic link
1
sam3s_example/src_sam3s
Symbolic link
@@ -0,0 +1 @@
|
||||
./atmel_softpack_libraries/libchip_sam3s/source
|
||||
Reference in New Issue
Block a user