switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

View File

@@ -0,0 +1,60 @@
TinyPinChange library
=====================
**TinyPinChange** is an asynchronous (interrupt-driven) library designed to detect event (rising or falling edege) on pins.
Very often in the arduino world, users complain about conflicts between libraries.
This **TinyPinChange** library allows to share the "pin change interrupt" vector for several "clients".
For example, it's possible to use the **SoftRcPulseIn** library whilst using the **SoftSerial** library: both libraries rely on the **TinyPinChange** library.
Some examples of use cases:
-------------------------
* **Event detector** (on pins)
* **Frequency meter**
* **Pulse width meter**
* **Tachometer**
* **Duty cycle measurement**
* **Software serial port** (see **SoftSerial** library which relies on TinyPinChange)
Supported Arduinos:
------------------
* **ATmega368 (UNO)**
* **ATmega2560 (MEGA)**
* **ATtiny84 (Standalone)**
* **ATtiny85 (Standalone or Digispark)**
* **ATtiny167 (Digispark pro)**
Tip and Tricks:
--------------
Develop your project on an arduino UNO or MEGA, and then shrink it by loading the sketch in an ATtiny or Digispark (pro).
API/methods:
-----------
* TinyPinChange_Init()
* TinyPinChange_RegisterIsr()
* TinyPinChange_EnablePin()
* TinyPinChange_DisablePin()
* TinyPinChange_GetPortEvent()
* TinyPinChange_GetCurPortSt()
* TinyPinChange_PinToMsk()
* TinyPinChange_Edge()
* TinyPinChange_RisingEdge
* TinyPinChange_FallingEdge
Design considerations:
---------------------
On the arduino MEGA, as all the pins do not support "pin change interrupt", only the following pins are supported:
* 10 -> 15
* 50 -> 53
* A8 -> A15
On other devices (ATmega328, ATtiny84, ATtiny85 and ATtiny167), all the pins are usable.
Contact
-------
If you have some ideas of enhancement, please contact me by clicking on: [RC Navy](http://p.loussouarn.free.fr/contact.html).

View File

@@ -0,0 +1,184 @@
/********************************************************************************/
/* PROJECT: All based on ATtinyX5, ATtinyX4, Atiny167, ATmega328P, ATmega2560 */
/* MODULE: TinyPinChange */
/* VERSION: 1.2 (20/12/2014) */
/* DATE: 30/01/2011 */
/* TARGET: ATtinyX5, ATtinyX4, ATtiny167, ATmega328P, ATmega2560 */
/* COMPILER: WinAvr, avr-gcc, avr-g++ */
/* IDE: ARDUINO, AVR Studio 4 */
/* PROGRAMER: AVR-JTAG-ICE MKII, ARDUINO IDE */
/* 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 per port */
/*************************************************************************
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_ATtinyX4__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)
DECLARE_PIN_CHANGE_ISR(1)
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)
DECLARE_PIN_CHANGE_ISR(2)
#endif
/*************************************************************************
PUBLIC FUNCTIONS
*************************************************************************/
/*********************************************************************
PinChange Initialization Function
Input:
Void
Output:
Void
*********************************************************************/
void TinyPinChange_Init(void)
{
/* ATtinyX5, ATtiny167, ATtinyX4, UNO, MEGA */
PinChange.Port[0].PinCur = PC_PIN0 & PC_PCMSK0;//PINB for ATtinyX5, UNO or MEGA, PINA for ATtinyX4 or ATtiny167
PinChange.Port[0].PinPrev = PinChange.Port[0].PinCur;
#if defined(__AVR_ATtinyX4__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)
/* ATtinyX4, ATtiny167, UNO or MEGA */
PinChange.Port[1].PinCur = PC_PIN1 & PC_PCMSK1;//PINB for for ATtinyX4 or ATtiny167, PINC for UNO, PINJ for MEGA
PinChange.Port[1].PinPrev = PinChange.Port[1].PinCur;
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)
/* UNO or MEGA */
PinChange.Port[2].PinCur = PC_PIN2 & PC_PCMSK2;//PIND for UNO, PINK for MEGA
PinChange.Port[2].PinPrev = PinChange.Port[2].PinCur;
#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);
}
/*********************************************************************
PinChange Enable Pin Function
Input:
Pin: the Pin
Output:
Void
*********************************************************************/
void TinyPinChange_EnablePin(uint8_t Pin)
{
if(digitalPinToPCICR(Pin))
{
*digitalPinToPCICR(Pin) |= _BV(digitalPinToPCICRbit(Pin));
*digitalPinToPCMSK(Pin) |= _BV(digitalPinToPCMSKbit(Pin));
}
}
/*********************************************************************
PinChange Disable Pin Function
Input:
Pin: the Pin
Output:
Void
*********************************************************************/
void TinyPinChange_DisablePin(uint8_t Pin)
{
if(digitalPinToPCICR(Pin))
{
*digitalPinToPCMSK(Pin) &= (_BV(digitalPinToPCMSKbit(Pin)) ^ 0xFF);
}
}
/*********************************************************************
PinChange GetPortEvent Function
Input:
VirtualPortIdx: Index of the Port
Output:
The bits which have changed in the port
*********************************************************************/
uint8_t TinyPinChange_GetPortEvent(uint8_t VirtualPortIdx)
{
return(PinChange.Port[VirtualPortIdx].Event);
}
/*********************************************************************
PinChange GetCurPortSt Function
Input:
VirtualPortIdx: Index of the Port
Output:
Current Status of the port
*********************************************************************/
uint8_t TinyPinChange_GetCurPortSt(uint8_t VirtualPortIdx)
{
return(PinChange.Port[VirtualPortIdx].PinCur);
}

View File

@@ -0,0 +1,116 @@
#ifndef TINY_PIN_CHANGE_H
#define TINY_PIN_CHANGE_H 1
/*
* <TinyPinChange>, a library for Pin Change Interrupt by RC Navy (2012)
* Supported devices: ATmega238P (UNO), ATmega2560 (MEGA), ATtiny84, ATtiny85, ATtiny167
*
* http://p.loussouarn.free.fr
* 20/04/2014: Support for MEGA added
* 22/12/2014: Support for ATtiny167 added
* Methods TinyPinChange_Edge(), TinyPinChange_RisingEdge(), TinyPinChange_FallingEdge() added
* TinyPinChange_GetPinEvent() replaced with TinyPinChange_GetPortEvent()
* TinyPinChange_GetPinCurSt() replaced with TinyPinChange_GetCurPortSt()
*/
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <inttypes.h>
#ifdef __AVR_ATtinyX5__
#undef __AVR_ATtinyX5__
#endif
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define __AVR_ATtinyX5__
#endif
#ifdef __AVR_ATtinyX4__
#undef __AVR_ATtinyX4__
#endif
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#define __AVR_ATtinyX4__
#endif
#ifdef __AVR_ATtinyX5__
/* ATtinyX5 */
#define PIN_CHG_PORT_NB 1
#define DigitalPinToPortIdx(p) 0
#define PC_PIN0 PINB
#define PC_PCMSK0 PCMSK
#else
#ifdef __AVR_ATtinyX4__
/* ATtinyX4 */
#define PIN_CHG_PORT_NB 2
#define DigitalPinToPortIdx(p) (((p) <= 7) ? (0) : (((p) <= 10) ? (1) : (0)))
#define PC_PIN0 PINA
#define PC_PCMSK0 PCMSK0
#define PC_PIN1 PINB
#define PC_PCMSK1 PCMSK1
#else
#if defined(__AVR_ATmega2560__)
/* MEGA */
#define PIN_CHG_PORT_NB 3
#define DigitalPinToPortIdx(p) ((((p) >= A8) && ((p) <= A15)) ? (2) : ((((p) >= 50) && ((p) <= 53)) ? (0) : ((((p) >= 10) && ((p) <= 13)) ? (0) : (1))))
#define PC_PIN0 PINB
#define PC_PCMSK0 PCMSK0
#define PC_PIN1 PINJ
#define PC_PCMSK1 PCMSK1
#define PC_PIN2 PINK
#define PC_PCMSK2 PCMSK2
#else
#if defined(__AVR_ATtiny167__)
/* ATtiny167 */
#define PIN_CHG_PORT_NB 2
#define DigitalPinToPortIdx(p) (((p) >= 5 && (p) <= 12) ? (0) : (1))
#define PC_PIN0 PINA
#define PC_PCMSK0 PCMSK0
#define PC_PIN1 PINB
#define PC_PCMSK1 PCMSK1
#else
/* UNO */
#define PIN_CHG_PORT_NB 3
#define DigitalPinToPortIdx(p) (((p) <= 7) ? (2) : (((p) <= 13) ? (0) : (((p) <= 21) ? (1) : (0))))
#define PC_PIN0 PINB
#define PC_PCMSK0 PCMSK0
#define PC_PIN1 PINC
#define PC_PCMSK1 PCMSK1
#define PC_PIN2 PIND
#define PC_PCMSK2 PCMSK2
#endif
#endif
#endif
#endif
void TinyPinChange_Init(void);
int8_t TinyPinChange_RegisterIsr(uint8_t Pin, void(*Isr)(void));
void TinyPinChange_EnablePin(uint8_t Pin);
void TinyPinChange_DisablePin(uint8_t Pin);
uint8_t TinyPinChange_GetPortEvent(uint8_t VirtualPortIdx);
uint8_t TinyPinChange_GetCurPortSt(uint8_t VirtualPortIdx);
#define TinyPinChange_PinToMsk(Pin) _BV(digitalPinToPCMSKbit(Pin))
#define TinyPinChange_Edge(VirtualPortIdx, Pin) ( TinyPinChange_GetPortEvent((VirtualPortIdx)) & TinyPinChange_PinToMsk((Pin)) )
#define TinyPinChange_RisingEdge(VirtualPortIdx, Pin) ( TinyPinChange_GetPortEvent((VirtualPortIdx)) & TinyPinChange_PinToMsk((Pin)) & TinyPinChange_GetCurPortSt((VirtualPortIdx)) )
#define TinyPinChange_FallingEdge(VirtualPortIdx, Pin) ( TinyPinChange_GetPortEvent((VirtualPortIdx)) & TinyPinChange_PinToMsk((Pin)) & (TinyPinChange_GetCurPortSt((VirtualPortIdx) ^ 0xFF)) )
/*******************************************************/
/* Application Programming Interface (API) en Francais */
/*******************************************************/
/* Methodes en Francais English native methods */
#define TinyPinChange_EnregistreFonctionInterruption TinyPinChange_RegisterIsr
#define TinyPinChange_ActiveBroche TinyPinChange_EnablePin
#define TinyPinChange_DesactiveBroche TinyPinChange_DisablePin
#define TinyPinChange_RetourneEvenemenPort TinyPinChange_GetPortEvent
#define TinyPinChange_RetourneEtatCourantPort TinyPinChange_GetCurPortSt
#define TinyPinChange_MasqueDeBroche TinyPinChange_PinToMsk
#define TinyPinChange_Front TinyPinChange_Edge
#define TinyPinChange_FrontMontant TinyPinChange_RisingEdge
#define TinyPinChange_FrontDescendant TinyPinChange_FallingEdge
#endif

View File

@@ -0,0 +1,158 @@
/*
_____ ____ __ _ ____ _ _ _ _
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
http://p.loussouarn.free.fr
*******************************************************
* <TinyPinChange> library Demo *
* with debugging capabilities using *
* <SoftSerial> object as single wire serial interface *
*******************************************************
This sketch demonstrates how to use <TinyPinChange> library.
It counts all the transitions (both edges) on 2 different pins.
/!\CAUTION/!\: as <TinyPinChange> library can be shared (and it is with SoftSerial in this sketch) , the user shall test if the changes are related to the declared pins.
Trick: By connecting Pin#1 to Pin#0 or to Pin#5 through a 1K resistor, you can generate transitions for testing purpose.
Output results are sent to a software serial.
And the great thing is: using a <SoftSerial> object as a bi-directionnal software serial port (half-duplex) on a single pin to communicate with the outside world!
To display the sketch results on a PC (in a Terminal):
1) Build the "Serial One Wire Debug Cable" and plug it to the regular RS232 port as depicted below,
2) Open your favorite Terminal at 38400,n,8,1: HyperTerminal, Teraterm (Windows) or Minicom, GtkTerm (Linux) and CoolTerm (MAC) does the trick.
3) You can also use the Serial Monitor of the arduino IDE: Tools->Serial Port and select your RS232 port (may be an USB virtual port), Rate=38400.
4) To enable the display, type 1, to disable, type 0 in the Terminal/Monitor.
SERIAL ONE WIRE
DEBUGGING CABLE
_______________ ________________
/ \___/\___/ \
____
.--------. | \
| GND |--------------------------------+---o5 \
| | 47K | | 9o |
| | .--###--' | o4 |
| DEBUG | 4.7K | | 8o |
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC or Serial/USB adapter
| PIN | ^ | 1N4148 | 7o |
| | | '-----------o2 |
'--------' | | 6o |
ATtiny85 Single | o1 /
(Digispark) I/O |____/
SubD 9 pins
Female
*/
#include <TinyPinChange.h>
#include <SoftSerial.h>
#define LED_PIN 1
#define DEBUG_TX_RX_PIN 2
#define FIRST_INPUT 0
#define SECOND_INPUT 5
volatile uint16_t FirstInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
volatile uint16_t SecondInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
uint8_t VirtualPortNb;
uint8_t VirtualPortNb_;
void setup()
{
TinyPinChange_Init();
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
/* Enable Pin Change for each pin */
TinyPinChange_EnablePin(FIRST_INPUT);
TinyPinChange_EnablePin(SECOND_INPUT);
MySerial.txMode();
MySerial.println(F("\n*** Tiny PinChange Demo (Rising AND Falling edges) ***"));
MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb);
MySerial.print(F("Pin "));MySerial.print((int)SECOND_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb_);
MySerial.println(F("As you can see, virtual port is always port 0 for ATtiny85"));
MySerial.println(F("Remember <TinyPinChange> is also designed for UNO, MEGA, ATtiny84 and ATtiny167 ;-)"));
MySerial.println(F("Type 1 to start display, 0 to stop display"));
pinMode(LED_PIN, OUTPUT);
MySerial.rxMode(); /* Switch to Rx Mode */
}
/* Function called in interruption in case of change on pins */
void InterruptFunctionToCall(void)
{
if(TinyPinChange_Edge(VirtualPortNb, FIRST_INPUT)) /* Check FIRST_INPUT has changed (falling or rising edge) */
{
FirstInputChangeCount++; /* Rising AND Falling edges are counted */
}
if(TinyPinChange_Edge(VirtualPortNb_, SECOND_INPUT)) /* Check SECOND_INPUT has changed (falling or rising edge) */
{
SecondInputChangeCount++; /* Rising AND Falling edges are counted */
}
}
void loop()
{
static boolean State = HIGH, DisplayEnabled = true;
static uint32_t LedStartMs = millis(), DisplayStartMs = millis();
uint16_t LocalFirstInputChangeCount;
uint16_t LocalSecondInputChangeCount;
/* Blink the built-in LED */
if(millis() - LedStartMs >= 500UL)
{
LedStartMs = millis();
digitalWrite(LED_PIN, State);
State = !State; /* State will be inverted at the next digitalWrite() */
}
/* Get command from single wire SoftSerial */
if(MySerial.available())
{
switch(MySerial.read())
{
case '0':
DisplayEnabled = false;
break;
case '1':
DisplayEnabled = true;
break;
}
}
/* Diplay Transition numbers every second */
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
{
DisplayStartMs = millis();
noInterrupts(); /* Mandatory since counters are 16 bits */
LocalFirstInputChangeCount = FirstInputChangeCount;
LocalSecondInputChangeCount = SecondInputChangeCount;
interrupts();
MySerial.txMode();
MySerial.print(F("FirstInputChangeCount="));MySerial.println(LocalFirstInputChangeCount);
MySerial.print(F("SecondInputChangeCount="));MySerial.println(LocalSecondInputChangeCount);
MySerial.rxMode();
}
}

View File

@@ -0,0 +1,158 @@
/*
_____ ____ __ _ ____ _ _ _ _
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
http://p.loussouarn.free.fr
*******************************************************
* <TinyPinChange> library Demo *
* with debugging capabilities using *
* <SoftSerial> object as single wire serial interface *
*******************************************************
This sketch demonstrates how to use <TinyPinChange> library.
It counts all the FALLING edges on 2 different pins.
/!\CAUTION/!\: as <TinyPinChange> library can be shared (and it is with SoftSerial in this sketch) , the user shall test if the changes are related to the declared pins.
Trick: By connecting Pin#1 to Pin#0 or to Pin#5 through a 1K resistor, you can generate transitions for testing purpose.
Output results are sent to a software serial.
And the great thing is: using a <SoftSerial> object as a bi-directionnal software serial port (half-duplex) on a single pin to communicate with the outside world!
To display the sketch results on a PC (in a Terminal):
1) Build the "Serial One Wire Debug Cable" and plug it to the regular RS232 port as depicted below,
2) Open your favorite Terminal at 38400,n,8,1: HyperTerminal, Teraterm (Windows) or Minicom, GtkTerm (Linux) and CoolTerm (MAC) does the trick.
3) You can also use the Serial Monitor of the arduino IDE: Tools->Serial Port and select your RS232 port (may be an USB virtual port), Rate=38400.
4) To enable the display, type 1, to disable, type 0 in the Terminal/Monitor.
SERIAL ONE WIRE
DEBUGGING CABLE
_______________ ________________
/ \___/\___/ \
____
.--------. | \
| GND |--------------------------------+---o5 \
| | 47K | | 9o |
| | .--###--' | o4 |
| DEBUG | 4.7K | | 8o |
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC or Serial/USB adapter
| PIN | ^ | 1N4148 | 7o |
| | | '-----------o2 |
'--------' | | 6o |
ATtiny85 Single | o1 /
(Digispark) I/O |____/
SubD 9 pins
Female
*/
#include <TinyPinChange.h>
#include <SoftSerial.h>
#define LED_PIN 1
#define DEBUG_TX_RX_PIN 2
#define FIRST_INPUT 0
#define SECOND_INPUT 5
volatile uint16_t FirstInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
volatile uint16_t SecondInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
uint8_t VirtualPortNb;
uint8_t VirtualPortNb_;
void setup()
{
TinyPinChange_Init();
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
/* Enable Pin Change for each pin */
TinyPinChange_EnablePin(FIRST_INPUT);
TinyPinChange_EnablePin(SECOND_INPUT);
MySerial.txMode();
MySerial.println(F("\n*** Tiny PinChange Demo (Falling Edge) ***"));
MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb);
MySerial.print(F("Pin "));MySerial.print((int)SECOND_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb_);
MySerial.println(F("As you can see, virtual port is always port 0 for ATtiny85"));
MySerial.println(F("Remember <TinyPinChange> is also designed for UNO, MEGA, ATtiny84 and ATtiny167 ;-)"));
MySerial.println(F("Type 1 to start display, 0 to stop display"));
pinMode(LED_PIN, OUTPUT);
MySerial.rxMode(); /* Switch to Rx Mode */
}
/* Function called in interruption in case of change on pins */
void InterruptFunctionToCall(void)
{
if(TinyPinChange_FallingEdge(VirtualPortNb, FIRST_INPUT)) /* Check for FIRST_INPUT Rising Edge */
{
FirstInputChangeCount++; /* Only Falling edges are counted */
}
if(TinyPinChange_FallingEdge(VirtualPortNb_, SECOND_INPUT)) /* Check for SECOND_INPUT Rising Edge */
{
SecondInputChangeCount++; /* Only Falling edges are counted */
}
}
void loop()
{
static boolean State = HIGH, DisplayEnabled = true;
static uint32_t LedStartMs = millis(), DisplayStartMs = millis();
uint16_t LocalFirstInputChangeCount;
uint16_t LocalSecondInputChangeCount;
/* Blink the built-in LED */
if(millis() - LedStartMs >= 500UL)
{
LedStartMs = millis();
digitalWrite(LED_PIN, State);
State = !State; /* State will be inverted at the next digitalWrite() */
}
/* Get command from single wire SoftSerial */
if(MySerial.available())
{
switch(MySerial.read())
{
case '0':
DisplayEnabled = false;
break;
case '1':
DisplayEnabled = true;
break;
}
}
/* Diplay Transition numbers every second */
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
{
DisplayStartMs = millis();
noInterrupts(); /* Mandatory since counters are 16 bits */
LocalFirstInputChangeCount = FirstInputChangeCount;
LocalSecondInputChangeCount = SecondInputChangeCount;
interrupts();
MySerial.txMode();
MySerial.print(F("FirstInputChangeCount="));MySerial.println(LocalFirstInputChangeCount);
MySerial.print(F("SecondInputChangeCount="));MySerial.println(LocalSecondInputChangeCount);
MySerial.rxMode();
}
}

View File

@@ -0,0 +1,158 @@
/*
_____ ____ __ _ ____ _ _ _ _
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
http://p.loussouarn.free.fr
*******************************************************
* <TinyPinChange> library Demo *
* with debugging capabilities using *
* <SoftSerial> object as single wire serial interface *
*******************************************************
This sketch demonstrates how to use <TinyPinChange> library.
It counts all the RISING edges on 2 different pins.
/!\CAUTION/!\: as <TinyPinChange> library can be shared (and it is with SoftSerial in this sketch) , the user shall test if the changes are related to the declared pins.
Trick: By connecting Pin#1 to Pin#0 or to Pin#5 through a 1K resistor, you can generate transitions for testing purpose.
Output results are sent to a software serial.
And the great thing is: using a <SoftSerial> object as a bi-directionnal software serial port (half-duplex) on a single pin to communicate with the outside world!
To display the sketch results on a PC (in a Terminal):
1) Build the "Serial One Wire Debug Cable" and plug it to the regular RS232 port as depicted below,
2) Open your favorite Terminal at 38400,n,8,1: HyperTerminal, Teraterm (Windows) or Minicom, GtkTerm (Linux) and CoolTerm (MAC) does the trick.
3) You can also use the Serial Monitor of the arduino IDE: Tools->Serial Port and select your RS232 port (may be an USB virtual port), Rate=38400.
4) To enable the display, type 1, to disable, type 0 in the Terminal/Monitor.
SERIAL ONE WIRE
DEBUGGING CABLE
_______________ ________________
/ \___/\___/ \
____
.--------. | \
| GND |--------------------------------+---o5 \
| | 47K | | 9o |
| | .--###--' | o4 |
| DEBUG | 4.7K | | 8o |
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC or Serial/USB adapter
| PIN | ^ | 1N4148 | 7o |
| | | '-----------o2 |
'--------' | | 6o |
ATtiny85 Single | o1 /
(Digispark) I/O |____/
SubD 9 pins
Female
*/
#include <TinyPinChange.h>
#include <SoftSerial.h>
#define LED_PIN 1
#define DEBUG_TX_RX_PIN 2
#define FIRST_INPUT 0
#define SECOND_INPUT 5
volatile uint16_t FirstInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
volatile uint16_t SecondInputChangeCount = 0; /* Volatile since the variable will be updated in interruption */
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
uint8_t VirtualPortNb;
uint8_t VirtualPortNb_;
void setup()
{
TinyPinChange_Init();
MySerial.begin(57600); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
VirtualPortNb = TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall);
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
/* Enable Pin Change for each pin */
TinyPinChange_EnablePin(FIRST_INPUT);
TinyPinChange_EnablePin(SECOND_INPUT);
MySerial.txMode();
MySerial.println(F("\n*** Tiny PinChange Demo (Rising Edge) ***"));
MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb);
MySerial.print(F("Pin "));MySerial.print((int)SECOND_INPUT);
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb_);
MySerial.println(F("As you can see, virtual port is always port 0 for ATtiny85"));
MySerial.println(F("Remember <TinyPinChange> is also designed for UNO, MEGA, ATtiny84 and ATtiny167 ;-)"));
MySerial.println(F("Type 1 to start display, 0 to stop display"));
pinMode(LED_PIN, OUTPUT);
MySerial.rxMode(); /* Switch to Rx Mode */
}
/* Function called in interruption in case of change on pins */
void InterruptFunctionToCall(void)
{
if(TinyPinChange_RisingEdge(VirtualPortNb, FIRST_INPUT)) /* Check for FIRST_INPUT Rising Edge */
{
FirstInputChangeCount++; /* Only Rising edges are counted */
}
if(TinyPinChange_RisingEdge(VirtualPortNb_, SECOND_INPUT)) /* Check for SECOND_INPUT Rising Edge */
{
SecondInputChangeCount++; /* Only Rising edges are counted */
}
}
void loop()
{
static boolean State = HIGH, DisplayEnabled = true;
static uint32_t LedStartMs = millis(), DisplayStartMs = millis();
uint16_t LocalFirstInputChangeCount;
uint16_t LocalSecondInputChangeCount;
/* Blink the built-in LED */
if(millis() - LedStartMs >= 500UL)
{
LedStartMs = millis();
digitalWrite(LED_PIN, State);
State = !State; /* State will be inverted at the next digitalWrite() */
}
/* Get command from single wire SoftSerial */
if(MySerial.available())
{
switch(MySerial.read())
{
case '0':
DisplayEnabled = false;
break;
case '1':
DisplayEnabled = true;
break;
}
}
/* Diplay Transition numbers every second */
if((millis() - DisplayStartMs >= 1000UL) && DisplayEnabled)
{
DisplayStartMs = millis();
noInterrupts(); /* Mandatory since counters are 16 bits */
LocalFirstInputChangeCount = FirstInputChangeCount;
LocalSecondInputChangeCount = SecondInputChangeCount;
interrupts();
MySerial.txMode();
MySerial.print(F("FirstInputChangeCount="));MySerial.println(LocalFirstInputChangeCount);
MySerial.print(F("SecondInputChangeCount="));MySerial.println(LocalSecondInputChangeCount);
MySerial.rxMode();
}
}

View File

@@ -0,0 +1,440 @@
/*
_____ ____ __ _ ____ _ _ _ _
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
http://p.loussouarn.free.fr
*******************************************************
* <TinyPinChange> library Demo *
* with display capabilities using *
* <SoftSerial> object as single wire serial interface *
*******************************************************
This "Tiny RC Scope" sketch demonstrates how to use <TinyPinChange> and <SoftSerial> libraries.
"Tiny RC Scope" acts as a simple real time ASCII oscilloscope for displaying one RC Channel in the serial console.
The displayed measurement (in µs) are: pulse width and RC period.
Trick: By connecting Pin#1 to Pin#0, through a 1K resistor, you can measure the RC Signal provided by the built-in RC generator for testing purpose.
Output results are sent to a software serial port. If a real RC signal is connected to Pin0, the trace is displayed in real time in the terminal.
And the great thing is: using a <SoftSerial> object as a bi-directionnal software serial port (half-duplex) on a single pin to communicate with the outside world!
To display the sketch results on a PC (in a Terminal):
1) Build the "Serial One Wire Debug Cable" and plug it to the regular RS232 port as depicted below.
2) Open your favorite Terminal at 57600,n,8,1: HyperTerminal, Teraterm (Windows) or Minicom, GtkTerm (Linux) and CoolTerm (MAC) does the trick.
3) You can also use the Serial Monitor of the arduino IDE: Tools->Serial Port and select your RS232 port (may be an USB virtual port), Rate=57600.
4) To test "Tiny RC Scope", connect Pin1 to Pin0, and look at the Terminal (57600,n,8,1) connected to Pin2 through a debug cable ()
5) The wave form should be displayed in the Terminal,
6) Type - to decrease the pulse width (-10us),
7) Type + to increase the pulse width (+10us),
8) Type m to set the pulse width to its minimum (500us),
9) Type n or N to set the pulse width to its Neutral value (1500us),
10) Type M to set the pulse width to its Maximum (2500us),
11) To measure real RC signals, disconnect the Pin1 from Pin0 and connect a RC receiver output to Pin0,
12) The Terminal will display in real time the pulse width of the connected RC channel.
13) If the channel is not connected, a flat line is displayed.
SERIAL ONE WIRE
DEBUGGING CABLE
_______________ ________________
/ \___/\___/ \
____
.--------. | \
| GND |--------------------------------+---o5 \
| | 47K | | 9o |
| | .--###--' | o4 |
| DEBUG | 4.7K | | 8o |
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC or Serial/USB adapter
| PIN | ^ | 1N4148 | 7o |
| | | '-----------o2 |
'--------' | | 6o |
ATtiny85 Single | o1 /
(Digispark) I/O |____/
(pro) SubD 9 pins
Female
*/
#include <TinyPinChange.h>
#include <SoftSerial.h>
#define RC_CHANNEL_PIN 0 /* RC Channel is connected to pin 0 */
#define RC_GEN_PIN 1 /* Pin used as internal RC generator for test purpose */
#define RC_PINS_MSK (_BV(RC_CHANNEL_PIN) | _BV(RC_GEN_PIN))
#define DEBUG_TX_RX_PIN 2
#define DEF_TEST_RC_CH_WIDTH_US 1500 /* This value can be change via the Terminal */
#define TEST_RC_PERIOD_US 20000
#define PULSE_MAX_US 2500
#define PULSE_MIN_US 500
#define STEP_US 10
#define ERR_MARGIN_US 150
#define SERIAL_BAUD_RATE 57600 /* 57600 is the maximum for Receiving commands from the serial port: 1 char -> #200us */
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
#define ONE_CHAR_TX_TIME_US 200 /* @ 57600 bauds */
enum {PULSE_SRC_INTERNAL, PULSE_SRC_EXTERNAL};
typedef struct {
uint32_t RisingStartUs;
uint32_t RcWidth_us;
uint32_t LastRxPulseMs;
boolean FallingEdgeFound;
}RcChSt_t;
volatile RcChSt_t Ch; /* volatile, since value are used in ISR and in the loop() */
volatile uint32_t RcPeriod_us = TEST_RC_PERIOD_US;
uint32_t TestRcWidth_us = DEF_TEST_RC_CH_WIDTH_US;
/* The different states of the display state machine */
enum {DISP_COMPUTE, DISP_FIRST_LINE, DISP_PREP_SEC_LINE, DISP_SECOND_LINE, DISP_PREP_THIRD_LINE, DISP_THIRD_LINE, DISP_WAIT};
#define LINE_LEN 38
typedef struct{
char Line[LINE_LEN];
uint8_t Idx;
uint8_t State;
uint8_t HighNb;
}DispSt_t;
static DispSt_t Disp;
volatile uint8_t IntRcSynch = 0;
uint8_t VirtualPortIdx;
/*
RC Signal
____ ____
_| |____________________________| |_
<---->
Width_us
<-------------------------------->
Period_us
*/
void setup()
{
TinyPinChange_Init();
MySerial.begin(SERIAL_BAUD_RATE); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
Disp.State = DISP_COMPUTE;
VirtualPortIdx = TinyPinChange_RegisterIsr(RC_CHANNEL_PIN, InterruptFunctionToCall); /* As all pins are on the same port, a single ISR is needed */
pinMode(RC_CHANNEL_PIN, INPUT);
digitalWrite(RC_CHANNEL_PIN, HIGH); /* Enable Pull-up to avoid floating inputs in case of nothing connected to them */
TinyPinChange_EnablePin(RC_CHANNEL_PIN);
Ch.RcWidth_us = 0;
Ch.FallingEdgeFound = 0;
MySerial.txMode();
MySerial.println(F("\n -- Tiny RC Scope V1.0 (C) RC Navy 2014 --\n"));
MySerial.rxMode(); /* Switch to Rx Mode */
pinMode(RC_GEN_PIN, OUTPUT);
}
void loop()
{
uint32_t RcGeneStartUs = micros();
static uint32_t ProcessStartUs = micros();
static uint32_t DisplayStartMs = millis();
uint32_t ProcessDurationUs;
uint32_t HalfRemaingLowUs;
char RxChar;
/* Blink the built-in LED (Built-in RC Signal generator) */
if(IsInternalRcSrc())
{
RcGeneStartUs = micros();
digitalWrite(RC_GEN_PIN, HIGH);
while(micros() - RcGeneStartUs < TestRcWidth_us);
digitalWrite(RC_GEN_PIN, LOW);
}
/********************/
/* Start of process */
/********************/
ProcessStartUs = micros();
DisplayRcMeasurement(5000U);/* Gives 5000 us to display a part of the trace */
/* Get command from single wire SoftSerial (to tune the built-in generator) */
if(MySerial.available() > 0)
{
RxChar = MySerial.read();MySerial.txMode();MySerial.println("");MySerial.rxMode(); /* Carriage return after the echo */
switch(RxChar)
{
case '-': /* Decrease Built-in RC Pulse */
if((TestRcWidth_us - STEP_US) >= PULSE_MIN_US)
{
TestRcWidth_us -= STEP_US;
}
break;
case '+': /* Increase Built-in RC Pulse */
if(TestRcWidth_us + STEP_US <= PULSE_MAX_US)
{
TestRcWidth_us += STEP_US;
}
break;
case 'm': /* Set Built-in RC Pulse o min value: 500 */
TestRcWidth_us = PULSE_MIN_US;
break;
case 'N': /* Set Built-in RC Pulse to Neutral: 1500 */
case 'n':
TestRcWidth_us = DEF_TEST_RC_CH_WIDTH_US;
break;
case 'M': /* Set Built-in RC Pulse to Max value: 2500 */
TestRcWidth_us = PULSE_MAX_US;
break;
default:
/* Ignore */
break;
}
}
/********************/
/* End of process */
/********************/
ProcessDurationUs = micros() - ProcessStartUs; //Compute how many us took the previous instructions
if(IsInternalRcSrc())
{
HalfRemaingLowUs = TEST_RC_PERIOD_US - (ProcessDurationUs + TestRcWidth_us + 100UL);
RcGeneStartUs = micros();
while((micros() - RcGeneStartUs) < HalfRemaingLowUs);
}
}
/*
RC Signal
____ ____
_| |____________________________| |_
<---->
Width_us
<-------------------------------->
Period_us
<-------------------->
Display is processed here
Explanation: the display of the trace is performed just after the falling edge of the RC pulse
As the duration between 2 pulses is too short to display the full trace, the trace is displayed part by part.
A full trace is composed of around 100 characters:
At 57600 bauds, one character takes (1/57600) * 10 = 174 us. As there are some overhead, it is closer than 200us.
So, the full trace takes 100 x 200 = 20000 us = 20 ms. It's impossible to display the full trace between 2 consecutive pulses.
DisplayRcMeasurement() function is the very tricky part of this sketch: it has as argument an amount of time and exits before
it exceeds it. A state machine is used to memorize where the display was arrived.
*/
uint8_t DisplayRcMeasurement(uint16_t FreetimeUs)
{
static uint32_t LocalRcWidth_us;
static uint32_t LocalRcPeriod_us;
static uint32_t StartWaitMs;
char *Ptr;
uint32_t ProcessStart_us;
uint32_t Elapsed_us;
uint8_t StartIdx, Idx;
uint8_t Ret = 0;
switch(Disp.State)
{
case DISP_COMPUTE:
DispCompute:
if(Ch.FallingEdgeFound)
{
DispComputeNoSignal:
ProcessStart_us = micros();
Ch.FallingEdgeFound = 0;
noInterrupts(); /* Mandatory since RcWidth_us and RcPeriod_us are 32 bits */
LocalRcWidth_us = Ch.RcWidth_us;
LocalRcPeriod_us = RcPeriod_us;
interrupts();
if(LocalRcWidth_us < (PULSE_MIN_US - ERR_MARGIN_US) || LocalRcWidth_us > (PULSE_MAX_US + ERR_MARGIN_US)) LocalRcWidth_us = 0; /* Out of Range */
Disp.HighNb = (LocalRcWidth_us + 50UL) / 100;
strcpy_P(Disp.Line, PSTR("Ch(P0)__"));
if(LocalRcWidth_us)
{
Ptr = Disp.Line + 8;
for(Idx = 0; Idx < Disp.HighNb; Idx++) *Ptr++='_';*Ptr++='\n';*Ptr=0;
}
else Disp.Line[6] = 0;
Elapsed_us = micros() - ProcessStart_us;
FreetimeUs -= (uint16_t)Elapsed_us;
Disp.Idx=0;
Disp.State = DISP_FIRST_LINE;
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
{
goto DispFirstLine;
}
}
else
{
if(millis() - StartWaitMs >= 1000UL)
{
LocalRcWidth_us = 0;
goto DispComputeNoSignal;
}
}
break;
case DISP_PREP_SEC_LINE:
DispPrepSecLine:
/* Prepare second line */
ProcessStart_us = micros();
if(LocalRcWidth_us)
{
strcpy_P(Disp.Line, PSTR("_____/"));
for(Idx = 0; Idx < (2 + Disp.HighNb); Idx++) Disp.Line[6 + Idx] = ' ';
itoa(LocalRcWidth_us, Disp.Line + 6, 10);StartIdx = 9; if(LocalRcWidth_us >= 1000) StartIdx++;Disp.Line[StartIdx++] = 'u';Disp.Line[StartIdx++] = 's';
StartIdx = 6 + 2 + Disp.HighNb;Disp.Line[StartIdx++] = '\\';
}
else StartIdx = 0;
for(Idx = 0; (StartIdx + Idx ) < (LINE_LEN - 2); Idx++) Disp.Line[StartIdx + Idx] = '_';Disp.Line[StartIdx + Idx] = '\n';Disp.Line[++StartIdx + Idx] = 0;
Elapsed_us = micros() - ProcessStart_us;
FreetimeUs -= (uint16_t)Elapsed_us;
Disp.Idx=0;
Disp.State = DISP_SECOND_LINE;
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
{
goto DispSecondLine;
}
break;
case DISP_PREP_THIRD_LINE:
DispPrepThirdLine:
/* Prepare third line */
ProcessStart_us = micros();
strcpy_P(Disp.Line, PSTR(" RC Period: "));
if(LocalRcWidth_us)
{
itoa(LocalRcPeriod_us, Disp.Line + 20, 10);
strcat_P(Disp.Line, PSTR("us"));
}
else strcat_P(Disp.Line, PSTR("???"));
Elapsed_us = micros() - ProcessStart_us;
FreetimeUs -= (uint16_t)Elapsed_us;
Disp.Idx=0;
Disp.State = DISP_THIRD_LINE;
if(FreetimeUs >= ONE_CHAR_TX_TIME_US)
{
goto DispThirdLine;
}
break;
case DISP_FIRST_LINE:
case DISP_SECOND_LINE:
case DISP_THIRD_LINE:
DispFirstLine:
DispSecondLine:
DispThirdLine:
ProcessStart_us = micros();
MySerial.txMode();
while(1)
{
if(Disp.Line[Disp.Idx])
{
MySerial.print(Disp.Line[Disp.Idx++]);
if (micros() - ProcessStart_us >= (FreetimeUs - ONE_CHAR_TX_TIME_US))
{
MySerial.rxMode();
break; /* exit while(1) and stay in the current state */
}
}
else
{
switch(Disp.State)
{
case DISP_FIRST_LINE:
/* First line is fully displayed */
Disp.State = DISP_PREP_SEC_LINE;
if(FreetimeUs - Elapsed_us >= 200)
{
FreetimeUs -= (uint16_t)Elapsed_us;
goto DispPrepSecLine;
}
else
{
/* Not enough time: just change state */
MySerial.rxMode();
}
break;
case DISP_SECOND_LINE:
/* Second line is fully displayed */
Disp.State = DISP_PREP_THIRD_LINE;
if(FreetimeUs - Elapsed_us >= 200)
{
FreetimeUs -= (uint16_t)Elapsed_us;
goto DispPrepThirdLine;
}
else
{
/* Not enough time: just change state */
MySerial.rxMode();
}
break;
case DISP_THIRD_LINE:
/* Third line is fully displayed */
MySerial.print('\n');
StartWaitMs = millis();
Disp.State = DISP_WAIT;
MySerial.rxMode();
break;
}
break; /* exit while(1) */
}
}
break;
case DISP_WAIT:
if(millis() - StartWaitMs >= 500UL) Disp.State = DISP_COMPUTE; /* Give some time to enter commands via the terminal (in internal source mode) */
else Ch.FallingEdgeFound = false;
break;
}
return(Ret);
}
/* The following function checks if the received signal is the image of the one of the built-in RC generator */
uint8_t IsInternalRcSrc()
{
uint8_t Ret;
static uint32_t SampleStartMs = millis();
if(millis() - Ch.LastRxPulseMs >= 300UL) IntRcSynch = 100; /* Kick off Internal RC generator */
Ret = (IntRcSynch >= 100);
if(millis() - SampleStartMs >= 10UL)
{
SampleStartMs = millis();
IntRcSynch = 99;
}
return(Ret);
}
/* Function called in interruption in case of change on RC pins: pulse width and RC period measurement */
void InterruptFunctionToCall(void)
{
if(TinyPinChange_RisingEdge(VirtualPortIdx, RC_CHANNEL_PIN)) /* Check for RC Channel rising edge */
{
RcPeriod_us = micros() - Ch.RisingStartUs;
Ch.RisingStartUs = micros();
}
else
{
Ch.RcWidth_us = micros() - Ch.RisingStartUs;
Ch.FallingEdgeFound = true;
Ch.LastRxPulseMs = millis();
if(!(PINB & RC_PINS_MSK)) /* Check if RC_CHANNEL_PIN and RC_GEN_PIN are both to 0 */
{
if(IntRcSynch < 100) IntRcSynch++; /* if IntRcSynch reaches 100, it means the RC source is internal (synchronized) */
}else IntRcSynch = 0; /* Not synchronized */
}
}

View File

@@ -0,0 +1,35 @@
#######################################
# Syntax Coloring Map TinyPinChange
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
TinyPinChange KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
TinyPinChange_Init KEYWORD2
TinyPinChange_RegisterIsr KEYWORD2
TinyPinChange_EnregistreFonctionInterruption KEYWORD2
TinyPinChange_EnablePin KEYWORD2
TinyPinChange_ActiveBroche KEYWORD2
TinyPinChange_DisablePin KEYWORD2
TinyPinChange_DesactiveBroche KEYWORD2
TinyPinChange_GetPortEvent KEYWORD2
TinyPinChange_RetourneEvenemenPort KEYWORD2
TinyPinChange_GetCurPortSt KEYWORD2
TinyPinChange_RetourneEtatCourantPort KEYWORD2
TinyPinChange_PinToMsk KEYWORD2
TinyPinChange_MasqueDeBroche KEYWORD2
TinyPinChange_Edge KEYWORD2
TinyPinChange_Front KEYWORD2
TinyPinChange_RisingEdge KEYWORD2
TinyPinChange_FrontMontant KEYWORD2
TinyPinChange_FallingEdge KEYWORD2
TinyPinChange_FrontDescendant KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################