webradio/buttons.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
00003  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00060 #include <cfg/os.h>
00061 #include <cfg/clock.h>
00062 #include <arch/arm.h>
00063 #include <dev/irqreg.h>
00064 
00065 #include <sys/event.h>
00066 #include <sys/timer.h>
00067 
00068 #include "buttons.h"
00069 
00106 #if defined(AT91SAM7X_EK)   /* Board */
00107 /* Calypso board configuration. */
00108 #define BTN_TC_ID       TC1_ID
00109 #define BTN_PIO_ID      PIOB_ID
00110 #define BTN_DOWN_BIT    27
00111 //#define BTN_SELECT_BIT    28 //Doesn't work. Reason currently unknown.
00112 #define BTN_UP_BIT      29
00113 
00114 #elif defined(AT91SAM9260_EK)
00115 /* Calypso board configuration. */
00116 #define BTN_TC_ID       TC1_ID
00117 #define BTN_PIO_ID      PIOB_ID
00118 #define BTN_DOWN_BIT    8
00119 #define BTN_SELECT_BIT  9
00120 #define BTN_UP_BIT      10
00121 
00122 #elif defined(ELEKTOR_IR1)
00123 /* EIR1 configuration. */
00124 #define BTN_TC_ID       TC1_ID
00125 #define BTN_PIO_ID      PIOB_ID
00126 #define BTN_DOWN_BIT    24
00127 #define BTN_SELECT_BIT  25
00128 #define BTN_UP_BIT      26
00129 #endif   /* Board */
00130 
00131 #ifndef BTN_SCAN_FREQ
00132 
00135 #define BTN_SCAN_FREQ       128UL
00136 #endif
00137 
00138 #ifndef BTN_REPEAT_FIRST
00139 
00142 #define BTN_REPEAT_FIRST    100
00143 #endif
00144 
00145 #ifndef BTN_REPEAT_NEXT
00146 
00149 #define BTN_REPEAT_NEXT     25
00150 #endif
00151 
00173 #if BTN_PIO_ID == PIOB_ID
00174 #define BTN_PIO_PE_REG  PIOB_PER
00175 #define BTN_PIO_OD_REG  PIOB_ODR
00176 #define BTN_PIO_PDS_REG PIOB_PDSR
00177 #define BTN_PIO_PUE_REG PIOB_PUER
00178 #elif BTN_PIO_ID == PIOA_ID
00179 #define BTN_PIO_PE_REG  PIOA_PER
00180 #define BTN_PIO_OD_REG  PIOA_ODR
00181 #define BTN_PIO_PDS_REG PIOA_PDSR
00182 #define BTN_PIO_PUE_REG PIOA_PUER
00183 #elif BTN_PIO_ID == PIOC_ID
00184 #define BTN_PIO_PE_REG  PIOC_PER
00185 #define BTN_PIO_OD_REG  PIOC_ODR
00186 #define BTN_PIO_PDS_REG PIOC_PDSR
00187 #define BTN_PIO_PUE_REG PIOC_PUER
00188 #else
00189 #define BTN_PIO_PE_REG  PIO_PER
00190 #define BTN_PIO_OD_REG  PIO_ODR
00191 #define BTN_PIO_PDS_REG PIO_PDSR
00192 #define BTN_PIO_PUE_REG PIO_PUER
00193 #endif
00194 
00196 #ifdef BTN_SELECT_BIT
00197 #define BTN_SELECT      _BV(BTN_SELECT_BIT)
00198 #else
00199 #define BTN_SELECT      0
00200 #endif
00201 
00203 #ifdef BTN_UP_BIT
00204 #define BTN_UP          _BV(BTN_UP_BIT)
00205 #else
00206 #define BTN_UP          0
00207 #endif
00208 
00210 #ifdef BTN_DOWN_BIT
00211 #define BTN_DOWN        _BV(BTN_DOWN_BIT)
00212 #else
00213 #define BTN_DOWN        0
00214 #endif
00215 
00253 #if BTN_TC_ID == TC1_ID
00254 #define sig_BTN_TC      sig_TC1
00255 #define BTN_TC_CC_REG   TC1_CCR
00256 #define BTN_TC_CM_REG   TC1_CMR
00257 #define BTN_TC_IE_REG   TC1_IER
00258 #define BTN_TC_ID_REG   TC1_IDR
00259 #define BTN_TC_S_REG    TC1_SR
00260 #define BTN_TC_RC_REG   TC1_RC
00261 #elif BTN_TC_ID == TC2_ID
00262 #define sig_BTN_TC      sig_TC2
00263 #define BTN_TC_CC_REG   TC2_CCR
00264 #define BTN_TC_CM_REG   TC2_CMR
00265 #define BTN_TC_IE_REG   TC2_IER
00266 #define BTN_TC_ID_REG   TC2_IDR
00267 #define BTN_TC_S_REG    TC2_SR
00268 #define BTN_TC_RC_REG   TC2_RC
00269 #endif
00270 
00278 static HANDLE btn_que;
00279 
00286 static volatile u_int btn_pressed;
00287 
00288 #if USE_BUTTONS
00289 
00292 static void ScanTimerInterrupt(void *arg)
00293 {
00294     static u_int btn_prev;
00295     static u_int btn_repeat;
00296     u_int btn_code;
00297 
00298     /* Read the negated GPIO line status. Pressing a button drives the pin low. */
00299     btn_code = ~inr(BTN_PIO_PDS_REG) & (BTN_DOWN | BTN_SELECT | BTN_UP);
00300     if (btn_code) {
00301         /* A button has been or still is pressed. */
00302         if (btn_code != btn_prev) {
00303             /* This is a new button. Immediately post an event. */
00304             btn_pressed = btn_code;
00305             NutEventPostFromIrq(&btn_que);
00306             /* Initialize the repeat rate. */
00307             btn_repeat = BTN_REPEAT_FIRST;
00308         }
00309         else if (btn_repeat == 0) {
00310             /* Button is still pressed and the repeat time elapsed. 
00311                Post a new event. */
00312             NutEventPostFromIrq(&btn_que);
00313             /* Re-initialize the repeat rate. */
00314             btn_repeat = BTN_REPEAT_NEXT;
00315         }
00316         else {
00317             /* Button is still pressed. Wait until repeat time elapses. */
00318             btn_repeat--;
00319         }
00320     }
00321     /* Keep the last code, so we are able to distinguish whether the user
00322        is still pressing the same or selected a new button. */
00323     btn_prev = btn_code;
00324 }
00325 #endif /* USE_BUTTONS */
00326 
00336 void ButtonInit(void)
00337 {
00338 #if USE_BUTTONS
00339     int dummy;
00340 
00341     /* Enable scan timer clock. */
00342     outr(PMC_PCER, _BV(BTN_TC_ID) | _BV(BTN_PIO_ID));
00343     /* Disable the Clock Counter */
00344     outr(BTN_TC_CC_REG, TC_CLKDIS);
00345     /* Disable all interrupts */
00346     outr(BTN_TC_ID_REG, 0xFFFFFFFF);
00347     /* Clear the status register. */
00348     dummy = inr(BTN_TC_S_REG);
00349     /* Select divider and compare trigger */
00350     outr(BTN_TC_CM_REG, TC_CLKS_MCK32 | TC_CPCTRG);
00351     /* Enable the Clock counter */
00352     outr(BTN_TC_CC_REG, TC_CLKEN);
00353     /* Validate the RC compare interrupt */
00354     outr(BTN_TC_IE_REG, TC_CPCS);
00355 
00356     /* Register timer interrupt handler. */
00357     NutRegisterIrqHandler(&sig_BTN_TC, ScanTimerInterrupt, 0);
00358     /* Set to lowest priority. */
00359     NutIrqSetPriority(&sig_BTN_TC, 0);
00360 
00361     /* Enable timer interrupts */
00362     NutIrqEnable(&sig_BTN_TC);
00363 
00364     /* Set compare value for specified scan frequency. */
00365 #if defined(AT91_PLL_MAINCK)
00366     outr(BTN_TC_RC_REG, At91GetMasterClock() / (32 * BTN_SCAN_FREQ));
00367 #else
00368     outr(BTN_TC_RC_REG, NutGetCpuClock() / (32 * BTN_SCAN_FREQ));
00369 #endif
00370 
00371     /* Initialize GPIO lines for buttons. */
00372     outr(BTN_PIO_PE_REG, BTN_SELECT | BTN_UP | BTN_DOWN);
00373     outr(BTN_PIO_OD_REG, BTN_SELECT | BTN_UP | BTN_DOWN);
00374     outr(BTN_PIO_PUE_REG, BTN_SELECT | BTN_UP | BTN_DOWN);
00375 
00376     /* Software trigger starts the scan timer. */
00377     outr(BTN_TC_CC_REG, TC_SWTRG);
00378 #endif
00379 }
00380 
00394 char ButtonRead(u_long tmo)
00395 {
00396     /* Wait for a button event from the interrupt handler. */
00397     if (NutEventWait(&btn_que, tmo) == 0) {
00398         /* Copy the volatile value to a local variable. */
00399         u_int pressed = btn_pressed;
00400 
00401         if (pressed & BTN_SELECT) {
00402             return KEYCODE_SELECT;
00403         }
00404         if (pressed & BTN_DOWN) {
00405             return KEYCODE_DOWN;
00406         }
00407         if (pressed & BTN_UP) {
00408             return KEYCODE_UP;
00409         }
00410     }
00411     return 0;
00412 }

© 2008 by egnite GmbH - visit www.ethernut.de