From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- drivers/async/async.c | 48 ++++ drivers/async/async.h | 65 ++++++ drivers/dmad/dmad.c | 300 ++++++++++++++++++++++++ drivers/dmad/dmad.dir | 36 +++ drivers/dmad/dmad.h | 158 +++++++++++++ drivers/drivers.dir | 44 ++++ drivers/lcd/color.h | 132 +++++++++++ drivers/lcd/draw.c | 237 +++++++++++++++++++ drivers/lcd/draw.h | 110 +++++++++ drivers/lcd/draw_hx8347.c | 387 +++++++++++++++++++++++++++++++ drivers/lcd/font.c | 209 +++++++++++++++++ drivers/lcd/font.h | 112 +++++++++ drivers/lcd/font10x14.h | 237 +++++++++++++++++++ drivers/lcd/lcd.dir | 39 ++++ drivers/lcd/lcdd.c | 138 +++++++++++ drivers/lcd/lcdd.h | 61 +++++ drivers/lcd/lcdd_hx8347.c | 147 ++++++++++++ drivers/macb/macb.c | 569 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/macb/macb.dir | 42 ++++ drivers/macb/macb.h | 106 +++++++++ drivers/macb/mii.h | 178 +++++++++++++++ drivers/tsd/tsd.dir | 42 ++++ drivers/tsd/tsd.h | 74 ++++++ drivers/tsd/tsd_ads7843.c | 438 +++++++++++++++++++++++++++++++++++ drivers/tsd/tsd_com.c | 390 +++++++++++++++++++++++++++++++ drivers/tsd/tsd_com.h | 48 ++++ drivers/tsd/tsd_tsadc.c | 269 ++++++++++++++++++++++ drivers/twi/twid.c | 344 ++++++++++++++++++++++++++++ drivers/twi/twid.h | 92 ++++++++ 29 files changed, 5052 insertions(+) create mode 100644 drivers/async/async.c create mode 100644 drivers/async/async.h create mode 100644 drivers/dmad/dmad.c create mode 100644 drivers/dmad/dmad.dir create mode 100644 drivers/dmad/dmad.h create mode 100644 drivers/drivers.dir create mode 100644 drivers/lcd/color.h create mode 100644 drivers/lcd/draw.c create mode 100644 drivers/lcd/draw.h create mode 100644 drivers/lcd/draw_hx8347.c create mode 100644 drivers/lcd/font.c create mode 100644 drivers/lcd/font.h create mode 100644 drivers/lcd/font10x14.h create mode 100644 drivers/lcd/lcd.dir create mode 100644 drivers/lcd/lcdd.c create mode 100644 drivers/lcd/lcdd.h create mode 100644 drivers/lcd/lcdd_hx8347.c create mode 100644 drivers/macb/macb.c create mode 100644 drivers/macb/macb.dir create mode 100644 drivers/macb/macb.h create mode 100644 drivers/macb/mii.h create mode 100644 drivers/tsd/tsd.dir create mode 100644 drivers/tsd/tsd.h create mode 100644 drivers/tsd/tsd_ads7843.c create mode 100644 drivers/tsd/tsd_com.c create mode 100644 drivers/tsd/tsd_com.h create mode 100644 drivers/tsd/tsd_tsadc.c create mode 100644 drivers/twi/twid.c create mode 100644 drivers/twi/twid.h (limited to 'drivers') diff --git a/drivers/async/async.c b/drivers/async/async.c new file mode 100644 index 0000000..618af33 --- /dev/null +++ b/drivers/async/async.c @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------------- + * 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 "async.h" + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Returns 1 if the given transfer has ended; otherwise returns 0. +/// \param pAsync Pointer to an Async instance. +//------------------------------------------------------------------------------ +unsigned char ASYNC_IsFinished(Async *pAsync) +{ + return (pAsync->status != ASYNC_STATUS_PENDING); +} + diff --git a/drivers/async/async.h b/drivers/async/async.h new file mode 100644 index 0000000..e359895 --- /dev/null +++ b/drivers/async/async.h @@ -0,0 +1,65 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef ASYNC_H +#define ASYNC_H + +//------------------------------------------------------------------------------ +// Global definitions +//------------------------------------------------------------------------------ + +/// Transfer is still pending. +#define ASYNC_STATUS_PENDING 0xFF + +//------------------------------------------------------------------------------ +// Global types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Asynchronous transfer descriptor. +//------------------------------------------------------------------------------ +typedef struct _Async { + + // Asynchronous transfer status. + volatile unsigned char status; + // Callback function to invoke when transfer completes or fails. + void *callback; + // Driver storage area; do not use. + unsigned int pStorage[4]; + +} Async; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern unsigned char ASYNC_IsFinished(Async *pAsync); + +#endif //#ifndef ASYNC_H + diff --git a/drivers/dmad/dmad.c b/drivers/dmad/dmad.c new file mode 100644 index 0000000..75187d0 --- /dev/null +++ b/drivers/dmad/dmad.c @@ -0,0 +1,300 @@ +/* ---------------------------------------------------------------------------- + * 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 "dmad.h" +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Local types +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +/// DMA transfer descriptor. Tracks the status and parameters of a transfer +/// on the DMA bus. +//------------------------------------------------------------------------------ +typedef struct _DmaTransfer { + /// Buffer transfer status. + volatile unsigned char status; + /// Transfer buffer size in byte. + unsigned int bufSize; + /// Total transfer size to byte. + volatile unsigned int transferSize; + /// Optional callback function. + DmaCallback callback; +} DmaTransfer; + +//------------------------------------------------------------------------------ +/// DMAD driver structure. Monitors the status of transfers on all +/// DMA channels. +//------------------------------------------------------------------------------ +typedef struct _Dmad { + + /// List of transfers occuring on each channel. + DmaTransfer transfers[DMA_CHANNEL_NUM]; +} Dmad; + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// Global DMA transfer instance. +static Dmad dmad; + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +/// This handler function must be called by the DMAC interrupt service routine. +/// Identifies which event was activated and calls the associated function. +//------------------------------------------------------------------------------ +void DMAD_Handler() +{ + unsigned int status; + unsigned char channel; + DmaTransfer *pTransfer; + status = DMA_GetStatus(); + // Check if the buffer transfer completed is set. + if(status & AT91C_BTC) + { + // Scan each channel status. + for(channel = 0; channel < DMA_CHANNEL_NUM; channel++) { + if(!(status & (DMA_BTC << channel))){ + continue; + } + + dmad.transfers[channel].transferSize -= dmad.transfers[channel].bufSize; + // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit. + if(dmad.transfers[channel].transferSize <= dmad.transfers[channel].bufSize) { + DMA_ClearAutoMode(channel); + } + // Transfer finished + if(dmad.transfers[channel].transferSize == 0) { + pTransfer = &(dmad.transfers[channel]); + pTransfer->callback(); + DMA_DisableIt(DMA_BTC << channel); + DMA_DisableChannel(channel); + } + else + { + // Write the KEEPON field to clear the STALL states. + DMA_KeeponChannel(channel); + } + } + } +} + +//------------------------------------------------------------------------------ +/// Initializes the DMA controller. +/// \param channel Particular channel number +/// \param defaultHandler Using the default dmad interrupt handler. +//------------------------------------------------------------------------------ +void DMAD_Initialize(unsigned char channel, unsigned char defaultHandler) +{ + unsigned int status; + unsigned int flag; + + // Enable peripheral clock +#if !defined(at91sam9rl64) + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_HDMA; +#endif + + // Read the channel handler status to ensure the channel is a free channel. + status = DMA_GetChannelStatus(); + TRACE_INFO ("DMAD_Initialize channel %x \n\r", channel); + SANITY_CHECK(!(status & (1 << channel))); + // Clear any pending interrupts on the channel. + DMA_GetStatus(); + // Disble the channel. + DMA_DisableChannel(channel); + // Disable the interrupt + flag = 0xffffff; + DMA_DisableIt(flag); + // Enable DMA. + DMA_Enable(); + if(defaultHandler) + { + IRQ_ConfigureIT(AT91C_ID_HDMA, 0, DMAD_Handler); + IRQ_EnableIT(AT91C_ID_HDMA); + } + // Initialize transfer instance. + dmad.transfers[channel].transferSize = 0; +} + +//------------------------------------------------------------------------------ +/// Configure the DMA transfer buffer by giving transfer mode, it could be single +/// buffer or multi-buffer(LLI/auto-reload/contiguous buffers) with or without +/// Picture-In-Picture mode. +/// \param channel Particular channel number. +/// \param sourceTransferMode Source buffer transfer mode. +/// \param destTransferMode Destination buffer transfer mode. +/// \param lli Pointer to a DmaLinkList structure instance. +/// \param pip Pointer to a PictureInPicture structure. +//------------------------------------------------------------------------------ +unsigned char DMAD_Configure_Buffer(unsigned char channel, + unsigned char sourceTransferMode, + unsigned char destTransferMode, + DmaLinkList *lli, + PictureInPicture *pip) +{ + DmaTransfer *pTransfer = &(dmad.transfers[channel]); + // Check that no transfer is pending on the channel + if (pTransfer-> transferSize > 0 ) { + TRACE_ERROR("DAM transfer is already pending\n\r"); + return DMAD_ERROR_BUSY; + } + // Configure source transfer mode. + DMA_SetSourceBufferMode(channel, sourceTransferMode, 0); + + // Configure destination transfer mode. + DMA_SetDestBufferMode(channel, destTransferMode, 0); + + if(lli){ + DMA_SetDescriptorAddr(channel, (unsigned int)(&lli[0])); + } + else { + DMA_SetDescriptorAddr(channel, 0); + } + + if(pip){ + #if defined(AT91C_SRC_PIP) + // If source picture-in-picture mode is enabled, program the DMAC_SPIP. + if(pip->pipSourceBoundarySize){ + // If destination picture-in-picture mode is enabled, program the DMAC_DPIP. + DMA_SPIPconfiguration(channel, pip->pipSourceHoleSize, pip->pipSourceBoundarySize); + } + #endif + + #if defined(AT91C_DST_PIP) + if(pip->pipDestBoundarySize){ + DMA_DPIPconfiguration(channel, pip->pipDestHoleSize, pip->pipDestBoundarySize); + } + #endif + } + return 0; +} + +//------------------------------------------------------------------------------ +/// Configure the DMA transfer control infomation. +/// \param channel Particular channel number. +/// \param bufSize Buffer transfer size in byte. +/// \param sourceWidth Source transfer width. +/// \param destWidth Destination transfer width. +/// \param sourceAddress Destination transfer width. +/// \param destAddress Destination transfer width. +//------------------------------------------------------------------------------ +unsigned char DMAD_Configure_TransferController(unsigned char channel, + unsigned int bufSize, + unsigned char sourceWidth, + unsigned char destWidth, + unsigned int sourceAddress, + unsigned int destAddress) +{ + DmaTransfer *pTransfer = &(dmad.transfers[channel]); + // Check that no transfer is pending on the channel + if (pTransfer-> transferSize > 0 ) { + TRACE_ERROR("DAM transfer is already pending\n\r"); + return DMAD_ERROR_BUSY; + } + pTransfer->bufSize = bufSize; + + // Set up the transfer width and transfer size. + DMA_SetSourceBufferSize(channel, bufSize, sourceWidth, destWidth, 0); + + if(sourceAddress) { + // Write the starting source address. + DMA_SetSourceAddr(channel, sourceAddress); + } + if(destAddress){ + // Write the starting destination address. + DMA_SetDestinationAddr(channel, destAddress); + } + return 0; +} + +//------------------------------------------------------------------------------ +/// Starts buffer transfer on the given channel +/// \param channel Particular channel number. +/// \param size Total transfer size in byte. +/// \param callback Optional callback function. +/// \param polling Polling channel status enable. +//------------------------------------------------------------------------------ +unsigned char DMAD_BufferTransfer(unsigned char channel, + unsigned int size, + DmaCallback callback, + unsigned char polling) +{ + DmaTransfer *pTransfer = &(dmad.transfers[channel]); + // Check that no transfer is pending on the channel + if (pTransfer-> transferSize > 0 ) { + TRACE_ERROR("DAM transfer is already pending\n\r"); + return DMAD_ERROR_BUSY; + } + pTransfer->status = DMAD_ERROR_BUSY; + pTransfer->transferSize = size; + pTransfer->callback = callback; + + if(!polling){ + DMA_EnableIt(DMA_BTC << channel); + } + // Enable the channel. + DMA_EnableChannel(channel); + + if(polling){ + while ((DMA_GetChannelStatus() & (DMA_ENA << channel)) == (DMA_ENA << channel)); + if (pTransfer->callback) { + pTransfer->callback(); + } + pTransfer->transferSize = 0; + DMA_DisableChannel(channel); + } + return 0; +} + +//------------------------------------------------------------------------------ +/// Returns 1 if no transfer is currently pending on the given channel; +/// otherwise, returns 0. +/// \param channel Channel number. +//------------------------------------------------------------------------------ +unsigned char DMAD_IsFinished(unsigned char channel) +{ + SANITY_CHECK(channel <= DMA_CHANNEL_NUM); + if (dmad.transfers[channel].transferSize > 0) { + return 0; + } + else { + DMA_DisableChannel(channel); + return 1; + } +} diff --git a/drivers/dmad/dmad.dir b/drivers/dmad/dmad.dir new file mode 100644 index 0000000..a9ec454 --- /dev/null +++ b/drivers/dmad/dmad.dir @@ -0,0 +1,36 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// +/// !!!Contents +/// +/// This directory contains the source code for the DMA driver in dmad.h. +//------------------------------------------------------------------------------ diff --git a/drivers/dmad/dmad.h b/drivers/dmad/dmad.h new file mode 100644 index 0000000..dfb0886 --- /dev/null +++ b/drivers/dmad/dmad.h @@ -0,0 +1,158 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// The %Dma driver is a high level dma driver which performs DMA device Initializes, +/// tansfer mode configuration and dma transfer. +/// +/// !!!Usage +/// +/// -# Initializes a %Dma controller and dma transfer instance. +/// Initializes dma for specified channel using DMAD_Initialize(). +/// -# Configures the %Dma transfer buffer by giving transfer mode, transfer mode +/// for source peripheral and destination peripheral could be single buffer or +/// multi-buffer(LLI/auto-reload/contiguous buffers) with or without +/// Picture-In-Picture mode. +/// DMAD_Configure_Buffer() +/// \code +/// // Configure multi-buffer transfer with source address auto-reloaded and +/// contiguous destination address. +/// DMAD_Configure_Buffer(DMA_CHANNEL_1, +/// DMA_TRANSFER_RELOAD, +/// DMA_TRANSFER_CONTIGUOUS, +/// 0, +/// 0); +/// \endcode +/// -# Configures the %Dma characteristics (such as source/destination +/// single transfer width, buffer transfer size and source/destionation +/// start addreass for the device corresponding to the specified channle +/// using DMAD_Configure_TransferController(). +/// -# Starts a %Dma transfer using DMAD_BufferTransfer(). +/// The transfer is performed using the %Dma channels. +/// -# Initialize the total size to be transfered. +/// -# Initialize the callback function if specified. +/// -# Enable the interrupt for specified %dma channel. +/// -# Enable the specified %dma channel. +/// -# Example for transfering buffer through the %Dma. +/// \code +/// // Start channel 1 transfer. Source image auto-reload 4 times. +/// and transfer to destination continguous. +/// DMAD_BufferTransfer(DMA_CHANNEL_1, bufferSize * 4, TestCallback, 0); +/// while (!DMAD_IsFinished(DMA_CHANNEL_1)); +/// \endcode +/// -# The DMAD_Handler() must be called by the DMA Interrupt Service Routine +/// with the corresponding %Dma instance. It is invokes to check for pending +/// interrupts. +/// - Example for initializing %Dma interrupt handler in upper application. +/// \code +/// AIC_ConfigureIT(AT91C_ID_HDMA, 0, DMAD_Handler); +/// \endcode +//------------------------------------------------------------------------------ + +#ifndef DMAD_H +#define DMAD_H + +//------------------------------------------------------------------------------ +// Global definitions +//------------------------------------------------------------------------------ +/// DMA driver is currently busy. +#define DMAD_ERROR_BUSY 1 +/// Using the default interrupt handler of the DMAD +#define DMAD_USE_DEFAULT_IT 1 +#define DMAD_NO_DEFAULT_IT 0 + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/// DMA driver callback function. +typedef void (*DmaCallback)(); + +//------------------------------------------------------------------------------ +/// DMA multi buffer transfer Linker List Item structure. +//------------------------------------------------------------------------------ +typedef struct _DmaLinkList { + /// Source address. + unsigned int sourceAddress; + /// Destination address. + unsigned int destAddress; + /// Control A value. + unsigned int controlA; + /// Control B value. + unsigned int controlB; + /// Descriptor Address. + unsigned int descriptor; +} DmaLinkList; + +//------------------------------------------------------------------------------ +/// DMA picture-in-picture mode configuration structure. +//------------------------------------------------------------------------------ +typedef struct _PictureInPicture { + /// Size in byte add to the source address in PIP. + unsigned short pipSourceHoleSize; + /// Number of transfer in byte to perform before the source address increase. + unsigned short pipSourceBoundarySize; + /// Size in byte add to the destination address in PIP. + unsigned short pipDestHoleSize; + /// Number of transfer in byte to perform before the destination address increase. + unsigned short pipDestBoundarySize; +} PictureInPicture; + + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ +extern void DMAD_Initialize(unsigned char channel, unsigned char defaultHandler); + +extern unsigned char DMAD_Configure_Buffer(unsigned char channel, + unsigned char sourceTransferMode, + unsigned char destTransferMode, + DmaLinkList *lli, + PictureInPicture *pip); + +extern unsigned char DMAD_Configure_TransferController(unsigned char channel, + unsigned int bufSize, + unsigned char sourceWidth, + unsigned char destWidth, + unsigned int sourceAddress, + unsigned int destAddress); + +extern unsigned char DMAD_BufferTransfer(unsigned char channel, + unsigned int size, + DmaCallback callback, + unsigned char polling); + +extern unsigned char DMAD_IsFinished(unsigned char channel); + +#endif //#ifndef DMAD_H + diff --git a/drivers/drivers.dir b/drivers/drivers.dir new file mode 100644 index 0000000..edf87bd --- /dev/null +++ b/drivers/drivers.dir @@ -0,0 +1,44 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// !Purpose +/// +/// This directory contains several sub-directories, each one corresponding to +/// a category of code modules. +/// +/// Each subdirectory inside this one provides code for fully-fledged drivers. +/// +/// Drivers APIs provide high-level unified interface of functions to drive +/// %interlnal Flash interface, tsd interface, %Twi interface and so on. +/// However, they do not provide low-level functions to use of AT91 peripherals; +/// such code can be found in the #perpherials# directory of at91lib. +//------------------------------------------------------------------------------ + diff --git a/drivers/lcd/color.h b/drivers/lcd/color.h new file mode 100644 index 0000000..68128c2 --- /dev/null +++ b/drivers/lcd/color.h @@ -0,0 +1,132 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef COLOR_H +#define COLOR_H + +//------------------------------------------------------------------------------ +/// RGB 24 Bpp +/// RGB 888 +/// R7R6R5R4 R3R2R1R0 G7G6G5G4 G3G2G1G0 B7B6B5B4 B3B2B1B0 +//------------------------------------------------------------------------------ +#define COLOR_BLACK 0x000000 +#define COLOR_WHITE 0xFFFFFF + +#define COLOR_BLUE 0x0000FF +#define COLOR_GREEN 0x00FF00 +#define COLOR_RED 0xFF0000 + +#define COLOR_NAVY 0x000080 +#define COLOR_DARKBLUE 0x00008B +#define COLOR_DARKGREEN 0x006400 +#define COLOR_DARKCYAN 0x008B8B +#define COLOR_CYAN 0x00FFFF +#define COLOR_TURQUOISE 0x40E0D0 +#define COLOR_INDIGO 0x4B0082 +#define COLOR_DARKRED 0x800000 +#define COLOR_OLIVE 0x808000 +#define COLOR_GRAY 0x808080 +#define COLOR_SKYBLUE 0x87CEEB +#define COLOR_BLUEVIOLET 0x8A2BE2 +#define COLOR_LIGHTGREEN 0x90EE90 +#define COLOR_DARKVIOLET 0x9400D3 +#define COLOR_YELLOWGREEN 0x9ACD32 +#define COLOR_BROWN 0xA52A2A +#define COLOR_DARKGRAY 0xA9A9A9 +#define COLOR_SIENNA 0xA0522D +#define COLOR_LIGHTBLUE 0xADD8E6 +#define COLOR_GREENYELLOW 0xADFF2F +#define COLOR_SILVER 0xC0C0C0 +#define COLOR_LIGHTGREY 0xD3D3D3 +#define COLOR_LIGHTCYAN 0xE0FFFF +#define COLOR_VIOLET 0xEE82EE +#define COLOR_AZUR 0xF0FFFF +#define COLOR_BEIGE 0xF5F5DC +#define COLOR_MAGENTA 0xFF00FF +#define COLOR_TOMATO 0xFF6347 +#define COLOR_GOLD 0xFFD700 +#define COLOR_ORANGE 0xFFA500 +#define COLOR_SNOW 0xFFFAFA +#define COLOR_YELLOW 0xFFFF00 + +#endif // #define COLOR_H + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/lcd/draw.c b/drivers/lcd/draw.c new file mode 100644 index 0000000..e7d5909 --- /dev/null +++ b/drivers/lcd/draw.c @@ -0,0 +1,237 @@ +/* ---------------------------------------------------------------------------- + * 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 "draw.h" +#include "font.h" +#include +#include + +#include + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Fills the given LCD buffer with a particular color. +/// Only works in 24-bits packed mode for now. +/// \param pBuffer LCD buffer to fill. +/// \param color Fill color. +//------------------------------------------------------------------------------ +void LCDD_Fill(void *pBuffer, unsigned int color) +{ + unsigned int i; + unsigned char tmpBuffer[12]; + + // Prepare temporary buffer + for (i=0; i < 4; i++) { + + memcpy(&(tmpBuffer[i*3]), &color, 3); + } + + // Copy in LCD buffer + i = 0; + while (i < (BOARD_LCD_FRAMESIZE * 4)) { + + memcpy(&(((unsigned char *) pBuffer)[i]), tmpBuffer, 12); + i += 12; + } +} + +//------------------------------------------------------------------------------ +/// Sets the specified pixel to the given color. +/// !!! Only works in 24-bits packed mode for now. !!! +/// \param pBuffer LCD buffer to draw on. +/// \param x X-coordinate of pixel. +/// \param y Y-coordinate of pixel. +/// \param color Pixel color. +//------------------------------------------------------------------------------ +void LCDD_DrawPixel( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int color) +{ + unsigned char *pTmp = &(((unsigned char *) pBuffer)[y*3*BOARD_LCD_WIDTH + x*3]); + + // Modify color when using RGB565 +#ifdef BOARD_LCD_RGB565 + unsigned char r; + unsigned char g; + unsigned char b; + + r = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + b = color & 0xFF; + r = ((r & 0x78) << 1) | ((r & 0x80) >> 5) | ((g & 0x80) >> 4); + g = ((g & 0x7C) << 1); + b = (b & 0xFC); + color = (b << 16) | (g << 8) | r; +#elif defined (BOARD_LCD_BGR565) + unsigned char r; + unsigned char g; + unsigned char b; + + r = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + b = color & 0xFF; + color = (b << 16) | (g << 8) | r; +#endif + + pTmp[0] = (color >> 16) & 0xFF; + pTmp[1] = (color >> 8) & 0xFF; + pTmp[2] = (color >> 0) & 0xFF; +} + +//------------------------------------------------------------------------------ +/// Read pixel of given coordinate. +/// !!! Only works in 24-bits packed mode for now. !!! +/// \param pBuffer LCD buffer to draw on. +/// \param x X-coordinate of pixel. +/// \param y Y-coordinate of pixel. +/// \return Pixel color. +//------------------------------------------------------------------------------ +unsigned int LCDD_ReadPixel( + void *pBuffer, + unsigned int x, + unsigned int y) +{ + unsigned char *pTmp = &(((unsigned char *) pBuffer)[y*3*BOARD_LCD_WIDTH + x*3]); + unsigned int color; + +#ifdef BOARD_LCD_RGB565 + color = 0; // TBD +#elif defined (BOARD_LCD_BGR565) + color = ((pTmp[2] << 16) | (pTmp[1] << 8) | pTmp[0]); +#else + color = ((pTmp[0] << 16) | (pTmp[1] << 8) | pTmp[2]); +#endif + + return color; +} + +//------------------------------------------------------------------------------ +/// Draws a rectangle inside a LCD buffer, at the given coordinates. +/// \param pBuffer LCD buffer to draw on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawRectangle( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int color) +{ + unsigned int rx, ry; + + for (ry=0; ry < height; ry++) { + + for (rx=0; rx < width; rx++) { + + LCDD_DrawPixel(pBuffer, x+rx, y+ry, color); + } + } +} + +//------------------------------------------------------------------------------ +/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks +/// will be honored. +/// \param pBuffer Buffer to draw on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawString( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int color) +{ + unsigned xorg = x; + + while (*pString != 0) { + if (*pString == '\n') { + + y += gFont.height + 2; + x = xorg; + } + else { + + LCDD_DrawChar(pBuffer, x, y, *pString, color); + x += gFont.width + 2; + } + pString++; + } +} + +//------------------------------------------------------------------------------ +/// 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. +//------------------------------------------------------------------------------ +void LCDD_GetStringSize( + const char *pString, + unsigned int *pWidth, + unsigned int *pHeight) +{ + unsigned int width = 0; + unsigned int 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) *pWidth = width; + if (pHeight) *pHeight = height; +} diff --git a/drivers/lcd/draw.h b/drivers/lcd/draw.h new file mode 100644 index 0000000..5690b66 --- /dev/null +++ b/drivers/lcd/draw.h @@ -0,0 +1,110 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// Provides simple drawing function to use with the LCD. +/// +/// !!!Usage +/// +/// -# Use LCDD_Fill to fill the LCD buffer with a specific color. +/// -# Draw a pixel on the screen at the specified coordinates using +/// LCDD_DrawPixel. +/// -# Draw a rectangle with LCDD_DrawRectangle. +/// -# Draw a string on the LCD with LCDD_DrawString. +//------------------------------------------------------------------------------ + +#ifndef DRAW_H +#define DRAW_H + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void LCDD_Fill(void *pBuffer, unsigned int color); + +extern void LCDD_DrawPixel( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int c); + +extern unsigned int LCDD_ReadPixel( + void *pBuffer, + unsigned int x, + unsigned int y); + +extern void LCDD_DrawRectangle( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int color); + +extern void LCDD_DrawString( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int color); +extern void LCDD_DrawStringEx( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int color, + unsigned int dir); + +extern void LCDD_DrawStringWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int fontColor, + unsigned int bgColor); + +extern void LCDD_DrawStringWithBGColorEx( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int fontColor, + unsigned int bgColor, + unsigned int dir); + +extern void LCDD_GetStringSize( + const char *pString, + unsigned int *pWidth, + unsigned int *pHeight); + +#endif //#ifndef DRAW_H diff --git a/drivers/lcd/draw_hx8347.c b/drivers/lcd/draw_hx8347.c new file mode 100644 index 0000000..f262d9a --- /dev/null +++ b/drivers/lcd/draw_hx8347.c @@ -0,0 +1,387 @@ +/* ---------------------------------------------------------------------------- + * 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 "draw.h" +#include "font.h" +#include +#include +#include + +#include +/// lcd is busy,0 free,1 busy +int gLCDIsBusy = 0; +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +/// indicate the lcd is available for use +//------------------------------------------------------------------------------ +int LCDD_IsBusy() +{ + return gLCDIsBusy; +} +//------------------------------------------------------------------------------ +/// Set lcd to busy +//------------------------------------------------------------------------------ +void LCDD_SetBusy() +{ + gLCDIsBusy = 1; +} +//------------------------------------------------------------------------------ +/// clear lcd to free +//------------------------------------------------------------------------------ +void LCDD_ClearBusy() +{ + gLCDIsBusy = 0; +} +//------------------------------------------------------------------------------ +/// Fills the given LCD buffer with a particular color. +/// Only works in 24-bits packed mode for now. +/// \param pBuffer LCD buffer to fill. +/// \param color Fill color. +//------------------------------------------------------------------------------ +void LCDD_Fill(void *pBuffer, unsigned int color) +{ + unsigned int i; + unsigned short color16 = RGB24ToRGB16(color); + + + LCD_SetCursor((void *)BOARD_LCD_BASE, 0, 0); + LCD_WriteRAM_Prepare((void *)BOARD_LCD_BASE); + for (i = 0; i < (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++) { + + LCD_WriteRAM((void *)BOARD_LCD_BASE, color16); + } +} + +//------------------------------------------------------------------------------ +/// Sets the specified pixel to the given color. +/// !!! Only works in 24-bits packed mode for now. !!! +/// \param pBuffer LCD buffer to draw on. +/// \param x X-coordinate of pixel. +/// \param y Y-coordinate of pixel. +/// \param color Pixel color. +//------------------------------------------------------------------------------ +void LCDD_DrawPixel( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int color) +{ + unsigned short color16 = RGB24ToRGB16(color); + + LCD_SetCursor(pBuffer, x, y); + LCD_WriteRAM_Prepare(pBuffer); + LCD_WriteRAM(pBuffer, color16); +} + +//------------------------------------------------------------------------------ +/// Read pixel of given coordinate. +/// !!! The return pixel is RGB565 format !!! +/// \param pBuffer LCD buffer to draw on. +/// \param x X-coordinate of pixel. +/// \param y Y-coordinate of pixel. +/// \return Pixel color. +//------------------------------------------------------------------------------ +unsigned int LCDD_ReadPixel( + void *pBuffer, + unsigned int x, + unsigned int y) +{ + unsigned short readData[4]; + unsigned int color; + + LCD_SetCursor(pBuffer, x, y); + LCD_ReadRAM_Prepare(pBuffer); + readData[0] = LCD_ReadRAM(pBuffer); // Dummy date + readData[1] = LCD_ReadRAM(pBuffer); // color R + readData[2] = LCD_ReadRAM(pBuffer); // color G + readData[3] = LCD_ReadRAM(pBuffer); // color B + color = (((readData[1] & 0xF8) << 8) | + ((readData[2] & 0xFC) << 3) | + ((readData[3] & 0xF8) >> 3)); + + return color; +} + +//------------------------------------------------------------------------------ +/// Draws a rectangle inside a LCD buffer, at the given coordinates. +/// \param pBuffer LCD buffer to draw on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawRectangle( + void *pBuffer, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + unsigned int color) +{ + unsigned int rx, ry; + + for (ry=0; ry < height; ry++) { + + for (rx=0; rx < width; rx++) { + + LCDD_DrawPixel(pBuffer, x+rx, y+ry, color); + } + } +} + +//------------------------------------------------------------------------------ +/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks +/// will be honored. +/// \param pBuffer Buffer to draw on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawString( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int color) +{ + unsigned xorg = x; + + while (*pString != 0) { + if (*pString == '\n') { + + y += gFont.height + 2; + x = xorg; + } + else { + + LCDD_DrawChar(pBuffer, x, y, *pString, color); + x += gFont.width + 2; + } + pString++; + } +} +//------------------------------------------------------------------------------ +/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks +/// will be honored. +/// \param pBuffer Buffer to draw on. +/// \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. +/// \param dir The dirciton of the string,0 for horizontal,1 for vertical +//------------------------------------------------------------------------------ +void LCDD_DrawStringEx( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int color, + unsigned int dir) +{ + unsigned int xorg = x; + unsigned int yorg = y; + + if(LCDD_IsBusy()) return; + + gLCDIsBusy = 1; + + if(dir) + { + while (*pString != 0) { + if (*pString == '\n') { + + x -= gFont.height + 2; + y = yorg; + + } + else { + LCDD_DrawCharVertical(pBuffer, x, y, *pString, color); + y += gFont.width + 2; + } + pString++; + } + + } + else + { + while (*pString != 0) { + if (*pString == '\n') { + + y += gFont.height + 2; + x = xorg; + + } + else { + LCDD_DrawChar(pBuffer, x, y, *pString, color); + x += gFont.width + 2; + } + pString++; + } + } + gLCDIsBusy = 0; + +} +//------------------------------------------------------------------------------ +/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks +/// will be honored. +/// \param pBuffer Buffer to draw on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawStringWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int fontColor, + unsigned int bgColor) +{ + unsigned xorg = x; + + while (*pString != 0) { + if (*pString == '\n') { + + y += gFont.height + 2; + x = xorg; + } + else { + + LCDD_DrawCharWithBGColor(pBuffer, x, y, *pString, fontColor, bgColor); + x += gFont.width + 2; + } + pString++; + } +} +//------------------------------------------------------------------------------ +/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks +/// will be honored. +/// \param pBuffer Buffer to draw on. +/// \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. +/// \param dir The dirciton of the string,0 for horizontal,1 for vertical +//------------------------------------------------------------------------------ +void LCDD_DrawStringWithBGColorEx( + void *pBuffer, + unsigned int x, + unsigned int y, + const char *pString, + unsigned int fontColor, + unsigned int bgColor, + unsigned int dir) +{ + unsigned int xorg = x; + unsigned int yorg = y; + + if(LCDD_IsBusy()) return; + + gLCDIsBusy = 1; + + if(dir) + { + while (*pString != 0) { + if (*pString == '\n') { + + x -= gFont.height + 2; + y = yorg; + + } + else { + LCDD_DrawCharVerticalWithBGColor(pBuffer, x, y, *pString, fontColor, bgColor); + y += gFont.width + 2; + } + pString++; + } + } + else + { + while (*pString != 0) { + if (*pString == '\n') { + + y += gFont.height + 2; + x = xorg; + + } + else { + LCDD_DrawCharWithBGColor(pBuffer, x, y, *pString, fontColor, bgColor); + x += gFont.width + 2; + } + pString++; + } + + } + + gLCDIsBusy = 0; + +} +//------------------------------------------------------------------------------ +/// 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. +//------------------------------------------------------------------------------ +void LCDD_GetStringSize( + const char *pString, + unsigned int *pWidth, + unsigned int *pHeight) +{ + unsigned int width = 0; + unsigned int 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) *pWidth = width; + if (pHeight) *pHeight = height; +} diff --git a/drivers/lcd/font.c b/drivers/lcd/font.c new file mode 100644 index 0000000..843c669 --- /dev/null +++ b/drivers/lcd/font.c @@ -0,0 +1,209 @@ +/* ---------------------------------------------------------------------------- + * 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 "font.h" +#include "draw.h" +#include "font10x14.h" +#include + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// Global variable describing the font being instancied. +const Font gFont = {10, 14}; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Draws an ASCII character on the given LCD buffer. +/// \param pBuffer Buffer to write on. +/// \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. +//------------------------------------------------------------------------------ +void LCDD_DrawChar( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int color) +{ + unsigned int row, col; + + SANITY_CHECK((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(pBuffer, x+col, y+row, color); + } + } + for (row = 0; row < 6; row++) { + + if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) { + + LCDD_DrawPixel(pBuffer, x+col, y+row+8, color); + } + } + } +} +//------------------------------------------------------------------------------ +/// Draws an ASCII character on the given LCD buffer with 90 degree clockwise rotate . +/// \param pBuffer Buffer to write on. +/// \param x X-coordinate of character upper-left corner, x decreasing by step. +/// \param y Y-coordinate of character upper-left corner, y increasing by step. +/// \param c Character to output. +/// \param color Character color. +//------------------------------------------------------------------------------ +void LCDD_DrawCharVertical( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int color) +{ + unsigned int row, col; + + SANITY_CHECK((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(pBuffer, x-row, y+col, color); + } + } + for (row = 0; row < 6; row++) { + + if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) { + + LCDD_DrawPixel(pBuffer, x-row-8, y+col, color); + } + } + } +} +//------------------------------------------------------------------------------ +/// Draws an ASCII character on the given LCD buffer. +/// \param pBuffer Buffer to write on. +/// \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 foreground color. +/// \param bgColor Background color of character +//------------------------------------------------------------------------------ +void LCDD_DrawCharWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int fontColor, + unsigned int bgColor) +{ + unsigned int row, col; + + SANITY_CHECK((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(pBuffer, x+col, y+row, fontColor); + } else { + LCDD_DrawPixel(pBuffer, x+col, y+row, bgColor); + } + } + for (row = 0; row < 6; row++) { + + if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) { + + LCDD_DrawPixel(pBuffer, x+col, y+row+8, fontColor); + } else { + LCDD_DrawPixel(pBuffer, x+col, y+row+8, bgColor); + } + } + } +} +//------------------------------------------------------------------------------ +/// Draws an ASCII character on the given LCD buffer ith 90 degree clockwise rotate. +/// \param pBuffer Buffer to write on. +/// \param x X-coordinate of character upper-left corner x decreasing by step. +/// \param y Y-coordinate of character upper-left corner y increasing by step. +/// \param c Character to output. +/// \param fontColor Character foreground color. +/// \param bgColor Background color of character +//------------------------------------------------------------------------------ +void LCDD_DrawCharVerticalWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int fontColor, + unsigned int bgColor) +{ + unsigned int row, col; + + SANITY_CHECK((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(pBuffer, x-row, y+col, fontColor); + } else { + LCDD_DrawPixel(pBuffer, x-row, y+col, bgColor); + } + } + for (row = 0; row < 6; row++) { + + if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) { + + LCDD_DrawPixel(pBuffer, x-row-8, y+col, fontColor); + } else { + LCDD_DrawPixel(pBuffer, x-row-8, y+col, bgColor); + } + } + } +} diff --git a/drivers/lcd/font.h b/drivers/lcd/font.h new file mode 100644 index 0000000..2576de6 --- /dev/null +++ b/drivers/lcd/font.h @@ -0,0 +1,112 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// The font.h files declares a font structure and a LCDD_DrawChar function +/// that must be implemented by a font definition file to be used with the +/// LCDD_DrawString method of draw.h. +/// +/// The font10x14.c implements the necessary variable and function for a 10x14 +/// font. +/// +/// !!!Usage +/// +/// -# Declare a gFont global variable with the necessary Font information. +/// -# Implement an LCDD_DrawChar function which displays the specified +/// character on the LCD. +/// -# Use the LCDD_DrawString method defined in draw.h to display a complete +/// string. +//------------------------------------------------------------------------------ + +#ifndef FONT_H +#define FONT_H + +//------------------------------------------------------------------------------ +// Global types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Describes the font (width, height, supported characters, etc.) used by +/// the LCD driver draw API. +//------------------------------------------------------------------------------ +typedef struct _Font { + + /// Font width in pixels. + unsigned char width; + /// Font height in pixels. + unsigned char height; + +} Font; + +//------------------------------------------------------------------------------ +// Global variables +//------------------------------------------------------------------------------ + +/// Global variable describing the font being instancied. +extern const Font gFont; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void LCDD_DrawChar( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int color); + +extern void LCDD_DrawCharVertical( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int color); + +extern void LCDD_DrawCharWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int fontColor, + unsigned int bgColor); + +extern void LCDD_DrawCharVerticalWithBGColor( + void *pBuffer, + unsigned int x, + unsigned int y, + char c, + unsigned int fontColor, + unsigned int bgColor); + +#endif //#ifndef FONT_H diff --git a/drivers/lcd/font10x14.h b/drivers/lcd/font10x14.h new file mode 100644 index 0000000..b86612a --- /dev/null +++ b/drivers/lcd/font10x14.h @@ -0,0 +1,237 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef LCD_FONT_10x14_H +#define LCD_FONT_10x14_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +const unsigned char 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 +}; + + +#endif // #ifdef _LCD_FONT_10x14_h diff --git a/drivers/lcd/lcd.dir b/drivers/lcd/lcd.dir new file mode 100644 index 0000000..260d5ea --- /dev/null +++ b/drivers/lcd/lcd.dir @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// +/// !!!Contents +/// +/// This directory contains the source code for the LCD driver in lcd.h. In +/// addition, several drawing function are provided by draw.h. A font system is +/// also defined in font.h. Now supports two types of lcd controller: +/// peripheral LCDC and and HX8347 LCDC. +//------------------------------------------------------------------------------ diff --git a/drivers/lcd/lcdd.c b/drivers/lcd/lcdd.c new file mode 100644 index 0000000..efb14ed --- /dev/null +++ b/drivers/lcd/lcdd.c @@ -0,0 +1,138 @@ +/* ---------------------------------------------------------------------------- + * 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 "lcdd.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the LCD controller using the board-specific parameters (stored +/// in the corresponding board.h). The LCD and DMA are not enabled by this +/// function; this is done during the first call to LCDD_DisplayBuffer. +//------------------------------------------------------------------------------ +void LCDD_Initialize(void) +{ + const Pin pPins[] = {PINS_LCD}; + + // Enable pins + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + // Enable peripheral clock + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_LCDC; + +#if defined(at91sam9g10)||defined(at91sam9261) + AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_HCK1; +#endif + + // Disable the LCD and the DMA + LCD_DisableDma(); + LCD_Disable(0); + + // Configure the LCD controller + LCD_SetPixelClock(BOARD_MCK, BOARD_LCD_PIXELCLOCK); + LCD_SetDisplayType(BOARD_LCD_DISPLAYTYPE); + LCD_SetScanMode(AT91C_LCDC_SCANMOD_SINGLESCAN); + LCD_SetBitsPerPixel(BOARD_LCD_BPP); + LCD_SetPolarities(BOARD_LCD_POLARITY_INVVD, + BOARD_LCD_POLARITY_INVFRAME, + BOARD_LCD_POLARITY_INVLINE, + BOARD_LCD_POLARITY_INVCLK, + BOARD_LCD_POLARITY_INVDVAL); + LCD_SetClockMode(BOARD_LCD_CLOCKMODE); + LCD_SetMemoryFormat((unsigned int) AT91C_LCDC_MEMOR_LITTLEIND); + LCD_SetSize(BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT); + + // Configure timings + LCD_SetVerticalTimings(BOARD_LCD_TIMING_VFP, + BOARD_LCD_TIMING_VBP, + BOARD_LCD_TIMING_VPW, + BOARD_LCD_TIMING_VHDLY); + LCD_SetHorizontalTimings(BOARD_LCD_TIMING_HBP, + BOARD_LCD_TIMING_HPW, + BOARD_LCD_TIMING_HFP); + + // Configure contrast (TODO functions) + LCD_SetContrastPrescaler(AT91C_LCDC_PS_NOTDIVIDED); + LCD_SetContrastPolarity(AT91C_LCDC_POL_POSITIVEPULSE); + LCD_SetContrastValue(0x80); + LCD_EnableContrast(); + + // Configure DMA + LCD_SetFrameSize(BOARD_LCD_FRAMESIZE); + LCD_SetBurstLength(4); +} + +//------------------------------------------------------------------------------ +/// Displays the contents of the provided buffer on the LCD. The buffer is +/// provided as-is to the LCD DMA and is not copied. +/// If the LCD and DMA are not yet enabled, this function enables them. +/// \param pBuffer Buffer to display. +/// \return The address of the previously displayed buffer. +//------------------------------------------------------------------------------ +void * LCDD_DisplayBuffer(void *pBuffer) +{ + void *pOldBuffer; + + pOldBuffer = LCD_SetFrameBufferAddress(pBuffer); + + // Enable LCD & DMA if needed + if ((AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMAEN) != AT91C_LCDC_DMAEN) { + + LCD_EnableDma(); + LCD_Enable(0x0C); + } + + return pOldBuffer; +} + +//------------------------------------------------------------------------------ +/// Shutdown the LCD +//------------------------------------------------------------------------------ +void LCDD_Stop(void) +{ + // Enable peripheral clock + AT91C_BASE_PMC->PMC_PCDR = 1 << AT91C_ID_LCDC; + +#if defined(at91sam9g10)||defined(at91sam9261) + AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_HCK1; +#endif + + // Disable the LCD and the DMA + LCD_DisableDma(); + LCD_Disable(0); +} diff --git a/drivers/lcd/lcdd.h b/drivers/lcd/lcdd.h new file mode 100644 index 0000000..27da073 --- /dev/null +++ b/drivers/lcd/lcdd.h @@ -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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// Simple driver for the LCD, which takes care of the initialization. +/// +/// !!!Usage +/// +/// -# Call LCDD_Initialize to configure the LCD controller. +/// -# Set the buffer displayed by the LCD with LCDD_DisplayBuffer if using +/// peripheral LCDC, or start displaying with LCDD_Start if using HX8347. +//------------------------------------------------------------------------------ + +#ifndef LCDD_H +#define LCDD_H + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void LCDD_Initialize(void); // For peripheral LCDC & HX8347 + +extern void * LCDD_DisplayBuffer(void *pBuffer); // For peripheral LCDC only + +extern void LCDD_Start(void); // For HX8347 only + +extern void LCDD_Stop(void); // For peripheral LCDC & HX8347 + +extern void LCDD_SetBacklight (unsigned int step); // For peripheral LCDC only + +#endif //#ifndef LCDD_H diff --git a/drivers/lcd/lcdd_hx8347.c b/drivers/lcd/lcdd_hx8347.c new file mode 100644 index 0000000..e5871ad --- /dev/null +++ b/drivers/lcd/lcdd_hx8347.c @@ -0,0 +1,147 @@ +/* ---------------------------------------------------------------------------- + * 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 "lcdd.h" + +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the LCD controller. +/// SMC are configured @ 96MHz for LCD. +/// \param pLcdBase LCD base address. +//------------------------------------------------------------------------------ +void LCDD_Initialize(void) +{ + const Pin pPins[] = {BOARD_LCD_PINS}; + AT91PS_HSMC4_CS pSMC = AT91C_BASE_HSMC4_CS2; + unsigned int rMode; + + // Enable pins + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + // Enable peripheral clock + PMC_EnablePeripheral(AT91C_ID_HSMC4); + + // EBI SMC Configuration + pSMC->HSMC4_SETUP = 0 + | ((1 << 0) & AT91C_HSMC4_NWE_SETUP) + | ((1 << 8) & AT91C_HSMC4_NCS_WR_SETUP) + | ((9 << 16) & AT91C_HSMC4_NRD_SETUP) + | ((9 << 24) & AT91C_HSMC4_NCS_RD_SETUP) + ; + + pSMC->HSMC4_PULSE = 0 + | (( 4 << 0) & AT91C_HSMC4_NWE_PULSE) + | (( 4 << 8) & AT91C_HSMC4_NCS_WR_PULSE) + | (( 36 << 16) & AT91C_HSMC4_NRD_PULSE) + | (( 36 << 24) & AT91C_HSMC4_NCS_RD_PULSE) + ; + + pSMC->HSMC4_CYCLE = 0 + | ((10 << 0) & AT91C_HSMC4_NWE_CYCLE) + | ((45 << 16) & AT91C_HSMC4_NRD_CYCLE) + ; + + rMode = pSMC->HSMC4_MODE & ~(AT91C_HSMC4_DBW | AT91C_HSMC4_READ_MODE | AT91C_HSMC4_WRITE_MODE); + pSMC->HSMC4_MODE = rMode + | (AT91C_HSMC4_READ_MODE) + | (AT91C_HSMC4_WRITE_MODE) + | (AT91C_HSMC4_DBW_WIDTH_SIXTEEN_BITS) + ; + + // Initialize LCD controller (HX8347) + LCD_Initialize((void *)BOARD_LCD_BASE); + + // Set LCD backlight + LCDD_SetBacklight(25); +} + +//------------------------------------------------------------------------------ +/// Turn on the LCD +//------------------------------------------------------------------------------ +void LCDD_Start(void) +{ + LCD_On((void *)BOARD_LCD_BASE); +} + +//------------------------------------------------------------------------------ +/// Turn off the LCD +//------------------------------------------------------------------------------ +void LCDD_Stop(void) +{ + LCD_Off((void *)BOARD_LCD_BASE); +} + +//------------------------------------------------------------------------------ +/// Set the backlight of the LCD. +/// \param level Backlight brightness level [1..32], 32 is maximum level. +//------------------------------------------------------------------------------ +void LCDD_SetBacklight (unsigned int level) +{ + unsigned int i; + const Pin pPins[] = {BOARD_BACKLIGHT_PIN}; + + // 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); + +// PIO_Clear(pPins); +// PIO_Clear(pPins); +// PIO_Clear(pPins); + } +// PIO_Set(pPins); +} diff --git a/drivers/macb/macb.c b/drivers/macb/macb.c new file mode 100644 index 0000000..0f387dd --- /dev/null +++ b/drivers/macb/macb.c @@ -0,0 +1,569 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +// drivers/macb/macb.c + +//----------------------------------------------------------------------------- +// Headers +//----------------------------------------------------------------------------- +#include "macb.h" +#include "mii.h" +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- +// Definitions +//----------------------------------------------------------------------------- + +/// Default max retry count +#define MACB_RETRY_MAX 1000000 + +//----------------------------------------------------------------------------- +/// Dump all the useful registers +/// \param pMacb Pointer to the MACB instance +//----------------------------------------------------------------------------- +static void MACB_DumpRegisters(Macb *pMacb) +{ + unsigned char phyAddress; + unsigned int retryMax; + unsigned int value; + + TRACE_INFO("MACB_DumpRegisters\n\r"); + ASSERT(pMacb, "F: MACB_DumpRegisters\n\r"); + + EMAC_EnableMdio(); + phyAddress = pMacb->phyAddress; + retryMax = pMacb->retryMax; + + TRACE_INFO("MII MACB @%d) Registers:\n\r", phyAddress); + + EMAC_ReadPhy(phyAddress, MII_BMCR, &value, retryMax); + TRACE_INFO(" _BMCR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_BMSR, &value, retryMax); + TRACE_INFO(" _BMSR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_ANAR, &value, retryMax); + TRACE_INFO(" _ANAR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_ANLPAR, &value, retryMax); + TRACE_INFO(" _ANLPAR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_ANER, &value, retryMax); + TRACE_INFO(" _ANER : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_DSCR, &value, retryMax); + TRACE_INFO(" _DSCR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_DSCSR, &value, retryMax); + TRACE_INFO(" _DSCSR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_10BTCSR, &value, retryMax); + TRACE_INFO(" _10BTCSR: 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_PWDOR, &value, retryMax); + TRACE_INFO(" _PWDOR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_CONFIGR, &value, retryMax); + TRACE_INFO(" _CONFIGR: 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_MDINTR, &value, retryMax); + TRACE_INFO(" _MDINTR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_RECR, &value, retryMax); + TRACE_INFO(" _RECR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_DISCR, &value, retryMax); + TRACE_INFO(" _DISCR : 0x%X\n\r", value); + EMAC_ReadPhy(phyAddress, MII_RLSR, &value, retryMax); + TRACE_INFO(" _RLSR : 0x%X\n\r", value); + + EMAC_DisableMdio(); +} + +//----------------------------------------------------------------------------- +/// Find a valid PHY Address ( from 0 to 31 ). +/// Check BMSR register ( not 0 nor 0xFFFF ) +/// Return 0xFF when no valid PHY Address found. +/// \param pMacb Pointer to the MACB instance +//----------------------------------------------------------------------------- +static unsigned char MACB_FindValidPhy(Macb *pMacb) +{ + unsigned int retryMax; + unsigned int value=0; + unsigned char rc; + unsigned char phyAddress; + unsigned char cnt; + + TRACE_DEBUG("MACB_FindValidPhy\n\r"); + ASSERT(pMacb, "F: MACB_FindValidPhy\n\r"); + + EMAC_EnableMdio(); + phyAddress = pMacb->phyAddress; + retryMax = pMacb->retryMax; + + // Check current phyAddress + rc = phyAddress; + if( EMAC_ReadPhy(phyAddress, MII_PHYID1, &value, retryMax) == 0 ) { + TRACE_ERROR("MACB PROBLEM\n\r"); + } + TRACE_DEBUG("_PHYID1 : 0x%X, addr: %d\n\r", value, phyAddress); + + // Find another one + if (value != MII_OUI_MSB) { + + rc = 0xFF; + for(cnt = 0; cnt < 32; cnt ++) { + + phyAddress = (phyAddress + 1) & 0x1F; + if( EMAC_ReadPhy(phyAddress, MII_PHYID1, &value, retryMax) == 0 ) { + TRACE_ERROR("MACB PROBLEM\n\r"); + } + TRACE_DEBUG("_PHYID1 : 0x%X, addr: %d\n\r", value, phyAddress); + if (value == MII_OUI_MSB) { + + rc = phyAddress; + break; + } + } + } + + EMAC_DisableMdio(); + if (rc != 0xFF) { + + TRACE_INFO("** Valid PHY Found: %d\n\r", rc); + EMAC_ReadPhy(phyAddress, MII_DSCSR, &value, retryMax); + TRACE_DEBUG("_DSCSR : 0x%X, addr: %d\n\r", value, phyAddress); + + } + return rc; +} + + +//----------------------------------------------------------------------------- +// Exported functions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +/// Setup the maximum timeout count of the driver. +/// \param pMacb Pointer to the MACB instance +/// \param toMax Timeout maxmum count. +//----------------------------------------------------------------------------- +void MACB_SetupTimeout(Macb *pMacb, unsigned int toMax) +{ + ASSERT(pMacb, "-F- MACB_SetupTimeout\n\r"); + + pMacb->retryMax = toMax; +} + +//----------------------------------------------------------------------------- +/// Initialize the MACB instance +/// \param pMacb Pointer to the MACB instance +/// \param pEmac Pointer to the Emac instance for the MACB +/// \param phyAddress The PHY address used to access the PHY +/// ( pre-defined by pin status on PHY reset ) +//----------------------------------------------------------------------------- +void MACB_Init(Macb *pMacb, unsigned char phyAddress) +{ + ASSERT(pMacb , "-F- MACB_Init\n\r"); + + pMacb->phyAddress = phyAddress; + + // Initialize timeout by default + pMacb->retryMax = MACB_RETRY_MAX; +} + + +//----------------------------------------------------------------------------- +/// Issue a SW reset to reset all registers of the PHY +/// Return 1 if successfully, 0 if timeout. +/// \param pMacb Pointer to the MACB instance +//----------------------------------------------------------------------------- +static unsigned char MACB_ResetPhy(Macb *pMacb) +{ + unsigned int retryMax; + unsigned int bmcr = MII_RESET; + unsigned char phyAddress; + unsigned int timeout = 10; + unsigned char ret = 1; + + ASSERT(pMacb, "-F- MACB_ResetPhy"); + TRACE_INFO(" MACB_ResetPhy\n\r"); + + phyAddress = pMacb->phyAddress; + retryMax = pMacb->retryMax; + + EMAC_EnableMdio(); + bmcr = MII_RESET; + EMAC_WritePhy(phyAddress, MII_BMCR, bmcr, retryMax); + + do { + EMAC_ReadPhy(phyAddress, MII_BMCR, &bmcr, retryMax); + timeout--; + } while ((bmcr & MII_RESET) && timeout); + + EMAC_DisableMdio(); + + if (!timeout) { + ret = 0; + } + + return( ret ); +} + +//----------------------------------------------------------------------------- +/// Do a HW initialize to the PHY ( via RSTC ) and setup clocks & PIOs +/// This should be called only once to initialize the PHY pre-settings. +/// The PHY address is reset status of CRS,RXD[3:0] (the emacPins' pullups). +/// The COL pin is used to select MII mode on reset (pulled up for Reduced MII) +/// The RXDV pin is used to select test mode on reset (pulled up for test mode) +/// The above pins should be predefined for corresponding settings in resetPins +/// The EMAC peripheral pins are configured after the reset done. +/// Return 1 if RESET OK, 0 if timeout. +/// \param pMacb Pointer to the MACB instance +/// \param mck Main clock setting to initialize clock +/// \param resetPins Pointer to list of PIOs to configure before HW RESET +/// (for PHY power on reset configuration latch) +/// \param nbResetPins Number of PIO items that should be configured +/// \param emacPins Pointer to list of PIOs for the EMAC interface +/// \param nbEmacPins Number of PIO items that should be configured +//----------------------------------------------------------------------------- + +unsigned char MACB_InitPhy(Macb *pMacb, + unsigned int mck, + const Pin *pResetPins, + unsigned int nbResetPins, + const Pin *pEmacPins, + unsigned int nbEmacPins) +{ + unsigned char rc = 1; + unsigned char phy; + volatile unsigned int i; + + ASSERT(pMacb, "-F- MACB_InitPhy\n\r"); + + // Perform RESET + TRACE_DEBUG("RESET PHY\n\r"); + + if (pResetPins) { + + // Configure PINS + PIO_Configure(pResetPins, nbResetPins); + +#if !defined(BOARD_EMAC_RESET) + // Execute reset + RSTC_SetExtResetLength(MACB_RESET_LENGTH); + RSTC_ExtReset(); + // Get NRST level + printf("NRST level %d\n\r", RSTC_GetNrstLevel()); + // Wait for end hardware reset + while (!RSTC_GetNrstLevel()); +#else + int i=0; + const Pin nrstPin = BOARD_EMAC_RESET; + PIO_Configure(&nrstPin, 1); + for(i=0;i<100000;i++) { + PIO_Clear(&nrstPin); + } + PIO_Set(&nrstPin); +#endif + } + + // Configure EMAC runtime pins + if (rc) { + + PIO_Configure(pEmacPins, nbEmacPins); + rc = EMAC_SetMdcClock( mck ); + if (!rc) { + + TRACE_ERROR("No Valid MDC clock\n\r"); + return 0; + } + + // Check PHY Address + phy = MACB_FindValidPhy(pMacb); + if (phy == 0xFF) { + + TRACE_ERROR("PHY Access fail\n\r"); + return 0; + } + if(phy != pMacb->phyAddress) { + + pMacb->phyAddress = phy; + + MACB_ResetPhy(pMacb); + + } + + } + else { + + TRACE_ERROR("PHY Reset Timeout\n\r"); + } + + return rc; +} + +//----------------------------------------------------------------------------- +/// Issue a Auto Negotiation of the PHY +/// Return 1 if successfully, 0 if timeout. +/// \param pMacb Pointer to the MACB instance +//----------------------------------------------------------------------------- +unsigned char MACB_AutoNegotiate(Macb *pMacb) +{ + unsigned int retryMax; + unsigned int value; + unsigned int phyAnar; + unsigned int phyAnalpar; + unsigned int retryCount= 0; + unsigned char phyAddress; + unsigned char rc = 1; + + ASSERT(pMacb, "-F- MACB_AutoNegotiate\n\r"); + phyAddress = pMacb->phyAddress; + retryMax = pMacb->retryMax; + + EMAC_EnableMdio(); + + if (!EMAC_ReadPhy(phyAddress, MII_PHYID1, &value, retryMax)) { + TRACE_ERROR("Pb EMAC_ReadPhy Id1\n\r"); + rc = 0; + goto AutoNegotiateExit; + } + TRACE_DEBUG("ReadPhy Id1 0x%X, addresse: %d\n\r", value, phyAddress); + if (!EMAC_ReadPhy(phyAddress, MII_PHYID2, &phyAnar, retryMax)) { + TRACE_ERROR("Pb EMAC_ReadPhy Id2\n\r"); + rc = 0; + goto AutoNegotiateExit; + } + TRACE_DEBUG("ReadPhy Id2 0x%X\n\r", phyAnar); + + if( ( value == MII_OUI_MSB ) + && ( ((phyAnar>>10)&MII_LSB_MASK) == MII_OUI_LSB ) ) { + + TRACE_DEBUG("Vendor Number Model = 0x%X\n\r", ((phyAnar>>4)&0x3F)); + TRACE_DEBUG("Model Revision Number = 0x%X\n\r", (phyAnar&0x7)); + } + else { + TRACE_ERROR("Problem OUI value\n\r"); + } + + // Setup control register + rc = EMAC_ReadPhy(phyAddress, MII_BMCR, &value, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + value &= ~MII_AUTONEG; // Remove autonegotiation enable + value &= ~(MII_LOOPBACK|MII_POWER_DOWN); + value |= MII_ISOLATE; // Electrically isolate PHY + rc = EMAC_WritePhy(phyAddress, MII_BMCR, value, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + // Set the Auto_negotiation Advertisement Register + // MII advertising for Next page + // 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 + phyAnar = MII_TX_FDX | MII_TX_HDX | + MII_10_FDX | MII_10_HDX | MII_AN_IEEE_802_3; + rc = EMAC_WritePhy(phyAddress, MII_ANAR, phyAnar, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + // Read & modify control register + rc = EMAC_ReadPhy(phyAddress, MII_BMCR, &value, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + value |= MII_SPEED_SELECT | MII_AUTONEG | MII_DUPLEX_MODE; + rc = EMAC_WritePhy(phyAddress, MII_BMCR, value, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + // Restart Auto_negotiation + value |= MII_RESTART_AUTONEG; + value &= ~MII_ISOLATE; + rc = EMAC_WritePhy(phyAddress, MII_BMCR, value, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + TRACE_DEBUG(" _BMCR: 0x%X\n\r", value); + + // Check AutoNegotiate complete + while (1) { + + rc = EMAC_ReadPhy(phyAddress, MII_BMSR, &value, retryMax); + if (rc == 0) { + + TRACE_ERROR("rc==0\n\r"); + goto AutoNegotiateExit; + } + // Done successfully + if (value & MII_AUTONEG_COMP) { + + TRACE_INFO("AutoNegotiate complete\n\r"); + break; + } + // Timeout check + if (retryMax) { + + if (++ retryCount >= retryMax) { + + MACB_DumpRegisters(pMacb); + TRACE_ERROR("TimeOut\n\r"); + rc = 0; + goto AutoNegotiateExit; + } + } + } + + // Get the AutoNeg Link partner base page + rc = EMAC_ReadPhy(phyAddress, MII_ANLPAR, &phyAnalpar, retryMax); + if (rc == 0) { + + goto AutoNegotiateExit; + } + + // Setup the EMAC link speed + if ((phyAnar & phyAnalpar) & MII_TX_FDX) { + + // set MII for 100BaseTX and Full Duplex + EMAC_SetLinkSpeed(1, 1); + } + else if ((phyAnar & phyAnalpar) & MII_10_FDX) { + + // set MII for 10BaseT and Full Duplex + EMAC_SetLinkSpeed(0, 1); + } + else if ((phyAnar & phyAnalpar) & MII_TX_HDX) { + + // set MII for 100BaseTX and half Duplex + EMAC_SetLinkSpeed(1, 0); + } + else if ((phyAnar & phyAnalpar) & MII_10_HDX) { + + // set MII for 10BaseT and half Duplex + EMAC_SetLinkSpeed(0, 0); + } + + // Setup EMAC mode +#if (BOARD_EMAC_MODE_RMII != 1) + EMAC_EnableMII(); +#else + EMAC_EnableRMII(); +#endif + +AutoNegotiateExit: + EMAC_DisableMdio(); + return rc; +} + +//----------------------------------------------------------------------------- +/// Get the Link & speed settings, and automatically setup the EMAC with the +/// settings. +/// Return 1 if link found, 0 if no ethernet link. +/// \param pMacb Pointer to the MACB instance +/// \param applySetting Apply the settings to EMAC interface +//----------------------------------------------------------------------------- +unsigned char MACB_GetLinkSpeed(Macb *pMacb, unsigned char applySetting) +{ + unsigned int retryMax; + unsigned int stat1; + unsigned int stat2; + unsigned char phyAddress; + unsigned char rc = 1; + + TRACE_DEBUG("MACB_GetLinkSpeed\n\r"); + ASSERT(pMacb, "-F- MACB_GetLinkSpeed\n\r"); + + EMAC_EnableMdio(); + phyAddress = pMacb->phyAddress; + retryMax = pMacb->retryMax; + + rc = EMAC_ReadPhy(phyAddress, MII_BMSR, &stat1, retryMax); + if (rc == 0) { + + goto GetLinkSpeedExit; + } + + if ((stat1 & MII_LINK_STATUS) == 0) { + + TRACE_ERROR("Pb: LinkStat: 0x%x\n\r", stat1); + + rc = 0; + goto GetLinkSpeedExit; + } + + if (applySetting == 0) { + + TRACE_ERROR("Pb: applySetting: 0x%x\n\r", applySetting); + goto GetLinkSpeedExit; + } + + // Re-configure Link speed + rc = EMAC_ReadPhy(phyAddress, MII_DSCSR, &stat2, retryMax); + if (rc == 0) { + + TRACE_ERROR("Pb: rc: 0x%x\n\r", rc); + goto GetLinkSpeedExit; + } + + if ((stat1 & MII_100BASE_TX_FD) && (stat2 & MII_100FDX)) { + + // set Emac for 100BaseTX and Full Duplex + EMAC_SetLinkSpeed(1, 1); + } + + if ((stat1 & MII_10BASE_T_FD) && (stat2 & MII_10FDX)) { + + // set MII for 10BaseT and Full Duplex + EMAC_SetLinkSpeed(0, 1); + } + + if ((stat1 & MII_100BASE_T4_HD) && (stat2 & MII_100HDX)) { + + // set MII for 100BaseTX and Half Duplex + EMAC_SetLinkSpeed(1, 0); + } + + if ((stat1 & MII_10BASE_T_HD) && (stat2 & MII_10HDX)) { + + // set MII for 10BaseT and Half Duplex + EMAC_SetLinkSpeed(0, 0); + } + + // Start the EMAC transfers + TRACE_DEBUG("MACB_GetLinkSpeed passed\n\r"); + +GetLinkSpeedExit: + EMAC_DisableMdio(); + return rc; +} + diff --git a/drivers/macb/macb.dir b/drivers/macb/macb.dir new file mode 100644 index 0000000..708cf7f --- /dev/null +++ b/drivers/macb/macb.dir @@ -0,0 +1,42 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// !Purpose +/// +/// Definition of methods and structures for using PHY DM9161 +/// +/// !Usage +/// +//----------------------------------------------------------------------------- +/// +/// +//------------------------------------------------------------------------------ + diff --git a/drivers/macb/macb.h b/drivers/macb/macb.h new file mode 100644 index 0000000..13741a3 --- /dev/null +++ b/drivers/macb/macb.h @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//----------------------------------------------------------------------------- +/// \unit +/// +/// !Purpose +/// +/// Implementation of MACB driver +/// +/// !Contents +/// +/// Please refer to the list of functions in the #Overview# tab of this unit +/// for more detailed information. +//----------------------------------------------------------------------------- + + +// drivers/macb/macb.h + +#ifndef _MACB_H +#define _MACB_H + +//----------------------------------------------------------------------------- +// Headers +//----------------------------------------------------------------------------- +#include + +//----------------------------------------------------------------------------- +// Definitions +//----------------------------------------------------------------------------- + +/// The reset length setting for external reset configuration +#define MACB_RESET_LENGTH 0xD + +//----------------------------------------------------------------------------- +// Types +//----------------------------------------------------------------------------- + +/// The DM9161 instance +typedef struct _Macb { + + /// The retry & timeout settings + unsigned int retryMax; + + /// PHY address ( pre-defined by pins on reset ) + unsigned char phyAddress; + +} Macb, *pMacb; + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +extern void MACB_SetupTimeout(Macb *pMacb, unsigned int toMax); + +extern void MACB_Init(Macb *pMacb, unsigned char phyAddress); + +extern unsigned char MACB_InitPhy(Macb *pMacb, + unsigned int mck, + const Pin *pResetPins, + unsigned int nbResetPins, + const Pin *pEmacPins, + unsigned int nbEmacPins); + +extern unsigned char MACB_AutoNegotiate(Macb *pMacb); + +extern unsigned char MACB_GetLinkSpeed(Macb *pMacb, + unsigned char applySettings); + +extern unsigned char MACB_Send(Macb *pMacb, + void *pBuffer, + unsigned int size); + +extern unsigned int MACB_Poll(Macb *pMacb, + unsigned char *pBuffer, + unsigned int size); + + +#endif // #ifndef _MACB_H + diff --git a/drivers/macb/mii.h b/drivers/macb/mii.h new file mode 100644 index 0000000..e1deda2 --- /dev/null +++ b/drivers/macb/mii.h @@ -0,0 +1,178 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef _MII_DEFINE_H +#define _MII_DEFINE_H + + +//----------------------------------------------------------------------------- +/// Definitions +//----------------------------------------------------------------------------- + +#define MII_BMCR 0 // Basic Mode Control Register +#define MII_BMSR 1 // Basic Mode Status Register +#define MII_PHYID1 2 // PHY Idendifier Register 1 +#define MII_PHYID2 3 // PHY Idendifier Register 2 +#define MII_ANAR 4 // Auto_Negotiation Advertisement Register +#define MII_ANLPAR 5 // Auto_negotiation Link Partner Ability Register +#define MII_ANER 6 // Auto-negotiation Expansion Register +#define MII_DSCR 16 // Specified Configuration Register +#define MII_DSCSR 17 // Specified Configuration and Status Register +#define MII_10BTCSR 18 // 10BASE-T Configuration and Satus Register +#define MII_PWDOR 19 // Power Down Control Register +#define MII_CONFIGR 20 // Specified config Register +#define MII_MDINTR 21 // Specified Interrupt Register +#define MII_RECR 22 // Specified Receive Error Counter Register +#define MII_DISCR 23 // Specified Disconnect Counter Register +#define MII_RLSR 24 // Hardware Reset Latch State Register + +// Basic Mode Control Register (BMCR) +// Bit definitions: MII_BMCR +#define MII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation +#define MII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation +#define MII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps +#define MII_AUTONEG (1 << 12) // Auto-negotiation Enable +#define MII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation +#define MII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation +#define MII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation +#define MII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation +#define MII_COLLISION_TEST (1 << 7) // 1 = Collision test enabled 0 = Normal operation +// Reserved 6 to 0 // Read as 0, ignore on write + +// Basic Mode Status Register (BMSR) +// Bit definitions: MII_BMSR +#define MII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable +#define MII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable +#define MII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable +#define MII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable +#define MII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable +// Reserved 10 to 7 // Read as 0, ignore on write +#define MII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression +#define MII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete +#define MII_REMOTE_FAULT (1 << 4) // Remote Fault +#define MII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability +#define MII_LINK_STATUS (1 << 2) // Link Status +#define MII_JABBER_DETECT (1 << 1) // Jabber Detect +#define MII_EXTEND_CAPAB (1 << 0) // Extended Capability + +// PHY ID Identifier Register +// definitions: MII_PHYID1 +#define MII_LSB_MASK 0x3F + +#if defined(BOARD_EMAC_PHY_COMP_DM9161) +#define MII_OUI_MSB 0x0181 +#define MII_OUI_LSB 0x2E +//#define MII_PHYID1_OUI 0x606E // OUI: Organizationally Unique Identifier +//#define MII_ID 0x0181b8a0 +#elif defined(BOARD_EMAC_PHY_COMP_LAN8700) +#define MII_OUI_MSB 0x0007 +#define MII_OUI_LSB 0x30 +#else +#error no PHY Ethernet component defined ! +#endif + +// Auto-negotiation Advertisement Register (ANAR) +// Auto-negotiation Link Partner Ability Register (ANLPAR) +// Bit definitions: MII_ANAR, MII_ANLPAR +#define MII_NP (1 << 15) // Next page Indication +#define MII_ACK (1 << 14) // Acknowledge +#define MII_RF (1 << 13) // Remote Fault +// Reserved 12 to 11 // Write as 0, ignore on read +#define MII_FCS (1 << 10) // Flow Control Support +#define MII_T4 (1 << 9) // 100BASE-T4 Support +#define MII_TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support +#define MII_TX_HDX (1 << 7) // 100BASE-TX Support +#define MII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support +#define MII_10_HDX (1 << 5) // 10BASE-T Support +// Selector 4 to 0 // Protocol Selection Bits +#define MII_AN_IEEE_802_3 0x0001 + +// Auto-negotiation Expansion Register (ANER) +// Bit definitions: MII_ANER +// Reserved 15 to 5 // Read as 0, ignore on write +#define MII_PDF (1 << 4) // Local Device Parallel Detection Fault +#define MII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able +#define MII_NP_ABLE (1 << 2) // Local Device Next Page Able +#define MII_PAGE_RX (1 << 1) // New Page Received +#define MII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able + +// Specified Configuration Register (DSCR) +// Bit definitions: MII_DSCR +#define MII_BP4B5B (1 << 15) // Bypass 4B5B Encoding and 5B4B Decoding +#define MII_BP_SCR (1 << 14) // Bypass Scrambler/Descrambler Function +#define MII_BP_ALIGN (1 << 13) // Bypass Symbol Alignment Function +#define MII_BP_ADPOK (1 << 12) // BYPASS ADPOK +#define MII_REPEATER (1 << 11) // Repeater/Node Mode +#define MII_TX (1 << 10) // 100BASE-TX Mode Control +#define MII_FEF (1 << 9) // Far end Fault enable +#define MII_RMII_ENABLE (1 << 8) // Reduced MII Enable +#define MII_F_LINK_100 (1 << 7) // Force Good Link in 100Mbps +#define MII_SPLED_CTL (1 << 6) // Speed LED Disable +#define MII_COLLED_CTL (1 << 5) // Collision LED Enable +#define MII_RPDCTR_EN (1 << 4) // Reduced Power Down Control Enable +#define MII_SM_RST (1 << 3) // Reset State Machine +#define MII_MFP_SC (1 << 2) // MF Preamble Suppression Control +#define MII_SLEEP (1 << 1) // Sleep Mode +#define MII_RLOUT (1 << 0) // Remote Loopout Control + +// Specified Configuration and Status Register (DSCSR) +// Bit definitions: MII_DSCSR +#define MII_100FDX (1 << 15) // 100M Full Duplex Operation Mode +#define MII_100HDX (1 << 14) // 100M Half Duplex Operation Mode +#define MII_10FDX (1 << 13) // 10M Full Duplex Operation Mode +#define MII_10HDX (1 << 12) // 10M Half Duplex Operation Mode + +// 10BASE-T Configuration/Status (10BTCSR) +// Bit definitions: MII_10BTCSR +// Reserved 18 to 15 // Read as 0, ignore on write +#define MII_LP_EN (1 << 14) // Link Pulse Enable +#define MII_HBE (1 << 13) // Heartbeat Enable +#define MII_SQUELCH (1 << 12) // Squelch Enable +#define MII_JABEN (1 << 11) // Jabber Enable +#define MII_10BT_SER (1 << 10) // 10BASE-T GPSI Mode +// Reserved 9 to 1 // Read as 0, ignore on write +#define MII_POLR (1 << 0) // Polarity Reversed + +// Specified Interrupt Register +// Bit definitions: MII_MDINTR +#define MII_INTR_PEND (1 << 15) // Interrupt Pending +// Reserved 14 to 12 // Reserved +#define MII_FDX_MASK (1 << 11) // Full-duplex Interrupt Mask +#define MII_SPD_MASK (1 << 10) // Speed Interrupt Mask +#define MII_LINK_MASK (1 << 9) // Link Interrupt Mask +#define MII_INTR_MASK (1 << 8) // Master Interrupt Mask +// Reserved 7 to 5 // Reserved +#define MII_FDX_CHANGE (1 << 4) // Duplex Status Change Interrupt +#define MII_SPD_CHANGE (1 << 3) // Speed Status Change Interrupt +#define MII_LINK_CHANGE (1 << 2) // Link Status Change Interrupt +// Reserved 1 // Reserved +#define MII_INTR_STATUS (1 << 0) // Interrupt Status + +#endif // #ifndef _MII_DEFINE_H + diff --git a/drivers/tsd/tsd.dir b/drivers/tsd/tsd.dir new file mode 100644 index 0000000..c72fa6f --- /dev/null +++ b/drivers/tsd/tsd.dir @@ -0,0 +1,42 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// +/// !!!Contents +/// +/// This directory contains the source code of the touchscreen driver. tsd.h +/// contains all the interface functions definitions. tsd_tsadc.c contains the +/// implementation of the driver for the chip that have the peripheral ip TSADC. +/// tsd_ads7843.c contains the driver implementation for board that have the +/// external component ads7843 (the chip has not the peripheral ip TSDADC). +/// tds_com.c contains all the common function for the two driver implementations +/// (calibration functions). +//------------------------------------------------------------------------------ diff --git a/drivers/tsd/tsd.h b/drivers/tsd/tsd.h new file mode 100644 index 0000000..22a4930 --- /dev/null +++ b/drivers/tsd/tsd.h @@ -0,0 +1,74 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// This unit provides a very powerful touchscreen driver which handles all the +/// complexity. This includes touchscreen calibration, retrieving measurements, +/// configuring the TSADC, etc. +/// +/// !!!Usage +/// +/// -# Call TSD_Initialize() whenever the touchscreen should start the +/// calibration process (as it is done in the function). +/// -# Declare a global TSD_PenPressed function anywhere in your code. This +/// function will get called every time the pen is pressed on the screen. +/// -# Declare a global TSD_PenMoved function, which will get called whenever +/// the pen stays in contact with the screen but changes position. +/// -# Declare a global TSD_PenReleased function, which will be invoked as the +/// pen is lifted from the screen. +//------------------------------------------------------------------------------ + +#ifndef TSD_H +#define TSD_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "tsd_com.h" + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void TSD_Initialize(void *pLcdBuffer); + +extern unsigned char TSD_Calibrate(void *pLcdBuffer); + +extern void TSD_Reset(void); + +#ifdef at91sam3u +extern void TSD_TimerHandler(void); +#endif + +#endif //#ifndef TSD_H diff --git a/drivers/tsd/tsd_ads7843.c b/drivers/tsd/tsd_ads7843.c new file mode 100644 index 0000000..3800a5f --- /dev/null +++ b/drivers/tsd/tsd_ads7843.c @@ -0,0 +1,438 @@ +/* ---------------------------------------------------------------------------- + * 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 + +#ifdef BOARD_TSC_ADS7843 + +#include "tsd.h" +#include "tsd_com.h" +#include +#include +#include +#if defined(cortexm3) +#include +#else +#include +#endif +#include +#include +#include +#include + +#include + +//------------------------------------------------------------------------------ +// Local definitions +//------------------------------------------------------------------------------ + +/// PIT period value in µseconds. +#define PIT_PERIOD 10000 // 10 ms + +/// Delay for pushbutton debouncing (in PIT_PERIOD time-base). +#define DEBOUNCE_TIME 6 // PIT_PERIOD * 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 + +//------------------------------------------------------------------------------ +// Local 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 Pin pinPenIRQ = PIN_TCS_IRQ; + +/// Global timestamp in milliseconds since start of application. +static volatile unsigned int timestamp = 0; + +/// last time when the pen is pressed on the touchscreen +static volatile unsigned int timePress = 0; + +/// last time when the pen is released +static volatile unsigned int timeRelease = 0; + +/// pen state +static volatile e_pen_state penState = STATE_PEN_RELEASED; + +/// Touch screen initiallized flag +static unsigned int tsInitFlag = 0; + +//------------------------------------------------------------------------------ +// External functions +//------------------------------------------------------------------------------ + +extern void TSD_PenPressed(unsigned int x, unsigned int y); +extern void TSD_PenMoved(unsigned int x, unsigned int y); +extern void TSD_PenReleased(unsigned int x, unsigned int y); + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ +extern void TSD_GetRawMeasurement(unsigned int *pData); + +#if defined(cortexm3) +//------------------------------------------------------------------------------ +/// 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. +/// For AT91SAM3, SysTick interrupt should call it per 10ms. +//------------------------------------------------------------------------------ +void TSD_TimerHandler(void) +{ + unsigned int data[2]; + static unsigned int 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) { + + if( (timestamp - timePress) > 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) { + + if( (timestamp - timeRelease) > 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]); + } + } + } + } +} + +#else // For SAM7/SAM9 + +//------------------------------------------------------------------------------ +/// Handler for PIT interrupt. 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. +//------------------------------------------------------------------------------ +static void ISR_Pit(void) +{ + unsigned int status; + unsigned int data[2]; + static unsigned int point[2]; + + // Read the PIT status register + status = PIT_GetStatus() & AT91C_PITC_PITS; + if (status != 0) { + + // Read the PIVR to acknowledge interrupt and get number of ticks + timestamp += (PIT_GetPIVR() >> 20); + } + + // 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 + PIO_DisableIt(&pinPenIRQ); + ADS7843_GetPosition(&data[0], &data[1]); + PIO_EnableIt(&pinPenIRQ); + + 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) { + + if( (timestamp - timePress) > 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) { + + if( (timestamp - timeRelease) > 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]); + } + } + } + } +} +#endif + +//------------------------------------------------------------------------------ +/// 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; + } + } +} + +#if !defined(cortexm3) +//------------------------------------------------------------------------------ +/// Configure the periodic interval timer to generate an interrupt every 10 ms +//------------------------------------------------------------------------------ +static void ConfigurePit(void) +{ + // Initialize the PIT to the desired frequency + PIT_Init(PIT_PERIOD, BOARD_MCK / 1000000); + + // Configure interrupt on PIT + IRQ_DisableIT(AT91C_ID_SYS); + IRQ_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, ISR_Pit); + IRQ_EnableIT(AT91C_ID_SYS); + PIT_EnableIT(); + + // Enable the pit + PIT_Enable(); +} +#endif + +//----------------------------------------------------------------------------- +/// Configure PENIRQ for interrupt +//----------------------------------------------------------------------------- +void ConfigurePenIRQ(void) +{ + // Configure pios + PIO_Configure(&pinPenIRQ, PIO_LISTSIZE(pinPenIRQ)); + + // Initialize interrupts +#if defined(cortexm3) + PIO_InitializeInterrupts(0); +#else // For SAM7/SAM9 + PIO_InitializeInterrupts(AT91C_AIC_PRIOR_HIGHEST); +#endif + PIO_ConfigureIt(&pinPenIRQ, (void (*)(const Pin *)) ISR_PenIRQ); + + // Enable the interrupt + PIO_EnableIt(&pinPenIRQ); +} + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Reads and store a touchscreen measurement in the provided array. +/// \param pData Array where the measurements will be stored +//------------------------------------------------------------------------------ +void TSD_GetRawMeasurement(unsigned int *pData) +{ +#if defined(cortexm3) + // Get the current position of the pressed pen + PIO_DisableIt(&pinPenIRQ); + ADS7843_GetPosition(&pData[0], &pData[1]); + PIO_EnableIt(&pinPenIRQ); +#else + // Get the current position of the pressed pen + PIO_DisableIt(&pinPenIRQ); + ADS7843_GetPosition(&pData[0], &pData[1]); + PIO_EnableIt(&pinPenIRQ); +#endif +} + +//------------------------------------------------------------------------------ +/// Wait pen pressed +//------------------------------------------------------------------------------ +void TSD_WaitPenPressed(void) +{ + // Wait for touch & end of conversion + while (penState != STATE_PEN_RELEASED); + while (penState != STATE_PEN_PRESSED); +} + +//------------------------------------------------------------------------------ +/// Wait pen released +//------------------------------------------------------------------------------ +void TSD_WaitPenReleased(void) +{ + // Wait for contact loss + while (penState != STATE_PEN_PRESSED); + while (penState != STATE_PEN_RELEASED); +} + +//------------------------------------------------------------------------------ +/// Do calibration +/// \param pLcdBuffer LCD buffer to use for displaying the calibration info. +/// \return 1 if calibration is Ok, 0 else +//------------------------------------------------------------------------------ +unsigned char TSD_Calibrate(void *pLcdBuffer) +{ + unsigned char ret = 0; + + // Calibration is done only once + if(TSDCom_IsCalibrationOk()) { + return 1; + } + + // Do calibration + ret = TSDCom_Calibrate(pLcdBuffer); + + return ret; +} + +//------------------------------------------------------------------------------ +/// Initializes the touchscreen driver and starts the calibration process. When +/// finished, the touchscreen is operational. +/// +/// Important: the LCD driver must have been initialized prior to calling this +/// function. +/// \param pBuffer LCD buffer to use for displaying the calibration info. +//------------------------------------------------------------------------------ +void TSD_Initialize(void *pLcdBuffer) +{ + ADS7843_Initialize(); + ConfigurePenIRQ(); +#if !defined(cortexm3) + ConfigurePit(); +#endif + tsInitFlag = 1; + + // Calibration + if(pLcdBuffer) { + while (!TSD_Calibrate(pLcdBuffer)); + } +} + +//------------------------------------------------------------------------------ +/// Stop the Touchscreen, disable interrupt and stop Pit +//------------------------------------------------------------------------------ +void TSD_Reset(void) +{ + // Disable SPI 0 + ADS7843_Reset(); + + // Disable the interrupt + PIO_DisableIt(&pinPenIRQ); + +#if !defined(cortexm3) + // Stop Pit interrupt + PIT_DisableIT(); + IRQ_DisableIT(AT91C_ID_SYS); +#endif +} + +#endif //#ifdef BOARD_TSC_ADS7843 diff --git a/drivers/tsd/tsd_com.c b/drivers/tsd/tsd_com.c new file mode 100644 index 0000000..a930cc9 --- /dev/null +++ b/drivers/tsd/tsd_com.c @@ -0,0 +1,390 @@ +/* ---------------------------------------------------------------------------- + * 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 "tsd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Local 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 (positive or negative) +#define DELAY_RESULT_DISPLAY 4000000 + +//------------------------------------------------------------------------------ +// Local types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Point used during the touchscreen calibration process. +//------------------------------------------------------------------------------ +typedef struct _CalibrationPoint { + + /// Coordinate of point along the X-axis of the screen. + unsigned int x; + /// Coordinate of point along the Y-axis of the screen. + unsigned int y; + /// Calibration data of point. + unsigned int data[2]; + +} CalibrationPoint; + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// indicates if the touch screen has been calibrated. +/// If not, Callback functions are not called +static volatile unsigned char bCalibrationOk = 0; +/// Slope for interpoling touchscreen measurements along the X-axis. +static signed int xSlope; +/// Slope for interpoling touchscreen measurements along the Y-axis. +static signed int 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} +}; + +//------------------------------------------------------------------------------ +// External functions +//------------------------------------------------------------------------------ + +extern void TSD_GetRawMeasurement(unsigned int *pData); +extern void TSD_WaitPenPressed(void); +extern void TSD_WaitPenReleased(void); + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Display a calibration point on the given buffer. +/// \param pLcdBuffer LCD buffer to draw on. +/// \param pPoint Calibration point to display. +//------------------------------------------------------------------------------ +static void DrawCalibrationPoint( + void *pLcdBuffer, + const CalibrationPoint *pPoint) +{ + LCDD_DrawRectangle(pLcdBuffer, + pPoint->x - POINTS_SIZE / 2, + pPoint->y - POINTS_SIZE / 2, + POINTS_SIZE, + POINTS_SIZE, + COLOR_RED); +} + +//------------------------------------------------------------------------------ +/// Clears a calibration point from the given buffer. +/// \param pLcdBuffer LCD buffer to draw on. +/// \param pPoint Calibration point to clear. +//------------------------------------------------------------------------------ +static void ClearCalibrationPoint( + void *pLcdBuffer, + const CalibrationPoint *pPoint) +{ + LCDD_DrawRectangle(pLcdBuffer, + pPoint->x - POINTS_SIZE / 2, + pPoint->y - POINTS_SIZE / 2, + POINTS_SIZE, + POINTS_SIZE, + COLOR_WHITE); +} + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Indicates if the calibration of the touch screen is Ok +/// \return 1 calibration Ok, 0 if not +//------------------------------------------------------------------------------ +unsigned char TSDCom_IsCalibrationOk(void) +{ + if (bCalibrationOk == 1) { + return 1; + } else { + return 0; + } +} + +//------------------------------------------------------------------------------ +/// 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 unsigned int *pData, unsigned int *pPoint) +{ + pPoint[0] = calibrationPoints[0].x + - (((signed int) calibrationPoints[0].data[0] - (signed int) pData[0]) * 1024) + / xSlope; + + pPoint[1] = calibrationPoints[0].y + - (((signed int) calibrationPoints[0].data[1] - (signed int) 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; + } +} + +//------------------------------------------------------------------------------ +/// Performs the calibration process using the provided buffer to display +/// information. +/// \param pLcdBuffer LCD buffer to display. +/// \return True if calibration was successful; otherwise false. +//------------------------------------------------------------------------------ +unsigned char TSDCom_Calibrate(void *pLcdBuffer) +{ +#ifdef AT91C_ID_LCDC + void *pOldLcdBuffer; +#endif + volatile unsigned int i; // to keep the tempo with gcc code optimisation + signed int slope1, slope2; + CalibrationPoint measuredPoint; + unsigned char xOk, yOk; + signed int xDiff, yDiff; + + // Calibration setup + LCDD_Fill(pLcdBuffer, COLOR_WHITE); + LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); + LCDD_DrawString(pLcdBuffer, 1, 100, " Touch the dots to\ncalibrate the screen", COLOR_DARKBLUE); +#ifdef AT91C_ID_LCDC + pOldLcdBuffer = LCDD_DisplayBuffer(pLcdBuffer); +#endif + + // Calibration points + for (i=0; i < 4; i++) { + + DrawCalibrationPoint(pLcdBuffer, &calibrationPoints[i]); + + // Wait for touch & end of conversion + TSD_WaitPenPressed(); + TSD_GetRawMeasurement(calibrationPoints[i].data); + ClearCalibrationPoint(pLcdBuffer, &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 = ((signed int) calibrationPoints[0].data[0]) - ((signed int) calibrationPoints[1].data[0]); + slope1 *= 1024; + slope1 /= ((signed int) calibrationPoints[0].x) - ((signed int) calibrationPoints[1].x); + slope2 = ((signed int) calibrationPoints[2].data[0]) - ((signed int) calibrationPoints[3].data[0]); + slope2 *= 1024; + slope2 /= ((signed int) calibrationPoints[2].x) - ((signed int) calibrationPoints[3].x); + xSlope = (slope1 + slope2) / 2; + + slope1 = ((signed int) calibrationPoints[0].data[1]) - ((signed int) calibrationPoints[2].data[1]); + slope1 *= 1024; + slope1 /= ((signed int) calibrationPoints[0].y) - ((signed int) calibrationPoints[2].y); + slope2 = ((signed int) calibrationPoints[1].data[1]) - ((signed int) calibrationPoints[3].data[1]); + slope2 *= 1024; + slope2 /= ((signed int) calibrationPoints[1].y) - ((signed int) calibrationPoints[3].y); + ySlope = (slope1 + slope2) / 2; + + // Test point + LCDD_Fill(pLcdBuffer, 0xFFFFFF); + LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); + LCDD_DrawString(pLcdBuffer, 1, 100, " Touch the point to\nvalidate calibration", COLOR_DARKBLUE); + DrawCalibrationPoint(pLcdBuffer, &testPoint); + + // Wait for touch & end of conversion + TSD_WaitPenPressed(); + + TSD_GetRawMeasurement(measuredPoint.data); + TSDCom_InterpolateMeasurement(measuredPoint.data, (unsigned int *) &measuredPoint); + DrawCalibrationPoint(pLcdBuffer, &measuredPoint); + + // Check resulting x and y + xDiff = (signed int) measuredPoint.x - (signed int) testPoint.x; + yDiff = (signed int) measuredPoint.y - (signed int) 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(pLcdBuffer, COLOR_WHITE); + LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); + LCDD_DrawString(pLcdBuffer, 80, 100, "Success !", COLOR_GREEN); + + } + else { + + bCalibrationOk = 0; + LCDD_Fill(pLcdBuffer, COLOR_WHITE); + LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); + LCDD_DrawString(pLcdBuffer, 40, 100, "Error too big", COLOR_RED); + } + + // Slight delay + for (i = 0; i < DELAY_RESULT_DISPLAY; i++); + +#ifdef AT91C_ID_LCDC + // Restore old LCD buffer + LCDD_DisplayBuffer(pOldLcdBuffer); +#endif + + return (xOk && yOk); +} + +//------------------------------------------------------------------------------ +/// Read calibrate data to buffer. +/// \param pBuffer Data buffer. +/// \param size Size of data buffer in bytes. +//------------------------------------------------------------------------------ +void TSDCom_ReadCalibrateData(void *pBuffer, unsigned int size) +{ + unsigned char *pDest = (unsigned char *)pBuffer; + + SANITY_CHECK((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); +} + +//------------------------------------------------------------------------------ +/// Restore calibrate data with buffer data. +/// \param pBuffer Data buffer. +/// \param size Size of data buffer in bytes. +//------------------------------------------------------------------------------ +void TSDCom_RestoreCalibrateData(void *pBuffer, unsigned int size) +{ + unsigned char *pSrc = (unsigned char *)pBuffer; + + SANITY_CHECK((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); +} + diff --git a/drivers/tsd/tsd_com.h b/drivers/tsd/tsd_com.h new file mode 100644 index 0000000..91e99c6 --- /dev/null +++ b/drivers/tsd/tsd_com.h @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef TSD_COM_H +#define TSD_COM_H + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void TSDCom_InterpolateMeasurement( + const unsigned int *pData, + unsigned int *pPoint); + +unsigned char TSDCom_Calibrate(void *pLcdBuffer); + +unsigned char TSDCom_IsCalibrationOk(void); + +void TSDCom_ReadCalibrateData(void *pBuffer, unsigned int size); +void TSDCom_RestoreCalibrateData(void *pBuffer, unsigned int size); + +#endif //#ifndef TSD_COM_H diff --git a/drivers/tsd/tsd_tsadc.c b/drivers/tsd/tsd_tsadc.c new file mode 100644 index 0000000..bb9106a --- /dev/null +++ b/drivers/tsd/tsd_tsadc.c @@ -0,0 +1,269 @@ +/* ---------------------------------------------------------------------------- + * 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 + +#ifdef AT91C_BASE_TSADC + +#include "tsd.h" +#include "tsd_com.h" +#include +#include +#include +#include +#include +#include + +#include + +//------------------------------------------------------------------------------ +// Local definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Local types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// External functions +//------------------------------------------------------------------------------ + +extern void TSD_PenPressed(unsigned int x, unsigned int y); +extern void TSD_PenMoved(unsigned int x, unsigned int y); +extern void TSD_PenReleased(unsigned int x, unsigned int y); + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ +extern void TSD_GetRawMeasurement(unsigned int *pData); + +//------------------------------------------------------------------------------ +/// Interrupt handler for the TSADC. Handles pen press, pen move and pen release +/// events by invoking three callback functions. +//------------------------------------------------------------------------------ +static void InterruptHandler(void) +{ + unsigned int status; + unsigned int data[2]; + static unsigned int newPoint[2]; + static unsigned int point[2]; + static unsigned char report = 0; + + // Retrieve TADC status + // Bug fix: two step operation so IAR doesn't complain that the order of + // volatile access is unspecified. + status = AT91C_BASE_TSADC->TSADC_SR; + status &= AT91C_BASE_TSADC->TSADC_IMR; + + // Pen release + if ((status & AT91C_TSADC_NOCNT) == AT91C_TSADC_NOCNT) { + + // Invoke PenReleased callback + if(TSDCom_IsCalibrationOk()) { + TSD_PenReleased(point[0], point[1]); + } + + // Stop periodic trigger mode + TSADCC_SetDebounceTime(BOARD_TOUCHSCREEN_DEBOUNCE); + AT91C_BASE_TSADC->TSADC_IDR = AT91C_TSADC_EOC3 | AT91C_TSADC_NOCNT; + + TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PENDET_TRIGGER); + TSD_GetRawMeasurement(data); // Clear data registers + AT91C_BASE_TSADC->TSADC_SR; + AT91C_BASE_TSADC->TSADC_IER = AT91C_TSADC_PENCNT; + } + // Pen press + else if ((status & AT91C_TSADC_PENCNT) == AT91C_TSADC_PENCNT) { + + // Invoke PenPressed callback with (x,y) coordinates + while ((AT91C_BASE_TSADC->TSADC_SR & AT91C_TSADC_EOC3) != AT91C_TSADC_EOC3); + TSD_GetRawMeasurement(data); + TSDCom_InterpolateMeasurement(data, point); + + // Invoke PenPressed callback + if(TSDCom_IsCalibrationOk()) { + TSD_PenPressed(point[0], point[1]); + } + + // Configure TSADC for periodic trigger + TSADCC_SetDebounceTime(10); // 1ns + AT91C_BASE_TSADC->TSADC_IER = AT91C_TSADC_EOC3 | AT91C_TSADC_NOCNT; + AT91C_BASE_TSADC->TSADC_IDR = AT91C_TSADC_PENCNT; + TSADCC_SetTriggerPeriod(10000000); // 10ms + TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PERIODIC_TRIGGER); + report = 0; + } + // Pen move + else if ((status & AT91C_TSADC_EOC3) == AT91C_TSADC_EOC3) { + + // Invoke callback with LAST value measured + // Explanation: the very last value that will be measured (just as the + // pen is released) might be corrupted and there is no way to know. So + // we just discard it. + + if (report) { + + memcpy(point, newPoint, sizeof(newPoint)); + // Invoke PenMoved callback + if(TSDCom_IsCalibrationOk()) { + TSD_PenMoved(point[0], point[1]); + } + report = 0; + } + + TSD_GetRawMeasurement(data); + TSDCom_InterpolateMeasurement(data, newPoint); + if ((newPoint[0] != point[0]) || (newPoint[1] != point[1])) { + + report = 1; + } + } +} + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Reads and store a touchscreen measurement in the provided array. +/// The value stored are: +/// - data[0] = CDR3 * 1024 / CDR2 +/// - data[1] = CDR1 * 1024 / CDR0 +/// \param pData Array where the measurements will be stored +//------------------------------------------------------------------------------ +void TSD_GetRawMeasurement(unsigned int *pData) +{ + pData[0] = (AT91C_BASE_TSADC->TSADC_CDR3 * 1024); + pData[0] /= AT91C_BASE_TSADC->TSADC_CDR2; + pData[1] = (AT91C_BASE_TSADC->TSADC_CDR1 * 1024); + pData[1] /= AT91C_BASE_TSADC->TSADC_CDR0; +} + +//------------------------------------------------------------------------------ +/// Wait pen pressed +//------------------------------------------------------------------------------ +void TSD_WaitPenPressed(void) +{ + // Wait for touch & end of conversion + while ((AT91C_BASE_TSADC->TSADC_SR & AT91C_TSADC_PENCNT) != AT91C_TSADC_PENCNT); + while ((AT91C_BASE_TSADC->TSADC_SR & AT91C_TSADC_EOC3) != AT91C_TSADC_EOC3); +} + +//------------------------------------------------------------------------------ +/// Wait pen released +//------------------------------------------------------------------------------ +void TSD_WaitPenReleased(void) +{ + // Wait for contact loss + while ((AT91C_BASE_TSADC->TSADC_SR & AT91C_TSADC_NOCNT) != AT91C_TSADC_NOCNT); +} + +//------------------------------------------------------------------------------ +/// Do calibration +/// \param pLcdBuffer LCD buffer to use for displaying the calibration info. +/// \return 1 if calibration is Ok, 0 else +//------------------------------------------------------------------------------ +unsigned char TSD_Calibrate(void *pLcdBuffer) +{ + unsigned char ret = 0; + + // Calibration is done only once + if(TSDCom_IsCalibrationOk()) { + return 1; + } + + // Enable trigger + TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PENDET_TRIGGER); + + // Do calibration + ret = TSDCom_Calibrate(pLcdBuffer); + + // Disable trigger + TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_NO_TRIGGER); + + // Configure interrupt generation + // Do it only if the calibration is Ok. + if(ret) { + TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PENDET_TRIGGER); + IRQ_ConfigureIT(AT91C_ID_TSADC, 0, InterruptHandler); + IRQ_EnableIT(AT91C_ID_TSADC); + AT91C_BASE_TSADC->TSADC_IER = AT91C_TSADC_PENCNT; + } + + return ret; +} + +//------------------------------------------------------------------------------ +/// Initializes the touchscreen driver and starts the calibration process. When +/// finished, the touchscreen is operational. +/// The configuration is taken from the board.h of the device being compiled. +/// +/// Important: the LCD driver must have been initialized prior to calling this +/// function. +/// \param pLcdBuffer LCD buffer to use for displaying the calibration info. +//------------------------------------------------------------------------------ +void TSD_Initialize(void *pLcdBuffer) +{ + const Pin pins[] = {PINS_TSADCC}; + + // Configuration + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TSADC; + PIO_Configure(pins, PIO_LISTSIZE(pins)); + TSADCC_SetOperatingMode(AT91C_TSADC_TSAMOD_TS_ONLY_MODE); + TSADCC_SetPenDetect(1); + TSADCC_SetAdcFrequency(BOARD_TOUCHSCREEN_ADCCLK, BOARD_MCK); + TSADCC_SetStartupTime(BOARD_TOUCHSCREEN_STARTUP); + TSADCC_SetTrackAndHoldTime(BOARD_TOUCHSCREEN_SHTIM); + TSADCC_SetDebounceTime(BOARD_TOUCHSCREEN_DEBOUNCE); + + // Do calibration if the LCd buffer is not a null pointer + if(pLcdBuffer) { + // Calibration + while (!TSD_Calibrate(pLcdBuffer)); + } +} + +//------------------------------------------------------------------------------ +/// Reset/stop the touchscreen +//------------------------------------------------------------------------------ +void TSD_Reset(void) +{ + IRQ_DisableIT(AT91C_ID_TSADC); + AT91C_BASE_PMC->PMC_PCDR = 1 << AT91C_ID_TSADC; +} + +#endif //#ifdef AT91C_BASE_TSADC diff --git a/drivers/twi/twid.c b/drivers/twi/twid.c new file mode 100644 index 0000000..d08d96a --- /dev/null +++ b/drivers/twi/twid.c @@ -0,0 +1,344 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + + +#define TWITIMEOUTMAX 50000 + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "twid.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Local types +//------------------------------------------------------------------------------ + +/// TWI driver callback function. +typedef void (*TwiCallback)(Async *); + +//------------------------------------------------------------------------------ +/// TWI asynchronous transfer descriptor. +//------------------------------------------------------------------------------ +typedef struct _AsyncTwi { + + /// Asynchronous transfer status. + volatile unsigned char status; + // Callback function to invoke when transfer completes or fails. + TwiCallback callback; + /// Pointer to the data buffer. + unsigned char *pData; + /// Total number of bytes to transfer. + unsigned int num; + /// Number of already transferred bytes. + unsigned int transferred; + +} AsyncTwi; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes a TWI driver instance, using the given TWI peripheral. 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, AT91S_TWI *pTwi) +{ + TRACE_DEBUG("TWID_Initialize()\n\r"); + SANITY_CHECK(pTwid); + SANITY_CHECK(pTwi); + + // Initialize driver + pTwid->pTwi = pTwi; + pTwid->pTransfer = 0; +} + +//------------------------------------------------------------------------------ +/// 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) +{ + unsigned char status; + AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; + AT91S_TWI *pTwi = pTwid->pTwi; + + SANITY_CHECK(pTwid); + + // Retrieve interrupt status + status = TWI_GetMaskedStatus(pTwi); + + // Byte received + if (TWI_STATUS_RXRDY(status)) { + + pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi); + pTransfer->transferred++; + + // Transfer finished ? + if (pTransfer->transferred == pTransfer->num) { + + TWI_DisableIt(pTwi, AT91C_TWI_RXRDY); + TWI_EnableIt(pTwi, AT91C_TWI_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, AT91C_TWI_TXRDY); + TWI_EnableIt(pTwi, AT91C_TWI_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, AT91C_TWI_TXCOMP); + pTransfer->status = 0; + if (pTransfer->callback) { + + pTransfer->callback((Async *) pTransfer); + } + pTwid->pTransfer = 0; + } +} + +//----------------------------------------------------------------------------- +/// Asynchronously reads data from a slave on the TWI bus. An optional +/// callback function is triggered when the transfer is complete. +/// Returns 0 if the transfer has been started; otherwise returns a TWI error +/// code. +/// \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. +//----------------------------------------------------------------------------- +unsigned char TWID_Read( + Twid *pTwid, + unsigned char address, + unsigned int iaddress, + unsigned char isize, + unsigned char *pData, + unsigned int num, + Async *pAsync) +{ + AT91S_TWI *pTwi = pTwid->pTwi; + AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; + unsigned int timeout; + + //TRACE_DEBUG("TWID_Read()\n\r"); + SANITY_CHECK(pTwid); + SANITY_CHECK((address & 0x80) == 0); + SANITY_CHECK((iaddress & 0xFF000000) == 0); + SANITY_CHECK(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, AT91C_TWI_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) && (++timeoutpTwi; + AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; + unsigned int timeout; + + //TRACE_DEBUG("TWID_Write()\n\r"); + //TRACE_DEBUG("0x%X\n\r", pData[0]); + SANITY_CHECK(pTwi); + SANITY_CHECK((address & 0x80) == 0); + SANITY_CHECK((iaddress & 0xFF000000) == 0); + SANITY_CHECK(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, AT91C_TWI_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 +#include + +//------------------------------------------------------------------------------ +// Global definitions +//------------------------------------------------------------------------------ + +/// TWI driver is currently busy. +#define TWID_ERROR_BUSY 1 +/// TWI driver operation timeout. +#define TWID_ERROR_TIMEOUT 2 + +//------------------------------------------------------------------------------ +// Global types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// TWI driver structure. Holds the internal state of the driver. +//------------------------------------------------------------------------------ +typedef struct _Twid { + + /// Pointer to the underlying TWI peripheral. + AT91S_TWI *pTwi; + /// Current asynchronous transfer being processed. + Async *pTransfer; + +} Twid; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void TWID_Initialize(Twid *pTwid, AT91S_TWI *pTwi); + +extern void TWID_Handler(Twid *pTwid); + +extern unsigned char TWID_Read( + Twid *pTwid, + unsigned char address, + unsigned int iaddress, + unsigned char isize, + unsigned char *pData, + unsigned int num, + Async *pAsync); + +extern unsigned char TWID_Write( + Twid *pTwid, + unsigned char address, + unsigned int iaddress, + unsigned char isize, + unsigned char *pData, + unsigned int num, + Async *pAsync); + +#endif //#ifndef TWID_H + -- cgit v1.2.3