1 //==========================================================================
5 // Cirrus Logic EDB7xxx eval board LCD touch panel support code
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
46 // Description: Tool used to support the LCD touch panel
47 //####DESCRIPTIONEND####
49 static char lcd_panel_server_stack[STACK_SIZE];
50 static cyg_thread lcd_panel_server_thread_data;
51 static cyg_handle_t lcd_panel_server_thread_handle;
53 static cyg_interrupt lcd_panel_interrupt;
54 static cyg_handle_t lcd_panel_interrupt_handle;
56 static cyg_mbox lcd_panel_events_mbox;
57 static cyg_handle_t lcd_panel_events_mbox_handle;
58 static cyg_sem_t lcd_panel_sem;
60 #define SYNCIO_TXFRMEN (1<<14)
61 #define SYNCIO_FRAMELEN(n) (n<<8)
62 #define ADC_START (1<<7)
63 #define ADC_CHAN(n) (n<<4)
64 #define ADC_UNIPOLAR (1<<3)
65 #define ADC_SINGLE (1<<2)
66 #define ADC_EXT_CLOCK (3<<0)
67 #define TOUCH_CTL KBD_PORT
75 *(volatile cyg_uint32 *)SYNCIO = SYNCIO_TXFRMEN | SYNCIO_FRAMELEN(24) |
76 ADC_START | ADC_CHAN(chan) | ADC_UNIPOLAR | ADC_SINGLE | ADC_EXT_CLOCK;
77 while (*(volatile cyg_uint32 *)SYSFLG1 & SYSFLG1_SSIBUSY) ;
78 val = *(volatile cyg_uint32 *)SYNCIO;
79 return (val & 0xFFFF);
86 for (i = 0; i < 800; i++) ;
89 // This ISR is called when the touch panel interrupt occurs
91 lcd_panel_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
93 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_EINT2);
94 return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
97 // This DSR starts up the touch panel [logical] processing
99 lcd_panel_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
101 // Tell the panel processing thread to give it a shot
102 cyg_semaphore_post(&lcd_panel_sem);
105 // Assumption: if the keypress vanishes for 5*20 ms, it probably isn't there
106 #define LCD_PANEL_TIMEOUT 5
108 static __inline__ int
111 if (x < 0) return -x;
116 lcd_panel_server(cyg_addrword_t p)
118 int iX, iY, newX, newY, diffX, diffY, timeout, samples;
120 diag_printf("LCD panel server here\n");
122 cyg_semaphore_wait(&lcd_panel_sem);
123 samples = 0; iX = 0; iY = 0;
124 // Wait for press to go away (no drag support)
126 while (timeout < LCD_PANEL_TIMEOUT) {
127 *(volatile cyg_uint8 *)TOUCH_CTL = 0x00; // Disable drives
128 while (*(volatile cyg_uint32 *)INTSR1 & INTSR1_EINT2) ;
129 *(volatile cyg_uint8 *)TOUCH_CTL = 0x70; // Idle state (so interrupt works)
130 cyg_thread_delay(2); // Wait 20 ms
131 if (*(volatile cyg_uint32 *)INTSR1 & INTSR1_EINT2) {
133 // Drive TSPY, ground TSMY, and disconnect TSPX and TSMX
134 *(volatile cyg_uint8 *)TOUCH_CTL = 0x50;
136 newY = adc_sample(2);
137 // Drive TSPX, ground TSMX, and disconnect TSPY and TSMY
138 *(volatile cyg_uint8 *)TOUCH_CTL = 0xA0;
140 newX = adc_sample(7);
142 diag_printf("timeout: %d, ISR: %x, newX: %d, newY: %d\n",
143 timeout, *(volatile cyg_uint32 *)INTSR1, newX, newY);
145 // See if this sample makes any sense
147 diffX = abs(iX/samples - newX);
148 diffY = abs(iY/samples - newY);
149 if ((diffX <= ((iX/samples)/4)) &&
150 (diffY <= ((iY/samples)/4))) {
156 diag_printf("Discard - newX: %d, X: %d, newY: %d, Y: %d\n",
157 newX, iX/samples, newY, iY/samples);
172 // Send event to user level
173 event = (iX/samples)<<16 | (iY/samples);
174 if (!cyg_mbox_tryput(lcd_panel_events_mbox_handle, (void *)event)) {
175 diag_printf("LCD event lost: %x\n", event);
178 *(volatile cyg_uint8 *)TOUCH_CTL = 0x00; // Disable drives
179 while (*(volatile cyg_uint32 *)INTSR1 & INTSR1_EINT2) ;
180 *(volatile cyg_uint8 *)TOUCH_CTL = 0x70; // Idle state (so interrupt works)
181 cyg_thread_delay(10);
182 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT2);
189 // Enable touch panel
190 *(volatile cyg_uint8 *)PEDR |= 0x04;
192 // Idle state (so interrupt works)
193 *(volatile cyg_uint8 *)TOUCH_CTL = 0x70;
195 // Enable ADC machinery
196 *(volatile cyg_uint32 *)SYSCON1 |= SYSCON1_ADC_CLOCK_128kHZ;
198 cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_EINT2,
199 99, // Priority - what goes here?
200 0, // Data item passed to interrupt handler
203 &lcd_panel_interrupt_handle,
204 &lcd_panel_interrupt);
205 cyg_drv_interrupt_attach(lcd_panel_interrupt_handle);
206 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EINT2);
207 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT2);
208 // Set up the mbox for panel data
209 cyg_mbox_create(&lcd_panel_events_mbox_handle, &lcd_panel_events_mbox);
210 // This semaphore is set when there is a touch
211 cyg_semaphore_init(&lcd_panel_sem, 0);
212 // Create a thread whose job it is to de-bounce the keyboard and
213 // actually process the input, turning it into a series of events
214 cyg_thread_create(10, // Priority - just a number
215 lcd_panel_server, // entry
216 0, // initial parameter
217 "LCD_PANEL_server", // Name
218 &lcd_panel_server_stack[0], // Stack
220 &lcd_panel_server_thread_handle, // Handle
221 &lcd_panel_server_thread_data // Thread data structure
223 cyg_thread_resume(lcd_panel_server_thread_handle); // Start it