/************************************************************************************ * configs/sam3u-ek/src/up_touchscreen.c * * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS 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. * ************************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "up_arch.h" #include "sam_gpio.h" #include "chip/sam3u_pio.h" #include "arduino-due.h" /* In order to use the SD card on the ITEAD shield, you must enable the SPI * bit-bang driver as well as support for SPI-based ADS7843E/XPT2046 * touchscreen controller. */ #if defined(CONFIG_ARDUINO_ITHEAD_TFT) && defined(CONFIG_SPI_BITBANG) && \ defined(CONFIG_INPUT_ADS7843E) /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ /* Configuration ************************************************************/ #ifndef CONFIG_SAM34_GPIOC_IRQ # error "Touchscreen support requires CONFIG_SAM34_GPIOC_IRQ" #endif #ifndef CONFIG_ADS7843E_FREQUENCY # define CONFIG_ADS7843E_FREQUENCY 500000 #endif #ifndef CONFIG_ADS7843E_SPIDEV # define CONFIG_ADS7843E_SPIDEV 0 #endif #ifndef CONFIG_ADS7843E_DEVMINOR # define CONFIG_ADS7843E_DEVMINOR 0 #endif /* Definitions for include/nuttx/spi/spi_bitbang.c. */ #define SPI_SETSCK putreg32(1 << 24, SAM_PIOA_SODR) #define SPI_CLRSCK putreg32(1 << 24, SAM_PIOA_CODR) #define SPI_SETMOSI putreg32(1 << 16, SAM_PIOA_SODR) #define SPI_CLRMOSI putreg32(1 << 16, SAM_PIOA_CODR) #define SPI_GETMISO ((getreg32(SAM_PIOC_PDSR) >> 22) & 1) /* Only mode 0 */ #undef SPI_BITBANG_DISABLEMODE0 #define SPI_BITBANG_DISABLEMODE1 1 #define SPI_BITBANG_DISABLEMODE2 1 #define SPI_BITBANG_DISABLEMODE3 1 /* Only 8-bit data width */ #undef SPI_BITBANG_VARWIDTH /* Calibration value for timing loop */ #define SPI_BITBAND_LOOPSPERMSEC CONFIG_BOARD_LOOPSPERMSEC /* SPI_PERBIT_NSEC is the minimum time to transfer one bit. This determines * the maximum frequency and is also used to calculate delays to achieve * other SPI frequencies. */ #define SPI_PERBIT_NSEC 100 /**************************************************************************** * Private Function Prototypes ****************************************************************************/ /* Lower-half SPI */ static void spi_select(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid, bool selected); static uint8_t spi_status(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid); #ifdef CONFIG_SPI_CMDDATA static int spi_cmddata(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid, bool cmd); #endif /* IRQ/GPIO access callbacks. These operations all hidden behind * callbacks to isolate the XPT2046 driver from differences in GPIO * interrupt handling by varying boards and MCUs. If possible, * interrupts should be configured on both rising and falling edges * so that contact and loss-of-contact events can be detected. * * attach - Attach the XPT2046 interrupt handler to the GPIO interrupt * enable - Enable or disable the GPIO interrupt * clear - Acknowledge/clear any pending GPIO interrupt * pendown - Return the state of the pen down GPIO input */ static int tsc_attach(FAR struct ads7843e_config_s *state, xcpt_t isr); static void tsc_enable(FAR struct ads7843e_config_s *state, bool enable); static void tsc_clear(FAR struct ads7843e_config_s *state); static bool tsc_busy(FAR struct ads7843e_config_s *state); static bool tsc_pendown(FAR struct ads7843e_config_s *state); /**************************************************************************** * Private Data ****************************************************************************/ /* A reference to a structure of this type must be passed to the XPT2046 * driver. This structure provides information about the configuration * of the XPT2046 and provides some board-specific hooks. * * Memory for this structure is provided by the caller. It is not copied * by the driver and is presumed to persist while the driver is active. The * memory must be writable because, under certain circumstances, the driver * may modify frequency or X plate resistance values. */ static struct ads7843e_config_s g_tscinfo = { .frequency = CONFIG_ADS7843E_FREQUENCY, .attach = tsc_attach, .enable = tsc_enable, .clear = tsc_clear, .busy = tsc_busy, .pendown = tsc_pendown, }; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Include the bit-band skeleton logic ****************************************************************************/ #include /**************************************************************************** * Name: spi_select * * Description: * Select or de-selected the SPI device specified by 'devid' * * Input Parameters: * priv - An instance of the bit-bang driver structure * devid - The device to select or de-select * selected - True:select false:de-select * * Returned Value: * None * ****************************************************************************/ static void spi_select(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid, bool selected) { /* The touchscreen controller is always selected */ } /**************************************************************************** * Name: spi_status * * Description: * Return status of the SPI device specified by 'devid' * * Input Parameters: * priv - An instance of the bit-bang driver structure * devid - The device to select or de-select * * Returned Value: * An 8-bit, bit-encoded status byte * ****************************************************************************/ static uint8_t spi_status(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid) { return 0; } /**************************************************************************** * Name: spi_cmddata * * Description: * If there were was a CMD/DATA line, this function would manage it * * Input Parameters: * priv - An instance of the bit-bang driver structure * devid - The device to use * cmd - True=MCD false=DATA * * Returned Value: * OK * ****************************************************************************/ #ifdef CONFIG_SPI_CMDDATA static int spi_cmddata(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid, bool cmd) { return OK; } #endif /**************************************************************************** * IRQ/GPIO access callbacks. These operations all hidden behind * callbacks to isolate the XPT2046 driver from differences in GPIO * interrupt handling by varying boards and MCUs. If possible, * interrupts should be configured on both rising and falling edges * so that contact and loss-of-contact events can be detected. * * attach - Attach the XPT2046 interrupt handler to the GPIO interrupt * enable - Enable or disable the GPIO interrupt * clear - Acknowledge/clear any pending GPIO interrupt * pendown - Return the state of the pen down GPIO input * ****************************************************************************/ static int tsc_attach(FAR struct ads7843e_config_s *state, xcpt_t isr) { /* Attach the XPT2046 interrupt */ ivdbg("Attaching %p to IRQ %d\n", isr, SAM_TSC_IRQ); return irq_attach(SAM_TSC_IRQ, isr); } static void tsc_enable(FAR struct ads7843e_config_s *state, bool enable) { /* Attach and enable, or detach and disable */ ivdbg("IRQ:%d enable:%d\n", SAM_TSC_IRQ, enable); if (enable) { sam_gpioirqenable(SAM_TSC_IRQ); } else { sam_gpioirqdisable(SAM_TSC_IRQ); } } static void tsc_clear(FAR struct ads7843e_config_s *state) { /* Does nothing */ } static bool tsc_busy(FAR struct ads7843e_config_s *state) { return false; /* The BUSY signal is not connected */ } static bool tsc_pendown(FAR struct ads7843e_config_s *state) { /* The /PENIRQ value is active low */ bool pendown = !sam_gpioread(GPIO_TSC_IRQ); ivdbg("pendown:%d\n", pendown); return pendown; } /**************************************************************************** * Name: sam_tsc_spiinitialize * * Description: * Initialize the SPI bit-bang driver * * Input Parameters: * None * * Returned Value: * A non-NULL reference to the SPI driver on success * ****************************************************************************/ static FAR struct spi_dev_s *sam_tsc_spiinitialize(void) { /* Configure the SPI bit-bang pins */ sam_configgpio(GPIO_TSC_SCK); sam_configgpio(GPIO_TSC_MISO); sam_configgpio(GPIO_TSC_MOSI); /* Create the SPI driver instance */ return spi_create_bitbang(&g_spiops); } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: arch_tcinitialize * * Description: * Each board that supports a touchscreen device must provide this function. * This function is called by application-specific, setup logic to * configure the touchscreen device. This function will register the driver * as /dev/inputN where N is the minor device number. * * Input Parameters: * minor - The input device minor number * * Returned Value: * Zero is returned on success. Otherwise, a negated errno value is * returned to indicate the nature of the failure. * ****************************************************************************/ int arch_tcinitialize(int minor) { FAR struct spi_dev_s *dev; static bool initialized = false; int ret; idbg("minor %d\n", minor); DEBUGASSERT(minor == 0); /* Have we already initialized? Since we never uninitialize we must prevent * multiple initializations. This is necessary, for example, when the * touchscreen example is used as a built-in application in NSH and can be * called numerous time. It will attempt to initialize each time. */ if (!initialized) { /* Configure and enable the XPT2046 interrupt pin as an input */ (void)sam_configgpio(GPIO_TSC_IRQ); /* Configure the PIO interrupt */ sam_gpioirq(SAM_TSC_IRQ); /* Get an instance of the SPI interface for the touchscreen chip select */ dev = sam_tsc_spiinitialize(); if (!dev) { idbg("Failed to initialize bit bang SPI\n"); return -ENODEV; } /* Initialize and register the SPI touschscreen device */ ret = ads7843e_register(dev, &g_tscinfo, CONFIG_ADS7843E_DEVMINOR); if (ret < 0) { idbg("Failed to register touchscreen device\n"); /* up_spiuninitialize(dev); */ return -ENODEV; } /* Now we are initialized */ initialized = true; } return OK; } /**************************************************************************** * Name: arch_tcuninitialize * * Description: * Each board that supports a touchscreen device must provide this function. * This function is called by application-specific, setup logic to * uninitialize the touchscreen device. * * Input Parameters: * None * * Returned Value: * None * ****************************************************************************/ void arch_tcuninitialize(void) { /* No support for un-initializing the touchscreen XPT2046 device. It will * continue to run and process touch interrupts in the background. */ } #endif /* CONFIG_ARDUINO_ITHEAD_TFT && CONFIG_SPI_BITBANG && CONFIG_INPUT_ADS7843E */