mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-04-27 23:29:01 -07:00
added updated tinypinchange and associated libraries to support PRO
This commit is contained in:
parent
d5fa60a1ec
commit
e09b5f479b
22
hardware/digistump/avr/libraries/DigisparkIRLib/.gitattributes
vendored
Normal file
22
hardware/digistump/avr/libraries/DigisparkIRLib/.gitattributes
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Custom for Visual Studio
|
||||||
|
*.cs diff=csharp
|
||||||
|
*.sln merge=union
|
||||||
|
*.csproj merge=union
|
||||||
|
*.vbproj merge=union
|
||||||
|
*.fsproj merge=union
|
||||||
|
*.dbproj merge=union
|
||||||
|
|
||||||
|
# Standard to msysgit
|
||||||
|
*.doc diff=astextplain
|
||||||
|
*.DOC diff=astextplain
|
||||||
|
*.docx diff=astextplain
|
||||||
|
*.DOCX diff=astextplain
|
||||||
|
*.dot diff=astextplain
|
||||||
|
*.DOT diff=astextplain
|
||||||
|
*.pdf diff=astextplain
|
||||||
|
*.PDF diff=astextplain
|
||||||
|
*.rtf diff=astextplain
|
||||||
|
*.RTF diff=astextplain
|
215
hardware/digistump/avr/libraries/DigisparkIRLib/.gitignore
vendored
Normal file
215
hardware/digistump/avr/libraries/DigisparkIRLib/.gitignore
vendored
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#################
|
||||||
|
## Eclipse
|
||||||
|
#################
|
||||||
|
|
||||||
|
*.pydevproject
|
||||||
|
.project
|
||||||
|
.metadata
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.classpath
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# CDT-specific
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# PDT-specific
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
## Visual Studio
|
||||||
|
#################
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
build/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.log
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
*.ncrunch*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.Publish.xml
|
||||||
|
*.pubxml
|
||||||
|
|
||||||
|
# NuGet Packages Directory
|
||||||
|
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||||
|
#packages/
|
||||||
|
|
||||||
|
# Windows Azure Build Output
|
||||||
|
csx
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
sql/
|
||||||
|
*.Cache
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file to a newer
|
||||||
|
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
App_Data/*.mdf
|
||||||
|
App_Data/*.ldf
|
||||||
|
|
||||||
|
#############
|
||||||
|
## Windows detritus
|
||||||
|
#############
|
||||||
|
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Mac crap
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
|
||||||
|
#############
|
||||||
|
## Python
|
||||||
|
#############
|
||||||
|
|
||||||
|
*.py[co]
|
||||||
|
|
||||||
|
# Packages
|
||||||
|
*.egg
|
||||||
|
*.egg-info
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
eggs/
|
||||||
|
parts/
|
||||||
|
var/
|
||||||
|
sdist/
|
||||||
|
develop-eggs/
|
||||||
|
.installed.cfg
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
.coverage
|
||||||
|
.tox
|
||||||
|
|
||||||
|
#Translations
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
#Mr Developer
|
||||||
|
.mr.developer.cfg
|
@ -0,0 +1,16 @@
|
|||||||
|
Change Log for IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
|
||||||
|
April 2013 Version 1.1 Constructor of IRsendBase now initializes output
|
||||||
|
pin and forces it low immediately.
|
||||||
|
|
||||||
|
New IRrecv::No_Output() method initializes output
|
||||||
|
pin and forces it low. Use this in sketches which
|
||||||
|
receive only by the have output hardware connected.
|
||||||
|
|
||||||
|
Added examples IRservo and IRserial_remote
|
||||||
|
|
||||||
|
February 2013 Version 1.0a Removed debugging test switch which was accidentally
|
||||||
|
left on in file "IRLib.h"
|
||||||
|
|
||||||
|
January 2013 Version 1.0 Initial Release
|
988
hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.cpp
Normal file
988
hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.cpp
Normal file
@ -0,0 +1,988 @@
|
|||||||
|
/* IRLib.cpp from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.1 April 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
*
|
||||||
|
* Port to Digispark (size optimization) August 2013
|
||||||
|
* by RC Navy http://p.loussouarn.free.fr
|
||||||
|
*
|
||||||
|
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
|
||||||
|
* That same license applies to this modified version. See his original copyright below.
|
||||||
|
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
|
||||||
|
* My purpose was to reorganize the code to make it easier to add or remove protocols.
|
||||||
|
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
|
||||||
|
* by making them separate classes. That way the receiving aspect can be more black box and implementers
|
||||||
|
* of decoders and senders can just deal with the decoding of protocols.
|
||||||
|
* Also added provisions to make the classes base classes that could be extended with new protocols
|
||||||
|
* which would not require recompiling of the original library nor understanding of its detailed contents.
|
||||||
|
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
|
||||||
|
* Some changes were just my weird programming style. Also extended debugging information added.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRremote
|
||||||
|
* Version 0.1 July, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
|
||||||
|
*
|
||||||
|
* Interrupt code based on NECIRrcv by Joe Knapp
|
||||||
|
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||||
|
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IRLib.h"
|
||||||
|
#include "IRLibMatch.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to a flash stored string that is the name of the protocol received.
|
||||||
|
*/
|
||||||
|
#if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||||
|
const char *Pnames(IRTYPES Type) {
|
||||||
|
return(NULL);
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
const __FlashStringHelper *Pnames(IRTYPES Type) {
|
||||||
|
if(Type>LAST_PROTOCOL) Type=UNKNOWN;
|
||||||
|
const __FlashStringHelper *Names[LAST_PROTOCOL+1]={F("Unknown"),
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
F("NEC")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
F("Sony")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5)
|
||||||
|
F("RC5")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
F("RC6")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
F("Panasonic Old")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
F("JVC")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
F("NECx")
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_HASH_CODE)
|
||||||
|
F("Hash Code")
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
return Names[Type];
|
||||||
|
#else
|
||||||
|
return Names[!!Type];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RC5_T1 889
|
||||||
|
#define RC5_RPT_LENGTH 46000
|
||||||
|
|
||||||
|
#define RC6_HDR_MARK 2666
|
||||||
|
#define RC6_HDR_SPACE 889
|
||||||
|
#define RC6_T1 444
|
||||||
|
|
||||||
|
#ifdef USE_IR_SEND
|
||||||
|
|
||||||
|
#define TOPBIT 0x80000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IRsend classes contain a series of methods for sending various protocols.
|
||||||
|
* Each of these begin by calling enableIROut(int kHz) to set the carrier frequency.
|
||||||
|
* It then calls mark(int usec) and space(inc usec) to transmit marks and
|
||||||
|
* spaces of varying length of microseconds however the protocol defines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Most of the protocols have a header consisting of a mark/space of a particular length followed by
|
||||||
|
* a series of variable length mark/space signals. Depending on the protocol they very the links of the
|
||||||
|
* mark or the space to indicate a data bit of "0" or "1". Most also end with a stop bit of "1".
|
||||||
|
* The basic structure of the sending and decoding these protocols led to lots of redundant code.
|
||||||
|
* Therefore I have implemented generic sending and decoding routines. You just need to pass a bunch of customized
|
||||||
|
* parameters and it does the work. This reduces compiled code size with only minor speed degradation.
|
||||||
|
* You may be able to implement additional protocols by simply passing the proper values to these generic routines.
|
||||||
|
* The decoding routines do not encode stop bits. So you have to tell this routine whether or not to send one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void IRsendBase::sendGeneric(unsigned long data, int Num_Bits, int Head_Mark, int Head_Space, int Mark_One, int Mark_Zero, int Space_One, int Space_Zero, int mHz, bool Use_Stop) {
|
||||||
|
data = data << (32 - Num_Bits);
|
||||||
|
enableIROut(mHz);
|
||||||
|
//Some protocols do not send a header when sending repeat codes. So we pass a zero value to indicate skipping this.
|
||||||
|
if(Head_Mark) mark(Head_Mark);
|
||||||
|
if(Head_Space) space(Head_Space);
|
||||||
|
for (int i = 0; i <Num_Bits; i++) {
|
||||||
|
if (data & TOPBIT) {
|
||||||
|
mark(Mark_One); space(Space_One);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mark(Mark_Zero); space(Space_Zero);
|
||||||
|
}
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
if (Use_Stop) mark(Mark_One); space(0) ; //stop bit of "1"
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
void IRsendNEC::send(unsigned long data)
|
||||||
|
{
|
||||||
|
ATTEMPT_MESSAGE(F("sending NEC"));
|
||||||
|
if (data==REPEAT) {
|
||||||
|
mark (564* 16); space (564*4); mark(564);space (96000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendGeneric(data,32, 564*16, 564*8, 564, 564, 564*3, 564, 38, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
/*
|
||||||
|
* Sony is backwards from most protocols. It uses a variable length mark and a fixed length space rather than
|
||||||
|
* a fixed mark and a variable space. Our generic send will still work. According to the protocol you must send
|
||||||
|
* Sony commands at least three times so we automatically do it here.
|
||||||
|
*/
|
||||||
|
void IRsendSony::send(unsigned long data, int nbits) {
|
||||||
|
for(int i=0; i<3;i++)
|
||||||
|
sendGeneric(data,nbits, 600*4, 600, 600*2, 600, 600, 600, 40, false);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
/*
|
||||||
|
* This next section of send routines were added by Chris Young. They all use the generic send.
|
||||||
|
*/
|
||||||
|
void IRsendNECx::send(unsigned long data)
|
||||||
|
{
|
||||||
|
sendGeneric(data,32, 564*8, 564*8, 564, 564, 564*3, 564, 38, true);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
void IRsendPanasonic_Old::send(unsigned long data)
|
||||||
|
{
|
||||||
|
sendGeneric(data,22, 833*4, 833*4, 833, 833, 833*3, 833,57, true);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
/*
|
||||||
|
* JVC omits the Mark/space header on repeat sending. Therefore we multiply it by 0 if it's a repeat.
|
||||||
|
* The only device I had to test this protocol was an old JVC VCR. It would only work if at least
|
||||||
|
* 2 frames are sent separated by 45us of "space". Therefore you should call this routine once with
|
||||||
|
* "First=true"and it will send a first frame followed by one repeat frame. If First== false,
|
||||||
|
* it will only send a single repeat frame.
|
||||||
|
*/
|
||||||
|
void IRsendJVC::send(unsigned long data, bool First)
|
||||||
|
{
|
||||||
|
sendGeneric(data, 16,525*16*First, 525*8*First, 525, 525,525*3, 525, 38, true);
|
||||||
|
delayMicroseconds(45);
|
||||||
|
if(First) sendGeneric(data, 16,0,0, 525, 525,525*3, 525, 38, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining protocols require special treatment. They were in the original IRremote library.
|
||||||
|
*/
|
||||||
|
void IRsendRaw::send(unsigned int buf[], int len, int hz)
|
||||||
|
{
|
||||||
|
enableIROut(hz);
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (i & 1) {
|
||||||
|
space(buf[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mark(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
space(0); // Just to be sure
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The RC5 protocol uses a phase encoding of data bits. A space/mark pair indicates "1"
|
||||||
|
* and a mark/space indicates a "0". It begins with a single "1" bit which is not encoded
|
||||||
|
* in the data. The high order data bit is a toggle bit that indicates individual
|
||||||
|
* keypresses. You must toggle this bit yourself when sending data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void IRsendRC5::send(unsigned long data)
|
||||||
|
{
|
||||||
|
enableIROut(36);
|
||||||
|
data = data << (32 - 13);
|
||||||
|
mark(RC5_T1); // First start bit
|
||||||
|
//Note: Original IRremote library incorrectly assumed second bit was always a "1"
|
||||||
|
//bit patterns from this decoder are not backward compatible with patterns produced
|
||||||
|
//by original library. Ucomment the following two lines to maintain backward compatibility.
|
||||||
|
//space(RC5_T1); // Second start bit
|
||||||
|
//mark(RC5_T1); // Second start bit
|
||||||
|
for (int i = 0; i < 13; i++) {
|
||||||
|
if (data & TOPBIT) {
|
||||||
|
space(RC5_T1); mark(RC5_T1);// 1 is space, then mark
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mark(RC5_T1); space(RC5_T1);// 0 is mark, then space
|
||||||
|
}
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
space(0); // Turn off at end
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The RC6 protocol also phase encodes databits although the phasing is opposite of RC5.
|
||||||
|
*/
|
||||||
|
void IRsendRC6::send(unsigned long data, int nbits)
|
||||||
|
{
|
||||||
|
enableIROut(36);
|
||||||
|
data = data << (32 - nbits);
|
||||||
|
mark(RC6_HDR_MARK); space(RC6_HDR_SPACE);
|
||||||
|
mark(RC6_T1); space(RC6_T1);// start bit "1"
|
||||||
|
int t;
|
||||||
|
for (int i = 0; i < nbits; i++) {
|
||||||
|
if (i == 3) {
|
||||||
|
t = 2 * RC6_T1; // double-wide trailer bit
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t = RC6_T1;
|
||||||
|
}
|
||||||
|
if (data & TOPBIT) {
|
||||||
|
mark(t); space(t);//"1" is a Mark/space
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
space(t); mark(t);//"0" is a space/Mark
|
||||||
|
}
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
space(0); // Turn off at end
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This method can be used to send any of the supported types except for raw and hash code.
|
||||||
|
* There is no hash code send possible. You can call sendRaw directly if necessary.
|
||||||
|
*/
|
||||||
|
void IRsend::send(IRTYPES Type, unsigned long data, int nbits) {
|
||||||
|
switch(Type) {
|
||||||
|
case NEC: IRsendNEC::send(data); break;
|
||||||
|
case SONY: IRsendSony::send(data,nbits); break;
|
||||||
|
case RC5: IRsendRC5::send(data); break;
|
||||||
|
case RC6: IRsendRC6::send(data,nbits); break;
|
||||||
|
case PANASONIC_OLD: IRsendPanasonic_Old::send(data); break;
|
||||||
|
case NECX: IRsendNECx::send(data); break;
|
||||||
|
case JVC: IRsendJVC::send(data,(bool)nbits); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Although I tried to keep all of the interrupt handling code at the bottom of this file
|
||||||
|
* so you didn't have to mess with it if you didn't want to, I needed to move this definition
|
||||||
|
* forwarded so it could be used by IRdecodeBase constructor.
|
||||||
|
*/
|
||||||
|
// receiver states
|
||||||
|
enum rcvstate_t {STATE_UNKNOWN, STATE_IDLE, STATE_MARK, STATE_SPACE, STATE_STOP};
|
||||||
|
// information for the interrupt handler
|
||||||
|
typedef struct {
|
||||||
|
uint8_t recvpin; // pin for IR data from detector
|
||||||
|
rcvstate_t rcvstate; // state machine
|
||||||
|
uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing
|
||||||
|
unsigned int timer; // state timer, counts 50uS ticks.
|
||||||
|
unsigned int rawbuf[RAWBUF]; // raw data
|
||||||
|
uint8_t rawlen; // counter of entries in rawbuf
|
||||||
|
}
|
||||||
|
irparams_t;
|
||||||
|
volatile irparams_t irparams;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We've chosen to separate the decoding routines from the receiving routines to isolate
|
||||||
|
* the technical hardware and interrupt portion of the code which should never need modification
|
||||||
|
* from the protocol decoding portion that will likely be extended and modified.
|
||||||
|
*/
|
||||||
|
IRdecodeBase::IRdecodeBase(void) {
|
||||||
|
rawbuf=(volatile unsigned int*)irparams.rawbuf;
|
||||||
|
Reset();
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Normally the decoder uses irparams.rawbuf but if you want to resume receiving while
|
||||||
|
* still decoding you can define a separate buffer and pass the address here.
|
||||||
|
* Then IRrecv::GetResults will copy the raw values from its buffer to yours allowing you to
|
||||||
|
* call IRrecv::resume immediately before you call decode.
|
||||||
|
*/
|
||||||
|
void IRdecodeBase::UseExtnBuf(void *P){
|
||||||
|
rawbuf=(volatile unsigned int*)P;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Copies rawbuf and rawlen from one decoder to another. See IRhashdecode example
|
||||||
|
* for usage.
|
||||||
|
*/
|
||||||
|
void IRdecodeBase::copyBuf (IRdecodeBase *source){
|
||||||
|
memcpy((void *)rawbuf,(const void *)source->rawbuf,sizeof(irparams.rawbuf));
|
||||||
|
rawlen=source->rawlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine is actually quite useful. See the Samsung36 sketch in the examples
|
||||||
|
*/
|
||||||
|
bool IRdecodeBase::decode(void) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void IRdecodeBase::Reset(void) {
|
||||||
|
decode_type= UNKNOWN;
|
||||||
|
value=0;
|
||||||
|
bits=0;
|
||||||
|
rawlen=0;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* This method dumps useful information about the decoded values.
|
||||||
|
*/
|
||||||
|
void IRdecodeBase::DumpResults(void) {
|
||||||
|
int i;
|
||||||
|
if(decode_type<=LAST_PROTOCOL){
|
||||||
|
Serial.print(F("Decoded ")); Serial.print(Pnames(decode_type));
|
||||||
|
Serial.print(F(": Value:")); Serial.print(value, HEX);
|
||||||
|
};
|
||||||
|
#ifdef DETAILLED_DUMP
|
||||||
|
Serial.print(F(" (")); Serial.print(bits, DEC); Serial.println(F(" bits)"));
|
||||||
|
Serial.print(F("Raw samples(")); Serial.print(rawlen, DEC);
|
||||||
|
Serial.print(F("): Gap:")); Serial.println(Interval_uSec(0), DEC);
|
||||||
|
Serial.print(F(" Head: m")); Serial.print(Interval_uSec(1), DEC);
|
||||||
|
Serial.print(F(" s")); Serial.println(Interval_uSec(2), DEC);
|
||||||
|
int LowSpace= 32767; int LowMark= 32767;
|
||||||
|
int HiSpace=0; int HiMark= 0;
|
||||||
|
for (i = 3; i < rawlen; i++) {
|
||||||
|
int interval= Interval_uSec(i);
|
||||||
|
if (i % 2) {
|
||||||
|
LowMark=min(LowMark, interval); HiMark=max(HiMark, interval);
|
||||||
|
Serial.print(i/2-1,DEC); Serial.print(F(":m"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(interval>0)LowSpace=min(LowSpace, interval); HiSpace=max (HiSpace, interval);
|
||||||
|
Serial.print(F(" s"));
|
||||||
|
}
|
||||||
|
Serial.print(interval, DEC);
|
||||||
|
int j=i-1;
|
||||||
|
if ((j % 2)==1)Serial.print(F("\t"));
|
||||||
|
if ((j % 4)==1)Serial.print(F("\t "));
|
||||||
|
if ((j % 8)==1)Serial.println();
|
||||||
|
if ((j % 32)==1)Serial.println();
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
Serial.print(F("Mark min:")); Serial.print(LowMark,DEC);Serial.print(F("\t max:")); Serial.println(HiMark,DEC);
|
||||||
|
Serial.print(F("Space min:")); Serial.print(LowSpace,DEC);Serial.print(F("\t max:")); Serial.println(HiSpace,DEC);
|
||||||
|
#endif
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This handy little routine converts ticks from rawbuf[index] into uSec intervals adjusting for the
|
||||||
|
* Mark/space bias.
|
||||||
|
*/
|
||||||
|
unsigned long IRdecodeBase::Interval_uSec(int index)
|
||||||
|
{
|
||||||
|
return rawbuf[index]*USECPERTICK+( (index%2)?-MARK_EXCESS: MARK_EXCESS);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Again we use a generic routine because most protocols have the same basic structure. However we need to
|
||||||
|
* indicate whether or not the protocol varies the length of the mark or the space to indicate a "0" or "1".
|
||||||
|
* If "Mark_One" is zero. We assume that the length of the space varies. If "Mark_One" is not zero then
|
||||||
|
* we assume that the length of Mark varies and the value passed as "Space_Zero" is ignored.
|
||||||
|
* When using variable length Mark, assumes Head_Space==Space_One. If it doesn't, you need a specialized decoder.
|
||||||
|
*/
|
||||||
|
bool IRdecodeBase::decodeGeneric(/*int*/int8_t Raw_Count, int Head_Mark,int Head_Space, int Mark_One, int Mark_Zero, int Space_One,int Space_Zero) {
|
||||||
|
// If raw samples count or head mark are zero then don't perform these tests.
|
||||||
|
// Some protocols need to do custom header work.
|
||||||
|
long data = 0; /*int*/int8_t Max; /*int*/int8_t offset;
|
||||||
|
if (Raw_Count) {if (rawlen != Raw_Count) return RAW_COUNT_ERROR;}
|
||||||
|
if (Head_Mark) {if (!MATCH_MARK(rawbuf[1],Head_Mark)) return HEADER_MARK_ERROR;}
|
||||||
|
if (Head_Space) {if (!MATCH_SPACE(rawbuf[2],Head_Space)) return HEADER_SPACE_ERROR;}
|
||||||
|
|
||||||
|
if (Mark_One) {//Length of a mark indicates data "0" or "1". Space_Zero is ignored.
|
||||||
|
offset=2;//skip initial gap plus header Mark.
|
||||||
|
Max=rawlen;
|
||||||
|
while (offset < Max) {
|
||||||
|
if (!MATCH_SPACE(rawbuf[offset], Space_One)) return DATA_SPACE_ERROR;
|
||||||
|
offset++;
|
||||||
|
if (MATCH_MARK(rawbuf[offset], Mark_One)) {
|
||||||
|
data = (data << 1) | 1;
|
||||||
|
}
|
||||||
|
else if (MATCH_MARK(rawbuf[offset], Mark_Zero)) {
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
else return DATA_MARK_ERROR;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
bits = (offset - 1) / 2;
|
||||||
|
}
|
||||||
|
else {//Mark_One was 0 therefore length of a space indicates data "0" or "1".
|
||||||
|
Max=rawlen-1; //ignore stop bit
|
||||||
|
offset=3;//skip initial gap plus two header items
|
||||||
|
while (offset < Max) {
|
||||||
|
if (!MATCH_MARK (rawbuf[offset],Mark_Zero)) return DATA_MARK_ERROR;
|
||||||
|
offset++;
|
||||||
|
if (MATCH_SPACE(rawbuf[offset],Space_One)) {
|
||||||
|
data = (data << 1) | 1;
|
||||||
|
}
|
||||||
|
else if (MATCH_SPACE (rawbuf[offset],Space_Zero)) {
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
else return DATA_SPACE_ERROR;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
bits = (offset - 1) / 2 -1;//didn't encode stop bit
|
||||||
|
}
|
||||||
|
// Success
|
||||||
|
value = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine has been modified significantly from the original IRremote.
|
||||||
|
* It assumes you've already called IRrecvBase::GetResults and it was true.
|
||||||
|
* The purpose of GetResults is to determine if a complete set of signals
|
||||||
|
* has been received. It then copies the raw data into your decode_results
|
||||||
|
* structure. By moving the test for completion and the copying of the buffer
|
||||||
|
* outside of this "decode" method you can use the individual decode
|
||||||
|
* methods or make your own custom "decode" without checking for
|
||||||
|
* protocols you don't use.
|
||||||
|
* Note: Don't forget to call IRrecvBase::resume(); after decoding is complete.
|
||||||
|
*/
|
||||||
|
bool IRdecode::decode(void) {
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
if (IRdecodeNEC::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
if (IRdecodeSony::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5)
|
||||||
|
if (IRdecodeRC5::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
if (IRdecodeRC6::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
if (IRdecodePanasonic_Old::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
if (IRdecodeNECx::decode()) return true;
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
if (IRdecodeJVC::decode()) return true;
|
||||||
|
#endif
|
||||||
|
//Deliberately did not add hash code decoding. If you get decode_type==UNKNOWN and
|
||||||
|
// you want to know a hash code you can call IRhash::decode() yourself.
|
||||||
|
// BTW This is another reason we separated IRrecv from IRdecode.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
#define NEC_RPT_SPACE 2250
|
||||||
|
bool IRdecodeNEC::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("NEC"));
|
||||||
|
// Check for repeat
|
||||||
|
if (rawlen == 4 && MATCH_SPACE(rawbuf[2], NEC_RPT_SPACE) &&
|
||||||
|
MATCH_MARK(rawbuf[3],564)) {
|
||||||
|
bits = 0;
|
||||||
|
value = REPEAT;
|
||||||
|
decode_type = NEC;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(!decodeGeneric(68, 564*16, 564*8, 0, 564, 564*3, 564)) return false;
|
||||||
|
decode_type = NEC;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
// According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sony8
|
||||||
|
// Sony protocol can only be 8, 12, 15, or 20 bits in length.
|
||||||
|
bool IRdecodeSony::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("Sony"));
|
||||||
|
if(rawlen!=2*8+2 && rawlen!=2*12+2 && rawlen!=2*15+2 && rawlen!=2*20+2) return RAW_COUNT_ERROR;
|
||||||
|
if(!decodeGeneric(0, 600*4, 600, 600*2, 600, 600,0)) return false;
|
||||||
|
decode_type = SONY;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next several decoders were added by Chris Young. They illustrate some of the special cases
|
||||||
|
* that can come up when decoding using the generic decoder.
|
||||||
|
*/
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
/*
|
||||||
|
* A very good source for protocol information is… http://www.hifi-remote.com/johnsfine/DecodeIR.html
|
||||||
|
* I used that information to understand what they call the "Panasonic old" protocol which is used by
|
||||||
|
* Scientific Atlanta cable boxes. That website uses a very strange notation called IRP notation.
|
||||||
|
* For this protocol, the notation was:
|
||||||
|
* {57.6k,833}<1,-1|1,-3>(4,-4,D:5,F:6,~D:5,~F:6,1,-???)+
|
||||||
|
* This indicates that the frequency is 57.6, the base length for the pulse is 833
|
||||||
|
* The first part of the <x,-x|x,-x> section tells you what a "0" is and the second part
|
||||||
|
* tells you what a "1" is. That means "0" is 833 on, 833 off while an "1" is 833 on
|
||||||
|
* followed by 833*3=2499 off. The section in parentheses tells you what data gets sent.
|
||||||
|
* The protocol begins with header consisting of 4*833 on and 4*833 off. The other items
|
||||||
|
* describe what the remaining data bits are.
|
||||||
|
* It reads as 5 device bits followed by 6 function bits. You then repeat those bits complemented.
|
||||||
|
* It concludes with a single "1" bit followed by and an undetermined amount of blank space.
|
||||||
|
* This makes the entire protocol 5+6+5+6= 22 bits long since we don't encode the stop bit.
|
||||||
|
* The "+" at the end means you only need to send it once and it can repeat as many times as you want.
|
||||||
|
*/
|
||||||
|
bool IRdecodePanasonic_Old::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("Panasonic_Old"));
|
||||||
|
if(!decodeGeneric(48,833*4,833*4,0,833,833*3,833)) return false;
|
||||||
|
/*
|
||||||
|
* The protocol spec says that the first 11 bits described the device and function.
|
||||||
|
* The next 11 bits are the same thing only it is the logical Bitwise complement.
|
||||||
|
* Many protocols have such check features in their definition but our code typically doesn't
|
||||||
|
* perform these checks. For example NEC's least significant 8 bits are the complement of
|
||||||
|
* of the next more significant 8 bits. While it's probably not necessary to error check this,
|
||||||
|
* here is some sample code to show you how.
|
||||||
|
*/
|
||||||
|
long S1= (value & 0x0007ff); // 00 0000 0000 0111 1111 1111 //00000 000000 11111 111111
|
||||||
|
long S2= (value & 0x3ff800)>> 11; // 11 1111 1111 1000 0000 0000 //11111 111111 00000 000000
|
||||||
|
S2= (~S2) & 0x0007ff;
|
||||||
|
if (S1!=S2) {REJECTION_MESSAGE(F("inverted bit redundancy")); return false;};
|
||||||
|
// Success
|
||||||
|
decode_type = PANASONIC_OLD;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
bool IRdecodeNECx::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("NECx"));
|
||||||
|
if(!decodeGeneric(68,564*8,564*8,0,564,564*3,564)) return false;
|
||||||
|
decode_type = NECX;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
// JVC does not send any header if there is a repeat.
|
||||||
|
bool IRdecodeJVC::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("JVC"));
|
||||||
|
if(!decodeGeneric(36,525*16,525*8,0,525,525*3,525))
|
||||||
|
{
|
||||||
|
ATTEMPT_MESSAGE(F("JVC Repeat"));
|
||||||
|
if (rawlen==34)
|
||||||
|
{
|
||||||
|
if(!decodeGeneric(0,525,0,0,525,525*3,525))
|
||||||
|
{REJECTION_MESSAGE(F("JVC repeat failed generic")); return false;}
|
||||||
|
else {
|
||||||
|
//If this is a repeat code then IRdecodeBase::decode fails to add the most significant bit
|
||||||
|
if (MATCH_SPACE(rawbuf[4],(525*3)))
|
||||||
|
{
|
||||||
|
value |= 0x8000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!MATCH_SPACE(rawbuf[4],525)) return DATA_SPACE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bits++;
|
||||||
|
}
|
||||||
|
else return RAW_COUNT_ERROR;
|
||||||
|
}
|
||||||
|
decode_type =JVC;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
/*
|
||||||
|
* The remaining protocols from the original IRremote library require special handling
|
||||||
|
* This routine gets one undecoded level at a time from the raw buffer.
|
||||||
|
* The RC5/6 decoding is easier if the data is broken into time intervals.
|
||||||
|
* E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
|
||||||
|
* successive calls to getRClevel will return MARK, MARK, SPACE.
|
||||||
|
* offset and used are updated to keep track of the current position.
|
||||||
|
* t1 is the time interval for a single bit in microseconds.
|
||||||
|
* Returns ERROR if the measured time interval is not a multiple of t1.
|
||||||
|
*/
|
||||||
|
IRdecodeRC::RCLevel IRdecodeRC::getRClevel(int *offset, int *used, int t1) {
|
||||||
|
if (*offset >= rawlen) {
|
||||||
|
// After end of recorded buffer, assume SPACE.
|
||||||
|
return SPACE;
|
||||||
|
}
|
||||||
|
int width = rawbuf[*offset];
|
||||||
|
IRdecodeRC::RCLevel val;
|
||||||
|
if ((*offset) % 2) val=MARK; else val=SPACE;
|
||||||
|
int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
|
||||||
|
|
||||||
|
int avail;
|
||||||
|
if (MATCH(width, t1 + correction)) {
|
||||||
|
avail = 1;
|
||||||
|
}
|
||||||
|
else if (MATCH(width, 2*t1 + correction)) {
|
||||||
|
avail = 2;
|
||||||
|
}
|
||||||
|
else if (MATCH(width, 3*t1 + correction)) {
|
||||||
|
avail = 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
(*used)++;
|
||||||
|
if (*used >= avail) {
|
||||||
|
*used = 0;
|
||||||
|
(*offset)++;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (val == MARK) Serial.println("MARK"); else Serial.println("SPACE");
|
||||||
|
#endif
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN_RC5_SAMPLES 11
|
||||||
|
#define MIN_RC6_SAMPLES 1
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5)
|
||||||
|
bool IRdecodeRC5::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("RC5"));
|
||||||
|
if (rawlen < MIN_RC5_SAMPLES + 2) return RAW_COUNT_ERROR;
|
||||||
|
int offset = 1; // Skip gap space
|
||||||
|
long data = 0;
|
||||||
|
int used = 0;
|
||||||
|
// Get start bits
|
||||||
|
if (getRClevel(&offset, &used, RC5_T1) != MARK) return HEADER_MARK_ERROR;
|
||||||
|
//Note: Original IRremote library incorrectly assumed second bit was always a "1"
|
||||||
|
//bit patterns from this decoder are not backward compatible with patterns produced
|
||||||
|
//by original library. Ucomment the following two lines to maintain backward compatibility.
|
||||||
|
//if (getRClevel(&offset, &used, RC5_T1) != SPACE) return HEADER_SPACE_ERROR;
|
||||||
|
//if (getRClevel(&offset, &used, RC5_T1) != MARK) return HEADER_MARK_ERROR;
|
||||||
|
int nbits;
|
||||||
|
for (nbits = 0; offset < rawlen; nbits++) {
|
||||||
|
RCLevel levelA = getRClevel(&offset, &used, RC5_T1);
|
||||||
|
RCLevel levelB = getRClevel(&offset, &used, RC5_T1);
|
||||||
|
if (levelA == SPACE && levelB == MARK) {
|
||||||
|
// 1 bit
|
||||||
|
data = (data << 1) | 1;
|
||||||
|
}
|
||||||
|
else if (levelA == MARK && levelB == SPACE) {
|
||||||
|
// zero bit
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
else return DATA_MARK_ERROR;
|
||||||
|
}
|
||||||
|
// Success
|
||||||
|
bits = 13;
|
||||||
|
value = data;
|
||||||
|
decode_type = RC5;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
bool IRdecodeRC6::decode(void) {
|
||||||
|
ATTEMPT_MESSAGE(F("RC6"));
|
||||||
|
if (rawlen < MIN_RC6_SAMPLES) return RAW_COUNT_ERROR;
|
||||||
|
// Initial mark
|
||||||
|
if (!MATCH_MARK(rawbuf[1], RC6_HDR_MARK)) return HEADER_MARK_ERROR;
|
||||||
|
if (!MATCH_SPACE(rawbuf[2], RC6_HDR_SPACE)) return HEADER_SPACE_ERROR;
|
||||||
|
int offset=3;//Skip gap and header
|
||||||
|
long data = 0;
|
||||||
|
int used = 0;
|
||||||
|
// Get start bit (1)
|
||||||
|
if (getRClevel(&offset, &used, RC6_T1) != MARK) return DATA_MARK_ERROR;
|
||||||
|
if (getRClevel(&offset, &used, RC6_T1) != SPACE) return DATA_SPACE_ERROR;
|
||||||
|
int nbits;
|
||||||
|
for (nbits = 0; offset < rawlen; nbits++) {
|
||||||
|
RCLevel levelA, levelB; // Next two levels
|
||||||
|
levelA = getRClevel(&offset, &used, RC6_T1);
|
||||||
|
if (nbits == 3) {
|
||||||
|
// T bit is double wide; make sure second half matches
|
||||||
|
if (levelA != getRClevel(&offset, &used, RC6_T1)) return TRAILER_BIT_ERROR;
|
||||||
|
}
|
||||||
|
levelB = getRClevel(&offset, &used, RC6_T1);
|
||||||
|
if (nbits == 3) {
|
||||||
|
// T bit is double wide; make sure second half matches
|
||||||
|
if (levelB != getRClevel(&offset, &used, RC6_T1)) return TRAILER_BIT_ERROR;
|
||||||
|
}
|
||||||
|
if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5
|
||||||
|
// 1 bit
|
||||||
|
data = (data << 1) | 1;
|
||||||
|
}
|
||||||
|
else if (levelA == SPACE && levelB == MARK) {
|
||||||
|
// zero bit
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return DATA_MARK_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Success
|
||||||
|
bits = nbits;
|
||||||
|
value = data;
|
||||||
|
decode_type = RC6;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) //|| (MY_IR_PROTOCOL == HASH_CODE)
|
||||||
|
/*
|
||||||
|
* This Hash decoder is based on IRhashcode
|
||||||
|
* Copyright 2010 Ken Shirriff
|
||||||
|
* For details see http://www.arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
|
||||||
|
* Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
|
||||||
|
* Converts the raw code values into a 32-bit hash code.
|
||||||
|
* Hopefully this code is unique for each button.
|
||||||
|
*/
|
||||||
|
#define FNV_PRIME_32 16777619
|
||||||
|
#define FNV_BASIS_32 2166136261
|
||||||
|
// Compare two tick values, returning 0 if newval is shorter,
|
||||||
|
// 1 if newval is equal, and 2 if newval is longer
|
||||||
|
int IRdecodeHash::compare(unsigned int oldval, unsigned int newval) {
|
||||||
|
if (newval < oldval * .8) return 0;
|
||||||
|
if (oldval < newval * .8) return 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRdecodeHash::decode(void) {
|
||||||
|
hash = FNV_BASIS_32;
|
||||||
|
for (int i = 1; i+2 < rawlen; i++) {
|
||||||
|
hash = (hash * FNV_PRIME_32) ^ compare(rawbuf[i], rawbuf[i+2]);
|
||||||
|
}
|
||||||
|
//note: does not set decode_type=HASH_CODE nor "value" because you might not want to.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This section is all related to interrupt handling and hardware issues. It has nothing to do with IR protocols.
|
||||||
|
* You need not understand this is all you're doing is adding new protocols or improving the decoding and sending
|
||||||
|
* of protocols.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Provides ISR
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
// defines for setting and clearing register bits
|
||||||
|
#ifndef cbi
|
||||||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||||
|
#endif
|
||||||
|
#ifndef sbi
|
||||||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||||
|
#endif
|
||||||
|
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead
|
||||||
|
#ifdef F_CPU
|
||||||
|
#define SYSCLOCK F_CPU // main Arduino clock
|
||||||
|
#else
|
||||||
|
#define SYSCLOCK 16000000 // main Arduino clock
|
||||||
|
#endif
|
||||||
|
#define PRESCALE 8 // timer clock prescale
|
||||||
|
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond
|
||||||
|
|
||||||
|
#include <IRLibTimer.h>
|
||||||
|
|
||||||
|
|
||||||
|
IRrecv::IRrecv(int recvpin)
|
||||||
|
{
|
||||||
|
irparams.recvpin = recvpin;
|
||||||
|
irparams.blinkflag = 0;
|
||||||
|
}
|
||||||
|
/* If your hardware is set up to do both output and input but your particular sketch
|
||||||
|
* doesn't do any output, this method will ensure that your output pin is low
|
||||||
|
* and doesn't turn on your IR LED or any output circuit.
|
||||||
|
*/
|
||||||
|
void IRrecv::No_Output (void) {
|
||||||
|
pinMode(TIMER_PWM_PIN, OUTPUT);
|
||||||
|
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRrecv::enableIRIn() {
|
||||||
|
// setup pulse clock timer interrupt
|
||||||
|
cli();
|
||||||
|
TIMER_CONFIG_NORMAL();
|
||||||
|
TIMER_ENABLE_INTR;
|
||||||
|
TIMER_RESET;
|
||||||
|
sei();
|
||||||
|
// initialize state machine variables
|
||||||
|
irparams.rcvstate = STATE_IDLE;
|
||||||
|
irparams.rawlen = 0;
|
||||||
|
// set pin modes
|
||||||
|
pinMode(irparams.recvpin, INPUT);
|
||||||
|
}
|
||||||
|
// enable/disable blinking of pin 13 on IR processing
|
||||||
|
void IRrecv::blink13(int blinkflag)
|
||||||
|
{
|
||||||
|
irparams.blinkflag = blinkflag;
|
||||||
|
if (blinkflag)
|
||||||
|
pinMode(BLINKLED, OUTPUT);
|
||||||
|
}
|
||||||
|
void IRrecv::resume() {
|
||||||
|
irparams.rcvstate = STATE_IDLE;
|
||||||
|
irparams.rawlen = 0;
|
||||||
|
}
|
||||||
|
bool IRrecv::GetResults(IRdecodeBase *decoder) {
|
||||||
|
if (irparams.rcvstate != STATE_STOP) return false;
|
||||||
|
decoder->Reset();//clear out any old values.
|
||||||
|
decoder->rawlen = (unsigned int)irparams.rawlen;
|
||||||
|
//By copying the entire array we could call IRrecv::resume immediately while decoding
|
||||||
|
//is still in progress.
|
||||||
|
if(decoder->rawbuf != irparams.rawbuf)
|
||||||
|
memcpy((void *)decoder->rawbuf,(const void *)irparams.rawbuf,sizeof(irparams.rawbuf));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#define _GAP 5000 // Minimum map between transmissions
|
||||||
|
#define GAP_TICKS (_GAP/USECPERTICK)
|
||||||
|
|
||||||
|
// TIMER2 interrupt code to collect raw data.
|
||||||
|
// Widths of alternating SPACE, MARK are recorded in rawbuf.
|
||||||
|
// Recorded in ticks of 50 microseconds.
|
||||||
|
// rawlen counts the number of entries recorded so far.
|
||||||
|
// First entry is the SPACE between transmissions.
|
||||||
|
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
|
||||||
|
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
|
||||||
|
ISR(TIMER_INTR_NAME)
|
||||||
|
{
|
||||||
|
TIMER_RESET;
|
||||||
|
enum irdata_t {IR_MARK=0, IR_SPACE=1};
|
||||||
|
irdata_t irdata = (irdata_t)digitalRead(irparams.recvpin);
|
||||||
|
irparams.timer++; // One more 50us tick
|
||||||
|
if (irparams.rawlen >= RAWBUF) {
|
||||||
|
// Buffer overflow
|
||||||
|
irparams.rcvstate = STATE_STOP;
|
||||||
|
}
|
||||||
|
switch(irparams.rcvstate) {
|
||||||
|
case STATE_IDLE: // In the middle of a gap
|
||||||
|
if (irdata == IR_MARK) {
|
||||||
|
if (irparams.timer < GAP_TICKS) {
|
||||||
|
// Not big enough to be a gap.
|
||||||
|
irparams.timer = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// gap just ended, record duration and start recording transmission
|
||||||
|
irparams.rawlen = 0;
|
||||||
|
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
|
||||||
|
irparams.timer = 0;
|
||||||
|
irparams.rcvstate = STATE_MARK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_MARK: // timing MARK
|
||||||
|
if (irdata == IR_SPACE) { // MARK ended, record time
|
||||||
|
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
|
||||||
|
irparams.timer = 0;
|
||||||
|
irparams.rcvstate = STATE_SPACE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_SPACE: // timing SPACE
|
||||||
|
if (irdata == IR_MARK) { // SPACE just ended, record it
|
||||||
|
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
|
||||||
|
irparams.timer = 0;
|
||||||
|
irparams.rcvstate = STATE_MARK;
|
||||||
|
}
|
||||||
|
else { // SPACE
|
||||||
|
if (irparams.timer > GAP_TICKS) {
|
||||||
|
// big SPACE, indicates gap between codes
|
||||||
|
// Mark current code as ready for processing
|
||||||
|
// Switch to STOP
|
||||||
|
// Don't reset timer; keep counting space width
|
||||||
|
irparams.rcvstate = STATE_STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_STOP: // waiting, measuring gap
|
||||||
|
if (irdata == IR_MARK) { // reset gap timer
|
||||||
|
irparams.timer = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (irparams.blinkflag) {
|
||||||
|
if (irdata == IR_MARK) {
|
||||||
|
BLINKLED_ON(); // turn pin 13 LED on
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLINKLED_OFF(); // turn pin 13 LED off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_IR_SEND
|
||||||
|
IRsendBase::IRsendBase () {
|
||||||
|
pinMode(TIMER_PWM_PIN, OUTPUT);
|
||||||
|
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRsendBase::enableIROut(int khz) {
|
||||||
|
// Enables IR output. The khz value controls the modulation frequency in kilohertz.
|
||||||
|
// The IR output will be on pin 3 (OC2B).
|
||||||
|
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
|
||||||
|
// to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
|
||||||
|
// TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
|
||||||
|
// controlling the duty cycle.
|
||||||
|
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
|
||||||
|
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
|
||||||
|
// A few hours staring at the ATmega documentation and this will all make sense.
|
||||||
|
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
|
||||||
|
|
||||||
|
// Disable the Timer2 Interrupt (which is used for receiving IR)
|
||||||
|
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
|
||||||
|
pinMode(TIMER_PWM_PIN, OUTPUT);
|
||||||
|
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
|
||||||
|
TIMER_CONFIG_KHZ(khz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRsendBase::mark(int time) {
|
||||||
|
TIMER_ENABLE_PWM;
|
||||||
|
delayMicroseconds(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRsendBase::space(int time) {
|
||||||
|
TIMER_DISABLE_PWM;
|
||||||
|
delayMicroseconds(time);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Various debugging routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int MATCH(int measured, int desired) {
|
||||||
|
Serial.print("Testing: "); Serial.print(TICKS_LOW(desired), DEC);
|
||||||
|
Serial.print(" <= "); Serial.print(measured, DEC); Serial.print(" <= "); Serial.println(TICKS_HIGH(desired), DEC);
|
||||||
|
return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MATCH_MARK(int measured_ticks, int desired_us) {
|
||||||
|
Serial.print("Testing mark "); Serial.print(measured_ticks * USECPERTICK, DEC); Serial.print(" vs "); Serial.print(desired_us, DEC); Serial.print(": ");
|
||||||
|
Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC); Serial.print(" <= "); Serial.print(measured_ticks, DEC);
|
||||||
|
Serial.print(" <= "); Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
|
||||||
|
return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MATCH_SPACE(int measured_ticks, int desired_us) {
|
||||||
|
Serial.print("Testing space "); Serial.print(measured_ticks * USECPERTICK, DEC); Serial.print(" vs "); Serial.print(desired_us, DEC); Serial.print(": ");
|
||||||
|
Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC); Serial.print(" <= "); Serial.print(measured_ticks, DEC);
|
||||||
|
Serial.print(" <= "); Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
|
||||||
|
return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TRACE
|
||||||
|
void ATTEMPT_MESSAGE(const __FlashStringHelper * s) {Serial.print(F("Attempting ")); Serial.print(s); Serial.println(F(" decode:"));};
|
||||||
|
byte REJECTION_MESSAGE(const __FlashStringHelper * s) { Serial.print(F(" Protocol failed because ")); Serial.print(s); Serial.println(F(" wrong.")); return false;};
|
||||||
|
#endif
|
318
hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h
Normal file
318
hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/* IRLib.h from IRLib an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.1 April 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
*
|
||||||
|
* Port to Digispark (size optimization) August 2013
|
||||||
|
* by RC Navy http://p.loussouarn.free.fr
|
||||||
|
*
|
||||||
|
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
|
||||||
|
* That same license applies to this modified version. See his original copyright below.
|
||||||
|
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
|
||||||
|
* My purpose was to reorganize the code to make it easier to add or remove protocols.
|
||||||
|
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
|
||||||
|
* by making them separate classes. That way the receiving aspect can be more black box and implementers
|
||||||
|
* of decoders and senders can just deal with the decoding of protocols.
|
||||||
|
* Also added provisions to make the classes base classes that could be extended with new protocols
|
||||||
|
* which would not require recompiling of the original library nor understanding of its detailed contents.
|
||||||
|
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
|
||||||
|
* Some changes were just my weird programming style. Also extended debugging information added.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRremote
|
||||||
|
* Version 0.1 July, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
|
||||||
|
*
|
||||||
|
* Interrupt code based on NECIRrcv by Joe Knapp
|
||||||
|
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||||
|
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IRLib_h
|
||||||
|
#define IRLib_h
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// The following are compile-time library options.
|
||||||
|
// If you change them, recompile the library.
|
||||||
|
// If DEBUG is defined, a lot of debugging output will be printed during decoding.
|
||||||
|
// If TRACE is defined, some debugging information about the decode will be printed
|
||||||
|
// TEST must be defined for the IRtest unittests to work. It will make some
|
||||||
|
// methods virtual, which will be slightly slower, which is why it is optional.
|
||||||
|
// If DETAILLED_DUMP is defined the dump informations are more detailled
|
||||||
|
// If ALL_IR_PROTOCOL is defined, it allows to discover the protocol used by the IR transmitter (eg, with an arduino UNO)
|
||||||
|
// Once the protocol used by the IR transmitter discovered, set MY_IR_PROTOCOL to PROTO_xxxx and comment ALL_IR_PROTOCOL
|
||||||
|
// this will reduce dramatically the size of the sketch
|
||||||
|
// #define DEBUG
|
||||||
|
// #define TRACE
|
||||||
|
// #define TEST
|
||||||
|
|
||||||
|
//#define USE_IR_SEND
|
||||||
|
//#define DETAILLED_DUMP
|
||||||
|
//#define ALL_IR_PROTOCOL
|
||||||
|
#define MY_IR_PROTOCOL PROTO_NEC /* Set Here the protocol you want to use among the following ones */
|
||||||
|
|
||||||
|
// Only used for testing; can remove virtual for shorter code
|
||||||
|
#ifdef TEST
|
||||||
|
#define VIRTUAL virtual
|
||||||
|
#else
|
||||||
|
#define VIRTUAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RAWBUF 70//100 // Length of raw duration buffer
|
||||||
|
#define USE_TIMER1 1 //should be "1" for timer 1, should be "0" for timer 2
|
||||||
|
|
||||||
|
/* Use one of the protocol in the list below if you want to support a single one */
|
||||||
|
#define PROTO_UNKNOWN 0
|
||||||
|
#define PROTO_NEC 1
|
||||||
|
#define PROTO_SONY 2
|
||||||
|
#define PROTO_RC5 3
|
||||||
|
#define PROTO_RC6 4
|
||||||
|
#define PROTO_PANASONIC_OLD 5
|
||||||
|
#define PROTO_JVC 6
|
||||||
|
#define PROTO_NECX 7
|
||||||
|
#define PROTO_HASH_CODE 8
|
||||||
|
|
||||||
|
enum IRTYPES {UNKNOWN, NEC, SONY, RC5, RC6, PANASONIC_OLD, JVC, NECX, HASH_CODE, LAST_PROTOCOL=HASH_CODE};
|
||||||
|
|
||||||
|
#if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||||
|
const char *Pnames(IRTYPES Type); //Returns a character string that is name of protocol.
|
||||||
|
#else
|
||||||
|
const __FlashStringHelper *Pnames(IRTYPES Type); //Returns a character string that is name of protocol.
|
||||||
|
#endif
|
||||||
|
// Base class for decoding raw results
|
||||||
|
class IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRdecodeBase(void);
|
||||||
|
IRTYPES decode_type; // NEC, SONY, RC5, UNKNOWN etc.
|
||||||
|
unsigned long value; // Decoded value
|
||||||
|
int bits; // Number of bits in decoded value
|
||||||
|
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
|
||||||
|
/*int*/uint8_t rawlen; // Number of records in rawbuf.
|
||||||
|
virtual void Reset(void); // Initializes the decoder
|
||||||
|
virtual bool decode(void); // This base routine always returns false override with your routine
|
||||||
|
bool decodeGeneric(/*int*/int8_t Raw_Count,int Head_Mark,int Head_Space, int Mark_One, int Mark_Zero, int Space_One,int Space_Zero);
|
||||||
|
unsigned long Interval_uSec(int index);
|
||||||
|
virtual void DumpResults (void);
|
||||||
|
void UseExtnBuf(void *P); //Normally uses same rawbuf as IRrecv. Use this to define your own buffer.
|
||||||
|
void copyBuf (IRdecodeBase *source);//copies rawbuf and rawlen from one decoder to another
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_HASH_CODE)
|
||||||
|
class IRdecodeHash: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unsigned long hash;
|
||||||
|
virtual bool decode(void);//made virtual in case you want to substitute your own hash code
|
||||||
|
protected:
|
||||||
|
int compare(unsigned int oldval, unsigned int newval);//used by decodeHash
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
class IRdecodeNEC: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
class IRdecodeSony: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
class IRdecodeRC: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum RCLevel {MARK, SPACE, ERROR};//used by decoders for RC5/RC6
|
||||||
|
// These are called by decode
|
||||||
|
RCLevel getRClevel(int *offset, int *used, int t1);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5)
|
||||||
|
class IRdecodeRC5: public virtual IRdecodeRC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
class IRdecodeRC6: public virtual IRdecodeRC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
class IRdecodePanasonic_Old: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
class IRdecodeJVC: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
class IRdecodeNECx: public virtual IRdecodeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// main class for decoding all supported protocols
|
||||||
|
class IRdecode:
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NEC)
|
||||||
|
public virtual IRdecodeNEC
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_SONY)
|
||||||
|
public virtual IRdecodeSony
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC5)
|
||||||
|
public virtual IRdecodeRC5
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_RC6)
|
||||||
|
public virtual IRdecodeRC6
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_PANASONIC_OLD)
|
||||||
|
public virtual IRdecodePanasonic_Old
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_JVC)
|
||||||
|
public virtual IRdecodeJVC
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
#if defined(ALL_IR_PROTOCOL) || (MY_IR_PROTOCOL == PROTO_NECX)
|
||||||
|
public virtual IRdecodeNECx
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool decode(void); // Calls each decode routine individually
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef USE_IR_SEND
|
||||||
|
//Base class for sending signals
|
||||||
|
class IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRsendBase() ;
|
||||||
|
void sendGeneric(unsigned long data, int Num_Bits, int Head_Mark, int Head_Space, int Mark_One, int Mark_Zero, int Space_One, int Space_Zero, int mHz, bool Stop_Bits);
|
||||||
|
protected:
|
||||||
|
void enableIROut(int khz);
|
||||||
|
VIRTUAL void mark(int usec);
|
||||||
|
VIRTUAL void space(int usec);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendNEC: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendSony: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data, int nbits);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendRaw: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned int buf[], int len, int hz);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendRC5: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendRC6: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data, int nbits);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendPanasonic_Old: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendJVC: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data, bool First);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsendNECx: public virtual IRsendBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(unsigned long data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRsend:
|
||||||
|
public virtual IRsendNEC,
|
||||||
|
public virtual IRsendSony,
|
||||||
|
public virtual IRsendRaw,
|
||||||
|
public virtual IRsendRC5,
|
||||||
|
public virtual IRsendRC6,
|
||||||
|
public virtual IRsendPanasonic_Old,
|
||||||
|
public virtual IRsendJVC,
|
||||||
|
public virtual IRsendNECx
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void send(IRTYPES Type, unsigned long data, int nbits);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// main class for receiving IR
|
||||||
|
class IRrecv
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRrecv(int recvpin);
|
||||||
|
void No_Output(void);
|
||||||
|
void blink13(int blinkflag);
|
||||||
|
bool GetResults(IRdecodeBase *decoder);
|
||||||
|
void enableIRIn();
|
||||||
|
void resume();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some useful constants
|
||||||
|
// Decoded value for NEC when a repeat code is received
|
||||||
|
#define REPEAT 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
|
#endif //IRLib_h
|
83
hardware/digistump/avr/libraries/DigisparkIRLib/IRLibMatch.h
Normal file
83
hardware/digistump/avr/libraries/DigisparkIRLib/IRLibMatch.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* IRLibMatch.h from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
*
|
||||||
|
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
|
||||||
|
* That same license applies to this modified version. See his original copyright below.
|
||||||
|
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
|
||||||
|
* My purpose was to reorganize the code to make it easier to add or remove protocols.
|
||||||
|
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
|
||||||
|
* by making them separate classes. That way the receiving aspect can be more black box and implementers
|
||||||
|
* of decoders and senders can just deal with the decoding of protocols.
|
||||||
|
* Also added provisions to make the classes base classes that could be extended with new protocols
|
||||||
|
* which would not require recompiling of the original library nor understanding of its detailed contents.
|
||||||
|
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
|
||||||
|
* Some changes were just my weird programming style. Also extended debugging information added.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRremote
|
||||||
|
* Version 0.1 July, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
|
||||||
|
*
|
||||||
|
* Interrupt code based on NECIRrcv by Joe Knapp
|
||||||
|
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||||
|
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IRLibMatch_h
|
||||||
|
#define IRLibMatch_h
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is some miscellaneous definition that is needed by the decoding routines.
|
||||||
|
* You need not include this file unless you are creating custom decode routines
|
||||||
|
* which will require these macros and definitions. Even if you include it, you probably
|
||||||
|
* don't need to be intimately familiar with the internal details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Marks tend to be 100us too long, and spaces 100us too short
|
||||||
|
// when received due to sensor lag.
|
||||||
|
#define MARK_EXCESS 100
|
||||||
|
#define USECPERTICK 50 // microseconds per clock interrupt tick
|
||||||
|
#if 0
|
||||||
|
#define TOLERANCE 25 // percent tolerance in measurements
|
||||||
|
#define TICKS_LOW(us) (int) (((us)*(1.0 - TOLERANCE/100.)/USECPERTICK))
|
||||||
|
#define TICKS_HIGH(us) (int) (((us)*(1.0 + TOLERANCE/100.)/USECPERTICK + 1))
|
||||||
|
#else
|
||||||
|
#define TICKS_LOW(us) (((us) - (us>>2))/USECPERTICK)
|
||||||
|
#define TICKS_HIGH(us) (((us) + (us>>2))/USECPERTICK)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int MATCH(int measured, int desired);
|
||||||
|
int MATCH_MARK(int measured_ticks, int desired_us);
|
||||||
|
int MATCH_SPACE(int measured_ticks, int desired_us);
|
||||||
|
#else
|
||||||
|
#define MATCH(measured_ticks, desired_us) ((measured_ticks) >= TICKS_LOW(desired_us) && (measured_ticks) <= TICKS_HIGH(desired_us))
|
||||||
|
#define MATCH_MARK(measured_ticks, desired_us) MATCH(measured_ticks, (desired_us) + MARK_EXCESS)
|
||||||
|
#define MATCH_SPACE(measured_ticks, desired_us) MATCH((measured_ticks), (desired_us) - MARK_EXCESS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TRACE
|
||||||
|
void ATTEMPT_MESSAGE(const __FlashStringHelper * s);
|
||||||
|
byte REJECTION_MESSAGE(const __FlashStringHelper * s);
|
||||||
|
#define RAW_COUNT_ERROR REJECTION_MESSAGE(F("number of raw samples"));
|
||||||
|
#define HEADER_MARK_ERROR REJECTION_MESSAGE(F("header mark"));
|
||||||
|
#define HEADER_SPACE_ERROR REJECTION_MESSAGE(F("header space"));
|
||||||
|
#define DATA_MARK_ERROR REJECTION_MESSAGE(F("data mark"));
|
||||||
|
#define DATA_SPACE_ERROR REJECTION_MESSAGE(F("data space"));
|
||||||
|
#define TRAILER_BIT_ERROR REJECTION_MESSAGE(F("RC5/RC6 trailer bit length"));
|
||||||
|
#else
|
||||||
|
#define ATTEMPT_MESSAGE(s)
|
||||||
|
#define REJECTION_MESSAGE(s) false
|
||||||
|
#define RAW_COUNT_ERROR false
|
||||||
|
#define HEADER_MARK_ERROR false
|
||||||
|
#define HEADER_SPACE_ERROR false
|
||||||
|
#define DATA_MARK_ERROR false
|
||||||
|
#define DATA_SPACE_ERROR false
|
||||||
|
#define TRAILER_BIT_ERROR false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //IRLibMatch_h
|
380
hardware/digistump/avr/libraries/DigisparkIRLib/IRLibTimer.h
Normal file
380
hardware/digistump/avr/libraries/DigisparkIRLib/IRLibTimer.h
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
/* IRLibTimer.h from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
*
|
||||||
|
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
|
||||||
|
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
|
||||||
|
* That same license applies to this modified version. See his original copyright below.
|
||||||
|
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
|
||||||
|
* My purpose was to reorganize the code to make it easier to add or remove protocols.
|
||||||
|
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
|
||||||
|
* by making them separate classes. That way the receiving aspect can be more black box and implementers
|
||||||
|
* of decoders and senders can just deal with the decoding of protocols.
|
||||||
|
* Also added provisions to make the classes base classes that could be extended with new protocols
|
||||||
|
* which would not require recompiling of the original library nor understanding of its detailed contents.
|
||||||
|
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
|
||||||
|
* Some changes were just my weird programming style. Also extended debugging information added.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRremote
|
||||||
|
* Version 0.1 July, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
|
||||||
|
*
|
||||||
|
* Interrupt code based on NECIRrcv by Joe Knapp
|
||||||
|
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||||
|
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||||
|
*/
|
||||||
|
/* This file defines which timer you wish to use. Different versions of Arduino and related boards
|
||||||
|
* have different timers available to them. For various reasons you might want to use something other than
|
||||||
|
* timer 2. Some boards do not have timer 2. This attempts to detect which type of board you are using.
|
||||||
|
* You need uncomment wish to use on your board. You probably will not need to include this in your
|
||||||
|
* program unless you want to see which timer is being used and which board has been detected.
|
||||||
|
* This information came from an alternative fork of the original Ken Shirriff library found here
|
||||||
|
* https://github.com/TKJElectronics/Arduino-IRremote
|
||||||
|
*/
|
||||||
|
#ifndef IRLibTimer_h
|
||||||
|
#define IRLibTimer_h
|
||||||
|
|
||||||
|
#if defined(ARDUINO) && ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef F_CPU
|
||||||
|
#define SYSCLOCK F_CPU // main Arduino clock
|
||||||
|
#else
|
||||||
|
#define SYSCLOCK 16000000 // main Arduino clock
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Arduino Mega
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
//#define IR_USE_TIMER1 // tx = pin 11
|
||||||
|
#define IR_USE_TIMER2 // tx = pin 9
|
||||||
|
//#define IR_USE_TIMER3 // tx = pin 5
|
||||||
|
//#define IR_USE_TIMER4 // tx = pin 6
|
||||||
|
//#define IR_USE_TIMER5 // tx = pin 46
|
||||||
|
|
||||||
|
// Teensy 1.0
|
||||||
|
#elif defined(__AVR_AT90USB162__)
|
||||||
|
#define IR_USE_TIMER1 // tx = pin 17
|
||||||
|
|
||||||
|
// Teensy 2.0 versus Leonardo
|
||||||
|
// These boards use the same chip but the pinouts are different.
|
||||||
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
#ifdef CORE_TEENSY
|
||||||
|
// it's Teensy 2.0
|
||||||
|
//#define IR_USE_TIMER1 // tx = pin 14
|
||||||
|
//#define IR_USE_TIMER3 // tx = pin 9
|
||||||
|
#define IR_USE_TIMER4_HS // tx = pin 10
|
||||||
|
#else
|
||||||
|
// it's probably Leonardo
|
||||||
|
#define IR_USE_TIMER1 // tx = pin 9
|
||||||
|
//#define IR_USE_TIMER3 // tx = pin 5
|
||||||
|
//#define IR_USE_TIMER4_HS // tx = pin 13
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Teensy++ 1.0 & 2.0
|
||||||
|
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||||
|
//#define IR_USE_TIMER1 // tx = pin 25
|
||||||
|
#define IR_USE_TIMER2 // tx = pin 1
|
||||||
|
//#define IR_USE_TIMER3 // tx = pin 16
|
||||||
|
|
||||||
|
// Sanguino
|
||||||
|
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||||
|
//#define IR_USE_TIMER1 // tx = pin 13
|
||||||
|
#define IR_USE_TIMER2 // tx = pin 14
|
||||||
|
|
||||||
|
// Tested with ATtiny85, presumably works with ATtiny45, possibly with ATtiny25
|
||||||
|
// The attiny core uses Timer 0 for millis() etc., so using timer 1 is advisable
|
||||||
|
// for IR out. Pin 4 also conveniently is not used in any role for ISP.
|
||||||
|
// The Arduino-tiny core uses Timer 1 for millis(), so using timer 0 is advisable
|
||||||
|
// for IR out. Pin 0 is used by default for IR out in the Tinyspark IR shield, but
|
||||||
|
// is not usable for PWM waveforms where the frequency, not just the duty cycle,
|
||||||
|
// needs to be controlled.
|
||||||
|
#elif defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||||
|
// #define IR_USE_TIMER1_TINY // tx = pin 4 (OC1B)
|
||||||
|
#define IR_USE_TIMER0 // tx = pin 1 (OC0B)
|
||||||
|
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
|
||||||
|
#else
|
||||||
|
//#define IR_USE_TIMER1 // tx = pin 9
|
||||||
|
#define IR_USE_TIMER2 // tx = pin 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer0 (8 bits). Tested on ATtiny85, may also work on other
|
||||||
|
// processors, but most of them use Timer 0 to keep system time
|
||||||
|
#if defined(IR_USE_TIMER0)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR0A |= _BV(COM0B1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR0A &= ~(_BV(COM0B1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK = _BV(OCIE0A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER0_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR0A = _BV(WGM00); \
|
||||||
|
TCCR0B = _BV(WGM02) | _BV(CS00); \
|
||||||
|
OCR0A = pwmval; \
|
||||||
|
OCR0B = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
|
||||||
|
#if (TIMER_COUNT_TOP < 256)
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR0A = _BV(WGM01); \
|
||||||
|
TCCR0B = _BV(CS00); \
|
||||||
|
OCR0A = TIMER_COUNT_TOP; \
|
||||||
|
TCNT0 = 0; \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR0A = _BV(WGM01); \
|
||||||
|
TCCR0B = _BV(CS01); \
|
||||||
|
OCR0A = TIMER_COUNT_TOP / 8; \
|
||||||
|
TCNT0 = 0; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
#if defined(CORE_OC0A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC0B_PIN
|
||||||
|
#else
|
||||||
|
#define TIMER_PWM_PIN 1 /* Attiny core */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// defines for timer2 (8 bits)
|
||||||
|
#elif defined(IR_USE_TIMER2)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK2 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER2_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR2A = _BV(WGM20); \
|
||||||
|
TCCR2B = _BV(WGM22) | _BV(CS20); \
|
||||||
|
OCR2A = pwmval; \
|
||||||
|
OCR2B = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
|
||||||
|
#if (TIMER_COUNT_TOP < 256)
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR2A = _BV(WGM21); \
|
||||||
|
TCCR2B = _BV(CS20); \
|
||||||
|
OCR2A = TIMER_COUNT_TOP; \
|
||||||
|
TCNT2 = 0; \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR2A = _BV(WGM21); \
|
||||||
|
TCCR2B = _BV(CS21); \
|
||||||
|
OCR2A = TIMER_COUNT_TOP / 8; \
|
||||||
|
TCNT2 = 0; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
#if defined(CORE_OC2B_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC2B_PIN /* Teensy */
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER_PWM_PIN 9 /* Arduino Mega */
|
||||||
|
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||||
|
#define TIMER_PWM_PIN 14 /* Sanguino */
|
||||||
|
#else
|
||||||
|
#define TIMER_PWM_PIN 3 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer1 (16 bits)
|
||||||
|
#elif defined(IR_USE_TIMER1)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK1 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER1_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR1A = _BV(WGM11); \
|
||||||
|
TCCR1B = _BV(WGM13) | _BV(CS10); \
|
||||||
|
ICR1 = pwmval; \
|
||||||
|
OCR1A = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR1A = 0; \
|
||||||
|
TCCR1B = _BV(WGM12) | _BV(CS10); \
|
||||||
|
OCR1A = SYSCLOCK * USECPERTICK / 1000000; \
|
||||||
|
TCNT1 = 0; \
|
||||||
|
})
|
||||||
|
#if defined(CORE_OC1A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC1A_PIN /* Teensy */
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER_PWM_PIN 11 /* Arduino Mega */
|
||||||
|
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||||
|
#define TIMER_PWM_PIN 13 /* Sanguino */
|
||||||
|
#else
|
||||||
|
#define TIMER_PWM_PIN 9 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer3 (16 bits)
|
||||||
|
#elif defined(IR_USE_TIMER3)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK3 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER3_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR3A = _BV(WGM31); \
|
||||||
|
TCCR3B = _BV(WGM33) | _BV(CS30); \
|
||||||
|
ICR3 = pwmval; \
|
||||||
|
OCR3A = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR3A = 0; \
|
||||||
|
TCCR3B = _BV(WGM32) | _BV(CS30); \
|
||||||
|
OCR3A = SYSCLOCK * USECPERTICK / 1000000; \
|
||||||
|
TCNT3 = 0; \
|
||||||
|
})
|
||||||
|
#if defined(CORE_OC3A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC3A_PIN /* Teensy */
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER_PWM_PIN 5 /* Arduino Mega */
|
||||||
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
#define TIMER_PWM_PIN 5 /* Arduino Leonardo note already checked for Teensy */
|
||||||
|
#else
|
||||||
|
#error "Please add OC3A pin number here\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer4 (10 bits, high speed option)
|
||||||
|
#elif defined(IR_USE_TIMER4_HS)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER4_OVF_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR4A = (1<<PWM4A); \
|
||||||
|
TCCR4B = _BV(CS40); \
|
||||||
|
TCCR4C = 0; \
|
||||||
|
TCCR4D = (1<<WGM40); \
|
||||||
|
TCCR4E = 0; \
|
||||||
|
TC4H = pwmval >> 8; \
|
||||||
|
OCR4C = pwmval; \
|
||||||
|
TC4H = (pwmval / 3) >> 8; \
|
||||||
|
OCR4A = (pwmval / 3) & 255; \
|
||||||
|
})
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR4A = 0; \
|
||||||
|
TCCR4B = _BV(CS40); \
|
||||||
|
TCCR4C = 0; \
|
||||||
|
TCCR4D = 0; \
|
||||||
|
TCCR4E = 0; \
|
||||||
|
TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \
|
||||||
|
OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \
|
||||||
|
TC4H = 0; \
|
||||||
|
TCNT4 = 0; \
|
||||||
|
})
|
||||||
|
#if defined(CORE_OC4A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */
|
||||||
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
#define TIMER_PWM_PIN 13 /*Leonardo*/
|
||||||
|
#else
|
||||||
|
#error "Please add OC4A pin number here\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer4 (16 bits)
|
||||||
|
#elif defined(IR_USE_TIMER4)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER4_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR4A = _BV(WGM41); \
|
||||||
|
TCCR4B = _BV(WGM43) | _BV(CS40); \
|
||||||
|
ICR4 = pwmval; \
|
||||||
|
OCR4A = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR4A = 0; \
|
||||||
|
TCCR4B = _BV(WGM42) | _BV(CS40); \
|
||||||
|
OCR4A = SYSCLOCK * USECPERTICK / 1000000; \
|
||||||
|
TCNT4 = 0; \
|
||||||
|
})
|
||||||
|
#if defined(CORE_OC4A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC4A_PIN
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER_PWM_PIN 6 /* Arduino Mega */
|
||||||
|
#else
|
||||||
|
#error "Please add OC4A pin number here\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for timer5 (16 bits)
|
||||||
|
#elif defined(IR_USE_TIMER5)
|
||||||
|
#define TIMER_RESET
|
||||||
|
#define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1))
|
||||||
|
#define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1)))
|
||||||
|
#define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A))
|
||||||
|
#define TIMER_DISABLE_INTR (TIMSK5 = 0)
|
||||||
|
#define TIMER_INTR_NAME TIMER5_COMPA_vect
|
||||||
|
#define TIMER_CONFIG_KHZ(val) ({ \
|
||||||
|
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
|
||||||
|
TCCR5A = _BV(WGM51); \
|
||||||
|
TCCR5B = _BV(WGM53) | _BV(CS50); \
|
||||||
|
ICR5 = pwmval; \
|
||||||
|
OCR5A = pwmval / 3; \
|
||||||
|
})
|
||||||
|
#define TIMER_CONFIG_NORMAL() ({ \
|
||||||
|
TCCR5A = 0; \
|
||||||
|
TCCR5B = _BV(WGM52) | _BV(CS50); \
|
||||||
|
OCR5A = SYSCLOCK * USECPERTICK / 1000000; \
|
||||||
|
TCNT5 = 0; \
|
||||||
|
})
|
||||||
|
#if defined(CORE_OC5A_PIN)
|
||||||
|
#define TIMER_PWM_PIN CORE_OC5A_PIN
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER_PWM_PIN 46 /* Arduino Mega */
|
||||||
|
#else
|
||||||
|
#error "Please add OC5A pin number here\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else // unknown timer
|
||||||
|
#error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// defines for blinking the LED
|
||||||
|
#if defined(CORE_LED0_PIN)
|
||||||
|
#define BLINKLED CORE_LED0_PIN
|
||||||
|
#define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH))
|
||||||
|
#define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW))
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define BLINKLED 13
|
||||||
|
#define BLINKLED_ON() (PORTB |= B10000000)
|
||||||
|
#define BLINKLED_OFF() (PORTB &= B01111111)
|
||||||
|
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||||
|
#define BLINKLED 0
|
||||||
|
#define BLINKLED_ON() (PORTD |= B00000001)
|
||||||
|
#define BLINKLED_OFF() (PORTD &= B11111110)
|
||||||
|
#elif defined(__AVR_ATmega32U4__) && defined(IR_USE_TIMER4_HS)
|
||||||
|
//Leonardo not teensy. When using Timer4 output is on 13. Therefore disabling blink LED
|
||||||
|
//You can add an LED elsewhere if you want
|
||||||
|
#define BLINKLED 1
|
||||||
|
#define BLINKLED_ON() (digitalWrite(BLINKLED, HIGH))
|
||||||
|
#define BLINKLED_OFF() (digitalWrite(BLINKLED, LOW))
|
||||||
|
#else
|
||||||
|
#define BLINKLED 13
|
||||||
|
#define BLINKLED_ON() (PORTB |= B00100000)
|
||||||
|
#define BLINKLED_OFF() (PORTB &= B11011111)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //IRLibTimer_h
|
BIN
hardware/digistump/avr/libraries/DigisparkIRLib/LICENSE.txt
Normal file
BIN
hardware/digistump/avr/libraries/DigisparkIRLib/LICENSE.txt
Normal file
Binary file not shown.
70
hardware/digistump/avr/libraries/DigisparkIRLib/README.txt
Normal file
70
hardware/digistump/avr/libraries/DigisparkIRLib/README.txt
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
Version 1.1 april 2013
|
||||||
|
Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
|
||||||
|
This library is a major rewrite of IRemote by Ken Shirriff which was covered
|
||||||
|
by GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make
|
||||||
|
modified versions. That same license applies to this modified version. See
|
||||||
|
his original copyright below.
|
||||||
|
|
||||||
|
The latest Ken Shirriff code can be found at
|
||||||
|
https://github.com/shirriff/Arduino-IRremote
|
||||||
|
|
||||||
|
My purpose was to reorganize the code to make it easier to add or remove
|
||||||
|
protocols. As a result I have separated the act of receiving a set of raw timing
|
||||||
|
codes from the act of decoding them by making them separate classes. That way
|
||||||
|
the receiving aspect can be more black box and implementers of decoders and
|
||||||
|
senders can just deal with the decoding of protocols.
|
||||||
|
|
||||||
|
Also added provisions to make the classes base classes that could be extended
|
||||||
|
with new protocols which would not require recompiling of the original library nor
|
||||||
|
understanding of its detailed contents. Some of the changes were made to reduce
|
||||||
|
code size such as unnecessary use of long versus bool. Some changes were just my
|
||||||
|
weird programming style. Also extended debugging information added.
|
||||||
|
|
||||||
|
IRremote
|
||||||
|
Version 0.1 July, 2009
|
||||||
|
Copyright 2009 Ken Shirriff
|
||||||
|
For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm
|
||||||
|
http://arcfn.com
|
||||||
|
|
||||||
|
Interrupt code based on NECIRrcv by Joe Knapp
|
||||||
|
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||||
|
Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||||
|
|
||||||
|
****************************************************
|
||||||
|
The package contains:
|
||||||
|
IRLib.cpp Code for the library written in object C++
|
||||||
|
IRLib.h Header file which you will include in your sketch
|
||||||
|
IRLibMatch.h Match macros used internally. Need not include this unless you implement
|
||||||
|
your own protocols
|
||||||
|
iRLibTimer.h Attempts to detect type of Arduino board and allows you to modify which
|
||||||
|
interrupt timer you will use. Defaults to timer 2 as did the original KS
|
||||||
|
library. Alternate board and timer information based on a fork of the
|
||||||
|
original KS library. That for can be found here.
|
||||||
|
https://github.com/TKJElectronics/Arduino-IRremote
|
||||||
|
|
||||||
|
Note: there is no "IRremoteInt.h" header as in the original library. Those values were
|
||||||
|
moved elsewhere.
|
||||||
|
|
||||||
|
The examples directory contains:
|
||||||
|
IRhashdecode Demonstrates hash decoder.
|
||||||
|
IRrecord Recording incoming signal and play it back when a character is sent
|
||||||
|
through the serial console. By using the console you no longer need
|
||||||
|
to wire up a pushbutton to run this code.
|
||||||
|
IRrecvDump Receives a code, attempts to decode it, produces well formatted
|
||||||
|
output of the results using the new "dump" method.
|
||||||
|
IRsendDemo Simplistic demo to send a Sony DVD power signal every time a
|
||||||
|
character is received from the serial monitor.
|
||||||
|
IRsendJVC Demonstrates sending a code using JVC protocol which is tricky.
|
||||||
|
Samsung36 Demonstrates how to expand the library without recompiling it.
|
||||||
|
Also demonstrates how to handle codes that are longer than 32 bits.
|
||||||
|
IRservo Demonstrates controlling a servo motor using an IR remote
|
||||||
|
IRserial_remote Demonstrates a Python application that runs on your PC and sends
|
||||||
|
serial data to Arduino which in turn sends IR remote signals.
|
||||||
|
Note: I did not port any of the other demo sketches although I may add IRTest later.
|
||||||
|
****************************************************
|
||||||
|
The library handles the following protocols:
|
||||||
|
NEC, Sony, RC5, RC6, Raw all of which were supported in the KS version.
|
||||||
|
Additionally added Panasonic_Old, JVC, NECx.
|
||||||
|
Also added KS hash code routines which he released separately.
|
@ -0,0 +1,84 @@
|
|||||||
|
#include <IRLib.h> // In {path_of_installation}/Digispark-Arduino-1.0.x/libraries/DigisparkIRLib/IRLib.h, set MY_PROTOCOL to NEC, SONY, RC5 to find the one used by your own IR Remote Control
|
||||||
|
#include <DigiUSB.h> // In {path_of_installation}/Digispark-Arduino-1.0.x/libraries/DigisparkUSB/DigiUSB.h, RING_BUFFER_SIZE shall be set to 32
|
||||||
|
/*
|
||||||
|
_____ ____ __ _ ____ _ _ _ _
|
||||||
|
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
|
||||||
|
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
||||||
|
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
||||||
|
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
||||||
|
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013
|
||||||
|
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
|
*************************************************
|
||||||
|
* Optimized <IRLib> library Dump Demo *
|
||||||
|
*************************************************
|
||||||
|
|
||||||
|
This sketch allows you to discover the protocol used by your own IR Remote Control and the code of each key when pressed.
|
||||||
|
You will see the decoded key codes in the DigiUSB console.
|
||||||
|
|
||||||
|
IMPORTANT:
|
||||||
|
=========
|
||||||
|
- In {path_of_installation}/Digispark-Arduino-1.0.x/libraries/DigisparkIRLib/IRLib.h, set MY_PROTOCOL to NEC, SONY, RC5 to find the protocol used by your own IR Remote Control
|
||||||
|
- In {path_of_installation}/Digispark-Arduino-1.0.x/libraries/DigisparkUSB/DigiUSB.h, RING_BUFFER_SIZE shall be set to 32
|
||||||
|
|
||||||
|
Sensor wiring: (Warning: the wiring may vary depending of the model of IR sensor)
|
||||||
|
=============
|
||||||
|
.-------.
|
||||||
|
| ___ |
|
||||||
|
| / \ | InfraRed
|
||||||
|
| \___/ | Sensor
|
||||||
|
| |
|
||||||
|
'+--+--+'
|
||||||
|
| | | 100
|
||||||
|
P5 <----' | '--+---###--- +5V
|
||||||
|
| |
|
||||||
|
| '==='4.7uF
|
||||||
|
| |
|
||||||
|
'--+--'
|
||||||
|
|
|
||||||
|
GND
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LED_PIN 1
|
||||||
|
#define IR_RX_PIN 5
|
||||||
|
|
||||||
|
#define BUTTON_OFF 0xF740BF //Set here the OFF code for the built-in LED when determined
|
||||||
|
#define BUTTON_ON 0xF7C03F //Set here the ON code for the built-in LED when determined
|
||||||
|
|
||||||
|
IRrecv My_Receiver(IR_RX_PIN);//Receive on pin IR_RX_PIN
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
DigiUSB.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if(My_Receiver.GetResults(&My_Decoder))
|
||||||
|
{
|
||||||
|
My_Decoder.decode();
|
||||||
|
switch(My_Decoder.value)
|
||||||
|
{
|
||||||
|
case BUTTON_OFF:
|
||||||
|
digitalWrite(LED_PIN, LOW);
|
||||||
|
break;
|
||||||
|
case BUTTON_ON:
|
||||||
|
digitalWrite(LED_PIN, HIGH);
|
||||||
|
break;
|
||||||
|
default:break;
|
||||||
|
}
|
||||||
|
My_Receiver.resume();
|
||||||
|
DigiUSB.println(My_Decoder.value, HEX);
|
||||||
|
}
|
||||||
|
if(DigiUSB.available())
|
||||||
|
{
|
||||||
|
DigiUSB.read();
|
||||||
|
}
|
||||||
|
DigiUSB.refresh();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,201 @@
|
|||||||
|
#include <TinySoftPwm.h>
|
||||||
|
#include <IRLib.h>
|
||||||
|
/*
|
||||||
|
_____ ____ __ _ ____ _ _ _ _
|
||||||
|
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
|
||||||
|
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
||||||
|
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
||||||
|
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
||||||
|
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013
|
||||||
|
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
|
*************************************************
|
||||||
|
* Optimized <IRLib> library Controller Demo *
|
||||||
|
*************************************************
|
||||||
|
|
||||||
|
This sketch allows you to use the Digispark as an IR RGB Controller.
|
||||||
|
This sketch is designed to used low cost 24 keys IR Remote Control for RGB strip LED,
|
||||||
|
but you can adapt it to your own IR Remote Control.
|
||||||
|
|
||||||
|
Sensor wiring: (Warning: the wiring may vary depending of the model of IR sensor)
|
||||||
|
=============
|
||||||
|
.-------.
|
||||||
|
| ___ |
|
||||||
|
| / \ | InfraRed
|
||||||
|
| \___/ | Sensor
|
||||||
|
| |
|
||||||
|
'+--+--+'
|
||||||
|
| | | 100
|
||||||
|
P5 <----' | '--+---###--- +5V
|
||||||
|
| |
|
||||||
|
| '==='4.7uF
|
||||||
|
| |
|
||||||
|
'--+--'
|
||||||
|
|
|
||||||
|
GND
|
||||||
|
|
||||||
|
/* P0, P1 and P2 shall be declared in Digispark-Arduino-1.0.x/libraries/TinySoftPwm.h */
|
||||||
|
#define LED_GREEN_PIN 0
|
||||||
|
#define LED_RED_PIN 1
|
||||||
|
#define LED_BLUE_PIN 2
|
||||||
|
|
||||||
|
#define IR_RX_PIN 5
|
||||||
|
|
||||||
|
#define CODE_OFF 0xF740BF
|
||||||
|
#define CODE_ON 0xF7C03F
|
||||||
|
#define CODE_BRIGHT_MINUS 0xF7807F
|
||||||
|
#define CODE_BRIGHT_PLUS 0xF700FF
|
||||||
|
|
||||||
|
#define CODE_FLASH 0xF7D02F
|
||||||
|
#define CODE_STROBE 0xF7F00F
|
||||||
|
#define CODE_FADE 0xF7C837
|
||||||
|
#define CODE_SMOOTH 0xF7E817
|
||||||
|
|
||||||
|
#define CODE_RED 0xF720DF
|
||||||
|
#define CODE_GREEN 0xF7A05F
|
||||||
|
#define CODE_BLUE 0xF7609F
|
||||||
|
#define CODE_WHITE 0xF7E01F
|
||||||
|
|
||||||
|
#define CODE_ORANGE 0xF710EF
|
||||||
|
#define CODE_ORANGE_LIGTH 0xF730CF
|
||||||
|
#define CODE_BROWN 0xF708F7
|
||||||
|
#define CODE_YELLOW 0xF728D7
|
||||||
|
|
||||||
|
#define CODE_GREEN_LIGTH 0xF7906F
|
||||||
|
#define CODE_GREEN_BLUE1 0xF7B04F
|
||||||
|
#define CODE_GREEN_BLUE2 0xF78877
|
||||||
|
#define CODE_GREEN_BLUE3 0xF7A857
|
||||||
|
|
||||||
|
#define CODE_BLUE_LIGTH 0xF750AF
|
||||||
|
#define CODE_PURPLE_DARK 0xF7708F
|
||||||
|
#define CODE_PURPLE_LIGTH 0xF748B7
|
||||||
|
#define CODE_PINK 0xF76897
|
||||||
|
|
||||||
|
#define BRIGTH_STEP 10
|
||||||
|
#define CODE_REPEAT 0xFFFFFFFF
|
||||||
|
|
||||||
|
IRrecv My_Receiver(IR_RX_PIN);//Receive on pin IR_RX_PIN
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
|
||||||
|
uint8_t PwmRed=0, PwmGreen=0, PwmBlue=0;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
pinMode(LED_RED_PIN, OUTPUT);
|
||||||
|
TinySoftPwm_begin(255,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
static uint32_t StartUs=micros(), LastIrCode=0;
|
||||||
|
|
||||||
|
if(My_Receiver.GetResults(&My_Decoder))
|
||||||
|
{
|
||||||
|
My_Decoder.decode();
|
||||||
|
if(My_Decoder.value==REPEAT && LastIrCode)
|
||||||
|
{
|
||||||
|
My_Decoder.value=LastIrCode;
|
||||||
|
}
|
||||||
|
switch(My_Decoder.value)
|
||||||
|
{
|
||||||
|
case CODE_BRIGHT_MINUS:
|
||||||
|
Tune(&PwmRed, -BRIGTH_STEP);
|
||||||
|
Tune(&PwmGreen, -BRIGTH_STEP);
|
||||||
|
Tune(&PwmBlue, -BRIGTH_STEP);
|
||||||
|
LastIrCode=CODE_BRIGHT_MINUS;
|
||||||
|
break;
|
||||||
|
case CODE_BRIGHT_PLUS:
|
||||||
|
if(PwmRed) Tune(&PwmRed, BRIGTH_STEP);
|
||||||
|
if(PwmGreen) Tune(&PwmGreen, BRIGTH_STEP);
|
||||||
|
if(PwmBlue) Tune(&PwmBlue, BRIGTH_STEP);
|
||||||
|
LastIrCode=CODE_BRIGHT_PLUS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LastIrCode=0; /* No repeat for the following codes */
|
||||||
|
switch(My_Decoder.value)
|
||||||
|
{
|
||||||
|
case CODE_OFF:
|
||||||
|
RGB(0x00, 0x00, 0x00);
|
||||||
|
break;
|
||||||
|
case CODE_ON:
|
||||||
|
RGB(0x7A, 0x00, 0xBF);
|
||||||
|
break;
|
||||||
|
case CODE_RED: RGB(0xFF, 0x00, 0x00);break;
|
||||||
|
case CODE_GREEN: RGB(0x00, 0xFF, 0x00);break;
|
||||||
|
case CODE_BLUE: RGB(0x00, 0x00, 0xFF);break;
|
||||||
|
case CODE_WHITE: RGB(0xFF, 0xFF, 0xFF);break;
|
||||||
|
|
||||||
|
case CODE_ORANGE: RGB(0xFF, 0x7F, 0x00); break;
|
||||||
|
case CODE_ORANGE_LIGTH: RGB(0xFF, 0xAA, 0x00); break;
|
||||||
|
case CODE_BROWN: RGB(0xFF, 0xD4, 0x00); break;
|
||||||
|
case CODE_YELLOW: RGB(0xFF, 0xFF, 0x00); break;
|
||||||
|
|
||||||
|
case CODE_GREEN_LIGTH: RGB(0x00, 0xFF, 0xAA); break;
|
||||||
|
case CODE_GREEN_BLUE1: RGB(0x00, 0xFF, 0xFF); break;
|
||||||
|
case CODE_GREEN_BLUE2: RGB(0x00, 0xAA, 0xFF); break;
|
||||||
|
case CODE_GREEN_BLUE3: RGB(0x00, 0x55, 0xFF); break;
|
||||||
|
|
||||||
|
case CODE_BLUE_LIGTH: RGB(0x00, 0x00, 0x80); break;
|
||||||
|
case CODE_PURPLE_DARK: RGB(0x3F, 0x00, 0x80); break;
|
||||||
|
case CODE_PURPLE_LIGTH: RGB(0x7A, 0x00, 0xBF); break;
|
||||||
|
case CODE_PINK: RGB(0xFF, 0x00, 0xFF); break;
|
||||||
|
|
||||||
|
case CODE_FLASH: /* to be implemented */break;
|
||||||
|
case CODE_STROBE: /* to be implemented */break;
|
||||||
|
case CODE_FADE: /* to be implemented */break;
|
||||||
|
case CODE_SMOOTH: /* to be implemented */break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
My_Receiver.resume();
|
||||||
|
TinySoftPwm_analogWrite(LED_RED_PIN, GammaCorrection(PwmRed));
|
||||||
|
TinySoftPwm_analogWrite(LED_GREEN_PIN, GammaCorrection(PwmGreen));
|
||||||
|
TinySoftPwm_analogWrite(LED_BLUE_PIN, GammaCorrection(PwmBlue));
|
||||||
|
}
|
||||||
|
/***********************************************************/
|
||||||
|
/* Call TinySoftPwm_process() with a period of 60 us */
|
||||||
|
/* The PWM frequency = 255 x 60 # 15 ms -> F # 65Hz */
|
||||||
|
/* 255 is the first argument passed to TinySoftPwm_begin() */
|
||||||
|
/***********************************************************/
|
||||||
|
if((micros() - StartUs) >= 60)
|
||||||
|
{
|
||||||
|
/* We arrived here every 60 microseconds */
|
||||||
|
StartUs=micros();
|
||||||
|
TinySoftPwm_process(); /* This function shall be called periodically (like here, based on micros(), or in a timer ISR) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RGB(uint8_t Red, uint8_t Green, uint8_t Blue)
|
||||||
|
{
|
||||||
|
PwmRed=Red;
|
||||||
|
PwmGreen=Green;
|
||||||
|
PwmBlue=Blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GammaCorrection(uint8_t Pwm)
|
||||||
|
{
|
||||||
|
return((Pwm*Pwm)>>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tune(uint8_t* Color, int8_t Offset)
|
||||||
|
{
|
||||||
|
if (Offset > 0) {
|
||||||
|
if ( *Color + Offset <= 255) {
|
||||||
|
*Color += Offset;
|
||||||
|
} else {
|
||||||
|
*Color = 255;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*Color + Offset >= 0) {
|
||||||
|
*Color += Offset;
|
||||||
|
} else {
|
||||||
|
// *Color = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRhashdecode - decode an arbitrary IR code.
|
||||||
|
* Instead of decoding using a standard encoding scheme
|
||||||
|
* (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
|
||||||
|
* This should produce a unique 32-bit number however that number cannot be used
|
||||||
|
* to retransmit the same code. This is just a quick and dirty way to detect a unique code
|
||||||
|
* for controlling a device when you don't really care what protocol or values
|
||||||
|
* are being sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
int RECV_PIN = 11;
|
||||||
|
IRrecv My_Receiver(RECV_PIN);
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
IRdecodeHash My_Hash_Decoder;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
|
||||||
|
//Restart the receiver so it can be capturing another code
|
||||||
|
//while we are working on decoding this one.
|
||||||
|
My_Receiver.resume();
|
||||||
|
My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
|
||||||
|
My_Decoder.decode();
|
||||||
|
Serial.print("real decode type:");
|
||||||
|
Serial.print(Pnames(My_Decoder.decode_type));
|
||||||
|
Serial.print(" value: 0x");
|
||||||
|
Serial.print(My_Decoder.value, HEX);
|
||||||
|
My_Hash_Decoder.decode();
|
||||||
|
Serial.print(", hash decode: 0x");
|
||||||
|
Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,130 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRrecord: record and play back IR signals
|
||||||
|
* An IR detector/demodulator must be connected to the input RECV_PIN.
|
||||||
|
* An IR LED must be connected to the output PWM pin 3.
|
||||||
|
* Unlike the original version of this demo sketch, you need not hook up a pushbutton
|
||||||
|
* Simply send any character from the serial screen to send the recorded code.
|
||||||
|
* Also demonstrates how to use toggle bits which must be controlled outside
|
||||||
|
* the library routines.
|
||||||
|
* The logic is:
|
||||||
|
* If an IR code is received, record it.
|
||||||
|
* If A serial character is received, send the IR code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
int RECV_PIN = 11;
|
||||||
|
|
||||||
|
IRrecv My_Receiver(RECV_PIN);
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
IRsend My_Sender;
|
||||||
|
/*
|
||||||
|
* Because this version of the library separated the receiver from the decoder,
|
||||||
|
* technically you would not need to "store" the code outside the decoder object
|
||||||
|
* for this overly simple example. All of the details would remain in the object.
|
||||||
|
* However we are going to go ahead and store them just to show you how.
|
||||||
|
*/
|
||||||
|
// Storage for the recorded code
|
||||||
|
IRTYPES codeType; // The type of code
|
||||||
|
unsigned long codeValue; // The data bits if type is not raw
|
||||||
|
int codeBits; // The length of the code in bits
|
||||||
|
// These values are only stored if it's an unknown type and we are going to use
|
||||||
|
// raw codes to resend the information.
|
||||||
|
unsigned int rawCodes[RAWBUF]; // The durations if raw
|
||||||
|
int rawCount; //The number of interval samples
|
||||||
|
|
||||||
|
bool GotOne, GotNew;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
GotOne=false; GotNew=false;
|
||||||
|
codeType=UNKNOWN;
|
||||||
|
codeValue=0;
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println(F("Send a code from your remote and we will record it."));
|
||||||
|
Serial.println(F("Type any character and press enter. We will send the recorded code."));
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stores the code for later playback
|
||||||
|
void storeCode(void) {
|
||||||
|
GotNew=true;
|
||||||
|
codeType = My_Decoder.decode_type;
|
||||||
|
if (codeType == UNKNOWN) {
|
||||||
|
Serial.println("Received unknown code, saving as raw");
|
||||||
|
// To store raw codes:
|
||||||
|
// Drop first value (gap)
|
||||||
|
// Convert from ticks to microseconds
|
||||||
|
// Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
|
||||||
|
rawCount = My_Decoder.rawlen-1;
|
||||||
|
for (int i = 1; i <=rawCount; i++) {
|
||||||
|
rawCodes[i - 1] = My_Decoder.Interval_uSec(i);//Converts to microseconds and adjusts for Mark/space
|
||||||
|
};
|
||||||
|
My_Decoder.DumpResults();
|
||||||
|
codeType=UNKNOWN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print(F("Received "));
|
||||||
|
Serial.print(Pnames(codeType));
|
||||||
|
if (My_Decoder.value == REPEAT) {
|
||||||
|
// Don't record a NEC repeat value as that's useless.
|
||||||
|
Serial.println("repeat; ignoring.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
codeValue = My_Decoder.value;
|
||||||
|
codeBits = My_Decoder.bits;
|
||||||
|
}
|
||||||
|
Serial.print(F(" Value:0x"));
|
||||||
|
Serial.println(My_Decoder.value, HEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sendCode(int repeat) {
|
||||||
|
if(codeType== UNKNOWN) {
|
||||||
|
// Assume 38 KHz
|
||||||
|
My_Sender.IRsendRaw::send(rawCodes,rawCount,38);
|
||||||
|
Serial.println("Sent raw");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( !GotNew ) {//We've already sent this so handle toggle bits
|
||||||
|
if (codeType == RC5) {
|
||||||
|
codeValue ^= 0x0800;
|
||||||
|
}
|
||||||
|
else if (codeType == RC6) {
|
||||||
|
codeValue ^= 0x10000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GotNew=false;
|
||||||
|
My_Sender.send(codeType,codeValue,codeBits);
|
||||||
|
Serial.print(F("Sent "));
|
||||||
|
Serial.print(Pnames(codeType));
|
||||||
|
Serial.print(F(" Value:0x"));
|
||||||
|
Serial.println(codeValue, HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (Serial.read() != -1) {
|
||||||
|
if(GotOne) {
|
||||||
|
sendCode(0);
|
||||||
|
My_Receiver.enableIRIn(); // Re-enable receiver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (My_Receiver.GetResults(&My_Decoder)) {
|
||||||
|
//Restart the receiver so it can be capturing another code
|
||||||
|
//while we are working on decoding this one.
|
||||||
|
if(My_Decoder.decode()) {
|
||||||
|
GotOne=true;
|
||||||
|
storeCode();
|
||||||
|
}
|
||||||
|
delay(500);
|
||||||
|
My_Receiver.resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* IRLib: IRrecvDump - dump details of IR codes with IRrecv
|
||||||
|
* An IR detector/demodulator must be connected to the input RECV_PIN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
int RECV_PIN = 11;
|
||||||
|
|
||||||
|
IRrecv My_Receiver(RECV_PIN);
|
||||||
|
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
unsigned int Buffer[RAWBUF];
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
My_Decoder.UseExtnBuf(Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (My_Receiver.GetResults(&My_Decoder)) {
|
||||||
|
//Restart the receiver so it can be capturing another code
|
||||||
|
//while we are working on decoding this one.
|
||||||
|
My_Receiver.resume();
|
||||||
|
My_Decoder.decode();
|
||||||
|
My_Decoder.DumpResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
IRsend My_Sender;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (Serial.read() != -1) {
|
||||||
|
//send a code every time a character is received from the serial port
|
||||||
|
//Sony DVD power A8BCA
|
||||||
|
My_Sender.send(SONY,0xa8bca, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* JVC sends repeat codes that are identical to the regular JVC codes
|
||||||
|
* however they have no header. Therefore there is an additional parameter
|
||||||
|
* that tells you whether or not to send as an original code or as a repeat.
|
||||||
|
*
|
||||||
|
* The only device I had to test this protocol was an old JVC VCR. It would only work if at least
|
||||||
|
* 2 frames are sent separated by 45us of "space". All JVC is the same bit length so we use
|
||||||
|
* the third parameter as a to tell it whether or not to send the header.
|
||||||
|
* Once with the third parameter "1" then delay about 50 microseconds and send again
|
||||||
|
* with the third parameter "0".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
IRsend My_Sender;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
//send a code every time a character is received from the serial port
|
||||||
|
void loop() {
|
||||||
|
if (Serial.read() != -1) {
|
||||||
|
My_Sender.send(JVC,0xc2d0,1); delayMicroseconds (50);
|
||||||
|
My_Sender.send(JVC,0xc2d0,0); delayMicroseconds (50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
#include <IRLib.h>
|
||||||
|
|
||||||
|
IRsend My_Sender;
|
||||||
|
|
||||||
|
int protocol;
|
||||||
|
long code;
|
||||||
|
int bits;
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
long parseHex (void) {
|
||||||
|
long Value=0; char C;delay(100);
|
||||||
|
while (Serial.available()>0) {
|
||||||
|
C= tolower(Serial.read());
|
||||||
|
if ((C>='0')&&(C<='9'))
|
||||||
|
C=C-'0';
|
||||||
|
else
|
||||||
|
if ((C>='a') && (C<='f'))
|
||||||
|
C=C-'a'+10;
|
||||||
|
else
|
||||||
|
return Value;
|
||||||
|
Value= C+(Value<<4);
|
||||||
|
};
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
void parseDelimiter () {
|
||||||
|
char C;
|
||||||
|
while(Serial.available()>0) {
|
||||||
|
C=tolower(Serial.peek());
|
||||||
|
if( (C>='0') && (C<='9') )return;
|
||||||
|
if( (C>='a') && (C<='f') )return;
|
||||||
|
C=Serial.read();//throwaway delimiters
|
||||||
|
delay (5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// enum IRTYPES {UNKNOWN, NEC, SONY, RC5, RC6, PANASONIC_OLD, JVC, NECX, HASH_CODE, LAST_PROTOCOL=HASH_CODE};
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (Serial.available ()>0) {
|
||||||
|
protocol = Serial.parseInt (); parseDelimiter();
|
||||||
|
code = parseHex (); parseDelimiter();
|
||||||
|
bits = Serial.parseInt (); parseDelimiter();
|
||||||
|
/* Serial.print("Prot:"); Serial.print(protocol);
|
||||||
|
Serial.print(" Code:"); Serial.print(code,HEX);
|
||||||
|
Serial.print(" Bits:"); Serial.println(bits);
|
||||||
|
*/
|
||||||
|
My_Sender.send(IRTYPES(protocol), code, bits);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
# IRLib demo script
|
||||||
|
# version 1.0 by Chris Young http://tech.cyborg5.com/irlib/
|
||||||
|
# Displays a "Virtual remote" on your screen. Clicking on the
|
||||||
|
# buttons sends serial datato the Arduino which in turn
|
||||||
|
# since IR signals to a cable box in TV.
|
||||||
|
|
||||||
|
# Import all of the necessary pieces of code
|
||||||
|
import serial, sys, pygame, pygame.mixer
|
||||||
|
from pygame.locals import *
|
||||||
|
|
||||||
|
# You will have to edit this to the proper port and speed
|
||||||
|
ser = serial.Serial('COM4', 9600)
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
# Established screen size, size of buttons and position
|
||||||
|
size = width, height = 400, 768
|
||||||
|
button_size=54; button_offset=71
|
||||||
|
button_x1=65;button_y1=39
|
||||||
|
max_rows=10; max_columns=4
|
||||||
|
|
||||||
|
# Specify a font. I'm using Arial narrow bold from my Windows
|
||||||
|
# font folder. However the default font shown below also works.
|
||||||
|
myfont =pygame.font.Font ("c:/windows/fonts/ARIALNB.TTF",30)
|
||||||
|
#myfont=pygame.font.Font(None,36)
|
||||||
|
|
||||||
|
# These are the text labels that will appear on each button
|
||||||
|
label_text=("TVp", "CBp", "P^", "Pv",\
|
||||||
|
"<<", ">", ">>", "->",\
|
||||||
|
"Rec", "=", "s", "<-",\
|
||||||
|
"Gd", "^", "Fav", "Inf",\
|
||||||
|
|
||||||
|
"<", "sel", ">", "Lis",\
|
||||||
|
"ret", "v", "Prv", "Mnu",\
|
||||||
|
"1", "2", "3", "Ch+",\
|
||||||
|
|
||||||
|
"4", "5", "6", "Ch-",\
|
||||||
|
"7", "8", "9", "Vol+",\
|
||||||
|
"Pip", "0", "Mut", "Vol-",\
|
||||||
|
)
|
||||||
|
# Each of these 40 strings of text correspond to the
|
||||||
|
# protocol in code which will be sent over the USB serial
|
||||||
|
# to the Arduino. The first number is the protocol number.
|
||||||
|
# See the defined protocols in "IRLib.h"for the
|
||||||
|
# enum IRTYPES at about line 50. This example uses
|
||||||
|
# protocol 3 which is "RC5" used by my Magnavox TV
|
||||||
|
# and protocol 5 "PANASONIC_OLD" used by my Scientific
|
||||||
|
# Atlantic SA 8300 DVR. The protocol number is followed by
|
||||||
|
# the hex code to be transmitted. That is followed by the
|
||||||
|
# number of bits. Note that the PANASONIC_OLD protocol
|
||||||
|
# does not need the number of bits specified so they are omitted.
|
||||||
|
IR_Codes= ("3,180c,13","5,37c107","5,36d924","5,37d904",\
|
||||||
|
"5,37291a","5,37990c","5,36293a","5,36b129",\
|
||||||
|
"5,375914","5,374117","5,365934","5,37c906",\
|
||||||
|
"5,36c127","5,36812f","5,37f101","5,36213b",\
|
||||||
|
|
||||||
|
"5,37810f","5,366133","5,364137","5,36c926",\
|
||||||
|
"5,366932","5,37a10b","5,36e123","5,373918",\
|
||||||
|
"5,36113d","5,37111d","5,36912d","5,377111",\
|
||||||
|
|
||||||
|
"5,37910d","5,365135","5,375115","5,36f121",\
|
||||||
|
"5,36d125","5,37d105","5,363139","3,1810,13",\
|
||||||
|
"5,37b908","5,373119","3,180d,13","3,1811,13",\
|
||||||
|
)
|
||||||
|
# This function gets called to shut everything down
|
||||||
|
def Finished():
|
||||||
|
pygame.quit()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
# Gets the button index based on mouse position. Returned
|
||||||
|
# value is from 0 to 39 (number of buttons-1)
|
||||||
|
# Returns -1 if you are not over a button.
|
||||||
|
def ComputeButton():
|
||||||
|
mx,my=pygame.mouse.get_pos()
|
||||||
|
mx=mx-button_x1
|
||||||
|
my=my-button_y1
|
||||||
|
bx=mx/button_offset; by=my/button_offset
|
||||||
|
if bx<0 or bx>=max_columns:return -1
|
||||||
|
if by<0 or by> max_rows:return -1
|
||||||
|
if (mx%button_offset)>button_size:return -1
|
||||||
|
if (my%button_offset)>button_size:return -1
|
||||||
|
return bx+by*max_columns
|
||||||
|
|
||||||
|
# Blits the button text from button number "i"
|
||||||
|
# onto the specified layer using the specified color.
|
||||||
|
def Show_Text(i,Layer,color=(0,0,0)):
|
||||||
|
t=label_text[i]
|
||||||
|
label = myfont.render (t,1,color)
|
||||||
|
labelpos= label.get_rect()
|
||||||
|
labelpos.centerx=button_x1+button_size/2+i%max_columns*button_offset
|
||||||
|
labelpos.centery=button_y1+button_size/2+i/max_columns*button_offset
|
||||||
|
Layer.blit(label,labelpos)
|
||||||
|
|
||||||
|
# Create the screen and load the background image.
|
||||||
|
screen = pygame.display.set_mode(size)
|
||||||
|
bg = pygame.image.load("remotebg.png")
|
||||||
|
|
||||||
|
# Blit black text labels onto the background image
|
||||||
|
for i in range (max_rows*max_columns):
|
||||||
|
Show_Text(i, bg)
|
||||||
|
# Copy the background to the display
|
||||||
|
screen.blit(bg,(0,0))
|
||||||
|
pygame.display.flip()
|
||||||
|
|
||||||
|
# Load the clicking sound
|
||||||
|
Click=pygame.mixer.Sound("click.wav")
|
||||||
|
|
||||||
|
# Used to detect when the mouse hovers over a different button
|
||||||
|
previous=-1
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
Finished()
|
||||||
|
elif event.type == KEYDOWN and event.key == K_ESCAPE:
|
||||||
|
Finished ()
|
||||||
|
elif event.type == MOUSEBUTTONDOWN:
|
||||||
|
i=ComputeButton() #which button did we click
|
||||||
|
if i>=0:
|
||||||
|
Click.play() #play the sound
|
||||||
|
ser.write(IR_Codes[i]) #send the codes
|
||||||
|
elif event.type==MOUSEMOTION:
|
||||||
|
i=ComputeButton() #which button are we over
|
||||||
|
if i!=previous: #difference in the last one?
|
||||||
|
if i>=0: #turn it red
|
||||||
|
Show_Text(i,screen,(255,0,0))
|
||||||
|
else: #or put it back the way it was
|
||||||
|
screen.blit(bg,(0,0))
|
||||||
|
previous=i
|
||||||
|
pygame.display.flip() #update the display
|
||||||
|
# That's all folks
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
//POV-Ray source to generate the background image for IRserial_remote
|
||||||
|
// create rectangular areas with rounded corners for use as
|
||||||
|
// buttons and background objects.
|
||||||
|
|
||||||
|
// Render at 1024x768 then crop 312 pixels from each side
|
||||||
|
// leaving 400x768 final image.
|
||||||
|
#declare Area=15; //size of area lights
|
||||||
|
#declare CR=0.1; //corner radius
|
||||||
|
#declare ER= 0.5; //edge radius
|
||||||
|
#declare CX= 3; //width from corner to corner
|
||||||
|
#declare CY= 7.75; //height from corner to corner
|
||||||
|
#declare BZ=-ER; //Z offset for buttons
|
||||||
|
|
||||||
|
plane {z,0 pigment{rgb<0.8,0.85,1>*0.8}}//background
|
||||||
|
|
||||||
|
#macro Thing (ER,CR,CX,CY,T)
|
||||||
|
#local Corner=
|
||||||
|
union {
|
||||||
|
torus {CR,ER rotate x*90}
|
||||||
|
cylinder {ER*z,-ER*z,CR}
|
||||||
|
}
|
||||||
|
union {
|
||||||
|
object{Corner translate< CX,CY,0>}
|
||||||
|
object{Corner translate<-CX,CY,0>}
|
||||||
|
object{Corner translate< CX,-CY,0>}
|
||||||
|
object{Corner translate<-CX,-CY,0>}
|
||||||
|
cylinder{CY*y,-CY*y,ER translate<-CX-CR,0,0>}
|
||||||
|
cylinder{CY*y,-CY*y,ER translate< CX+CR,0,0>}
|
||||||
|
cylinder{CX*x,-CX*x,ER translate<0,-CY-CR,0>}
|
||||||
|
cylinder{CX*x,-CX*x,ER translate<0, CY+CR,0>}
|
||||||
|
box{<-CX,-CY-CR,-ER><CX,CY+CR,ER>}
|
||||||
|
box{<-CX-CR,-CY,-ER><CX+CR,CY,ER>}
|
||||||
|
texture {T}
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
#declare BX= 0.4; #declare BY=BX;//size of the buttons
|
||||||
|
#declare White_Texture=texture{pigment{rgb 1}finish {ambient 0.3}}
|
||||||
|
#declare Blue_Texture=texture{pigment {rgb<0.85,0.9 ,1>}}
|
||||||
|
|
||||||
|
object {Thing(ER,CR,CX,CY, White_Texture)}//main object
|
||||||
|
//loop through the buttons
|
||||||
|
#declare R=-4.5;
|
||||||
|
#while (R<5.5)
|
||||||
|
#declare C=-1.5;
|
||||||
|
#while (C<=1.5)
|
||||||
|
object{Thing(0.1,0.2,(BX*0.8),(BY*0.8), Blue_Texture)
|
||||||
|
translate <C*BX*4,R*BY*4,BZ>
|
||||||
|
}
|
||||||
|
#declare C=C+1;
|
||||||
|
#end
|
||||||
|
#declare R=R+1;
|
||||||
|
#end
|
||||||
|
|
||||||
|
|
||||||
|
light_source{<50,50,-100>*5 color 0.8
|
||||||
|
#if (Area)area_light x*Area,y*Area,9,9#end
|
||||||
|
}
|
||||||
|
light_source{<0,0,-400>*3 rgb 1}
|
||||||
|
|
||||||
|
camera{orthographic location <0,0,-120> look_at <0,0,0> angle 11 }
|
||||||
|
//That's all folks!
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,68 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.1 April 2013 by Chris Young http://cyborg5.com
|
||||||
|
* "IRservo" Control a servo using an IR remote
|
||||||
|
*/
|
||||||
|
#include <IRLib.h>
|
||||||
|
#include <Servo.h>
|
||||||
|
// You will have to set these values depending on the protocol
|
||||||
|
// and remote codes that you are using. These are from my Sony DVD/VCR
|
||||||
|
#define MY_PROTOCOL SONY
|
||||||
|
#define RIGHT_ARROW 0x86bca //Move several clockwise
|
||||||
|
#define LEFT_ARROW 0x46bca //Move servo counterclockwise
|
||||||
|
#define SELECT_BUTTON 0xd0bca //Center the servo
|
||||||
|
#define UP_ARROW 0x42bca //Increased number of degrees servo moves
|
||||||
|
#define DOWN_ARROW 0xc2bca //Decrease number of degrees servo moves
|
||||||
|
#define BUTTON_0 0x90bca //Pushing buttons 0-9 moves to fix positions
|
||||||
|
#define BUTTON_1 0x00bca // each 20 degrees greater
|
||||||
|
#define BUTTON_2 0x80bca
|
||||||
|
#define BUTTON_3 0x40bca
|
||||||
|
#define BUTTON_4 0xc0bca
|
||||||
|
#define BUTTON_5 0x20bca
|
||||||
|
#define BUTTON_6 0xa0bca
|
||||||
|
#define BUTTON_7 0x60bca
|
||||||
|
#define BUTTON_8 0xe0bca
|
||||||
|
#define BUTTON_9 0x10bca
|
||||||
|
|
||||||
|
IRrecv My_Receiver(11);//Receive on pin 11
|
||||||
|
IRdecode My_Decoder;
|
||||||
|
Servo My_Servo; // create servo object to control a servo
|
||||||
|
int pos; // variable to store the servo position
|
||||||
|
int Speed; // Number of degrees to move each time a left/right button is pressed
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
My_Receiver.No_Output();//Turn off any unused IR LED output circuit
|
||||||
|
My_Servo.attach(9); // attaches the servo on pin 9 to the servo object
|
||||||
|
pos = 90; // start at midpoint 90 degrees
|
||||||
|
Speed = 3; // servo moves 3 degrees each time left/right is pushed
|
||||||
|
My_Servo.write(pos); // Set initial position
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (My_Receiver.GetResults(&My_Decoder)) {
|
||||||
|
My_Decoder.decode();
|
||||||
|
if(My_Decoder.decode_type==MY_PROTOCOL) {
|
||||||
|
switch(My_Decoder.value) {
|
||||||
|
case LEFT_ARROW: pos=min(180,pos+Speed); break;
|
||||||
|
case RIGHT_ARROW: pos=max(0,pos-Speed); break;
|
||||||
|
case SELECT_BUTTON: pos=90; break;
|
||||||
|
case UP_ARROW: Speed=min(10, Speed+1); break;
|
||||||
|
case DOWN_ARROW: Speed=max(1, Speed-1); break;
|
||||||
|
case BUTTON_0: pos=0*20; break;
|
||||||
|
case BUTTON_1: pos=1*20; break;
|
||||||
|
case BUTTON_2: pos=2*20; break;
|
||||||
|
case BUTTON_3: pos=3*20; break;
|
||||||
|
case BUTTON_4: pos=4*20; break;
|
||||||
|
case BUTTON_5: pos=5*20; break;
|
||||||
|
case BUTTON_6: pos=6*20; break;
|
||||||
|
case BUTTON_7: pos=7*20; break;
|
||||||
|
case BUTTON_8: pos=8*20; break;
|
||||||
|
case BUTTON_9: pos=9*20; break;
|
||||||
|
}
|
||||||
|
My_Servo.write(pos); // tell servo to go to position in variable 'pos'
|
||||||
|
}
|
||||||
|
My_Receiver.resume();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
|
||||||
|
* Version 1.0 January 2013
|
||||||
|
* Copyright 2013 by Chris Young http://cyborg5.com
|
||||||
|
* Based on original example sketch for IRremote library
|
||||||
|
* Version 0.11 September, 2009
|
||||||
|
* Copyright 2009 Ken Shirriff
|
||||||
|
* http://arcfn.com
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This example demonstrates how to extend this library to add a new protocol
|
||||||
|
* without actually modifying or recompiling the library itself. It implements a 36 bit
|
||||||
|
* Samsung protocol that is used on a Blu-ray player that I own.
|
||||||
|
* Because a 36 bit value will not fit in the value field (only 32 bits) we have to create
|
||||||
|
* a second value field.
|
||||||
|
*/
|
||||||
|
#include <IRLib.h>
|
||||||
|
#include <IRLibMatch.h>
|
||||||
|
|
||||||
|
int RECV_PIN = 11;
|
||||||
|
|
||||||
|
IRrecv My_Receiver(RECV_PIN);
|
||||||
|
#define SAMSUNG36 (LAST_PROTOCOL+1) //Unfortunately cannot extend an enum. This is the best we can do.
|
||||||
|
|
||||||
|
/*Is the value in this if statement is "1" then we will extend the base decoder.
|
||||||
|
*The result is this will only decode Samsung 36 and no others.
|
||||||
|
*If the value is "0" we will extend the all-inclusive decoder.
|
||||||
|
*Try changing this value and note the effect on code size when compiling.
|
||||||
|
*/
|
||||||
|
#if(1)
|
||||||
|
#define MY_BASE IRdecodeBase
|
||||||
|
#else
|
||||||
|
#define MY_BASE IRdecode
|
||||||
|
#endif
|
||||||
|
class IRdecodeSamsung36: public virtual MY_BASE{
|
||||||
|
public:
|
||||||
|
bool decode(void);
|
||||||
|
unsigned int value2;
|
||||||
|
void Reset(void);
|
||||||
|
void DumpResults(void);
|
||||||
|
private:
|
||||||
|
bool GetBit(void);
|
||||||
|
int offset;
|
||||||
|
unsigned long data;
|
||||||
|
};
|
||||||
|
void IRdecodeSamsung36::Reset(void) {
|
||||||
|
MY_BASE::Reset();//respect your parents
|
||||||
|
value2=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IRdecodeSamsung36::GetBit(void) {
|
||||||
|
if (!MATCH_MARK (rawbuf[offset],500)) return DATA_MARK_ERROR;
|
||||||
|
offset++;
|
||||||
|
if (MATCH_SPACE(rawbuf[offset],1500)) {
|
||||||
|
data = (data << 1) | 1;
|
||||||
|
}
|
||||||
|
else if (MATCH_SPACE (rawbuf[offset],500)) {
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
else return DATA_SPACE_ERROR;
|
||||||
|
offset++;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#Samsung36
|
||||||
|
* The IRP notation for this protocol is:
|
||||||
|
* {38k,500}<1,-1|1,-3>(9,-9,D:8,S:8,1,-9,E:4,F:8,-68u,~F:8,1,-118)+
|
||||||
|
* This means it uses 38k frequency. Base timing is multiples of 500.
|
||||||
|
* A "0" is mark(500) space(500). A "1" is mark (500) space(1500)
|
||||||
|
* The header is mark(4500) space(4500).
|
||||||
|
* The header is followed by 16 bits (8 device, 8 sub device)
|
||||||
|
* This is followed by a mark(500) space(4500).
|
||||||
|
* This is followed by 12 more bits (4+8)
|
||||||
|
* This is followed by 68us ofspace. Followed by eight more bits
|
||||||
|
* and a final stop bit.
|
||||||
|
*/
|
||||||
|
bool IRdecodeSamsung36::decode(void) {
|
||||||
|
if(MY_BASE::decode()) return true;
|
||||||
|
ATTEMPT_MESSAGE(F("Samsung36"));
|
||||||
|
if (rawlen != 78) return RAW_COUNT_ERROR;
|
||||||
|
if (!MATCH_MARK(rawbuf[1],4500)) return HEADER_MARK_ERROR;
|
||||||
|
if (!MATCH_SPACE(rawbuf[2],4500)) return HEADER_SPACE_ERROR;
|
||||||
|
offset=3; data=0;
|
||||||
|
//Get first 18 bits
|
||||||
|
while (offset < 16*2+2) if(!GetBit()) return false;
|
||||||
|
//Skip middle header
|
||||||
|
if (!MATCH_MARK(rawbuf[offset],500)) return DATA_MARK_ERROR;
|
||||||
|
offset++;
|
||||||
|
if (!MATCH_SPACE(rawbuf[offset],4500)) return DATA_SPACE_ERROR;
|
||||||
|
//save first 18 bits in "value" and reset data
|
||||||
|
offset++; value=data; data=0;
|
||||||
|
rawbuf[62]=(rawbuf[62]*USECPERTICK-68)/USECPERTICK;
|
||||||
|
while(offset<77)if(!GetBit()) return false;
|
||||||
|
bits =36;//set bit length
|
||||||
|
value2 = data;//put remaining bits in value2
|
||||||
|
decode_type= static_cast<IRTYPES>SAMSUNG36;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
void IRdecodeSamsung36::DumpResults(void){
|
||||||
|
if(decode_type==SAMSUNG36) {
|
||||||
|
Serial.print(F("Decoded Samsung36: Value1:")); Serial.print(value, HEX);
|
||||||
|
Serial.print(F(": Value2:")); Serial.print(value2, HEX);
|
||||||
|
};
|
||||||
|
MY_BASE::DumpResults();
|
||||||
|
};
|
||||||
|
IRdecodeSamsung36 My_Decoder;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
My_Receiver.enableIRIn(); // Start the receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (My_Receiver.GetResults(&My_Decoder)) {
|
||||||
|
My_Decoder.decode();
|
||||||
|
My_Decoder.DumpResults();
|
||||||
|
My_Receiver.resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ IMPORTANT:
|
|||||||
For this sketch, which is using <DigiUSB> library:
|
For this sketch, which is using <DigiUSB> library:
|
||||||
1) Comment "#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT" in "arduino-1.xx\libraries\RcSeq.h".
|
1) Comment "#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT" in "arduino-1.xx\libraries\RcSeq.h".
|
||||||
This will disable the code to manage incoming RC pulses and save some flash memory.
|
This will disable the code to manage incoming RC pulses and save some flash memory.
|
||||||
|
RC_SEQ_WITH_SHORT_ACTION_SUPPORT and RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT shall be defined
|
||||||
2) Replace #define RING_BUFFER_SIZE 128 with #define RING_BUFFER_SIZE 32 in "arduino-1.xx\libraries\DigisparkUSB\DigiUSB.h".
|
2) Replace #define RING_BUFFER_SIZE 128 with #define RING_BUFFER_SIZE 32 in "arduino-1.xx\libraries\DigisparkUSB\DigiUSB.h".
|
||||||
3) The sequence will be launch by sending "g" character through USB link (using Digiterm or Digi Monitor).
|
3) The sequence will be launch by sending "g" character through USB link (using Digiterm or Digi Monitor).
|
||||||
To check all the sequence is performed asynchronously, you can send 't' to toggle the LED during servo motion!
|
To check all the sequence is performed asynchronously, you can send 't' to toggle the LED during servo motion!
|
@ -0,0 +1,115 @@
|
|||||||
|
#include <RcSeq.h>
|
||||||
|
#include <TinyPinChange.h>
|
||||||
|
#include <SoftRcPulseIn.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPORTANT:
|
||||||
|
For this sketch to compile, RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT and RC_SEQ_WITH_SHORT_ACTION_SUPPORT shall be defined
|
||||||
|
in PathOfTheLibraries/(Digispark)RcSeq/RcSeq.h and RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT shall be commented.
|
||||||
|
|
||||||
|
This sketch demonstrates how to easily use a 3 positions switch on a channel of a RC Transmitter with <RcSeq> library.
|
||||||
|
1) If the switch is at the MIDDLE position, a LED will be OFF
|
||||||
|
2) If the switch is at the DOWN position, a LED will be ON
|
||||||
|
2) If the switch is at the UP position, a LED will blink
|
||||||
|
|
||||||
|
This sketch can be extended to a rotactor (up to 8 positions)
|
||||||
|
|
||||||
|
RC Navy (2013)
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
|
|
||||||
|
WIRING A TRANSMITTER SIDE WIRING AT RECEIVER SIDE
|
||||||
|
|
||||||
|
.------+-------------> +
|
||||||
|
| |
|
||||||
|
/ | # .-------------------------.
|
||||||
|
| UP o # 4.7K | |
|
||||||
|
| \ # | ARDUINO or ATTINY |
|
||||||
|
3 positions | \ | | | R
|
||||||
|
switch < MIDDLE o o---+-------------> To Tx Channel Rx Channel->|RC_CHANNEL_PIN LED_PIN >----###---|>|----|GND
|
||||||
|
| C | | | LED
|
||||||
|
| # | Sketch |
|
||||||
|
| DOWN o # 4.7K '-------------------------' External or
|
||||||
|
\ | # Built-in LED
|
||||||
|
| |
|
||||||
|
'------+-------------> -
|
||||||
|
|
||||||
|
.------------.------------------------.--------------.
|
||||||
|
| Switch Pos | Pulse Width Range (us) | Action |
|
||||||
|
+------------+------------------------+--------------+
|
||||||
|
| UP | 1000 -> 1270 | LED Blinking |
|
||||||
|
+------------+------------------------+--------------+
|
||||||
|
| MIDDLE | 1360 -> 1630 | LED OFF |
|
||||||
|
+------------+------------------------+--------------+
|
||||||
|
| DOWN | 1720 -> 1990 | LED ON |
|
||||||
|
'------------'------------------------'--------------'
|
||||||
|
|
||||||
|
Note:
|
||||||
|
====
|
||||||
|
<RcSeq> computes automatically the valid pulse width range for each position of the switch.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Channel Declaration */
|
||||||
|
enum {RC_CHANNEL=0, RC_CHANNEL_NB}; /* Here, as there is a single channel, we could used a simple "#define RC_CHANNEL 0" rather an enumeration */
|
||||||
|
|
||||||
|
#define RC_CHANNEL_PIN 0 // Choose here the pin
|
||||||
|
#define LED_PIN 1 // Choose here the pin
|
||||||
|
|
||||||
|
enum {SW_POS_DOWN=0, SW_POS_MIDDLE, SW_POS_UP, SW_POS_NB}; /* Switch has 3 positions: Down, Middle and Up (For a rotactor with more positions, add positions here) */
|
||||||
|
|
||||||
|
boolean BlinkCmd=false;
|
||||||
|
boolean LedState=false;
|
||||||
|
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
RcSeq_Init();
|
||||||
|
|
||||||
|
RcSeq_DeclareSignal(RC_CHANNEL, RC_CHANNEL_PIN); /* RC_CHANNEL Channel is assigned to RC_CHANNEL_PIN pin */
|
||||||
|
|
||||||
|
RcSeq_DeclareMultiPosSwitch(RC_CHANNEL, 1000, 2000, SW_POS_NB); /* Tells to <RcSeq> that the RC_CHANNEL channel has SW_POS_NB positions distributed between 1000 and 2000 us */
|
||||||
|
|
||||||
|
RcSeq_DeclareCommandAndShortAction(RC_CHANNEL, SW_POS_DOWN, ActionSwPosDown); /* Action assigned to DOWN position */
|
||||||
|
RcSeq_DeclareCommandAndShortAction(RC_CHANNEL, SW_POS_MIDDLE, ActionSwPosMiddle); /* Action assigned to MIDDLE position */
|
||||||
|
RcSeq_DeclareCommandAndShortAction(RC_CHANNEL, SW_POS_UP, ActionSwPosUp); /* Action assigned to UP position */
|
||||||
|
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
static uint32_t StartMs=millis();
|
||||||
|
|
||||||
|
/* Refresh RcSeq (mandatory) */
|
||||||
|
RcSeq_Refresh();
|
||||||
|
|
||||||
|
/* Blink Management */
|
||||||
|
if( (BlinkCmd==true) && (millis() - StartMs >= 250UL) )
|
||||||
|
{
|
||||||
|
StartMs=millis();
|
||||||
|
LedState=!LedState;
|
||||||
|
digitalWrite(LED_PIN, LedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionSwPosUp() /* This function will be called when the switch is in UP position */
|
||||||
|
{
|
||||||
|
BlinkCmd=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionSwPosMiddle() /* This function will be called when the switch is in MIDDLE position */
|
||||||
|
{
|
||||||
|
BlinkCmd=false;
|
||||||
|
LedState=false;
|
||||||
|
digitalWrite(LED_PIN, LedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionSwPosDown() /* This function will be called when the switch is in DOWN position */
|
||||||
|
{
|
||||||
|
BlinkCmd=false;
|
||||||
|
LedState=true;
|
||||||
|
digitalWrite(LED_PIN, LedState);
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,15 @@
|
|||||||
#include <RcSeq.h>
|
#include <RcSeq.h>
|
||||||
#include <TinyPinChange.h>
|
#include <TinyPinChange.h>
|
||||||
#include <SoftRcPulseIn.h>
|
#include <SoftRcPulseIn.h>
|
||||||
#include <SoftRcPulseOut.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
IMPORTANT:
|
||||||
|
For this sketch to compile, RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT and RC_SEQ_WITH_SHORT_ACTION_SUPPORT shall be defined
|
||||||
|
in PathOfTheLibraries/(Digispark)RcSeq/RcSeq.h and RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT shall be commented.
|
||||||
|
|
||||||
This sketch demonstrates how to easily transform a proportionnal RC channel into 5 digital commands with an ATtiny85.
|
This sketch demonstrates how to easily transform a proportionnal RC channel into 5 digital commands with an ATtiny85.
|
||||||
RC Navy (2013)
|
RC Navy (2013)
|
||||||
http://P.loussouarn.free.fr
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
COMMMAND OF 5 digital outputs from 5 push button replacing a potentiometer in the RC transmitter:
|
COMMMAND OF 5 digital outputs from 5 push button replacing a potentiometer in the RC transmitter:
|
||||||
================================================================================================
|
================================================================================================
|
||||||
@ -87,12 +90,21 @@ KeyMap_t CustomKeyboard[] PROGMEM ={ {CENTER_VALUE_US(1100,TOLERANCE)}, /* PUSH_
|
|||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/* Trick: a macro to write a single time the ToggleAction#() function */
|
/* Trick: a macro to write a single time the ToggleAction#() function */
|
||||||
#define DECLARE_TOGGLE_ACTION(Idx) \
|
#define DECLARE_TOGGLE_ACTION(Idx) \
|
||||||
void ToggleAction##Idx(void) \
|
void ToggleAction##Idx(void) \
|
||||||
{ \
|
{ \
|
||||||
static boolean Etat=HIGH; \
|
static uint32_t StartMs=millis(); \
|
||||||
digitalWrite(Idx, Etat); \
|
static boolean Etat=HIGH; \
|
||||||
Etat=!Etat; \
|
\
|
||||||
|
/* Since version 2.0 of the <RcSeq> library, */ \
|
||||||
|
/* for reactivity reasons, inter-command delay */ \
|
||||||
|
/* shall be managed in the user sketch. */ \
|
||||||
|
if(millis() - StartMs >= 500UL) \
|
||||||
|
{ \
|
||||||
|
StartMs=millis(); \
|
||||||
|
digitalWrite(Idx, Etat); \
|
||||||
|
Etat=!Etat; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Declaration of the actions using the DECLARE_TOGGLE_ACTION(Idx) macro with Idx = The number of the action and the pin number (The ##Idx will be automatically replaced with the Idx value */
|
/* Declaration of the actions using the DECLARE_TOGGLE_ACTION(Idx) macro with Idx = The number of the action and the pin number (The ##Idx will be automatically replaced with the Idx value */
|
@ -1,4 +1,16 @@
|
|||||||
|
#include <RcSeq.h>
|
||||||
|
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
|
||||||
|
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
|
||||||
|
#include <SoftRcPulseOut.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseOut> qui est utilisee par la librairie <RcSeq> */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
IMPORTANT:
|
||||||
|
Pour compiler ce sketch, RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT, RC_SEQ_WITH_SHORT_ACTION_SUPPORT et RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
|
doivent etre definis dans ChemainDesLibraires/(Digispark)RcSeq/RcSeq.h.
|
||||||
|
|
||||||
|
RC Navy 2013
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
Ce sketch de demo de la librairie RcSeq montre comment configurer tres facilement la commande d'actions ou de sequences de servo predefinies.
|
Ce sketch de demo de la librairie RcSeq montre comment configurer tres facilement la commande d'actions ou de sequences de servo predefinies.
|
||||||
La commande peut etre:
|
La commande peut etre:
|
||||||
- un manche de l'emetteur RC avec possibilité de definir jusqu'a 8 positions "actives" (le nombre de position doit etre pair: neutre au milieu)
|
- un manche de l'emetteur RC avec possibilité de definir jusqu'a 8 positions "actives" (le nombre de position doit etre pair: neutre au milieu)
|
||||||
@ -8,10 +20,6 @@ La commande peut etre:
|
|||||||
(la largeur d'impulsion pour chaque bouton-poussoir est define dans une table, une tolerance est egalement prevue)
|
(la largeur d'impulsion pour chaque bouton-poussoir est define dans une table, une tolerance est egalement prevue)
|
||||||
Les 3 exemples sont traites dans ce sketch de demo.
|
Les 3 exemples sont traites dans ce sketch de demo.
|
||||||
*/
|
*/
|
||||||
#include <RcSeq.h>
|
|
||||||
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
|
|
||||||
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
|
|
||||||
#include <SoftRcPulseOut.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseOut> qui est utilisee par la librairie <RcSeq> */
|
|
||||||
|
|
||||||
enum {RC_VOIE1, RC_VOIE2, RC_VOIE3, NBR_VOIES_RC}; /* Declaration des voies */
|
enum {RC_VOIE1, RC_VOIE2, RC_VOIE3, NBR_VOIES_RC}; /* Declaration des voies */
|
||||||
|
|
||||||
@ -134,7 +142,13 @@ void loop()
|
|||||||
/* Action associee au BP1 de la VOIE1 ou au manche position basse de la VOIE2 ou au BP_MAISON1 de la VOIE3 */
|
/* Action associee au BP1 de la VOIE1 ou au manche position basse de la VOIE2 ou au BP_MAISON1 de la VOIE3 */
|
||||||
void InverseLed(void)
|
void InverseLed(void)
|
||||||
{
|
{
|
||||||
static boolean Etat=HIGH; /* static, pour conserver l'etat entre 2 appels de la fonction */
|
static uint32_t DebutMs=millis(); /* static, pour conserver l'etat entre 2 appels de la fonction */
|
||||||
|
static boolean Etat=HIGH; /* static, pour conserver l'etat entre 2 appels de la fonction */
|
||||||
|
|
||||||
|
if(millis() - DebutMs >= 500UL) /* Depuis RcSeq V2.0, la tempo inter-commande doit etre geree dans le sketch utilisateur */
|
||||||
|
{
|
||||||
|
DebutMs=millis();
|
||||||
digitalWrite(LED, Etat);
|
digitalWrite(LED, Etat);
|
||||||
Etat=!Etat; /* AU prochain appel de InverseLed(), l'etat de la LED sera inverse */
|
Etat=!Etat; /* Au prochain appel de InverseLed(), l'etat de la LED sera inverse */
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,15 @@
|
|||||||
#include <RcSeq.h>
|
#include <RcSeq.h>
|
||||||
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
|
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
|
||||||
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
|
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
|
||||||
#include <SoftRcPulseOut.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseOut> qui est utilisee par la librairie <RcSeq> */
|
|
||||||
|
/*
|
||||||
|
IMPORTANT:
|
||||||
|
Pour compiler ce sketch, RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT et RC_SEQ_WITH_SHORT_ACTION_SUPPORT doivent etre definie
|
||||||
|
dans ChemainDesLibraires/(Digispark)RcSeq/RcSeq.h et RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT doit etre mis en commentaire.
|
||||||
|
|
||||||
|
RC Navy 2013
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
*/
|
||||||
|
|
||||||
/*================= COMMMANDE DE 8 SORTIES ON/OFF PAR 8 INTERS POUSSOIR ========================
|
/*================= COMMMANDE DE 8 SORTIES ON/OFF PAR 8 INTERS POUSSOIR ========================
|
||||||
Les 8 relais ou sont connectés aux prise n°1,2,3,4,5,6,7,8 d'un ATtiny84
|
Les 8 relais ou sont connectés aux prise n°1,2,3,4,5,6,7,8 d'un ATtiny84
|
||||||
@ -34,12 +42,20 @@ KeyMap_t ClavierMaison[] PROGMEM ={ {VALEUR_CENTRALE_US(1100,TOLERANCE)}, /* BP
|
|||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/* Astuce: une macro pour n'ecrire qu'une seule fois la fonction ActionX() */
|
/* Astuce: une macro pour n'ecrire qu'une seule fois la fonction ActionX() */
|
||||||
#define DECLARE_ACTION(Idx) \
|
#define DECLARE_ACTION(Idx) \
|
||||||
void Action##Idx(void) \
|
void Action##Idx(void) \
|
||||||
{ \
|
{ \
|
||||||
static boolean Etat=HIGH; \
|
static uint32_t DebutMs=millis(); \
|
||||||
digitalWrite(Idx, Etat); \
|
static boolean Etat=HIGH; \
|
||||||
Etat=!Etat; \
|
/* Depuis la version 2.0 de la lib <RcSeq>, pour */ \
|
||||||
|
/* des raisons de reactivite, la tempo inter-commande */ \
|
||||||
|
/* doit etre geree dans le sketch utilisateur. */ \
|
||||||
|
if(millis() - DebutMs >= 500UL) \
|
||||||
|
{ \
|
||||||
|
DebutMs=millis(); \
|
||||||
|
digitalWrite(Idx, Etat); \
|
||||||
|
Etat=!Etat; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Declaration des actions en utilisant la macro DECLARE_ACTION(Idx) avec Idx = le numero de l'action et de la pin (le ##Idx sera remplace automatiquement par la valeur de Idx */
|
/* Declaration des actions en utilisant la macro DECLARE_ACTION(Idx) avec Idx = le numero de l'action et de la pin (le ##Idx sera remplace automatiquement par la valeur de Idx */
|
@ -11,6 +11,7 @@
|
|||||||
3) <SoftRcPulseOut>: a library mainly based on the <SoftwareServo> library, but with a better pulse generation to limit jitter
|
3) <SoftRcPulseOut>: a library mainly based on the <SoftwareServo> library, but with a better pulse generation to limit jitter
|
||||||
RC Signals (receiver outputs) can be assigned to a control type:
|
RC Signals (receiver outputs) can be assigned to a control type:
|
||||||
-Stick Positions (up to 8, but in practice, 4 is the maximum to manually discriminate each stick position)
|
-Stick Positions (up to 8, but in practice, 4 is the maximum to manually discriminate each stick position)
|
||||||
|
-Multi position switch (2 pos switch, 3 pos switch, or more, eg. rotactor)
|
||||||
-Keyboard (<RcSeq> assumes Push-Buttons associated Pulse duration are equidistant)
|
-Keyboard (<RcSeq> assumes Push-Buttons associated Pulse duration are equidistant)
|
||||||
-Custom Keyboard (The pulse durations can be defined independently for each Push-Button)
|
-Custom Keyboard (The pulse durations can be defined independently for each Push-Button)
|
||||||
Some definitions:
|
Some definitions:
|
||||||
@ -20,7 +21,7 @@
|
|||||||
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
|
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
|
||||||
http://p.loussouarn.free.fr
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
Francais: par RC Navy (2012)
|
Francais: par RC Navy (2012/2013)
|
||||||
========
|
========
|
||||||
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
|
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
|
||||||
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
|
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
|
||||||
@ -31,6 +32,7 @@
|
|||||||
3) <SoftRcPulseOut>: une librairie majoritairement basee sur la librairie <SoftwareServo>, mais avec une meilleur generation des impulsions pour limiter la gigue
|
3) <SoftRcPulseOut>: une librairie majoritairement basee sur la librairie <SoftwareServo>, mais avec une meilleur generation des impulsions pour limiter la gigue
|
||||||
Les signaux RC (sorties du recepteur) peuvent etre associes a un type de controle:
|
Les signaux RC (sorties du recepteur) peuvent etre associes a un type de controle:
|
||||||
-Positions de Manche (jusqu'a 8, mais en pratique, 4 est le maximum pour discriminer manuellement les positions du manche)
|
-Positions de Manche (jusqu'a 8, mais en pratique, 4 est le maximum pour discriminer manuellement les positions du manche)
|
||||||
|
-Interrupteur multi-positions (interrupteur 2 pos, interrupteur 3 pos, ou plus, ex. rotacteur)
|
||||||
-Clavier (<RcSeq> suppose que les durees d'impulsion des Bouton-Poussoirs sont equidistantes)
|
-Clavier (<RcSeq> suppose que les durees d'impulsion des Bouton-Poussoirs sont equidistantes)
|
||||||
-Clavier "Maison" (Les durees d'impulsion peuvent etre definies de manière independante pour chaque Bouton-Poussoir)
|
-Clavier "Maison" (Les durees d'impulsion peuvent etre definies de manière independante pour chaque Bouton-Poussoir)
|
||||||
Quelques definitions:
|
Quelques definitions:
|
||||||
@ -74,14 +76,10 @@
|
|||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
MACROS
|
MACROS
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
/* For an easy Library Version Management */
|
|
||||||
#define LIB_VERSION 1
|
|
||||||
#define LIB_REVISION 0
|
|
||||||
|
|
||||||
#define STR(s) #s
|
#define STR(s) #s
|
||||||
#define MAKE_TEXT_VER_REV(Ver,Rev) (char*)(STR(Ver)"."STR(Rev))
|
#define MAKE_TEXT_VER_REV(Ver,Rev) (char*)(STR(Ver)"."STR(Rev))
|
||||||
|
|
||||||
#define LIB_TEXT_VERSION_REVISION MAKE_TEXT_VER_REV(LIB_VERSION,LIB_REVISION) /* Make Full version as a string "Ver.Rev" */
|
#define LIB_TEXT_VERSION_REVISION MAKE_TEXT_VER_REV(RC_SEQ_LIB_VERSION,RC_SEQ_LIB_REVISION) /* Make Full version as a string "Ver.Rev" */
|
||||||
|
|
||||||
/* A Set of Macros for bit manipulation */
|
/* A Set of Macros for bit manipulation */
|
||||||
#define SET_BIT(Value,BitIdx) (Value)|= (1<<(BitIdx))
|
#define SET_BIT(Value,BitIdx) (Value)|= (1<<(BitIdx))
|
||||||
@ -92,11 +90,8 @@
|
|||||||
#define REFRESH_INTERVAL_MS 20L
|
#define REFRESH_INTERVAL_MS 20L
|
||||||
|
|
||||||
/* A pulse shall be valid during XXXX_PULSE_CHECK_MS before being taken into account */
|
/* A pulse shall be valid during XXXX_PULSE_CHECK_MS before being taken into account */
|
||||||
#define STICK_PULSE_CHECK_MS 100L
|
#define STICK_PULSE_CHECK_MS 150L
|
||||||
#define KBD_PULSE_CHECK_MS 10L
|
#define KBD_PULSE_CHECK_MS 50L
|
||||||
|
|
||||||
/* Duration between 2 consecutive commands */
|
|
||||||
#define INTER_CMD_DURATION_MS 1000L
|
|
||||||
|
|
||||||
/* Free servo Indicator */
|
/* Free servo Indicator */
|
||||||
#define NO_SEQ_LINE 255
|
#define NO_SEQ_LINE 255
|
||||||
@ -115,11 +110,18 @@
|
|||||||
#define PGM_READ_32(FlashAddr) pgm_read_dword(&(FlashAddr))
|
#define PGM_READ_32(FlashAddr) pgm_read_dword(&(FlashAddr))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
STICK TYPE:
|
STICK TYPE: (dead zone expected at the middle)
|
||||||
==========
|
==========
|
||||||
Pos 0 1 2 3
|
Pos 0 1 2 3
|
||||||
|---|-|---|--|---|-|---|
|
|---|-|---|--|---|-|---|
|
||||||
1000us 2000us (Typical Pulse Width values)
|
1000us 2000us (Typical Pulse Width values)
|
||||||
|
|
||||||
|
MULTI_POS_SW: (Middle area active as well)
|
||||||
|
============
|
||||||
|
Pos 0 1 2 3 4
|
||||||
|
|---|-|---|-|---|-|---|-|---|
|
||||||
|
1000us 2000us (Typical Pulse Width values)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#define ACTIVE_AREA_STEP_NBR 3
|
#define ACTIVE_AREA_STEP_NBR 3
|
||||||
#define INACTIVE_AREA_STEP_NBR 1
|
#define INACTIVE_AREA_STEP_NBR 1
|
||||||
@ -156,11 +158,13 @@ typedef struct {
|
|||||||
}RcCmdSt_t;
|
}RcCmdSt_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SoftRcPulseOut Motor;
|
SoftRcPulseOut Motor;
|
||||||
uint16_t RefreshNb; /* Used to store the number of refresh to perform during a servo motion (if not 0 -> Motion in progress) */
|
uint16_t RefreshNb; /* Used to store the number of refresh to perform during a servo motion (if not 0 -> Motion in progress) */
|
||||||
uint8_t SeqLineInProgress;
|
uint8_t SeqLineInProgress;
|
||||||
}ServoSt_t;
|
}ServoSt_t;
|
||||||
|
#endif
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
GLOBAL VARIABLES
|
GLOBAL VARIABLES
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
@ -172,11 +176,15 @@ static RcCmdSt_t RcChannel[RC_CMD_MAX_NB];
|
|||||||
#endif
|
#endif
|
||||||
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
|
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
|
||||||
#define AsMember .
|
#define AsMember .
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
static ServoSt_t Servo[SERVO_MAX_NB];
|
static ServoSt_t Servo[SERVO_MAX_NB];
|
||||||
|
#endif
|
||||||
static CmdSequenceSt_t CmdSequence[SEQUENCE_MAX_NB];
|
static CmdSequenceSt_t CmdSequence[SEQUENCE_MAX_NB];
|
||||||
#else
|
#else
|
||||||
#define AsMember ->
|
#define AsMember ->
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
static ServoSt_t **Servo=NULL;
|
static ServoSt_t **Servo=NULL;
|
||||||
|
#endif
|
||||||
static CmdSequenceSt_t **CmdSequence=NULL;
|
static CmdSequenceSt_t **CmdSequence=NULL;
|
||||||
#endif
|
#endif
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -217,12 +225,12 @@ void RcSeq_Init(void)
|
|||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
uint8_t RcSeq_LibVersion(void)
|
uint8_t RcSeq_LibVersion(void)
|
||||||
{
|
{
|
||||||
return(LIB_VERSION);
|
return(RC_SEQ_LIB_VERSION);
|
||||||
}
|
}
|
||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
uint8_t RcSeq_LibRevision(void)
|
uint8_t RcSeq_LibRevision(void)
|
||||||
{
|
{
|
||||||
return(LIB_REVISION);
|
return(RC_SEQ_LIB_REVISION);
|
||||||
}
|
}
|
||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
char *RcSeq_LibTextVersionRevision(void)
|
char *RcSeq_LibTextVersionRevision(void)
|
||||||
@ -230,6 +238,7 @@ char *RcSeq_LibTextVersionRevision(void)
|
|||||||
return(LIB_TEXT_VERSION_REVISION);
|
return(LIB_TEXT_VERSION_REVISION);
|
||||||
}
|
}
|
||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin)
|
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin)
|
||||||
{
|
{
|
||||||
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
|
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
|
||||||
@ -250,6 +259,7 @@ void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
||||||
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin)
|
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin)
|
||||||
@ -299,6 +309,7 @@ uint32_t StartMinMs[SERVO_MAX_NB];
|
|||||||
LoadSequenceOrShortAction(CmdIdx,Pos,(void*)Table, SequenceLength);
|
LoadSequenceOrShortAction(CmdIdx,Pos,(void*)Table, SequenceLength);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
/* Get initial pulse width for each Servo */
|
/* Get initial pulse width for each Servo */
|
||||||
for(Idx=0;Idx<SERVO_MAX_NB;Idx++)
|
for(Idx=0;Idx<SERVO_MAX_NB;Idx++)
|
||||||
{
|
{
|
||||||
@ -317,6 +328,7 @@ uint32_t StartMinMs[SERVO_MAX_NB];
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
||||||
//========================================================================================================================
|
//========================================================================================================================
|
||||||
@ -381,7 +393,8 @@ uint32_t MotionDurationMs, StartOfSeqMs, EndOfSeqMs, Pos;
|
|||||||
uint16_t StartInDegrees, EndInDegrees;
|
uint16_t StartInDegrees, EndInDegrees;
|
||||||
|
|
||||||
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
||||||
uint8_t ChIdx, CmdPos;
|
uint8_t ChIdx;
|
||||||
|
int8_t CmdPos; /* Shall be signed */
|
||||||
uint32_t RcPulseWidthUs;
|
uint32_t RcPulseWidthUs;
|
||||||
|
|
||||||
/* Asynchronous RC Command acquisition */
|
/* Asynchronous RC Command acquisition */
|
||||||
@ -394,11 +407,8 @@ uint32_t RcPulseWidthUs;
|
|||||||
{
|
{
|
||||||
if(RcChannel[ChIdx].Pos.Idx!=CmdPos)
|
if(RcChannel[ChIdx].Pos.Idx!=CmdPos)
|
||||||
{
|
{
|
||||||
if((millis()-RcChannel[ChIdx].Pos.StartChronoMs)>=INTER_CMD_DURATION_MS) /* Check the last command was received for at least 1 second */
|
RcChannel[ChIdx].Pos.Idx=CmdPos;
|
||||||
{
|
RcChannel[ChIdx].Pos.StartChronoMs=millis();
|
||||||
RcChannel[ChIdx].Pos.Idx=CmdPos;
|
|
||||||
RcChannel[ChIdx].Pos.StartChronoMs=millis();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -416,7 +426,7 @@ uint32_t RcPulseWidthUs;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
NowMs=millis();
|
NowMs=millis();
|
||||||
if((NowMs - StartChronoInterPulseMs) >= 20L)
|
if((NowMs - StartChronoInterPulseMs) >= 20UL)
|
||||||
{
|
{
|
||||||
/* We arrive here every 20 ms */
|
/* We arrive here every 20 ms */
|
||||||
/* Asynchronous Servo Sequence management */
|
/* Asynchronous Servo Sequence management */
|
||||||
@ -448,6 +458,7 @@ uint32_t RcPulseWidthUs;
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
if(Servo[ServoIdx] AsMember RefreshNb && SeqLine!=Servo[ServoIdx] AsMember SeqLineInProgress)
|
if(Servo[ServoIdx] AsMember RefreshNb && SeqLine!=Servo[ServoIdx] AsMember SeqLineInProgress)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -484,9 +495,12 @@ uint32_t RcPulseWidthUs;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
SoftRcPulseOut::refresh(1); /* Force Refresh */
|
SoftRcPulseOut::refresh(1); /* Force Refresh */
|
||||||
|
#endif
|
||||||
StartChronoInterPulseMs=millis();
|
StartChronoInterPulseMs=millis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -535,9 +549,9 @@ uint16_t PulseMinUs,PulseMaxUs;
|
|||||||
{
|
{
|
||||||
switch(RcChannel[ChIdx].Type)
|
switch(RcChannel[ChIdx].Type)
|
||||||
{
|
{
|
||||||
case RC_CMD_STICK: /* No break: normal */
|
case RC_CMD_STICK: /* No break: normal */
|
||||||
case RC_CMD_KEYBOARD:
|
case RC_CMD_MULTI_POS_SW:
|
||||||
if(Idx<(RcChannel[ChIdx].PosNb/2))
|
if( (RcChannel[ChIdx].Type==RC_CMD_MULTI_POS_SW) || ((RcChannel[ChIdx].Type==RC_CMD_STICK) && (Idx<(RcChannel[ChIdx].PosNb/2))) )
|
||||||
{
|
{
|
||||||
PulseMinUs=RcChannel[ChIdx].PulseMinUs+KEY_MIN_VAL(Idx,RcChannel[ChIdx].StepUs);
|
PulseMinUs=RcChannel[ChIdx].PulseMinUs+KEY_MIN_VAL(Idx,RcChannel[ChIdx].StepUs);
|
||||||
PulseMaxUs=RcChannel[ChIdx].PulseMinUs+KEY_MAX_VAL(Idx,RcChannel[ChIdx].StepUs);
|
PulseMaxUs=RcChannel[ChIdx].PulseMinUs+KEY_MAX_VAL(Idx,RcChannel[ChIdx].StepUs);
|
||||||
@ -549,10 +563,10 @@ uint16_t PulseMinUs,PulseMaxUs;
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RC_CMD_CUSTOM:
|
case RC_CMD_CUSTOM:
|
||||||
PulseMinUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min);
|
PulseMinUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min);
|
||||||
PulseMaxUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max);
|
PulseMaxUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if((PulseWidthUs>=PulseMinUs) && (PulseWidthUs<=PulseMaxUs))
|
if((PulseWidthUs>=PulseMinUs) && (PulseWidthUs<=PulseMaxUs))
|
||||||
{
|
{
|
@ -2,7 +2,7 @@
|
|||||||
#define RC_SEQ_H
|
#define RC_SEQ_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
English: by RC Navy (2012)
|
English: by RC Navy (2012/2013)
|
||||||
=======
|
=======
|
||||||
<RcSeq> is an asynchronous library for ATmega328P (UNO), ATtiny84 and ATtiny85 to easily create servo's sequences and/or to execute short actions from RC commands.
|
<RcSeq> is an asynchronous library for ATmega328P (UNO), ATtiny84 and ATtiny85 to easily create servo's sequences and/or to execute short actions from RC commands.
|
||||||
It can also be used to trig some short "actions" (the duration must be less than 20ms to not disturb the servo commands)
|
It can also be used to trig some short "actions" (the duration must be less than 20ms to not disturb the servo commands)
|
||||||
@ -13,6 +13,7 @@
|
|||||||
3) <SoftRcPulseOut>: a library mainly based on the <SoftwareServo> library, but with a better pulse generation to limit jitter
|
3) <SoftRcPulseOut>: a library mainly based on the <SoftwareServo> library, but with a better pulse generation to limit jitter
|
||||||
RC Signals (receiver outputs) can be assigned to a control type:
|
RC Signals (receiver outputs) can be assigned to a control type:
|
||||||
-Stick Positions (up to 8, but in practice, 4 is the maximum to manually discriminate each stick position)
|
-Stick Positions (up to 8, but in practice, 4 is the maximum to manually discriminate each stick position)
|
||||||
|
-Multi position switch (2 pos switch, 3 pos switch, or more, eg. rotactor)
|
||||||
-Keyboard (<RcSeq> assumes Push-Buttons associated Pulse duration are equidistant)
|
-Keyboard (<RcSeq> assumes Push-Buttons associated Pulse duration are equidistant)
|
||||||
-Custom Keyboard (The pulse durations can be defined independently for each Push-Button)
|
-Custom Keyboard (The pulse durations can be defined independently for each Push-Button)
|
||||||
Some definitions:
|
Some definitions:
|
||||||
@ -22,7 +23,7 @@
|
|||||||
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
|
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
|
||||||
http://p.loussouarn.free.fr
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
Francais: par RC Navy (2012)
|
Francais: par RC Navy (2012/2013)
|
||||||
========
|
========
|
||||||
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
|
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
|
||||||
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
|
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
|
||||||
@ -33,6 +34,7 @@
|
|||||||
3) <SoftRcPulseOut>: une librairie majoritairement basee sur la librairie <SoftwareServo>, mais avec une meilleur generation des impulsions pour limiter la gigue
|
3) <SoftRcPulseOut>: une librairie majoritairement basee sur la librairie <SoftwareServo>, mais avec une meilleur generation des impulsions pour limiter la gigue
|
||||||
Les signaux RC (sorties du recepteur) peuvent etre associes a un type de controle:
|
Les signaux RC (sorties du recepteur) peuvent etre associes a un type de controle:
|
||||||
-Positions de Manche (jusqu'a 8, mais en pratique, 4 est le maximum pour discriminer manuellement les positions du manche)
|
-Positions de Manche (jusqu'a 8, mais en pratique, 4 est le maximum pour discriminer manuellement les positions du manche)
|
||||||
|
-Interrupteur multi-positions (interrupteur 2 pos, interrupteur 3 pos, ou plus, ex. rotacteur)
|
||||||
-Clavier (<RcSeq> suppose que les durees d'impulsion des Bouton-Poussoirs sont equidistantes)
|
-Clavier (<RcSeq> suppose que les durees d'impulsion des Bouton-Poussoirs sont equidistantes)
|
||||||
-Clavier "Maison" (Les durees d'impulsion peuvent etre definies de manière independante pour chaque Bouton-Poussoir)
|
-Clavier "Maison" (Les durees d'impulsion peuvent etre definies de manière independante pour chaque Bouton-Poussoir)
|
||||||
Quelques definitions:
|
Quelques definitions:
|
||||||
@ -45,15 +47,20 @@
|
|||||||
/**********************************************/
|
/**********************************************/
|
||||||
/* RCSEQ LIBRARY CONFIGURATION */
|
/* RCSEQ LIBRARY CONFIGURATION */
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
//#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT /* Comment this line if you use <DigiUSB> library in your sketch */
|
#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT /* Comment this line if you use <DigiUSB> library in your sketch */
|
||||||
#define RC_SEQ_WITH_SHORT_ACTION_SUPPORT /* This allows to put call to short action in sequence table */
|
//#define RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Uncomment this if you use <SoftRcPulseOut> library in your sketch for servos and ESC */
|
||||||
|
#define RC_SEQ_WITH_SHORT_ACTION_SUPPORT /* Uncomment this to allows to put call to short action in sequence table */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
/* /!\ Do not touch below /!\ */
|
/* /!\ Do not touch below /!\ */
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
#define RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT /* Do NOT comment this line for DigiSpark */
|
/* For an easy Library Version Management */
|
||||||
|
#define RC_SEQ_LIB_VERSION 2
|
||||||
|
#define RC_SEQ_LIB_REVISION 0
|
||||||
|
|
||||||
|
#define RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT /* Do NOT comment this line for DigiSpark, but you can for UNO */
|
||||||
|
|
||||||
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
||||||
#include <TinyPinChange.h>
|
#include <TinyPinChange.h>
|
||||||
@ -64,7 +71,11 @@
|
|||||||
#ifndef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
|
#ifndef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
|
||||||
#warning RC_SEQ_WITH_SHORT_ACTION_SUPPORT disabled: no short action possible!!!
|
#warning RC_SEQ_WITH_SHORT_ACTION_SUPPORT disabled: no short action possible!!!
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
#include <SoftRcPulseOut.h>
|
#include <SoftRcPulseOut.h>
|
||||||
|
#else
|
||||||
|
#warning RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT disabled: no Servo/ESC command possible!!!
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO) && ARDUINO >= 100
|
#if defined(ARDUINO) && ARDUINO >= 100
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
@ -114,7 +125,7 @@ typedef struct {
|
|||||||
/* Macro to declare a short action (to use in "Sequence[]" structure table) */
|
/* Macro to declare a short action (to use in "Sequence[]" structure table) */
|
||||||
#define SHORT_ACTION_TO_PERFORM(ShortAction, StartActionOffsetMs) {255, 0, 0, (StartActionOffsetMs), 0L, (ShortAction)},
|
#define SHORT_ACTION_TO_PERFORM(ShortAction, StartActionOffsetMs) {255, 0, 0, (StartActionOffsetMs), 0L, (ShortAction)},
|
||||||
|
|
||||||
enum {RC_CMD_STICK=0, RC_CMD_KEYBOARD, RC_CMD_CUSTOM};
|
enum {RC_CMD_STICK=0, RC_CMD_MULTI_POS_SW, RC_CMD_CUSTOM};
|
||||||
|
|
||||||
#define RC_SEQUENCE(Sequence) Sequence, TABLE_ITEM_NBR(Sequence)
|
#define RC_SEQUENCE(Sequence) Sequence, TABLE_ITEM_NBR(Sequence)
|
||||||
#define RC_CUSTOM_KEYBOARD(KeyMap) KeyMap, TABLE_ITEM_NBR(KeyMap)
|
#define RC_CUSTOM_KEYBOARD(KeyMap) KeyMap, TABLE_ITEM_NBR(KeyMap)
|
||||||
@ -125,13 +136,16 @@ void RcSeq_Init(void);
|
|||||||
uint8_t RcSeq_LibVersion(void);
|
uint8_t RcSeq_LibVersion(void);
|
||||||
uint8_t RcSeq_LibRevision(void);
|
uint8_t RcSeq_LibRevision(void);
|
||||||
char *RcSeq_LibTextVersionRevision(void);
|
char *RcSeq_LibTextVersionRevision(void);
|
||||||
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
|
||||||
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin);
|
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin);
|
||||||
|
#endif
|
||||||
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
|
||||||
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin);
|
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin);
|
||||||
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, KeyMap_t *KeyMapTbl, uint8_t PosNb);
|
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, KeyMap_t *KeyMapTbl, uint8_t PosNb);
|
||||||
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, KeyMap_t *KeyMapTbl, uint8_t PosNb);
|
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, KeyMap_t *KeyMapTbl, uint8_t PosNb);
|
||||||
#define RcSeq_DeclareStick(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_STICK, PulseMinUs, PulseMaxUs, NULL, PosNb)
|
#define RcSeq_DeclareStick(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_STICK, PulseMinUs, PulseMaxUs, NULL, PosNb)
|
||||||
#define RcSeq_DeclareKeyboard(ChIdx, PulseMinUs, PulseMaxUs, KeyNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_KEYBOARD, PulseMinUs, PulseMaxUs, NULL, KeyNb)
|
#define RcSeq_DeclareMultiPosSwitch(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_MULTI_POS_SW, PulseMinUs, PulseMaxUs, NULL, PosNb)
|
||||||
|
#define RcSeq_DeclareKeyboard(ChIdx, PulseMinUs, PulseMaxUs, KeyNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_MULTI_POS_SW, PulseMinUs, PulseMaxUs, NULL, KeyNb)
|
||||||
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
|
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
|
||||||
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx,uint8_t TypeCmd,void(*ShortAction)(void));
|
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx,uint8_t TypeCmd,void(*ShortAction)(void));
|
||||||
#endif
|
#endif
|
||||||
@ -161,6 +175,7 @@ void RcSeq_Refresh(void);
|
|||||||
#define RcSeq_DeclareManche RcSeq_DeclareStick
|
#define RcSeq_DeclareManche RcSeq_DeclareStick
|
||||||
#define RcSeq_DeclareClavier RcSeq_DeclareKeyboard
|
#define RcSeq_DeclareClavier RcSeq_DeclareKeyboard
|
||||||
#define RcSeq_DeclareClavierMaison RcSeq_DeclareCustomKeyboard
|
#define RcSeq_DeclareClavierMaison RcSeq_DeclareCustomKeyboard
|
||||||
|
#define RcSeq_DeclareInterMultiPos RcSeq_DeclareMultiPosSwitch
|
||||||
#define RcSeq_DeclareCommandeEtActionCourte RcSeq_DeclareCommandAndShortAction
|
#define RcSeq_DeclareCommandeEtActionCourte RcSeq_DeclareCommandAndShortAction
|
||||||
#endif
|
#endif
|
||||||
#define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence
|
#define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence
|
@ -22,6 +22,8 @@ RcSeq_DeclareManche KEYWORD2
|
|||||||
RcSeq_DeclareServo KEYWORD2
|
RcSeq_DeclareServo KEYWORD2
|
||||||
RcSeq_DeclareCustomKeyboard KEYWORD2
|
RcSeq_DeclareCustomKeyboard KEYWORD2
|
||||||
RcSeq_DeclareClavierMaison KEYWORD2
|
RcSeq_DeclareClavierMaison KEYWORD2
|
||||||
|
RcSeq_DeclareMultiPosSwitch KEYWORD2
|
||||||
|
RcSeq_DeclareInterMultiPos KEYWORD2
|
||||||
RcSeq_DeclareCommandAndSequence KEYWORD2
|
RcSeq_DeclareCommandAndSequence KEYWORD2
|
||||||
RcSeq_DeclareCommandeEtSequence KEYWORD2
|
RcSeq_DeclareCommandeEtSequence KEYWORD2
|
||||||
RcSeq_DeclareCommandAndShortAction KEYWORD2
|
RcSeq_DeclareCommandAndShortAction KEYWORD2
|
@ -37,6 +37,7 @@ uint8_t Ret=0;
|
|||||||
next = first;
|
next = first;
|
||||||
first = this;
|
first = this;
|
||||||
pinMode(_Pin,INPUT);
|
pinMode(_Pin,INPUT);
|
||||||
|
digitalWrite(_Pin, HIGH);
|
||||||
_VirtualPortIdx=TinyPinChange_RegisterIsr(_Pin,SoftRcPulseIn::SoftRcPulseInInterrupt);
|
_VirtualPortIdx=TinyPinChange_RegisterIsr(_Pin,SoftRcPulseIn::SoftRcPulseInInterrupt);
|
||||||
if(_VirtualPortIdx>=0)
|
if(_VirtualPortIdx>=0)
|
||||||
{
|
{
|
||||||
@ -92,7 +93,7 @@ SoftRcPulseIn *RcPulseIn;
|
|||||||
|
|
||||||
for ( RcPulseIn = first; RcPulseIn != 0; RcPulseIn = RcPulseIn->next )
|
for ( RcPulseIn = first; RcPulseIn != 0; RcPulseIn = RcPulseIn->next )
|
||||||
{
|
{
|
||||||
if(TinyPinChange_GetPinEvent(RcPulseIn->_VirtualPortIdx)&RcPulseIn->_PinMask)
|
if(TinyPinChange_GetPortEvent(RcPulseIn->_VirtualPortIdx)&RcPulseIn->_PinMask)
|
||||||
{
|
{
|
||||||
if(digitalRead(RcPulseIn->_Pin))
|
if(digitalRead(RcPulseIn->_Pin))
|
||||||
{
|
{
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
_____ ____ __ _ ____ _ _ _ _
|
||||||
|
| __ \ / __ \ | \ | | / __ \ | | | | | | | |
|
||||||
|
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
||||||
|
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
||||||
|
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
||||||
|
|_| |_| \____/ |_| \__| |_| |_| \__/ |_| 2013
|
||||||
|
|
||||||
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
|
*******************************************
|
||||||
|
* Digispark RC Debug Demo with 1 I/O *
|
||||||
|
*******************************************
|
||||||
|
|
||||||
|
This sketch demonstrates how to display received RC pulse width with a Digispark in the serial console of the arduino IDE.
|
||||||
|
by using a bi-directional serial port using a single I/O.
|
||||||
|
This approach allows to use the built-in Serial Console of the arduino IDE.
|
||||||
|
Please, note this solution requires a native RS232 port (rare today) or a RS232/USB adapter on the development PC.
|
||||||
|
|
||||||
|
To display properly the outputs in the IDE serial console, you have to:
|
||||||
|
- in the arduino IDE, select "Tools->Board->Digispark 16.0mhz - NO USB (Tiny core)"
|
||||||
|
- in the arduino IDE, select the right serial port in "Tools->Serial Port" and select the port where the debug cable is connected to.
|
||||||
|
- in the serial console, set the right baud rate (38400 in this sketch)
|
||||||
|
|
||||||
|
In this sketch, only Tx capabilty of SoftSerial is used.
|
||||||
|
|
||||||
|
Hardware Wiring:
|
||||||
|
===============
|
||||||
|
SERIAL SINGLE I/O
|
||||||
|
DEBUGGING CABLE
|
||||||
|
___________________/\__________________
|
||||||
|
/ \
|
||||||
|
____
|
||||||
|
.--------. | \
|
||||||
|
| GND |--------------------------------+---o5 \
|
||||||
|
| | 47K | | 9o |
|
||||||
|
| | .--###--' | o4 |
|
||||||
|
| DEBUG | 4.7K | | 8o |
|
||||||
|
| TX_RX |-------------------###--+--|<|------o3 | ---> To regular RS232 SubD 9 pins Male of PC
|
||||||
|
| PIN | ^ | 1N4148 | 7o | or to RS232/USB adapter
|
||||||
|
| | | '-----------o2 |
|
||||||
|
'--------' | | 6o |
|
||||||
|
ATtiny85 Single | o1 /
|
||||||
|
(Digispark) I/O |____/
|
||||||
|
SubD 9 pins
|
||||||
|
Female
|
||||||
|
*/
|
||||||
|
#include <TinyPinChange.h>
|
||||||
|
#include <SoftRcPulseIn.h>
|
||||||
|
#include <SoftSerial.h>
|
||||||
|
|
||||||
|
#define RX_AUX_GEAR_PIN 0 //Choose here the pin for the RC signal
|
||||||
|
#define DEBUG_TX_RX_PIN 1 //Adjust here your Tx/Rx debug pin (Do NOT work on Digispark PIN 5: choose another PIN)
|
||||||
|
|
||||||
|
SoftRcPulseIn RxAuxGear; //Choose a name for your RC channel signal
|
||||||
|
|
||||||
|
SoftSerial MyDbgSerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); //true allows to connect to a regular RS232 without RS232 line driver
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
RxAuxGear.attach(RX_AUX_GEAR_PIN);
|
||||||
|
|
||||||
|
MyDbgSerial.begin(38400); //Do NOT forget to setup your terminal at 38400 (eg: arduino IDE serial monitor)
|
||||||
|
MyDbgSerial.txMode(); //Before sending a message, switch to txMode
|
||||||
|
MyDbgSerial.print(F("SoftRcPulseIn lib V"));MyDbgSerial.print(SoftRcPulseIn::LibTextVersionRevision());MyDbgSerial.println(F(" demo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if(RxAuxGear.available())
|
||||||
|
{
|
||||||
|
MyDbgSerial.print(F("Pulse="));MyDbgSerial.println(RxAuxGear.width_us()); // Display Rx Pulse Width (in us)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
@ -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
|
@ -4,7 +4,7 @@
|
|||||||
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
| |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / /
|
||||||
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
| _ / | | _ | |\ \| | | |__| | | | | | \ ' /
|
||||||
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
| | \ \ | \__/ | | | \ ' | | __ | \ \/ / | |
|
||||||
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013
|
|_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014
|
||||||
|
|
||||||
http://p.loussouarn.free.fr
|
http://p.loussouarn.free.fr
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
*******************************************************
|
*******************************************************
|
||||||
|
|
||||||
This sketch demonstrates how to use <TinyPinChange> library.
|
This sketch demonstrates how to use <TinyPinChange> library.
|
||||||
It counts all the transitions on 2 different pins.
|
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.
|
/!\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.
|
Trick: By connecting Pin#1 to Pin#0 or to Pin#5 through a 1K resistor, you can generate transitions for testing purpose.
|
||||||
@ -58,8 +58,8 @@ To display the sketch results on a PC (in a Terminal):
|
|||||||
#define FIRST_INPUT 0
|
#define FIRST_INPUT 0
|
||||||
#define SECOND_INPUT 5
|
#define SECOND_INPUT 5
|
||||||
|
|
||||||
volatile uint16_t FirstInputChangeCount=0; /* Volatile since the variable will be updated in interruption */
|
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 */
|
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) */
|
SoftSerial MySerial(DEBUG_TX_RX_PIN, DEBUG_TX_RX_PIN, true); /* Tx/Rx on a single Pin !!! (Pin#2) */
|
||||||
|
|
||||||
@ -72,15 +72,15 @@ void setup()
|
|||||||
|
|
||||||
MySerial.begin(38400); /* Trick: use a "high" data rate (less time wasted in ISR and for transmitting each character) */
|
MySerial.begin(38400); /* 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(FIRST_INPUT, InterruptFunctionToCall);
|
||||||
VirtualPortNb_=TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
|
VirtualPortNb_ = TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall);
|
||||||
|
|
||||||
/* Enable Pin Change for each pin */
|
/* Enable Pin Change for each pin */
|
||||||
TinyPinChange_EnablePin(FIRST_INPUT);
|
TinyPinChange_EnablePin(FIRST_INPUT);
|
||||||
TinyPinChange_EnablePin(SECOND_INPUT);
|
TinyPinChange_EnablePin(SECOND_INPUT);
|
||||||
|
|
||||||
MySerial.txMode();
|
MySerial.txMode();
|
||||||
MySerial.println(F("\n*** Tiny PinChange Demo ***"));
|
MySerial.println(F("\n*** Tiny PinChange Demo (Rising AND Falling edges) ***"));
|
||||||
MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT);
|
MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT);
|
||||||
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb);
|
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb);
|
||||||
|
|
||||||
@ -88,7 +88,8 @@ void setup()
|
|||||||
MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb_);
|
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("As you can see, virtual port is always port 0 for ATtiny85"));
|
||||||
MySerial.println(F("Remember <TinyPinChange> is also designed for UNO, MEGA and ATtiny84 ;-)"));
|
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);
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
|
||||||
@ -98,14 +99,12 @@ void setup()
|
|||||||
/* Function called in interruption in case of change on pins */
|
/* Function called in interruption in case of change on pins */
|
||||||
void InterruptFunctionToCall(void)
|
void InterruptFunctionToCall(void)
|
||||||
{
|
{
|
||||||
uint8_t PortChange;
|
if(TinyPinChange_Edge(VirtualPortNb, FIRST_INPUT)) /* Check FIRST_INPUT has changed (falling or rising edge) */
|
||||||
|
|
||||||
PortChange = TinyPinChange_GetPinEvent(VirtualPortNb);
|
|
||||||
if(PortChange & TinyPinChange_PinToMsk(FIRST_INPUT)) /* Check FIRST_INPUT has changed */
|
|
||||||
{
|
{
|
||||||
FirstInputChangeCount++; /* Rising AND Falling edges are counted */
|
FirstInputChangeCount++; /* Rising AND Falling edges are counted */
|
||||||
}
|
}
|
||||||
if(PortChange & TinyPinChange_PinToMsk(SECOND_INPUT)) /* Check SECOND_INPUT has changed */
|
|
||||||
|
if(TinyPinChange_Edge(VirtualPortNb_, SECOND_INPUT)) /* Check SECOND_INPUT has changed (falling or rising edge) */
|
||||||
{
|
{
|
||||||
SecondInputChangeCount++; /* Rising AND Falling edges are counted */
|
SecondInputChangeCount++; /* Rising AND Falling edges are counted */
|
||||||
}
|
}
|
||||||
@ -113,17 +112,17 @@ uint8_t PortChange;
|
|||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
static boolean State=HIGH, DisplayEnabled=false;
|
static boolean State = HIGH, DisplayEnabled = true;
|
||||||
static uint32_t LedStartMs=millis(), DisplayStartMs=millis();
|
static uint32_t LedStartMs = millis(), DisplayStartMs = millis();
|
||||||
uint16_t LocalFirstInputChangeCount;
|
uint16_t LocalFirstInputChangeCount;
|
||||||
uint16_t LocalSecondInputChangeCount;
|
uint16_t LocalSecondInputChangeCount;
|
||||||
|
|
||||||
/* Blink the built-in LED */
|
/* Blink the built-in LED */
|
||||||
if(millis()-LedStartMs >= 500)
|
if(millis() - LedStartMs >= 500)
|
||||||
{
|
{
|
||||||
LedStartMs=millis();
|
LedStartMs = millis();
|
||||||
digitalWrite(LED_PIN, State);
|
digitalWrite(LED_PIN, State);
|
||||||
State=!State; /* State will be inverted at the next digitalWrite() */
|
State = !State; /* State will be inverted at the next digitalWrite() */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get command from single wire SoftSerial */
|
/* Get command from single wire SoftSerial */
|
||||||
@ -132,19 +131,19 @@ uint16_t LocalSecondInputChangeCount;
|
|||||||
switch(MySerial.read())
|
switch(MySerial.read())
|
||||||
{
|
{
|
||||||
case '0':
|
case '0':
|
||||||
DisplayEnabled=false;
|
DisplayEnabled = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
DisplayEnabled=true;
|
DisplayEnabled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Diplay Transition numbers every second */
|
/* Diplay Transition numbers every second */
|
||||||
if((millis()-DisplayStartMs >= 1000) && DisplayEnabled)
|
if((millis() - DisplayStartMs >= 1000) && DisplayEnabled)
|
||||||
{
|
{
|
||||||
DisplayStartMs=millis();
|
DisplayStartMs = millis();
|
||||||
noInterrupts(); /* Mandatory since counters are 16 bits */
|
noInterrupts(); /* Mandatory since counters are 16 bits */
|
||||||
LocalFirstInputChangeCount = FirstInputChangeCount;
|
LocalFirstInputChangeCount = FirstInputChangeCount;
|
||||||
LocalSecondInputChangeCount = SecondInputChangeCount;
|
LocalSecondInputChangeCount = SecondInputChangeCount;
|
@ -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(38400); /* 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 >= 500)
|
||||||
|
{
|
||||||
|
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 >= 1000) && 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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(38400); /* 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 >= 500)
|
||||||
|
{
|
||||||
|
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 >= 1000) && 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,12 +17,18 @@ TinyPinChange_EnablePin KEYWORD2
|
|||||||
TinyPinChange_ActiveBroche KEYWORD2
|
TinyPinChange_ActiveBroche KEYWORD2
|
||||||
TinyPinChange_DisablePin KEYWORD2
|
TinyPinChange_DisablePin KEYWORD2
|
||||||
TinyPinChange_DesactiveBroche KEYWORD2
|
TinyPinChange_DesactiveBroche KEYWORD2
|
||||||
TinyPinChange_GetPinEvent KEYWORD2
|
TinyPinChange_GetPortEvent KEYWORD2
|
||||||
TinyPinChange_RetourneEvenemenPort KEYWORD2
|
TinyPinChange_RetourneEvenemenPort KEYWORD2
|
||||||
TinyPinChange_GetPinCurSt KEYWORD2
|
TinyPinChange_GetCurPortSt KEYWORD2
|
||||||
TinyPinChange_RetourneEtatCourantPort KEYWORD2
|
TinyPinChange_RetourneEtatCourantPort KEYWORD2
|
||||||
TinyPinChange_PinToMsk KEYWORD2
|
TinyPinChange_PinToMsk KEYWORD2
|
||||||
TinyPinChange_MasqueDeBroche KEYWORD2
|
TinyPinChange_MasqueDeBroche KEYWORD2
|
||||||
|
TinyPinChange_Edge KEYWORD2
|
||||||
|
TinyPinChange_Front KEYWORD2
|
||||||
|
TinyPinChange_RisingEdge KEYWORD2
|
||||||
|
TinyPinChange_FrontMontant KEYWORD2
|
||||||
|
TinyPinChange_FallingEdge KEYWORD2
|
||||||
|
TinyPinChange_FrontDescendant KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
@ -20,12 +20,12 @@
|
|||||||
/* Define here the PIN to use with Tiny Soft PWM */
|
/* Define here the PIN to use with Tiny Soft PWM */
|
||||||
/* Unused Pin(s) SHALL be commented */
|
/* Unused Pin(s) SHALL be commented */
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
//#define TINY_SOFT_PWM_USES_P0
|
#define TINY_SOFT_PWM_USES_P0
|
||||||
#define TINY_SOFT_PWM_USES_P1
|
#define TINY_SOFT_PWM_USES_P1
|
||||||
#define TINY_SOFT_PWM_USES_P2
|
#define TINY_SOFT_PWM_USES_P2
|
||||||
//#define TINY_SOFT_PWM_USES_P3 /* /!\ used for USB on DigiSpark: do not use it for PWM if DigiUSB is also used /!\ */
|
//#define TINY_SOFT_PWM_USES_P3 /* /!\ used for USB on DigiSpark: do not use it for PWM if DigiUSB is also used /!\ */
|
||||||
//#define TINY_SOFT_PWM_USES_P4 /* /!\ used for USB on DigiSpark: do not use it for PWM if DigiUSB is also used /!\ */
|
//#define TINY_SOFT_PWM_USES_P4 /* /!\ used for USB on DigiSpark: do not use it for PWM if DigiUSB is also used /!\ */
|
||||||
#define TINY_SOFT_PWM_USES_P5
|
//#define TINY_SOFT_PWM_USES_P5
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
|||||||
/****************************************************************************/
|
|
||||||
/* 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);
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
#ifndef TINY_PIN_CHANGE_H
|
|
||||||
#define TINY_PIN_CHANGE_H 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* <TinyPinChange>, a library for Pin Change Interrupt by RC Navy (2012)
|
|
||||||
* Supported device ATmega238P (UNO), ATtiny84, ATtiny85
|
|
||||||
*
|
|
||||||
* http://p.loussouarn.free.fr
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(ARDUINO) && ARDUINO >= 100
|
|
||||||
#include "Arduino.h"
|
|
||||||
#else
|
|
||||||
#include "WProgram.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
|
||||||
/* ATtinyX5 */
|
|
||||||
#define PIN_CHG_PORT_NB 1
|
|
||||||
#define DigitalPinToPortIdx(p) 0
|
|
||||||
#define PC_PIN0 PINB
|
|
||||||
#define PC_PCMSK0 PCMSK
|
|
||||||
#else
|
|
||||||
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
|
||||||
/* 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
|
|
||||||
/* 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
|
|
||||||
|
|
||||||
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_GetPinEvent(uint8_t VirtualPortIdx);
|
|
||||||
uint8_t TinyPinChange_GetPinCurSt(uint8_t VirtualPortIdx);
|
|
||||||
#define TinyPinChange_PinToMsk(Pin) _BV(digitalPinToPCMSKbit(Pin))
|
|
||||||
|
|
||||||
/*******************************************************/
|
|
||||||
/* 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_GetPinEvent
|
|
||||||
#define TinyPinChange_RetourneEtatCourantPort TinyPinChange_GetPinCurSt
|
|
||||||
#define TinyPinChange_MasqueDeBroche TinyPinChange_PinToMsk
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
x
Reference in New Issue
Block a user