2025-02-15 11:05:28 -05:00

523 lines
12 KiB
C

/**
*
* \file
*
* \brief This module contains SAMD21 BSP APIs implementation.
*
* Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include "bsp/include/nm_bsp_samd21_app.h"
#include "common/include/nm_common.h"
#define BSP_MIN(x,y) ((x)>(y)?(y):(x))
#define SW1_PIN
#define SW1_MUX
#define SW1_LINE
#ifdef WING_BOARD_WITH_LEDS_BUTTON
#define SW2_LINE 3
#define SW2_PIN PIN_PB03
#define SW2_MUX MUX_PB03A_EIC_EXTINT3
#endif /* WING_BOARD_WITH_LEDS_BUTTON */
/*
---------------------------------
------ Module Pin Settings ------
---------------------------------
*/
#define LONG_PRESS_TIME (1500/TICK_RES) // ~2 sec
#define DEBOUNCE_TIME (40/TICK_RES) // ~50ms
/*
* Structure
*
*/
typedef struct
{
tpfNmBspTimerCb pfCb;
uint32 u32Timeout;
uint32 u32Period;
} tstrTimer;
typedef struct
{
tstrTimer strTimer;
uint8 u8Enabled;
} tstrWakeTimer;
/**
*
* Global variables
*/
uint32 gu32Jiffies1ms;
uint32 gu32Jiffies20ms;
static uint16 gu16Btn1Cnt, gu16Btn2Cnt;
static tpfNmBspBtnPress gpfBtns;
static uint8 gu8BtnIfg;
static tstrTimer gstrTimer20ms, gstrTimer1ms, gstrConfigurableTimer;
#if (defined _STATIC_PS_)||(defined _DYNAMIC_PS_)
static tstrWakeTimer gstrWakeTimer;
#endif
struct tcc_module tcc_instance;
struct tcc_module configurable_tcc;
/**
*
* Static functions
*/
static void btn_poll(void)
{
bool btn_inactive;
if (gu8BtnIfg & SW1) {
if (gu16Btn1Cnt <= LONG_PRESS_TIME) {
gu16Btn1Cnt++;
}
if (gu16Btn1Cnt == LONG_PRESS_TIME) {
gpfBtns(SW1, 1); /* long press callback */
}
btn_inactive = (port_pin_get_input_level(BUTTON_0_PIN) == BUTTON_0_INACTIVE);
if ((gu16Btn1Cnt >= DEBOUNCE_TIME) && (gu16Btn1Cnt < LONG_PRESS_TIME)
&& btn_inactive) {
gpfBtns(SW1, 0); /* Short press callback */
}
if (btn_inactive)
{
gu8BtnIfg &= ~SW1;
gu16Btn1Cnt = 0;
extint_chan_enable_callback(BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT);
}
}
#ifdef WING_BOARD_WITH_LEDS_BUTTON
if (gu8BtnIfg & SW2) {
if (gu16Btn2Cnt <= LONG_PRESS_TIME) {
gu16Btn2Cnt++;
}
if (gu16Btn2Cnt == LONG_PRESS_TIME) {
gpfBtns(SW2, 1); /* long press callback */
}
btn_inactive = (port_pin_get_input_level(SW2_PIN) == BUTTON_0_INACTIVE);
if ((gu16Btn2Cnt >= DEBOUNCE_TIME) && (gu16Btn2Cnt < LONG_PRESS_TIME)
&& btn_inactive) {
gpfBtns(SW2, 0); /* Short press callback */
}
if (btn_inactive)
{
gu8BtnIfg &= ~SW2;
gu16Btn2Cnt = 0;
extint_chan_enable_callback(SW2_LINE, EXTINT_CALLBACK_TYPE_DETECT);
}
}
#endif /* WING_BOARD_WITH_LEDS_BUTTON */
}
static void _tcc_callback_to_change_duty_cycle(struct tcc_module *const module_inst)
{
gu32Jiffies1ms++;
if(gstrTimer1ms.pfCb)
gstrTimer1ms.pfCb();
if(gu32Jiffies1ms%20 == 0)
{
#ifdef _STATIC_PS_
if((gstrWakeTimer.strTimer.pfCb)&&(gstrWakeTimer.u8Enabled))
{
gu32Jiffies20ms+=(TICK_RES_SLEEP/TICK_RES);
}
else
#endif
{
gu32Jiffies20ms++;
}
#ifdef _STATIC_PS_
if(gstrWakeTimer.strTimer.pfCb)
{
if(NM_BSP_TIME_MSEC >= gstrWakeTimer.strTimer.u32Timeout)
{
nm_bsp_wake_ctrl(0);
gstrWakeTimer.strTimer.pfCb();
gstrWakeTimer.strTimer.u32Timeout = NM_BSP_TIME_MSEC + gstrWakeTimer.strTimer.u32Period;
}
}
#endif
if(gstrTimer20ms.pfCb)
{
if(NM_BSP_TIME_MSEC >= gstrTimer20ms.u32Timeout)
{
gstrTimer20ms.pfCb();
gstrTimer20ms.u32Timeout = NM_BSP_TIME_MSEC + gstrTimer20ms.u32Period;
}
}
btn_poll();
}
}
/*
* @fn _tcc_configurable_timer_callback
* @brief Configurable Timer Callback
* @date 08 October 2015
* @version 1.0
*/
static void _tcc_configurable_timer_callback(struct tcc_module *const module_inst)
{
if(gstrConfigurableTimer.pfCb)
gstrConfigurableTimer.pfCb();
}
static void timer0_init(void)
{
struct tcc_config config_tcc;
tcc_get_config_defaults(&config_tcc, TCC0);
//! [setup_change_config]
config_tcc.counter.period = 750;
config_tcc.counter.reload_action = TCC_RELOAD_ACTION_GCLK;
config_tcc.counter.clock_prescaler = TCC_CLOCK_PRESCALER_DIV64;
tcc_init(&tcc_instance, TCC0, &config_tcc);
tcc_enable(&tcc_instance);
//! [setup_register_callback]
tcc_register_callback(
&tcc_instance,
_tcc_callback_to_change_duty_cycle,
TCC_CALLBACK_CHANNEL_0);
tcc_enable_callback(&tcc_instance,
TCC_CALLBACK_CHANNEL_0);
}
/*
* @fn configurable_timer_init
* @brief Initialize the Configurable Timer
* @date 08 October 2015
* @version 1.0
*/
static void configurable_timer_init(uint32_t u32Period)
{
struct tcc_config config_tcc;
tcc_get_config_defaults(&config_tcc, TCC1);
M2M_DBG("Timer period: %lu\r\n", u32Period);
//! [setup_change_config]
config_tcc.counter.period = u32Period;
tcc_init(&configurable_tcc, TCC1, &config_tcc);
tcc_enable(&configurable_tcc);
//! [setup_register_callback]
tcc_register_callback(
&configurable_tcc,
_tcc_configurable_timer_callback,
TCC_CALLBACK_OVERFLOW);
}
static void btn_isr(void)
{
gu8BtnIfg |= SW1;
extint_chan_disable_callback(BUTTON_0_EIC_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
}
#ifdef WING_BOARD_WITH_LEDS_BUTTON
static void btn2_isr(void)
{
gu8BtnIfg |= SW2;
extint_chan_disable_callback(SW2_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
}
#endif /* WING_BOARD_WITH_LEDS_BUTTON */
/*
* @fn nm_bsp_init
* @brief Initialize BSP
* @return 0 in case of success and -1 in case of failure
* @author M.S.M
* @date 11 July 2012
* @version 1.0
*/
sint8 nm_bsp_app_init(void)
{
gstrTimer20ms.pfCb = NULL;
gstrTimer20ms.u32Timeout = 0;
gstrTimer20ms.u32Period = 0;
#ifdef _STATIC_PS_
gstrWakeTimer.strTimer.pfCb = NULL;
gstrWakeTimer.strTimer.u32Timeout = 0;
gstrWakeTimer.strTimer.u32Period = ((uint32)-1);
gstrWakeTimer.u8Enabled = 0;
#endif
gstrTimer1ms.pfCb = NULL;
gstrTimer1ms.u32Timeout = 0;
gstrTimer1ms.u32Period = 0;
gstrConfigurableTimer.pfCb = NULL;
gstrConfigurableTimer.u32Timeout = 0;
gstrConfigurableTimer.u32Period = 0;
timer0_init();
return M2M_SUCCESS;
}
/*
* @fn nm_bsp_app_configurable_timer_init
* @brief Initialize the Configurable Timer
* @date 08 October 2015
* @version 1.0
*/
void nm_bsp_app_configurable_timer_init(uint32_t u32Period)
{
configurable_timer_init(u32Period);
}
/**
* @fn nm_bsp_deinit
* @brief De-iInitialize BSP
* @return 0 in case of success and -1 in case of failure
* @author M. Abdelmawla
* @date 11 July 2012
* @version 1.0
*/
sint8 nm_bsp_app_deinit(void)
{
return M2M_SUCCESS;
}
/*
* @fn nm_bsp_btn_init
* @brief Initialize buttons driver
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_btn_init(tpfNmBspBtnPress pfBtnCb)
{
//struct port_config pin_conf;
struct extint_chan_conf config_extint_chan;
gpfBtns = pfBtnCb;
gu8BtnIfg = 0;
gu16Btn1Cnt = 0;
gu16Btn2Cnt = 0;
#ifdef WING_BOARD_WITH_LEDS_BUTTON
port_get_config_defaults(&pin_conf);
/* Set buttons as inputs */
pin_conf.direction = PORT_PIN_DIR_INPUT;
pin_conf.input_pull = PORT_PIN_PULL_UP;
port_pin_set_config(SW2_PIN, &pin_conf);
/*Configure SW1*/
extint_chan_get_config_defaults(&config_extint_chan);
config_extint_chan.gpio_pin = SW2_PIN;
config_extint_chan.gpio_pin_mux = SW2_MUX;
config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP;
config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING;
extint_chan_set_config(SW2_LINE, &config_extint_chan);
extint_register_callback(btn2_isr,
SW2_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
extint_chan_enable_callback(SW2_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
#endif /* WING_BOARD_WITH_LEDS_BUTTON */
/*Configure SW2*/
extint_chan_get_config_defaults(&config_extint_chan);
config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN;
config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX;
config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP;
config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING;
extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan);
extint_register_callback(btn_isr,
BUTTON_0_EIC_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
extint_chan_enable_callback(BUTTON_0_EIC_LINE,
EXTINT_CALLBACK_TYPE_DETECT);
}
/*
* @fn nm_bsp_uart_sendnm_bsp_uart_send
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_uart_send(const uint8 *pu8Buf, uint16 u16Sz)
{
}
/**
* @fn nm_bsp_start_timer
* @brief Start 20ms timer
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_start_timer(tpfNmBspTimerCb pfCb, uint32 u32Period)
{
gstrTimer20ms.pfCb = pfCb;
gstrTimer20ms.u32Timeout = u32Period+ NM_BSP_TIME_MSEC;
gstrTimer20ms.u32Period = u32Period;
}
/*
* @fn nm_bsp_start_1ms_timer
* @brief Start 1ms timer
* @date 08 October 2015
* @version 1.0
*/
void nm_bsp_start_1ms_timer(tpfNmBspTimerCb pfCb)
{
gstrTimer1ms.pfCb = pfCb;
}
/*
* @fn nm_bsp_start_configurable_timer
* @brief Start configurable timer
* @date 08 October 2015
* @version 1.0
*/
void nm_bsp_start_configurable_timer(tpfNmBspTimerCb pfCb)
{
tcc_enable_callback(&configurable_tcc, TCC_CALLBACK_OVERFLOW);
gstrConfigurableTimer.pfCb = pfCb;
}
/**
* @fn nm_bsp_stop_timer
* @brief Start 20ms timer
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_stop_timer(void)
{
gstrTimer20ms.pfCb = NULL;
}
/*
* @fn nm_bsp_stop_1ms_timer
* @brief Stop 1ms timer
* @date 08 October 2015
* @version 1.0
*/
void nm_bsp_stop_1ms_timer(void)
{
gstrTimer1ms.pfCb = NULL;
}
/*
* @fn nm_bsp_stop_configurable_timer
* @brief Stop configurable timer
* @date 08 October 2015
* @version 1.0
*/
void nm_bsp_stop_configurable_timer(void)
{
gstrConfigurableTimer.pfCb = NULL;
tcc_disable_callback(&configurable_tcc, TCC_CALLBACK_OVERFLOW);
tcc_disable(&configurable_tcc);
}
#ifdef _STATIC_PS_
/**
* @fn nm_bsp_register_wake_isr
* @brief REGISTER wake up timer
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_register_wake_isr(tpfNmBspIsr pfIsr,uint32 u32MsPeriod)
{
gstrWakeTimer.strTimer.pfCb = pfIsr;
gstrWakeTimer.strTimer.u32Timeout = u32MsPeriod + NM_BSP_TIME_MSEC;
gstrWakeTimer.strTimer.u32Period = u32MsPeriod;
gstrWakeTimer.u8Enabled = 0;
}
/**
* @fn nm_bsp_wake_ctrl
* @brief control wake up timer
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_wake_ctrl(uint8 en)
{
gstrWakeTimer.u8Enabled = en;
if(en)
{
gstrWakeTimer.strTimer.u32Timeout = gstrWakeTimer.strTimer.u32Period + NM_BSP_TIME_MSEC;
}
}
#endif
#if (defined _STATIC_PS_)||(defined _DYNAMIC_PS_)
/**
* @fn nm_bsp_enable_mcu_ps
* @brief Start POWER SAVE FOR MCU
* @author M.S.M
* @date 28 OCT 2013
* @version 1.0
*/
void nm_bsp_enable_mcu_ps(void)
{
if(!gu8BtnIfg)
{
if(gstrWakeTimer.u8Enabled)
{
}
}
}
#endif