nes-proj/arch/platform/simplelink/cc13xx-cc26xx/launchpad/button-sensor-arch.c

222 lines
7.4 KiB
C

/*
* Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* 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 of the copyright holder 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 HOLDER 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.
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup launchpad-button-sensor
* @{
*
* \file
* Driver for LaunchPad buttons
*/
/*---------------------------------------------------------------------------*/
#include <contiki.h>
#include <sys/timer.h>
#include <lib/sensors.h>
/*---------------------------------------------------------------------------*/
#include <Board.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/Power.h>
/*---------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#include "button-sensor.h"
/*---------------------------------------------------------------------------*/
/* LaunchPad has 2 buttons: BTN1 and BTN2 */
/* Map the GPIO defines from the Board file */
#define BTN1_PIN Board_PIN_BTN1
#define BTN2_PIN Board_PIN_BTN2
/*---------------------------------------------------------------------------*/
#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
# define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
#else
# define BUTTON_SENSOR_ENABLE_SHUTDOWN 0
#endif
/*---------------------------------------------------------------------------*/
#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5)
/*---------------------------------------------------------------------------*/
typedef struct {
struct timer debounce;
clock_time_t start;
clock_time_t duration;
} BtnTimer;
/*---------------------------------------------------------------------------*/
static BtnTimer btn1_timer;
static BtnTimer btn2_timer;
/*---------------------------------------------------------------------------*/
static const PIN_Config btn_pin_table[] = {
BTN1_PIN | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
BTN2_PIN | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
PIN_TERMINATE
};
static PIN_State pin_state;
static PIN_Handle pin_handle;
/*---------------------------------------------------------------------------*/
static void
button_press_cb(PIN_Handle handle, PIN_Id pin_id)
{
#if BUTTON_SENSOR_ENABLE_SHUTDOWN
if (pin_id == BTN2_PIN) {
Power_shutdown(Power_ENTERING_SHUTDOWN, 0);
return;
}
#endif
BtnTimer *btn_timer = NULL;
const struct sensors_sensor *btn_sensor = NULL;
switch (pin_id) {
case BTN1_PIN: btn_timer = &btn1_timer;
btn_sensor = &button_left_sensor; break;
case BTN2_PIN: btn_timer = &btn2_timer;
btn_sensor = &button_right_sensor; break;
default: return; /* No matching PIN */
}
if (!timer_expired(&btn_timer->debounce)) {
return;
}
timer_set(&btn_timer->debounce, DEBOUNCE_DURATION);
// Start press duration counter on press (falling), notify on release (rising)
if (PIN_getInputValue(pin_id) == 0) {
btn_timer->start = clock_time();
btn_timer->duration = 0;
} else {
btn_timer->duration = clock_time() - btn_timer->start;
sensors_changed(btn_sensor);
}
}
/*---------------------------------------------------------------------------*/
static int
button_value(int type, uint8_t pin, BtnTimer *btn_timer)
{
switch (type) {
case BUTTON_SENSOR_TYPE_STATE:
return (PIN_getInputValue(pin) == 0)
? BUTTON_SENSOR_VALUE_PRESSED
: BUTTON_SENSOR_VALUE_RELEASED;
case BUTTON_SENSOR_TYPE_DURATION:
return (int)btn_timer->duration;
default:
return 0;
}
}
/*---------------------------------------------------------------------------*/
static int
button_config(int type, int value, uint8_t pin)
{
switch (type) {
case SENSORS_HW_INIT:
// Open PIN handle
if (pin_handle) {
return 1;
}
pin_handle = PIN_open(&pin_state, btn_pin_table);
if (!pin_handle) {
return 0;
}
// Register button callback function
PIN_registerIntCb(pin_handle, button_press_cb);
break;
case SENSORS_ACTIVE:
if (value) {
// Enable interrupts on both edges
PIN_setInterrupt(pin_handle, pin | PIN_IRQ_BOTHEDGES);
} else {
// Disable pin interrupts
PIN_setInterrupt(pin_handle, pin | PIN_IRQ_DIS);
}
break;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int
button_status(int type, uint8_t pin)
{
switch(type) {
case SENSORS_ACTIVE: /* fallthrough */
case SENSORS_READY: {
PIN_Config pin_cfg = PIN_getConfig(pin);
return (pin_cfg & PIN_BM_IRQ) == PIN_IRQ_DIS;
}
default: break;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int
btn1_value(int type)
{
return button_value(type, BTN1_PIN, &btn1_timer);
}
/*---------------------------------------------------------------------------*/
static int
btn1_config(int type, int value)
{
return button_config(type, value, BTN1_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn1_status(int type)
{
return button_status(type, BTN1_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn2_value(int type)
{
return button_value(type, BTN2_PIN, &btn2_timer);
}
/*---------------------------------------------------------------------------*/
static int
btn2_config(int type, int value)
{
return button_config(type, value, BTN2_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn2_status(int type)
{
return button_status(type, BTN2_PIN);
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, btn1_value, btn1_config, btn1_status);
SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, btn2_value, btn2_config, btn2_status);
/*---------------------------------------------------------------------------*/
/** @} */