cc2530-projects/Zigbee无线通信/A板/CC2530_lib/common/hal_digio.c
2021-10-04 22:26:10 +08:00

493 lines
14 KiB
C

//-------------------------------------------------------------------
// Filename: hal_digio.c
// Description: HAL digital IO functionality
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// INCLUDES
//-------------------------------------------------------------------
#include "hal_defs.h"
#include "hal_int.h"
#include "hal_digio.h"
//-------------------------------------------------------------------
// LOCAL VARIABLES
//-------------------------------------------------------------------
static ISR_FUNC_PTR port0_isr_tbl[8] =
{
0
};
static ISR_FUNC_PTR port1_isr_tbl[8] =
{
0
};
static ISR_FUNC_PTR port2_isr_tbl[5] =
{
0
};
// Find a better place for this!
#define PICTL_PADSC_BM 0x80
#define PICTL_P2IEN_BM 0x40
#define PICTL_P0IENH_BM 0x20
#define PICTL_P0IENL_BM 0x10
#define PICTL_P2ICON_BM 0x08
#define PICTL_P1ICONH_BM 0x04
#define PICTL_P1ICONL_BM 0x02
#define PICTL_P1ICON_BM 0x06 // Combined - for compatibility
#define PICTL_P0ICON_BM 0x01
//-------------------------------------------------------------------
// GLOBAL FUNCTIONS
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// @fn halDigioConfig
// @brief Configure the pin as specified by p.
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
//comment: find better way of doing this. SFR registers can not be accessed by pointers, therefore code is different from MSP430 code
// comment: currently support only P0 and P1
uint8 halDigioConfig(const digioConfig *p)
{
// register volatile uint8* dir;
register const uint8 bitmask = p->pin_bm;
// Sanity check
if ((bitmask == 0) || (bitmask != (uint8)BV(p->pin)))
{
return (HAL_DIGIO_ERROR);
}
switch (p->port)
{
case 0:
P0SEL &= ~bitmask;
if (p->dir == HAL_DIGIO_OUTPUT)
{
if (p->initval == 1)
{
P0 |= bitmask;
}
else
{
P0 &= ~bitmask;
}
P0DIR |= bitmask;
}
else
// input
{
P0DIR &= ~bitmask;
}
break;
case 1:
P1SEL &= ~bitmask;
if (p->dir == HAL_DIGIO_OUTPUT)
{
if (p->initval == 1)
{
P1 |= bitmask;
}
else
{
P1 &= ~bitmask;
}
P1DIR |= bitmask;
}
else
// input
{
P1DIR &= ~bitmask;
}
break;
case 2:
P2SEL &= ~bitmask;
if (p->dir == HAL_DIGIO_OUTPUT)
{
if (p->initval == 1)
{
P2 |= bitmask;
}
else
{
P2 &= ~bitmask;
}
P2DIR |= bitmask;
}
else
// input
{
P2DIR &= ~bitmask;
}
break;
//case 1: P1SEL &= ~bitmask; out = &P1OUT; dir = &P1DIR; break;
//case 2: P2SEL &= ~bitmask; out = &P2OUT; dir = &P2DIR; break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn halDigioSet
// @brief Set output pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioSet(const digioConfig *p)
{
if (p->dir == HAL_DIGIO_OUTPUT)
{
switch (p->port)
{
case 0:
P0 |= p->pin_bm;
break;
case 1:
P1 |= p->pin_bm;
break;
case 2:
P2 |= p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
return (HAL_DIGIO_ERROR);
}
//-------------------------------------------------------------------
// @fn halDigioClear
// @brief Clear output pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioClear(const digioConfig *p)
{
if (p->dir == HAL_DIGIO_OUTPUT)
{
switch (p->port)
{
case 0:
P0 &= ~p->pin_bm;
break;
case 1:
P1 &= ~p->pin_bm;
break;
case 2:
P2 &= ~p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
return (HAL_DIGIO_ERROR);
}
//-------------------------------------------------------------------
// @fn halDigioToggle
// @brief Toggle output pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioToggle(const digioConfig *p)
{
if (p->dir == HAL_DIGIO_OUTPUT)
{
switch (p->port)
{
case 0:
P0 ^= p->pin_bm;
break;
case 1:
P1 ^= p->pin_bm;
break;
case 2:
P2 ^= p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
return (HAL_DIGIO_ERROR);
}
//-------------------------------------------------------------------
// @fn halDigioGet
// @brief Get value on input pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioGet(const digioConfig *p)
{
if (p->dir == HAL_DIGIO_INPUT)
{
switch (p->port)
{
case 0:
return (P0 &p->pin_bm ? 1 : 0);
case 1:
return (P1 &p->pin_bm ? 1 : 0);
case 2:
return (P2 &p->pin_bm ? 1 : 0);
default:
break;
}
}
return (HAL_DIGIO_ERROR);
}
//-------------------------------------------------------------------
// @fn halDigioIntConnect
// @brief Connect function to IO interrupt
// @param digioConfig* p - pointer to configuration structure for IO pin
// ISR_FUNC_PTR func - pointer to function
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioIntConnect(const digioConfig *p, ISR_FUNC_PTR func)
{
istate_t key;
HAL_INT_LOCK(key);
switch (p->port)
{
case 0:
port0_isr_tbl[p->pin] = func;
break;
case 1:
port1_isr_tbl[p->pin] = func;
break;
case 2:
port2_isr_tbl[p->pin] = func;
break;
default:
HAL_INT_UNLOCK(key);
return (HAL_DIGIO_ERROR);
}
halDigioIntClear(p);
HAL_INT_UNLOCK(key);
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn halDigioIntEnable
// @brief Enable interrupt on IO pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioIntEnable(const digioConfig *p)
{
switch (p->port)
{
case 0:
P0IE = 1; // set P0IE bit
P0IEN |= p->pin_bm;
break;
case 1:
IEN2 |= 0x10; // set P1IE bit
P1IEN |= p->pin_bm;
break;
case 2:
IEN2 |= 0x02; // set P2IE bit
P2IEN |= p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn halDigioIntDisable
// @brief Disable interrupt on IO pin
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioIntDisable(const digioConfig *p)
{
switch (p->port)
{
case 0:
P0IEN &= ~p->pin_bm;
break;
case 1:
P1IEN &= ~p->pin_bm;
break;
case 2:
P2IEN &= ~p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn halDigioIntClear
// @brief Clear interrupt flag
// @param digioConfig* p - pointer to configuration structure for IO pin
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
uint8 halDigioIntClear(const digioConfig *p)
{
switch (p->port)
{
case 0:
P0IFG &= ~p->pin_bm;
break;
case 1:
P1IFG &= ~p->pin_bm;
break;
case 2:
P2IFG &= ~p->pin_bm;
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn halDigioIntSetEdge
// @brief Set edge for IO interrupt
// @param digioConfig* p - pointer to configuration structure for IO pin
// edge - HAL_DIGIO_INT_FALLING_EDGE or HAL_DIGIO_INT_RISING_EDGE
// @return uint8 - HAL_DIGIO_ERROR or HAL_DIGIO_OK
//-------------------------------------------------------------------
// Comment: all pins on port are configured at same time
uint8 halDigioIntSetEdge(const digioConfig *p, uint8 edge)
{
switch (edge)
{
case HAL_DIGIO_INT_FALLING_EDGE:
switch (p->port)
{
case 0:
PICTL |= PICTL_P0ICON_BM; // set P0ICON high
break;
case 1:
PICTL |= PICTL_P1ICON_BM; // set P1ICON high
break;
case 2:
PICTL |= PICTL_P2ICON_BM; // set P2ICON high
break;
default:
return (HAL_DIGIO_ERROR);
}
break;
case HAL_DIGIO_INT_RISING_EDGE:
switch (p->port)
{
case 0:
PICTL &= ~PICTL_P0ICON_BM; // set P0ICON low
break;
case 1:
PICTL &= ~PICTL_P1ICON_BM; // set P0ICON low
break;
case 2:
PICTL &= ~PICTL_P2ICON_BM; // set P0ICON low
break;
default:
return (HAL_DIGIO_ERROR);
}
break;
default:
return (HAL_DIGIO_ERROR);
}
return (HAL_DIGIO_OK);
}
//-------------------------------------------------------------------
// @fn port0_ISR
// @brief ISR framework for P0 digio interrupt
// @param none
// @return none
//-------------------------------------------------------------------
HAL_ISR_FUNCTION(port0_ISR, P0INT_VECTOR)
{
register uint8 i;
P0IF = 0;
if (P0IFG)
{
for (i = 0; i < 8; i++)
{
register const uint8 pinmask = 1 << i;
if (P0IFG &pinmask)
{
if (port0_isr_tbl[i] != 0)
{
(*port0_isr_tbl[i])();
}
P0IFG &= ~pinmask;
}
}
//__low_power_mode_off_on_exit();
}
}
//-------------------------------------------------------------------
// @fn port1_ISR
// @brief ISR framework for P0 digio interrupt
// @param none
// @return none
//-------------------------------------------------------------------
HAL_ISR_FUNCTION(port1_ISR, P1INT_VECTOR)
{
register uint8 i;
P1IF = 0;
if (P1IFG)
{
for (i = 0; i < 8; i++)
{
register const uint8 pinmask = 1 << i;
if (P1IFG &pinmask)
{
if (port1_isr_tbl[i] != 0)
{
(*port1_isr_tbl[i])();
}
P1IFG &= ~pinmask;
}
}
//__low_power_mode_off_on_exit();
}
}
//-------------------------------------------------------------------
// @fn port2_ISR
// @brief ISR framework for P2 digio interrupt
// @param none
// @return none
//-------------------------------------------------------------------
HAL_ISR_FUNCTION(port2_ISR, P2INT_VECTOR)
{
register uint8 i;
P2IF = 0;
if (P2IFG)
{
for (i = 0; i < 5; i++)
{
register const uint8 pinmask = 1 << i;
if (P2IFG &pinmask)
{
if (port2_isr_tbl[i] != 0)
{
(*port2_isr_tbl[i])();
}
P2IFG &= ~pinmask;
}
}
//__low_power_mode_off_on_exit();
}
}