mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-04-28 07:39:02 -07:00
179 lines
5.9 KiB
C++
179 lines
5.9 KiB
C++
![]() |
/****************************************************************************/
|
||
|
/* PROJECT: All based on ATtinyX5, ATtinyX4, ATmega328P */
|
||
|
/* MODULE: PinChange */
|
||
|
/* VERSION: 1.0 */
|
||
|
/* DATE: 30/01/2011 */
|
||
|
/* TARGET: ATtinyX5, ATtinyX4, ATmega328P */
|
||
|
/* COMPILER: WinAvr (avr-gcc) */
|
||
|
/* IDE: AVR Studio 4 */
|
||
|
/* PROGRAMER: AVR-JTAG-ICE MKII */
|
||
|
/* AUTHOR: P.LOUSSOUARN (P.Loussouarn: http://p.loussouarn.free.fr) */
|
||
|
/****************************************************************************/
|
||
|
#include <TinyPinChange.h>
|
||
|
#include <avr/interrupt.h>
|
||
|
|
||
|
/*************************************************************************
|
||
|
MACROS
|
||
|
*************************************************************************/
|
||
|
|
||
|
#define PIN_CHANGE_HANDLER_MAX_NB 3 /* ISR max number Pin Change ISR can handle */
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
GLOBAL VARIABLES
|
||
|
*************************************************************************/
|
||
|
struct PinChangeStruct
|
||
|
{
|
||
|
void (*Isr[PIN_CHANGE_HANDLER_MAX_NB])(void);
|
||
|
uint8_t LoadedIsrNb;
|
||
|
uint8_t Event;
|
||
|
uint8_t PinPrev;
|
||
|
uint8_t PinCur;
|
||
|
};
|
||
|
|
||
|
struct PinChangePortStruct
|
||
|
{
|
||
|
PinChangeStruct Port[PIN_CHG_PORT_NB];
|
||
|
};
|
||
|
|
||
|
static volatile struct PinChangePortStruct PinChange;
|
||
|
|
||
|
/*************************************************************************
|
||
|
INTERRUPT SUB-ROUTINE
|
||
|
*************************************************************************/
|
||
|
#define DECLARE_PIN_CHANGE_ISR(VirtualPortIdx) \
|
||
|
ISR(PCINT##VirtualPortIdx##_vect) \
|
||
|
{ \
|
||
|
uint8_t Idx; \
|
||
|
PinChange.Port[VirtualPortIdx].PinCur=(PC_PIN##VirtualPortIdx)&(PC_PCMSK##VirtualPortIdx); \
|
||
|
PinChange.Port[VirtualPortIdx].Event=PinChange.Port[VirtualPortIdx].PinPrev^PinChange.Port[VirtualPortIdx].PinCur; \
|
||
|
PinChange.Port[VirtualPortIdx].PinPrev=PinChange.Port[VirtualPortIdx].PinCur; \
|
||
|
for(Idx=0;Idx<PinChange.Port[VirtualPortIdx].LoadedIsrNb;Idx++) \
|
||
|
{ \
|
||
|
PinChange.Port[VirtualPortIdx].Isr[Idx](); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
DECLARE_PIN_CHANGE_ISR(0)
|
||
|
|
||
|
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
|
||
|
DECLARE_PIN_CHANGE_ISR(1)
|
||
|
#endif
|
||
|
|
||
|
#if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__)
|
||
|
DECLARE_PIN_CHANGE_ISR(2)
|
||
|
#endif
|
||
|
|
||
|
/*************************************************************************
|
||
|
PUBLIC FUNCTIONS
|
||
|
*************************************************************************/
|
||
|
|
||
|
/*********************************************************************
|
||
|
PinChange Initialization Function
|
||
|
Input:
|
||
|
Void
|
||
|
Output:
|
||
|
Void
|
||
|
*********************************************************************/
|
||
|
void TinyPinChange_Init(void)
|
||
|
{
|
||
|
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||
|
/* ATtinyX5 */
|
||
|
PinChange.Port[0].PinCur=PC_PIN0&PC_PCMSK0; //PINB,
|
||
|
PinChange.Port[0].PinPrev=PinChange.Port[0].PinCur;
|
||
|
#else
|
||
|
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||
|
/* ATtinyX4 */
|
||
|
PinChange.Port[0].PinCur=PC_PIN0&PC_PCMSK0;//PINA;
|
||
|
PinChange.Port[0].PinPrev=PinChange.Port[0].PinCur;
|
||
|
PinChange.Port[1].PinCur=PC_PIN1&PC_PCMSK1;//PINB;
|
||
|
PinChange.Port[1].PinPrev=PinChange.Port[1].PinCur;
|
||
|
#else
|
||
|
/* UNO */
|
||
|
PinChange.Port[0].PinCur=PC_PIN0&PC_PCMSK0;//PINB;
|
||
|
PinChange.Port[0].PinPrev=PinChange.Port[0].PinCur;
|
||
|
PinChange.Port[1].PinCur=PC_PIN1&PC_PCMSK1;//PINC;
|
||
|
PinChange.Port[1].PinPrev=PinChange.Port[1].PinCur;
|
||
|
PinChange.Port[2].PinCur=PC_PIN2&PC_PCMSK2;//PIND;
|
||
|
PinChange.Port[2].PinPrev=PinChange.Port[2].PinCur;
|
||
|
#endif
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*********************************************************************
|
||
|
PinChange RegisterIsr Function
|
||
|
Input:
|
||
|
Pointer on a PinChange Function
|
||
|
Output:
|
||
|
The associated VirtualPortIdx (0 to 2)
|
||
|
< 0 in case of failure
|
||
|
*********************************************************************/
|
||
|
int8_t TinyPinChange_RegisterIsr(uint8_t Pin, void(*Isr)(void))
|
||
|
{
|
||
|
int8_t IsrIdx,PortIdx,AlreadyLoaded=0;
|
||
|
|
||
|
PortIdx=DigitalPinToPortIdx(Pin);
|
||
|
|
||
|
for(IsrIdx=0;IsrIdx<PIN_CHANGE_HANDLER_MAX_NB;IsrIdx++)
|
||
|
{
|
||
|
if(PinChange.Port[PortIdx].Isr[IsrIdx]==Isr)
|
||
|
{
|
||
|
AlreadyLoaded=1;
|
||
|
break; /* Already loaded */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!AlreadyLoaded)
|
||
|
{
|
||
|
if(PinChange.Port[PortIdx].LoadedIsrNb<PIN_CHANGE_HANDLER_MAX_NB)
|
||
|
{
|
||
|
/* Not aready loaded: load it */
|
||
|
PinChange.Port[PortIdx].Isr[PinChange.Port[PortIdx].LoadedIsrNb]=Isr;
|
||
|
PinChange.Port[PortIdx].LoadedIsrNb++;
|
||
|
}
|
||
|
else PortIdx=-1; /* Failure */
|
||
|
}
|
||
|
return(PortIdx);
|
||
|
}
|
||
|
|
||
|
void TinyPinChange_EnablePin(uint8_t Pin)
|
||
|
{
|
||
|
if(digitalPinToPCICR(Pin))
|
||
|
{
|
||
|
*digitalPinToPCICR(Pin) |= _BV(digitalPinToPCICRbit(Pin));
|
||
|
*digitalPinToPCMSK(Pin) |= _BV(digitalPinToPCMSKbit(Pin));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TinyPinChange_DisablePin(uint8_t Pin)
|
||
|
{
|
||
|
if(digitalPinToPCICR(Pin))
|
||
|
{
|
||
|
*digitalPinToPCMSK(Pin) &= (_BV(digitalPinToPCMSKbit(Pin)) ^ 0xFF);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*********************************************************************
|
||
|
PinChange GetEvent Function
|
||
|
Input:
|
||
|
Idx: Index of the Port
|
||
|
Output:
|
||
|
The bits which have been changed in the port
|
||
|
*********************************************************************/
|
||
|
uint8_t TinyPinChange_GetPinEvent(uint8_t VirtualPortIdx)
|
||
|
{
|
||
|
return(PinChange.Port[VirtualPortIdx].Event);
|
||
|
}
|
||
|
|
||
|
/*********************************************************************
|
||
|
PinChange GetPinCurSt Function
|
||
|
Input:
|
||
|
Idx: Index of the Port
|
||
|
Output:
|
||
|
Current Pin Status of the port
|
||
|
*********************************************************************/
|
||
|
uint8_t TinyPinChange_GetPinCurSt(uint8_t VirtualPortIdx)
|
||
|
{
|
||
|
return(PinChange.Port[VirtualPortIdx].PinCur);
|
||
|
}
|