523 lines
12 KiB
C
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
|
|
|
|
|